diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 38281783ef9..fad32a7e224 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1,10 +1,27 @@ # Lower entries on this list take precedence # Anything unmatched by selectors below -* @annafil @runleonarun +* @runleonarun + +# Cloud docs and images are assigned to Leona +/website/docs/docs/dbt-cloud/dbt-cloud-changelog.md @runleonarun +/website/docs/docs/dbt-cloud/ @runleonarun +/website/src/pages/dbt-cloud/ @runleonarun +/website/static/img/docs/dbt-cloud/ @runleonarun + +# Blog content assigned to Developer experience team +/website/blog/ @runleonarun + + + +# Adapter & Package Development Docs +/website/docs/docs/supported-data-platforms.md/ @runleonarun @dataders +/website/docs/reference/warehouse-profiles/ @runleonarun @dataders +/website/docs/reference/resource-configs/ @runleonarun @dataders +/website/docs/guides/building-packages @runleonarun @amychen1776 @dataders @dbeatty10 +/website/docs/contributing/building-a-new-adapter @runleonarun @dataders @dbeatty10 +/website/docs/contributing/testing-a-new-adapter @runleonarun @dataders @dbeatty10 +/website/docs/guides/creating-new-materializations @runleonarun @dataders @dbeatty10 +/website/docs/docs/dbt-cloud/cloud-configuring-dbt-cloud/ @runleonarun @dataders @dbeatty10 + -# Cloud docs and images are assigned to Drew -/website/docs/docs/dbt-cloud/dbt-cloud-changelog.md @drewbanin @alexbethea22 -/website/docs/docs/dbt-cloud/ @drewbanin -/website/src/pages/dbt-cloud/ @drewbanin -/website/static/img/docs/dbt-cloud/ @drewbanin diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 00000000000..9349000f66b --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,8 @@ +blank_issues_enabled: true +contact_links: + - name: Want to see new content? Open a discussion! + url: https://github.com/dbt-labs/docs.getdbt.com/discussions/new + about: You can open a discussion to propose new content for the dbt product documentation. + - name: Have questions about dbt? Join the Community! + url: https://www.getdbt.com/community/join-the-community + about: You can join the dbt Labs Community to ask and answer questions. diff --git a/.github/ISSUE_TEMPLATE/contribute-to-developer-blog.yml b/.github/ISSUE_TEMPLATE/contribute-to-developer-blog.yml new file mode 100644 index 00000000000..f138b9e4e06 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/contribute-to-developer-blog.yml @@ -0,0 +1,54 @@ +name: Contribute to the dbt Developer Blog +description: > + For proposing a new post on the dbt Developer Blog. +labels: ["content","developer blog"] +body: + - type: markdown + attributes: + value: | + We're excited to hear about your idea for the dbt Developer Blog. This template will help lay out the proposed post and then we will work with on next steps! + + - type: input + id: contact + attributes: + label: Contact Details + description: How can we get in touch with you? + placeholder: your preferred email and/or dbt Slack handle + validations: + required: true + + - type: checkboxes + id: read-contribution + attributes: + label: I have read the dbt Developer Blog contribution guidelines. + description: You can find the contribution guide [here](https://github.com/dbt-labs/docs.getdbt.com/blob/current/contributing/developer-blog.md) + options: + - label: I have read the dbt Developer Blog contribution guidelines. + validations: + required: true + + - type: checkboxes + id: author_type + attributes: + label: Which of these best describes you? + options: + - label: I am a dbt Community member or partner contributing to the Developer Blog + - label: I work for dbt Labs and am creating this issue for a community or marketing approved piece. + validations: + + + - type: textarea + attributes: + label: > + What is the topic of your post? + description: | + Please provide a short (~ 1 paragraph) summary as well as who this post is targeted towards (ie people interested in learning more about dbt snapshots or advanced Jinja users) + validations: + required: true + + - type: textarea + attributes: + label: Link to an initial outline. + description: Please link to a short outline in Notion, or Google Docs + validations: + required: true diff --git a/.github/ISSUE_TEMPLATE/improve-docs.yml b/.github/ISSUE_TEMPLATE/improve-docs.yml new file mode 100644 index 00000000000..57dc64cc312 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/improve-docs.yml @@ -0,0 +1,42 @@ +name: Improve content +description: Make a suggestion to improve the content in an existing page. +labels: ["content","improvement"] +body: + - type: markdown + attributes: + value: | + * You can ask questions or submit ideas for the dbt docs in [Discussions](https://github.com/dbt-labs/docs.getdbt.com/discussions) + * Before you file an issue read the [Contributing guide](https://github.com/dbt-labs/docs.getdbt.com#contributing). + * Check to make sure someone hasn't already opened a similar [issue](https://github.com/dbt-labs/docs.getdbt.com/issues). + + - type: checkboxes + id: contributions + attributes: + label: Contributions + description: Please read the contribution docs before opening an issue or pull request. + options: + - label: I have read the contribution docs, and understand what's expected of me. + + - type: textarea + attributes: + label: Link to the page on docs.getdbt.com requiring updates + description: Please link to the page or pages you'd like to see improved. + validations: + required: true + + - type: textarea + attributes: + label: What part(s) of the page would you like to see updated? + description: | + - Give as much detail as you can to help us understand the change you want to see. + - Why should the docs be changed? What use cases does it support? + - What is the expected outcome? + validations: + required: true + + - type: textarea + attributes: + label: Additional information + description: Add any other context or screenshots about the feature request here. + validations: + required: false \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/improve-the-site.yml b/.github/ISSUE_TEMPLATE/improve-the-site.yml new file mode 100644 index 00000000000..e0556d7374f --- /dev/null +++ b/.github/ISSUE_TEMPLATE/improve-the-site.yml @@ -0,0 +1,42 @@ +name: Improve the docs.getdbt.com site +description: Make a suggestion or report a problem about the technical implementation of docs.getdbt.com. +labels: ["engineering"] +body: + - type: markdown + attributes: + value: | + * You can ask questions or submit ideas for the dbt docs in [Discussions](https://github.com/dbt-labs/docs.getdbt.com/discussions) + * Before you file an issue read the [Contributing guide](https://github.com/dbt-labs/docs.getdbt.com#contributing). + * Check to make sure someone hasn't already opened a similar [issue](https://github.com/dbt-labs/docs.getdbt.com/issues). + + - type: checkboxes + id: contributions + attributes: + label: Contributions + description: Please read the contribution docs before opening an issue or pull request. + options: + - label: I have read the contribution docs, and understand what's expected of me. + + - type: textarea + attributes: + label: What page(s) or areas on docs.getdbt.com are affected? + description: Include links to pages where you're seeing a problem or making a suggestion. Also include screenshots, what browser you're using, etc. + validations: + required: true + + - type: textarea + attributes: + label: What changes are you suggesting? + description: | + - Give as much detail as you can to help us understand the change you want to see. + - Why should the docs be changed? + - What is the expected outcome? + validations: + required: true + + - type: textarea + attributes: + label: Additional information + description: Any additional information, configuration, or data that might be necessary to reproduce the issue. + validations: + required: false \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/new-dbt-feature.yml b/.github/ISSUE_TEMPLATE/new-dbt-feature.yml new file mode 100644 index 00000000000..fa46a189fc4 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/new-dbt-feature.yml @@ -0,0 +1,33 @@ +name: Start docs project for a new feature +description: For dbt PMs to add docs for their new or updated dbt product features. +labels: ["content","upcoming release"] +body: + - type: markdown + attributes: + value: | + * Before you file an issue read the [Contributing guide](https://github.com/dbt-labs/docs.getdbt.com#contributing). + * Check to make sure someone hasn't already opened a similar [issue](https://github.com/dbt-labs/docs.getdbt.com/issues). + + - type: checkboxes + id: contributions + attributes: + label: Contributions + description: This applies to new, unreleased content. + options: + - label: I am a PM or subject matter expert at dbt who is responsible for this feature. + + - type: textarea + attributes: + label: Where does this content belong? + description: | + - Give as much detail as you can to help us understand where you expect the content to live. + validations: + required: true + + - type: textarea + attributes: + label: Link to source material + description: | + Use the [source material template](https://docs.google.com/document/d/1lLWGMXJFjkY4p7r8ZKhBX73dOLmIjgXZBYq39LqmAJs/edit) to provide source material for this feature. + validations: + required: true \ No newline at end of file diff --git a/.github/issue_template.md b/.github/issue_template.md deleted file mode 100644 index 4f32d903281..00000000000 --- a/.github/issue_template.md +++ /dev/null @@ -1,24 +0,0 @@ -## Steps to reproduce: - - -## Expected results: - - -## Actual results - - -## Extra details - diff --git a/.github/labeler.yml b/.github/labeler.yml new file mode 100644 index 00000000000..595db45cd66 --- /dev/null +++ b/.github/labeler.yml @@ -0,0 +1,8 @@ +developer blog: +- website/blog/**/* + +guides: +- website/docs/docs/guides/**/* + +content: +- website/docs/**/* diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 19112fa74a5..5ae7e9f4d6d 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -2,6 +2,8 @@ ## To-do before merge @@ -12,14 +14,10 @@ Include any notes about things that need to happen before this PR is merged, e.g - [ ] Ensure PR #56 is merged --> -## Pre-release docs -Is this change related to an unreleased version of dbt? -- [ ] Yes: please - - update the base branch to `next` - - add Changelog components: `[New/Changed] in v0.x.0` - - add links to the "New and changed documentation" section of the latest [Migration Guide](../website/docs/docs/guides/migration-guide) -- [ ] No: please ensure the base branch is `current` -- [ ] Unsure: we'll let you know! +## Prerelease docs +If this change is related to functionality in a prerelease version of dbt (delete if not applicable): +- [ ] I've added versioning components, as described in ["Versioning Docs"](https://github.com/dbt-labs/docs.getdbt.com/blob/current/contributing/versioningdocs.md) +- [ ] I've added a note to the prerelease version's [Migration Guide](https://github.com/dbt-labs/docs.getdbt.com/tree/current/website/docs/guides/migration/versions) ## Checklist If you added new pages (delete if not applicable): @@ -29,3 +27,4 @@ If you added new pages (delete if not applicable): If you removed existing pages (delete if not applicable): - [ ] The page has been removed from `website/sidebars.js` - [ ] An entry has been added to `_redirects` +- [ ] [Run link testing](https://github.com/dbt-labs/docs.getdbt.com#running-the-cypress-tests-locally) to update the links that point to the deleted page diff --git a/.github/workflows/mark_pr_as_done.yml b/.github/workflows/add_pr_to_project.yml similarity index 96% rename from .github/workflows/mark_pr_as_done.yml rename to .github/workflows/add_pr_to_project.yml index 5fdad116526..a08840f98d0 100644 --- a/.github/workflows/mark_pr_as_done.yml +++ b/.github/workflows/add_pr_to_project.yml @@ -1,7 +1,7 @@ -name: Mark PR as done +name: Add PR to project on: - pull_request: - types: [closed] + pull_request_target: + types: [opened,reopened] jobs: track_pr: @@ -57,7 +57,7 @@ jobs: with: name: "data.json" json: ${{ steps.get_project_info.outputs.data }} - + - name: Extract date field ID uses: sergeysova/jq-action@v2 id: date_field_id @@ -77,8 +77,8 @@ jobs: id: status_field_value with: cmd: - jq '.organization.projectNext.fields.nodes[] | select(.name== "Status") |.settings | fromjson.options[] | select(.name=="Done") |.id' data.json - + jq '.organization.projectNext.fields.nodes[] | select(.name== "Status") |.settings | fromjson.options[] | select(.name=="Triage") |.id' data.json + - name: Set fields id: set_fields uses: octokit/graphql-action@v2.x @@ -88,7 +88,7 @@ jobs: $project: ID! $item: ID! $status_field: ID! - $status_value: ID! + $status_value: String! $date_field: ID! $date_value: String! ) { diff --git a/.github/workflows/create_next_pr.yml b/.github/workflows/create_next_pr.yml new file mode 100644 index 00000000000..becef0db654 --- /dev/null +++ b/.github/workflows/create_next_pr.yml @@ -0,0 +1,18 @@ +on: + push: + branches: + - "current" + +jobs: + pull-request: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: pull-request + uses: repo-sync/pull-request@v2 + with: + source_branch: "current" + destination_branch: "next" + pr_title: "Merge current branch into next" + pr_body: "*An automated PR to keep the next branch up to date with current*" + github_token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/cypress_tests.yml b/.github/workflows/cypress_tests.yml new file mode 100644 index 00000000000..1973e0ef43e --- /dev/null +++ b/.github/workflows/cypress_tests.yml @@ -0,0 +1,47 @@ +name: cypress tests + +on: + pull_request: + branches: + - current + +jobs: + start-workflow: + name: start workflow + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: install node + uses: actions/setup-node@v2 + with: + node-version: '16.13.1' + + - name: npm install + run: cd website && npm ci + + - name: setup env + run: | + PR_NUMBER=$(jq --raw-output .pull_request.number ${{ github.event_path }}) + echo "PR_NUMBER=${PR_NUMBER}" >> ${GITHUB_ENV} + + - name: run cypress e2e + uses: cypress-io/github-action@v4 + with: + command: npx cypress run + browser: chrome + working-directory: website + spec: cypress/e2e/*.cy.js + wait-on: https://deploy-preview-${{ env.PR_NUMBER }}--docs-getdbt-com.netlify.app + wait-on-timeout: 600 + env: + CYPRESS_BASE_URL: https://deploy-preview-${{ env.PR_NUMBER }}--docs-getdbt-com.netlify.app + + - name: Screenshot artifact upload + uses: actions/upload-artifact@v2 + if: failure() + with: + name: cypress-screenshots + path: cypress/screenshots \ No newline at end of file diff --git a/.github/workflows/labeler.yml b/.github/workflows/labeler.yml new file mode 100644 index 00000000000..057208eda32 --- /dev/null +++ b/.github/workflows/labeler.yml @@ -0,0 +1,14 @@ +name: "Pull Request Labeler" +on: +- pull_request_target + +jobs: + triage: + permissions: + contents: read + pull-requests: write + runs-on: ubuntu-latest + steps: + - uses: actions/labeler@v4 + with: + repo-token: "${{ secrets.GITHUB_TOKEN }}" diff --git a/.github/workflows/labelsizer.yml b/.github/workflows/labelsizer.yml new file mode 100644 index 00000000000..d1ad5776597 --- /dev/null +++ b/.github/workflows/labelsizer.yml @@ -0,0 +1,24 @@ +name: labeler + +on: [pull_request_target] + +jobs: + labeler: + runs-on: ubuntu-latest + name: Label the PR size + steps: + - uses: codelytv/pr-size-labeler@v1.8.1 + with: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + xs_label: 'size: x-small' + xs_max_size: '10' + s_label: 'size: small' + s_max_size: '50' + m_label: 'size: medium' + m_max_size: '250' + l_label: 'size: large' + l_max_size: '100000' + xl_label: 'size: x-large' + fail_if_xl: 'false' + files_to_ignore: '' + diff --git a/.github/workflows/mark_issue_as_done.yml b/.github/workflows/mark_issue_as_done.yml deleted file mode 100644 index 3408a4fa72d..00000000000 --- a/.github/workflows/mark_issue_as_done.yml +++ /dev/null @@ -1,123 +0,0 @@ -name: Mark issue as done -on: - issues: - types: [closed] - -jobs: - track_issue: - runs-on: ubuntu-latest - - steps: - - uses: octokit/graphql-action@v2.x - name: Get project data - id: get_project_info - with: - query: | - query($org: String!, $number: Int!) { - organization(login: $org){ - projectNext(number: $number) { - id - fields(first:20) { - nodes { - id - name - settings - } - } - } - } - } - org: 'dbt-labs' - number: 14 - headers: 'GraphQL-Features: projects_next_graphql' - env: - GITHUB_TOKEN: ${{ secrets.PROJECT_NEXT }} - - - uses: octokit/graphql-action@v2.x - name: Add Issue to Project - id: add_issue - with: - query: | - mutation($project:ID!, $issue:ID!) { - addProjectNextItem(input: {projectId: $project, contentId: $issue}) { - projectNextItem { - id - } - } - } - project: ${{ fromJSON(steps.get_project_info.outputs.data).organization.projectNext.id }} - issue: ${{ github.event.issue.node_id}} - headers: 'GraphQL-Features: projects_next_graphql' - env: - GITHUB_TOKEN: ${{ secrets.PROJECT_NEXT }} - - - name: create-json - id: create-json - uses: jsdaniell/create-json@1.1.2 - with: - name: "data.json" - json: ${{ steps.get_project_info.outputs.data }} - - - name: Extract date field ID - uses: sergeysova/jq-action@v2 - id: date_field_id - with: - cmd: - jq '.organization.projectNext.fields.nodes[] | select(.name == "Date") | .id' data.json - - - name: Extract status field ID - uses: sergeysova/jq-action@v2 - id: status_field_id - with: - cmd: - jq '.organization.projectNext.fields.nodes[] | select(.name == "Status") | .id' data.json - - - name: Extract status field value - uses: sergeysova/jq-action@v2 - id: status_field_value - with: - cmd: - jq '.organization.projectNext.fields.nodes[] | select(.name== "Status") |.settings | fromjson.options[] | select(.name=="Done") |.id' data.json - - - name: Set fields - id: set_fields - uses: octokit/graphql-action@v2.x - with: - query: | - mutation ( - $project: ID! - $item: ID! - $status_field: ID! - $status_value: ID! - $date_field: ID! - $date_value: String! - ) { - set_status: updateProjectNextItemField(input: { - projectId: $project - itemId: $item - fieldId: $status_field - value: $status_value - }) { - projectNextItem { - id - } - } - set_date_posted: updateProjectNextItemField(input: { - projectId: $project - itemId: $item - fieldId: $date_field - value: $date_value - }) { - projectNextItem { - id - } - } - } - GITHUB_TOKEN: ${{ secrets.PROJECT_NEXT }} - project: ${{ fromJSON(steps.get_project_info.outputs.data).organization.projectNext.id }} - headers: 'GraphQL-Features: projects_next_graphql' - item: ${{ fromJSON(steps.add_issue.outputs.data).addProjectNextItem.projectNextItem.id }} - status_field: ${{ steps.status_field_id.outputs.value }} - status_value: ${{ steps.status_field_value.outputs.value }} - date_field: ${{ steps.date_field_id.outputs.value }} - date_value: ${{ github.event.issue.created_at }} diff --git a/.gitignore b/.gitignore index 5395ea795d6..49c7bdb5b3e 100755 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,6 @@ website/build/ website/yarn.lock website/node_modules website/i18n/* + +# Local Netlify folder +.netlify diff --git a/README.md b/README.md index 69968a648bb..6203bbaba9a 100644 --- a/README.md +++ b/README.md @@ -1,37 +1,72 @@ -A [docusaurus](https://v2.docusaurus.io/) site that powers [docs.getdbt.com](https://docs.getdbt.com/). +_We use [docusaurus](https://v2.docusaurus.io/) to power [docs.getdbt.com](https://docs.getdbt.com/)._ -## Branching +#### Table of Contents -There are two long-lived branches in this repo: -- `current`: This branch is what is reflected at at [docs.getdbt.com](https://docs.getdbt.com/) -- `next`: This branch represent the next release of dbt, and is deployed [next.docs.getdbt.com](https://next.docs.getdbt.com/) +* [Code of Conduct](#Code-of-conduct) +* [Contributing](#contributing) +* [Writing content](#writing-content) +* [Running the docs site locally](#running-the-docs-site-locally) + +# Code of conduct + +Please review the dbt docs contributors [code of conduct](https://github.com/dbt-labs/docs.getdbt.com/blob/current/contributing/contributor-code-of-conduct.md). +Creating an inclusive and equitable environment for our documents is more important than any other aspect. Syntax errors can be corrected, but trust, once lost, is difficult to gain back. + +# Contributing -## Contributing We welcome contributions from community members to this repo: -- **Fixes**: If you notice an error (there are likely many), use the `Edit this page` button at the bottom of each page to suggest a change. We recommend you contribute small changes directly from the GitHub interface. -- **New documentation**: If you contributed code in [dbt-core](https://github.com/fishtown-analytics/dbt), we encourage you to also write the docs here! -- **Refactors**: At this time, we are unable to support community members who wish to re-write sections of docs.getdbt.com. We hope to change this in the future! +- **Fixes**: When you notice an error, you can use the `Edit this page` button at the bottom of each page to suggest a change. +- **New documentation**: If you contributed code in [dbt-core](https://github.com/dbt-labs/dbt-core), we encourage you to also write the docs here! Please reach out in the dbt community if you need help finding a place for these docs. +- **Major rewrites**: You can [file an issue](https://github.com/dbt-labs/docs.getdbt.com/issues/new?assignees=&labels=content%2Cimprovement&template=improve-docs.yml) or [start a discussion](https://github.com/dbt-labs/docs.getdbt.com/discussions) to propose ideas for a content area that requires attention. + +You can use components documented in the [docusaurus library](https://v2.docusaurus.io/docs/markdown-features/). + +# Writing content + +When writing content, you should refer to the [style guide](https://github.com/dbt-labs/docs.getdbt.com/blob/current/contributing/content-style-guide.md) and [content types](/contributing/content-types.md) to help you understand our writing standards and how we break down information in the product documentation. + +## Versioning and single-sourcing content + +We now enable you to reuse content between different docs pages, version pages, and establish product variables in the dbt Labs product documentation. To learn more about how to single source content between versions, product variables, and other content, see [Single-sourcing content](/contributing/single-sourcing-content.md). + +## Adding tabbed components to a page + +You can add code snippets and other content in a tabbed view. To learn more about adding tabbed components, see [Adding page components](/contributing/adding-page-components.md). + +# Running the Docs site locally + +You can click a link available in a netlify bot PR comment to see and review your changes rendered on a staging server. You are also able to see and review your proposed modifications locally on your computer. Our setup instructions use [homebrew](https://brew.sh/): -### Running the Docs site locally +## Prerequisites -We recommend locally rendering changes made to the docs site so you can review your proposed modifications. Our setup instructions use [homebrew](https://brew.sh/): +* (Mac Terminal) Install [Xcode Command Line Tools](https://developer.apple.com/download/more/) + - Open a terminal window, run `xcode-select --install`, and follow the on-screen prompts in the pop-up window. +* (Mac and Linux) Install [homebrew](https://brew.sh/) + - Copy and paste `/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"` in to a terminal window and follow the prompts. Once the installation has completed, follow the **Next Steps** instructions listed in terminal. +* (Windows) Install [Node.js](https://nodejs.org/en/download/) -0. If applicable, install [Xcode Command Line Tools](https://developer.apple.com/download/more/); you'll likely need an AppleID for this. You will also need [homebrew](https://brew.sh/). -2. Install `node`: `brew install node` -3. Clone this repo: `git clone git@github.com:fishtown-analytics/docs.getdbt.com.git` -4. `cd` into the repo: `cd docs.getdbt.com` -5. `cd` into the `website` subdirectory: `cd website` -6. Install the required node packages: `npm install` -7. Build the website: `npm start` -8. Before pushing your changes to a branch, check that all links work by using the `make build` script. +1. (Mac and Linux only) Install `node`: `brew install node` +2. Clone this repo: `git clone https://github.com/dbt-labs/docs.getdbt.com.git` +3. `cd` into the repo: `cd docs.getdbt.com` +4. `cd` into the `website` subdirectory: `cd website` +5. Install the required node packages: `npm install` (optional — install any updates) +6. Build the website: `npm start` +7. Before pushing your changes to a branch, check that all links work by using the `make build` script. -Advisory: -- Currently an `npm install` produces a number of dependency warnings, in particular several claiming that `docusaurus/core` is missing. Rest assured, this message is a red herring. As of writing this, no 2.0.0 package exists, so you won't have much luck trying to install it. Feel free to ignore those warnings. +Advisory: - If you run into an `fatal error: 'vips/vips8' file not found` error when you run `npm install`, you may need to run `brew install vips`. Warning: this one will take a while -- go ahead and grab some coffee! -You can also check out [this Loom video](https://www.loom.com/share/7037780b86eb4f16953664b8f15f1e21) that I recorded for co-workers — it covers setting up docs.getdbt.com locally, and adding a page with links and images. Heads up — this was very much something I did on the fly, so is not super polished! +## Running the Cypress tests locally -## Custom components -Check out [docs.getdbt.com/styles](https://docs.getdbt.com/styles) for examples of different components that can be used in these docs. +Method 1: Utilizing the Cypress GUI +1. `cd` into the repo: `cd docs.getdbt.com` +2. `cd` into the `website` subdirectory: `cd website` +3. Install the required node packages: `npm install` +4. Run `npx cypress open` to open the Cypress GUI, and choose `E2E Testing` as the Testing Type, before finally selecting your browser and clicking `Start E2E testing in {broswer}` +5. Click on a test and watch it run! -You can also use components directly from the [docusaurus library](https://v2.docusaurus.io/docs/markdown-features/). +Method 2: Running the Cypress E2E tests headlessly +1. `cd` into the repo: `cd docs.getdbt.com` +2. `cd` into the `website` subdirectory: `cd website` +3. Install the required node packages: `npm install` +4. Run `npx cypress run` diff --git a/RELEASE.md b/RELEASE.md deleted file mode 100644 index 2793687c403..00000000000 --- a/RELEASE.md +++ /dev/null @@ -1,21 +0,0 @@ -# Releasing docs - -There are two long-lived branches of this repo: - - `current` is the version of dbt released at [docs.getdbt.com](docs.getdbt.com) - - `next` reflects the next version of dbt to be releases. It is accessible at [docs-next.getdbt.com](docs-next.getdbt.com), and a warning banner is displayed on the site. - -- Any fixes or revisions to existing docs should be merged into `current` -- Any pre-release docs should be merged into `next` -- The `next` branch should be rebased from `current` somewhat regularly - -When new versions of dbt are released: -1. Rebase `next` on top of `current`. The workflow might look something like this: -``` -(current) $ git fetch -(current) $ git pull -(current) $ git checkout next -(next) $ git pull -(next) $ git rebase current -i -``` -2. Make a PR from `next` onto `current` -3. Merge the PR once the deploy preview builds successfully diff --git a/_redirects b/_redirects index 8e4c451cf54..f820d2420ad 100644 --- a/_redirects +++ b/_redirects @@ -1,3 +1,7 @@ +/useful_components https://github.com/dbt-labs/docs.getdbt.com/blob/current/contributing/adding-page-components.md 302 +/guides/legacy/managing-environments /docs/building-a-dbt-project/managing-environments 302 +/docs/running-a-dbt-project/dbt-api /docs/introduction 301 +/img/docs/dbt-cloud/dbt-cloud-enterprise/icon.png https://www.getdbt.com/ui/img/dbt-icon.png 301! /dbt-cli/installation-guides/centos /dbt-cli/install/overview 302 /dbt-cli/installation-guides/centos /dbt-cli/install/overview 302 /dbt-cli/installation-guides/install-from-source /dbt-cli/install/from-source 302 @@ -5,14 +9,15 @@ /dbt-cli/installation-guides/ubuntu-debian /dbt-cli/install/overview 302 /dbt-cli/installation-guides/windows /dbt-cli/install/overview 302 /dbt-cli/installation /dbt-cli/install/overview 302 +/dbt-jinja-functions /reference/dbt-jinja-functions 302 /docs /docs/introduction 302 /docs/adapter /docs/writing-code-in-dbt/jinja-context/adapter 302 /docs/analyses /docs/building-a-dbt-project/analyses 302 /docs/api-variable /docs/writing-code-in-dbt/api-variable 302 /docs/archival /docs/building-a-dbt-project/archival 302 /docs/artifacts /docs/dbt-cloud/using-dbt-cloud/artifacts 302 -/docs/best-practices /docs/guides/best-practices 302 /docs/bigquery-configs /reference/resource-configs/bigquery-configs 302 +/reference/resource-properties/docs /reference/resource-configs/docs 302 /docs/building-a-dbt-project/building-models/bigquery-configs /reference/resource-configs/bigquery-configs 302 /docs/building-a-dbt-project/building-models/configuring-models /reference/model-configs /docs/building-a-dbt-project/building-models/enable-and-disable-models /reference/resource-configs/enabled 302 @@ -36,7 +41,7 @@ /docs/building-a-dbt-project/using-operations /docs/building-a-dbt-project/hooks-operations 302 /docs/building-a-new-adapter /docs/contributing/building-a-new-adapter 302 /docs/building-models /docs/building-a-dbt-project/building-models 302 -/docs/building-packages /docs/guides/building-packages 302 +/docs/building-packages /guides/legacy/building-packages 302 /docs/centos /dbt-cli/installation 302 /docs/clean /reference/commands/clean 302 /docs/cloud-choosing-a-dbt-version /docs/dbt-cloud/cloud-configuring-dbt-cloud/cloud-choosing-a-dbt-version 302 @@ -67,8 +72,8 @@ /docs/connecting-your-database /docs/dbt-cloud/cloud-configuring-dbt-cloud/connecting-your-database 302 /docs/contributor-license-agreements /docs/contributing/contributor-license-agreements 302 /docs/creating-a-project /docs/building-a-dbt-project/dbt-projects/creating-a-project 302 -/docs/creating-new-materializations /docs/guides/creating-new-materializations 302 -/docs/custom-schema-tests /docs/guides/writing-custom-schema-tests 302 +/docs/creating-new-materializations /guides/legacy/creating-new-materializations 302 +/docs/custom-schema-tests /guides/legacy/writing-custom-generic-tests 302 /docs/dbt-api /docs/running-a-dbt-project/dbt-api 302 /docs/dbt-cloud-enterprise /docs/dbt-cloud/dbt-cloud-enterprise 302 /docs/dbt-cloud/cloud-configuring-repositories /docs/dbt-cloud/cloud-configuring-dbt-cloud/cloud-configuring-repositories 302 @@ -94,9 +99,21 @@ /docs/getting-started-with-jinja /docs/building-a-dbt-project/jinja-macros 302 /docs/global-cli-flags /reference/global-cli-flags 302 /docs/graph /docs/writing-code-in-dbt/jinja-context/graph 302 -/docs/guides/migration-guide/upgrading-to-014 /docs/guides/migration-guide/upgrading-to-0-14-0 302 -/docs/guides/migration-guide/upgrading-from-0-10-to-0-11 /docs/guides/migration-guide/upgrading-to-0-11-0 302 -/docs/guides/writing-custom-schema-tests /docs/guides/writing-custom-generic-tests +/docs/guides/building-packages /guides/legacy/building-packages 302 +/docs/guides/creating-new-materializations /guides/legacy/creating-new-materializations 302 +/docs/guides/debugging-errors /guides/legacy/debugging-errors 302 +/docs/guides/debugging-schema-names /guides/legacy/debugging-schema-names 302 +/docs/guides/getting-help /guides/legacy/getting-help 302 +/docs/guides/managing-environments /guides/legacy/managing-environments 302 +/docs/guides/navigating-the-docs /guides/legacy/navigating-the-docs 302 +/docs/guides/understanding-state /guides/legacy/understanding-state 302 +/docs/guides/videos /guides/legacy/videos 302 +/docs/guides/writing-custom-generic-tests /guides/legacy/writing-custom-generic-tests 302 +/docs/guides/writing-custom-schema-tests /guides/legacy/writing-custom-generic-tests 302 +/docs/guides/best-practices#choose-your-materializations-wisely /guides/legacy/best-practices#choose-your-materializations-wisely 302 +/docs/guides/best-practices#version-control-your-dbt-project /guides/legacy/best-practices#version-control-your-dbt-project 302 +/docs/best-practices /guides/legacy/best-practices 302 +/docs/guides/best-practices /guides/best-practices 302 /docs/hooks /docs/building-a-dbt-project/hooks-operations 302 /docs/init /reference/commands/init 302 /docs/install-from-source /dbt-cli/installation 302 @@ -108,13 +125,13 @@ /docs/log /docs/writing-code-in-dbt/jinja-context/log 302 /docs/macos /dbt-cli/installation 302 /docs/macros /docs/building-a-dbt-project/macros 302 -/docs/managing-environments /docs/guides/managing-environments 302 +/docs/managing-environments /guides/legacy/managing-environments 302 /docs/materializations /docs/building-a-dbt-project/building-models/materializations 302 /docs/model-selection-syntax /reference/node-selection/syntax 302 /docs/modules /docs/writing-code-in-dbt/jinja-context/modules 302 /docs/on-run-end-context /docs/writing-code-in-dbt/jinja-context/on-run-end-context 302 +/docs/overview /docs/introduction 302 /docs/package-management /docs/building-a-dbt-project/package-management 302 -/docs/profile /docs/available-adapters 302 /docs/profile-bigquery /reference/warehouse-profiles/bigquery-profile 302 /docs/profile-mssql /reference/warehouse-profiles/mssql-profile 302 /docs/profile-postgres /reference/warehouse-profiles/postgres-profile 302 @@ -176,7 +193,6 @@ /docs/snowflake-configs /reference/resource-configs/snowflake-configs 302 /docs/source /reference/commands/source 302 /docs/statement-blocks /docs/writing-code-in-dbt/jinja-context/statement-blocks 302 -/docs/supported-databases /docs/available-adapters 302 /docs/supported-databases/profile-bigquery /reference/bigquery-profile 302 /docs/supported-databases/profile-mssql /reference/mssql-profile 302 /docs/supported-databases/profile-postgres /reference/postgres-profile 302 @@ -193,15 +209,12 @@ /docs/this /docs/writing-code-in-dbt/jinja-context/this 302 /docs/tojson /docs/writing-code-in-dbt/jinja-context/tojson 302 /docs/ubuntu-debian /dbt-cli/installation 302 -/docs/upgrading-to-0-14-1 /docs/guides/migration-guide/upgrading-to-0-14-1 302 -/docs/upgrading-to-0-16-0 /docs/guides/migration-guide/upgrading-to-0-16-0 302 -/docs/upgrading-to-014 /docs/guides/migration-guide/upgrading-to-014 302 /docs/use-an-existing-project /docs/building-a-dbt-project/dbt-projects/use-an-existing-project 302 /docs/using-custom-aliases /docs/building-a-dbt-project/building-models/using-custom-aliases 302 /docs/using-custom-database /docs/building-a-dbt-project/building-models/using-custom-databases 302 /docs/using-custom-schemas /docs/building-a-dbt-project/building-models/using-custom-schemas 302 /docs/using-dbt-cloud /docs/dbt-cloud/using-dbt-cloud 302 -/docs/using-jinja /tutorial/using-jinja 302 +/docs/using-jinja /guides/getting-started/learning-more/using-jinja 302 /docs/using-operations /docs/building-a-dbt-project/hooks-operations 302 /docs/using-sources /docs/building-a-dbt-project/using-sources 302 /docs/using-sql-headers /reference/resource-configs/sql_header 302 @@ -210,12 +223,12 @@ /docs/using-variables /docs/building-a-dbt-project/building-models/using-variables 302 /docs/var /docs/writing-code-in-dbt/jinja-context/var 302 /docs/version /reference/global-cli-flags#version 302 -/docs/videos /docs/guides/videos 302 +/docs/videos /guides/legacy/videos 302 /docs/viewpoint /docs/about/viewpoint 302 /docs/windows /dbt-cli/installation 302 /docs/writing-code-in-dbt/class-reference /reference/dbt-classes 302 -/docs/writing-code-in-dbt/extending-dbts-programming-environment/creating-new-materializations /docs/guides/creating-new-materializations 302 -/docs/writing-code-in-dbt/extending-dbts-programming-environment/custom-schema-tests /docs/guides/writing-custom-schema-tests 302 +/docs/writing-code-in-dbt/extending-dbts-programming-environment/creating-new-materializations /guides/legacy/creating-new-materializations 302 +/docs/writing-code-in-dbt/extending-dbts-programming-environment/custom-schema-tests /guides/legacy/writing-custom-schema-tests 302 /docs/writing-code-in-dbt/getting-started-with-jinja /docs/building-a-dbt-project/jinja-macros 302 /docs/writing-code-in-dbt/jinja-context/adapter /reference/dbt-jinja-functions/adapter 302 /docs/writing-code-in-dbt/jinja-context/as_text /reference/dbt-jinja-functions/as_text 302 @@ -252,8 +265,10 @@ /docs/writing-code-in-dbt/jinja-context/toyaml /reference/dbt-jinja-functions/toyaml 302 /docs/writing-code-in-dbt/jinja-context/var /reference/dbt-jinja-functions/var 302 /docs/writing-code-in-dbt/macros /docs/building-a-dbt-project/jinja-macros 302 -/docs/writing-code-in-dbt/using-jinja /tutorial/using-jinja 302 -/faqs/getting-help/ /docs/guides/getting-help/ 302 +/docs/writing-code-in-dbt/using-jinja /guides/getting-started/learning-more/using-jinja 302 +/faqs/getting-help/ /guides/legacy/getting-help 302 +/migration-guide/upgrading-to-0-17-0 /guides/migration/versions 302 +/migration-guide/upgrading-to-0-18-0 /guides/migration/versions 302 /reference/accounts /dbt-cloud/api 302 /reference/api /dbt-cloud/api 302 /reference/connections /dbt-cloud/api 302 @@ -261,6 +276,7 @@ /reference/declaring-properties /reference/configs-and-properties 302 /reference/dbt-artifacts /reference/artifacts/dbt-artifacts 302 /reference/environments /dbt-cloud/api 302 +/reference/events /reference/events-logging 302 /reference/jobs /dbt-cloud/api 302 /reference/model-selection-syntax /reference/node-selection/syntax 302 /reference/project-configs/on-run-end /reference/project-configs/on-run-start-on-run-end 302 @@ -278,3 +294,86 @@ https://tutorial.getdbt.com/* https://docs.getdbt.com/:splat 301! /reference/project-configs/source-paths /reference/project-configs/model-paths 302 /reference/project-configs/data-paths /reference/project-configs/seed-paths 302 /reference/project-configs/modules-paths /reference/project-configs/packages-install-path 302 +/docs/dbt-cloud/using-dbt-cloud/cloud-slack-notifications /docs/dbt-cloud/using-dbt-cloud/cloud-notifications 302 +/reference/warehouse-profiles/presto-profile /reference/profiles.yml 302 +/setting-up /guides/getting-started/getting-set-up/setting-up-bigquery 302 +/tutorial/setting-up /guides/getting-started 302 +/tutorial/test-and-document-your-project /guides/getting-started/building-your-first-project/test-and-document-your-project 302 +/tutorial/build-your-first-models /guides/getting-started/building-your-first-project/build-your-first-models 302 +/tutorial/deploy-your-project /guides/getting-started/building-your-first-project/schedule-a-job 302 +/tutorial/using-jinja /guides/getting-started/learning-more/using-jinja 302 +/tutorial/refactoring-legacy-sql /guides/getting-started/learning-more/refactoring-legacy-sql 302 +/tutorial/2b-create-a-project-dbt-cli.md /guides/getting-started/learning-more/getting-started-dbt-core 302 +/tutorial/create-a-project-dbt-cli /guides/getting-started/learning-more/getting-started-dbt-core 302 +/tutorial/2a-create-a-project-dbt-cloud.md /guides/getting-started 302 +/tutorial/create-a-project-dbt-cloud /guides/getting-started 302 +/tutorial/getting-started /guides/getting-started 302 +/docs/dbt-cloud/cloud-changelog /docs/dbt-cloud/release-notes 302 +/faqs/all /docs/faqs 301! +/faqs/* /docs/faqs/:splat 301 +/tutorial/learning-more/* /guides/getting-started/learning-more/:splat 301 +/tutorial/getting-set-up/* /guides/getting-started/getting-set-up/:splat 301 +/tutorial/building-your-first-project/* /guides/getting-started/building-your-first-project/:splat 301 +/tutorial/refactoring-legacy-sql /guides/getting-started/learning-more/refactoring-legacy-sql 302 +/blog/change-data-capture-metrics /blog/change-data-capture 301 +/blog/model-timing-tab /blog/how-we-shaved-90-minutes-off-model 301 +# supported data platforms page +/docs/profile /docs/supported-data-platforms 302 +/docs/available-adapters /docs/supported-data-platforms 302 +/docs/supported-databases /docs/supported-data-platforms 302 +# migration and legacy guides +/docs/guides/migration-guide/upgrading-to-0-14-0 /guides/migration/versions 302 +/docs/guides/migration-guide/upgrading-to-0-15-0 /guides/migration/versions 302 +/docs/guides/migration-guide/upgrading-to-0-16-0 /guides/migration/versions 302 +/docs/guides/migration-guide/upgrading-to-0-17-0 /guides/migration/versions 302 +/docs/guides/migration-guide/upgrading-to-0-18-0 /guides/migration/versions 302 +/docs/guides/migration-guide/upgrading-to-0-19-0 /guides/migration/versions 302 +/docs/guides/migration-guide/upgrading-from-0-10-to-0-11 /guides/migration/versions 302 +/docs/guides/migration-guide/upgrading-to-014 /guides/migration/versions 302 +/docs/upgrading-to-014 /guides/migration/versions 302 +/docs/upgrading-to-0-14-1 /guides/migration/versions 302 +/docs/upgrading-to-0-16-0 /guides/migration/versions 302 +/docs/guides/migration-guide/upgrading-to-0-20-0 /guides/migration/versions/upgrading-to-v0.20 302 +/docs/guides/migration-guide/upgrading-to-0-21-0 /guides/migration/versions/upgrading-to-v0.21 302 +/docs/guides/migration-guide/upgrading-to-1-0-0 /guides/migration/versions/upgrading-to-v1.0 302 +/docs/guides/migration-guide/upgrading-to-v1.0 /guides/migration/versions/upgrading-to-v1.0 302 +/docs/guides/getting-help /guides/legacy/getting-help 302 +/docs/guides/migration-guide/* /guides/migration/versions/:splat 301! +/docs/guides/* /guides/legacy/:splat 301! +docs/contributing/building-a-new-adapter /docs/contributing/adapter-development/3-building-a-new-adapter 302 +docs/contributing/testing-a-new-adapter /docs/contributing/adapter-development/4-testing-a-new-adapter 302 +docs/contributing/documenting-a-new-adapter /docs/contributing/adapter-development/5-documenting-a-new-adapter 302 +/docs/building-a-new-adapter /docs/contributing/adapter-development/3-building-a-new-adapter 301! +/reference/warehouse-profiles/impala-profile /reference/warehouse-setups/impala-setup 302 +/reference/warehouse-profiles/exasol-profile /reference/warehouse-setups/exasol-setup 302 +/reference/warehouse-profiles/layer-profile /reference/warehouse-setups/layer-setup 302 +/reference/warehouse-profiles/postgres-profile /reference/warehouse-setups/postgres-setup 302 +/reference/warehouse-profiles/greenplum-profile /reference/warehouse-setups/greenplum-setup 302 +/reference/warehouse-profiles/alloydb-profile /reference/warehouse-setups/alloydb-setup 302 +/reference/warehouse-profiles/azuresynapse-profile /reference/warehouse-setups/azuresynapse-setup 302 +/reference/warehouse-profiles/snowflake-profile /reference/warehouse-setups/snowflake-setup 302 +/reference/warehouse-profiles/rockset-profile /reference/warehouse-setups/rockset-setup 302 +/reference/warehouse-profiles/trino-profile /reference/warehouse-setups/trino-setup 302 +/reference/warehouse-profiles/glue-profile /reference/warehouse-setups/glue-setup 302 +/reference/warehouse-profiles/duckdb-profile /reference/warehouse-setups/duckdb-setup 302 +/reference/warehouse-profiles/vertica-profile /reference/warehouse-setups/vertica-setup 302 +/reference/warehouse-profiles/clickhouse-profile /reference/warehouse-setups/clickhouse-setup 302 +/reference/warehouse-profiles/athena-profile /reference/warehouse-setups/athena-setup 302 +/reference/warehouse-profiles/iomete-profile /reference/warehouse-setups/iomete-setup 302 +/reference/warehouse-profiles/mssql-profile /reference/warehouse-setups/mssql-setup 302 +/reference/warehouse-profiles/tidb-profile /reference/warehouse-setups/tidb-setup 302 +/reference/warehouse-profiles/materialize-profile /reference/warehouse-setups/materialize-setup 302 +/reference/warehouse-profiles/redshift-profile /reference/warehouse-setups/redshift-setup 302 +/reference/warehouse-profiles/databricks-profile /reference/warehouse-setups/databricks-setup 302 +/reference/warehouse-profiles/bigquery-profile /reference/warehouse-setups/bigquery-setup 302 +/reference/warehouse-profiles/dremio-profile /reference/warehouse-setups/dremio-setup 302 +/reference/warehouse-profiles/oracle-profile /reference/warehouse-setups/oracle-setup 302 +/reference/warehouse-profiles/teradata-profile /reference/warehouse-setups/teradata-setup 302 +/reference/warehouse-profiles/singlestore-profile /reference/warehouse-setups/singlestore-setup 302 +/reference/warehouse-profiles/sqlite-profile /reference/warehouse-setups/sqlite-setup 302 +/reference/warehouse-profiles/spark-profile /reference/warehouse-setups/spark-setup 302 +/reference/warehouse-profiles/mindsdb-profile /reference/warehouse-setups/mindsdb-setup 302 +/reference/warehouse-profiles/ibmdb2-profile /reference/warehouse-setups/ibmdb2-setup 302 +/reference/warehouse-profiles/firebolt-profile /reference/warehouse-setups/firebolt-setup 302 +/reference/warehouse-profiles/mysql-profile /reference/warehouse-setups/mysql-setup 302 +/reference/warehouse-profiles/hive-profile /reference/warehouse-setups/hive-setup 302 diff --git a/contributing/adding-page-components.md b/contributing/adding-page-components.md new file mode 100644 index 00000000000..1a43cbe8a81 --- /dev/null +++ b/contributing/adding-page-components.md @@ -0,0 +1,90 @@ +## Using warehouse components + +You can use the following components to provide code snippets for each supported warehouse. You can see a real-life example in the docs page, "[Initialize your database](https://docs.getdbt.com/guides/getting-started/getting-set-up/setting-up-databricks#initialize-your-dbt-project)." + +Identify code by labeling with the warehouse names: + +```js + + +
+ + ```sql + select * from `dbt-tutorial.jaffle_shop.customers` + ``` + +
+ +
+ + ```sql + select * from default.jaffle_shop_customers + ``` + +
+ +
+``` + +## Using tabs for multiple resources + +You can use the following components to provide code snippets in a tabbed view. You can see a real-life example in the docs page, "[Building models](https://docs.getdbt.com/docs/building-a-dbt-project/building-models#building-dependencies-between-models)." + +Identify code and code files by labeling with the component they are describing: + +```code + + + + + + + ```sql + + {{ config( + + ) }} + + select ... + + + ``` + + + + + + ```yml + models: + [](resource-path): + + + ``` + + + + + + + + + + ```yml + sources: + [](resource-path): + + + ``` + + + + + + +``` \ No newline at end of file diff --git a/contributing/content-style-guide.md b/contributing/content-style-guide.md new file mode 100644 index 00000000000..d59eb98e118 --- /dev/null +++ b/contributing/content-style-guide.md @@ -0,0 +1,417 @@ +# Content style guide + +Welcome to the content style guide for docs.getdbt.com! We aim to provide docs that help readers accomplish their goals. To this end, we should focus on clarity and meaning in our sentences, and follow up with consistency and grammatical correctness when we can. + +This guide includes standards we want to emphasize, likely because we've made deliberate decisions about them. You can refer to [_The Microsoft Writing Style Guide_](https://docs.microsoft.com/en-us/style-guide/welcome/) and the [_Chicago Manual of Style_](https://www.chicagomanualofstyle.org/home.html) for those nagging questions like, "[Should I use an Em dash, En dash or hyphen?](https://docs.microsoft.com/en-us/style-guide/punctuation/dashes-hyphens/)" + +### Table of Contents +* [Callouts](#callouts) +* [Text formatting](#Text-formatting) +* [UI elements](#UI-elements) +* [Titles](#Titles) +* [Placeholder text](#Placeholder-text) +* [Oxford comma](#Oxford-comma) +* [Lists](#Lists) +* [Tables](#Tables) +* [Word choice & terminology](#Word-choice-&-terminology) +* [Links](#Links) +* [Images](#Images) +* [Talk to us](#Talk-to-us) + +## Callouts + +Callouts highlight important or high-value information that readers need to know. We want callouts to stand out, so we should keep their content to a minimum, avoiding general information, permissions, or prerequisites. Too much information can make it difficult to absorb. Imagine driving down one block with five stop signs!?! + +Use callouts sparingly for high-value information — avoid including general information, permissions, or prerequisites in callouts. + +## Text formatting +You consider many elements when designing technical docs, and the way you format text can help you achieve a well-articulated design. With consistency of use, well-formatted text creates a single voice when there are multiple authors/contributors, increases the readability of the content, and further establishes an organization's branding. + +### Italics +Use italics to decorate text for emphasis. + +:white_check_mark: Do _not_ leave any personal belongings on the bus. + +### Bold +Don't use bold for emphasis. It's reserved for titles, headers, and UI elements. + +:white_check_mark: Click **Pay** to complete your purchase. + +:x: **DO NOT** lock the door. + +### Code +Use code font to decorate text for: + +|Text |Example | +|-----|--------| +| source code (like SQL, YAML, and JavaScript) | `select * from customers` | +| [placeholder text](#placeholder-text) | `CUSTOMER_ID` | +| directory paths | `/opt/homebrew/bin/` | +| directory names | The file is in the `etc` directory. | +| filenames | Update your `dbt_project.yml` to configure this | +| git branch names | When done, merge your PR to `main` | +| commands | To check the status of a running cluster, use the `ghe-cluster-status` command | +| arguments, parameters, keys | Update the `name` in your YAML file | + +Use [code blocks](#code-blocks) for longer or more complex commands. Do _not_ use multiple font decorations on text as it can cause it to be visually busy and so harder to read; for example, avoid inline links in command names. + +### Code blocks + +Keep lines in code samples to about 60 characters, to avoid requiring readers to scroll horizontally in the code block. Locate explanatory text before the code block, rather than using comments inside the code block. + +Within code blocks: + +* Avoid using markup before the command output. +* Only use $ before the command itself if you’re showing the command’s output in the same block. + +#### Code block examples + +Provide context for code examples referring to a larger file by showing the relevant section of the file, so that users understand how to edit their own code. + +:white_check_mark: Use: + +```yaml +name: my_dbt_project +version: 1.0.0 + +config-version: 2 + +vars: + # The `start_date` variable will be accessible in all resources + start_date: '2021-06-01' +``` + +:x: Avoid: +```yaml +config-version: 2 + +vars: + # The `start_date` variable will be accessible in all resources + start_date: '2021-06-01' +``` + +## UI elements + +Similar to [text formatting](#text-formatting), consistent use of how we refer to the user interface (UI) elements can help increase the scannability and readability of the docs for our readers. + +The following sections describe the guidelines for documenting UI elements. + +### Buttons + +Bold the button name and use the term click. + +:white_check_mark: Click **Submit** to create a new branch. + +:x: Click the **Submit** button to create a new branch. + +### Checkboxes + +Bold the name of the checkbox. You can use the terms select, choose, or clear. + +:white_check_mark: Select the **New** option. + +:white_check_mark: Clear the **New** option. + +:x: Check the **New** option. + +:x: Uncheck the **New** option. + +### Dropdown menus + +Bold the name of the dropdown menu and also the names of its list items. You can use the terms select or choose. + +:white_check_mark: In the **Create** menu, select the **From a template** option. + +:white_check_mark: Choose **Create** > **From a template** to create a new page. + +### Radio buttons + +Bold the name of the radio button. You can use the terms select, choose, or clear. + +:white_check_mark: Choose the **Small size** option. + +:white_check_mark: Clear the **Small size** option. + +:x: Click the **Small size** radio button. + +### Text fields + +Bold the name of the text field and use the term enter for user input. + +:white_check_mark: In the **Address** field, enter your company's address. + +### Location of UI elements + +When referring to UI elements, describe its position in the software application to help users locate it easily. You can use upper, lower, center, left, and right to do this. + +:white_check_mark: Use the search box in the upper left corner to explore more topics. + +:white_check_mark: You can view alerts in the lower right corner of the tool. + +:white_check_mark: You can manage your projects in the file explorer on the left side of the page. + +:white_check_mark: Access all guides from the Guides menu at the top of the page. + + +### UI text + +When referring to different sections of the IDE, use the name of the section and bold it. Avoid using the terms panel and pane. + +:white_check_mark: In the **Settings** section, choose the default address for your account. + +:x: You can review all your past orders from the **History** pane. + +## Titles + +People make use of titles in many places like table headers, section headings (such as an H2, H3, or H4), page titles, sidebars, and so much more. + +When generating titles or updating them, use sentence case. It sets a more conversational tone to the docs—making the content more approachable and creating a friendly feel. + +We've defined five content types you can use when contributing to the docs (as in, writing or authoring). Learn more about title guidelines for [each content type](https://github.com/dbt-labs/docs.getdbt.com/blob/current/contributing/content-types.md). + +## Placeholder text + +Placeholder text is something that the user should replace with their own text. For example, their website domain name. + +Use all capital letters([screaming snake case](https://fission.codes/blog/screaming-snake-case/)) to indicate text that changes in the user interface or that the user needs to supply in a command or code snippet. Avoid surrounding it in brackets or braces, which someone might copy and use, producing an error. + +Identify what the user should replace the placeholder text with in the paragraph preceding the code snippet or command. + +:white_check_mark: The following is an example of configuring a connection to a Redshift database. In your YAML file, you must replace `CLUSTER_ID` with the ID assigned to you during setup: + +```yaml +my-redshift-db: + target: dev + outputs: + dev: + type: redshift + method: iam + cluster_id: CLUSTER_ID + +``` + +## Oxford comma + +Use an Oxford comma (serial comma) when you have a series with three or more terms. + +The sentence below could mean my parents are Maria and Lin or it could mean they are people I love in addition to my parents. + +:x: I love my parents, Maria and Lin. + +Removing this ambiguity by using Oxford commas makes content easier to translate. + +:white_check_mark: I love my parents, Maria, and Lin. + +## Lists + +People often scan technical documentation until they find the information they’re looking for, instead of reading it line by line. Lists are a great way to present content in a scannable format. + +There are bulleted (unordered) lists and numbered (ordered) lists. If the list items can be in any order, use a bulleted list. For a prioritized list or a set of steps, use a numbered list. + +Guidelines for making lists are: +- There are at least two items. +- All list items follow a consistent, grammatical structure (like each item starts with a verb, each item begins with a capitalized word, each item is a sentence fragment). +- Lists items don't end in commas, semicolons, or conjunctions (like "and", "or"). However, you can use periods if they’re complete sentences. +- Introduce the list with a heading or, if it's within text, as a complete sentence or as a sentence fragment followed by a colon. + +If the list starts getting lengthy and dense, consider presenting the same content in a different format such as a table, as separate subsections, or a new guide. + +### Examples of lists + +A bulleted list with introductory text: + +> A dbt project is a directory of `.sql` and .yml` files. The directory must contain at a minimum: +> +> - Models: A model is a single `.sql` file. Each model contains a single `select` statement that either transforms raw data into a dataset that is ready for analytics, or, more often, is an intermediate step in such a transformation. +> - A project file: A `dbt_project.yml` file, which configures and defines your dbt project. + +A bulleted list with sentence fragments: + +> Supported languages: +> - Python +> - Java +> - C++ + +A numbered list following an H2 heading: + +> ## Check out a new git branch +> +> 1. Make sure you're in the Develop interface. If you're not, click the hamburger menu, then click `Develop`. The main branch is now set as read-only mode so you'll need to create a new branch. +> +> 2. Click **+ create new branch** and enter `add-customers-model` for the branch name. + +## Tables +Tables provide a great way to present complex information and can help the content be more scannable for users, too. + +There are many ways to construct a table, like row spanning and cell splitting. Make sure the content is clear, concise, and presents well on the web page (like avoid awkward word wrapping). + +Guidelines for making tables are: +- Introduce the table with a heading or, if it's within text, as a complete sentence or as a sentence fragment followed by a colon. +- Use a header row +- Use sentence case for all content, including the header row +- Content can be complete sentences, sentence fragments, or single words (like `Currency`) + +If the table starts getting cumbersome and hard to read (that is, bad UX), consider presenting the same content in a different format such as a definition list. Consider your design of the content, too (like using flag icons instead of country names as it takes up less space on a page). Or, you could split the content so they’re in separate subsections, separate tabs, or separate pages (like by data warehouse or programming language). + +### Examples of tables + +A table with introductory text: + +> You can use **custom schemas** in dbt to build models in a schema other than your target schema. By default, dbt generates a model's schema name by concatenating the custom schema to the target schema, as follows: `_;`. +> +> | Target schema | Custom schema | Resulting schema | +> | ------------- | ------------- | ---------------- | +> | <target_schema> | None | <target_schema> | +> | analytics | None | analytics | +> | dbt_alice | None | dbt_alice | +> | <target_schema> | <custom_schema> | <target_schema>\_<custom_schema> | +> | analytics | marketing | analytics_marketing | +> | dbt_alice | marketing | dbt_alice_marketing | + +A table following an H3 heading: + +> ### Arguments +> | Name | Description | Values | +> | -----| ----------- | ------ | +> | `-help` | Displays information on how to use the command. | Doesn't take any values. | +> | `-readable` | Print output in human readable format. | | +> | `-file` | Print output to file instead of stdout. | Name of the file. | + +## Word choice & terminology + +### Abbreviations + +According to The American Heritage Dictionary, an abbreviation is "[a] shortened form of a word or phrase used chiefly in writing to represent the complete form" but, unlike the acronym, it's letters aren't pronounced together as one full word. + +### Acronyms + +Spell out acronyms the first time they’re used in an article, except in titles or headers. If an uncommon abbreviation appears in the title, define it in the first couple of lines of the body text. + +_Do_ provide the full word or phrase being abbreviated before the abbreviation itself and encapsulate within parentheses.
+ * *Example: Integrated Development Environment (IDE)* + +**DO NOT** use an acronym if its only used once. Please use the full word or phrase for its one-time use. + +### Latin abbreviations + +Avoid using Latin abbreviations. These terms are harder to localize/translate. + +Some common Latin abbreviations and other words to use instead: + +| Avoid | Use | Example | +|--------------------|------------|---------| +| i.e. | that is | Use incremental models when your dbt runs are becoming too slow (that is, don't start with incremental models) | +| e.g. | | | +| etc. | | | + + +### Prepositions + +Avoid ending a sentence with a preposition unless the rewritten sentence would sound awkward or too formal. + +### Product names + +Product names, trademarks, services, and tools should be written as proper nouns, unless otherwise specified by the company or trademark owner. + +### Terms to use or avoid + +Use industry-specific terms and research new/improved terminology. Also refer to the Inclusive Language section of this style guide for inclusive and accessible language and style. + +**DO NOT** use jargon or language familiar to a small subset of readers or assume that your readers understand ALL technical terms. + +Use | Avoid +-- | -- +type (in the user interface) | enter (in the user interface) +enter (in the command line) | type (in the command line) +email | e-mail +on dbt | on a remote server +person, human | client, customer +press (a key) | hit, tap +recommended limit | soft limit +sign in | log in, login +sign up | signup +terminal | shell +username | login + + +## Links + +Links embedded in documentation are about trust. Users trust that we will lead them to sites or pages related to their reading content. In order to maintain that trust, it is important that links are transparent, up-to-date, and lead to legitimate resources. + +### Link format + +Hyperlinks should be text only, please avoid image-based links. The text should clearly state the destination. + + :x: For more information, visit https://docs.getdbt.com + + :x: For more information, [_Click Here_](https://docs.getdbt.com/) + + ✅ For more information, visit the [_dbt Labs doc site_](https://docs.getdbt.com/). + +### Link destinations + +The link destination should be directly related to the topic of the document. There are many valid destinations, including educational material, third-party product instructions, explanations of a limitation, FAQs, and other pages on the dbt Labs site. + +Some destination types should be avoided entirely: +* Sales or promotional material. +* General landing pages - link to specific information. +* Content that is hidden behind paywalls or that requires credentials to access. +* Untrusted or otherwise questionable sites that might contain dubious information, malware, or suspicious behavior. +* Personal sites such as file sharing folders or blogs. +* Instant downloads (the user clicks the link and the download begins immediately). If you need to host a file, please contact dbt Labs for a solution. + + +## Images + +### Alt text + +In order to include people using screen readers, remember to add alternate text for images. Every image should include an alt attribute that provides a complete description of the image for the user. For more information, see “Images, image maps, and multimedia” in Microsoft’s Style Guide. + +### Icons +When describing icons that appear on-screen, use the [_Google Material Icons_](https://fonts.google.com/icons?selected=Material+Icons) reference page as a guide. + +:x:Click on the hamburger menu icon + +:white_check_mark:Click on the menu icon + +### Image names + +Two words that are either adjectives or nouns describing the name of a file separated by an underscore `_` (known as `snake_case`). The two words can also be separated by a hyphen (`kebab-case`). +* Types and Examples + * `snake_case` + * *gitlab_setup.jpg* + * `kebab-case` + * *sso-setup.jpg* + +### Screenshots + +There are scenarios where a visual aid may be beneficial, especially when creating a document highlighting navigation. Screenshots provide a lightweight alternative to videos and are much easier to produce, edit, and insert into documents. Due to their limitations, they should be used sparingly. + +It is important to remember that all of dbt Labs documentation is currently in English only. Users might require screen readers or translation programs to read content and these will not pick up the text within screenshots. + +#### How to take a screenshot + +Both macOS and Windows include tools that allow you to capture and manipulate screenshots. You can use alternatives based on your preferences, but avoid programs that place a watermark over the content. + +* [How to take screenshots in MacOS](https://support.apple.com/en-us/HT201361#:~:text=How%20to%20take%20a%20screenshot,to%20save%20to%20your%20desktop.) +* [How to take screenshots with the Snipping Tool in Windows](https://support.microsoft.com/en-us/windows/use-snipping-tool-to-capture-screenshots-00246869-1843-655f-f220-97299b865f6b#:~:text=Press%20Ctrl%20%2B%20PrtScn%20keys.,that%20you%20want%20to%20capture.) + +#### Screenshot guidelines + +Once you have determined that a screenshot will add value to the document where words alone can't, refer to these guidelines for capturing the information: + +* Use screenshots to highlight navigation, on-screen elements, and other noteworthy product visuals. +* Avoid using screenshots to demonstrate inputs and outputs. All code snippets and sample results should be in the documents as text fields. +* Use concise filenames that are relevant to the content contained within. Enumerate them if they are part of a sequence. + + :x: screenshot-august0822.jpg + + :white_check_mark: viewing-admins-01.jpg + +* Redact all sensitive information from the screenshot — names, email addresses, phone numbers, or anything that could be considered personally identifiable information (PII) should be obfuscated. +* Avoid URL and bookmark bars in the screenshot and limit the scope to the product and page being documented. + +## Talk to us +Your feedback helps drive us forward. At dbt Labs, we want you to get involved if you see areas in the documentation that need improvement. That might include becoming a docs contributor or simply filing a GitHub issue so we know where to look. We have an incredible community of contributors, and our documents reflect that. + +dbt Labs is growing, and a team of technical writers is now handling reviews and requests. This style guide will continue to grow as we identify more ways to make the documents easily accessible to all users. diff --git a/contributing/content-types.md b/contributing/content-types.md new file mode 100644 index 00000000000..f1094e29b2c --- /dev/null +++ b/contributing/content-types.md @@ -0,0 +1,167 @@ +# Content types + +These content types can all form articles. Some content types can form sections within a larger article. + +# TOC + +* [Conceptual](#conceptual) +* [Referential](#referential) +* [Procedural](#procedural) +* [Guide](#guide) +* [Quickstart](#quickstart-guide) + + +## Conceptual + +Conceptual content provides a clear, high-level overview of a feature or topic. Conceptual content should be clear enough for a novice audience but also include relevant information for advanced users. Conceptual content should contextualize a task within the reader’s workflow, such as including use cases or examples. + +Conceptual content can be found in a standalone article or in a conceptual section within another article. +Most major features or parts of the product will get their own conceptual article. +For smaller or more specific conceptual sections that accompany one or more procedures, we instead place conceptual content within guides. + +### Contents of a conceptual article or header + +Describe in plain language what the feature, product, or topic is +Describe its purpose and why it’s useful to the reader (value proposition) +If relevant, describe how the feature or topic works without getting into too much irrelevant technical detail +Highlight any details the reader needs to know to use the feature +Include next steps for getting started with the feature (whether through further reading links or content within the article itself) + +### Titles for conceptual content + +Conceptual articles or headers of conceptual sections should always start with “About [topic]” +Always use a noun in the place of the topic, not a gerund + +### Examples of conceptual content + +* Conceptual articles +TBD +* Conceptual sections within other articles +TBD + +## Referential + +Referential content provides detailed information that customers need to access or select from to use a specific part of the product. + +Referential content can be found in a standalone article or in a referential section within another article. + +* Some major subjects may require their own referential article, especially if there is a large amount of referential content, such as for search syntax or YAML syntax. +* For smaller or more specific referential sections that accompany conceptual or procedural information, like a list of a feature’s supported languages or hardware requirements, we’ll add referential sections in context within procedural or conceptual content. + +### Contents of a referential article or header + +* Use an introductory sentence or an entire conceptual section to introduce relevant information about the referential content. This should be general enough to apply to all of the following content. + +* Present the actual referential content clearly and consistently. +* For subjects with a single element to explain, use a list. + * Example: TBD +* For subjects with multiple elements, use a table + * Example: TBD +* For longer referential content, such as YAML syntax for workflows, use headers consistently: + * H3 headers for each distinct section + * H4 headers for subsections, such as examples + * Example: TBD + +Formatting API reference documentation (TBD) + +### Title guidelines for referential content +Referential articles or headers of referential sections should clearly describe the contents of the section, and generally begin with nouns +Titles should include enough information to be accessible to novice users and fully describe the contents of each section +Titles should avoid stacked nouns - use prepositions to break up long strings of nouns + +### Examples of referential content + +* Referential articles +TBD +* Referential sections within other articles +TBD +* Placeholder: Referential REST content +* Placeholder: Referential GraphQL content + +## Procedural + +Procedural articles tell users how to complete a single task from start to finish, most often using numbered steps. Procedural content should contextualize a task within the reader’s workflow, such as including use cases or examples. + +Procedural content can be found in a standalone article or in a procedural section within another article. If an article contains a procedure, it’s always considered either a procedural article (single procedure) or a guide (multiple procedures). For details on creating articles with multiple procedural sections, see the section on guides below. + +When creating multiple related procedures, or when describing how to both do and undo a setting or action, you should consider gathering all of the procedures into a guide rather than creating multiple individual articles. +* If disabling or undoing a procedure requires the same steps and has no detailed implications, then you do not need to write a separate procedure for undoing the setting. +* If disabling or undoing a procedure requires different steps or has important or detailed implications, create a guide with an agnostic title (unless there are significant reasons to create separate individual procedural articles for both doing and undoing a task). + +Procedural content should include troubleshooting tips as frequently as possible. See the troubleshooting section below for more information. +### Title guidelines for procedural articles +* Procedural articles or procedural sections within articles should be task-based and begin with a gerund +* Use active and specific verbs (occasionally this takes some brainstorming or hitting a thesaurus) +* Titles should specifically describe the task contained within the article or header +* Article title length: maximum 80 characters, 60 if possible + +#### Examples of procedural articles: +* Adding information to your account +* Setting up metrics in dbt Projects +* Setting up continuous integration + +## Guide + +Guides (formerly called long-form procedural articles) are highly-approachable articles that group information in context to help readers complete a complex task or set of related tasks. Guides eliminate duplication and ensure the customer finds contextual content in the right place. Guides may be a set of tasks within the reader’s larger workflow, such as including use cases. + +Guides combine the content types within a single article to illustrate an entire workflow within a single page, rather than splitting the workflow out into separate pieces. Guides containing multiple procedures help us scale as more options are added to the product. Users may need to complete different procedures within the guide at different times, or refer back to the guide for conceptual content or to complete a followup task. +Example usage: If there is a large number of the same type of setting, use a guide that gathers all of the tasks in context. + +Guides must include a table of contents. +You can replicate the guide’s title in a header if needed. + +### Contents of guides + +* Guides contain multiple headers. +* Guides contain at least one procedural section, plus at least one additional conceptual, referential, or procedural section. +* Content within guides follows the content order used throughout the site. +* Guides should include troubleshooting sections as frequently as possible. See the troubleshooting section below for more information. + +### Title guidelines for guides + +* Titles of guides should be task-based and begin with a gerund +* Titles should be general enough to describe the range of information and tasks contained within the article +* Titles should describe the setting being toggled and should be agnostic about what setting the reader chooses, e.g., “Setting repository visibility” instead of “Making a private repository public” + +### Examples of guides +TBD + +## Quickstart guide + +Quickstart guides are a type of article that enable the user to complete a discrete, focused task in a single sitting, illustrating an entire workflow in a single page. Quickstart guides follow the guide model, with a few exceptions noted here - see the guides section above for anything not covered here. + +Quickstart guides are generally more conversational in tone than our other documentation. + +### Contents of quickstart guides + +* Table of contents +* Introduction: + * Clarifies audience + * Clearly states prerequisites and prior knowledge needed + * States what the user will accomplish or build + * Includes an example of a successful project + * Does not include the expected amount of time that it may take users to complete the task, as this is highly dependent on the experience level of the user and can be demoralizing for beginners +* Procedural sections + * Based on the audience for the guide, the steps can be less explicit and formal than those used in procedural content. You do not have to use existing reusables to form these steps if the audience doesn’t require that level of detail. + * Use: “From your profile, click **Settings, and then click **Developer settings**.” + * Avoid: In the upper-right corner of any page, click your profile photo, then click **Settings**. In the left sidebar, click **Developer settings**. + * Link out to other articles or resources rather than replicating them, to avoid interrupting the flow of information in the quickstart. + * Give visual cues. Use code blocks and screenshots heavily to help reassure users that they're performing the correct actions. + * Provide real examples. For example, don't tell a user to "Enter a commit message," give them an appropriate example commit message that matches the previous steps. +* Troubleshooting + * Acknowledge what may go wrong in the task and list a few common problems readers might run into with solutions. +* Conclusion + * Review what the user has accomplished or built. Refer back to the project provided in the introduction as an example of a successful project. +* Next steps + * Include 2-3 actionable next steps that the user take after completing the guide. Link off to other related information like: + * Projects that illustrate the introduced concepts + * Relevant information + * Relevant Learning courses + * Relevant published talks, blog posts, or Community posts + +### Title guidelines for quickstart guides +* Follow the title guidelines for guides +* Don’t use “quickstart” or “guide” in the title + +Examples +TBD diff --git a/contributing/contributor-code-of-conduct.md b/contributing/contributor-code-of-conduct.md new file mode 100644 index 00000000000..4e2f1a3be32 --- /dev/null +++ b/contributing/contributor-code-of-conduct.md @@ -0,0 +1,39 @@ +## Documentation contributor code of conduct + +dbt Labs is privileged to have a passionate community of supporters from all over the world. The contributors to the community represent the very best of what we can accomplish when people work collaboratively. The code of conduct is the cornerstone of informative, accessible, and inclusive documentation. + +### Be inclusive + +It is critical that all of dbt Labs documentation is inclusive and respectful of the audience, which consists of people in widely varying circumstances from all over the planet. When writing documentation, use words that are inclusive, anti-racist, and accessible. + +Individual words might be small, but together they can create community, belonging, and equity. Be empathetic in all word and style choices. Be accurate when referring to people and communities. + + +Here are resources to help you think about inclusive and accessible language and style: +* [18F Content Guide on Inclusive Language](https://content-guide.18f.gov/inclusive-language/) +* [Plain language guidelines (US Gov)](https://www.plainlanguage.gov/guidelines/) +* MailChimp Content Style Guide: + * [Writing About People](https://styleguide.mailchimp.com/writing-about-people/) + * [Writing for Accessibility](https://styleguide.mailchimp.com/writing-for-accessibility/) +* [Readability Guidelines (UK)](https://readabilityguidelines.co.uk/) +* [Conscious Style Guide](https://consciousstyleguide.com/) + +### Be respectful + +dbt Labs greatly admire the people who use dbt, partner with the organization, and implement our open source code. We strive for the tone of our documentation to reflect this and never make the reader feel patronized. + +Please don't use a disparaging tone when writing about another organization’s product or services. Remain neutral (or positive) and remove any personal feelings you might have from the content. + +Through mutual respect for one another, we can enlighten the world. + +### Be mindful + +Users represent a wide variety of positions in organizations across the world. The goal is to make our documents as appealing and easy to understand to as many people as possible. The dbt Labs style guide is a framework, but the experience you bring to the docs is what will give the most value to our readers. + +dbt Labs currently only publishes the content in English, but there are many users who are not native speakers. Keep the wording clear and professional. Avoid idioms, jokes, and anything else that might muddle the point. + +Write in straightforward language that requires minimal effort to parse or translate. This helps us reach a wider audience. + +### Be collaborative + +Community members and dbt Labs staff are in this together. We are a passionate group working towards a common goal — making dbt accessible to everyone. Just as we value community feedback, we are prepared to give feedback to all contributors, fostering an environment of friendly and respectful conversation. Together we can accomplish more than we ever could as individuals. You are an integral part of dbt Labs, and your enthusiasm for collaboration is essential to dbt Labs success. diff --git a/contributing/developer-blog.md b/contributing/developer-blog.md new file mode 100644 index 00000000000..1ad3c271ed3 --- /dev/null +++ b/contributing/developer-blog.md @@ -0,0 +1,65 @@ + +* [Contributing](#contributing) +* [Core Principles](#core-principles) + +## Contributing + +The dbt Developer Blog is a place where analytics practitioners can go to share their knowledge with the community. Analytics Engineering is a discipline we’re all building together. The developer blog exists to cultivate the collective knowledge that exists on how to build and scale effective data teams. + +### What makes a good developer blog post? + +- The short answer: Practical, hands on analytics engineering tutorials and stories + - [Slim CI/CD with Bitbucket](https://docs.getdbt.com/blog/slim-ci-cd-with-bitbucket-pipelines) + - [So You Want to Build a dbt Package](https://docs.getdbt.com/blog/so-you-want-to-build-a-package) + - [Founding an Analytics Engineering Team](https://docs.getdbt.com/blog/founding-an-analytics-engineering-team-smartsheet) +- See the [Developer Blog Core Principles](#core-principles) + +### How do I submit a proposed post? + +To submit a proposed post, open a `Contribute to the dbt Developer Blog` issue on the [Developer Hub repo](https://github.com/dbt-labs/docs.getdbt.com/issues/new/choose). You will be asked for: + +- A short (one paragraph) summary of the post you’d like to publish +- An outline of the post + +You’ll hear back from a member of the dbt Labs teams within 7 days with one of three responses: + +- The post looks good to go as is! We’ll ask you to start creating a draft based off of the initial outline you submitted +- Proposed changes to the outline. This could be additional focus on a topic you mention that’s of high community interest or a tweak to the structure to help with narrative flow +- Not a fit for the developer blog right now. We hugely appreciate *any* interest in submitting to the Developer Blog - right now our biggest backlog is capacity to help folks get these published. See below on how we are thinking about and evaluating potential posts. + +### What is the process once my blog is accepted? + +Once a blog is accepted, we’ll ask you for a date when we can expect the draft by. Typically we’ll ask that you can commit to having this ready within a month of submitting the issue. + +Once you submit a draft, we’ll return a first set of edits within 5 business days. + +The typical turnaround time from issue creation to going live on the developer blog is ~4 to 6 weeks. + +### What happens after my blog is published? + +We’ll share the blog on the dbt Labs social media channels! We also encourage you to share on the dbt Slack in #i-made-this. + +### What if my post doesn’t get approved? + +We want to publish as many community contributors as possible, but not every post will be a fit for the Developer Blog. That’s ok! There are many different reasons why we might not be able to publish a post right now and none of them reflect on the quality of the proposed post. + +- **dbt Labs capacity**: We’re committed to providing hands-on feedback and coaching throughout the process. Our goal is not just to generate great developer blogs - it’s to help build a community of great writers / practitioners who can share their knowledge with the community for years to come. This necessarily means we will be able to take on a lower absolute number of posts in the short term, but will hopefully be helpful for the community long term. +- **Focus on narrative / problem solving - not industry trends**: The developer blog exists, primarily, to tell the stories of analytics engineering practitioners and how they solve problems. The idea is that reading the developer blog gives a feel for what it is like to be a data practitioner on the ground today. This is not a hard and fast rule, but a good way to approach this is “How I/we solved X problem” rather than “How everyone should solve X problem”. + +We are very interested in stacks, new tools and integrations and will happily publish posts about this - with the caveat that the *focus* of the post should be solving real world problems. Hopefully if you are writing about these, this is something that you have used yourself in a hands on, production implementation. + +- **Right sized scope**: We want to be able to cover a topic in-depth and dig into the nuances. Big topics like “How should you structure your data team” or “How to ensure data quality in your organization” will be tough to cover in the scope of a single post. If you have a big idea - try subdividing it! “How should you structure your data team” could become “How we successfully partnered with our RevOps team on improving lead tracking” and “How to ensure data quality in your organization” might be “How we cleaned up our utm tracking”. + +### What if I need help / have questions: + +- Feel free to post any questions in #community-writers on the dbt Slack. + +## Core Principles + +- 🧑🏻‍🤝‍🧑🏾 The dbt Developer blog is written by humans **- individual analytics professionals sharing their insight with the world. To the extent feasible, a community member posting on the developer blog is not staking an official organizational stance, but something that *they* have learned or believe based on their work. This is true for dbt Labs employees as well. +- 💍 Developer blog content is knowledge rich - these are posts that readers share, bookmark and come back to time and time again. +- ⛹🏼‍♂️ Developer blog content is written by and for *practitioners* - end users of analytics tools (and sometimes people that work with practitioners). +- ⭐ Developer blog content is best when it is *the story which the author is uniquely positioned to tell.* Authors are encouraged to consider what insight they have that is specific to them and the work they have done. +- 🏎️ Developer blog content is actionable - readers walk away with a clear sense of how they can use this information to be a more effective practitioner. Posts include code snippets, Loom walkthroughs and hands-on, practical information that can be integrated into daily workflows. +- 🤏 Nothing is too small to share - what you think is simple has the potential to change someone's week. +- 🔮 Developer blog content is present focused —posts tell a story of a thing that you've already done or are actively doing, not something that you may do in the future. diff --git a/contributing/single-sourcing-content.md b/contributing/single-sourcing-content.md new file mode 100644 index 00000000000..1c47b87b977 --- /dev/null +++ b/contributing/single-sourcing-content.md @@ -0,0 +1,254 @@ +# Single-sourcing content + +* [About versioning](#adding-a-new-version) + * [Using end-of-life dates](#using-end-of-life-dates) + * [Versioning entire pages](#versioning-entire-pages) + * [Versioning blocks of content](#versioning-blocks-of-content) +* [Using global variables](#using-global-variables) +* [Reusing snippets of content](#reusing-snippets-of-content) + +## About versioning + +Versions are managed in the `versions` array located in the `website/dbt-versions.js` file. This array holds all versions which are selectable from the versions dropdown in the navigation. + +**The first version in the array is the latest version.** This is the default version when a visitor loads the page. + +### Adding a new version + +To add a new version to the site, a new object must be added to the `versions` array in the same format as existing versions. This object holds two properties: **version** and **EOLDate (See End of Life Dates below)**. + +Example Version: + +```jsx +exports.versions = [ + { + version: "1.2", + EOLDate: "2023-01-01" + } +] +``` + +The **version** property is the value which shows in the nav dropdown. This value is compared to the VersionBlock component on a docs page to determine whether that section should be visible for the current active version (See the **Versioning the Sidebar** section on using the VersionBlock component). + +### Using end-of-life dates + +The **EOLDate** property determines when a version is no longer supported. A version is supported up until 1 year after its release. + +When a documentation page is viewed, the **EOLDate** property for the active version is compared to today’s date. If the current version has reached, or is nearing the end of support, a banner will show atop the page, notifying the visitor of the end-of-life status. + +Two different versions of the banner will show depending on the end-of-life date: + +- When the version is within 3 months of the **EOLDate.** +- When the version has passed the **EOLDate.** + +#### Updating EOL date banner language + +The content for these two EOLDate banners are located in the `website/src/theme/DocPage/index.js` file, in the `EOLBannerText` property. + +### Versioning entire pages + +If a Docs page should not be available for the selected version, it is possible to version the entire page. This is managed in the `versionedPages` array within the `website/dbt-versions.js` file. + +Two things occur when a page is not available for the selected version: + +- A banner will appear atop the page, noting this page covers a new feature which isn’t available for the selected version. +- The page is removed from the sidebar + + +Example of how to version a page in the `dbt-versions.js` file: + +```jsx +exports.versionedPages = [ + { + "page": "docs/supported-data-platforms", + "firstVersion": "0.21", + } +] +``` + +### Properties for versioning an entire page + +**page** (mandatory): The path of the Docs page to version. This string must match the string for the page in the `sidebars.js` file. + +**firstVersion** (optional): Sets the first version which this page is available. + +**lastVersion** (optional): Sets the last version which this page is available. + +## Versioning blocks of content + +The **VersionBlock** component provides the ability to version a specific piece of content on a docs page. + +This component can be added directly to a markdown file in a similar way as other components (FAQ, File, Lightbox). + +### Versioning properties + +- **firstVersion** (optional): Sets the first version this piece of content is available for. + - Defaults to **0** if not set. +- **lastVersion** (optional): Sets the last version this piece of content is available for. + - If **lastVersion** prop not set, it will be available from the **firstVersion,** up to the latest version. + +Both properties can be used together to set a range where the content should show. In the example below, this content will only show if the selected version is between **0.21** and **1.0**: + +```markdown + + + Versioned content here + + +``` + +### Example for versioning entire pages + +On the [Docs Defer page](https://docs.getdbt.com/reference/node-selection/defer), tabs are used to show different versions of a piece of code. **v0.21.0 and later** shows `--select`, while **v-.20.x and earlier** changes this to `--models`. + +![oldway](https://user-images.githubusercontent.com/3880403/163254165-dea23266-2eea-4e65-b3f0-c7b6d3e51fc3.png) + +Below is how we can implement the same versioning using the new **VersionBlock** component: + +You see this block when the selected version is >= 0.21: + +```markdown + + + +```shell +$ dbt run --select [...] --defer --state path/to/artifacts +$ dbt test --select [...] --defer --state path/to/artifacts +\``` + + +``` + +You see this version block when the selected version is <= 0.20 + +```markdown + + +```shell +$ dbt run --models [...] --defer --state path/to/artifacts +$ dbt test --models [...] --defer --state path/to/artifacts +\``` + + +``` + +## Using global variables + +--- + +Global variables can be configured for use throughout the docs. + +Using a global variable requires two steps: + +1. Set the variable in the `website/dbt-global-variables.js` file. +2. Use the **Var** component to add the global variable to a page. + +```jsx +// The dbtCore property is the identifer for the variable, +// while the name property is the value shown on the page. + +exports.dbtVariables = { + dbtCore: { + name: "dbt Core" + } +} +``` + +```markdown +// is converted to dbt Core + +You can install on the command line by using one of these recommended methods: +``` + +### Versioning global variables + +It is possible to version global variables as well. This creates the ability to show different variations of a string based off the current version a visitor has selected. + +To extend our `dbt-global-variables.js` file above, we can add a new variable: *note - these versions are not accurate and only shown for this example.* + +```jsx +// A new variable called dbtCloud is added below +// This variable includes a versions array +// "Sinter" will replace "dbt Cloud" for versions 0.21 or lower + +exports.dbtVariables = { + dbtCore: { + name: "dbt Core" + }, + dbtCloud: { + name: "dbt Cloud", + versions: [ + { + "name": "Sinter", + "version": "0.21" + } + ] + } +} +``` + +```markdown +You can get started with by [Signing up](https://www.getdbt.com/signup/). +``` + +In the above example, the **dbtCloud** property has a default name of “dbt Cloud”. The naming for variables cascade down, meaning “dbt Cloud” will show for all versions, until version **0.21** or lower is selected. At that point “Sinter” will replace “dbt Cloud”. + +### Global variables properties + +**name** (required): Expects the identifier for a global variable. + +### Global variables example + +The global `` component can be used inline, for example: + +```markdown +This piece of markdown content explains why is awesome. +``` + +However, a Var component cannot start a new line of content. Fortunately, a workaround exists to use the Var component at the beginning of a line of content. + +To use the component at the beginning of a sentence, add a non-breaking space character before the component: + +```markdown +// When starting a new line with a global variable, +// a non-breaking space is required + +// Works +  is awesome! + +// Does not work + is awesome! +``` + +## Reusing snippets of content + +The Snippet component allows for content to be reusable throughout the Docs. This is very similar to the existing FAQ component. + +Creating and using a snippet requires two steps: + +1. Create a new markdown snippet file in the `website/snippets` directory. +2. Use the `` component within a Docs file. + +### Snippet properties + +**src:** Expects the file name of the snippet which lives in the snippets directory + +### Snippet example + +To create a new snippet to use throughout the site, first we will create a new markdown snippet within the snippets directory: + +```markdown +## Header 2 + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam fermentum porttitor dui, id scelerisque enim scelerisque at. +``` + +Now, we can add this snippet to a Docs file with the Snippet component: + +```markdown +Docs content here. + + + +Docs content here. +``` diff --git a/netlify.toml b/netlify.toml index 298ac05fdd5..6ab92757410 100644 --- a/netlify.toml +++ b/netlify.toml @@ -1,8 +1,2 @@ -# for deployments of prerelease docs -[context.next] - command = "make build-prerelease" - -[context.next.environment] - PRERELEASE = "true" - ALGOLIA_API_KEY = "044414e92a8b8137a33fd276d4533895" - ALGOLIA_INDEX_NAME = "dbt_next" +[build] + functions = "functions" diff --git a/website/.gitignore b/website/.gitignore index b60fa977326..e0c5b212ea1 100644 --- a/website/.gitignore +++ b/website/.gitignore @@ -8,8 +8,13 @@ .docusaurus .cache-loader +# cypress artifacts +/cypress/videos +/cypress/screenshots + # misc .DS_Store +.env .env.local .env.development.local .env.test.local diff --git a/website/.swcrc b/website/.swcrc new file mode 100644 index 00000000000..046ec0b01c1 --- /dev/null +++ b/website/.swcrc @@ -0,0 +1,23 @@ +{ + "jsc": { + "parser": { + "syntax": "ecmascript", + "jsx": true, + "dynamicImport": false, + "privateMethod": false, + "functionBind": false, + "exportDefaultFrom": false, + "exportNamespaceFrom": false, + "decorators": false, + "decoratorsBeforeExport": false, + "topLevelAwait": false, + "importMeta": false + }, + "transform": null, + "target": "es5", + "loose": false, + "externalHelpers": false, + // Requires v1.2.50 or upper and requires target to be es2016 or upper. + "keepClassNames": false + } +} diff --git a/website/Makefile b/website/Makefile index f75e64951db..9ba2bd80303 100644 --- a/website/Makefile +++ b/website/Makefile @@ -20,7 +20,3 @@ build: cat ../_redirects | grep 'docs/' | awk '{ print "/v0.10" $$1 "\t" $$2 "\t" $$3 }' >> build/_redirects cat ../_headers > build/_headers - -build-prerelease: - make build - cat ../_headers > build/_headers diff --git a/website/blog/2016-03-11-blog-post.md b/website/blog/2016-03-11-blog-post.md deleted file mode 100755 index cf2ba296067..00000000000 --- a/website/blog/2016-03-11-blog-post.md +++ /dev/null @@ -1,18 +0,0 @@ ---- -title: Blog Title -author: Blog Author -authorURL: http://twitter.com/ -authorFBID: 100002976521003 ---- - -Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus elementum massa eget nulla aliquet sagittis. Proin odio tortor, vulputate ut odio in, ultrices ultricies augue. Cras ornare ultrices lorem malesuada iaculis. Etiam sit amet libero tempor, pulvinar mauris sed, sollicitudin sapien. - - - -Mauris vestibulum ullamcorper nibh, ut semper purus pulvinar ut. Donec volutpat orci sit amet mauris malesuada, non pulvinar augue aliquam. Vestibulum ultricies at urna ut suscipit. Morbi iaculis, erat at imperdiet semper, ipsum nulla sodales erat, eget tincidunt justo dui quis justo. Pellentesque dictum bibendum diam at aliquet. Sed pulvinar, dolor quis finibus ornare, eros odio facilisis erat, eu rhoncus nunc dui sed ex. Nunc gravida dui massa, sed ornare arcu tincidunt sit amet. Maecenas efficitur sapien neque, a laoreet libero feugiat ut. - -Nulla facilisi. Maecenas sodales nec purus eget posuere. Sed sapien quam, pretium a risus in, porttitor dapibus erat. Sed sit amet fringilla ipsum, eget iaculis augue. Integer sollicitudin tortor quis ultricies aliquam. Suspendisse fringilla nunc in tellus cursus, at placerat tellus scelerisque. Sed tempus elit a sollicitudin rhoncus. Nulla facilisi. Morbi nec dolor dolor. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Cras et aliquet lectus. Pellentesque sit amet eros nisi. Quisque ac sapien in sapien congue accumsan. Nullam in posuere ante. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Proin lacinia leo a nibh fringilla pharetra. - -Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Proin venenatis lectus dui, vel ultrices ante bibendum hendrerit. Aenean egestas feugiat dui id hendrerit. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Curabitur in tellus laoreet, eleifend nunc id, viverra leo. Proin vulputate non dolor vel vulputate. Curabitur pretium lobortis felis, sit amet finibus lorem suscipit ut. Sed non mollis risus. Duis sagittis, mi in euismod tincidunt, nunc mauris vestibulum urna, at euismod est elit quis erat. Phasellus accumsan vitae neque eu placerat. In elementum arcu nec tellus imperdiet, eget maximus nulla sodales. Curabitur eu sapien eget nisl sodales fermentum. - -Phasellus pulvinar ex id commodo imperdiet. Praesent odio nibh, sollicitudin sit amet faucibus id, placerat at metus. Donec vitae eros vitae tortor hendrerit finibus. Interdum et malesuada fames ac ante ipsum primis in faucibus. Quisque vitae purus dolor. Duis suscipit ac nulla et finibus. Phasellus ac sem sed dui dictum gravida. Phasellus eleifend vestibulum facilisis. Integer pharetra nec enim vitae mattis. Duis auctor, lectus quis condimentum bibendum, nunc dolor aliquam massa, id bibendum orci velit quis magna. Ut volutpat nulla nunc, sed interdum magna condimentum non. Sed urna metus, scelerisque vitae consectetur a, feugiat quis magna. Donec dignissim ornare nisl, eget tempor risus malesuada quis. diff --git a/website/blog/2017-04-10-blog-post-two.md b/website/blog/2017-04-10-blog-post-two.md deleted file mode 100755 index 3ab4637bd5b..00000000000 --- a/website/blog/2017-04-10-blog-post-two.md +++ /dev/null @@ -1,18 +0,0 @@ ---- -title: New Blog Post -author: Blog Author -authorURL: http://twitter.com/ -authorFBID: 100002976521003 ---- - -Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus elementum massa eget nulla aliquet sagittis. Proin odio tortor, vulputate ut odio in, ultrices ultricies augue. Cras ornare ultrices lorem malesuada iaculis. Etiam sit amet libero tempor, pulvinar mauris sed, sollicitudin sapien. - - - -Mauris vestibulum ullamcorper nibh, ut semper purus pulvinar ut. Donec volutpat orci sit amet mauris malesuada, non pulvinar augue aliquam. Vestibulum ultricies at urna ut suscipit. Morbi iaculis, erat at imperdiet semper, ipsum nulla sodales erat, eget tincidunt justo dui quis justo. Pellentesque dictum bibendum diam at aliquet. Sed pulvinar, dolor quis finibus ornare, eros odio facilisis erat, eu rhoncus nunc dui sed ex. Nunc gravida dui massa, sed ornare arcu tincidunt sit amet. Maecenas efficitur sapien neque, a laoreet libero feugiat ut. - -Nulla facilisi. Maecenas sodales nec purus eget posuere. Sed sapien quam, pretium a risus in, porttitor dapibus erat. Sed sit amet fringilla ipsum, eget iaculis augue. Integer sollicitudin tortor quis ultricies aliquam. Suspendisse fringilla nunc in tellus cursus, at placerat tellus scelerisque. Sed tempus elit a sollicitudin rhoncus. Nulla facilisi. Morbi nec dolor dolor. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Cras et aliquet lectus. Pellentesque sit amet eros nisi. Quisque ac sapien in sapien congue accumsan. Nullam in posuere ante. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Proin lacinia leo a nibh fringilla pharetra. - -Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Proin venenatis lectus dui, vel ultrices ante bibendum hendrerit. Aenean egestas feugiat dui id hendrerit. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Curabitur in tellus laoreet, eleifend nunc id, viverra leo. Proin vulputate non dolor vel vulputate. Curabitur pretium lobortis felis, sit amet finibus lorem suscipit ut. Sed non mollis risus. Duis sagittis, mi in euismod tincidunt, nunc mauris vestibulum urna, at euismod est elit quis erat. Phasellus accumsan vitae neque eu placerat. In elementum arcu nec tellus imperdiet, eget maximus nulla sodales. Curabitur eu sapien eget nisl sodales fermentum. - -Phasellus pulvinar ex id commodo imperdiet. Praesent odio nibh, sollicitudin sit amet faucibus id, placerat at metus. Donec vitae eros vitae tortor hendrerit finibus. Interdum et malesuada fames ac ante ipsum primis in faucibus. Quisque vitae purus dolor. Duis suscipit ac nulla et finibus. Phasellus ac sem sed dui dictum gravida. Phasellus eleifend vestibulum facilisis. Integer pharetra nec enim vitae mattis. Duis auctor, lectus quis condimentum bibendum, nunc dolor aliquam massa, id bibendum orci velit quis magna. Ut volutpat nulla nunc, sed interdum magna condimentum non. Sed urna metus, scelerisque vitae consectetur a, feugiat quis magna. Donec dignissim ornare nisl, eget tempor risus malesuada quis. diff --git a/website/blog/2017-09-25-testing-rss.md b/website/blog/2017-09-25-testing-rss.md deleted file mode 100755 index b7ff8129ceb..00000000000 --- a/website/blog/2017-09-25-testing-rss.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -title: Adding RSS Support - RSS Truncation Test -author: Eric Nakagawa -authorURL: http://twitter.com/ericnakagawa -authorFBID: 661277173 ---- -1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890 - -This should be truncated. - -This line should never render in XML. diff --git a/website/blog/2017-09-26-adding-rss.md b/website/blog/2017-09-26-adding-rss.md deleted file mode 100755 index eeb4f0477e5..00000000000 --- a/website/blog/2017-09-26-adding-rss.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -title: Adding RSS Support -author: Eric Nakagawa -authorURL: http://twitter.com/ericnakagawa -authorFBID: 661277173 ---- - -This is a test post. - -A whole bunch of other information. diff --git a/website/blog/2017-10-24-new-version-1.0.0.md b/website/blog/2017-10-24-new-version-1.0.0.md deleted file mode 100755 index 60761c02dc6..00000000000 --- a/website/blog/2017-10-24-new-version-1.0.0.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -title: New Version 1.0.0 -author: Eric Nakagawa -authorURL: http://twitter.com/ericnakagawa -authorFBID: 661277173 ---- - -This blog post will test file name parsing issues when periods are present. diff --git a/website/blog/2019-05-01-how-we-structure-dbt-projects.md b/website/blog/2019-05-01-how-we-structure-dbt-projects.md new file mode 100644 index 00000000000..361373ae9d5 --- /dev/null +++ b/website/blog/2019-05-01-how-we-structure-dbt-projects.md @@ -0,0 +1,265 @@ +--- +title: "How We Structure our dbt Projects" +description: "As the maintainers of dbt, and analytics consultants, at Fishtown Analytics we build a lot of dbt projects. Over time, we’ve developed internal conventions on how we structure them." +slug: how-we-structure-our-dbt-projects +canonical_url: https://discourse.getdbt.com/t/how-we-structure-our-dbt-projects/355 + +authors: [claire_carroll] + +tags: [dbt tutorials] +hide_table_of_contents: false + +date: 2019-05-01 +is_featured: true +--- + + +As the maintainers of dbt, and analytics consultants, at [Fishtown Analytics](https://www.getdbt.com/dbt-labs/about-us/) (now dbt Labs) we build a lot of dbt projects. Over time, we’ve developed internal conventions on how we structure them. + +This article does not seek to instruct you on how to design a final model for your stakeholders — it won’t cover whether you should denormalize everything into one wide master , or have many tables that need to be joined together in the BI layer. There are entire books on this topic. Instead, use this as a guide once you’ve already got an idea of what you’re building for how you should break the transformations up into separate dbt models. + + + +It’s important to note that **this is not the only, or the objectively best, way to structure a dbt project**. Rather, this document reflects our current opinions. These opinions are strongly influenced by: + +* our views on data model design; which in turn are influenced by: +* the kinds of analytics problems we are solving for clients +* the data stack we typically work within, in which multiple data sources are loaded by third party tools, and the is optimized for analytical queries (therefore we aren’t tightly bounded by performance optimization considerations). + +Our opinions are **almost guaranteed to change over time** as we update our views on modeling, are exposed to more analytics problems, and data stacks evolve. It’s also worth clearly stating here: the way we structure dbt projects makes sense for our projects, but may not be the best fit for yours! This article exists on Discourse so that we can have a conversation – I would love to know how others in the community are structuring their projects. + +In comparison, the (recently updated) [best practices](/guides/best-practices) reflect principles that we believe to be true for any dbt project. Of course, these two documents go hand in hand – our projects are structured in such a way that makes the those principles easy to observe, in particular: + +* Limit references to raw data +* Rename and recast fields once +* Group your models in directories +* Add tests to your models +* Consider the information architecture of your data warehouse +* Separate source-centric and business-centric transformations + +If you want to see what the code for one of our projects looks like, check out [this demonstration dbt project](https://github.com/dbt-labs/dbt-learn-demo/tree/day2-dbt-training/models). + +We also recently held (and recorded) an office hours on this topic – this article provides a high level outline, but there’s a lot more detail and discussion in the [video](https://youtu.be/xzKLh342s08). + +Lastly, before I dive in, a huge thank you to Jeremy Cohen for not only teaching me a lot of the material in this article, but also for doing a lot of the groundwork that went into this article – entire sections of this article are in fact lifted from his work. + +## Data transformation 101 +----------------------------------------------------- + +The data in any of our projects has three distinct checkpoints: + +1. **Sources**: Schemas and tables in a source-conformed structure (i.e. tables and columns in a structure based on what an API returns), loaded by a third party tool. +2. **Staging models**: The atomic unit of data modeling. Each model bears a one-to-one relationship with the source data table it represents. It has the same granularity, but the columns have been renamed, recast, or usefully reconsidered into a consistent format. +3. **Marts models**: Models that represent business processes and entities, abstracted from the data sources that they are based on. + +In a simple project, these may be the only models you build; more complex projects may have a number of intermediate models that help along this journey, as well as accessories to these models (see below). + +Still confused? An example might help! Let’s think about a software business that uses both Stripe and Braintree to collect subscription payments. Their three stages of modeling might look like: + +1. **Sources**: Payment records from the Stripe API and payment records from the Braintree API, loaded into their data warehouse by a third party tool. +2. **Staging models**: Both the Stripe and Braintree payments are recast into a consistent shape, with consistent column names. +3. **Marts models**: A monthly recurring revenue (MRR) model that classifies revenue per customer per month as new revenue, upgrades, downgrades, and churn, to understand how a business is performing over time. It may be useful to note whether the revenue was collected via Stripe or Braintree, but they are not fundamentally separate models. + +Of note here is that there is a distinct change that occurs between the staging and marts checkpoints – sources and staging models are source-centric, whereas marts models are business-centric. + +In our dbt projects, this leads us to our first split in our `models/` directory which helps us make this distinction: + +``` + ├── dbt_project.yml + └── models + ├── marts + └── staging + +``` + +## Staging raw data +--------------------------------------- + +The goal of the staging layer is to create staging models. Staging models take raw data, and clean and prepare them for further analysis. For a user querying the data warehouse, a relation with a `stg_` prefix indicates that: + +* Fields have been renamed and recast in a consistent way.¹ +* Datatypes, such as timezones, are consistent. +* Light cleansing, such as replacing empty string with NULL values, has occurred. +* If useful, flattening of objects might have occurred. +* There is a that is both unique and not null (and tested). + +Staging models can have joins in them to field additional columns for context or enrichment; add rows through unions and remove them through filters; deduplicate a natural key or hash together a [surrogate one](/blog/sql-surrogate-keys). + +Because we often work with multiple data sources, in our `staging` directory, we create one directory per source. + + +``` + ├── dbt_project.yml + └── models + ├── marts + └── staging + ├── braintree + └── stripe +``` + +Each staging directory contains at a minimum: + + +* One staging model for each object that is useful for analytics: + * Named `stg___`. + * Generally materialized as a (unless performance requires it as a table). +* A `src_.yml` file which contains: + * [Source](/docs/building-a-dbt-project/using-sources) definitions, tests, and documentation +* A `stg_.yml` file which contains + * [Tests](/docs/building-a-dbt-project/tests) and [documentation](/docs/building-a-dbt-project/documentation) for models in the same directory + +``` + ├── dbt_project.yml + └── models + ├── marts + └── staging + └── braintree + ├── src_braintree.yml + ├── stg_braintree.yml + ├── stg_braintree__customers.sql + └── stg_braintree__payments.sql +``` + + +Some dbt users prefer to have one `.yml` file per model (e.g. `stg_braintree__customers.yml`). This is a completely reasonable choice, and we recommend implementing it if your `.yml` files start to become unwieldy. + +### But what about base models? + +Earlier versions of the dbt documentation recommended implementing “base models” as the first layer of transformation – and we used to organize and name our models in this way, for example `models/braintree/base/base_payments.sql`. + +We realized that while the reasons behind this convention were valid, the naming was an opinion, so in our recent update to the [best practices](/guides/best-practices), we took the mention of base models out. Instead, we replaced it with the principles of “renaming and recasting once” and “limiting the dependencies on raw data”. + +That being said, in our dbt projects every source flows through exactly one model of the following form: + +``` + with source as ( + + select * from {{ source('braintree', 'payments') }} + + ), + + renamed as ( + + select + id as payment_id, + order_id, + convert_timezone('America/New_York', 'UTC', createdat) as created_at, + ... + + from source + + ) + + select * from renamed +``` + +We still refer to this a base transformation. If your source data is in good shape, this transformation may be all that’s required to build a staging model, and our staging model is this SQL. + +However, building a staging model may warrant several models’ worth of cleaning, correcting, and categorizing, or may require a join or union to another source. To ensure our data source flows through a base transformation, we extend our DAG upstream of the staging model, by creating a separate base model, that we then select from. + +![27_AM](/img/blog/dbt-project-structure-318751d1b7d09a0abc1627a7f6d219d3a8c0455b_2_690x173.jpeg) + +In our dbt projects, we place these base models in a nested `base` subdirectory. + +``` + ├── dbt_project.yml + └── models + ├── marts + └── staging + └── braintree + ├── base + | ├── base.yml + | ├── base_braintree__failed_payments.sql + | └── base_braintree__successful_payments.sql + ├── src_braintree.yml + ├── stg_braintree.yml + ├── stg_braintree__customers.sql + └── stg_braintree__payments.sql +``` + +In our projects, base models: + +* Often use the ephemeral materialization, so they are not exposed to end users querying our warehouse. +* Are tested in a `base.yml` file within the same directory as the base models. + +If we need additional transformations between base and staging models, we create a nested `staging//intermediate` directory and place these transformations in there. + +## Describing a business through `marts` +------------------------------------------------------------------------------- + +Marts are stores of models that describe business entities and processes. They are often grouped by business unit: marketing, finance, product. Models that are shared across an entire business are grouped in a core directory. + +``` + ├── dbt_project.yml + └── models + ├── marts + | ├── core + | ├── finance + | ├── marketing + | └── product + └── staging +``` + +There are entire books written on how to design models, which is beyond the scope of this article. In our view of the world, our goal is to build fact and dimension models, that are abstracted from the source data that they rely upon: + +* `fct_`**:** A tall, narrow table representing real-world processes that have occurred or are occurring. The heart of these models is usually an immutable event stream: sessions, transactions, orders, stories, votes. +* `dim_`: A wide, short table where each row is a person, place, or thing; the ultimate source of truth when identifying and describing entities of the organization. They are mutable, though slowly changing: customers, products, candidates, buildings, employees. + +Where the work of staging models is limited to cleaning and preparing, fact tables are the product of substantive data transformation: choosing (and reducing) dimensions, date-spining, executing business logic, and making informed, confident decisions. + +This layer of modeling is considerably more complex than creating staging models, and the models we _design_ are highly tailored to the analytical needs of an organization. As such, we have far less convention when it comes to these models. Some patterns we’ve found to be useful are: + +* `fct_` and `dim_` models should be materialized as tables within a warehouse to improve query performance. As a default, we use the table materialization, and where performance requires it, we use the incremental materialization. +* Intermediate transformations required to get to a fact or dimension model are placed in a nested `marts//intermediate` directory. They are named `__.sql`. The lack of prefix and use of double underscores indicates that these are intermediate models, not to be trusted, however, it may also be worth hiding these in a different [schema](/docs/building-a-dbt-project/building-models/using-custom-schemas). +* Models are tested and documented in a `.yml` file in the same directory as the models. +* Any extra documentation in a [docs block](/docs/building-a-dbt-project/documentation#using-docs-blocks) is placed in a `.md` file in the same directory. + +A marts directory may therefore end up looking like: + +``` + ├── dbt_project.yml + └── models + ├── marts + │ ├── core + │ │ ├── core.md + │ │ ├── core.yml + │ │ ├── dim_customers.sql + │ │ ├── fct_orders.sql + │ │ └── intermediate + │ │ ├── customer_orders__grouped.sql + │ │ ├── customer_payments__grouped.sql + │ │ ├── intermediate.yml + │ │ └── order_payments__joined.sql + │ ├── finance + │ ├── marketing + │ └── product + └── staging +``` + +This entire project results in the following DAG: + +![12_AM](/img/blog/dbt-project-structure-a5567e3711a30c72bbf9c117548452fac476d8c6_2_690x160.jpeg) + +## Accessories to data +------------------------------------------------- + +There are other kinds of SQL files that find their way into robust dbt projects. In addition to `staging` and `marts`, we find ourselves with model directories such as: + +* `utils`: An `all_days` table. This is useful everywhere, though it never forms the basis for analysis/reporting. +* `lookups`**:** A user-mapping table, a zipcode-country table, etc. These are as likely to be [CSV seeds](/docs/building-a-dbt-project/seeds) as tables in a production database. You may reference it at several unpredictable points throughout modeling, and maybe even in a BI tool. +* `admin`**:** Audit logs, warehouse operations, Redshift maintenance, and incremental records of the miscellaneous you run to make your project run smoothly. +* `metrics`**:** Precisely defined measurements taken from fact tables, directly conducive to time-series reporting, and tightly structured so as to allow one-to-one comparison with goals and forecasting. A metrics table lives downstream of dimension and fact tables in your DAG, and it deserves special status. +* **Packages:** While not a model folder within your main project, packages that include models (like our [snowplow](https://github.com/dbt-labs/snowplow) package) can be configured into custom schema and materialization patterns from `dbt_project.yml`. + +In projects where we find ourselves with these additional models, we often leverage [custom schemas](/docs/building-a-dbt-project/building-models/using-custom-schemas) as directories in our warehouse, to logically group the models, choosing a schema name that matches the directory name in our dbt project. + +## Final thoughts +----------------------------------- + +In this article, building the DAG for a dbt project has been described left to right, starting at sources, and ending with marts models. + +However, it’s worth noting that in reality we often first think through a modeling problem from right to left — we start with an idea of the dashboard or report we want to build, then whiteboard the structure of the marts model we need in our warehouse to power this dashboard. On the same whiteboard, we’ll often then work backwards until we reach our source, before we start writing any actual SQL. I’ve found that it’s only once I’ve solved a modeling problem a few times that I get an intuition for how to build a DAG from left to right. In other words: we tend to think about our destination before we start our modeling journey. + +* * * + +¹We’ve standardized our naming and type conventions in our [dbt coding conventions](https://github.com/dbt-labs/corp/blob/master/dbt_coding_conventions.md). diff --git a/website/blog/2020-07-01-how-to-create-near-real-time-models-with-just-dbt-sql.md b/website/blog/2020-07-01-how-to-create-near-real-time-models-with-just-dbt-sql.md new file mode 100644 index 00000000000..944d6fdd3f9 --- /dev/null +++ b/website/blog/2020-07-01-how-to-create-near-real-time-models-with-just-dbt-sql.md @@ -0,0 +1,185 @@ +--- +title: "How to Create Near Real-time Models With Just dbt + SQL" +description: "Before I dive into how to create this, I have to say this. **You probably don’t need this**." +slug: how-to-create-near-real-time-models-with-just-dbt-sql +canonical_url: https://discourse.getdbt.com/t/how-to-create-near-real-time-models-with-just-dbt-sql/1457 + +authors: [amy_chen] + +tags: [dbt tutorials] +hide_table_of_contents: false + +date: 2020-07-01 +is_featured: false +--- + +Before I dive into how to create this, I have to say this. **You probably don’t need this**. I, along with my other Fishtown colleagues, have spent countless hours working with clients that ask for near-real-time streaming data. However, when we start digging into the project, it is often realized that the use case is not there. There are a variety of reasons why near real-time streaming is not a good fit. Two key ones are: + +1. The source data isn’t updating frequently enough. +2. End users aren’t looking at the data often enough. + +So when presented with a near-real-time modeling request, I (and you as well!) have to be cynical. + + + +## The right use case +------------------------------------------- + +Recently I was working on a JetBlue project and was presented with a legitimate use case: operational data. JetBlue’s Crewmembers need to make real-time decisions on when to close the door to a flight or rebook a flight. If you have ever been to an airport when there is a flight delay, you know how high the tension is in the room for airline employees to make the right decisions. They literally cannot do their jobs without real-time data. + +If possible, the best thing to do is to query data as close to the source as possible. You don’t want to hit your production database unless you want to frighten and likely anger your DBA. Instead, the preferred approach is to replicate the source data to your analytics warehouse, which would provide a suitable environment for analytic queries. In JetBlue’s case, the data arrives in blobs, which then need to be unnested, transformed, and joined before the data becomes useful for analysis. There was no way to just query from the source to get the information people required. + +Tldr: If you need transformed, operational data to make in-the-moment decisions then you probably need real-time data. + +## What are our options? +------------------------------------------------ + +#### 1\. Materialize everything as views + +Since views are simply stored queries that do not store data, they are always up to date. This approach works until your transformations take more than 2+ minutes, which wouldn’t meet a “near real-time” SLA. When your data is small enough, this is the preferred approach, however it isn’t scalable. + +#### 2\. Run dbt in micro-batches + +Just don’t do it. Because dbt is primarily designed for batch-based data processing, you should not schedule your dbt jobs to run continuously. This can open the door to unforeseeable bugs. + +#### 3\. Use Materialized Views + +While the concept is very exciting, implementation still has some key limitations. They are expensive and cannot include some useful transformations. Check out this [section in Snowflake’s documentation about their current limitations](https://docs.snowflake.com/en/user-guide/views-materialized.html#limitations-on-creating-materialized-views). Additionally, we have a [office hours](https://www.youtube.com/watch?v=awj-5aYXZnc) on this topic that I recommend checking out. Overall, we are excited to see how this develops. + +#### 4\. Use a dedicated streaming stack + +Tools like [Materialize](https://materialize.io/) and [Spark](https://databricks.com/glossary/what-is-spark-streaming) are great solutions to this problem. At the time of writing this post, these dbt adapters were not available and would have required a commitment to a new platform in this situation so they were not considered. + +#### 5\. Use dbt in a clever way + +By being thoughtful about how we define models, we can use dbt and the existing materializations to solve this problem. Lambda views are a simple and readily available solution that is tool agnostic and SQL based. This is what I implemented at JetBlue. + +## What are lambda views? +-------------------------------------------------- + +The idea of lambda views comes from lambda architecture. This [Wikipedia page](https://en.wikipedia.org/wiki/Lambda_architecture) can explain much more in-depth but the core concept of this architecture is to take advantage of both batch and stream processing methods. This enables handling a lot of data in a very performant manner. + +Taking that approach, a lambda view is essentially the union of a historical table and a current view. The model where the union takes place is the lambda view. Here is a diagram that might be helpful: + +![lambda views](/img/blog/real-time-9eb7699399fe576a2a20b13bcf523a1e8b96cf09_2_624x244.png) + +The lamba view can be queried for always up-to-date data, no matter how often you have run your dbt models. Since the majority of the records in the lambda view come directly from a table, it should be relatively fast to query. And since the most recent rows come from the view, transformations are run on a small subset of data which shouldn’t take long in the lambda view. This provides a performant and always up-to-date model. + +The SQL in the lambda view is simple (just a `union all`), but there’s a bit of work to get to the unioned model. To better understand this, it is important to think about the flow of transformations as demonstrated below. + +![lambda view flow](/img/blog/real-time-5ab4b384ec36ed52d422e3ffcf238a4446dc3ba5_2_624x345.jpeg) + +What is essentially happening is a series of parallel transformations from the raw data. Looking at the blue and red boxes that represent the creation of both the current view and historical table, you can see that they are the same transformations. The only key difference is that one flow is always using views as the materialization versus the other is materialized as tables. Often, those tables are incrementally built to improve performance. + +The most basic version of the SQL looks like this: + +``` + with current_view as ( + + select * from {{ ref('current_view') }} + + where max_collector_tstamp >= ‘{{ run_started_at }}’ + + ), + + historical_table as ( + + select * from {{ ref('historical_table') }} + + where max_collector_tstamp < '{{ run_started_at }}' + + ), + + unioned_tables as ( + + select * from current_view + + union all + + select * from historical_table + + ) + + select * from unioned_tables +``` + + +As you start to implement lambda views with more sources, creating a macro for the lambda view union is a great way to make things drier. + +## Key Concepts of a lambda view +------------------------------------------------------------------ + +#### Filters are key to making this performant + +You need to filter often and intentionally on your current view flow. This is because there is usually a lot of data being transformed and you want to transform only what is necessary. There are two main places that filters should be considered. + +* **At the beginning of the current view flow**: This is usually happening at Transformation 1. This filter takes into account how often the historical table is run. If it’s being run every hour, then I filter for only the last 2 hours of “current rows”. The overlap is assurance that if there are any issues with the job run, we don’t miss out on rows. +* **At the unioned model**: If you have late-arriving facts, you will want to include a filter to assure that there are no fanouts. + +As you start to create more lambda views, you will want to make the filter into a macro for drier code. Here is a sample macro for you to use: + +``` + {% macro lambda_filter(column_name) %} + + {% set materialized = config.require('materialized') %} + + {% set filter_time = var(lambda_timestamp, run_started_at) %} + + {% if materialized == 'view' %} + + where {{ column_name }} >= '{{ filter_time }}' + + {% elif is_incremental() %} + + where {{ column_name }} >= (select max({{ column_name }}) from {{ this }}) + + and {{ column_name }} < '{{ filter_time }}' + + {% else %} + + where {{ column_name }} < '{{ filter_time }}' + + {% endif %} + + {% endmacro %} +``` + + +\*\* Note for the macro above, the timestamp is `var(lambda_timestamp, run_started_at)`. We want to default to the last time the historical models were run but allow for flexibility depending on the situation. It would be useful to note that we used [run\_started\_at timestamp](/reference/dbt-jinja-functions/run_started_at/) rather than `current_timestamp()` to avoid any situations where there is a job failure and the historical table hasn’t been updated for the last 5 hours. + +### Write idempotent models + +As with every dbt model, be sure to keep this principle in mind as you start to create the models leading up to the union as well as the union itself. + +### Build the historical model intentionally + +My dbt cloud jobs are set to run every hour, building all of the models in the historical table flow. All of the models leading up to the historical table are configured as an incremental model to improve performance. + +## Tradeoffs & Limitations +---------------------------------------------------- + +#### 1\. Duplicated logic + +We are essentially creating duplicate models with the same logic, just different materializations. There are currently two approaches: 1) You can write the SQL in a macro and then have only one place to update this logic. This is great but creates complex folder organization and lowers model readability. 2) You can duplicate the SQL in both models but then there’s two places to update the logic in. This makes maintenance more error-prone. + +#### 2\. Complex DAGs & Multi-step transformations + +With every final model needing duplicate models, this makes DAGs significantly more complex. Add to that the need for more complex transformations, this approach may not scale up well due to the complexity. + +#### 3\. Enforcing materializations + +This approach is extremely dependent on the type of materializations. Requiring that models in the current view flow and their dependencies are all views can be challenging. Your project is more brittle because small changes can easily impact your data quality and how up-to-date it is. + +## Future implementations +---------------------------------------------------- + +All I can truly say is there’s more to come. Internally Jeremy and Claire have been working on if and how we should create a custom materialization to make this approach a lot cleaner. If interested, keep an eye out on our [experimental features repo](https://github.com/dbt-labs/dbt-labs-experimental-features) and contribute if you have thoughts! + +## Thank You +-------------------------- + +This post would not have materialized (lol) without the Fishtown Team working together. + +Drew and I had a brainstorming session to discuss lambda architecture and the initial concept of lambda views. Sanajana and Jeremy were my rubber duckies as I started writing the SQL and conceptizing how things would work in code. Janessa and Claire also spent a lot of time helping me write this discourse post as I tried to form it between meetings. [This is basically us at Fishtown.](https://gph.is/2R7vpjR) + +I also want to give a special thanks to Ben from JetBlue who has been essential to this process from implementation to editing this post. My apologies for spelling JetBlue as Jetblue far too many times! diff --git a/website/blog/2021-02-05-dbt-project-checklist.md b/website/blog/2021-02-05-dbt-project-checklist.md new file mode 100644 index 00000000000..19ff0cd3eda --- /dev/null +++ b/website/blog/2021-02-05-dbt-project-checklist.md @@ -0,0 +1,260 @@ +--- +title: "Your Essential dbt Project Checklist" +description: "A checklist created to guide our internal work, which you can use to clean up your own dbt project." +slug: essential-dbt-project-checklist +canonical_url: https://discourse.getdbt.com/t/your-essential-dbt-project-checklist/1377 + +authors: [amy_chen, dave_connors] + +tags: [dbt tutorials] +hide_table_of_contents: false + +date: 2020-06-20 +is_featured: true +--- + +If you’ve been using dbt for over a year, your project is out-of-date. This is natural. + +New functionalities have been released. Warehouses change. Best practices are updated. Over the last year, I and others on the Fishtown Analytics (now dbt Labs!) team have conducted seven audits for clients who have been using dbt for a minimum of 2 months. + + + +In every single audit, we found opportunities to: + +1. Improve performance +2. Improve maintainability +3. Make it easier for new people to get up-to-speed on the project + +This post is the checklist I created to guide our internal work, and I’m sharing it here so you can use it to clean up your own dbt project. Think of this checklist like a `Where's Waldo?` book: you’ll still have to go out and find him, but with this in hand, you’ll at least know what you’re looking for. + +## ✅ dbt\_project.yml +-------------------------------------------------------------------------------------------------------------------------------------------------- + +* Project naming conventions + * What is the name of your project? + * Did you keep it as ‘my\_new\_project’ per the init project or renamed it to make sense? + * Our recommendation is to name it after your company such as ‘fishtown\_analytics’. + * If you have multiple dbt projects, something like ‘fishtown\_analytics\_marketing’ might make more sense. +* Do you have unnecessary configurations like materialized: ? + * By default, dbt models are materialized as “views”. This removes the need to declare any models as views. + * If all of your models in a folder are tables, define the on the dbt\_project.yml file rather than on the model file. This removes clutter from the model file. +* Do you have a ton of placeholder comments from the init command? + * This creates unnecessary clutter. +* Do you use post-hooks to grant permissions to other transformers and BI users? + * If no, you should! This will ensure that any changes made will be accessible to your collaborators and be utilized on the BI layer. + ![on run end](/img/blog/checklist-on-run-end.png) +* Are you utilizing tags in your project? + * The majority of your project’s models should be untagged. Use tags for models and tests that fall out of the norm with how you want to interact with them. For example, tagging ‘nightly’ models makes sense, but _also_ tagging all your non-nightly models as ‘hourly’ is unnecessary - you can simply exclude the nightly models! + * Check to see if a node selector is a good option here instead of tags. + * Are you tagging individual models in config blocks? + * You can use folder selectors in many cases to eliminate over tagging of every model in a folder. +* Are you using YAML selectors? + * These enable intricate, layered model selection and can eliminate complicated tagging mechanisms and improve the legibility of the project configuration + +**Useful links**: + +* [.yml files](/docs/building-a-dbt-project/using-sources/#testing-and-documenting-sources) +* [Materializations](/docs/building-a-dbt-project/building-models/materializations/#configuring-materializations) +* [YAML selectors](/reference/node-selection/yaml-selectors/) + +## ✅ Package Management +-------------------------------------------------------------------------------------------------------------------------------------------------------- + +* How up to date are the versions of your dbt Packages? + * You can check this by looking at your packages.yml file and comparing it to the packages hub page. +* Do you have the dbt\_utils package installed? + * This is by far our most popular and essential package. The package contains clever macros to improve your dbt Project. Once implemented, you have access to the macros (no need to copy them over to your project). + +**Useful links** + +* [Packages Docs](/docs/building-a-dbt-project/package-management/) +* [Package Hub](https://hub.getdbt.com/) +* [dbt utils package](https://github.com/dbt-labs/dbt-utils) + +## ✅ Code style +---------------------------------------------------------------------------------------------------------------------------------------- + +* Do you have a clearly defined code style? +* Are you following it strictly? +* Are you optimizing your SQL? + * Are you using window functions and aggregations? + +**Useful links** + +* [dbt Labs' code style](https://github.com/dbt-labs/corp/blob/master/dbt_style_guide.md) +* [Leveling up SQL](https://blog.getdbt.com/one-analysts-guide-for-going-from-good-to-great/) + +## ✅ Project structure +------------------------------------------------------------------------------------------------------------------------------------------------------ + +* If you are using techniques, do you have staging and marts models? + * Do they use table prefixes like ‘fct\_’ and ‘dim\_’? +* Is the code modular? Is it one transformation per one model? +* Are you filtering as early as possible? + * One of the most common mistakes we have found is not filtering or transforming early enough. This causes multiple models downstream to have the same repeated logic (i.e., wet code) and makes updating business logic more cumbersome. +* Are the CTEs modular with one transformation per CTE? +* If you have macro files, are you naming them in a way that clearly represent the macro(s) contained in the file? + +**Useful links** + +* [How Fishtown Structures our dbt Project](https://discourse.getdbt.com/t/how-we-structure-our-dbt-projects/355) +* [Why the Fishtown SQL style guide uses so many CTEs](https://discourse.getdbt.com/t/why-the-fishtown-sql-style-guide-uses-so-many-ctes/1091) + +## ✅ dbt +-------------------------------------------------------------------------------------------------------------------------- + +* What version of dbt are you on? + * The further you get away from the latest release, the more likely you are to keep around old bugs and make updating that much harder. +* What happens when you `dbt run`? + * What are your longest-running models? + * Is it time to reevaluate your modeling strategy? + * Should the model be incremental? + * If it’s already incremental, should you adjust your incremental strategy? + * How long does it take to run the entire dbt project? + * Does every model run? (This is not a joke.) + * If not, why? + * Do you have circular model references? +* Do you use sources? + * If so, do you use source freshness tests? +* Do you use refs and sources for everything? + * Make sure nothing is querying off of raw tables, etc. + ![no querying raw tables](/img/blog/checklist-8ddc2f76de24c98690ef986dcc7974bff09adb59.png) + +* Do you regularly run `dbt test` as part of your workflow and production jobs? +* Do you use Jinja & Macros for repeated code? + * If you do, is the balance met where it’s not being overused to the point code is not readable? + * Is your Jinja easy to read? + * Did you place all of your `set` statements at the top of the model files? + * Did you format the code for Jinja-readability or just for the compiled SQL? + * Do you alter your whitespace? + * Example: `{{ this }}` and not `{{this}}` + * Did you make complex macros as approachable as possible? + * Way to do this are providing argument names and in-line documentation using `{# #}` +* If you have incremental models, are they using unique keys and is\_incremental() macro? +* If you have tags, do they make sense? Do they get utilized? + +**Useful links** + +* [dbt release version](https://github.com/dbt-labs/dbt/releases) +* [Sources](/docs/building-a-dbt-project/using-sources/) +* [Refs](/reference/dbt-jinja-functions/ref/) +* [tags](/reference/resource-configs/tags/) +* [Jinja docs](/docs/building-a-dbt-project/jinja-macros) + +## ✅ Testing & Continuous Integration +---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + +* Do your models have tests? + * The ideal project has 100% test coverage on all of its models. While there are cases where this doesn’t make sense, our rule of thumb is models should have at least a not\_null/unique test on the . +* What are you testing for? Does it make sense? +* What are the assumptions you should be testing for? + * Think about your core business logic as well as your understanding of your sources. +* Are you using pull requests/other forms of version control? + * How easy is it to understand what the code change and intention behind the code change do? +* Do you have mandatory PR reviews before merging code to your dbt project or BI layer? + * Do you use a PR template? + +**Useful links** + +* [Version control](/guides/legacy/best-practices#version-control-your-dbt-project) +* [dbt Labs' PR Template](/blog/analytics-pull-request-template) + +## ✅ Documentation +---------------------------------------------------------------------------------------------------------------------------------------------- + +* Do you use documentation? +* Are there descriptions for each model? +* Are complex transformations and business logic explained in an easily accessible place? +* Are your stakeholders using your documentation? + * If not, why? +* Do you have a readme and regularly update it? +* How easy would it be to onboard someone to your project? +* If you have column-level descriptions, are you using doc blocks? + +Useful Links + +* [FAQs for documentation](/docs/building-a-dbt-project/documentation/#faqs) +* [Doc blocks](/docs/building-a-dbt-project/documentation/#using-docs-blocks) + +## ✅ dbt Cloud specifics +---------------------------------------------------------------------------------------------------------------------------------------------------------- + +* What dbt version are the jobs? + * Are the majority of them inheriting from the environment to make upgrading easier? +* What do your jobs look like? Do they make sense? +* How are your dbt cloud projects organized? + * Do you have any unused projects? +* Have you chosen the most appropriate job for your account level documentation? +* Are the number of runs syncing up with how often your raw data updates and are viewed? + * If your data isn’t updating as often as the runs are happening, this is just not doing anything. +* Do you have a full refresh of the production data? +* Do you run tests on a periodic basis? +* What are the longest-running jobs? +* Do you have a Continuous Integration job? (Github only) + +Are you using the IDE and if so, how well? + +* We found that the IDE has assisted in alleviating issues of maintaining the upgraded dbt version. +* Does dbt cloud have its own user in their warehouse? What is the default warehouse/role? +* Are you getting notifications for failed jobs? Have you set up the slack notifications? + +**Useful links** + +* [dbt Cloud as a CI tool](/docs/dbt-cloud/using-dbt-cloud/cloud-enabling-continuous-integration-with-github) + + +## ✅ DAG Auditing +------------------------------------------------------------------------------------------------------------------------- + +_Note: diagrams in this section show what NOT to do!_ + +* Does your DAG have any common modeling pitfalls? + * Are there any direct joins from sources into an intermediate model? + + * All sources should have a corresponding staging model to clean and standardize the data structure. They should not look like the image below. + + ![bad dag](/img/blog/checklist-28c75101367e272fbc2db2ebb1a1ec030517bb5e_2_517x250.jpeg) + + * Do sources join directly together? + + * All sources should have a corresponding staging model to clean and standardize the data structure. They should not look like the image below. + + ![bad dag 2](/img/blog/checklist-5d8ad45deb695eb6771003e010b242c0a3c122b9_2_517x220.jpeg) + + * Are there any rejoining of upstream concepts? + + * This may indicate: + * a model may need to be expanded so all the necessary data is available downstream + * a new intermediate model is necessary to join the concepts for use in both places + + ![bad dag 2](/img/blog/checklist-acd57c0e781b1eaf75a65b5063f97ac3ddc5c493_2_517x136.jpeg) + + * Are there any “bending connections”? + + * Are models in the same layer dependent on each other? + * This may indicate a change in naming is necessary, or the model should reference further upstream models + + ![bad dag 3](/img/blog/checklist-0532fd13a7d63e3e5df71d025700c4d9c158a7ff_2_517x155.jpeg) + + * Are there model fan outs of intermediate/dimension/fact models? + + * This might indicate some transformations should move to the BI layer, or transformations should be moved upstream + * Your dbt project needs a defined end point! + + [![bad dag 4](/img/blog/checklist-33fcd7c4922233412d1364b39227c876d0cb8215_2_517x111.jpeg) + + * Is there repeated logic found in multiple models? + + * This indicates an opportunity to move logic into upstream models or create specific intermediate models to make that logic reusable + * One common place to look for this is complex join logic. For example, if you’re checking multiple fields for certain specific values in a join, these can likely be condensed into a single field in an upstream model to create a clean, simple join. + +Thanks to Christine Berger for her DAG diagrams! + +**Useful links** + +* [How Fishtown Structures our dbt Project](/blog/how-we-structure-our-dbt-projects/) +* [Coalesce DAG Audit Talk](https://www.youtube.com/watch?v=5W6VrnHVkCA&t=2s) +* [Modular Data Modeling Technique](https://getdbt.com/analytics-engineering/modular-data-modeling-technique/) +* [Understanding Threads](/dbt-cli/configure-your-profile/#understanding-threads) + +This is a quick overview of things to think about in your project. We’ll keep this post updated as we continue to refine our best practices! Happy modeling! diff --git a/website/blog/2021-02-09-how-to-configure-your-dbt-repository-one-or-many.md b/website/blog/2021-02-09-how-to-configure-your-dbt-repository-one-or-many.md new file mode 100644 index 00000000000..60dc91278d2 --- /dev/null +++ b/website/blog/2021-02-09-how-to-configure-your-dbt-repository-one-or-many.md @@ -0,0 +1,162 @@ +--- +title: "How to Configure Your dbt Repository (One or Many)?" +description: "At dbt Labs, as more folks adopt dbt, we have started to see more and more use cases that push the boundaries of our established best practices." +slug: how-to-configure-your-dbt-repository-one-or-many +canonical_url: https://discourse.getdbt.com/t/how-to-configure-your-dbt-repository-one-or-many/2121 + +authors: [amy_chen] + +tags: [dbt tutorials] +hide_table_of_contents: false + +date: 2021-02-09 +is_featured: false +--- + +At dbt Labs, as more folks adopt dbt, we have started to see more and more use cases that push the boundaries of our established best practices. This is especially true to those adopting dbt in the enterprise space. + +After two years of helping companies from 20-10,000+ employees implement dbt & dbt Cloud, the below is my best attempt to answer the question: “Should I have one repository for my dbt project or many?” Alternative title: “To mono-repo or not to mono-repo, that is the question!” + + + +Before we jump into specific structures, I want to start by emphasizing that our guiding principle has always been that **simpler is better**, especially when you are getting started! It should also be noted that everything presented below builds upon Jeremy’s excellent write up on this [from a few years back](https://discourse.getdbt.com/t/should-i-have-an-organisation-wide-project-a-monorepo-or-should-each-work-flow-have-their-own/666/2). That is the prerequisite to this article. + +Before we get started, we need to take inventory. Consider the workflow and teams that will be using dbt. + +**From a workflow perspective, consider:** + +* What will the review process look like at your organization? + * Who can approve pull requests? + * Who will be able to merge code to production? +* For more complex environments who have a dev/qa/prod git branching paradigm: + * Who has access to the objects created in the dev environment? In the qa environment? + * Who needs to be alerted when code has been released to the qa branch? + * Who is responsible for promoting objects from dev to qa? From qa to prod? + +**From a people or team perspective, consider:** + +* How do teams using dbt usually work together? + +* Do those teams have different code styles, review processes, and chief maintainers? + +* Do the teams using dbt ever use the same data sources? Is the raw data located somewhere that all teams using dbt will have access to? + +* Is there SQL that one team should have access to but another team should not? Can folks see the SQL behind the object creation? + +* Are there objects that one team is responsible for that other teams are the consumers of? + + +The answers to these questions should help you navigate through the four options detailed below. I also want to make it clear: the options I’m about to show you will likely be influenced by your data team(s) size but that should not be the only factor to consider. I have seen a team of 30 folks use option 1 and a team of 10 use option 3. It is truly dependent on what your priorities lay. + +**Note:** One repository in this context equates to one dbt project with one dbt\_project.yml. It does not need to have a 1:1 relationship with a dbt cloud project. + +## Option 1: One Repository +------------------------------------------------------ + +![one repository](/img/blog/monorepo-52954083da8268c53f27a578b4b5722b35803b03_2_624x439.png) + +This is the most common structure we see for dbt repository configuration. Though the illustration separates models by business unit, all of the SQL files are stored and organized in a single repository. + +**Strengths** + +* Easy to share and maintain the same core business logic +* Full dependency lineage - your dbt generated DAG encompasses all of your data transformations for your entire company + +**Weaknesses** + +* Too many people! Your repository could have a lot of concurrently open issues/pull requests. +* Too many models! Your analyst is now wading through hundreds of files when their team only works on one business unit’s modeling +* Pull Request approval can be challenging (who has approval for which team? who approves changes to core models used across teams?) + +This is our most time tested option and our most recommended. However, we have started to see folks “size out” of this approach. While it’s difficult to define qualitatively when your team has outgrown this model, these are some factors to consider that might push you to consider alternative options: + +* Your project has 500+ models and the time it takes to compile your dbt project hinders the workflow of your developer\* +* Your git workflow is starting to become cumbersome because there are too many hands in the pot in terms of who needs to approve what + +\*We are making significant efforts to improve this on larger projects but this is something to keep in mind. + +## Option 2: Separate Team Repository with One Shared Repository +-------------------------------------------------------------------------------------------------------------------------------- + +![separate repository](/img/blog/monorepo-3d6f91c1ab275d953417d2239f66e8f81bad7078_2_600x217.png) + +This is one of the first structures we see people move toward when they “outgrow” the mono repo: there is one “core” repository that is incorporated into team specific repositories as a package. If you aren’t familiar with packages, [see the documentation](https://docs.getdbt.com/docs/building-a-dbt-project/package-management/) for more information. + +How would the above function? While each team would work in their own repository, they would put shared items into the shared repository which is then installed in as a package to their repository. Some common things to put into that shared repository would be: + +* a core `dim_customers` model that is relevant across marketing and finance departments. +* `all_days` or calendar model that defines your specific business logics around your financial year calendar and company holidays. +* Macros to be used across your business units. Things like date conversions, seed files to help segment company wide attributes, etc. +* Shared sources (sources.yml files + staging models for those sources) + +What doesn’t go into that shared repository? + +* Models specific to the team (things like `fct_transactions` or `fct_ads`) would live in the unique team repos. +* Team specific logic (things like if you have different definitions of what revenue is, etc) + +**Strengths** + +* Easier approval workflows in terms of team-specific models +* Easier to control user permissions (especially if you have sensitive data or SQL) +* Fewer people contributing to each repository + +**Weaknesses** + +* Hard to decide what goes into the Shared Repository +* Maintaining downstream dependencies of macros and models. There is a need to create a CI/CD process that assures changes in the shared repository will not negatively impact the downstream repositories. It’s possible that you will have to introduce [semantic versioning](https://en.wikipedia.org/wiki/Software_versioning) to mitigate miscommunication about breaking changes. +* Incomplete lineage/documentation for objects not the shared repository + +This is the option I recommend the most when one must stray away from Option 2. This follows our [dbt viewpoint](https://docs.getdbt.com/docs/about/viewpoint/#analytics-is-collaborative) the best in terms of dry code and collaboration as opposed to Option 3 & 4. + +## Option 3: Completely Separate Repositories +------------------------------------------------------------------------------------------ + +![completely separate repos](/img/blog/monorepo-7f6c787766d980479e44a0419e845bc2fc80fa1a_2_296x390.png) + +Then, there is the “don’t allow any overlap” complete separation of repositories within a single organization. + +**Strengths** + +* Simple approval process +* Fitting if different teams have separate Snowflake Accounts/Redshift instances + +**Weaknesses** + +* Easy to create duplicate business logic or out of sync business logic between repositories + * A less than ideal work around: consumers from other teams can subscribe to another team’s releases to be aware of changes. +* Non-collaborative approach +* Incomplete lineage/documentation of company wide data transformations + +There is a time and a place where this makes sense but you start to lose the reusability of code that is one of dbt’s biggest strengths! Unless there is a really good security reason behind this and a true separation of analytics needs across the teams, this approach is the one we recommend avoiding as much as possible. + +## Option 4: Separate Team Repositories + One Documentation Repository +------------------------------------------------------------------------------------------------------------------------------------------ + +![separate team repositories](/img/blog/monorepo-275ba0c84ef31370a57f125ac13a0cbcb808af9a_2_600x365.png) + +This approach is nearly identical to the former (completely separate repositories) but solves one of the weaknesses (“incomplete lineage/documentation”) by introducing an additional repository. If you need something akin to Option 3, this is the better approach. + +**Strengths** + +* Creates a project to provide an overview of the entire organization’s dbt projects\* +* Simple maintenance +* Takes advantage of the strengths from `completely separate repositories` (see above example) + +**Weaknesses** + +* Creates an extraneous project for administrative oversight +* Does not prevent conflicting business logic or duplicate macros +* All models must have unique names across all packages + +\*\* The project will include the information from the dbt projects but might be missing information that is pulled from your if you are on multiple Snowflake accounts/Redshift instances. This is because dbt is only able to query the information schema from that one connection. + +## So… to mono-repo or not to mono-repo? +------------------------------------------------------------------------------- + +All of the above configurations “work”. And as detailed, they each solve for a different use case and business priority. At the end of the day, you need to choose what makes sense for your team today and what your team will need 6 months from now. My recommendations are: + +1. Ask the above questions. +2. Figure out what may be a pain point in the future and try to plan for it from the beginning. +3. Don’t over-complicate things until you have the right reason. As I said in my Coalesce talk: **don’t drag your skeletons from one closet to another** 💀! + +**Note:** Our attempt in writing guides like this and [How we structure our dbt projects](/blog/how-we-structure-our-dbt-projects) aren’t to try to convince you that our way is right; it is to hopefully save you the hundreds of hours it has taken us to form those opinions! diff --git a/website/blog/2021-09-11-sql-dateadd.md b/website/blog/2021-09-11-sql-dateadd.md new file mode 100644 index 00000000000..eae9a500969 --- /dev/null +++ b/website/blog/2021-09-11-sql-dateadd.md @@ -0,0 +1,147 @@ +--- +title: "DATEADD SQL Function Across Data Warehouses" +description: "DATEADD Function syntax varies across data warehouses. Learn how to standardize your syntax no matter the container." +slug: sql-dateadd + +authors: david_krevitt + +tags: [SQL magic] +hide_table_of_contents: false + +date: 2021-11-15 +is_featured: true +--- + +I’ve used the dateadd SQL function thousands of times. + +I’ve googled the syntax of the dateadd SQL function all of those times except one, when I decided to hit the "are you feeling lucky" button and go for it. + +In switching between SQL dialects (BigQuery, Postgres and Snowflake are my primaries), I can literally never remember the argument order (or exact function name) of dateadd. + +This article will go over how the DATEADD function works, the nuances of using it across the major cloud warehouses, and how to standardize the syntax variances using dbt macro. + + + +## What is the DATEADD SQL Function? + +The DATEADD function in SQL adds a time/date interval to a date and then returns the date. This allows you to add or subtract a certain period of time from a given start date. + +Sounds simple enough, but this function lets you do some pretty useful things like calculating an estimated shipment date based on the ordered date. + + +## Differences in DATEADD syntax across data warehouse platforms + +All of them accept the same rough parameters, in slightly different syntax and order: + +* Start / from date +* Datepart (day, week, month, year) +* Interval (integer to increment by) + +The *functions themselves* are named slightly differently, which is common across SQL dialects. + +### For example, the DATEADD function in Snowflake… + +```sql +dateadd( {{ datepart }}, {{ interval }}, {{ from_date }} ) +``` + +*Hour, minute and second are supported!* + +### The DATEADD Function in Databricks + +```sql +date_add( {{ startDate }}, {{ numDays }} ) +``` + +### The DATEADD Function in BigQuery… + +```sql +date_add( {{ from_date }}, INTERVAL {{ interval }} {{ datepart }} ) +``` + +*Dateparts of less than a day (hour / minute / second) are not supported.* + +### The DATEADD Function in Postgres... + +Postgres doesn’t provide a dateadd function out of the box, so you’ve got to go it alone - but the syntax looks very similar to BigQuery’s function… + +```sql +{{ from_date }} + (interval '{{ interval }} {{ datepart }}') +``` + +Switching back and forth between those SQL syntaxes, at least for me, usually requires a quick scan through the warehouse's docs to get back on the horse. + +So I made this handy 2 x 2 matrix to help sort the differences out: + +![blank 2x2 matrix](/img/blog/dateadd_matrix.png) + +I am sorry - that’s just a blank 2x2 matrix. I've surrendered to just searching for the docs. + +## Standardizing your DATEADD SQL syntax with a dbt macro + +But couldn’t we be doing something better with those keystrokes, like typing out and then deleting a tweet? + +dbt (and the [dbt_utils](https://hub.getdbt.com/dbt-labs/dbt_utils/latest/#dateadd-source-macros-cross_db_utils-dateadd-sql-) macro package) helps us smooth out these wrinkles of writing SQL across data warehouses. + +Instead of looking up the syntax each time you use it, you can just write it the same way each time, and the macro compiles it to run on your chosen warehouse: + +```sql +{{ dbt_utils.dateadd(datepart, interval, from_date_or_timestamp) }} +``` + +Adding 1 month to today would look like... + +```sql +{{ dbt_utils.dateadd(month, 1, '2021-08-12' }} +``` + +> *New to dbt? Check out [dbt introduction](https://docs.getdbt.com/docs/introduction) for more background on dbt and the analytics engineering workflow that it facilitates.* +> +> *TL;DR: dbt allows data practitioners to write code like software engineers, which in this case means not repeating yourself unnecessarily.* + +### Compiling away your DATEADD troubles + +When we run dbt, the dateadd macro compiles your function into the SQL dialect of the warehouse adapter you’re running on—it’s running the same SQL you would’ve written yourself in your native query browser. + +And it’s actually quite a simple 31-line macro ([source here](https://github.com/dbt-labs/dbt-utils/blob/0.1.20/macros/cross_db_utils/dateadd.sql) and snapshot below) - if you wanted to extend it (to support another warehouse adapter, for example), I do believe almost any SQL user is qualified to submit a PR to the repo: + +```sql +{% macro dateadd(datepart, interval, from_date_or_timestamp) %} + {{ adapter_macro('dbt_utils.dateadd', datepart, interval, from_date_or_timestamp) }} +{% endmacro %} + + +{% macro default__dateadd(datepart, interval, from_date_or_timestamp) %} + + dateadd( + {{ datepart }}, + {{ interval }}, + {{ from_date_or_timestamp }} + ) + +{% endmacro %} + + +{% macro bigquery__dateadd(datepart, interval, from_date_or_timestamp) %} + + datetime_add( + cast( {{ from_date_or_timestamp }} as datetime), + interval {{ interval }} {{ datepart }} + ) + +{% endmacro %} + + +{% macro postgres__dateadd(datepart, interval, from_date_or_timestamp) %} + + {{ from_date_or_timestamp }} + ((interval '1 {{ datepart }}') * ({{ interval }})) + +{% endmacro %} +``` + +Enjoy! FYI I've used dateadd macro in dbt-utils on BigQuery, Postgres, Redshift and Snowflake, but it likely works across most other warehouses. + +*Note: While `dbt_utils` doesn't support Databricks by default, you can use other packages that [implement overrides](/reference/dbt-jinja-functions/dispatch#overriding-package-macros) as a workaround.* + +*This [spark_utils package](https://github.com/dbt-labs/spark-utils/blob/main/macros/dbt_utils/cross_db_utils/dateadd.sql) can help you implement the override needed to add support for Databricks dateadd* + diff --git a/website/blog/2021-09-11-union-all.md b/website/blog/2021-09-11-union-all.md new file mode 100644 index 00000000000..b85645e7da7 --- /dev/null +++ b/website/blog/2021-09-11-union-all.md @@ -0,0 +1,104 @@ +--- +title: "Towards an Error-free UNION ALL" +description: "Union'ing two or more tables with a long list of columns can be an error-prone chore, which dbt + dbt_utils abstracts away." +slug: sql-union-all + +authors: david_krevitt + +tags: [SQL magic] +hide_table_of_contents: false + +date: 2021-11-15 +is_featured: true +--- + +It is a thankless but necessary task. In SQL, often we’ll need to UNION ALL two or more tables vertically, to combine their values. + + + +Say we need to combine 3 tables: web traffic, ad spend and sales data, to form a full picture of cost per acquisition (CPA). + +Ultimately, we’d want to roll up data at a granularity of date, landing page URL, campaign and channel—so however we combine the 3 tables, we’ll want to wrap it in an outer query with a GROUP BY to reduce the . + +To accomplish that, we could do a few things: + +* `FULL OUTER JOIN`: returns all values + joins where there is a date / landing page / campaign / channel match + +* `UNION`: combines all values vertically + dedupes to return unique values + +* `UNION ALL`: combines all values vertically, with no matching logic + +Let’s assume that data has been deduped at a lower level (in a [staging model for the raw source](https://www.getdbt.com/analytics-engineering/modular-data-modeling-technique/#data-model-naming-conventions)), so deduping here isn’t necessary. + +In terms of performance, UNION ALL will always be more performant than FULL OUTER JOIN, as there’s no matching operation taking place, UNION ALL is just appending tables. + +## The chore of populating null column values in UNION ALLs + +Often when running a UNION ALL, tables will have mismatched columns: the web traffic table won’t have revenue values, and the sales data won’t have session values. + +To complete the union, we have to propagate those columns as null or 0 in our query, in order for the union to succeed: + +```sql +select + date, + landing_page_url, + campaign, + channel, + sessions, + pageviews, + time_on_site, + null as orders, + null as customers, + null as revenue +from sessions + +union all + +select + date, + landing_page_url, + campaign, + channel, + null as sessions, + null as pageviews, + null as time_on_site, + orders, + customers, + revenue +from sales +``` + +Without those null values, we’ll get the dreaded error: + +*Queries in UNION ALL have mismatched column count; query 1 has 10 columns, query 2 has 12 columns* + +As you can imagine, this gets super painful when we want to add a new column within our UNIONs—we must add the column as a null value to every query statement within the UNION ALL stack. + +## Enter the union_relations dbt macro + +dbt allows you to write [macro functions in Jinja](https://docs.getdbt.com/docs/building-a-dbt-project/jinja-macros) to automate away this chore. + +The [union_relations](https://github.com/dbt-labs/dbt-utils#union_relations-source) macro in the [dbt_utils](https://hub.getdbt.com/dbt-labs/dbt_utils/latest/) package completely frees us from propagating null or 0 values for each column that doesn’t exist in the other tables that we’re UNIONing. + +With 3 lines of code, we can accomplish what previously required dozens: + +```sql +{{ dbt_utils.union_relations( + + relations=[ref('sessions'), ref('sales'), ref('ads') + +) }} +``` + +When dbt runs (either locally on the command line, in dbt Cloud, or wherever you choose to deploy it), the union_relations macro generates the exact same SQL as we’d previously written by hand. + +You can see in the [macro’s source code](https://github.com/dbt-labs/dbt-utils/blob/master/macros/sql/union.sql), it finds every column in the tables you’re UNIONing, checks whether those columns exist in the other tables, and if not populates them with a `null as ,` line. + +> *New to dbt? Check out [dbt introduction](https://docs.getdbt.com/docs/introduction) for more background on dbt and the analytics engineering workflow that it facilitates.* +> +> *TL;DR: dbt allows data practitioners to write code like software engineers, which in this case means not repeating yourself unnecessarily.* + +The magic to me of the `union_relations` macro is clear—it allows me to save significant time doing the chore of propagating `null` column values across a UNION ALL statement. + +If you’re interested in going deeper on how dbt macros work, the `union_relations` macro uses a couple programming control structures: for loops and if statements—thanks to dbt’s support for Jinja templating, we can now use these control structures to *write SQL that writes itself.* + diff --git a/website/blog/2021-09-15-september-21-product-email.md b/website/blog/2021-09-15-september-21-product-email.md new file mode 100644 index 00000000000..14985385bc4 --- /dev/null +++ b/website/blog/2021-09-15-september-21-product-email.md @@ -0,0 +1,88 @@ +--- +title: "September 2021 dbt Update: DAG in the IDE + Metadata API in GA" +description: "dbt v1.0 is coming up! Don't forget to update your projects to the latest release." +slug: dbt-product-update-2021-september +authors: [lauren_craigie] + +tags: [dbt updates] +hide_table_of_contents: false + +date: 2021-09-15 +is_featured: false +--- + +Hello there, + +Do you remember? The 21st day of September? 🎶 Course you do it was **two days ago**. Well that's a win in your bucket and the day's barely begun! So let's get a win for someone else -- like Jeremy Cohen, the dbt Core product manager. + +I'm sure you know that half of the updates in this email are pushed automatically when we upgrade everyone to the latest version of dbt Cloud 🚀 + +But did you know the other half requires you (or your account admin) to actively switch to the latest version of dbt *Core*? 😱 If this isn't happening regularly (how-to video [here](https://www.loom.com/share/10f153f24b5448ad96074ebd0b2d917c?utm_campaign=Monthly%20Product%20Updates&utm_source=hs_email&utm_medium=email&_hsenc=p2ANqtz-8nIpohDBSr7SvpXrqY-5ONmnjdIgW0XMiAPkjQTb9Pgwt24nzqAWNX2Xgtj8LA0LrPoHpD)), you may miss out on major improvements to performance, stability, and speed. + +Give Jeremy a win and check out the [blog](http://blog.getdbt.com/getting-ready-for-v1-0/?utm_campaign=Monthly%20Product%20Updates&utm_source=hs_email&utm_medium=email&_hsenc=p2ANqtz-8nIpohDBSr7SvpXrqY-5ONmnjdIgW0XMiAPkjQTb9Pgwt24nzqAWNX2Xgtj8LA0LrPoHpD) he just posted on why this matters even more leading up to 💥dbt v1.0💥. While we're throwing W's, don't forget to also [register for his talk at Coalesce now](https://coalesce.getdbt.com/talks/dbt-v10-reveal/?utm_campaign=Monthly%20Product%20Updates&utm_source=hs_email&utm_medium=email&_hsenc=p2ANqtz-8nIpohDBSr7SvpXrqY-5ONmnjdIgW0XMiAPkjQTb9Pgwt24nzqAWNX2Xgtj8LA0LrPoHpD)! + + + + +## **What's New** +-------------- + +### dbt v0.20.2 +- Check out the [#dbt-releases](https://getdbt.slack.com/archives/C37J8BQEL?utm_campaign=Monthly%20Product%20Updates&utm_source=hs_email&utm_medium=email&_hsenc=p2ANqtz-8nIpohDBSr7SvpXrqY-5ONmnjdIgW0XMiAPkjQTb9Pgwt24nzqAWNX2Xgtj8LA0LrPoHpD) channel in the dbt Community Slack for full detail! +- More fixes for bugs, support for the latest Python version, and best-yet partial parsing for stable & speedy development + +### dbt v0.21.0-rc1 +- Check out the [#dbt-prereleases](https://getdbt.slack.com/archives/C016X6ABVUK?utm_campaign=Monthly%20Product%20Updates&utm_source=hs_email&utm_medium=email&_hsenc=p2ANqtz-8nIpohDBSr7SvpXrqY-5ONmnjdIgW0XMiAPkjQTb9Pgwt24nzqAWNX2Xgtj8LA0LrPoHpD) channel in the dbt Community Slack, and Jeremy's [Discourse post](https://discourse.getdbt.com/t/prerelease-dbt-core-v0-21-louis-kahn/3077?utm_campaign=Monthly%20Product%20Updates&utm_source=hs_email&utm_medium=email&_hsenc=p2ANqtz-8nIpohDBSr7SvpXrqY-5ONmnjdIgW0XMiAPkjQTb9Pgwt24nzqAWNX2Xgtj8LA0LrPoHpD)! +- dbt build: Did you catch our teaser last month at [Staging](https://www.youtube.com/watch?v=-XRD_IjWX2U&utm_campaign=Monthly%20Product%20Updates&utm_source=hs_email&utm_medium=email&_hsenc=p2ANqtz-8nIpohDBSr7SvpXrqY-5ONmnjdIgW0XMiAPkjQTb9Pgwt24nzqAWNX2Xgtj8LA0LrPoHpD)? +- Defining resource configs in all the places you'd expect (i.e. yaml files) +- Capture changes to macros in state:modified, for best-yet Slim CI + + ![Screen Shot 2021-09-20 at 11.34.47 AM (1)](https://hs-8698602.f.hubspotemail.net/hub/8698602/hubfs/Screen%20Shot%202021-09-20%20at%2011.34.47%20AM%20(1).png?upscale=true&width=600&upscale=true&name=Screen%20Shot%202021-09-20%20at%2011.34.47%20AM%20(1).png) + +### dbt Cloud v1.1.32 - v1.1.35:  +- Changelog and additional assets located [here.](https://docs.getdbt.com/docs/dbt-cloud/cloud-changelog?utm_campaign=Monthly%20Product%20Updates&utm_source=hs_email&utm_medium=email&_hsenc=p2ANqtz-8nIpohDBSr7SvpXrqY-5ONmnjdIgW0XMiAPkjQTb9Pgwt24nzqAWNX2Xgtj8LA0LrPoHpD)* +- [DAG in the IDE](https://blog.getdbt.com/on-dags-hierarchies-and-ides/?utm_campaign=Monthly%20Product%20Updates&utm_source=hs_email&utm_medium=email&_hsenc=p2ANqtz-8nIpohDBSr7SvpXrqY-5ONmnjdIgW0XMiAPkjQTb9Pgwt24nzqAWNX2Xgtj8LA0LrPoHpD): We want users to have a frictionless experience when navigating between code and context. Embedding the DAG within the IDE makes investigating project structure a lot easier + ![Screen Shot 2021-09-22 at 4.59.24 PM](https://hs-8698602.f.hubspotemail.net/hub/8698602/hubfs/Screen%20Shot%202021-09-22%20at%204.59.24%20PM.png?upscale=true&width=1120&upscale=true&name=Screen%20Shot%202021-09-22%20at%204.59.24%20PM.png) +- The [Metadata API](https://docs.getdbt.com/docs/dbt-cloud/dbt-cloud-api/metadata/metadata-overview?utm_campaign=Monthly%20Product%20Updates&utm_source=hs_email&utm_medium=email&_hsenc=p2ANqtz-8nIpohDBSr7SvpXrqY-5ONmnjdIgW0XMiAPkjQTb9Pgwt24nzqAWNX2Xgtj8LA0LrPoHpD): Now in GA! Assess data health with the metadata generated by recent dbt job runs +- [Dashboard Status Tiles](https://docs.getdbt.com/docs/dbt-cloud/using-dbt-cloud/cloud-dashboard-status-tiles?utm_campaign=Monthly%20Product%20Updates&utm_source=hs_email&utm_medium=email&_hsenc=p2ANqtz-8nIpohDBSr7SvpXrqY-5ONmnjdIgW0XMiAPkjQTb9Pgwt24nzqAWNX2Xgtj8LA0LrPoHpD): Embed this tile anywhere iFrames live to quickly check data freshness + +## New Resources  +-------------- + +### Things to Read 📚 + +- Have you subscribed to the [Analytics Engineering Roundup](https://roundup.getdbt.com/subscribe?utm_campaign=Monthly%20Product%20Updates&utm_source=hs_email&utm_medium=email&_hsenc=p2ANqtz-8nIpohDBSr7SvpXrqY-5ONmnjdIgW0XMiAPkjQTb9Pgwt24nzqAWNX2Xgtj8LA0LrPoHpD)? Tristan (dbt Labs Founder and CEO), and Anna (Director of Community) just started trading off Sunday sends, giving them both a little more time to go deep on a topic that's top of mind for Data Twitter everyone. Anna's latest reflection?*[ Your Data PM is not a panacea](https://roundup.getdbt.com/p/your-data-pm-is-not-a-panacea?utm_campaign=Monthly%20Product%20Updates&utm_source=hs_email&utm_medium=email&_hsenc=p2ANqtz-8nIpohDBSr7SvpXrqY-5ONmnjdIgW0XMiAPkjQTb9Pgwt24nzqAWNX2Xgtj8LA0LrPoHpD).* + + + + + +### Things to Listen To 🎧 + +- The [latest episode](https://roundup.getdbt.com/p/brittany-bennett-sunrise-movement?utm_campaign=Monthly%20Product%20Updates&utm_source=hs_email&utm_medium=email&_hsenc=p2ANqtz-8nIpohDBSr7SvpXrqY-5ONmnjdIgW0XMiAPkjQTb9Pgwt24nzqAWNX2Xgtj8LA0LrPoHpD) of the Analytics Engineering podcast dropped this morning, and I'm literally listening as I type. The guest, Brittany Bennett, is talking about hiring for mission alignment over "technical" skill. I can even feel this over in Product Marketing, so I'm keen to parse the parallels! *Also, if you think you'd do a better job at these emails (I don't doubt you could) you should join my team -- HMU.* + +- If you missed the previous episode of the pod, our friends at [Hex](https://hex.tech/?utm_campaign=Monthly%20Product%20Updates&utm_source=hs_email&utm_medium=email&_hsenc=p2ANqtz-8nIpohDBSr7SvpXrqY-5ONmnjdIgW0XMiAPkjQTb9Pgwt24nzqAWNX2Xgtj8LA0LrPoHpD) joined Tristan and Julia to ask, *"What if data team collaboration looked more like a GDoc than a Git workflow?"* 😱 In the distance, I can be heard asking why marketing collaboration can't look more like a Powerpoint, but no one answers, because no one agrees. + + + + + +### Things to Experience ✨ + +- World-renowned podcast host and product manager, Julia Schottenstein, is speaking at the [Open Source Data conference](https://www.opensourcedatastack.com/?utm_campaign=Monthly%20Product%20Updates&utm_source=hs_email&utm_medium=email&_hsenc=p2ANqtz-8nIpohDBSr7SvpXrqY-5ONmnjdIgW0XMiAPkjQTb9Pgwt24nzqAWNX2Xgtj8LA0LrPoHpD) next week! She's joining an all-star panel of friends from Snowplow, Meltano, Elementl, and more. + +- World-renowned aerial acrobat and solutions architect, Amy Chen, is leading a workshop at the [Snowflake Build Summit](https://www.snowflake.com/build/?utm_source=dbt-labs&utm_medium=referral&utm_campaign=build-summit-na-en-partner-dbt&_hsenc=p2ANqtz-8nIpohDBSr7SvpXrqY-5ONmnjdIgW0XMiAPkjQTb9Pgwt24nzqAWNX2Xgtj8LA0LrPoHpD) next month! They'll share [how to build a scalable data pipeline](https://events.snowflake.com/build/agenda/session/619834?utm_campaign=Monthly%20Product%20Updates&utm_source=hs_email&utm_medium=email&_hsenc=p2ANqtz-8nIpohDBSr7SvpXrqY-5ONmnjdIgW0XMiAPkjQTb9Pgwt24nzqAWNX2Xgtj8LA0LrPoHpD) using dbt + Snowflake for financial reporting use cases. + + +### Things to Observe 👀 + +- This photo of me on top of Mt Whitney after my solo SOBO of the JMT last month. This is both the reason why I'll never again eat oatmeal, and the reason you didn't get a newsletter in August. *Sorry about that.* + + ![Image from iOS (2)](https://hs-8698602.f.hubspotemail.net/hub/8698602/hubfs/Image%20from%20iOS%20(2).jpg?upscale=true&width=400&upscale=true&name=Image%20from%20iOS%20(2).jpg) + +Hey, thanks for reading. I appreciate you. + +*Lauren Craigie* +*Director of Product Marketing, dbt Labs* + + diff --git a/website/blog/2021-10-15-october-21-product-update-email.md b/website/blog/2021-10-15-october-21-product-update-email.md new file mode 100644 index 00000000000..b08b6de77e5 --- /dev/null +++ b/website/blog/2021-10-15-october-21-product-update-email.md @@ -0,0 +1,88 @@ +--- +title: "October 2021 dbt Update: Metrics and Hat Tricks 🎩" +description: "Also flagging that Coalesce is less than 3 weeks away! 😱" +slug: dbt-product-update-2021-october +authors: [lauren_craigie] + +tags: [dbt updates] +hide_table_of_contents: false + +date: 2021-10-15 +is_featured: false +--- + +Hello there, + +While I have a lot of fun things to share this month, I can't start with anything other than this: + +[![Screen Shot 2021-10-20 at 6.12.16 PM](https://hs-8698602.f.hubspotemail.net/hub/8698602/hubfs/Screen%20Shot%202021-10-20%20at%206.12.16%20PM.png?upscale=true&width=800&upscale=true&name=Screen%20Shot%202021-10-20%20at%206.12.16%20PM.png)](https://twitter.com/getdbt/status/1449090582865981442?s=20&utm_campaign=Monthly%20Product%20Updates&utm_source=hs_email&utm_medium=email&_hsenc=p2ANqtz-_wfy8vfjMjwQ7o8TXEOVz-oXI35iVcVP1HtAvriVHfJoAd1IcsP-MCww6vJUDlvAfiuQjZ) + +Yep, it's official: + +**💥[dbt will support metric definitions](https://github.com/dbt-labs/dbt-core/issues/4071?utm_campaign=Monthly%20Product%20Updates&utm_source=hs_email&utm_medium=email&_hsenc=p2ANqtz-_wfy8vfjMjwQ7o8TXEOVz-oXI35iVcVP1HtAvriVHfJoAd1IcsP-MCww6vJUDlvAfiuQjZ)💥** + +With this feature, you'll be able to centrally define rules for aggregating metrics (think, "active users" or "MRR") in version controlled, tested, documented dbt project code. + + + +We still have a ways to go, but in future, you'll be able to explore these metrics in the BI and analytics tools that you know and love. + +Jeremy (dbt PM) will share more about the metrics layer in his [v1.0 reveal at Coalesce](https://coalesce.getdbt.com/talks/dbt-v10-reveal/?utm_medium=email&utm_source=hs_email%5B%E2%80%A6%5Dn%3Dh2-2021_coalesce-2021_awareness&utm_content=connect_prod_&_hsenc=p2ANqtz-_wfy8vfjMjwQ7o8TXEOVz-oXI35iVcVP1HtAvriVHfJoAd1IcsP-MCww6vJUDlvAfiuQjZ). + +While this topic plays a significant supporting role in [Drew's keynote](https://coalesce.getdbt.com/talks/keynote-building-a-force-of-gravity/?utm_medium=ema%5B%E2%80%A6%5Dn%3Dh2-2021_coalesce-2021_awareness&utm_content=connect_prod_&_hsenc=p2ANqtz-_wfy8vfjMjwQ7o8TXEOVz-oXI35iVcVP1HtAvriVHfJoAd1IcsP-MCww6vJUDlvAfiuQjZ), *it's not the whole story*🍿. Drew's talk will tie together several threads across the industry right now, and introduce some *very* exciting futures for dbt and the community as a whole. + +*You really don't want to miss this one - [register for free here](https://coalesce.getdbt.com/talks/keynote-building-a-force-of-gravity/?utm_medium=ema%5B%E2%80%A6%5Dn%3Dh2-2021_coalesce-2021_awareness&utm_content=connect_prod_&_hsenc=p2ANqtz-_wfy8vfjMjwQ7o8TXEOVz-oXI35iVcVP1HtAvriVHfJoAd1IcsP-MCww6vJUDlvAfiuQjZ).* + +## What's New +-------------- + +I've got three really exciting things to share this month! + +### dbt v0.21:  +- Check out the [#dbt-releases](https://getdbt.slack.com/archives/C37J8BQEL?utm_campaign=Monthly%20Product%20Updates&utm_source=hs_email&utm_medium=email&_hsenc=p2ANqtz-_wfy8vfjMjwQ7o8TXEOVz-oXI35iVcVP1HtAvriVHfJoAd1IcsP-MCww6vJUDlvAfiuQjZ) channel in the dbt Community Slack for full detail! + +- [dbt build](https://docs.getdbt.com/reference/commands/build?utm_campaign=Monthly%20Product%20Updates&utm_source=hs_email&utm_medium=email&_hsenc=p2ANqtz-_wfy8vfjMjwQ7o8TXEOVz-oXI35iVcVP1HtAvriVHfJoAd1IcsP-MCww6vJUDlvAfiuQjZ) is here! 🙌 This command executes everything you'd want to do in the DAG, in order, and does it with attitude *opinions:* Run models, test tests, snapshot snapshots and seed seeds while prioritizing quality and resiliency. Reduce several steps to a single command and bring best practices along for the ride 🚗 + +### v1.0 beta:  +- Check out the [#dbt-prereleases](https://getdbt.slack.com/archives/C016X6ABVUK?utm_campaign=Monthly%20Product%20Updates&utm_source=hs_email&utm_medium=email&_hsenc=p2ANqtz-_wfy8vfjMjwQ7o8TXEOVz-oXI35iVcVP1HtAvriVHfJoAd1IcsP-MCww6vJUDlvAfiuQjZ) channel in the dbt Community Slack**, and Jeremy's [Discourse post](https://discourse.getdbt.com/t/prerelease-dbt-core-v1-0-0-b1/3180?utm_campaign=Monthly%20Product%20Updates&utm_source=hs_email&utm_medium=email&_hsenc=p2ANqtz-_wfy8vfjMjwQ7o8TXEOVz-oXI35iVcVP1HtAvriVHfJoAd1IcsP-MCww6vJUDlvAfiuQjZ)!* + +- v1.0 is a huge milestone with all the trimmings, including 100x faster project parsing compared to v0.19.0 ⚡. We're excited to celebrate with you during [Jeremy's session at Coalesce](https://coalesce.getdbt.com/talks/dbt-v10-reveal/?utm_campaign=Monthly%20Product%20Updates&utm_source=hs_email&utm_medium=email&_hsenc=p2ANqtz-_wfy8vfjMjwQ7o8TXEOVz-oXI35iVcVP1HtAvriVHfJoAd1IcsP-MCww6vJUDlvAfiuQjZ), but until then, we hope you give the [beta a spin](https://getdbt.slack.com/archives/C016X6ABVUK/p1634151813050300?utm_campaign=Monthly%20Product%20Updates&utm_source=hs_email&utm_medium=email&_hsenc=p2ANqtz-_wfy8vfjMjwQ7o8TXEOVz-oXI35iVcVP1HtAvriVHfJoAd1IcsP-MCww6vJUDlvAfiuQjZ)! And don't forget to join the [#dbt-v1-readiness](https://getdbt.slack.com/archives/C02HM9AAXL4?utm_campaign=Monthly%20Product%20Updates&utm_source=hs_email&utm_medium=email&_hsenc=p2ANqtz-_wfy8vfjMjwQ7o8TXEOVz-oXI35iVcVP1HtAvriVHfJoAd1IcsP-MCww6vJUDlvAfiuQjZ) channel in Slack. + +### dbt Cloud v1.1.36 - v1.1.37 +- Changelog + docs located [here.](https://docs.getdbt.com/docs/dbt-cloud/cloud-changelog?utm_campaign=Monthly%20Product%20Updates&utm_source=hs_email&utm_medium=email&_hsenc=p2ANqtz-_wfy8vfjMjwQ7o8TXEOVz-oXI35iVcVP1HtAvriVHfJoAd1IcsP-MCww6vJUDlvAfiuQjZ) + +- [Model bottlenecks beta](https://getdbt.slack.com/archives/C02GUTGK73N?utm_campaign=Monthly%20Product%20Updates&utm_source=hs_email&utm_medium=email&_hsenc=p2ANqtz-_wfy8vfjMjwQ7o8TXEOVz-oXI35iVcVP1HtAvriVHfJoAd1IcsP-MCww6vJUDlvAfiuQjZ): Identify long-running models ripe for refactoring (or re-scheduling). The new model timing dashboard in the run detail page helps you quickly assess job composition, order, and duration to optimize your workflows and cut costs💰 + + ![image-1](https://hs-8698602.f.hubspotemail.net/hub/8698602/hubfs/image-1.png?upscale=true&width=1120&upscale=true&name=image-1.png) + +The Model Timing tab in dbt Cloud highlights models taking particularly long to run. + + +## New Resources  +-------------- + +### Things to Try 🛠️ + +- Nearly *500* dbt Cloud accounts are using CI. Want to know why? (or maybe... *how?*) Julia breaks it down in her [latest blog](https://blog.getdbt.com/adopting-ci-cd-with-dbt-cloud/?utm_campaign=Monthly%20Product%20Updates&utm_source=hs_email&utm_medium=email&_hsenc=p2ANqtz-_wfy8vfjMjwQ7o8TXEOVz-oXI35iVcVP1HtAvriVHfJoAd1IcsP-MCww6vJUDlvAfiuQjZ) and shares how to choose and configure continuous delivery or continuous deployment at your organization. +- Hex just [launched an integration](https://hex.tech/blog/dbt-integration?utm_campaign=Monthly%20Product%20Updates&utm_source=hs_email&utm_medium=email&_hsenc=p2ANqtz-_wfy8vfjMjwQ7o8TXEOVz-oXI35iVcVP1HtAvriVHfJoAd1IcsP-MCww6vJUDlvAfiuQjZ) with dbt! It uses the [dbt Cloud Metadata API](https://docs.getdbt.com/docs/dbt-cloud/dbt-cloud-api/metadata/metadata-overview?utm_campaign=Monthly%20Product%20Updates&utm_source=hs_email&utm_medium=email&_hsenc=p2ANqtz-_wfy8vfjMjwQ7o8TXEOVz-oXI35iVcVP1HtAvriVHfJoAd1IcsP-MCww6vJUDlvAfiuQjZ) to surface metadata from dbt right in Hex, letting you quickly get the context you need on things like data freshness without juggling multiple apps and browser tabs. Get started [here](https://docs.hex.tech/connecting-to-data/configuring-data-connections/dbt-integration?utm_campaign=Monthly%20Product%20Updates&utm_source=hs_email&utm_medium=email&_hsenc=p2ANqtz-_wfy8vfjMjwQ7o8TXEOVz-oXI35iVcVP1HtAvriVHfJoAd1IcsP-MCww6vJUDlvAfiuQjZ). +- The [dbt-Rockset adapter](https://github.com/rockset/dbt-rockset?utm_campaign=Monthly%20Product%20Updates&utm_source=hs_email&utm_medium=email&_hsenc=p2ANqtz-_wfy8vfjMjwQ7o8TXEOVz-oXI35iVcVP1HtAvriVHfJoAd1IcsP-MCww6vJUDlvAfiuQjZ) (now in beta) just received a major update. It now supports View, Table, Incremental, and Ephemeral materializations to help you perform real-time data transformations on Rockset. Read more [here.](https://rockset.com/blog/real-time-data-transformations-dbt-rockset?utm_campaign=Monthly%20Product%20Updates&utm_source=hs_email&utm_medium=email&_hsenc=p2ANqtz-_wfy8vfjMjwQ7o8TXEOVz-oXI35iVcVP1HtAvriVHfJoAd1IcsP-MCww6vJUDlvAfiuQjZ). + +### Things to Read 📚 + +- Everyone is talking about the next layer of the modern data stack. It's [not a new conversation](https://benn.substack.com/p/metrics-layer?utm_campaign=Monthly%20Product%20Updates&utm_source=hs_email&utm_medium=email&_hsenc=p2ANqtz-_wfy8vfjMjwQ7o8TXEOVz-oXI35iVcVP1HtAvriVHfJoAd1IcsP-MCww6vJUDlvAfiuQjZ), but it is starting to heat up. Anna (dbt Labs Director of Community), does a phenomenal job connecting this week's events in the latest issue of the [Analytics Engineering Roundup](https://roundup.getdbt.com/?utm_campaign=Monthly%20Product%20Updates&utm_source=hs_email&utm_medium=email&_hsenc=p2ANqtz-_wfy8vfjMjwQ7o8TXEOVz-oXI35iVcVP1HtAvriVHfJoAd1IcsP-MCww6vJUDlvAfiuQjZ). + +### Things to Watch 📺 + +- [Infrastructure-as-Code and the Modern Data Experience](https://futuredata.brighttalk.live/talk/19069-506932/?utm_campaign=Monthly%20Product%20Updates&utm_source=hs_email&utm_medium=email&_hsenc=p2ANqtz-_wfy8vfjMjwQ7o8TXEOVz-oXI35iVcVP1HtAvriVHfJoAd1IcsP-MCww6vJUDlvAfiuQjZ) + + At the Future Data Conference last week Tristan noted that data workflows borrow much from software engineering, but haven't really crossed the DevOps chasm. What's missing? Spreadsheets? Actually... *maybe.* 😅 Okay you had to be there. Luckily you still can! Check out the [recording](https://futuredata.brighttalk.live/talk/19069-506932/?utm_campaign=Monthly%20Product%20Updates&utm_source=hs_email&utm_medium=email&_hsenc=p2ANqtz-_wfy8vfjMjwQ7o8TXEOVz-oXI35iVcVP1HtAvriVHfJoAd1IcsP-MCww6vJUDlvAfiuQjZ). +- [Modeling behavioral data with Snowplow and dbt](https://get.snowplowanalytics.com/wbn/dbt-and-snowplow/data-modeling/?utm_campaign=Monthly%20Product%20Updates&utm_source=hs_email&utm_medium=email&_hsenc=p2ANqtz-_wfy8vfjMjwQ7o8TXEOVz-oXI35iVcVP1HtAvriVHfJoAd1IcsP-MCww6vJUDlvAfiuQjZ) (coming up on 10/27). + Our own Sanjana Sen joins the Snowplow team to talk modeling Snowplow event data in dbt -- including how to structure your data models, best practices to follow, and key pitfalls to avoid. +- [How Blend Eliminated Data Silos with dbt and Hightouch](https://hightouch.io/dbt-hightouch-blend-event/?utm_campaign=Monthly%20Product%20Updates&utm_source=hs_email&utm_medium=email&_hsenc=p2ANqtz-_wfy8vfjMjwQ7o8TXEOVz-oXI35iVcVP1HtAvriVHfJoAd1IcsP-MCww6vJUDlvAfiuQjZ) (coming up 10/28). + Fin-tech behemoth, Blend, processes trillions of dollars in loans (and recently IPO'd). Join this talk with William Tsu (Customer Success Operations at Blend) to learn how adopting dbt and Hightouch has helped them overcome data silos to keep kicking a$$. + + +That's all for now! Thanks for reading, and as always, *let me know if there's anything else you want to see in these updates!* + +*Lauren Craigie* +*Director of Product Marketing, dbt Labs* diff --git a/website/blog/2021-11-15-november-21-product-email.md b/website/blog/2021-11-15-november-21-product-email.md new file mode 100644 index 00000000000..3c28187f739 --- /dev/null +++ b/website/blog/2021-11-15-november-21-product-email.md @@ -0,0 +1,71 @@ +--- +title: "November 2021 dbt Update: v1.0, Environment Variables, and a Question About the Size of Waves 🌊" +description: "Also flagging that Coalesce is less than 3 weeks away! 😱" +slug: dbt-product-update-2021-november +authors: [lauren_craigie] + +tags: [dbt updates] +hide_table_of_contents: false + +date: 2021-11-15 +is_featured: false +--- + +Hi there, + +Before I get to the goods, I just wanted to quickly flag that Coalesce is less than 3 weeks away! 😱 If you had to choose just ONE of the 60+ sessions on tap, consider [Tristan's keynote with A16z's Martin Casado](https://coalesce.getdbt.com/talks/keynote-how-big-is-this-wave/?utm_medium=email&utm_source=hs_email&utm_campaign=h2-2021_coalesce-2021_awareness&utm_content=connect_prod-2_&_hsenc=p2ANqtz-9SoWbfj9_ZRDew6i8p8yand1JSmLh7yfridIrLwO7bgHTUmnbKcRp3AEKCO8pOytotdxAo). + +It has two of my favorite elements: + +1) Spice 🌶️ + +2) Not-actually-about-us 😅 + +Martin and Tristan will discuss something we've all probably considered with the latest wave of innovation (and funding) in our space: + +*Is the modern data stack just another wave in a long string of trendy technologies, or is it somehow more permanent?* + +Hear their take, and share your own by [registering here](https://coalesce.getdbt.com/talks/keynote-how-big-is-this-wave/?utm_medium=email&utm_source=hs_email&utm_campaign=h2-2021_coalesce-2021_awareness&utm_content=connect_prod-2_&_hsenc=p2ANqtz-9SoWbfj9_ZRDew6i8p8yand1JSmLh7yfridIrLwO7bgHTUmnbKcRp3AEKCO8pOytotdxAo). + + + +## **What's New** +-------------- + +### dbt v1.0.0rc1: +- Check out the [#dbt-prereleases](https://getdbt.slack.com/archives/C016X6ABVUK?utm_campaign=Monthly%20Product%20Updates&utm_source=hs_email&utm_medium=email&_hsenc=p2ANqtz-9SoWbfj9_ZRDew6i8p8yand1JSmLh7yfridIrLwO7bgHTUmnbKcRp3AEKCO8pOytotdxAo) channel in the dbt Community Slack, and Jeremy's [Discourse post](https://discourse.getdbt.com/t/prerelease-dbt-core-v1-0-0-b1/3180?utm_campaign=Monthly%20Product%20Updates&utm_source=hs_email&utm_medium=email&_hsenc=p2ANqtz-9SoWbfj9_ZRDew6i8p8yand1JSmLh7yfridIrLwO7bgHTUmnbKcRp3AEKCO8pOytotdxAo)! + +- A first release candidate of v1.0 is now live! 🎉 I've talked about v1.0 a bit, but this version also includes a new logging interface, and a start at the [metrics issue](https://github.com/dbt-labs/dbt-core/issues/4071?utm_campaign=Monthly%20Product%20Updates&utm_source=hs_email&utm_medium=email&_hsenc=p2ANqtz-9SoWbfj9_ZRDew6i8p8yand1JSmLh7yfridIrLwO7bgHTUmnbKcRp3AEKCO8pOytotdxAo) mentioned last month *(Drew will have a lot more to say about that at [Coalesce](https://coalesce.getdbt.com/talks/keynote-building-a-force-of-gravity/?utm_medium=ema%5B%E2%80%A6%5Dn%3Dh2-2021_coalesce-2021_awareness&utm_content=connect_prod_&_hsenc=p2ANqtz-9SoWbfj9_ZRDew6i8p8yand1JSmLh7yfridIrLwO7bgHTUmnbKcRp3AEKCO8pOytotdxAo)!)* + +### dbt v0.21.1:  +- Check out the [#dbt-prereleases](https://getdbt.slack.com/archives/C016X6ABVUK?utm_campaign=Monthly%20Product%20Updates&utm_source=hs_email&utm_medium=email&_hsenc=p2ANqtz-9SoWbfj9_ZRDew6i8p8yand1JSmLh7yfridIrLwO7bgHTUmnbKcRp3AEKCO8pOytotdxAo) channel in the dbt Community Slack! + +- A release candidate for v0.21.1 is available, with an official release coming next week. This release resolves some [slowdown issues](https://github.com/dbt-labs/dbt-core/issues/4012?utm_campaign=Monthly%20Product%20Updates&utm_source=hs_email&utm_medium=email&_hsenc=p2ANqtz-9SoWbfj9_ZRDew6i8p8yand1JSmLh7yfridIrLwO7bgHTUmnbKcRp3AEKCO8pOytotdxAo) encountered in large projects on v0.21.0. + +### dbt Cloud v1.1.38 - v1.1.39: *Changelog + docs located [here.](https://docs.getdbt.com/docs/dbt-cloud/cloud-changelog?utm_campaign=Monthly%20Product%20Updates&utm_source=hs_email&utm_medium=email&_hsenc=p2ANqtz-9SoWbfj9_ZRDew6i8p8yand1JSmLh7yfridIrLwO7bgHTUmnbKcRp3AEKCO8pOytotdxAo)* + +- [Environment Variables](https://docs.getdbt.com/docs/dbt-cloud/using-dbt-cloud/cloud-environment-variables?utm_campaign=Monthly%20Product%20Updates&utm_source=hs_email&utm_medium=email&_hsenc=p2ANqtz-9SoWbfj9_ZRDew6i8p8yand1JSmLh7yfridIrLwO7bgHTUmnbKcRp3AEKCO8pOytotdxAo) have landed in dbt Cloud! Clone private packages, limit data processed in dev environments, and a whole lot more + +## New Resources  +-------------- + +### Things to Try 🛠️ + +- New Course! If you're new to dbt and wondering how to migrate legacy transformation code into modular dbt data models, our new [Refactoring course](https://blog.getdbt.com/sql-refactoring-course/?utm_campaign=Monthly%20Product%20Updates&utm_source=hs_email&utm_medium=email&_hsenc=p2ANqtz-9SoWbfj9_ZRDew6i8p8yand1JSmLh7yfridIrLwO7bgHTUmnbKcRp3AEKCO8pOytotdxAo) can help! *It's also just 3.5hrs, so no excuses* 🙂  + +### Things to Read 📚 + +- The [dbt Discourse](https://discourse.getdbt.com/?utm_campaign=Monthly%20Product%20Updates&utm_source=hs_email&utm_medium=email&_hsenc=p2ANqtz-9SoWbfj9_ZRDew6i8p8yand1JSmLh7yfridIrLwO7bgHTUmnbKcRp3AEKCO8pOytotdxAo) has been a great place for asking long-form questions, and sharing helpful how-to's like [this insanely popular piece](https://discourse.getdbt.com/t/how-we-sped-up-our-ci-runs-by-10x-using-slim-ci/2603?utm_campaign=Monthly%20Product%20Updates&utm_source=hs_email&utm_medium=email&_hsenc=p2ANqtz-9SoWbfj9_ZRDew6i8p8yand1JSmLh7yfridIrLwO7bgHTUmnbKcRp3AEKCO8pOytotdxAo) on 10x-ing CI runs using Slim CI. But to collect more knowledge from across our community, we need a bigger boat. Stay tuned for the solution, arriving November 29th 👀 +- Can you guess the #1 job title of Coalesce registrants? 🛎️ Data Engineer! But you don't have to be one to get value out of the 60+ sessions on offer that week. Check out [this blog](https://blog.getdbt.com/coalesce-returns-for-year-two-this-december/?utm_campaign=Monthly%20Product%20Updates&utm_source=hs_email&utm_medium=email&_hsenc=p2ANqtz-9SoWbfj9_ZRDew6i8p8yand1JSmLh7yfridIrLwO7bgHTUmnbKcRp3AEKCO8pOytotdxAo) by the Coalesce Queen herself to help you decide which sessions are right for you. + +### Things to Listen To 🎧 + +- Julien Le Dem joined the [Analytics Engineer Podcast](https://roundup.getdbt.com/p/ep-10-why-data-lineage-matters-w?utm_campaign=Monthly%20Product%20Updates&utm_source=hs_email&utm_medium=email&_hsenc=p2ANqtz-9SoWbfj9_ZRDew6i8p8yand1JSmLh7yfridIrLwO7bgHTUmnbKcRp3AEKCO8pOytotdxAo) to talk about how OS projects become standards, and why data lineage in particular is in need of an open standard.  + +- [The rise of the Analytics Engineer](https://youtu.be/ixyzF4Dy9Us?utm_campaign=Monthly%20Product%20Updates&utm_source=hs_email&utm_medium=email&_hsenc=p2ANqtz-9SoWbfj9_ZRDew6i8p8yand1JSmLh7yfridIrLwO7bgHTUmnbKcRp3AEKCO8pOytotdxAo): Anna, dbt Labs Director of Community, joined Thoughtspot to talk about the evolution of analytics engineering, or the emergence of the "full stack data analyst." + + +That's all for now! See you at Coalesce! + +*Lauren Craigie* +*Director of Product Marketing, dbt Labs* diff --git a/website/blog/2021-11-22-dbt-labs-pr-template.md b/website/blog/2021-11-22-dbt-labs-pr-template.md new file mode 100644 index 00000000000..7ecec933704 --- /dev/null +++ b/website/blog/2021-11-22-dbt-labs-pr-template.md @@ -0,0 +1,255 @@ +--- +title: "The Exact GitHub Pull Request Template We Use at dbt Labs" +description: "Having a GitHub PR template is one of the most important and frequently overlooked aspects of creating an efficient and scalable dbt-centric analytics workflow." +slug: analytics-pull-request-template + +authors: [jess_williams] + +tags: [data ecosystem] +hide_table_of_contents: false + +date: 2021-11-29 +is_featured: false +--- + +Having a GitHub pull request template is one of the most important and frequently overlooked aspects of creating an efficient and scalable dbt-centric analytics workflow. Opening a pull request is the final step of your modeling process - a process which typically involves a lot of complex work! + +For you, the dbt developer, the pull request (PR for short) serves as a final checkpoint in your modeling process, ensuring that no key elements are missing from your code or project. + + + +For the reviewer, it lets them know what it is they are reviewing before laying eyes on any code. Most importantly, the PR template sets a standard for your team so that PRs can be both submitted and reviewed with ease. + +On dbt Labs’ Professional Services team, our [analytics engineers](https://getdbt.com/what-is-analytics-engineering/) frequently work in pairs on client projects, meaning two AEs are writing and reviewing PRs against the same repo. + +Now imagine you are paired with 2-3 different people on 2-3 projects. Absent some structure, the chances of everyone following thorough and repeatable PR writing/review processes is extremely slim. + +Let’s jump into the exact PR template we use internally at dbt Labs. + + +## The GitHub PR template we use + + + +Our PR template ([view markdown file in GitHub](https://github.com/dbt-labs/dbt-init/blob/master/starter-project/.github/pull_request_template.md)) is composed of 6 sections: + +* Description & motivation +* To-do before merge (optional) +* Screenshots +* Validation of models +* Changes to existing models +* Checklist + +### How and why this GitHub PR template works + +Having each of these sections written down significantly limits the communication overhead on our team, and limits the chances of us shipping low-quality analytics code. Let's explore how to use each section and its benefits. + +#### Description & motivation: + +This is the intro to your PR and should allow the reviewer to quickly be able to understand the reason for opening this PR. If your actual code is the “how”, the description is the “what” and “why.” As an example from a recent project: + +> Example: This PR updates the channel mapping for Google Adwords data based on this Google Sheet. This mimics the mapping used for sessions and will be used in our final attribution modeling to look at ROAS. + +> This PR also adds a stg table for the `final_url_report` from Adwords. This is currently only being used to map `utm_medium` and `utm_source` to `campaign_id` and `ad_group_id` to then derive a channel. This is not yet being used as an input to the Adwords package due to limitations in the data that is configured and available via Adwords. We may choose to incorporate that later. + +> The main purpose of this PR was to update the channel mapping for an attribution model. I could have quickly written “updated channel mapping” and called it a day. But, knowing that I would likely need to reference this mapping again at some point in the future, I added this link to the google sheet where we initially built the mapping. + +Remember, you know more about this PR **right now** than you will in a couple of months. If you or your team ships 30+ PRs and need to go back to one of those early ones to reference something, you’re going to be bummed when your description says “added a model”. + + +#### Screenshots: + +This is where we add the relevant sections from our DAG! This is one of my favorite features of dbt, as I’m a very visual learner. So when I open a PR, I take a quick look at the relevant sections of the DAG (aka dependency graph) to help me conceptualize the modeling. + +![dbt dag check](/img/blog/pr-template-dag-check.png "dbt DAG check") + +Checking for things like modularity and 1:1 relationships between sources and staging models is much easier done visually via the DAG than trying to look at code and visualize the relationships. + +> Note: my colleagues Christine Berger + Randy Pitcher published an excellent walkthrough of [modular data modeling technique](https://www.getdbt.com/analytics-engineering/modular-data-modeling-technique/) if you’re interested in learning more. + + +#### Validation of models: + +This section should show something to confirm that your model is doing what you intended it to do. This could be a [dbt test](https://docs.getdbt.com/docs/building-a-dbt-project/tests) like uniqueness or not null, or could be an ad-hoc query that you wrote to validate your data. Here is a screenshot from a test run on a local development branch: + +![test validation](/img/blog/pr-template-test-validation.png "dbt test validation") + +Adding uniqueness tests shows that you have put thought into the of each of your models, and then ensures that those assumptions hold true over time. + +By including a screenshot of your dbt test run here, you are confirming that you have done the work. + +#### Changes to existing models: + +This is a place to leave post-merge instructions. Maybe you updated your existing [incremental model](https://docs.getdbt.com/docs/building-a-dbt-project/building-models/configuring-incremental-models) with an additional column and need to run a [full refresh](https://docs.getdbt.com/docs/building-a-dbt-project/building-models/configuring-incremental-models#how-do-i-rebuild-an-incremental-model). + +Or, maybe you have a corresponding PR for your BI tool that needs to be merged to accommodate your dbt modeling changes. + + +#### Checklist: + +The launch checklist is probably the most important piece of the PR template—it ensures that you’ve followed the QC steps required to push your PR into production. + +**My pull request represents one logical piece of work:** + +Each PR should represent a cohesive body of work—a specific fct model, or staging a particular data source. If you’re having trouble narrowing down and describing **_the thing_** your PR does, it may be too broad. + +This also makes things much easier on your reviewer. Reviewing a PR with multiple, unrelated concepts is extremely challenging and time consuming. + +**My commits are related to the pull request and look clean.** + +Think of yourself! What if you need to roll back a change, but in a moment of post-coding fogginess, you made a massive commit of unrelated concepts that “updated all the things”. Woof. + +![woof](/img/blog/pr-template-woof.gif "woof") + +**My SQL follows the [dbt Labs style guide](https://github.com/dbt-labs/corp/blob/master/dbt_style_guide.md).** + +By standardizing the way your team writes code, your reviewer is able to spend less time picking apart each team member’s individual styling nuances and more time reviewing the actual code. + +**I have added appropriate tests and documentation to any new models.** + +By default, all new models should have _at least_ unique and not null tests on the . + +Documentation follows the same reasoning as the PR description. You will know more **right now** about the intricacies of these models than you will after you’ve developed 50 more models in the coming months. + +**I have [materialized my models](https://docs.getdbt.com/docs/building-a-dbt-project/building-models/materializations) appropriately.** + +This is all about performance. Our ultimate goal is to model data such that end users can easily and efficiently query the resulting database objects. + +![choose your materializations wisely](/img/blog/pr-template-fct-meme.jpeg "choose your materializations wisely") + + +**I have updated the README file.** +Last but not least, the README. This doesn’t need to be updated with every single PR. + +In general, your README contains information about things such as how to get going with contributing to your dbt project, who to go to for database access, additional development resources, etc. If any of this changes as a result of your PR, make sure to update the README! + + +## Adding the full GitHub PR template to your repository + +If you haven’t already picked it up from GitHub, the full markdown code of the dbt Labs PR template is below. After copying the PR template to your clipboard, let's walk through how to add it to your repository. + +``` + +<!--- + +Provide a short summary in the Title above. Examples of good PR titles: + +* "Feature: add so-and-so models" + +* "Fix: deduplicate such-and-such" + +* "Update: dbt version 0.13.0" + +--> + +## Description & motivation + +<!--- + +Describe your changes, and why you're making them. Is this linked to an open + +issue, a Trello card, or another pull request? Link it here. + +--> + +## To-do before merge + +<!--- + +(Optional -- remove this section if not needed) + +Include any notes about things that need to happen before this PR is merged, e.g.: + +- [ ] Change the base branch + +- [ ] Update dbt Cloud jobs + +- [ ] Ensure PR #56 is merged + +--> + +## Screenshots: + +<!--- + +Include a screenshot of the relevant section of the updated DAG. You can access + +your version of the DAG by running `dbt docs generate && dbt docs serve`. + +--> + +## Validation of models: + +<!--- + +Include any output that confirms that the models do what is expected. This might + +be a link to an in-development dashboard in your BI tool, or a query that + +compares an existing model with a new one. + +--> + +## Changes to existing models: + +<!--- + +Include this section if you are changing any existing models. Link any related + +pull requests on your BI tool, or instructions for merge (e.g. whether old + +models should be dropped after merge, or whether a full-refresh run is required) + +--> + +## Checklist: + +<!--- + +This checklist is mostly useful as a reminder of small things that can easily be + +forgotten – it is meant as a helpful tool rather than hoops to jump through. + +Put an `x` in all the items that apply, make notes next to any that haven't been + +addressed, and remove any items that are not relevant to this PR. + +--> + +- [ ] My pull request represents one logical piece of work. + +- [ ] My commits are related to the pull request and look clean. + +- [ ] My SQL follows the style guide. + +- [ ] I have materialized my models appropriately. + +- [ ] I have added appropriate tests and documentation to any new models. + +- [ ] I have updated the README file. + +{%- if project.warehouse == 'redshift' %} + +- [ ] I have added sort and dist keys to models materialized as tables. + +- [ ] I have validated the SQL in any late-binding views. + +{% endif %} + +``` + +### Create a markdown file + +Copy the full PR template text above and copy it into your favorite text editor. Once you’ve done that, export the document as an `.md` file. + +### Add the `.md` file to your GitHub repository + +Now that you have your pull request template markdown file, navigate to the main page of your repository on GitHub. Above the list of files, using the **Add file** dropdown, click on **Create new file**. + +Once the file is added, name it whatever you want to make it clear that it’s your pull request template. A good name for the file might be `pull_request_template.md`. + +### And that’s it! + +With that, you now have a pull request template in your GitHub repository that can help your team follow analytics engineering best practices. + +To dive deeper into how we use it as part of the analytics engineering workflow, check out the free [dbt Fundamentals on-demand course](https://courses.getdbt.com/courses/fundamentals). diff --git a/website/blog/2021-11-22-exact-commands-we-run-in-production.md b/website/blog/2021-11-22-exact-commands-we-run-in-production.md new file mode 100644 index 00000000000..350afa45052 --- /dev/null +++ b/website/blog/2021-11-22-exact-commands-we-run-in-production.md @@ -0,0 +1,116 @@ +--- +title: "The Exact dbt Commands We Run in Production" +description: "Without a command to run them, dbt models and tests are just taking up space in a Git repo. These are the exact dbt commands we run internally at dbt Labs." +slug: dbt-production-commands + +authors: [andrew_escay] + +tags: [dbt tutorials] +hide_table_of_contents: false + +date: 2021-11-29 +is_featured: false +--- + +Without a command to run them, dbt models and tests are just taking up space in a Git repo. + +The specific dbt commands you run in production are the control center for your project. They are the structure that defines your team’s data quality + freshness standards. + + + +> _Note: As of dbt v0.21.0 (released in October 2021), you can now set your preferred production commands using [`dbt build`](https://github.com/dbt-labs/dbt-core/releases). Once setup, a single `dbt build` command can be used to execute your prescribed `seed`, `test`, `run` and `snapshot` and other commands in a specified order._ + +The most important command is [`dbt run`](https://docs.getdbt.com/reference/commands/run). But in deployment, we rarely just use `dbt run`. + +You’re probably familiar with a bunch of [dbt commands](https://docs.getdbt.com/reference/dbt-commands) already, and this section is dedicated to showing you what we believe the most effective commands should be when running your dbt project in production! + +In production, reliability and consistency are key. This guarantees that your stakeholders have data that could be meaningfully used. In order to ensure reliability and consistency, here are a few principles we believe you should keep in mind when designing your deployment commands: + +## Principles of dbt deployment commands + + + +### 1) Always test your data + +You’re likely already familiar with testing in dbt, and we believe that every production run should always be tested. + + +### 2) Understand the impact of delayed data in your project + +Some projects can afford to have older data in the warehouse, others can’t. + + +### 3) Simplify your regularly scheduled runs + +The more complex your run commands are, the harder it gets to maintain this in the long run. Feel free to rely on dbt’s DAG (more info on why we <3 DAGs in my colleagues Christine + Randy’s [modular data modeling technique](https://getdbt.com/analytics-engineering/modular-data-modeling-technique/) post). + +Given those principles, we’ll now take a look at the most common run commands for production jobs, and why we think they could work for your organization! Do note that yours may vary slightly (depending on your team’s specific needs), but as long as you stick to the principles mentioned above, your project should be in good shape! + + +## Simplest possible production dbt commands + +The simplest version of your project’s scheduled run commands could be: + +``` + +dbt run + +dbt test + +``` + +This version is the most basic and adheres to all the principles mentioned above. This assumes that you can afford to have slightly incorrect data (data is only tested after a dbt project runs). + + +## Preferred production dbt commands + +In practice however, we often find that this is more effective: + +``` + +dbt test -s source:* (or dbt test -m source:* if you are on a version earlier than dbt v0.21.0) + +dbt run + +dbt test --exclude source:* + +dbt source `freshness ` (or dbt source snapshot-freshness if you are on a version earlier to dbt v0.21.0) (this could optionally be the first step) + +``` + +This is a more robust implementation of the first version. The two additions here would be: + + + +1. Testing source data before running any dbt transformation, and +2. Testing source freshness + +When you test source data before running transformations, this removes the possibility of bad source data affecting the dbt project. + +This will stop the build process if bad source data is detected, and protects the integrity of your dbt models. + +When sources are tested for freshness, it allows you to easily triage whether data in your warehouse is old, and subsequently alert relevant stakeholders. + +You could also opt to run your source freshness test at the beginning, if your organization would prefer that stale data isn’t processed, or if you believe that stale data could lead to unreliable final models. + + +## Pro trip: beware of model selectors + +First, I want to quickly cover the topic of using [model selectors](https://docs.getdbt.com/reference/node-selection/syntax) (`-s` for specific models/tags/folders, or `-m` if you’re on a version prior to dbt v0.21.0) in your run commands. You may already know how to run specific models and subsequently their parent or child models. + +When building production jobs, we highly advise not relying on these, as it adds to the complexity of your project, and is prone to creating mismatched timings in your build steps. + +The way to think about model selectors in runs is more of an exception, rather than the default. It’s best to start with a single main job that runs at a consistent cadence. From there, assess whether specific parts of your dbt project need specific handling for optimization. + +Maybe some models only require updating once a week, while everything else needs to be updated every hour. Maybe some teams need data at a specific time of the day, and thus need their models to be run at a specific time in the morning. + +These exceptions justify having separate run commands, and even a separate job, but make sure to exercise caution when building these as they could easily become difficult to manage in the long run. + + +## How do your run commands differ? + +These are the dbt commands that our team runs in production, and we recommend to our professional services clients. + +But! Your mileage will vary, and there are perfectly good reasons for running other commands in production—I’m always curious to see what works best for your team. + +As long as you remember the core principles I shared earlier (mostly keep things simple), you’ll be in great shape. diff --git a/website/blog/2021-11-22-primary-keys.md b/website/blog/2021-11-22-primary-keys.md new file mode 100644 index 00000000000..0467565ee28 --- /dev/null +++ b/website/blog/2021-11-22-primary-keys.md @@ -0,0 +1,143 @@ +--- +title: "What's a Primary Key and Why Do We Test Them?" +description: "Let’s dive deep into: what primary keys are, which cloud analytics warehouses support them, and how you can test them in your warehouse to enforce uniqueness" +slug: primary-key-testing +authors: [sanjana_sen,jason_ganz,david_krevitt] + +tags: [sql magic] +hide_table_of_contents: false + +date: 2021-11-29 +is_featured: true + +--- + +We’ve all done it: fanned out data during a join to produce duplicate records (sometimes duplicated in multiple). + +That time when historical revenue numbers doubled on Monday? Classic fanout. + +Could it have been avoided? Yes, very simply: by defining the uniqueness for a with a primary key and enforcing it with a dbt test. + +So let’s dive deep into: what primary keys are, which cloud analytics warehouses support them, and how you can test them in your warehouse to enforce uniqueness. + + + + + +## What’s a primary key? + +A is a column in your database that exists to uniquely identify a single row. + +Primary keys are _critical_ to data modeling. Without a primary key, you’ll find yourself constantly struggling to identify duplicate rows and define the expected grain of your tables. + +There is just about no more ironclad law in the land of analytics than `you must have a primary key on every table`. + + +## Why do we test primary keys? + +But what happens when blank or duplicate data finds its way into your primary keys? As I mentioned up top, it can create quite a firedrill. + +Invalid data getting into your primary keys is one of _the_ biggest data problems - it can lead to rows getting dropped or miscounted and for all kinds of weird results to pop into your data. It’s one of the most common causes of time-sensitive headaches in analytic-land. + +This is, of course, what makes your primary keys so powerful. See, most of the time that primary keys get messed up, they do so because: + +* There are rows where the primary key is null +* There are rows where the primary key is not unique (duplicate values) + +As you’ll see below in the “warehouse support for PKs” section, while some warehouses allow you to define primary keys, but will not enforce either not-nullness or uniqueness on values. So, we test. + +In the days before testing your data was commonplace, you often found out that you had issues in your primary keys by you (or worse, your boss) noticing that a report was off. This has lead to a lot of unnecessary angst and loss of trust in data. + + +## How to test primary keys with dbt + +Today, you can add two simple [dbt tests](https://docs.getdbt.com/docs/building-a-dbt-project/tests) onto your primary keys and feel secure that you are going to catch the vast majority of problems in your data. + +Not surprisingly, these two tests correspond to the two most common errors found on your primary keys, and are usually the first tests that teams testing data with dbt implement: + + + +* [Not_null](https://docs.getdbt.com/reference/resource-properties/tests#not_null) +* [Unique](https://docs.getdbt.com/reference/resource-properties/tests#unique) + +These tests are specified inline in your models’ .yml configuration files, so you can define a batch of tests across models from one file. Put together, a `not_null` + `unique` test would look like so: + +``` + +models: + + - name: orders + + columns: + + - name: order_id + + tests: + + - unique + + - not_null + +``` + +It really is as simple as adding those two tests to the primary keys of all of your tables, and then you have a built-in safeguard against bad data in your primary keys. + +Having tests configured and running in production using the [`dbt test`](https://docs.getdbt.com/reference/commands/test) command unlocks your ability to do things like [send Slack alerts](https://docs.getdbt.com/docs/dbt-cloud/using-dbt-cloud/cloud-slack-notifications) on test failures, so you’ll be the first to know when PK issues arise. + + +## Does your warehouse support primary keys? + +Does your warehouse even _support_ primary keys at all? If it does, how can you actually find out if a table has a primary key set, and what that primary key is? + +Let’s walk through primary key support + access across the major cloud platforms. + + +### TL;DR on primary key support across warehouses + +BigQuery + Databricks don’t support primary keys, Redshift + Snowflake support primary keys but don’t enforce them fully, and Postgres fully supports + enforces primary keys. + +This means that across major analytics warehouses, _data testing_ (using a tool like dbt) to enforce your primary keys is super important for ensuring analytics data quality. + +Redshift, Snowflake and Postgres allow you to query primary key column lists from your database’s information schema tables. Read on for the gritty details + links to appropriate docs. + + +### BigQuery primary keys + +BigQuery does not have a concept of primary key constraints for tables, so instead you’ll want to use [surrogate keys](/blog/sql-surrogate-keys) in dbt to define your primary key for a table. + + +### Databricks primary keys + +Databricks Delta SQL does not support primary keys in a classic SQL sense, and instead offers what they call [constraints](https://docs.databricks.com/delta/delta-constraints.html) for fields (`not null` being one of them). + +Similarly to BigQuery, surrogate keys can be used to get around this limitation. + + +### Redshift primary keys + +Amazon Redshift allows you to set primary keys as a [table constraint](https://docs.aws.amazon.com/redshift/latest/dg/t_Defining_constraints.html) (which helps with query optimization), however these constraints are not actually enforced by the warehouse itself. + +You can then query these constraints out of the `information_schema.table_constraints` + `information_schema.key_column_usage` tables. + +It’s ultimately up to you to check for uniqueness + not null-ness in your data, to ensure that your table constraints are actually enforced (see testing section at the bottom of this post). + + +### Snowflake primary keys + +Snowflake supports a command of [SHOW PRIMARY KEYS](https://docs.snowflake.com/en/sql-reference/sql/show-primary-keys.html), which allows you to query out primary keys for your tables. + +Note that Snowflake primary keys are purely declarative--neither uniqueness nor non-nullness constraints are enforced. However, Snowflake supports a separate `not null` constraint that can be applied to column that is enforced. Regardless, you'll still want to ensure your primary key column values are actually unique (see testing section at the bottom.) + + +### Postgres primary keys + +Postgres does fully support primary keys, meaning it enforces uniqueness and not null constraints on tables with primary keys. + +This makes a ton of sense given Postgres’ primary use as an application database, where primary keys *really* need behave like primary keys, as opposed to the data warehouses above that aren’t generally being used to power applications. + +You can query out primary key columns from the `pg_index` and `pg_attribute` admin tables. + + +## Have you started testing primary keys yet? + +If you’re looking for a deeper dive on testing primary keys, definitely check out the [dbt Fundamentals course](https://courses.getdbt.com/courses/fundamentals), which includes a full section with examples + practice on data testing in dbt. diff --git a/website/blog/2021-11-22-sql-surrogate-keys.md b/website/blog/2021-11-22-sql-surrogate-keys.md new file mode 100644 index 00000000000..05422ba3506 --- /dev/null +++ b/website/blog/2021-11-22-sql-surrogate-keys.md @@ -0,0 +1,186 @@ +--- +title: "Generating Surrogate Keys Across Warehouses" +description: "What's a surrogate key, and how can you generate them across BigQuery, Databricks, Redshift, Snowflake and other data warehouses?" +slug: sql-surrogate-keys +authors: [sanjana_sen,jason_ganz,david_krevitt] + +tags: [sql magic] +hide_table_of_contents: false + +date: 2021-11-29 +is_featured: false +--- + +### Why primary keys are important + +We all know one of the most fundamental rules in data is that every should have a . Primary keys are critical for many reasons: + +* They ensure that you don’t have duplicate rows in your table +* They help establish relationships to other tables +* They allow you to quickly identify the of the table (ex: the `customers` table with a PK of `customer_id` has one row per customer) +* You can test them in dbt, to ensure that your data is complete and unique + + + +If you are lucky, your data will come to you with a unique primary key already in place. Maybe it is an `id` generated by your internal product systems, or maybe you are pulling data in from a third party source that generates the id for you. + +Sometimes, however, you find yourself in a situation where you don’t have a natural [primary key](/blog/primary-key-testing). + +For example, maybe you have joined your users to the set of features that they use in your product, such that your data should be expected to be unique on the `user_id` + `product_id` basis. + +The question is - in this situation, how are you supposed to set a primary key? Meet the _surrogate key_. + + + +### What’s a surrogate key? + +A surrogate key is a primary key that, instead of existing in your underlying dataset, is _derived in the analytics layer itself._ + +Learning when to use surrogate keys and bring them into your project is a critical skill for any analytics professional. + +Knowing when to use a surrogate key is actually quite easy: you should have a surrogate key on any table that doesn’t already have a unique primary key. + +Knowing _how_ to create a surrogate key can prove to be much more challenging. The reason for this is that it isn’t always easy to know the best way to implement surrogate keys. Should you just be blocking off time on your calendar every day to individually name each of your rows? + +Turns out this is a relatively well-solved problem. To create a surrogate key, you traditionally follow these two steps. + +1. Concatenate together all of the fields required to make a unique row (for example, `user_id` and `product_id`) +2. Apply a function to create a cryptographic hash (usually using the [md5 function](https://blog.getdbt.com/the-most-underutilized-function-in-sql/)) on top of these to generate a unique id per combination of unique values + +While the process of creating a surrogate key is relatively well understood, you will be shocked (SHOCKED I SAY) to hear that SQL syntax can have subtle differences across dialects and databases. + +#### Surrogate keys in BigQuery, Databricks, Redshift and Snowflake + +[BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/string_functions#concat), [Redshift](https://docs.aws.amazon.com/redshift/latest/dg/r_CONCAT.html) and [Snowflake’s](https://docs.snowflake.com/en/sql-reference/functions/concat.html) concat functions returns null if any of the referenced columns for that row returns a null, so to create a proper surrogate key you’d need to wrap each column in a `coalesce` before hashing with an md5 function: + +```sql +md5 ( concat ( coalesce(column1, ''), coalesce(column2, '') ) ) +``` + +[Databricks](https://docs.databricks.com/sql/language-manual/functions/concat.html)’ concat function docs don’t specifically reference returning null for the concat if one column is null, but I believe that’s what’s meant by `The result type matches the argument types`. + +You could also separate your columns with pipes (`||`) rather than using the concat function, but I generally stay away from pipes (one comma > two pipes). + + +#### Surrogate keys in Postgres + +Postgres’ `concat` function ignores nulls, which saves you from having to wrap each column in a `coalesce` function to default nulls to blank. + +If you used `||` instead of `concat`, one _null_ column would cause the entire statement would return a null, breaking your concatenation. . + +So in plain old PostgreSQL, you’d use: + +```sql +md5 ( concat (column1, column2) ) +``` + + +#### The null value problem in surrogate keys +The primary annoyance when creating surrogate keys comes when you try and concatenate a row that has a null value for one or more columns. If any value is null, then often the entire concatenated string is returned as null - no good! +```sql +with + +example_ids as ( + 123 as user_id, + 123 as product_id + + union all + + select + 123 as user_id, + null as product_id + + union all + + select + null as user_id, + 123 as product_id + +) + +select + *, + concat(user_id, product_id) as _surrogate_key +from example_ids +``` +output: + +| USER_ID | PRODUCT_ID | _SURROGATE_KEY | +|---------|------------|----------------| +| 123 | 123 | 123123 | +| 123 | `null` | `null` | +| `null` | 123 | `null` | + + +You can get around this by wrapping each of your columns in a `coalesce` function to default nulls to blank (''), which is pretty tedious. You can also run into problems if the fields are different datatypes (string vs numeric), so sometimes you need to cast as well. + +```sql +... +select + *, + concat( + coalesce(cast(user_id as string), ''), + coalesce(cast(product_id as string), '') + ) as _surrogate_key +from example_ids +``` +output: + +| USER_ID | PRODUCT_ID | _SURROGATE_KEY | +|---------|------------|----------------| +| 123 | 123 | 123123 | +| 123 | `null` | 123 | +| `null` | 123 | 123 | + +At first glance, this looks like it works, but in reality, there should be three unique IDs and instead, there are two: `123123` & `123`, which could be a problem in the off chance there is any potential overlap in the sequencing used by the two IDs. + +To remedy this, you need to add a separator between fields you wish to concatenate. + +```sql +... +select + *, + concat( + coalesce(cast(user_id as string), ''), + '|', + coalesce(cast(product_id as string), '') + ) as _surrogate_key +from example_ids +``` +output: + +| USER_ID | PRODUCT_ID | _SURROGATE_KEY | +|---------|------------|----------------| +| 123 | 123 | 123\|123 | +| 123 | `null` | 123\| | +| `null` | 123 | \|123 | + + +Let’s take a look at how generating surrogate keys specifically looks in practice across data warehouses, and how you can use one simple dbt macro ([dbt_utils.surrogate_key](https://github.com/dbt-labs/dbt-utils#surrogate_key-source)) to abstract away the null value problem. + + +### A surrogate_key macro to the rescue + +Thanks to a handy function called [surrogate_key](https://github.com/dbt-labs/dbt-utils#surrogate_key-source) in the [dbt_utils package](https://hub.getdbt.com/dbt-labs/dbt_utils/latest/), you can fire yourself from the business of wrapping your columns in `coalesce` every time you want to generate a surrogate key. + +Forming your surrogate keys with this macro has the benefit of **elegant + null handling**. + +Rather than wrapping your columns in a `coalesce` function when concatenating them, the macro loops through your columns and _coalesces_ on your behalf, so that you can avoid repeating yourself. + +When you call `{{ dbt_utils.surrogate_key(['field_a', 'field_b'[,...]]) }}`, behind the scenes dbt compiles SQL on your behalf, looping through each field and generating the correct number of `coalesce` statements with type casting: + +```sql + coalesce(cast(" ~ field ~ " as " ~ dbt_utils.type_string() ~ "), '') +``` + +and with conditional logic, adding separator between fields: + +```sql + {%- if not loop.last %} + {%- set _ = fields.append("'-'") -%} + {%- endif -%} +``` + +What does this mean in practice? + +Well, you simply don’t have to think about your surrogate keys all that much. On any data warehouse, nulls or no nulls, it just works. Because honestly, who wants to spend more time than they need to thinking about surrogate keys? diff --git a/website/blog/2021-11-23-how-to-upgrade-dbt-versions.md b/website/blog/2021-11-23-how-to-upgrade-dbt-versions.md new file mode 100644 index 00000000000..87b3ea7bd1e --- /dev/null +++ b/website/blog/2021-11-23-how-to-upgrade-dbt-versions.md @@ -0,0 +1,179 @@ +--- +title: "How to Upgrade dbt Versions (Mostly) Without Fear" +description: "Upgrading your dbt project can be daunting – you rely on dbt to power your analytics workflow and can’t afford to change things just to discover that your daily run doesn’t work anymore. I’ve been there. This is the checklist I wish I had when I owned my last company’s dbt project." +slug: upgrade-dbt-without-fear + +authors: [joel_labes] + +tags: [dbt tutorials] +hide_table_of_contents: false + +date: 2021-11-29 +is_featured: true +--- + +As we get closer to dbt v1.0 shipping in December, it's a perfect time to get your installation up to scratch. dbt 1.0 represents the culmination of over five years of development and refinement to the analytics engineering experience - smoothing off sharp edges, speeding up workflows and enabling whole new classes of work. + +Even with all the new shinies on offer, upgrading can be daunting – you rely on dbt to power your analytics workflow and can’t afford to change things just to discover that your daily run doesn’t work anymore. I’ve been there. This is the checklist I wish I had when I owned my last company’s dbt project. + + + +This guide covers the steps to safely upgrade, using a hypothetical project as a case study. The project uses dbt v0.16.0 and is relatively mature. It contains a couple of hundred models and uses a wide swathe of dbt functionality - custom tests, macros from dbt-utils, and snapshots to capture changes in critical business data. + +We’ll walk through the steps to upgrade from 0.16.0 to 0.17.2, but the same principles apply regardless of the migration you’re making. The steps of the process boil down to: + +1. Decide which version you are upgrading to + +2. Add `require-dbt-version` to your `dbt_project.yml` file + +3. Upgrade dbt + +4. Try to run `dbt compile` + +5. Handle any deprecations + + 1. Update your packages + + 2. Fix errors, then warnings + + 3. Rinse and repeat until all errors and warnings are resolved + +6. Test and review + +7. Merge and communicate + +>ℹ️ If you're not clear on the difference between major, minor and patch versions, it'd be useful to [read Jeremy's blog post](https://blog.getdbt.com/getting-ready-for-v1-0/) first which includes a primer on semantic versioning. + +## Step 1: Decide which version you are upgrading to + +Key principles: + +* Only move up one or two minor versions at a time. + +* Update to the most recent patch version of a given minor version. + +* Read the migration guide in advance. + +As noted above, the project is on 0.16.0 right now. 0.17.2 is the final patch release of the next minor version, so we’ll be upgrading to that. + +>❓ Why not an earlier patch? 0.17.0 introduced a breaking change that was reverted in a later release; let's jump straight to the most stable version of 0.17 instead of stepping through each bugfix release +> +> If that's the logic for patch versions, why not leap all the way to dbt 0.21 or 1.0 in one hit? In short: **reduced risk**. Dealing with deprecations and behaviour changes one at a time makes it easier to pinpoint the cause of an issue. +> +> Practically, it also lets you lock in "checkpoints" of known-stable setups. If you need to pause your migration work to deal with an urgent request, you can safely deploy what you've finished so far instead of having a bunch of unrelated half-finished changes. + +Review the migration guides to get an initial indication of what changes you might need to make. For example, in [the migration guide for 0.17.0](/guides/migration/versions), there are several significant changes to dbt's functionality, but it's unlikely that all of them will apply to your project. We'll cover this more later. + +## Step 2: `Add require-dbt-version` to your `dbt_project.yml` file. + +Key principles: + +* Stop your colleagues from accidentally staying on an old version. + +Your `dbt_project.yml` file lets you prevent users from running your dbt project with an unsupported version of dbt Core. If your project already has this configuration, update it. If not, add it in like this: + +```yml +#/dbt_project.yml + +name: 'your_company_project' + +version: '0.1.0' + +require-dbt-version: ">=0.17.2" + +... +``` + +You can add an upper bound of supported versions like this: `[">=0.20.0", "<=1.0.0"]`, but for an internal analytics project it's probably overkill. Fun fact: this upper bound is how package vendors stop users from accidentally using an old version of a package like dbt-utils - more on this in a bit! + +## Step 3: Upgrade dbt + +If you use dbt Cloud, you can upgrade [as described here](https://docs.getdbt.com/docs/dbt-cloud/cloud-configuring-dbt-cloud/cloud-choosing-a-dbt-version). We recommend that you [create a second "sandbox" project](https://docs.getdbt.com/docs/dbt-cloud/cloud-configuring-dbt-cloud/cloud-upgrading-dbt-versions#testing-your-changes-before-upgrading), so that your experimentation doesn’t impact the rest of the team. For dbt Core, upgrade instructions will vary based on your [original installation method](https://docs.getdbt.com/dbt-cli/installation). + +## Step 4: Try to run `dbt compile` + +Key principles: + +* Check that your version has increased as you expect. + +* Quickly identify backwards incompatible changes which need to be resolved. + +`dbt compile` is the quickest way to validate that the upgrade succeeded. If you are still on 0.16.0, your `require-dbt-version` constraint will reject the command. + +Compiling your project will also validate that your project is valid while interacting with the database as little as possible, so you don't need to wait for queries' results. + +## Step 5: Handle any deprecations + +Key principles: + +* Update packages first - there's no point in worrying about code that someone else has already fixed. + +* Fix errors, then warnings. + +* Stay focused: don't try to refactor logic "while you're there". + +* Repeat until there are no errors left. + +### Step 5a. Update your packages + +The easiest migrations are those that someone else did for you. By installing an updated package, you'll get rid of a host of errors immediately. + +>ℹ️ As hinted at above, most packages have an upper bound of dbt version compatibility as well as a lower bound. Treating future versions of dbt Core as incompatible with a package until proven otherwise is a defensive approach common prior to dbt Core v1.0's release. Once the API stabilises in v1.0, the upper boundaries will be able to loosen, making upgrades easier. + +In this case, our example project probably has dbt 0.3.0 installed. By reviewing the [dbt-utils x dbt-core compatibility matrix](https://docs.google.com/spreadsheets/d/1RoDdC69auAtrwiqmkRsgcFdZ3MdNpeKcJrWkmEpXVIs/edit#gid=0), we see that both 0.4.1 and 0.5.1 are compatible with dbt Core v.0.17.2. The same principles apply for packages as dbt Core versions - install the latest patch release, and don't jump too far ahead in one go. Since there are no breaking changes in 0.4.x, we can safely move to 0.5.1. + +>⚠️ Remember to run [`dbt clean`](https://docs.getdbt.com/reference/commands/clean) and [`dbt deps`](https://docs.getdbt.com/reference/commands/deps) after updating your `packages.yml` file! + +### Step 5b. Fix errors, then warnings + +Obviously, errors that stop you from running your dbt project at all are the most important to deal with. Let's assume that our project used a too-broadly-scoped variable in a macro file, support for which was removed in v0.17. The [migration guide explains what to do instead](/guides/migration/versions), and it's a pretty straightforward fix. + +Once your errors are out of the way, have a look at warnings. For example, 0.17 introduced `config-version: 2` to `dbt_project.yml`. Although it's backwards compatible for now, we know that support for the old version will be removed in a future version of dbt so we might as well deal with it now. Again, the migration guide explains [what we need to do](/guides/migration/versions), and how to take full advantage of the new functionality in the future. + +### Stay focused + +It might be tempting to update all of your `whatever.yml` files to use the new syntax, or totally rewrite an old macro that depended on a broadly scoped variable "while you're there". Suppress this urge! The primary goal is to get everything upgraded more or less in-place. As you come across things that could be done in a more elegant fashion, make a note to come back to them at the end of your migration journey. + +You want to make your code review as easy as possible when the time comes to merge your work back into the main branch. Combining refactors with compatibility updates is a sure-fire way to confuse your reviewer. For more discussion on this topic, check out the Netlify team's writeup of [moving from one warehouse to another](https://www.netlify.com/blog/2021/08/10/how-the-netlify-data-team-migrated-from-databricks-to-snowflake/) which touches on the same principles. + +### Step 5c. Rinse and repeat + +This part of the process is an iterative loop. As you fix each error, run dbt compile again to identify any new issues. For example, until you upgrade dbt-utils from 0.3.0 to 0.5.1, your project won't even start to compile because of the `require-dbt-version` mismatch. Once that's fixed, new issues might appear. + +## Step 6. Test and review + +Key principles: + +* Complete a full `dbt run` and `dbt test`. + +* Update your CI job's dbt version. + +* Review your Slim CI configuration. + +* Open a PR. + +Once your compilation issues are resolved, it's time to run your job for real, to make sure that everything works from end to end. It's unlikely that a dbt version change will cause any runtime errors with your SQL, so you should feel confident going into this stage that the end is near. + +After that, make sure that your CI environment in dbt Cloud or your orchestrator is on the right dbt version, then open a PR. + +If you're using [Slim CI](https://docs.getdbt.com/docs/guides/best-practices#run-only-modified-models-to-test-changes-slim-ci), keep in mind that artifacts aren't necessarily compatible from one version to another, so you won't be able to use it until the job you defer to has completed a run with the upgraded dbt version. This doesn't impact our example because support for Slim CI didn't come out until 0.18.0. + +## Step 7. Merge and communicate + +Key principles: + +* 🎉 You did it! + +* Make sure everyone knows that you did it, or they'll hit an error next time they run. + +* Update your production environment's dbt version. + +* Move onto the next upgrade while you're on a roll. + +Merge your upgrade branch into your main branch, and then make sure your colleagues in turn pull main into their development branches and update their local environments. + +>⚠️ Remember to also update your production environment! + +>💡 If you're moving through multiple versions, you might like to wait and have your colleagues update their development environments in one go. + +Thanks to [Claire](https://twitter.com/clairebcarroll) and [Winnie](https://twitter.com/gwenwindflower) for their help in developing this post 💕 diff --git a/website/blog/2021-11-23-on-the-importance-of-naming.md b/website/blog/2021-11-23-on-the-importance-of-naming.md new file mode 100644 index 00000000000..05cc5c597b9 --- /dev/null +++ b/website/blog/2021-11-23-on-the-importance-of-naming.md @@ -0,0 +1,118 @@ +--- +title: "On the Importance of Naming: Model Naming Conventions (Part 1)" +description: "Naming our models is one of the hardest and most important tasks of the analytics engineer. This post walks through the reasons that we should focus on naming as a key part of the process of building data models." +slug: on-the-importance-of-naming + +authors: [pat_kearns] + +tags: [analytics craft] +hide_table_of_contents: false + +date: 2021-11-29 +is_featured: false +--- + +💾 _This article is for anyone who has ever questioned the sanity of a date not in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) format_ + + +Have you ever been assigned to add new fields or concepts to an existing set of models and wondered: + +* Why are there multiple models named almost the same but slightly different? + +* Which model has the fields I need? + +* Which model is upstream or downstream from which? + + + +* If I am going to add to those models, should I add it here or there (or over there)? + +Someone on the data team might send you a list of models and say "It is in one of these models, but I am not sure which" + +``` + +* users + +* user_dimensions + +* user_properties + +* dim_users_attributed + +* dim_users_revenue_attributed + +``` + +This is a common problem when multiple developers (both past and present) are cohabitating in a project repo, continually creating new combinations of models in all directions as new analytic opportunities arise. + +It's not difficult to imagine why this happens — people have different opinions, habits, and diligence about naming and when developing, it is often easier to build a new thing fit for the new purpose then to integrate your changes into the pre-existing ecosystem, test that yours works without breaking everyone else's, etc. + +It is a common joke in computer science (and by extension data) that among all of the hard things we do, naming things is *one of the hardest*. These problems are not going away, but what if we can add a little more structure to the naming conventions so that the name of the model can clearly communicate its intent. Simply by reading the name of the model you can know what type of data might be in there, where in the DAG it might be (left, middle, right), or whether it is an internal building block or an external used in the BI Tool for analysis. + +This is the first in a series of posts around model naming conventions: why they are important and how you should think about naming models in your own projects. + +### **Standing on the Shoulders of Giants** + +There is some prior art on this topic - the foundational post[ How We Structure Our dbt Projects](https://discourse.getdbt.com/t/how-we-structure-our-dbt-projects/355). This article has helped countless projects begin the process of organizing their data, but after implementing dbt at a series of large enterprise companies it has left me with some lingering questions and some of its precepts are open to individual interpretations - which can cause drift and tech debt down the line. + +I am elated to stand on the shoulders of giants to write a follow up to this post, with the caveat that this is aimed at a different audience. The above discourse is usually read or linked in 101 courses, where the focus is on initial project setup. In this series of posts you will see how our approach has shifted after working with and implementing these practices at scale. + +![example marts folder structure](/img/blog/on_the_importance_of_naming_image_0.png) + +If you follow the advice from ‘How We Structure Our dbt Projects', you will end up with a project which is fairly easy to read when viewing within the folder hierarchy (from the Analytics Engineer perspective), but the same is not true when viewing in the DAG or the database itself. For the analyst or stakeholder who simply has access to the output database objects and not the hierarchy and flow with which they were developed, it can be at best slightly overwhelming, and at worst, unmanageable. With that in mind, I set out to help answer some of the outstanding questions around model naming and organization: + +* Do intermediates live within marts folder or as a top level directory (or does it matter)? + +* How can we delineate between what is a building block and what is a final output model? + +* We all (I think) agree on `stg_` model naming conventions, but should we have more formalized naming guidelines as we move throughout the DAG?? + +The folder structure is a useful way to organize a project based off of your stakeholders and how they might contribute, as marts are usually mapped to specific business units. This structure also helps with configs, materializations, etc. which can be setup based on the folder structure, which is a great way to apply many configs all at once. But while it is great to have a project that makes sense when viewed from within the folder hierarchy of your dbt project, there are many other ways you and your team will be interacting with your models. By settling on a more formalized naming convention to supplement your folder based organization, your project will be much more usable when viewed in the DAG, in your database, or even in the BI layer + +**When your company scales to have hundreds or thousands of models, the subtle freedom to name models whatever you want starts to wreak havoc on the system** — the developer isn't sure which model to add to or what it's usage is, so they start spinning up tangentially related models using some of the pieces and adding another slightly different variant of the, for example, _`users`_ model. We should do a favor to others in our organization, including our future selves, by sensibly naming and keeping a lid on maintainability, preventing our DAG from descending into chaos. + +Backing up, dbt builds a [directed acyclic graph (DAG)](https://docs.getdbt.com/docs/introduction#what-makes-dbt-so-powerful) based on the interdepencies between models – each node of the graph represents a model, and edges between the nodes are defined by ref functions, where a model specified in a ref function is recognized as a predecessor of the current model. Analytics Engineers often use the DAG to get a holistic of the project or at least the subset of models that our model of interest is interacting with, typically a few models in either direction that are direct parents or children. The DAG helps you visualize how the data flows from left to right (from raw to transformed), without having to comb through SQL with a magnifying glass. + +**Here are some real life examples of a company's DAG, simplified using model selection syntax:** + +Let’s take a look at a real life example of an (admittedly rather complex) DAG to see just how important it is to have a solid framework for naming your models + +`+users` + +* Everything to the left of their users flow + +* Meaning, all the descendants needed to build the `users` model + +![zoomed out screenshot of a DAG](/img/blog/on_the_importance_of_naming_image_1.png) + +`users+` + +* Everything to the right of their users flow + +* Meaning, all the ancestor references that depend on the `users` model once created + +![zoomed out screenshot of the right of a dag](/img/blog/on_the_importance_of_naming_image_2.png) + +Imagine trying to mentally internalize this after reading through countless SQL files, without looking at the DAG! + +### **Zoom in and it will make more sense?** + +You're not actually supposed to be able to read those DAGs, as they are notoriously hard to grok when zoomed out. Let's pick a random zoom in point to show the "spider web", aka uncontrollable references to other models with no clear movement from left to right in a logical fashion. + +![zoomed in picture of a DAG](/img/blog/on_the_importance_of_naming_image_3.png) + +In my utopia, when you zoom into a DAG and you would see a swimlane, or etymology, such that you would be able to understand the purpose of a given model. This real world example gives us a view into what happens when we don’t have that. + +* `fct_`'s on both sides of the screenshot, with all sorts of other models in between + +* a `report_` is used, not as an endpoint, but instead as an input by another model + +* what is a `tool_` (or your company’s equivalent of an undocumented pattern)? + +* Does `user_` at the beginning have a meaning? + +In the organization which produced the above example, they are managing to remain prolific in their creation of models and outgoing analysis (which is good!), but they are introducing tech debt and potential failure modes that loom in the future, such as decreasing modularity and reproducibility, and increasing complexity. These are the kinds of issues that will increase the time to onboard new team members. + +Hopefully by now I have convinced you that it is worth your time to spend a considerable amount of effort on a logical naming convention for your models. After all, if you cannot understand the flow of data through models even when looking at the DAG (or using folder hierarchy) then how are we supposed to set our company up for success, onboard new members to our team quickly, and ensure that without supervision, your project (and DAG) continues to grow in a stable fashion? + +In the next posts in this series, I’ll walk you through a number of guidelines and heuristics that we have developed to make it easy and repeatable to name your models well. diff --git a/website/blog/2021-11-23-so-you-want-to-build-a-package.md b/website/blog/2021-11-23-so-you-want-to-build-a-package.md new file mode 100644 index 00000000000..ba25cef9c05 --- /dev/null +++ b/website/blog/2021-11-23-so-you-want-to-build-a-package.md @@ -0,0 +1,213 @@ +--- +title: "So You Want to Build a dbt Package" +description: "Packages are the easiest way for a dbt user to contribute code to the dbt community." +slug: so-you-want-to-build-a-package + +authors: [amy_chen] + +tags: [dbt tutorials] +hide_table_of_contents: false + +date: 2021-11-29 +is_featured: true +--- + + +Packages are the easiest way for a dbt user to contribute code to the dbt community. This is a belief that I hold close as someone who is a contributor to packages and has helped many partners create their own during my time here at dbt Labs. + +The reason is simple: packages, as an inherent part of dbt, follow our principle of being built by and for analytics engineers. They’re easy to install, accessible and at the end of the day, it’s just SQL (with sprinklings of git and jinja). You can either share your package with the community or just use it among your teams at your org. + +So I challenge you after reading this article to test out your skillsets, think about the code that you find yourself reusing again and again, and build a package. Packages can be as complex as you would want; it’s just SQL hidden in the mix of reusable macros and expansive testing frameworks. So let’s get started on your journey. + +**What is a package even?** + +If you’re considering making a package, you probably already know what one is but let’s take a quick review to help structure our thinking. A dbt package is basically a mini-dbt project. The only mandatory file that it requires is a dbt_project.yml to validate that it’s a dbt package (same as any dbt project). It can contain macros that help you write something in SQL in significantly less lines. It could contain models that help you model your SaaS dataset in a manner of minutes (I’m looking at you, Fivetran Salesforce package). But in dbt land, you could literally take one project (say Jaffle shop) and install it as a package to your project, regardless of whether it's from the Hub or not. + +Packages are a way to share code in dbt without ever having to copy and paste (or *email* :screaming face:). + +Let’s break down the [dateadd macro](https://github.com/dbt-labs/dbt-utils/blob/main/macros/cross_db_utils/dateadd.sql) from the dbt_utils macro to show you the process that created this fantastic macro. + +The problem: Analysts often need to add an interval to a timestamp/date. To make this cross-database and standardized across a project, a macro is needed. + +```sql + +{% macro dateadd(datepart, interval, from_date_or_timestamp) %} + + {{ return(adapter.dispatch('dateadd', 'dbt_utils')(datepart, interval, from_date_or_timestamp)) }} + +{% endmacro %} + +``` + +In this section, we are using the [dispatch](/reference/dbt-jinja-functions/dispatch) Jinja reference to enable the right macro from the rest of the file is called (since they are specific to the adapter) when a user called the macro. This means the user doesn’t have to think about what to call based on the adapter, they just need to call one macro, dbt handles it all behind the scene. + +```sql + +{% macro default__dateadd(datepart, interval, from_date_or_timestamp) %} + + dateadd( + + {{ datepart }}, + + {{ interval }}, + + {{ from_date_or_timestamp }} + + ) + +{% endmacro %} + +``` + +In this macro, we are providing a default way to create a dateadd. This is the first macro to be used unless an adapter specific one is needed. + +```sql + +{% macro bigquery__dateadd(datepart, interval, from_date_or_timestamp) %} + + datetime_add( + + cast( {{ from_date_or_timestamp }} as datetime), + + interval {{ interval }} {{ datepart }} + + ) + +{% endmacro %} + +{% macro postgres__dateadd(datepart, interval, from_date_or_timestamp) %} + + {{ from_date_or_timestamp }} + ((interval '1 {{ datepart }}') * ({{ interval }})) + +{% endmacro %} + +{# redshift should use default instead of postgres #} + +{% macro redshift__dateadd(datepart, interval, from_date_or_timestamp) %} + + {{ return(dbt_utils.default__dateadd(datepart, interval, from_date_or_timestamp)) }} + +{% endmacro %} + +``` + +Here we have macros that are adapter specific. The dispatch function that we called in our first macro will help dbt know which one to point to. + +Now, that wasn’t so bad, right? + +**Intentions** + +Before embarking on any great adventure, you should always have an idea of why you’re going on this journey. For package creation, intentions generally fall into two categories: **technical and social. ** + +Technically, you have something reusable that you want to share. Awesome things that fit in that bucket can look like: + +* Macros that you use very often for your projects: [dbt_utils](https://github.com/dbt-labs/dbt-utils/blob/0.7.3/macros/cross_db_utils/dateadd.sql) + +* Tests that you find valuable: [dbt_expectations](https://hub.getdbt.com/calogica/dbt_expectations/latest) + +* Methods to expand on dbt’s core functionality: [dbt_artifacts](https://hub.getdbt.com/tailsdotcom/dbt_artifacts/latest) + +* Ways to push dbt transformations outside of the box: [dbt_ml](https://hub.getdbt.com/kristeligt-dagblad/dbt_ml/latest) + +* Standard methods of modeling a SaaS data source: [Salesforce](https://hub.getdbt.com/fivetran/salesforce/latest) + +I’ve even written a macro that alters the union_relations macro to a specific use case (unioning two massive tables in an incremental manner). Analytics often means that there is a lot of reusable code, across organizations and verticals. + +Socially, you want to contribute to dbt. By using dbt, you are inherently part of our open source community. This means you are benefiting from the community contributions made from those prior to you and those after. So what better way to show your appreciation than contributing your knowledge, to help dbt continuously improve. Contributions help you validate your dbt expertise, both to yourself and the greater community. Creating a dbt package is a great vehicle to provide an opinionated way to use dbt. You can help define industry standards across projects, for yourself and the community. And all of this done without requiring python knowledge. + +**Requirements:** + +But Amy, you just said that anyone with SQL and dbt knowledge can create a package. + +I didn’t lie but I want to be specific about what skillsets you want to be comfortable with or expect to hone in as you develop your package: + +* High level of SQL knowledge + +* Understanding of git, especially with semantic versioning and git maintenance + +* Knowledge of dbt (think 300s levels where you have fully built out a dbt project) + +* Proficient with Jinja + +* Have used dbt packages in the past + +* If you’re making a public package, an high-level understanding of how open source works + +**Flavors of Packages** + +dbt Packages can come in a variety of flavors; let’s break down your options: + +* **Public vs Private** + +Now, generally speaking, we encourage contributions to our open source community so we always want to recommend sharing your package publicly. You can host your package on our[ Packages Hub](https://hub.getdbt.com/) to showcase alongside your fellow experts. But we understand sometimes there is the knowledge that you might want to share in a more controlled manner. You can make your package private in git so only those you have granted access to it can install the package in their dbt project. This often means including additional credentials during installation via using env_vars. + +* **Content** + + * We have found that our most popular packages are configurable so keep in mind how customizable you want to be. Packages containing macros are by far the leading packages installed but modeling SaaS datasets has a very specific and still helpful space. So what is your package solving for? Is it going to be usable across different platforms or just Snowflake specific? + +* **Documentation ** + +This is basically pineapple on pizza. It’s an alternative use case where you might be installing another project on your own to gain access to the documentation and potentially internal team models. I reference this approach in my ([repo discourse post](https://discourse.getdbt.com/t/how-to-configure-your-dbt-repository-one-or-many/2121)). This will likely not be a public package but you will treat the project just like a package in this use case. + +**How to create a package** + +** +**Now let’s get to the fun part. Starting out high level, what does the workflow look like? + +**The workflow ** + +Here is a diagram that shows the workflow. You might notice that this looks a lot like how you might work on a dbt project and you would be absolutely right. Once again, you just need to know dbt and SQL to create a package :) + +![image alt text](/img/blog/how_to_build_a_package_image_0.png) + +Now let’s deep dive into what happens in this flow. + +**Develop** + +This is where you create the foundation. + +1. Start out with creating a dbt Project in Github (you can use other git providers if you plan to make a private package). All it needs to include is a `dbt_project.yml` to be installed as a package. + +2. Add in your package contents. This means your models and macros. Don’t forget to declare the vars in your dbt_project.yml file if you have any specific configurations. + +As you’re going through these steps, keep in mind how configurable you want your code to be. Does your code follow [dbt best practices](https://discourse.getdbt.com/t/your-essential-dbt-project-checklist/1377)? If it’s cross-platform, have you taken into account the various SQL dialects? Also if your package relies on any existing dbt packages, are you tying it to a specific version? [For more information on developing your package, check out our docs site. ](https://docs.getdbt.com/docs/guides/building-packages#3-develop-your-package)If you want assistance from the community, the [#packages-ecosystem](https://getdbt.slack.com/archives/CU4MRJ7QB) channel is a fantastic place to start. + +**Testing ** + +After you have developed your core code, it’s time to [add integration tests](https://docs.getdbt.com/docs/guides/building-packages#4-add-integration-tests). This is a great thing to do because this confirms your assumptions and gives you and any contributors to your package a baseline of how the package should work. Our [audit-helper](https://github.com/dbt-labs/dbt-audit-helper/tree/master/integration_tests) package has some fantastic cross-platform integrations tests. Be sure to also install your package into an existing dbt project to validate that it works. + +**Document** + +We, at dbt Labs, have a strongly held belief that good code is documented so make sure to document any models or macros. Update the Readme with the package’s use cases, how to use it, and specifics on what it contains. Take a look at the [dbt-expectations](https://hub.getdbt.com/calogica/dbt_expectations/latest/) package as an example of exemplary documentation. You want to make sure to cover what a user might need to know to use this package and debug any errors. + +**Community Contribution ** + +If you plan to create a public package, I highly recommend implementing a contribution process. This will help users contribute to your code and continue to expand its usage (yay open source!). To create a trusted process, be sure to include the following elements: + +* [Pull Request](https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/creating-a-pull-request-template-for-your-repository) and [Issue Templates](https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/configuring-issue-templates-for-your-repository) to help users contribute with guidance. This prevents unnecessary back and forth and helps set up productive conversations. It will help you help users debug issues and encourage folks to contribute to your package. + +* Declare a reasonable SLA. Be transparent with how quickly you can respond to pull requests and issues. + +* Define your [code owners](https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners) if you have multiple maintainers to automate reviewers + +A mindset to have here is setting up a framework that encourages people to join in. This will make it a lot easier for you and your users to reap the benefits of collective knowledge. + +**Publish** + +Now that all the work is done, it’s time to take the stage. This is the part of the workflow where you will make the repo public if necessary and [add to have it added to our Hub site](https://docs.getdbt.com/docs/guides/building-packages#7-add-the-package-to-hubgetdbtcom). Be sure to tell folks what you have done in dbt Slack in the #i-made-this channel or social media. + +**Maintain ** + +Now, this is actually the section that package maintainers tell me is the hardest. You want to make sure to keep up with dbt core versions as well as make sure to respond to open pull requests and issues with transparency. You also might have users who are asking questions about your packages in a part of the slack community that you don’t see. This is why it’s so key to have a good process for contribution during the community contribution section of the workflow. One package maintainer told me he just regularly keyword searches in dbt Slack to catch stray questions about his package. So be clear on communication and this will make life so much easier in terms of the community element. In terms of keeping dbt core versions up to date, luckily for you, v1 is coming out and this means the end of breaking changes. That being said, it would be good to keep in mind a maintenance schedule, say every 2 months to keep your package updated to date with the latest and greatest. + +**My challenge to you** + +Share your knowledge. There are never too many voices in an open-source community. Join the [#packages-ecoystem](https://getdbt.slack.com/archives/CU4MRJ7QB) channel to speak with maintainers of packages. + +Check out the hub for ideas on gaps you might see. Maybe there’s an [existing package with an issue you have a solution for](https://github.com/dbt-labs/dbt-utils/issues). Contributing to an existing package is a great way to get started. + + I’m excited to see what you create. + +**Thank yous!** + +Many thanks to our package creators and maintainers that allow me to interview them and pick their brain about packages best practices: Anders, Joe Markiewicz, Claus Herther, Mateusz Klimek, Jeremy Cohen diff --git a/website/blog/2021-11-26-welcome-to-the-dbt-developer-blog.md b/website/blog/2021-11-26-welcome-to-the-dbt-developer-blog.md new file mode 100644 index 00000000000..3037002955b --- /dev/null +++ b/website/blog/2021-11-26-welcome-to-the-dbt-developer-blog.md @@ -0,0 +1,65 @@ +--- +title: "Welcome to the dbt Developer Blog" +description: "Doing analytics is hard. Doing analytics *right* is even harder. The purpose of this blog is to double down on our long running commitment to contributing to the knowledge loop." +slug: welcome + +authors: [jason_ganz, david_krevitt] + +tags: [analytics craft] +hide_table_of_contents: false + +date: 2021-11-29 +is_featured: true +--- +Doing analytics is hard. Doing analytics *right* is even harder. + +There are a massive number of factors to consider: Is data missing? How do we make this insight discoverable? Why is my database locked? *Are we even asking the right questions?* + +Compounding this is the fact that analytics can sometimes feel like a lonely pursuit. + +Sure, our data is generally proprietary and therefore we can’t talk much about it. But we certainly **can** share what we’ve learned **about** working with that data. + +So let’s all commit to sharing our hard won knowledge with each other—and in doing so pave the path for the next generations of analytics practitioners. + + +## Welcome to the dbt Developer Blog + +The purpose of this blog is to double down on our long running commitment to contributing to the knowledge loop. + +From early posts like ‘[The Startup Founders Guide to Analytics’](https://thinkgrowth.org/the-startup-founders-guide-to-analytics-1d2176f20ac1) to foundational guides like [‘How We Structure Our dbt Projects](/blog/how-we-structure-our-dbt-projects)’, we’ve had a long standing goal of working with the community to create practical, hands-on tutorials and guides which distill the knowledge we’ve been able to collectively gather. + +dbt as a product is based around the philosophy that even the most complicated problems can be broken down into modular, reusable components, then mixed and matched to create something novel. + +This blog represents the exact same philosophy, just applied via the lens of written guides rather than code. Our knowledge grows strongest when we bounce ideas off of each other: no idea is too small, something that’s old hat to you may spark something big in someone else. + +## A Note on "Best Practices" + +A critical part of making knowledge sharing successful is understanding that many ideas are a work in progress—think of posts here less as canonical declarations of truth, and more as point-in-time snapshots of the writer’s thinking. + +The goal is for each post here to have at least one new reusable piece of knowledge that you can return to again and again throughout your work. + +## The Types of Posts You’ll Find Here + +A brief overview of the types of posts that you will find on the blog: + +* *Analytics Craft*: The art of being an analytics practitioner. + +* *dbt Tutorials:* Best practices in the usage of our favorite data transformation tool. + +* *Data Ecosystem:* Walkthroughs of how top data practitioners use tools in the modern data stack. + +* *Product Updates:* An archive of monthly product updates from the dbt Labs team. + +* *SQL Magic*: Stories of dbt developers making SQL sing across warehouses + +## Get Involved + +Analytics engineering is a relatively young skillset, and many of the basic tenets and patterns are still in the process of being discovered. There is not yet a canonical set of patterns to implement and processes to follow in order to guarantee success. + +So! We hope this blog can provide a platform for community learning and knowledge sharing. + +The insights to get there cannot come from any one individual or organization - for this project to be successful, they have to integrate the collective knowledge of a diverse set of voices from within the analytics community. + +If you are interested in contributing, requesting topics or just looking at what is coming down the road on the blog, check out the [dbt Developer Blog repo](https://github.com/dbt-labs/dbt-technical-blog-writing). This repo contains all the information you need to get involved and get started, including the [Discussions board](https://github.com/dbt-labs/dbt-technical-blog-writing/discussions) where you can propose new topics for posts. + +Together, we will begin to write the playbooks to ensure any organization has access to the accumulated knowledge of the analytics engineering community. diff --git a/website/blog/2021-11-29-dbt-airflow-spiritual-alignment.md b/website/blog/2021-11-29-dbt-airflow-spiritual-alignment.md new file mode 100644 index 00000000000..73eb4a510d9 --- /dev/null +++ b/website/blog/2021-11-29-dbt-airflow-spiritual-alignment.md @@ -0,0 +1,251 @@ +--- +title: "The Spiritual Alignment of dbt + Airflow" +description: "Airflow and dbt are often framed as either / or, but in practice I've experienced them to play extremely well together." +slug: dbt-airflow-spiritual-alignment + +authors: [sung_chung] + +tags: [data ecosystem] +hide_table_of_contents: false + +date: 2021-11-29 +is_featured: true +--- + +Airflow and dbt are often framed as either / or: + +You either build SQL transformations using Airflow’s SQL database operators (like [SnowflakeOperator](https://airflow.apache.org/docs/apache-airflow-providers-snowflake/stable/operators/snowflake.html)), or develop them in a dbt project. + +You either orchestrate dbt models in Airflow, or you deploy them using dbt Cloud. + +In my experience, these are false dichotomies, that sound great as hot takes but don’t really help us do our jobs as data people. + + + +In my days as a data consultant and now as a member of the dbt Labs Solutions Architecture team, I’ve frequently seen Airflow, dbt Core & dbt Cloud ([via the API](https://docs.getdbt.com/dbt-cloud/api-v2)) blended as needed, based on the needs of a specific data pipeline, or a team’s structure and skillset. + +More fundamentally, I think it’s important to call out that Airflow + dbt are **spiritually aligned** in purpose. They both exist to facilitate clear communication across data teams, in service of producing trustworthy data. + +Let’s dive a bit deeper into that spiritual alignment, hone in on a couple cases where they play nicely, and then dive into the nitty gritty of which combination of Airflow + dbt might be right for your team. + +## Where Airflow + dbt align + +Let’s walk through a hypothetical scenario I’d run into as a consultant, to illustrate how Airflow + dbt operate on a parallel spiritual wavelength. + +TL;DR: they both provide **common interfaces** that data teams can use to get on the same page. + +The intricacies of when I’ve found each to be useful (Airflow alone, Airflow w/ dbt Core or Cloud, dbt Core or Cloud alone) is in _which team members_ need to get on the same page—I’ll get to that in the next section. + +### From the Airflow side + +A client has 100 data pipelines running via a cron job in a GCP (Google Cloud Platform) virtual machine, every day at 8am. + +It was simple to set up, but then the conversation started flowing: + +* “Where am I going to put logs?” In a Google Cloud Storage bucket. +* “Where can I view history in a format?” Let’s export log events into BigQuery. +* “I have to create log alerts to notify people of failures.” Let’s use GCP’s logging alerts to send emails. +* “When something fails, how do you rerun from the point of failure?” Let’s mangle the production script. + +Over time, you end up building a bunch of pieces that Airflow provides out of the box. + +But what makes one come alive as a data engineer—is it fine-tuning logging and making sure that the basic overhead of your pipeline works, or is it getting trustworthy data to the people you’re working with? + +Airflow solves those same problems, but in a publicly-verifiable and trusted way—it provides **a common interface** by which data teams can get on the same page about overall data pipeline health. And that common interface is configured in code + version-controlled. + +### From the dbt side + +That pipeline above included a plethora of data transformation jobs, built in various ways. + +They were often written in naked python scripts that only ran a SQL query + wrote data to BigQuery. These stored procedure-like SQL scripts required: + +* Writing boilerplate (`CREATE TABLE` etc * 1000) +* Managing schema names between production and dev environments +* Manually managing dependencies between scripts + +Again, this is **pretty easy to set up**, but it doesn’t get to the heart of the matter: getting trusted data to the people that you care about. + +It _kind of works_, but you need it to _really work_ in a way that’s publicly observable + verifiable via testing. + +I have never encountered a client writing a script to auto-generate DDL, or writing boilerplate tests for SQL—no one wants these to be their job. + +So like Airflow for pipeline orchestration, dbt does these things out of the box for the data transformation layer. + +dbt provides a **common interface** where data teams can get on the same page about the business logic + run status of data transformations—again, in a way that’s configured in code + version-controlled. + +> If you’re curious about the migration path from a stored procedure-based transformation workflow to modular data modeling in dbt, check out my colleagues Sean McIntyre + Pat Kearns writing on [migrating to an ELT pipeline](https://getdbt.com/analytics-engineering/case-for-elt-workflow/). + +## A note on data team roles for Airflow + dbt + +In my experience, these tech decisions also boil down to the **[data team structure](https://www.getdbt.com/data-teams/data-org-structure-examples/)** you’re building around, and specifically the **skills** + **training** baked into that structure. + +Tools are cheap relative to hiring + training, so I’ve most often seen tool decisions made by the availability of staff + training support, rather than the technical specs or features of the tools themselves. So let’s peek into what roles are required to build around dbt and Airflow (these same skills would also roughly map to any other orchestration tool). + +Many of us define roles like [data engineer](https://www.getdbt.com/data-teams/hiring-data-engineer/), [analytics engineer](https://getdbt.com/what-is-analytics-engineering/) and data analyst differently. + +So instead of getting bogged down in defining roles, let’s focus on hard skills I’ve seen in practice. + +![airflow and dbt skills required](/img/blog/airflow-dbt-skills.png "airflow and dbt skills required") + +The common skills needed for implementing any flavor of dbt (Core or Cloud) are: + +* SQL: ‘nuff said +* YAML: required to generate config files for [writing tests on data models](/docs/building-a-dbt-project/tests) +* [Jinja](/guides/getting-started/learning-more/using-jinja): allows you to write DRY code (using [macros](/docs/building-a-dbt-project/jinja-macros), for loops, if statements, etc) + +YAML + Jinja can be learned pretty quickly, but SQL is the non-negotiable you’ll need to get started. + +SQL skills are generally shared by data people + engineers, which makes SQL-based transformations (as in dbt) a ripe common interface for collaboration. + +To layer on Airflow, you’ll need more software or infrastructure engineering-y skills to build + deploy your pipelines: Python, Docker, Bash (for using the Airflow CLI), Kubernetes, Terraform and secrets management. + +## How Airflow + dbt play nicely + +Knowing that this toolbelt (Airflow + dbt) provides sustenance to the same spiritual needs (public observability, configuration as code, version control etc), how might one decide when and where to deploy them? + +> This is the same sensibility expressed in the [dbt viewpoint](/docs/about/viewpoint) in 2016, the closest thing to a founding blog post as exists for dbt. ] + +I usually think in terms of how I want my job to look when things go wrong—am I equipped to do the debugging, and is it clear who to pass the baton to, to fix the issue (if it’s not me)? + +A couple examples: + +### Pipeline observability for analysts + +If your team’s dbt users are analysts rather than engineers, they still may need to be able to dig into the root cause of a failing dbt [source freshness test](/docs/dbt-cloud/using-dbt-cloud/cloud-snapshotting-source-freshness). + +Having your upstream extract + load jobs configured in Airflow means that analysts can pop open the Airflow UI to monitor for issues (as they would a GUI-based [ETL tool](https://www.getdbt.com/analytics-engineering/etl-tools-a-love-letter/)), rather than opening a ticket or bugging an engineer in Slack. The Airflow UI provides the common interface that analysts need to self-serve, up to the point of action needing to be taken. + +![airflow dashboard](/img/blog/airflow-dbt-dashboard.png "airflow dashboard") + +### Transformation observability for engineers + +When a dbt run fails within an Airflow pipeline, an engineer monitoring the overall pipeline will likely not have the business context to understand why the individual model or test failed—they were probably not the one who built it. + +dbt provides common programmatic interfaces (the [dbt Cloud Admin + Metadata APIs](/docs/dbt-cloud/dbt-cloud-api/cloud-apis), and [.json-based artifacts](/reference/artifacts/dbt-artifacts) in the case of dbt Core) that provide the context needed for the engineer to self-serve—either by rerunning from a point of failure or reaching out to the owner. + +![dbt run log](/img/blog/airflow-dbt-run-log.png "dbt run log") + +## Why I ❤️ dbt Cloud + Airflow + +dbt Core is a fantastic framework for developing data transformation + testing logic. It is less fantastic as a shared interface for data analysts + engineers to collaborate **_on production runs of transformation jobs_**. + +dbt Labs and the Astronomer team has been hard at work with co-developing some options for dbt Core, and [a new dbt Cloud Provider](https://registry.astronomer.io/providers/dbt-cloud) for those using dbt Cloud that's ready for use by all OSS Airflow users. The best choice for you will depend on things like the resources available to your team, the complexity of your use case, and how long your implementation might need to be supported. + +This tool picks up that baton, and provides a common interface where teams can configure runs + debug issues in production jobs. + +If you productionalize your dbt runs in Airflow using the dbt Core operator, you run into the same `SQL wrapped in Python` communication challenge I mentioned at the top: the analyst who built the transformation logic is in the dark about the production run workflow, which is spiritually the thing we’re trying to avoid here. + +### dbt Core + Airflow + +Let’s take a look at an example, from GitLab’s [dbt_full_refresh](https://gitlab.com/gitlab-data/analytics/-/blob/master/dags/transformation/dbt_full_refresh.py) Airflow pipeline. + +If this task fails in the Airflow pipeline, there are a number of aspects of the pipeline to debug: was it an issue with Kubernetes or secrets, the Docker image, or the dbt transformation code itself? + +An analyst will be in the dark when attempting to debug this, and will need to rely on an engineer to tap them on the shoulder in the event that the issue lies with dbt. + +This can be perfectly ok, in the event your data team is structured for data engineers to exclusively own dbt modeling duties, but that’s a quite uncommon org structure pattern from what I’ve seen. And if you have easy solutions for this analyst-blindness problem, I’d love to hear them. + +Once the data has been ingested, dbt Core can be used to model it for consumption. Most of the time, users choose to either: +Use the dbt CLI+ [BashOperator](https://registry.astronomer.io/providers/apache-airflow/modules/bashoperator) with Airflow (If you take this route, you can use an external secrets manager to manage credentials externally), or +Use the [KubernetesPodOperator](https://registry.astronomer.io/providers/kubernetes/modules/kubernetespodoperator) for each dbt job, as data teams have at places like [Gitlab](https://gitlab.com/gitlab-data/analytics/-/blob/master/dags/transformation/dbt_trusted_data.py#L72) and [Snowflake](https://www.snowflake.com/blog/migrating-airflow-from-amazon-ec2-to-kubernetes/). + +Both approaches are equally valid; the right one will depend on the team and use case at hand. + +| | Dependency management | Overhead | Flexibility | Infrastructure Overhead | +|---|---|---|---|---| +| dbt CLI + BashOperator | Medium | Low | Medium | Low | +| Kubernetes Pod Operator | Very Easy | Medium | High | Medium | +| | | | | | + +If you have DevOps resources available to you, and your team is comfortable with concepts like Kubernetes pods and containers, you can use the KubernetesPodOperator to run each job in a Docker image so that you never have to think about Python dependencies. Furthermore, you’ll create a library of images containing your dbt models that can be run on any containerized environment. However, setting up development environments, CI/CD, and managing the arrays of containers can mean a lot of overhead for some teams. Tools like the [astro-cli](https://github.com/astronomer/astro-cli) can make this easier, but at the end of the day, there’s no getting around the need for Kubernetes resources for the Gitlab approach. + +If you’re just looking to get started or just don’t want to deal with containers, using the BashOperator to call the dbt CLI can be a great way to begin scheduling your dbt workloads with Airflow. + +It’s important to note that whichever approach you choose, this is just a first step; your actual production needs may have more requirements. If you need granularity and dependencies between your dbt models, like the team at [Updater does, you may need to deconstruct the entire dbt DAG in Airflow.](https://www.astronomer.io/guides/airflow-dbt#use-case-2-dbt-airflow-at-the-model-level) If you’re okay managing some extra dependencies, but want to maximize control over what abstractions you expose to your end users, you may want to use the [GoCardlessProvider](https://github.com/gocardless/airflow-dbt), which wraps the BashOperator and dbt CLI. + +#### Rerunning jobs from failure + +Until recently, one of the biggest drawbacks of any of the approaches above was the inability to rerun a job from the point of failure — there was no simple way to do it. As of dbt 1.0, however, dbt now supports the ability to rerun jobs from failure, which should provide a significant quality-of-life improvement. + +In the past, if you ran 100 dbt models and 1 of them failed, it’d be cumbersome. You’d either have to rerun all 100 or hard-code rerunning the failed model. + + +One example of this is ‘dbt run –select ``. + + +Instead you can now use the following command: + +`dbt build –select result:error+ –defer –state ` … and that’s it! + + +You can see more examples [here](https://docs.getdbt.com/docs/guides/best-practices#run-only-modified-models-to-test-changes-slim-ci). + + +This means that whether you’re actively developing or you simply want to rerun a scheduled job (because of, say, permission errors or timeouts in your database), you now have a unified approach to doing both. + +![airflow dbt run select](/img/blog/2021-11-29-dbt-airflow-spiritual-alignment/airflow-dbt-run-select.png) + +[In an Airflow context](https://registry.astronomer.io/dags/dbt-core-run-from-failure-pattern), you can use this command with TriggerRules to make it so that, in the event that your initial model fails, you can keep rerunning it from the point of failure without leaving the Airflow UI. This can be especially convenient when the reason your model fails isn't related to the model code itself (permissions for certain schemas, bad data, etc.) + +![airflow dbt run select](/img/blog/2021-11-29-dbt-airflow-spiritual-alignment/dbt-airflow-tree-graph.png) + +### dbt Cloud + Airflow + +With dbt Cloud and its aforementioned [APIs](https://docs.getdbt.com/docs/dbt-cloud/dbt-cloud-api/cloud-apis), any dbt user can configure dbt runs from the UI. + +In Airflow, engineers can then call the API, and everyone can move on with their lives. This allows the API to be a programmatic interface between analysts and data engineers, vs relying on the human interface. + +If you look at what this practically looks like in code (my [airflow-toolkit repo is here](https://github.com/sungchun12/airflow-toolkit/blob/demo-sung/dags/examples/dbt_cloud_example.py)), just a few settings need to be configured after you create the initial python API call: [here](https://github.com/sungchun12/airflow-toolkit/blob/95d40ac76122de337e1b1cdc8eed35ba1c3051ed/dags/dbt_cloud_utils.py) + +``` + +dbt_cloud_job_runner_config = dbt_cloud_job_runner( + + account_id=4238, project_id=12220, job_id=12389, cause=dag_file_name + +) + +``` + +If the operator fails, it’s an Airflow problem. If the dbt run returns a model or test failure, it’s a dbt problem and the analyst can be notified to hop into the dbt Cloud UI to debug. + +#### Using the new dbt Cloud Provider + +With the new dbt Cloud Provider, you can use Airflow to orchestrate and monitor your dbt Cloud jobs without any of the overhead of dbt Core. Out of the box, the dbt Cloud provider comes with: + +An operator that allows you to both [run a predefined job in dbt Cloud and download an artifact from a dbt Cloud job](https://registry.astronomer.io/dags/example-dbt-cloud). +A hook that gives you a secure way to leverage Airflow’s connection manager to connect to dbt Cloud. The Operator leverages the hook, but you can also [use the hook directly in a Taskflow function or PythonOperator](https://registry.astronomer.io/dags/dbt-cloud-operational-check) if there’s custom logic you need that isn’t covered in the Operator. + +A sensor that allows you to poll for a job completion. You can use this [for workloads where you want to ensure your dbt job has run before continuing on with your DAG](https://registry.astronomer.io/dags/fivetran-dbt-cloud-census). +TL;DR - This combines the end-to-end visibility of everything (from ingestion through data modeling) that you know and love in Airflow with the rich and intuitive interface of dbt Cloud. + +#### Setting up Airflow and dbt Cloud + +To set up Airflow and dbt Cloud, you can: + + +1. Set up a dbt Cloud job, as in the example below. + +![job settings](/img/blog/2021-11-29-dbt-airflow-spiritual-alignment/job-settings.png) + +2. Set up an Airflow Connection ID + +![airflow dbt run select](/img/blog/2021-11-29-dbt-airflow-spiritual-alignment/airflow-connection-ID.png) + +3. Set up your Airflow DAG similar to [this example](https://github.com/apache/airflow/blob/main/airflow/providers/dbt/cloud/example_dags/example_dbt_cloud.py). + +4. You can use Airflow to call the dbt Cloud API via the new `DbtCloudRunJobOperator` to run the job and monitor it in real time through the dbt Cloud interface. + +![dbt Cloud API graph](/img/blog/2021-11-29-dbt-airflow-spiritual-alignment/dbt-Cloud-API-graph.png) + +![Monitor Job Runs](/img/blog/2021-11-29-dbt-airflow-spiritual-alignment/Monitor-Job-Runs.png) + +![run number](/img/blog/2021-11-29-dbt-airflow-spiritual-alignment/run-number.png) + +If your task errors or fails in any of the above use cases, you can view the logs within dbt Cloud (think: data engineers can trust analytics engineers to resolve errors). + +This creates a much more natural baton pass, and clarity on who needs to fix what. + +And if my goal is to ship trusted data, I opt for that simplicity + clarity every time. + +But there are no right or wrong decisions here! Any combination of tools that solves the problem of delivering trusted data for your team is the right choice. diff --git a/website/blog/2021-11-29-open-source-community-growth.md b/website/blog/2021-11-29-open-source-community-growth.md new file mode 100644 index 00000000000..a61fa7ac46b --- /dev/null +++ b/website/blog/2021-11-29-open-source-community-growth.md @@ -0,0 +1,498 @@ +--- +title: "How I Study Open Source Community Growth with dbt" +description: "Building a data pipeline to study open source community growth with BigQuery, dbt, OpenLineage and Superset." +slug: open-source-community-growth-analysis + +authors: [ross_turk] + +tags: [analytics craft] +hide_table_of_contents: false + +date: 2021-11-29 +is_featured: false +--- + +Most organizations spend at least *some* of their time contributing to an open source project. 100% of them, though, depend in some way on the output of open source communities. + + + +In fact we all do. The work of communities can be found everywhere - in the cell phone that wakes you up, the machine that makes your coffee, the car that drives you to get better coffee, the magic app that brings you dinner, and the television that lulls you back to sleep. It's your entire day, even if you aren't a software engineer. Call me weird, but I think everyone should be interested in how open source communities grow and operate. + +## Why I Care About Open Source Adoption +There are two communities that my colleagues and I have a particular curiosity in: OpenLineage and Marquez. We build a product based on the standards, conventions, and capabilities that are created there, and at least 70% of our engineering time is spent in contribution. Understanding how these communities grow and evolve, and how our behavior affects them, is important to each of us. + +In many organizations it's important to measure the results of ongoing investment in open source projects, especially when dealing with stakeholders who favor quantitative proof. Often, this is framed in terms of popularity and adoption - i.e., "how many people use our stuff" and "how many people love it". A chart showing strong adoption of a project is likely to make hard conversations easier...and a hockey stick might just lead to a stronger round of funding. + +But there are tactical uses for this data as well. Consider these scenarios: + +* Docker pulls of a particular image have unexpectedly dropped in frequency +* A vulnerability has been fixed in a Python module, but people are still downloading the old version for some reason +* An engineer who is about to go on sabbatical is the most active participant on Slack + +These are all situations that require investigation and action, and can only be discovered with up-to-date information on open source community activity. It has become essential for teams like ours - perhaps even as essential as an accurate sales pipeline forecast. Fortunately, this information is easy to find. + +In most cases, the numbers I'm looking for are on a web page, just a few clicks away. I can visit the GitHub page for a project and see the number of stars, or look at a package on PyPI when I need to know how many downloads it's gotten. But it's hard to get a sense of how a thing behaves by looking at its current state. Instead, you have to watch it move! You need to *collect* the data that's important to your business and study how it changes over time. + +That's why I built a mini-warehouse for studying community growth. Several times a day I gather information about the OpenLineage and Marquez communities from different data sources. My models process the data so that it's easy to perform analysis and spot trends. + +In this post, I'll walk you through our stack and sources. Then I'll show you how I track engagement across Slack, GitHub, Docker Hub, and PyPI, using a warehouse built with BigQuery, dbt, OpenLineage and Superset. + +## The Tool Stack +I am a copy-and-paste coder, which means that starting with an empty screen is difficult for me. So it was important that I built everything using standard tools with established communities and plenty of examples. + +Here are the tools I chose to use: + +- Google Bigquery acts as the main database, holding all the source data, intermediate models, and data marts. This could just as easily have been Snowflake or Redshift, but I chose BigQuery because one of my data sources is already there as a public dataset. + +- dbt seeds data from offline sources and performs necessary transformations on data after it's been loaded into BigQuery. + +- OpenLineage collects data lineage and performance metadata as models run, so I can identify issues and find bottlenecks. Also, to be the subject ecosystem for this study :) + +- Superset visualizes and analyzes results, creates dashboards, and helps me communicate with stakeholders. + +## Data Sources & Metrics +I decided to start small, with just four data sources: Slack, GitHub, Docker Hub, and PyPI. This gives me a good sense for both the activity in and adoption of the projects over time. + +For starters, I want to know how much conversation is occurring across the various channels and communities we participate in. Our communities use Slack, so the number of messages over time (by user) is what I'm looking for. When there's an unexpected boost in activity, I'd like to be able to study the change in its historical context. I need to be able to view a list of the most active users, updated automatically. When new members join, I want to understand how their activity affects the community. + +There are a ton of metrics that can be tracked in any GitHub project — committers, pull requests, forks, releases — but I started pretty simple. For each of the projects we participate in, I just want to know how the number of GitHub stars grows over time, and whether the growth is accelerating or flattening out. This has become a key performance indicator for open source communities, for better or for worse, and keeping track of it isn't optional. + +Finally, I want to know how much Marquez and OpenLineage are being used. It used to be that when you wanted to consume a bit of tech, you'd download a file. Folks like me who study user behavior would track download counts as if they were stock prices. This is no longer the case; today, our tech is increasingly distributed through package managers and image repositories. Docker Hub and PyPI metrics have therefore become good indicators of consumption. Docker image pulls and runs of `pip install` are the modern day download and, as noisy as these metrics are, they indicate a similar level of user commitment. + +To summarize, here are the metrics I decided to track (for now, anyway): +- Slack messages (by user/ by community) +- GitHub stars (by project) +- Docker Hub pulls (by image) +- PyPI downloads (by package) + +## Getting raw data into BigQuery + +The first step was to get all of my raw data into BigQuery. This was the messiest part of the entire operation, without question. Let's dig into each data source one at a time. + +### Slack + +**Loading in the raw data** + +It wasn't immediately clear how to get a message count from each of the Slack communities. The Slack API can provide some of what I need, but I chose instead to use Zapier to load messages into BigQuery in real time. + +Zapier is an event-based system that can be used to automate random tasks. It has a collection of connectors with common toolchain components and a straightforward interface for designing actions. I implemented a basic Zap that triggers on each new Slack message, storing a copy of the message in a BigQuery . + +Before creating the Zap, I created a table called `slack_messages` to act as a destination. The schema is as follows: + +```sql +CREATE TABLE `openlineage.metrics.slack_messages` +( + message_time TIMESTAMP NOT NULL, + domain STRING NOT NULL, + username STRING, + realname STRING, + email STRING, + channel STRING, + permalink STRING, + text STRING +) +``` + +Next I created two separate Zaps using the "New Public Message Posted Anywhere in Slack" trigger, one for the OpenLineage community and one for the Marquez community. I chose the ["Create Row in Google BigQuery" action](https://zapier.com/shared/61b1356ac4f7542d3adee2e8c6adecbfcb469a25), and mapped across each of the fields the schema required. + +After turning the two Zaps on, I was able to verify that new messages were appearing in the `slack_messages` table. + +**Setting up dbt sources** + +To make dbt aware of this new table, I created a new `models/schema.yml` file containing the following: + +``` +sources: + - name: metrics + database: openlineage + schema: metrics + tables: + - name: slack_messages +``` + +From this, dbt knows to grab the schema for these tables from BigQuery during generation of the documentation website and store it in `catalog.json` for later use. For more information about defining sources, take a look at the Sources page in the dbt docs. + +Explicitly defining external data sources in dbt was important to me for two reasons: + +1. It allows us to use the jinja `source()` and `ref()` functions to refer to these tables within our models, as opposed to hardcoding the table names. +2. It ensures that the schemas are included in `catalog.json` when `dbt docs generate` is run, which is critical for collecting and tracing data lineage. I need this information so that it can be transmitted to OpenLineage during the run cycle. + +### GitHub + +**Loading in the raw data** + +Getting a current GitHub star count into BigQuery wasn't terribly difficult, since there is a public API that provides it. + +I created a short Python script inside a new `loaderscripts/` directory in my project to pull the latest star count from the GitHub API and load it into BigQuery. This script is called at the beginning of each pipeline run, currently as part of my container's `entrypoint.sh`. Here are the important bits: + +``` +dataset_ref = client.dataset('metrics') +table_ref = dataset_ref.table('github_stars') +table = client.get_table(table_ref) + +now = int(time.time()) + +for project in projects: + url = 'https://api.github.com/repos/' + project + response = requests.get(url) + watchers = response.json()['watchers'] + client.insert_rows(table, [(now,project,watchers)]) +``` + +You can see the script in its entirety here. It ensures that the latest GitHub star count is always available before the run cycle begins. + +Before running the script, I created a table called `github_stars` to act as a destination. The schema: + +```sql +CREATE TABLE `openlineage.metrics.github_stars` +( + timestamp TIMESTAMP, + project STRING, + stars INT64 +) +``` + +**Setting up dbt sources** + +To make dbt aware of this new `github_stars` table, I added it to the list of tables in `models/schema.xml`: + +``` +sources: + - name: metrics + database: openlineage + schema: metrics + tables: + - name: github_stars +``` + +This is an effective way to track stars from now on, but can't be used to populate any historical data. Fortunately, there are a few ways to get the complete star history for a project. I used this tool to download CSVs of GitHub star history for each of the projects. I combined them into a single file and placed it in `data/github_daily_summary_history.csv` as a seed file. + +The schema for this data must be explicitly defined. I did this by adding a section to `dbt_project.yml` file with the following: + +``` +seeds: + openlineage_elt: + github_daily_summary_history: + +column_types: + day: date + project: string + stars: integer +``` + +When `dbt seed` is run, a table will be created with the star history. Being explicit about column types in this way ensures that each field is parsed as the intended type. + +### DockerHub + +**Loading in the raw data** + +For Docker Hub, I took a similar approach. There's an API that provides the total number of pulls each image has had over its entire history. I wrote another simple script in `loaderscripts/` to poll the API and load the count into BigQuery. It is very similar to the GitHub script, with only the block at the end differing: + +``` +for image in images: + url = 'https://hub.docker.com/v2/repositories/' + image + response = requests.get(url) + pull_count = response.json()['pull_count'] + client.insert_rows(table, [(now,image,pull_count)]) +``` + +You can see the script in its entirety here. Like the GitHub loader script, this is executed immediately before the dbt run cycle begins. + +Just as I did with the GitHub loader script, I created a table called `dockerhub_pulls`. The schema is as follows: + +```sql +CREATE TABLE `openlineage.metrics.dockerhub_pulls` +( + timestamp TIMESTAMP, + image STRING, + pull_count INT64 +) +``` + +**Setting up dbt sources** + +Again, to make dbt aware of this new `dockerhub_pulls` table, I added it to the list of tables in `models/schema.xml`: + +``` +sources: + - name: metrics + database: openlineage + schema: metrics + tables: + - name: slack_messages + - name: github_stars + - name: dockerhub_pulls +``` + +### PyPI + +PyPI download stats are available as a public data set in BigQuery, so they are easy to work with. There is a `file_downloads` table that contains one row per download, which is ideal for my purposes. However, it's a lot of data to be working with, and I only care about a little bit of it. + +I decided that this situation called for a small slice of PyPI: a table that only contains rows for the packages I am studying, one that I can point a greedy dashboarding tool at without blowing up my Google Cloud bill. + +To carve this slice, I first added the source table from the BigQuery public data set to `models/schema.xml`: + +``` +sources: + - name: metrics + database: openlineage + schema: metrics + tables: + - name: slack_messages + - name: github_stars + - name: dockerhub_pulls + - name: pypi + database: bigquery-public-data + schema: pypi + tables: + - name: file_downloads +``` + +Then, I created an incremental model in `models/pypi_downloads.sql` that pulls the target rows and columns from the source table. I used an incremental model so it could be re-run periodically to update my slice with the latest rows from the source table: + +``` +{{ + config( + materialized='incremental' + ) +}} + +select timestamp, country_code, url, +file.project as project, file.version as version, +file.type as type + +from {{ source('pypi', 'file_downloads') }} + +where ( + file.project = 'marquez-python' + or file.project = 'marquez-airflow' +) + +and timestamp > TIMESTAMP_SECONDS(1549497600) + +{% if is_incremental() %} + and timestamp > (select max(timestamp) from {{ this }}) +{% endif %} +``` + +## Creating data models + +So! I had figured out how to load all the raw data into BigQuery, but I wasn't done yet. Dashboarding tools tend to want data structured in predictable ways, and that means having clear measures and dimensions (almost always with one of the dimensions being a unit of time). I created several dbt models to cajole everything into the proper shape. + +**Slack** + +For Slack, I had a simple transformation to do. The `slack_messages` table contains one row per message sent. What I needed, instead, was one row per user, per community, per day; the only measure I track currently is the number of messages sent. + +To create this table, I built a new model in `models/slack_daily_summary_by_user.sql` containing: + +``` +select + DATE_TRUNC(DATE(message_time), DAY) AS day, + domain, + username, + count(*) AS messages +from {{ source('metrics', 'slack_messages') }} + +group by day, domain, username +``` + +**GitHub** + +For GitHub, the challenge is that there are two inputs: `github_stars`, which is populated by the loader script, and `github_daily_summary_history`, which is loaded from a CSV file. Both of these sources contain a date, a project, and a star count. In both cases there is the possibility of multiple data points per day. + +What I want, instead, is a single table with one row per day per GitHub project. I created `models/github_daily_summary.sql` containing: + +``` +with combined_stars as ( + select DATE_TRUNC(DATE(timestamp), DAY) AS day, project, stars + from {{ source('metrics', 'github_stars') }} + union all + select * from {{ ref('github_daily_summary_history') }} +) + +select day, project, max(stars) AS stars +from combined_stars +group by day, project +``` + +**Docker Hub** + +The Docker Hub data requires very little transformation. However, for consistency I decided to create a summary table containing the maximum value recorded for each image on a given day. To accomplish this, a new `models/dockerhub_daily_summary.sql` file was required: + +``` +{{ + config( + materialized='view' + ) +}} + +select + DATE_TRUNC(DATE(timestamp), DAY) AS day, + image, max(pull_count) AS total_pulls +from {{ source('metrics', 'dockerhub_pulls') }} + +group by day, image +``` + +I decided to make this a , since the source table is already pretty svelte and the transformation involved is lightweight. In the future, I'd like to calculate a `new_pulls` field that contains the difference between the current `total_pulls` and the previous day's value. Once I build that, I'm likely to change this model into a table. + +**PyPI** + +Finally, the PyPI data requires a simple model to count the number of daily downloads per package, `models/pypi_daily_summary.sql`: + +``` +select + DATE_TRUNC(DATE(timestamp), DAY) AS day, + project, version, count(*) AS num_downloads +from {{ ref('pypi_downloads') }} + +group by day, project, version +``` + +## Configuring OpenLineage + +In order to collect lineage metadata as the models run, I used the OpenLineage wrapper script. This script collects lineage metadata from files generated by dbt during the run, emitting OpenLineage events to a metadata server. + +Having this metadata allows me to study the flow of data as it changes over time. This might seem like overkill for such a small, basic pipeline, but I've got a feeling it won't stay that way for long. It's best to establish good practices early. + +To make sure the script and OpenLineage client libraries were installed in my Python virtual environment (hey, folks, always use a virtual environment!) I ran: + +``` +% pip3 install openlineage-dbt +``` + +Marquez is an OpenLineage-compatible metadata server and lineage analysis tool. I spun up an instance using its `docker/up.sh` script: + +``` +% git clone git@github.com:MarquezProject/marquez.git +% cd marquez +% ./docker/up.sh -d +``` + +Finally, I set the `OPENLINEAGE_URL` environment variable to the location of my Marquez server: + +``` +% export OPENLINEAGE_URL=http://localhost:5000 +``` + +## Running the Pipeline + +The OpenLineage integration pulls some important metadata from `target/catalog.json`, which is created by dbt when docs are generated. So it's necessary to do so before running models: + +``` +% dbt docs generate +Running with dbt=0.21.0 +Found 7 models, 0 tests, 0 snapshots, 0 analyses, 184 macros, 0 operations, 2 seed files, 4 sources, 0 exposures + +18:41:20 | Concurrency: 1 threads (target='dev') +18:41:20 | +18:41:20 | Done. +18:41:20 | Building catalog +18:41:31 | Catalog written to /Users/rturk/projects/metrics/target/catalog.json + +``` + +Next, I ran each of the scripts inside the `loaderscripts/` directory to populate GitHub stars and Docker Hub pulls from their respective APIs: + +``` +% for x in loaderscripts/*.py; do python3 $x; done +``` + +Then, to create the `github_daily_summary_history` table with the contents of the file in `data/`: + +``` +% dbt seed +Running with dbt=0.21.0 +Found 7 models, 0 tests, 0 snapshots, 0 analyses, 184 macros, 0 operations, 2 seed files, 4 sources, 0 exposures + +18:40:45 | Concurrency: 1 threads (target='dev') +18:40:45 | +18:40:45 | 1 of 2 START seed file metrics.github_daily_summary_history.......... [RUN] +18:40:49 | 1 of 2 OK loaded seed file metrics.github_daily_summary_history...... [INSERT 2000 in 4.60s] +18:40:49 | 2 of 2 START seed file metrics.slack_daily_summary_history........... [RUN] +18:40:53 | 2 of 2 OK loaded seed file metrics.slack_daily_summary_history....... [INSERT 316 in 4.07s] +18:40:53 | +18:40:53 | Finished running 2 seeds in 9.48s. + +Completed successfully + +Done. PASS=2 WARN=0 ERROR=0 SKIP=0 TOTAL=2 + +``` + +Finally, to run the models and pass lineage metadata to my local instance of Marquez: + +``` +% dbt-ol run +Running OpenLineage dbt wrapper version 0.3.1 +This wrapper will send OpenLineage events at the end of dbt execution. +Running with dbt=0.21.0 +Found 7 models, 0 tests, 0 snapshots, 0 analyses, 184 macros, 0 operations, 2 seed files, 4 sources, 0 exposures + +18:44:15 | Concurrency: 1 threads (target='dev') +18:44:15 | +18:44:15 | 1 of 7 START view model metrics.dockerhub_daily_summary.............. [RUN] +18:44:16 | 1 of 7 OK created view model metrics.dockerhub_daily_summary......... [OK in 0.98s] +18:44:16 | 2 of 7 START table model metrics.github_daily_summary................ [RUN] +18:44:19 | 2 of 7 OK created table model metrics.github_daily_summary........... [CREATE TABLE (1.6k rows, 79.1 KB processed) in 3.03s] +18:44:19 | 3 of 7 START incremental model metrics.pypi_downloads................ [RUN] +18:44:44 | 3 of 7 OK created incremental model metrics.pypi_downloads........... [MERGE (1.7k rows, 7.2 GB processed) in 25.10s] +18:44:44 | 4 of 7 START view model metrics.slack_daily_summary.................. [RUN] +18:44:45 | 4 of 7 OK created view model metrics.slack_daily_summary............. [OK in 0.81s] +18:44:45 | 5 of 7 START view model metrics.slack_daily_summary_by_user.......... [RUN] +18:44:46 | 5 of 7 OK created view model metrics.slack_daily_summary_by_user..... [OK in 0.87s] +18:44:46 | 6 of 7 START table model metrics.pypi_daily_summary.................. [RUN] +18:44:49 | 6 of 7 OK created table model metrics.pypi_daily_summary............. [CREATE TABLE (35.9k rows, 4.7 MB processed) in 3.04s] +18:44:49 | 7 of 7 START view model metrics.daily_summary........................ [RUN] +18:44:50 | 7 of 7 OK created view model metrics.daily_summary................... [OK in 0.87s] +18:44:50 | +18:44:50 | Finished running 4 view models, 2 table models, 1 incremental model in 35.55s. + +Completed successfully + +Done. PASS=7 WARN=0 ERROR=0 SKIP=0 TOTAL=7 +Emitting OpenLineage events: 100%|████████████████████████████████████████████████████████████████████| 14/14 [00:01<00:00, 7.89it/s] +Emitted 16 openlineage events + +``` + +A lineage graph of the entire pipeline can now be viewed in Marquez, which shows the relationships between datasets and provides detail about the run history. + + +![marquez dashboard](/img/blog/community-growth-marquez.png "marquez dashboard") + + +## Visualizing the Results + +This is the simplest part, by far. Since we have a set of tables with clearly-defined measures and dimensions, getting everything working in a system like Apache Superset is straightforward. + +Configuring the data source and adding each table to a Preset Workspace was easy. First, I connected my BigQuery database by uploading a key for my service account. + +Once the database connection was in place, I created datasets for each of my `*_daily_summary` tables by selecting the database/schema/table from a dropdown. + +With the database and datasets configured, I was able to use the charting interface to explore the various measures and dimensions in the warehouse. After about fifteen minutes, I had created a dashboard that shows the evolution of the communities where my colleagues and I do our work. + + +![community growth dashboard](/img/blog/community-growth-dashboard.png "community growth dashboard") + + +This overall view is interesting - it suggests acceleration in activity across every channel during the summer of 2021, which makes a lot of sense. That is when the first release of OpenLineage happened, and also when a few talks and podcasts were released. Things have slowed down as the holiday approaches, which also checks out. Unless you're in the retail business, that kind of thing happens. + +Indeed, you can see a familiar pattern happen every year on the PyPI chart. That indicates at least one thing: CI/CD systems aren't responsible for *all* of those package downloads. The trend has too much humanity baked into it, too many calendar-influenced peaks and valleys. + +Something else can be learned from this PyPI data, something more specific to my project. Over the summer, several integrations were moved from the Marquez project to the OpenLineage project. That means that `marquez-airflow` has become `openlineage-airflow`. I'd like to know whether the old packages are still being used. When I create a chart using `num_downloads` as a metric and `package` as a dimension, with monthly granularity, it shows: + +![community growth trends](/img/blog/community-growth-trend.png "community growth trends") + +The shift began in August, and as of right now the Marquez packages still account for about half of the total downloads. That means we have some work to do. Likely there is some old documentation still out there to be found and updated. + +## What's next? + +This is a very simple community metrics pipeline. Maybe this post should have been called "how to *start* studying community growth". Still, it contains all of the pieces of a large, complex one. +Next, I plan to: + + +* Use Airflow (perhaps with the Astro CLI) to orchestrate the loading of data into `dockerhub_stats` and `github_stats`, then trigger the necessary seed/run steps in dbt. +* Look into creating some basic user segmentation - e.g., how much of this activity comes from people my employer sponsors? +* Expand the list of projects to include those we contribute to less frequently, so I can study possible intersections. Perhaps even include a few completely unrelated projects just for fun :) + +To view the entire thing (including a Dockerfile I use to containerize it all) check out the [OpenLineage metrics GitHub project](https://github.com/OpenLineage/metrics), where pull requests are most welcome. I am easy to find - @rossturk on [GitHub](https://github.com/rossturk), [Twitter](https://mobile.twitter.com/rossturk), and dbt Slack - and am always interested in a chat about community metrics. diff --git a/website/blog/2021-11-29-the-missing-role-of-design-in-analytics.md b/website/blog/2021-11-29-the-missing-role-of-design-in-analytics.md new file mode 100644 index 00000000000..8487cd601e1 --- /dev/null +++ b/website/blog/2021-11-29-the-missing-role-of-design-in-analytics.md @@ -0,0 +1,192 @@ +--- +title: "The (Missing) Role of Design in Analytics" +description: "Opportunities to make the shift from building dashboards to designing analytical applications." +slug: design-for-analytics-towards-analytical-applications + +authors: [seth_rosen] + +tags: [analytics craft] +hide_table_of_contents: false + +date: 2021-11-29 +is_featured: false +--- + +If you’ve spoken to me lately, follow me on [Twitter](https://twitter.com/sethrosen), or have taken my order at [Wendy’s](https://i.ytimg.com/vi/_oMc4eD9-XM/maxresdefault.jpg), you probably know how much I hate traditional dashboards. My dad, a psychotherapist, has been working with me to get to the root of my upbringing that led to this deep-rooted feeling. + + + +As it turns out, the cause of my feelings towards traditional dashboarding are actually quite obvious. Before entering the field of data, I spent my entire career as a product manager working alongside user experience designers and engineers on cross-functional product teams. + +When building software, getting users to actually use the product is no easy feat. The smallest amount of friction can cause a user to abandon the flow. Add enough friction to any product and users and engagement will drop dramatically. As analysts, we know this intuitively. We are constantly measuring retention, cohorts, and engagement within our business. + +These principles also apply to analytics. The more friction there is in analytics and the less we focus on the user, the less our output will be used. So it makes me wonder why, within the field of data, is design thinking often so absent? + + +## Why are we lacking design thinking in analytics? + +Painting with broad strokes, design is generally not something that is a top priority for data teams. There are a few primary reasons that I see off the top: + +1. Data teams think within the limitations of their current tools, not the ideal user experience. +2. Traditional Dashboards have become so commoditized that there is a perception that anyone can build good ones. +3. There is a belief that analytics ends at the data visualization, not the user experience. +4. There is a general misconception that the overall look and feel does not matter in data analytics. +5. Stakeholders often ask for a “dashboard” when they actually need something else (with more functionality). + +These more or less boil down to data teams running like service teams rather than [product teams](https://locallyoptimistic.com/post/run-your-data-team-like-a-product-team/)—when you always give the squeakiest wheel the grease, it’s impossible to put in the strategic effort that design thinking requires. + +One solution I proposed back in 2019 is hiring a [data product manager](https://www.linkedin.com/pulse/why-your-organization-may-need-data-product-manager-seth-rosen/), which seems to be picking up a bit of steam. But what would that person actually do? + + I have attempted to sum the solutions to these complex issues into a table of overly-simplified do’s and don’ts: + + + + + + + + + + + + + + + + + + + + + + + + + + +
Don’t + Do +
Think only within the constraints of your current tooling. + First define the ideal user experience, irrespective of tooling. +
Think users can simply build their own solution given a self-service interface. + Recognize that hard ongoing problems require a design-focused analyst. +
Stop at the data visualization. + Think about how to group visualizations, the interactions, and purpose-built exploratory flows. +
Ignore look and feel. + Think about the overall aesthetics of your output. +
Just respond to tickets and user requests. + Truly try to understand the problem and design the appropriate solution. +
+ +## The Full-Stack Analyst and Analytical Applications + +An analyst who can gather the necessary data, transform it into the analytics-ready format, and understand & analyze it is an incredible asset to your team. An analyst who can also build a user experience around it is unstoppable. + +If you think about the workflow for an analyst, a simple process might go something like this: + +1. Initial exploratory analysis and ad-hoc queries +2. Model data in dbt +3. Build out data visualizations +4. Write tests/monitor performance + +But, you might also consider adding the following to your workflow. + +1. Build user stories and use cases: Work with the end-user to understand exactly why they need the data and what decisions they need to make. Generally speaking, do not ask them to define the solution. That’s your job. +2. Build out wireframes and user flows: A very quick sketch of the end-user experience can be shared for discussion. This might get some really great feedback about how the user may end up using the data. +3. Build out the user interface: Break free from the traditional dashboard design and implement the design which truly solves the pain. + +In order to realize the full potential of the ["full stack analyst"](https://roundup.getdbt.com/p/seth-rosen-topcoat)”, we must apply the principles of design to be part of our workflows. We should shift our thinking from making traditional dashboards to building user-centric [analytical applications](https://towardsdatascience.com/the-analytical-application-stack-eead8ce6b70). + +This simple shift from thinking in “dashboards” towards thinking in “analytical applications” is one of the key changes which has helped me be more design-focused. + +Here are a few examples: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Traditional Dashboards + Analytical Applications +
Built for generic use cases + Purpose-built for specific use cases +
Standard dashboard interactions + Interactive based on the desired workflow +
Fixed, static layout + Dynamic layout determined by logic +
Each element is a tile + Elements can be grouped and purposefully-arranged +
Filters are global + Users have preferences and their own defaults +
Minimal software development lifecycle + Strong SDLC to promote user trust +
Look and feel are ignored + Custom look and feel to match company products +
Low bar for performance + High bar for performance +
+ + +## An Example: Weather Applications + +Let’s take a look at one of the OG analytical applications: the weather forecast. + +Like most people, I rely on weather apps to make all sorts of decisions throughout the day. We are fortunate to have very smart and talented user experience designers working on these apps. + +[![twitter screenshot](/img/blog/analyst-ux-twitter.png)](https://twitter.com/sethrosen/status/1455176609288396807) + +Here are a few examples from AccuWeather and the decisions it enables me to make: + +![weather app screenshots](/img/blog/analyst-ux-weather.png) + +While the data being presented in the weather app could technically be presented in any dashboarding tool, the designers of this app agonized about every screen, interaction, and component to build a bespoke experience. + +When it is done right, the user has everything they need to make quick decisions and take appropriate actions. + +It’s worth noting this simple weather app is purpose-built for everyday weather situations. There are some use cases where highly specific information may be needed by a particular subset of users. + +For example, surfers want different information. Ultimately, they may want an overall "Surf or don't surf" recommendation. Additionally, pilots could never simply rely on AccuWeather. These use cases warrant their own user-centered, purpose-built experiences. + + +## The missing piece of the puzzle + +While a design process can help you build better analytics output, there is still a missing part of the analytics stack to enable true user-centered design. + +How would you, today, build out a weather-like application? + +Traditional dashboarding tools limit the user experience and prevent purpose-built applications from being created. Luckily our tools are evolving to meet the needs of the data consumer. + +I encourage you to explore these new tools as much as possible and to work design into your analytics workflows. I’m always up for chatting, especially about this - my DMs are always open on [Twitter](https://twitter.com/sethrosen). diff --git a/website/blog/2021-12-05-how-to-build-a-mature-dbt-project-from-scratch.md b/website/blog/2021-12-05-how-to-build-a-mature-dbt-project-from-scratch.md new file mode 100644 index 00000000000..00ed7ee35c8 --- /dev/null +++ b/website/blog/2021-12-05-how-to-build-a-mature-dbt-project-from-scratch.md @@ -0,0 +1,208 @@ +--- +title: "How to Build a Mature dbt Project from Scratch" +description: "A guide to how to start and evolve a dbt project." +slug: how-to-build-a-mature-dbt-project-from-scratch + +authors: [dave_connors] + +tags: [dbt tutorials] +hide_table_of_contents: false + +date: 2021-12-06 +is_featured: true +--- + +# Building a Mature dbt Project from Scratch + +> *[We would love to have] A maturity curve of an end-to-end dbt implementation for each version of dbt .... There are so many features in dbt now but it'd be great to understand, "what is the minimum set of dbt features/components that need to go into a base-level dbt implementation?...and then what are the things that are extra credit?"* +-*Will Weld on dbt Community Slack* + +One question we hear time and time again is this - what does it look like to progress through the different stages of maturity on a dbt project? + +When Will posed this question on Slack, it got me thinking about what it would take to create a framework for dbt project maturity. + +As an analytics engineer on the professional services team at dbt Labs, my teammates and I have had the unique opportunity to work on an unusually high number dbt projects at organizations ranging from tiny startups to Fortune 500 companies and everything in between. From this vantage point, we have gained a unique understanding of the dbt adoption curve - how companies actually implement and expand their usage of dbt. + +With every new engagement, we find ourselves working in a project with a unique mix of data challenges. With the explosion in popularity of dbt, and the constant release of new features and capabilities available in the tool, it’s really easy for data teams to go down the rabbit hole of dbt’s shiniest new features before prioritizing the simple ones that will likely be the most immediately impactful to their organization. + +A lot of teams find themselves in this position because getting the organizational buy-in for the tool is actually the *easy* part. Folks have a lot of freedom to go ahead to try out dbt, but once you get started it can be hard to know whether you are taking advantage of all the dbt features that would be right for your project. + +In working alongside teams on their dbt journey, we’ve noticed that there tend to be distinct stages of dbt usage that organizations progress through. We’ve come to think of these stages as representing **dbt project maturity. ** + +We can break the concept of maturity down into two categories. The first is** feature** **completeness**, or the number of distinct dbt features you are using. The other is** feature depth**, the level of sophistication within the use of individual features. For example, adding the source feature to your project would be increasing the completeness of your project, but adding the source freshness feature to the sources you already defined would be a way to add depth to your project. Walking along this matrix we can watch a teeny tiny baby project grow into a fully mature production grade dbt pipeline. + +![image alt text](/img/blog/building-a-mature-dbt-project-from-scratch/image_0.png) + +**How do we do this?** + +Let’s pretend that we are an analytics engineer at Seeq Wellness, a hypothetical EHR (electronic health record!) company, and we want to try out dbt to model our patient, doctor and claims data for a critical KPI dashboard. We’re going to create a new dbt project together, and walk through the stages of development, incrementally adding key dbt features as we go along. + +[We’ve developed a repository](https://github.com/dbt-labs/dbt-project-maturity) that traces the progress in this project; **for each step along the maturity curve**, there is a subfolder in that repo with a **fully functional version of our dbt project** at that stage. We’ve also included some sample raw data to add to your warehouse so you can run these projects yourself! You can use this repository to **benchmark the maturity of your own dbt project**. + +## Caveats and Assumptions + +**This is an art, not science!** + +*There are real life use cases where some features get introduced into projects out of the order described here, and that is perfectly reasonable. There are often justifiable reasons to introduce more advanced dbt features earlier in the development cycle.* + +**You are the pace setter** + +*There is no sense of timescale in this presentation! Some teams may mature their project in weeks rather than months. It's more important to think about ***_how_*** features build upon themselves (and each other) rather than ***_how quickly_*** they do so.* + +## Level 1 - Infancy - Running your first model + +**Key Outcomes** + +* Create your first [model](/docs/building-a-dbt-project/building-models) + +* Execute your first [dbt run](/reference/commands/run) + +![image alt text](/img/blog/building-a-mature-dbt-project-from-scratch/image_1.png) + +**Themes and Goals** + +Now, I definitely have no authority to speak on what it takes to raise a child, but I understand that a big part of caring for an infant has to do with taking care of its inputs and outputs. The same can be said about a dbt project in this stage! + +The goal here is to learn the very basics of interacting with a dbt project; feeding it SQL, getting data objects out of it. We will build on this later, but right now, the important thing to do is create a model in dbt, give dbt a command, and see that it properly produces the or in our warehouse that we expect. + +In addition to learning the basic pieces of dbt, we're familiarizing ourselves with the modern, version-controlled analytics engineering workflow, and experimenting with how it feels to use it at our organization. + +If we decide not to do this, we end up missing out on what the dbt workflow has to offer. If you want to learn more about why we think analytics engineering with dbt is the way to go, I encourage you to read the [dbt Viewpoint](/docs/about/viewpoint)! + +In order to learn the basics, we’re going to [port over the SQL file](/guides/getting-started/learning-more/refactoring-legacy-sql) that powers our existing "patient_claim_summary" report that we use in our KPI dashboard in parallel to our old transformation process. We’re not ripping out the old plumbing just yet. In doing so, we're going to try dbt on for size and get used to interfacing with a dbt project. + +**Project Appearance** + +We have one single SQL model in our models folder, and really, that's it. At this stage, the README and dbt_project.yml are just artifacts from the [dbt init command](/reference/commands/init), and don’t yet have specific documentation or configuration. At this stage of our journey, we just want to get up and running with a functional dbt project. + +![image alt text](/img/blog/building-a-mature-dbt-project-from-scratch/image_2.png) + +The most important thing we’re introducing when your project is an infant is the modern, version-controlled, collaborative approach to analytics that dbt offers. The thrill of executing your first successful dbt run is all you need to do to understand how dbt can be massively impactful to your analytics team. + +## Level 2 - Toddlerhood - Building Modular Data Models + +**Key Outcomes** + +* Configure your first [sources](/docs/building-a-dbt-project/using-sources) + +* Introduce modularity with [{{ ref() }}](/reference/dbt-jinja-functions/ref) and [{{ source() }}](/reference/dbt-jinja-functions/source) + +* [Document](/docs/building-a-dbt-project/documentation) and [test](/docs/building-a-dbt-project/tests) your first models + +![image alt text](/img/blog/building-a-mature-dbt-project-from-scratch/image_3.png) + +**Themes and Goals** + +Now that we're comfortable translating SQL into a model from our infant project, it's time to teach our project to take its very first steps. + +Specifically, now is when it's useful to introduce **_modularity_** to our project. + +We’re going to: + +* Break out reused code into separate models and use [{{ ](/reference/dbt-jinja-functions/ref)[ref](/reference/dbt-jinja-functions/ref)[() }}](/reference/dbt-jinja-functions/ref) to build dependencies + +* Use the[ {{ source() }}](/reference/commands/source) macro to declare our raw data dependencies + +* Dip our toes into testing and documenting our models + +**Project Appearance** + +Let's check in on the growth of [our projec](https://github.com/dbt-labs/dbt-project-maturity/tree/main/2-toddlerhood)t. We've broken some of our logic into its own model — our original script had repetitive logic in subqueries, now it's following a key principle of analytics engineering: Don't Repeat Yourself (DRY). For more information on how to refactor your SQL queries for Modularity - check out our [free on-demand course](https://courses.getdbt.com/courses/refactoring-sql-for-modularity). + +We also added our first [YML files](https://circleci.com/blog/what-is-yaml-a-beginner-s-guide/). Here, we have one yml file to [configure our sources](https://github.com/dbt-labs/dbt-project-maturity/blob/main/2-toddlerhood/models/source.yml), and one one yml file to [describe our models](https://github.com/dbt-labs/dbt-project-maturity/blob/main/2-toddlerhood/models/schema.yml). We're just starting with basic declarations of our sources, testing using dbt built in tests, and a model-level description -- these are the first steps of a project just learning to walk! + +![image alt text](/img/blog/building-a-mature-dbt-project-from-scratch/image_4.png) + +Leveling up from infant to toddler is a huge jump in terms of feature completeness! By adding in sources and refs, we’ve really started to take advantage of what makes dbt special. + +## Level 3 - Childhood - Developing Standards for Code Collaboration and Maintainability + +**Key Outcomes** + +* Standardize [project structure](https://discourse.getdbt.com/t/how-we-structure-our-dbt-projects/355), [SQL style guide](https://github.com/dbt-labs/corp/blob/master/dbt_style_guide.md) and [model naming conventions](https://www.getdbt.com/analytics-engineering/modular-data-modeling-technique/) in a contribution guide + +* Develop testing and documentation requirements + +* Create a PR template to ensure quality and consistency + +* [Deploy your project](/docs/running-a-dbt-project/running-dbt-in-production)! + +![image alt text](/img/blog/building-a-mature-dbt-project-from-scratch/image_5.png) + +**Themes and Goals** + +We made a huge jump in our feature completeness in the last stage - now it’s time to think about getting the project ready to be used by multiple developers and even deployed into production. The best way to ensure consistency as we start collaborating is to define standards for how we write code and model data then enforce them in the review process. From the data team's perspective, we shouldn't be able to infer who wrote what line of code because one of our teammates uses the dreaded leading comma. Analytics code is an asset, and should be treated as production grade software. Project Appearance + +We've added project-level documentation to [our repo](https://github.com/dbt-labs/dbt-project-maturity/tree/main/3-childhood) for developers to review as they get started in this project. This generally includes: + +1. A [contribution and SQL style guide](https://github.com/dbt-labs/dbt-project-maturity/blob/main/3-childhood/CONTRIBUTING.md). + +2. A [README](https://github.com/dbt-labs/dbt-project-maturity/blob/main/3-childhood/README.md) with a set up guide with project-specific resources and links out to general dbt resources. + +3. A [pull request template](https://github.com/dbt-labs/dbt-project-maturity/blob/main/3-childhood/.github/pull_request_template.md) to make sure we're checking new code against these guidelines every time we want to add new modeling work! + +Let's look at our models — we went from a eary stage DAG, starting to get a feel for modularity, to a clean, standardized and logically organized DAG — we can now see logical layers of modeling that correspond the file tree structure we saw before — we can even see the model naming conventions lining up with these layers (stg, int, fct). Defining the standards in how we organize our models in our project level has resulted in a cleaner, easier to understand DAG too! + +![image alt text](/img/blog/building-a-mature-dbt-project-from-scratch/image_6.png) + +Even though we haven't changed the function of a lot of our features *codifying and standardizing the use of these features is a huge step forward for project maturity.* Getting to this level of maturity is when we generally start to think about running this project in production. With these guardrails in place, we can be confident our project isn’t going to fall out of bed at night and hurt itself -- it’s ready to take on a little bit of independence! + +## Level 4 - Adolescence - Increasing Flexibility + +**Key Outcomes** + +* Leverage code from dbt [packages](/docs/building-a-dbt-project/package-management) + +* Increase model flexibility and scope of project + +* Reduce dbt production build times with [advanced materializations](/docs/building-a-dbt-project/building-models/materializations) + +![image alt text](/img/blog/building-a-mature-dbt-project-from-scratch/image_7.png) + +**Themes and Goals** + +Wow, our project is growing up fast — it's heading off into the world, learning new things, getting into trouble (don't worry that's just normal teen stuff). Our project is finally starting to think about its place in the world and in the greater dbt ecosystem. It's also starting to get buy-in from our stakeholders, and they want *more. *At this stage, learning how to do some more advanced tricks with dbt can allow us to think beyond the business logic we’re defining, and instead think more about *how *that business logic is built. Where can we make this project more efficient? How can we start serving up more information *about* our data to our stakeholders? + +I want to also call out that a "feature" to introduce at this stage is engagement with the [dbt community](https://www.getdbt.com/community/) — in reality, I'm hopeful that we'd have been doing that this whole time, but thinking about opening up your projects to community-supported packages, as well as using the braintrust in the community Slack as a jumping off point for solving some of your data problems starts to really blossom around this point in the project lifecycle. + +**Project Appearance** + +We can see the major development at [this stage](https://github.com/dbt-labs/dbt-project-maturity/tree/main/4-adolescence) is adding additional models that make our original claims report a lot more flexible -- we had only shown our users a subset of patient and doctor information in our fact model. Now, we have a more Kimball-ish-style marts set up, and we can leave selecting the dimensions up to our BI tool. + +![image alt text](/img/blog/building-a-mature-dbt-project-from-scratch/image_8.png) + +Other enhancements not seen in the DAG at this stage include new custom macros to make SQL writing more dynamic and less repetitive. We can also see a packages.yml file, and we can start leveraging tests, macros, and even models developed by the dbt community. Leveraging package code is a key way to shrink our development time! We've also leveled up to using incremental logic for our largest data sets to speed up our runs and deliver insights faster. We're also interested in surfacing a little bit of the metadata from our project — we can start by enhancing our marts with data about its recency by enabling the source freshness feature. Knowing that the data in our dashboard is up to date and reliable can massively improve consumer confidence in our stack. + +We've spent this level focused on deepening and optimizing our feature set — we haven't introduced much more feature completeness except for SQL macros and the use of packages. Now, we're strong enough dbt developers that our time and energy is focused on taking a step back from making this project work to thinking about how to make it work *well*. + +## Level 5 - Adulthood - Solidifying Relationships + +**Key Outcomes** + +* Formalize dbt’s relationship to BI with [exposures](/docs/building-a-dbt-project/exposures)! + +* Advanced use of metadata + +![image alt text](/img/blog/building-a-mature-dbt-project-from-scratch/image_9.png)Themes and Goals + +In adulthood, we're turning our gaze even further inward. Our dbt project itself is independent enough to start asking itself the big questions! What does it mean to be a dbt project in the year 2021? How have I been changing? How am I relating to my peers? + +At this point, like we started to do in adolescence, we are going to focus on thinking about dbt-as-a-product, and how that product interacts with the rest of our stack. We are sinking our roots a layer deeper. + +**Project Appearance** + +We see the biggest jump from the previous stage in the [macros folder](https://github.com/dbt-labs/dbt-project-maturity/tree/main/5-adulthood/macros). By introducing advanced macros that go beyond simple SQL templating, we’re able to have dbt deepen its relationship to our warehouse. Now we can have dbt manage things like custom schema behavior, run post hooks to drop retired models and dynamically orchestrate object permission controls; dbt itself can become your command post for warehouse management. + +Additionally, we’ve added an exposures file to formally define the use of our marts models in our BI tool. Exposures are the most mature way to declare the data team's contracts with data consumers. We now have close to end-to-end awareness of the data lineage — we know what data our project depends on, whether it's fresh, how it is transformed in our dbt models, and finally where it’s consumed in reports. Now, we can also know which of our key reports are impacted if and when we hit an error at any point in this flow. + +That end to end awareness is visible on the DAG too — we can see the dashboard we declared in our exposures file here in orange! + +![image alt text](/img/blog/building-a-mature-dbt-project-from-scratch/image_10.png) + +Making the jump to thinking about metadata is a really powerful way to find areas for improvement in your project. For example, you can develop macros to measure things like your test coverage, and test to model ratio. You can look into packages like dbt_meta_testing to ensure your hitting minimum testing and documentation requirements. + +If you're on cloud, you can do all of these and more in a more programmatic way with the metadata API — you can dig into model runtimes and bottlenecks, and leverage exposures directly in your BI tool to bring that metadata to your end users! Neat! + +## Conclusion + +Life is truly a highway. We’ve traced the growth of the Seeq Wellness dbt project from birth to mid-life crisis, and we have so much growing left to do. Hopefully you can use this framework as a jumping off point to find areas in your own projects where it could stand to grow up a bit. We would love to hear from you in the repo if there are any questions, disagreements, or enhancements you’d like to see here! Another huge thank you to Will Weld, who was instrumental in developing this framework! diff --git a/website/blog/2022-01-12-time-on-task-calculation.md b/website/blog/2022-01-12-time-on-task-calculation.md new file mode 100644 index 00000000000..d4b3dac0666 --- /dev/null +++ b/website/blog/2022-01-12-time-on-task-calculation.md @@ -0,0 +1,168 @@ +--- +title: "How We Calculate Time on Task, the Business Hours Between Two Dates" +description: "An overview of how to calculate the Time on Task metric, the number of business hours between two dates, in SQL." +slug: measuring-business-hours-sql-time-on-task + +authors: [dave_connors] + +tags: [analytics craft] +hide_table_of_contents: false + +date: 2022-02-03 +is_featured: false +--- + +Measuring the number of business hours between two dates using SQL is one of those classic problems that sounds simple yet has [plagued analysts since time immemorial](https://www.sqlteam.com/forums/topic.asp?TOPIC_ID=74645). + +This comes up in a couple places at dbt Labs: + +* Calculating the time it takes for a support ticket to be solved +* Measuring team performance against response time SLAs + +We internally refer to this at "Time on Task," and it can be a critical data point for customer or client facing teams. Thankfully our tools for calculating Time on Task have improved just a little bit since 2006. + +Even still, you've got to do some pretty gnarly SQL or dbt gymnastics to get this right, including: + +1. Figuring out how to exclude nights and weekends from your SQL calculations +2. Accounting for holidays using a custom holiday calendar +3. Accommodating for changes in business hour schedules + +This piece will provide an overview of how and critically *why* to calculate Time on Task and how we use it here at dbt Labs. + + + +## Two strategies to calculate Time on Task + +1. One size fits all with nested macros + +This solution allowed us to create a one-line [dbt macro](/docs/building-a-dbt-project/jinja-macros#macros) to account for most common Time On Task use cases by having a series of nested macros behind the scenes. + +This strategy does a great job in being able to account for nights, weekends and custom holidays, but lacks the flexibility to accommodate changes in business hours, so we've transitioned off of it to the 2nd option: + +2. Bespoke and customizable with a subquery + +Our current production Time on Task calculation is able to be both powerful and flexible by bringing in a construct you rarely see at dbt Labs - a _[gasp]_ . By using an hourly-grain date , you are able to standardize your organization's unique definition of business hours vs. non business hours in a fully customizable way. + +You can find example code for each of these approaches in [an example repo](https://github.com/dbt-labs/dbt-labs-experimental-features/tree/master/business-hours). + +After we’ve walked through the mechanics of calculating Time on Task, we’ll spend some time thinking about how and why to use this metric in your reporting. Time on Task can be a huge boon for operational reporting, but like any metric it has inherent strengths and weaknesses in terms of reflecting actual business value. + +We’ve put together a series of questions to ask yourself to make sure that you are optimizing Time on Task for the problems it is best suited to solve. + +## The one size fits all solution: nested macros + +Our first approach to calculating Time on Task relied upon tying together a series of macros. Specifically, as we diagram below, we needed a way to model non-working time to properly remove it from a standard `date_diff` calculation. + +This approach works great for the case where we have a standard business schedule, but falls flat when we want to bring in more complex, real world applications. + +Let’s assume that your customer support team always works Monday to Friday, and from 8am to 8pm, and your schedule looks something like this: + +![image alt text](/img/blog/2022-01-12-time-on-task/image_0.png) + +And let’s say you have a few tickets that come in, and your team works through them diligently, as always: + +![image alt text](/img/blog/2022-01-12-time-on-task/image_1.png) + +Our schedule-aware metric should only capture the non-grey time: + +![image alt text](/img/blog/2022-01-12-time-on-task/image_2.png) + +How do we get there? For any of these tickets, the general formula to get the answer we want can be boiled down to subtracting non-working time from the total amount of time between the dates (i.e. a regular ol’ datediff): + +![image alt text](/img/blog/2022-01-12-time-on-task/image_3.png) + +Those blocks of non-working time can be broken down into two sections: overnights and weekends. But how can we dynamically count the number of overnights or weekend days? Enter the weekday macro! + +### How to exclude weekends? + +Building off the excellent [work](https://help.looker.com/hc/en-us/articles/360023861113-How-to-Count-Only-Weekdays-Between-Two-Dates) of the intrepid staff over at Looker, we created a macro that returns the number of weekdays between two dates. It works by calculating the number of calendar days between two timestamps, then subtracting the number of Saturdays and Sundays from that result. So, for a ticket created on a Monday, closed on Tuesday, the `weekdays_between` macro returns 1. For a ticket opened on a Thursday, closed on the following Monday, this macro returns 2! + +This ends up being helpful twice - the result of the weekdays macro is the same as the number of overnights between two dates, which is effectively the first half of our non-working time formula. Multiplying the number of weekdays between the two dates by the daily window of non-working time gets us the number of overnight hours (in our example, this window is 8pm - 8am, or 12 hours). + +We can use this result to measure the number of weekend days between the two dates – subtracting the number of weekdays from the total number of days between the two dates gives you the number of weekend days. Let’s focus on our example ticket that was opened on Friday and closed on Monday to explain: + +![image alt text](/img/blog/2022-01-12-time-on-task/image_4.png) + +You might have already picked up the huge caveat here — a consistent schedule is baked into this calculation, and that’s usually not the case. Throw in a public holiday, or a new hire in a different time zone, and suddenly these calculations stop reflecting reality! Some edge cases and how we deal with them: + + +### What if a ticket comes in outside business hours? + +In the past, we had a workaround baked into the ticket table itself! We maintain a `all_business_hours` model in our project using the `date_spine` macro from dbt_utils. This creates a table at the hour level, and we add a custom boolean column that indicates whether that hour is within our 8am - 8pm working hour window. We then join this to our ticket data, and for each ticket timestamp of interest, create a new column that returns *the next available business hour.* + +So for any timestamp that is already in business hours like the above example, the timestamp_business column is identical, but for any ticket that comes in outside business hours, it returns the first business hour of the following day - i.e. a ticket made late Wednesday night has a start_business timestamp of 8:00am on Thursday. This allows us to only ever perform these calculations on timestamps that appear within our working hours. + +### What about holidays? + +We maintain a [seed file](/docs/building-a-dbt-project/seeds) in our project that has the dates of holidays for the next 5 years or so - we join this to our hour-level date_dim table, and incorporate holidays into the boolean column mentioned above. This way, any ticket that comes in on a holiday gets fast forwarded to the beginning of the next working day. Not a perfect solution, so curious to hear how this is handled elsewhere! + +## The customizable option: a bespoke calendar + subquery + +Our first measurement approach recently needed to be adjusted when our business hours changed. It was immediately obvious that this Jenga-tower of macros was too difficult to parse and did not easily accommodate the changes we needed to make. We decided to scrap the whole thing and simplify with the rare (for us!) use of a correlated subquery. + +### How we accounted for changing business hours +We realized that since we were already maintaining an hourly-grain date dimension table using the [datespine macro from dbt_utils](https://github.com/dbt-labs/dbt-utils/blob/0.7.4/macros/sql/date_spine.sql), as mentioned above, we could adjust the boolean `is_business_hour` to reflect the changing schedules over time. Then, we can use the hourly grain table to control the aggregation properly without overly complex macros. The options to accomplish that were: + +1. Join directly to the hour-grain table, aggregate after the fact + +2. Use a subquery to perform the aggregation + +Given that we were actually calculating several of these metrics on one single table of tickets (think: time to first touch, time to first close, time to last touch, etc), direct joining would cause *a lot* of competing fanout that we decided would be too difficult to manage. + +Generally speaking, the dbt Labs team tends to opt for use of CTEs rather than subqueries, but this was one of the few times where the benefits seemed to outweigh the tradeoffs. A subquery allowed us to perform our business hours calculation on any two date fields without changing the grain of our tickets model. + +Here’s an example to explain our subquery approach:If working hours for our team are 8AM - 8PM, and a ticket was opened at 8:46 AM Tues, closed 1:13PM Wed on an 8-8 schedule to measure the business hours from open to close, you’d need to include: + +* 14 minutes (8:46 AM - 9AM) + + +* 16 hours (9AM-8PM Tues + 8am-1pm Wed) + + +* 13 min (1PM - 1:13PM) + +Which reduces down to: + +``` + +select + + (60 - extract(minute from start_time) + + + ( select count_if(is_business_hour) * 60 from all_business_hours where date_hour > start_date and date_hour < end_date ) + + + ( extract(minute from end_time) + +from table + +``` + +## What's the value of accurately measuring business hours? + +Let’s step back and think about what utility these metrics actually have. What is the benefit of having a schedule-sensitive metric versus just doing a simple date_diff() function and finding the total elapsed time? + +I've found business-adjusted time measures to be helpful in a few ways: + +1. SLA metrics + + 1. Answering questions like "what percent of tickets are responded to within 15 working minutes?" are great applications of these metrics! + +2. Is my staff using their time well? + +3. What is the capacity of an FTE to get through the work we have? + +4. How many more FTEs will I need to hire to get through the inbound work? + +5. Did that process/tooling change I made have any significant impact on how well my team can do their jobs? + +### What business-adjusted time measures won’t tell you + +1. Was my customer frustrated by how long this took? (A ticket might have taken your team a couple hours of working time, but if the elapsed time went overnight or over the weekend, it still feels that long to the customer!) + + 1. If they were, am I communicating the expectations for response time well enough to my customers? + +So is there utility in measuring these metrics in a way that takes working hours into account? I think so! But as mentioned in our [slack community a while back](https://getdbt.slack.com/archives/C0VLZPLAE/p1606928499154300), doing so in isolation doesn’t give you the whole story of how your customers are feeling when interacting with your team. A great quote from community member James Weakley: + +> "Any measures that take the support team's schedules into account are process measures rather than outcome measures. In other words, they are very useful for workforce planning or process improvement, but anyone who has logged support cases with large companies will know that they won't correlate with customer happiness as they are far too easy to game." + +I totally agree with James here, and think these metrics are most useful when they are answering specific questions about your tools and processes. They can’t tell you much about what the customer is feeling, which is why they should be paired with schedule-agnostic metrics that actually tell you what it’s like from the customer’s perspective (as well as with direct customer satisfaction measures like surveys!). + +Special thanks to Claire Carroll and Erica Louie for helping on this work! Some sample data and code for both approaches can be found in [this repo](https://github.com/dbt-labs/dbt-labs-experimental-features/tree/master/business-hours). diff --git a/website/blog/2022-02-07-customer-360-view-census-playbook.md b/website/blog/2022-02-07-customer-360-view-census-playbook.md new file mode 100644 index 00000000000..8da0a488372 --- /dev/null +++ b/website/blog/2022-02-07-customer-360-view-census-playbook.md @@ -0,0 +1,404 @@ +--- +title: "The JaffleGaggle Story: Data Modeling for a Customer 360 View" +description: "The core challenge of building a customer 360 view is identity resolution. How do you map individual users of a freemium product to potential customer accounts?" +slug: customer-360-view-identity-resolution + +authors: [donny_flynn] + +tags: [analytics craft] +hide_table_of_contents: false + +date: 2022-02-08 +is_featured: true +--- + +*Editor's note: In this tutorial, Donny walks through the fictional story of a SaaS company called JaffleGaggle, who needs to group their freemium individual users into company accounts (aka a customer 360 view) in order to drive their product-led growth efforts.* + +*You can follow along with Donny's data modeling technique for identity resolution in [this dbt project repo](https://github.com/dflynn20/jaffle_gaggle). It includes a set of demo CSV files, which you can use as [dbt seeds](https://docs.getdbt.com/docs/building-a-dbt-project/seeds) to test Donny's project for yourself.* + + + +**Before we begin: a quick note on Jaffles** + +If you’ve been in the sphere of dbt, you probably know the lore of the Jaffle shop. If not, I’d recommend taking a second to look at Claire Carroll’s [README for the original Jaffle Shop demo project](https://github.com/dbt-labs/jaffle_shop) (otherwise this playbook is probably going to be a little weird, but still useful, to read). + +In short, a jaffle is: + +> "A toasted sandwich with crimped, sealed edges. Invented in Bondi in 1949, the humble jaffle is an Australian classic. The sealed edges allow jaffle-eaters to enjoy liquid fillings inside the sandwich, which reach temperatures close to the core of the earth during cooking. Often consumed at home after a night out, the most classic filling is tinned spaghetti, while my personal favourite is leftover beef stew with melted cheese." + +![freshly-toasted jaffles](/img/blog/2022-02-08-customer-360-view/image_0.jpg) + +*See above: Tasty, tasty jaffles.* + +Jaffle Shop is a demo repo referenced in [dbt’s Getting Started Guide](guides/getting-started), and its jaffles hold a special place in the dbt community’s hearts, as well as on Data Twitter™. + +![jaffles on data twitter](/img/blog/2022-02-08-customer-360-view/image_1.png) + +So, I thought it only apt to build on the collective reverence for these tasty, crunchy snacks to talk about customer 360 views. + +## What's a customer 360? +A customer 360 is a fancy way of saying that you have a holistic dataset that lets understand your customers’ behavior. It involves being able to link together all of the different kinds of data you collect about customers via identity resolution, which we’ll talk through later in this tutorial. + +This can be challenging because people move companies, create new accounts with different email addresses, or the same company might have different associated workspaces (gaggles 🦢 in our case). + +All this to say, creating a customer 360 view is a powerful way to gain understanding of your customers and users, but can come with challenges (which we’ll help you work through). + +**Meet JaffleGaggle, our fictitious company** + +In our fictitious data world for today’s example, a B2B company saw that people really loved a thing (e.g. jaffles) and found a way to scale that beloved thing into a business. **Enter JaffleGaggle.** + +There are two parts of JaffleGaggle’s product: + +1. **A feed of jaffle recipes**, supported with functionality that lets you order all the ingredients you need to make late-night jaffles at home. + +2. **Social groups** to foster bonding among a company’s teams (lovingly called a Gaggle) where coworkers can invite each other with a free email for virtual jaffle hours. + +JaffleGaggle is growing rapidly and has just bought a CRM (yay!), but it’s currently empty (less yay 😟). By the end of this guide, you and the JaffleGaggle data team will know how to use dbt to model account, user, and event data from usage of their application and aggregate it into their warehouse, to upload to a CRM for use by the sales team. + +As people invite more of their peers to their Gaggle, they’re able to unlock even more recipes and jaffles. + +![a live look at jafflegaggle](/img/blog/2022-02-08-customer-360-view/jafflegaggle_screenshot.png) + +**Seen above**: One of the many, many delicious jaffle recipes that await teams on JaffleGaggle. + +OK, now that we’ve got you hungry for some tasty, tasty jaffles, here’s what this has to do with data and product led-growth (aka PLG). + +## How a customer 360 view supports product-led growth + +JaffleGaggle is, like many startups, focused on signing companies to annual contracts so they can raise Venture Capital funding (at an insane multiple). To do so, they want to build out their sales motion to target companies with active gaggles. + +JaffleGaggle has to keep track of information about their interactions with their customers and the businesses they belong to, including data to enable to sales team to answer a few key questions: + +* How has a user been interacting with the platform? +* How many workspaces are associated with a company? +* Who are the company’s power users that should be reached out to? + +All of these questions require aggregating + syncing data from application usage, workspace information, and orders into the CRM for the sales team to have at their fingertips. + +This aggregation process requires an analytics warehouse, as all of these things need to be synced together outside of the application database itself to incorporate other data sources (billing / events information, past touchpoints in the CRM, etc). Thus, we can create our fancy customer 360 within JaffleGaggle’s , which is a standard project for a B2B company’s data team. + +**Diving into data modeling** + +In this playbook, I’ll take you along on JaffleGaggle’s journey to build a customer 360 view using dbt so they (and you, too) can supercharge their PLG strategy with better data (and spread the love of jaffles everywhere). + +The data structure breaks down as follows: + +* 823 gaggles +* 5,781 users (unique by email, can only be associated with one gaggle) +* 120,307 events (‘recipe_viewed’, ‘recipe_favorited’, or ‘order_placed’) + +Let’s get rolling. + +> Builder Beware! If this was an actual event stream, it would be much better to leverage [incremental models based on timestamp](/docs/building-a-dbt-project/building-models/configuring-incremental-models), but because it’s a playground project, I did not. + +## Step 1: Define our entities + +For a freemium product like this one, where users only sign up with their email address, it’s best practice to use the email domain for users as the unique identifier for accounts. There could be multiple gaggles associated with a singular corporate email domain, thus belonging to a singular account. + +Below, I’ll break down the DAG at each step of our process so you can see how it builds all together. + +To use our CRM, we’ll need to **upload data for the following**: + +* **Contacts** (contacts that are unique by email address) + +![contacts in the dbt DAG](/img/blog/2022-02-08-customer-360-view/image_2.png) + +* **Gaggles** (understanding the activity of a workspace) + +![gaggles in the dbt DAG](/img/blog/2022-02-08-customer-360-view/image_3.png) + +* **Accounts** (companies our sales team can track and prioritize) + +![accounts in the dbt DAG](/img/blog/2022-02-08-customer-360-view/image_4.png) + +## Step 2: Model the contact + +We’ll start at the lowest level, which are the contacts the sales team wants to reach out to, and we will then work our way up to the account. To do so, we’ll focus on three steps: + +1. Performing the email domain extraction from the email + +2. Flagging personal emails + +3. Creating a column for corporate emails + +After we complete these steps, we’ll also cover a "human in the loop" step to ensure data integrity at the modelling stage. All of this put together will help guarantee that, when contacting a user, the sales team has all of the relevant product usage information at their fingertips. + +### Step 2.1: Extract email domain from an email + +For this step, take a look at a snippet from [`models/staging/stg_users.sql`](https://github.com/dflynn20/jaffle_gaggle/blob/main/models/staging/stg_users.sql) below. In it, we **perform the email domain extraction from the email**. + +``` + select + id as user_id, + name as user_name, + email, + + {{ extract_email_domain('email') }} AS email_domain, + + gaggle_id, + created_at + + from source +``` + +We defined the email domain extraction as a [macro](https://docs.getdbt.com/docs/building-a-dbt-project/jinja-macros) called [`extract_email_domain`](https://github.com/dflynn20/jaffle_gaggle/blob/main/macros/extract_email_domain.sql), which we call in line 18 (which you can find in the pullout below). + +This uses a regex to capture the text to the right of the ‘@’ character and makes sure to only use the lowercase email parameter before extracting the domain. This is because email domains aren’t case sensitive, but SQL is (see users 2954 and 3140 in the [seed data](https://github.com/dflynn20/jaffle_gaggle/blob/main/data/raw_user.csv) for an example). + + +``` +{% macro extract_email_domain(email) %} + +{# This is the SQL to extract the email domain in the Snowflake Flavor of SQL #} + + regexp_substr(lower({{ email }}), '@(.*)', 1, 1, 'e',1) + +{% endmacro %} +``` + +> Builder Beware! Notice we didn’t check for improperly formatted emails, like periods at the end of the domain or whitespaces. Make sure you check your dataset to see if this is a valid assumption. + +Generally, it’d be useful to leverage a regular expression to strip and pull down an email address. However, because this is a B2B use case, not all email domains are created equal. We want to make sure we flag personal emails so they’re treated differently than the corporate emails our sales team will reach out to (this makes sales outreach more productive, and ensures we aren’t contacting people more than once). + +**Tip:** If you’re building out a definition like "personal email domains" for the first time, I strongly recommend building alignment upfront with the rest of the business. . Understanding the impact and having a shared understanding of these kinds of definitions reduces friction and allows you to [run your data team like a product team](https://locallyoptimistic.com/post/run-your-data-team-like-a-product-team/) rather than responding to ad hoc service requests. + +### Step 2.2: Flag personal emails + +Next, we can **flag personal emails** with [`models/jafflegaggle_contacts.sql`](https://github.com/dflynn20/jaffle_gaggle/blob/main/models/jafflegaggle_contacts.sql), which calls another macro at the top of the file to pull in the personal emails we would like to exclude: + +``` +{% macro get_personal_emails() %} + + {{ return(('gmail.com', 'outlook.com', 'yahoo.com', 'icloud.com', 'hotmail.com')) }} + +{% endmacro %} +``` + +One of the great things about writing this as a macro in dbt is that the data team can easily reuse this file in other places in the codebase. + +Doing so improves consistency and makes sure additions or deletions to this personal email list are up to date. + +### Step 2.3: Create a column for corporate email + +Next, we’ll **create a column for corporate email** that will be null if an email domain is personal, also in the same `jafflegaggle_contacts` model: + +``` +iff(users.email_domain in {{ personal_emails }}, null, users.email_domain) + + as corporate_email +``` + +> Builder beware! Not all of these treatments are exhaustive. You might encounter country suffixes on email domains or other domains entirely. Be sure to check for your own use case, and add the columns that make the most sense in your scenario. + +The other aspects to this users model are related to the event data we reference in the event stream. For example, the `order_placed` event is broken out in a because it’s important to our use case at JaffleGaggle (it’s the basis for getting that dough 💰). + +``` +order_events as ( + + select + user_id, + + min(timestamp) as first_order, + max(timestamp) as most_recent_order, + count(event_id) as number_of_orders + + from events + where event_name = 'order_placed' + group by 1 + +), +``` + +By the end of the `jafflegaggle_contacts` model, we have a unified of events by user email, with personal email domains filtered out. + +### Step 2.4: Merging duplicate contacts + +> Definition: When I write "Human in the Loop" I mean that operational people at the company are contributing to data integrity at the modelling stage and reviewing data for quality. This is very important for making sure that the domain knowledge is used in the CRM definitions. + +I intentionally left out two seed files, one of which [`data/merged_user.csv`](https://github.com/dflynn20/jaffle_gaggle/blob/main/data/merged_user.csv) contains users the JaffleGaggle team have identified as the same person. + +To track this, the team decided to track the old user email and the new user email as one. Oftentimes, in a CRM’s data schema, there’s a built-in treatment for handling merged entities. + +However, since JaffleGaggle just started building out their infrastructure for a CRM, this CSV file exists to map old user emails to new (this example for Constance Rohr, userId 6759): + +``` +old_email, new_email + +constancerohr@icloud.com,constancerohr@outlaws.com +``` + +So what does this do for duplicate contacts? On line 100 of `jafflegaggle_contacts`, we left join to that `merged_user` seed file to map old emails to new: + +``` +left join {{ ref('merged_user') }} +``` + +Now to generate dbt docs and view our DAG, we can run: + +> `dbt docs generate` +> `dbt docs serve` + +This gives us access to the DAG for `jafflegaggle_contacts.sql` which can serve as the source of truth for the JaffleGaggle Ops team about where the analytics definitions live for the contacts in the system. + +![jafflegaggle contacts DAG](/img/blog/2022-02-08-customer-360-view/image_6.png) + +## Step 3: Model the Gaggle + +Working our way up to accounts, we arrive at the Gaggle, which is the traditional B2B workspace equivalent. This is important to understand how many users are associated with a workspace and when/what their activity has been. + +For example, the NFL Rams (who *love* jaffles) moved from St. Louis to Los Angeles, changing their company email domain in the process. For the JaffleGaggle sales team, it’s important that the changed email domain does not change the identity resolution for gaggles and Accounts in the process. + +If we don’t successfully do this merge when a corporate domain changes (e.g. `rams.sl` and `rams.la`), we’ll end up with two rows for the same gaggle_id (i.e. 1187), when we really just want one. The [`merged_company_domain` seed file](https://github.com/dflynn20/jaffle_gaggle/blob/main/data/merged_company_domain.csv) + a left join in the `final_merged` CTE of the [`jafflegaggle_facts`](https://github.com/dflynn20/jaffle_gaggle/blob/main/models/jafflegaggle_facts.sql) model solves this problem for us. + +``` +old_email, new_email + +rams.sl,rams.la +``` + +> Builder beware! As is flagged in the comments of the `jafflegaggle_facts` file, this assumes that there is only one non-personal email domain per workspace. If this is not the case, we would need to establish rules for what to do among gaggles with multiple companies within, such as performing attribution to the corresponding corporate email addresses of the users within each Gaggle. + +We also **aggregate information on the entire Gaggle**, including users who don’t have a company domain. This is found in the CTE named `gaggle_total_facts`. + +``` +gaggle_total_facts as ( + + select + gaggles.gaggle_id, + gaggles.gaggle_name, + gaggles.created_at, + + min(users.first_event) as first_event, + max(users.most_recent_event) as most_recent_event, + sum(number_of_events) as number_of_events, + count(users.user_id) as number_of_users, + + min(users.first_order) as first_order, + max(users.most_recent_order) as most_recent_order, + sum(users.number_of_orders) as number_of_orders + + from users + left join gaggles on users.gaggle_id = gaggles.gaggle_id + + group by 1,2,3 + +), +``` + +I know, that’s a ton of code. Check out the dbt docs for the project for an explanation of the fields. Here’s the output of final `jafflegaggle_facts` : + +![jafflegaggle facts query output screenshot](/img/blog/2022-02-08-customer-360-view/image_7.png) + +Referring to the DAG from the dbt docs, you can see how we are already benefiting from merging at the user level for analytics information related to `jafflegaggle_contacts`. + +![DAG of gaggle modeling](/img/blog/2022-02-08-customer-360-view/image_8.png) + +We also use an upstream table of `stg_gaggles` which pulls in information about the creation of the Gaggle and its name. + +## Step 4: Model the Account + +We have modelled the contacts and the gaggles, so we are at the account level now. + +We want to **join the characteristics for different gaggles that share the same company email address domain** so we can use operational analytics to create a customer 360 view for the sales team to prioritize outreach efforts. 🙌 + +By looking at the dbt docs, we see that every model is an upstream source for [`jafflegaggle_corporate_accounts`](https://github.com/dflynn20/jaffle_gaggle/blob/main/models/jafflegaggle_corporate_accounts.sql). + +![jagglegaggle corporate accounts](/img/blog/2022-02-08-customer-360-view/image_9.png) + +At this level we **coalesce the company for the merged domain** as we did with the `merged_users` previously. Here’s the code for this step: + +``` +select + + coalesce(mcd.new_domain, corporate_gaggles.corporate_email) as corporate_email, + + .... + + from corporate_gaggles + + left join {{ ref('merged_company_domain') }} mcd on corporate_gaggles.corporate_email = mcd.old_domain + + group by 1 +``` + +Note: This is not the only place where we reference the `merged_company_domain` file. We also need to reference this in the case where there are distinct gaggles with the old and new corporate domains, such as the Thrashers and the Jets. + +Here is an output of the final corporate accounts table: + +![corporate accounts table](/img/blog/2022-02-08-customer-360-view/image_10.png) + +### Step 4.1: Identify power users for an account + +Now imagine the sales operations team has identified the accounts they want to reach out to. They’ll also need to identify who they should contact to upgrade the account to paid. + +Ideally, this is a jaffle-loving office manager who created the account, who has been the most active, and who has placed the most orders. + +Great news for the sales team! We can identify those folks using the following CTE to identify the top users for each account. + +``` +corporate_power_users as ( + + select + + corporate_email, + + get(array_agg(user_id) within group (order by created_at asc), 0)::int as first_user_id, + + get(array_agg(user_id) within group (order by number_of_events desc), 0)::int as most_active_user_id, + + get(array_agg(user_id) within group (order by number_of_orders desc), 0)::int as most_orders_user_id + + from {{ ref('jafflegaggle_contacts') }} + + where corporate_email is not null + + group by 1 + +), +``` + +In almost every CRM, there’s a supported Lookup functionality, which means a record includes a property linked to another related record. As long as the `user_id` is marked as an external and unique id for the contact object in the CRM, this can be set from the model here. + +**Building the JaffleGaggle empire of your dreams** + +Congrats! If you’ve made it this far, you should be well on your way to establishing the JaffleGaggle empire you’ve always dreamed of. Since we covered a lot of ground in this tutorial, here’s a summary of all the steps together: + +1. **Define your entities** + +2. **Model the contact** + + 1. Perform the email domain extraction from the email + + 2. Flag personal emails + + 3. Create a column for corporate emails + + 4. Add in your human in the loop logic + +3. **Model your Gaggle** to summarize each group and aggregate that information for workspaces, or other relevant user groups. + + 5. Add in human in the loop merging logic + +4. **Model your account** to join the characteristics for different user groups with the same company email domain. + + 6. Add in human in the loop merging logic + +If we wanted to take it a step further we could: + +* Create a model for gaggles based solely on personal emails, who might consider moving to paid +* Create another layer of breakdown that uses `user_gaggle` or `gaggle_domain` + +In terms of data architecture, there are four things you need to do to get this productionized: + +1. Use [reverse ETL](https://www.getdbt.com/analytics-engineering/use-cases/operational-analytics/#what-is-reverse-etl) to get these fact tables synced to the CRM +2. Track payment or subscription information for which accounts are currently paying +3. Leverage / to get CRM data back into the data warehouse +4. Design for how you can extend the current merging solution + +![customer 360 view architecture diagram](/img/blog/2022-02-08-customer-360-view/image_11.png) + +If you’ve made it this far, you’ve gone from having three raw source tables to a business-specific source of truth within your own data warehouse featuring human-in-the-loop identity resolution, email domain dbt macro magic, and best practices for operationalizing B2B product-led growth. You most definitely deserve a jaffle. 🥪 + +DM me in [dbt Community Slack](https://www.getdbt.com/community/join-the-community) (I’m *@Donny Flynn (Census)*) if you want to learn more about JaffleGaggle, PLG, reverse ETL, or how I created these random datasets. 😊 + +PS: @clrclr don’t hate me. 🙏🏻 diff --git a/website/blog/2022-02-23-founding-an-AE-team-smartsheet.md b/website/blog/2022-02-23-founding-an-AE-team-smartsheet.md new file mode 100644 index 00000000000..a6e80f9ccdd --- /dev/null +++ b/website/blog/2022-02-23-founding-an-AE-team-smartsheet.md @@ -0,0 +1,211 @@ +--- +title: "Founding an Analytics Engineering Team" +description: "Nate Sooter shares the challenges and successes of forming the first analytics engineering team at Smartsheet" +slug: founding-an-analytics-engineering-team-smartsheet + +authors: [nate_sooter] + +tags: [analytics craft] +hide_table_of_contents: false + +date: 2022-03-02 +is_featured: true +--- + +# Founding an Analytics Engineering Team + +**Executive Summary:** + +If your company is struggling to leverage analytics, dealing with an overgrown ecosystem of dashboards/databases or simply want to avoid the mistakes of others, this story is for you. In this article, I will walk through forming the first analytics engineering team at Smartsheet including how momentum built around forming the team,  the challenges we faced, and the solutions we developed within the first year. + +## Introduction + +Most writing about analytics engineering, or AE for short, assumes a team already exists. It’s about operating as an AE team or managing stakeholders or leveraging tools more effectively. But what about the prologue? What initial problems do AEs solve? How does an AE team even start? What do the early days look like? + +Enter this story. I’m Nate and I manage the Analytics Engineering team at [Smartsheet](https://www.smartsheet.com/customers-home), a software platform that helps you manage your work. We’re not a large team, just me and two others. A lot went into the formation of our team and this is that story. I’ll tell it in three parts: + +- State of Analytics Before AE +- Selling & Starting the AE team +- Technology & Database Design + +## State of Analytics Before Analytics Engineering + +Smartsheet, in general, has a great analytics setup. Strong data engineering and data analytics teams. A cloud and an on-prem BI tool for front-end data visibility.  However, even with that foundation, there were some limitations under the hood requiring action: + +### (1) Multiple undocumented transformation databases + +Organic growth of a company usually translates to organic growth of the database. One became two, became fifteen, became too many to count. Analysts who built key tables left, new analysts joined and re-made or duplicated key tables. Suddenly, “the truth” was hard to find as data sprawl increased. + +Expanding data meant increasing difficulty finding The Truth within the database. Analysts gained knowledge inefficiently and over a long period of time of discussions and trial and error. With limited documentation and a growing database, this challenge continued to expand as more and more analysts came on board. + +### (2) Analysts could only ship code once every 1-2 weeks + +Analysts need a process to “productionalize” tables where their code is version controlled and is run on a schedule. Such a process existed at Smartsheet for analysts, but the issue was that deployments only happened once per week. The existing data engineering workflow understandably emphasized stability and reliability, with analysts simply hitching a ride. This meant a tradeoff on speed and agility as it was a one to two week process for any analyst to get new or updated code into the repository, no matter how simple. + +For example, this meant if an analyst noticed some incorrect data on a dashboard, it was a long process to get that fixed. The business moved too fast to wait a week or two for data to update. + +### (3) Data & business logic siloed in visualization layer + +Analysts found the pressure release valve around problem two in the visualization tool. It turns out that visualization tools can: + +(a) Hold a custom SQL script + +and + +(b) Run that script on a schedule. + +Voila, new analytics code now deployed more often than once per week. But it came with a downside as data and business logic became even more siloed than before. + +With undocumented and undiscoverable logic embedded in custom code buried deep within a dashboard workbook instead of in database tables, the data ecosystem became brittle and unmaintainable. Whenever raw data or business logic changed, no one had any idea which dashboards went sour (hint: usually it was the business users seeing “something off”). Discovering data became even more difficult. Data silos deepened between team members. Thousands of dashboards appeared. + +The above problems are not uncommon for most companies and you can get by like this for a while. But as the scale of these challenges compounded, laying the foundation for the formation of an analytics engineering team. + +## Justifying & Starting the Analytics Engineering Team + +### Making our case + +We just didn’t realize it yet, but momentum for an AE team was building.  Several internal analysts, including myself, [knew things could be better](https://www.hashpath.com/2020/12/an-analytics-engineer-is-really-just-a-pissed-off-data-analyst/) and discussed a new schema holding core transformed tables. One analyst in particular (who later became the core engineer of the AE team) created crucial tables which everyone needed. I joined the effort. We gained traction rapidly as we sold its value to other analysts and it immediately saved everyone time and effort. + +Around this same time, I discovered the [Locally Optimistic](https://locallyoptimistic.com/) data community and learned the name of our efforts: [Analytics Engineering](https://locallyoptimistic.com/post/analytics-engineer/#:~:text=They%20bring%20a%20formal%20and,data%20team%20as%20a%20whole.). Given our clear need for this internally and the early traction of our initial schema, my job became clear: Smartsheet needed Analytics Engineering. I put together a couple slide decks going over our analytics issues and why an AE practice would help. For example, I drew a chart showing our existing messy data ecosystem: + +![Graphic depicting the current state of Smartsheet's enrichment structure and its flaws](/img/blog/2022-02-23-founding-an-AE-team-smartsheet/current-enrichment-structure.png) + +I also presented slides going over solutions to these issues. After all, outlining problems is easy; bringing solutions is difficult. + +![Image of Nate's proposed solutions to Smartsheet's dysfunctional data enrichment structure](/img/blog/2022-02-23-founding-an-AE-team-smartsheet/enrichment-structure-solutions.png) + +The core of the solutions at the time seemed simple. It boiled down to: + +**Let’s just make some more tables in that source of truth schema, with some additional governance and clarity of ownership.** + +More on this in a bit - turns out this was only *part* of the solution. + +After a few meetings, additional discussions and a couple months, the opportunity crystallized: I and the analyst creating most source-of-truth tables would form the team. We would have one more headcount to hire. We officially became a team on Valentines Day, a true Data Love Story. + +### The early days and re-scoping our mission + +As mentioned earlier, we set off thinking “let’s just make some more tables in that trusted schema, except make them more organized.” So we compiled a list of tables asking questions like, what do we need to make? And more importantly, how do we make it scalable? + +The list of tables grew and grew. Enough that we started to realize a single schema wouldn’t pass muster. If we just made a ‘faster horse’ we would repeat the existing problem: too many tables in one place, all tangled up. After a couple months of planning and strategizing (delayed in part due to my parental leave, which I’m very thankful Smartsheet provides!), we thought to ourselves: what if we start fresh with our own database? + +Something magical happened over the period of a couple weeks. We started asking even more “What if?” questions. They included: + +What if we chose our own set of tools? + +What if we overhauled the analytics code production process? + +What if analysts could ship early and often instead of every few weeks? + +What if we cleaned up the old reporting ecosystem at the same time? + +A dozen light bulbs went off at once. We could change *everything*. We could make *everyone’s* time more effective and efficient. + +I remember going into a meeting with our team SVP after realizing we should do more than just make some clean tables. I told him “this project is a lot bigger than we signed on for, there’s so much to do to get it right.” He was gracious to give us some more time, with the expectation that we’d deliver something within the year. It was time to get to work. We not only needed to make some clean data, choose our tools, overhaul the analytics code production process and significantly clean the old reporting ecosystem. It would take a marathon sprint to get there. The question of “What if” became “When?” We ambitiously chose by the end of the calendar year and off to the races we went. + +## Technology & Database Design + +While this expansive project required numerous decisions, I want to highlight three primary and important decision points early on in our development. + +### Technology Stack + +As mentioned earlier, the Smartsheet data stack was already pretty modern—including our cloud data warehouse. We also used some other modern on-prem or in-house tools in the existing analytics stack. However, we had a rare chance to take a step back and choose anew. + +In the interest of getting a proof of concept out the door (I highly favor focus on delivering value quickly and then iterating improvements), we settled on a small and compact tech stack: + +- Our own Dev, Prod & Publish databases +- Our own code repository which we managed independently +- dbt CLI +- Virtual Machine running dbt on a schedule + +None of us had used dbt before, but we’d heard amazing things about it. We hotly debated the choice between dbt and building our own lightweight stack, and looking back now, I couldn’t be happier with choosing dbt. While there was a learning curve that slowed us down initially, we’re now seeing the benefit of that decision. Onboarding new analysts is a breeze and much of the functionality we need is pre-built. The more we use the tool, the faster we are at using it and the more value we’re gaining from the product. + +For example, we previously used a separate tool to schedule [DAGs](https://analyticsengineers.club/whats-a-dag/). There was quite the spaghetti graph to keep straight and the tool became a headache for analysts. With dbt setting our DAGs automatically during the run, we could (and can) focus on more important tasks. + +I’m certain that if we’d chosen to roll our own homemade transformation pipeline, we’d be operating at a much slower pace today. + +### Our own take on Data Mesh + +In the midst of the [Great Data Mesh Debate](https://pedram.substack.com/p/the-last-thing-ill-ever-say-about), we were silently applying pieces of [Data Mesh](https://martinfowler.com/articles/data-monolith-to-mesh.html) into our database design. Specifically, we truly believed that separating out ownership and/or structure of data by domain within the company was a valuable step. Certain departments know certain pieces of information, and it is normal in transformations to join those things together to solve common use cases. + +We believed this because our goal was to have wide, denormalized tables covering specific concepts like “Accounts”, “Users” or “Contracts”. The issue with wide tables is that a lot of columns from a lot of different ‘owners’ are needed. That sounded like a nightmare. If everyone owns a table, no one owns the table. + +Then, the lightbulb came suddenly one day. We realized that the **ownership of data could be at the column level, *not* just at the table level.** That piece of the puzzle unlocked our design. + +![Graphic depicting Smartsheet's new proposed data structure ](/img/blog/2022-02-23-founding-an-AE-team-smartsheet/new-structure-example.png) + +1. Each core ‘object’ in our database (e.g., a customer Contract) would start with a **Frame** table, which was just a simple table holding one row for each record to serve as the backbone of downstream transformations (e.g., a list of all unique Contract IDs). +2. Each department would then take that Frame into their own schema and own their **Detail** version of the table. Finance would have the Finance.Contract table, Product would have Product.Contract table, etc. These were simply left joins of the Frame table with the columns about which each domain could supply trustworthy information. For example: Finance knows the value and when that contract is up for renewal, Product knows how many active users there are for that contract, and Sales knows the value of open opportunities for that contract’s renewal. +3. We would then take those disparate Contract tables and join them together into our **Core** schema. Since all of these tables share the same root Frame table, the join is simple and there are no duplication issues or confusion about what counts as a contract. +4. We left room for a **Utility** set of schemas for teams to take Core tables and build their own tables for specific use cases, knowing that not every use case ended in a wide table. + +This twist on Data Mesh gave us a strong foundation to build around. Enforcing ownership of columns at the domain level is important since data experts should contribute their knowledge into tables others can leverage.  Previously, those experts contributed knowledge when someone asked around. Now that knowledge lives in intuitive locations of the database, discoverable by anyone. + +### Data flow from Raw to Prod + +With the structure figured out, we turned our attention to the nitty gritty details and, wow, this was overwhelming. None of us came from a data engineering background. We had never created databases or maintained them, or thought about permissions, run schedules or disaster recovery. But there were decisions to make and we ran headlong into tackling them one at a time. + +For example, we originally assumed the data flow from Raw into its Prod state would be relatively simple: Raw → dbt magic → Prod.  But that ‘dbt magic’ part had *many* layers to it. Where will dbt run? How do we schedule it? How do we make sure data is in sync? What does being in sync even mean? How often do we update the database? What happens if one model is queried in the middle of an update? How do we make sure the right people see the right objects? + +To get through the fog of questions, we chose one principle on which to plant our flag: **Data must be in sync and always accessible across the database**. In our existing database, if you queried a table mid-update: too bad. You got weird data and might not even know it, or your query would fail. We wanted to do better and our cloud data warehouse provided the platform we needed to make it happen. + +We settled on the following data transformation flow. Our transformation code is pulled every 8 hours onto a virtual machine (VM). A script on that VM triggers dbt to run that code, populating a staging database which is visible only to my team. Staging continues to update table by table until the run is successful.  When successful, Staging immediately clones over to Prod, with no downtime for users even if they are mid-query.  Everyone is happy. + +![Graphic depicting Smartsheet's finalized data transformation workflow structure](/img/blog/2022-02-23-founding-an-AE-team-smartsheet/new-transformation-workflow.png) + +This is scratching the surface of the decisions we made, but I hope it’s helpful in illuminating some of the hidden decisions one makes when designing a reliable analytics database. + +## V1 Launch + +Starting around August, not only was the vision clear, we also had a plan of attack of what to make for V1. Planning and strategy time was largely over; it was time to execute and deliver value. + +I could write much more about each of these and the entire story of how we went from August to December but we’ll have to save that for another day. By December 20, 2021, we completed three key deliverables which will become the foundation for an internal analytics renaissance. + +### 70+ enriched tables in dbt refreshing every eight hours + +We identified the core tables which covered the broadest swaths of use cases and laser focused on those. We delivered 70 tables in total, with highlights of: + +- 17 **Core** tables joined from the building blocks discussed in the prior section, +- Multiple **Journal** tables (i.e., one row per change to a record) that had been on the “we want these” list for analysts for years, such as Account history and User history. These existed prior in a very raw format; good luck avoiding landmines and/or writing efficient queries on raw data, and +- **Meta** tables giving up to date statistics on each model such as their data freshness.Up to this point, analysts had no idea how fresh the data was in a table and you couldn’t confidently tell a stakeholder through when the data on a dashboard was accurate. + +Plenty more to make but the foundation was there, and now it was time to enroll other analysts in this process. This is a significant step toward unwinding the tangled data ecosystem described in problem one at the beginning of this article. + +### Brand new code production process + +This topic also deserves its own blog post, but I’ll attempt to quickly describe what we changed. As described in the problem statement, analysts could only ship code every 1-2 weeks and the process was incredibly painful. It was more than 16 steps with multiple ‘gotchas’ where analysts would get stuck and waste time. + +The process is now six steps, with massive time savings for the analytics team both in the creation and testing of their script along with how long it takes for new data to get into the data warehouse.This is on top of all of dbt’s benefits such as data definitions, lineage, automatic testing, macros…the list goes on. + +![Graphic depicting Smartsheet's new and improved code production process that outlines 6 steps](/img/blog/2022-02-23-founding-an-AE-team-smartsheet/completed-process.png) + +### Cleaned up dashboard/reporting ecosystem + +With clean tables in place and a strong process to create even more, it was time to tackle dashboarding/reporting. Over 1,000 workbooks contained over 5,000 dashboards, built up over years of analysts adding in ad-hoc queries and letting them run. + +I started by setting up a process with criteria determining which dashboards to delete: if your dashboard isn’t used, it’s getting deleted. At first, the rule was “no views within six months” but then it tightened to “less than five views within six months”. Soon, it will move to “less than five views within three months” and we’ll tweak from there. + +Next, I send out a monthly Smartsheet which lists all dashboards set for deprecation, notify everyone who owns at least one workbook, and give them the requirement of explaining why their workbook should remain. So far, very few dashboards receive a request to remain and most are allowed to expire by the owners. + +As of now, we’ve retired 50% of all workbooks (roughly 500) which contained 42% of all dashboards (roughly 2,100). We’re confident that this cleanup will pair with less and less demand to make workbooks. The code automation process with dbt will also significantly relieve the pressure that drove analysts to over-rely on our visualization tool for data refreshing. + +All of this cascades into many benefits that Smartsheet will benefit from going forward: + +- Less business logic living in disparate systems (it shouldn’t be in there in the first place!) +- Fewer reports breaking when business logic does change +- Discoverability of the important reports greatly improved for business users + +## The Road Ahead + +All the above brings us to today. It’s been an amazing, stressful, ridiculous journey over the last year.  Lots of learning and mistakes and triumphs and failures and everything in between. I’m in awe of the team as they took on this incredible task with gusto and grit. I’m proud to work alongside them each day. + +It’s difficult to remember to pause and look back and see where you came from, especially when the mountain in front of you still feels larger than life. This blog is partially an attempt to do just that. We’ve come far, and we have momentum going forward. + +My hope is this story is helpful for you, wherever you are on your analytics journey. I’m certain the above isn’t unique to Smartsheet and is common. We’re all in good company. + +The road ahead is both clear and unclear.  But there is one primary focus we have for the upcoming year:  **Adoption, Adoption, Adoption** + +Even if we build the most amazing process on top of the most amazing tools available, it’s irrelevant if internal adoption lags. Our team of three is incapable of delivering everything Smartsheet needs, and our design intentionally avoids us becoming an internal bottleneck. Instead, we are **enablers**.  We *have* to move away from our old enrichment databases and build anew in the new database. We *have* to onboard new analysts into our new process. We *have* to apply this new foundation to better serve our internal customers. + +So the focus is now on adoption. What does this mean for analysts? What does this mean for internal stakeholders?  How do we leverage all this newfound power into better self-serve tools and more agile data teams? + +We have some ideas - but that’s for another blog post.  What is certain is my job is turning into an internal sales and marketing position. Good thing I started out in Customer Success before going into analytics; it’s time to put that hat back on. diff --git a/website/blog/2022-04-05-when-backend-devs-spark-joy.md b/website/blog/2022-04-05-when-backend-devs-spark-joy.md new file mode 100644 index 00000000000..3b87d3a7d6c --- /dev/null +++ b/website/blog/2022-04-05-when-backend-devs-spark-joy.md @@ -0,0 +1,74 @@ +--- +title: "From the Slack Archives: When Backend Devs Spark Joy for Data Folks" +description: "An overview of an interesting community slack thread about the relationship between data folks and backend developers" +slug: when-backend-devs-spark-joy + +authors: [kira_furuichi] + +tags: [analytics craft] +hide_table_of_contents: false + +date: 2022-04-05 +is_featured: true +--- + +*"I forgot to mention we dropped that column and created a new one for it!”* + +*“Hmm, I’m actually not super sure why `customer_id` is passed as an int and not a string.”* + +*“The for that is actually the `order_id`, not the `id` field.”* + +I think many analytics engineers, including myself, have been on the receiving end of some of these comments from their backend application developers. + +Backend developers work incredibly hard. They create the database and tables that drive the heart of many businesses. In their efforts, they can sometimes overlook, forget, or not understand their impact on analytics work. However, when backend developers do understand and implement the technical and logistical requirements from data teams, *they can spark joy*. + +So what makes strong collaboration possible between analytics engineers and backend application developers? + + + +![A screenshot of the conversation that started the thread](/img/blog/2022-04-05-when-backend-devs-spark-joy/slack_thread_screenshot.png) +*A screenshot of the conversation that started the thread* + +## When the pieces fall into place + +A [recent slack thread](https://getdbt.slack.com/archives/C0VLZPLAE/p1643161237258600) in the dbt Community slack went over some of the technical and logistical aspects that can lead to happy data folks. Here were some of my favorite rules of the road that backend developers can follow to help them enjoy a quieter Slack. + +### Signs the data is sparking joy + +**All tables have a primary key.** + +Having columns in your tables that uniquely identify each row is fundamental to analytics work. [Primary keys](https://docs.getdbt.com/blog/primary-key-testing) ensure there are no duplicates in the data, ultimately allowing for accurate counts. This is especially important for backend application database tables, since many organizations consider those tables to be their “source of truth” for backend application data. It’s even better when primary key fields are clearly identifiable in backend application tables! + +**Time-based fields are passed as timestamps, not dates.** + +Time-based fields, such as when an account is created or an order is placed, should be passed as timestamps. This format provides the most flexibility and granularity for analytics engineers and end business users. Timestamps can be made into accurate dates, date type fields cannot be made into accurate timestamps. Bonus points: When backend application tables have accurate `created_at` and `updated_at` fields, it’s a win for everyone. + +**There are consistent naming conventions for tables and fields.** + +Having a consistent method to name tables and fields for backend data is incredibly important for the readability and scalability of both backend application tables and data models. + +**Soft deletes FTW.** + +In a soft delete, data is noted as deleted in a type of `deleted_at`/`is_deleted` field. A hard delete performs a true deletion which ultimately removes the row from the table. Soft deletes and fields that specify whether rows were removed provide a true record of what is happening to the data. They establish greater context into backend application data and help analytics engineers ensure higher data quality. + +**Data is passed as the proper type.** + +Fields that are strings should be strings! And ints should be ints! Completing funky casts of fields in your data models is sometimes inevitable, but limiting where those complexities happen makes data modeling more intuitive. + +> “I looked back at the list above and I didn't see 'proper data typing' explicitly called out. I've seen so many cases of strings when it should be an int or a decimal or date or whatever else.” - [a comment in the slack thread from Josh Andrews](https://getdbt.slack.com/archives/C0VLZPLAE/p1643305705280300?thread_ts=1643161237.258600&cid=C0VLZPLAE) + +### Signs that operations are sparking joy + +**Communication and collaboration before releases is the norm.** + +Analytics engineers can catch release changes that may break their models prior to release by having routine communication with backend developers. Consider monitoring or reviewing PRs for backend work to understand the magic beneath the hood! In addition, collaboration between backend and analytics teams can encourage backend developers to establish a mindset where they frequently think about how their work will impact downstream analytics. + +**Don’t forget the documentation.** + +Regularly maintained and well-written documentation for backend application database tables helps analytics engineers and backend developers alike unpack complex data and data models. Documentation for backend application database tables might look like an entity relationship diagram (ERD) or an ERD supplemented with a living text-document providing greater detail into tables and fields. Furthermore, strong documentation helps analytics engineers write more descriptive [documentation for source models in dbt](https://docs.getdbt.com/docs/building-a-dbt-project/using-sources#testing-and-documenting-sources). + +## A match made in heaven + +Maintaining a strong and collaborative relationship with your backend application developers *is hard*. Forming the technical and logistical requirements that satisfy both parties is also challenging. However, taking the time to clearly define and understand why these requirements should exist is extremely rewarding and worth every difficult conversation. When done right, this kind of collaboration can lead to better partnership, more readable data models, higher quality data, and happier team members. + +Want to read more about what makes data modeling a joy? Make sure to join the [dbt Community slack](https://www.getdbt.com/community/join-the-community/)! \ No newline at end of file diff --git a/website/blog/2022-04-14-add-ci-cd-to-bitbucket.md b/website/blog/2022-04-14-add-ci-cd-to-bitbucket.md new file mode 100644 index 00000000000..6cdb20d0df3 --- /dev/null +++ b/website/blog/2022-04-14-add-ci-cd-to-bitbucket.md @@ -0,0 +1,307 @@ +--- +title: "Slim CI/CD with Bitbucket Pipelines" +description: "How to set up slim CI/CD outside of dbt Cloud" +slug: slim-ci-cd-with-bitbucket-pipelines + +authors: [simon_podhajsky] + +tags: [dbt tutorials] +hide_table_of_contents: false + +date: 2022-05-06 +is_featured: true +--- + +Continuous Integration (CI) sets the system up to test everyone’s pull request before merging. Continuous Deployment (CD) deploys each approved change to production. “Slim CI” refers to running/testing only the changed code, [thereby saving compute](https://discourse.getdbt.com/t/how-we-sped-up-our-ci-runs-by-10x-using-slim-ci/2603). In summary, CI/CD automates dbt pipeline testing and deployment. + +[dbt Cloud](https://www.getdbt.com/), a much beloved method of dbt deployment, [supports GitHub- and Gitlab-based CI/CD](https://blog.getdbt.com/adopting-ci-cd-with-dbt-cloud/) out of the box. It doesn’t support Bitbucket, AWS CodeCommit/CodeDeploy, or any number of other services, but you need not give up hope even if you are tethered to an unsupported platform. + +Although this article uses Bitbucket Pipelines as the compute service and Bitbucket Downloads as the storage service, this article should serve as a blueprint for creating a dbt-based Slim CI/CD *anywhere*. The idea is always the same: + + + +1. Deploy your product and save the deployment artifacts. +2. Use the artifacts to allow dbt to determine the stateful changes and run only those (thereby achieving “slimness”). + +## Overview of steps + +To accomplish this, we’ll need to prepare three parts of our pipeline to work together: + +1. Database access - ensure that our warehouse has users, roles and permissions to run our pipelines +2. Repository preparation - setup our repository and build our automation based on our git platform provider’s (in this example, Bitbucket) capabilities +3. Bitbucket (or other platform) environment - configure our environment with the necessary secrets and variables to run our workflow + +## Step 1: Database preparation + +In general, we want the following: + +1. Create a CI user with proper grants in your database, including the ability to create the schema(s) they’ll write to (`create on [dbname]`). +2. Create a production user with proper grants in your database. + +The specifics will differ based on the database type you’re using. To see what constitutes “proper grants”, please consult the dbt Discourse classic “[The exact grant statements we use in a dbt project](https://discourse.getdbt.com/t/the-exact-grant-statements-we-use-in-a-dbt-project/430)” and Matt Mazur’s “[Wrangling dbt Database Permissions](https://mattmazur.com/2018/06/12/wrangling-dbt-database-permissions/)”. + +In my case, I created: + +1. A `dev_ci` Postgres user which had been granted a previously created `role_dev` role (same as all other development users). `role_dev` has connect and create grants on the database. +2. A `dbt_bitbucket` user which has been granted a previously created `role_prod` role (same as dbt Cloud production environment). The `role_prod` role must have write access to your production schemas. + +```sql +create role role_dev; + +grant create on database [dbname] to role_dev; + +-- Grant all permissions required for the development role + +create role role_prod; + +grant create on database [dbname] to role_prod; + +-- Grant all permissions required for the production role + +create role dev_ci with login password [password]; + +grant role_dev to dev_ci; + +create schema dbt_ci; + +grant all on schema dbt_ci to role_dev; + +alter schema dbt_ci owner to role_dev; + +create role dbt_bitbucket with login password [password]; + +grant role_prod to dbt_bitbucket; +``` + +### Role Masking + +Finally - and this might be a Postgres-only step - I had to make sure that the regularly scheduled dbt Cloud jobs connected with a `dbt_cloud` user with a `role_prod` grant would be able to drop and re-create views and tables during their run, which they could not if `dbt_bitbucket` had previously created and owned them. To do that, I needed to [mask both roles](https://dba.stackexchange.com/a/295736): + +```sql +alter role dbt_bitbucket set role role_prod; + +alter role dbt_cloud set role role_prod; +``` + +That way, any tables and views created by either user would be owned by “user” role_prod. + +## Step 2: Repository preparation + +Next, we’ll need to configure the repository. Within the repo, we’ll need to configure: + +1. The pipeline environment +2. The database connections +3. The pipeline itself + +### Pipeline environment: requirements.txt + +You’ll need at least your dbt adapter-specific package, ideally pinned to a version. Mine is just: + +```yaml +dbt-[adapter] ~= 1.0 +``` + +### Database connections: profiles.yml + +You shouldn’t ever commit secrets in a plain-text file, but you can reference environmental variables (which we’ll securely define in Step 3). + +```yaml +your_project: + target: ci + outputs: + ci: + type: postgres + host: "{{ env_var('DB_CI_HOST') }}" + port: "{{ env_var('DB_CI_PORT') | int }}" + user: "{{ env_var('DB_CI_USER') }}" + password: "{{ env_var('DB_CI_PWD') }}" + dbname: "{{ env_var('DB_CI_DBNAME') }}" + schema: "{{ env_var('DB_CI_SCHEMA') }}" + threads: 16 + keepalives_idle: 0 + prod: + type: postgres + host: "{{ env_var('DB_PROD_HOST') }}" + port: "{{ env_var('DB_PROD_PORT') | int }}" + user: "{{ env_var('DB_PROD_USER') }}" + password: "{{ env_var('DB_PROD_PWD') }}" + dbname: "{{ env_var('DB_PROD_DBNAME') }}" + schema: "{{ env_var('DB_PROD_SCHEMA') }}" + threads: 16 + keepalives_idle: 0 +``` + +### Pipeline itself: bitbucket-pipelines.yml + +This is where you’ll define the steps that your pipeline will take. In our case, we’ll use the Bitbucket Pipelines format, but the approach will be similar for other providers. + +There are two pipelines we need to configure: + +1. Continuous Deployment (CD) pipeline, which will deploy and also store the production run artifacts +2. Continuous Integration (CI) pipeline, which will retrieve them for state-aware testing runs in development + +[The entire file is accessible in a Gist](https://gist.github.com/shippy/78c2f5b124b70f31b2cef81c9017c8fd), but we’ll take it step-by-step to explain what we’re doing and why. + +### Continuous Deployment: Transform by latest master and keep the artifacts + +Each pipeline is a speedrun of setting up the environment and the database connections, then running what needs to be run. In this case, we also save the artifacts to a place we can retrieve them from - here, it’s the Bitbucket Downloads service, but it could just as well be AWS S3 or another file storage service. + +```yaml +image: python:3.8 + +pipelines: + branches: + main: + - step: + name: Deploy to production + caches: + - pip + artifacts: # Save the dbt run artifacts for the next step (upload) + - target/*.json + script: + - pip install -r requirements.txt + - mkdir ~/.dbt + - cp .ci/profiles.yml ~/.dbt/profiles.yml + - dbt deps + - dbt seed --target prod + - dbt run --target prod + - dbt snapshot --target prod + - step: + name: Upload artifacts for slim CI runs + script: + - pipe: atlassian/bitbucket-upload-file:0.3.2 + variables: + BITBUCKET_USERNAME: $BITBUCKET_USERNAME + BITBUCKET_APP_PASSWORD: $BITBUCKET_APP_PASSWORD + FILENAME: 'target/*.json' +``` + +Reading the file over, you can see that we: + +1. Set the container image to Python 3.8 +2. Specify that we want to execute the workflow on each change to the branch called main (if yours is called something different, you’ll want to change this) +3. Specify that this pipeline is a two-step process +4. Specify that in the first step called “Deploy to production”, we want to: + 1. Use whatever pip cache is available, if any + 2. Keep whatever files are generated in this step in target/ + 3. Run the dbt setup by first installing dbt as defined in requirements.txt, then adding `profiles.yml` to the location dbt expects them in, and finally running `dbt deps` to install any dbt packages + 4. Run `dbt seed`, `run`, and `snapshot`, all with `prod` as specified target +5. Specify that in the first step called “Upload artifacts for slim CI runs”, we want to use the Bitbucket “pipe” (pre-defined action) to authenticate with environment variables and upload all files that match the glob `target/*.json`. + +In summary, anytime anything is pushed to main, we’ll ensure our production database reflects the dbt transformation, and we’ve saved the resulting artifacts to defer to. + +> ❓ **What are artifacts and why should I defer to them?** dbt artifacts are metadata of the last run - what models and tests were defined, which ones ran successfully, and which failed. If a future dbt run is set to ***defer*** to this metadata, it means that it can select models and tests to run based on their state, including and especially their difference from the reference metadata. See [Artifacts](https://docs.getdbt.com/reference/artifacts/dbt-artifacts), [Selection methods: “state”](https://docs.getdbt.com/reference/node-selection/methods#the-state-method), and [Caveats to state comparison](https://docs.getdbt.com/reference/node-selection/state-comparison-caveats) for details. + +### Slim Continuous Integration: Retrieve the artifacts and do a state-based run + +The Slim CI pipeline looks similar to the CD pipeline, with a couple of differences explained in the code comments. As discussed earlier, it’s the deferral to the artifacts is that makes our CI run “slim”. + +```yaml +pipelines: + pull-requests: + '**': # run on any branch that’s referenced by a pull request + - step: + name: Set up and build + caches: + - pip + script: + # Set up dbt environment + dbt packages. Rather than passing + # profiles.yml to dbt commands explicitly, we'll store it where dbt + # expects it: + - pip install -r requirements.txt + - mkdir ~/.dbt + - cp .ci/profiles.yml ~/.dbt/profiles.yml + - dbt deps + + # The following step downloads dbt artifacts from the Bitbucket + # Downloads, if available. (They are uploaded there by the CD + # process -- see "Upload artifacts for slim CI runs" step above.) + # + # curl loop ends with "|| true" because we want downstream steps to + # always run, even if the download fails. Running with "-L" to + # follow the redirect to S3, -s to suppress output, --fail to avoid + # outputting files if curl for whatever reason fails and confusing + # the downstream conditions. + # + # ">-" converts newlines into spaces in a multiline YAML entry. This + # does mean that individual bash commands have to be terminated with + # a semicolon in order not to conflict with flow keywords (like + # for-do-done or if-else-fi). + - >- + export API_ROOT="https://api.bitbucket.org/2.0/repositories/$BITBUCKET_REPO_FULL_NAME/downloads"; + mkdir target-deferred/; + for file in manifest.json run_results.json; do + curl -s -L --request GET \ + -u "$BITBUCKET_USERNAME:$BITBUCKET_APP_PASSWORD" \ + --url "$API_ROOT/$file" \ + --fail --output target-deferred/$file; + done || true + - >- + if [ -f target-deferred/manifest.json ]; then + export DBT_FLAGS="--defer --state target-deferred/ --select +state:modified"; + else + export DBT_FLAGS=""; + fi + + # Finally, run dbt commands with the appropriate flag that depends + # on whether state deferral is available. (We're skipping `dbt + # snapshot` because only production role can write to it and it's + # not set up otherwise.) + - dbt seed + - dbt run $DBT_FLAGS + - dbt test $DBT_FLAGS +``` + +In short, we: + +1. Set up the pipeline trigger condition to trigger on any pull request +2. Set up dbt +3. Retrieve the files from Bitbucket Downloads via API and credentials +4. Set flags for state deferral if the retrieval was successful +5. Run dbt with the default target (which we’d defined in `profiles.yml` as `ci`) + +## Step 3: Bitbucket environment preparation + +Finally, we need to setup the environment so that all the steps requiring authentication can succeed, this includes: + +1. Database authentication - for dbt communicating with the warehouse +2. Bitbucket Downloads authentication - for storing our dbt artifacts + +As with the earlier steps, these specific instructions are for Bitbucket but the basic principles apply to any other platform. + +### Database authentication + +1. Determine the values of all of the variables in `.ci/profiles.yml` (`DB_{CI,PROD}_{HOST,PORT,USER,PWD,DBNAME,SCHEMA}`) +2. Go to Repository > Repository Settings > Repository Variables in Bitbucket and define them there, making sure to store any confidential values as “Secured”. + +![Bitbucket repository variables settings screenshot](/img/blog/2022-04-14-add-ci-cd-to-bitbucket/2022-04-14-add-ci-cd-to-bitbucket-image-2.png) + +### Bitbucket Downloads authentication + +1. Go to Personal Settings > App Passwords in Bitbucket and create a Bitbucket App Password with scope `repository:write`. +2. Go to Repository > Repository Settings > Repository Variables and define the following: + 1. `BITBUCKET_USERNAME`, which is not your sign-up e-mail, but rather the username found by clicking your avatar in the top left > Personal settings > Account settings page, under Bitbucket Profile Settings. + 2. `BITBUCKET_APP_PASSWORD`, making sure to store it as “Secured” + +![Bitbucket repository app password scope settings screenshot](/img/blog/2022-04-14-add-ci-cd-to-bitbucket/2022-04-14-add-ci-cd-to-bitbucket-image-1.png) + +### Enable Bitbucket Pipelines + +Lastly, under Repository > Repository Settings > Pipelines Settings, check “Enable Pipelines”. + +![Bitbucket Pipeline Settings enabling screenshot](/img/blog/2022-04-14-add-ci-cd-to-bitbucket/2022-04-14-add-ci-cd-to-bitbucket-image-3.png) + +## Step 4: Test + +You’re all done! Now it’s time to test that things work: + +1. Push a change to your main branch. This should trigger a Pipeline. Check that it’s successful. +2. File a Pull Request with a change to a single model / addition of a single test. Check that only that model/test ran. + +## Conclusion + +It’s important to remember that CI/CD is a convenience, not a panacea. You must still devise the model logic and determine the appropriate tests. Some things it can do, though: catch more mistakes early, make sure that the database always reflects the most up-to-date code, and decrease the friction in collaboration. By automating the steps that should *always* be taken, it frees you up to think about the unusual steps required (e.g., do your changes to [incremental models](https://docs.getdbt.com/docs/building-a-dbt-project/building-models/configuring-incremental-models) require an additional deployment with `--full-refresh`?) and reduces the amount of review that others’ actions necessitate. + +Plus, it’s a good time, and it’s fun to watch the test lights turn green. Ding! + +![wild-child-yes.gif](https://c.tenor.com/wemr0g_Do8IAAAAC/wild-child-yes.gif) diff --git a/website/blog/2022-04-19-complex-deduplication.md b/website/blog/2022-04-19-complex-deduplication.md new file mode 100644 index 00000000000..be61eae643b --- /dev/null +++ b/website/blog/2022-04-19-complex-deduplication.md @@ -0,0 +1,186 @@ +--- +title: "How we remove partial duplicates: Complex deduplication to refine your models' grain" +description: "dbt Labs Analytics Engineer Lauren Benezra walks you through an example of how to refine your data's grain, using less-than-ideal data loading issues as an opportunity to improve the clarity of the entities you're modeling and how you express them." +authors: [lauren_benezra] +hide_table_of_contents: false +tags: [analytics craft] +is_featured: true +slug: how-we-remove-partial-duplicates +date: 2022-05-12 +--- + +Hey data champion — so glad you’re here! Sometimes datasets need a **team** of engineers to tackle their deduplification (totz a real word), and that’s why we wrote this down. *For you*, friend, *we wrote it down for you*. You’re welcome! + +Let’s get rid of these dupes and send you on your way to do the rest of the *super-fun-analytics-engineering* that you want to be doing, on top of *super-sparkly-clean* data. But first, let’s make sure we’re all on the same page. + + + +You’re here because your duplicates are *special* duplicates. These special dupes are not the basic ones that have same exact values in every column and duplicate primary keys that can be easily fixed by haphazardly throwing in a `distinct` (yeah that’s right, I called using `distinct` haphazard!). These are *partial* duplicates, meaning your entity of concern's primary key is not unique *on purpose* (or perhaps you're just dealing with some less than ideal data syncing). You may be capturing historical, type-two slowly changing dimensional data, or incrementally building a table with an append-only strategy, because you actually want to capture some change over time for the entity your recording. (Or, as mentioned, your loader may just be appending data indiscriminately on a schedule without much care for your time and sanity.) Whatever has brought you here, you now have a table where the is not your entity’s primary key, but instead the entity’s primary key + the column values that you’re tracking. Confused? Let’s look at an example. + +Here’s your raw table: + +| entity_id | unimportant_value | important_status | updated_date | +|-----------|-------------------|------------------|--------------| +| 1 | cool | pending | 2022-02-24 | +| 1 | lame | submitted | 2022-03-01 | +| 1 | cool | submitted | 2022-03-03 | +| 2 | cool | pending | 2022-02-27 | + +You have this historical record that captures all the changes made to the entities. Fine so far, but here's the rub: you don’t actually care about the changes that happen in the `unimportant_value` column, and a thus a fresh `updated_date` column value and a new row doesn’t always indicate a *real change* (real here is defined in terms of what matters to you modeling the data for our stakeholders). As discussed, the grain of the dataset you want to capture is the combination of the columns we deem important that make each row unique. So in this case, the grain is `entity_id` + `important_status`, not just `entity_id`. As a result, rows 2 and 3 are what we’ll call *partial duplicates*. If you were to ignore the two columns whose values you don’t want to track, you’d find the dupes that need to be banished! + +## Identifying key columns + +First, let’s look a little closer at identifying the desired grain of the model you are building before you go removing these partial duplicates from your dataset. These questions can help you figure out the core entity that you are tracking, and the real grain at which changes should be captured in your new model. + +- **What is the primary key of the entity which you are tacking historical data for?** You should be able to group by this id in order to identify the duplicates for each id. +- **What other column(s) are capturing the changes in the data you want to track in your new model?** These columns will become part of your new unique primary key. +- **What timestamp provides the most reliable update time for these records?** You’ll need this to ensure you’re picking the most recent row among the partial duplicates. +- **What column value(s) are changing, but you don’t care about tracking in your new model?** These are the columns that you’ll ignore when building your `grain_id`. + +The combination of `entity_id` + [changing column(s)] you want to capture becomes the grain of your model. In our example, we are looking to capture data at the grain of `entity_important_status` which we'll call our `entity_grain` for now. + +| entity_grain | entity_id | unimportant_value | important_status | updated_date | +|--------------|-----------|-------------------|------------------|--------------| +| 1_pending | 1 | cool | pending | 2022-02-24 | +| 1_submitted | 1 | lame | submitted | 2022-03-01 | +| 1_submitted | 1 | cool | submitted | 2022-03-03 | +| 2_pending | 2 | cool | pending | 2022-02-27 | + +Now the `entity_grain` clearly shows us which rows are duplicates! We only need to keep the most recent one, so row 2 above can be removed from the cleaned dataset, giving us the output below. In our full process below, we’ll make this concatenated key into a proper id, but this is funamentally what's happening under the hood. + +| entity_grain | entity_id | unimportant_value | important_status | updated_date | +|--------------|-----------|-------------------|------------------|--------------| +| 1_pending | 1 | cool | pending | 2022-02-24 | +| 1_submitted | 1 | cool | submitted | 2022-03-03 | +| 2_pending | 2 | cool | pending | 2022-02-27 | + +Hopefully this is making a bit more sense. The TL;DR is that you need to think about the grain of your data, and the entity you want to capture as you are tracking changes. Only then can you find the more complex partial duplicates you want to eliminate. + +## Overview + +Here’s a brief overview of the steps we’ll take: + +1. Create a unique, hashed `grain_id` for each row of your table from every significant column value. +2. Mark the real differences within the data based on the key you created, and filter duplicates. +3. Add tests to ensure your deduplication has worked and your dataset stays clean! + +## Step 1: Build a unique key for each row of your table + +> Step 1 walks you through how to build a hashed entity id from column values using a macro. You’ll use this key in Step 2 to find the true duplicates and clean them out. + +The idea in this step is to enable checking for duplicates in the data by attaching a unique key to the hashed values of the columns that make up the entity grain you want to track. It’s important to note here that the *[dbt_utils.surrogate_key](https://github.com/dbt-labs/dbt-utils/blob/0.8.2/macros/sql/surrogate_key.sql)* will not create a unique key yet! Instead, it will create a key that will be the same as the key of another row, as long as the column values we’ve selected for our entity grain are the same. *This is intentional and critical!*  The specific non-uniqueness is how we’ll catch our sneaky duplicates. + +In our example, you can see that the `surrogate_key` function builds the same `grain_id` or the two rows we know are duplicates, rows 2 and 3, with row 3 being the most recent row. + +| grain_id | entity_grain | entity_id | unimportant_value | important_status | updated_at_date | +|----------------------------------|--------------|-----------|-------------------|------------------|-----------------| +| 8e0bd4a0e4a6e3a4ad3f28f13a3d5e51 | 1_pending | 1 | cool | pending | 2022-02-24 | +| c8b91b84808caaf5870d707866b59c | 1_submitted | 1 | lame | submitted | 2022-03-01 | +| c8b91b84808caaf5870d707866b59c | 1_submitted | 1 | cool | submitted | 2022-03-03 | +| 283ff22afb622dcc6a7da373ae1a0fb | 2_pending | 2 | cool | pending | 2022-02-27 | + +Remember, it’s important to only look for duplicate rows for the values that indicate a *true* difference between the rows of data the data; e.g., in type-two data, `updated_at_date` doesn’t mean that the other columns that we’ve decided we’re concerned with have changed since the previous time it was loaded, so that column doesn’t necessarily indicate a true difference between rows (though it usually indicates that something has changed, but that change may be outside our scope of concern in this case). But a change in `important_status`, for our purposes, would indicate a change in the data that you’d probably want to track. If you aren’t applying this technique to type-two data, but instead wanting to remove everything except the most recent data, you may have just a few columns that indicate a true difference between rows (an id at the right grain, and/or an id at a larger grain + timestamp). + +To build our `grain_id` key, we use the pure gold of the *[dbt_utils package](https://hub.getdbt.com/dbt-labs/dbt_utils/0.8.0/)*. If you’re unsure of what this package is, stop reading right now and make sure this is installed in your dbt project. It will bring joy to your life and ease to your struggling! + +`dbt_utils.star` is the *star* [Editor’s note: 🤦‍♀️] of the show here, which allows you to grab all the columns, *except* the ones you list. If you only have a couple columns, it may be easier just to list them for the `cols` variable instead of using the `star` function. + +```sql +{% macro build_key_from_columns(table_name, exclude=[]) %} + +{% set cols = {{ dbt_utils.star(from=ref('table_name'), except = exclude) }} %} + +{%- for col in cols -%} + + {%- do col_list.append("coalesce(cast(" ~ col.column ~ " as " ~ dbt_utils.type_string() ~ "), '')")  -%} + +{%- endfor -%} + +{{ return(dbt_utils.surrogate_key(col_list)) }} + +{% endmacro %} +``` + +For each row of data, this macro grabs each value from all the columns, except the columns we specify in the exclude list. Then it creates a hash-key using `dbt_utils.surrogate_key` that will reflect the uniqueness of the column values (i.e. if the combination of values is *not* unique, the `surrogate_key` will be the same, which is what we want to capture). The columns in the exclude list are values that we want to ignore when looking for a change in the data table (like `unimportant_value,`a column whose fluctuations we don’t want to indicate a real difference between rows). Call the macro above to create a column in your base or staging layer, and call it `grain_id`, so we can filter out the changes where `count(grain_id) > 1`: + +```sql +{{ build_key_from_columns(source('name', 'table_name')) }} as grain_id, +``` + +## Step 2: Mark truly unique rows, and filter + +> Step 2 walks you through how to filter out duplicates based on your new `grain_id` from Step 1. + +To get rid of dupes, find the previous `grain_id` (remember this is a hash-key of all the values in a row), compare it to the most recent `grain_id` as ordered by a reliable timestamp. If they are not equal, then mark it as a real difference in the data, meaning you’ll keep it! Notice that we `coalesce` our window function with a string `‘first_record’`, so that an entity’s first record, which naturally has no `previous_grain_id`, won’t have a `null` in that column and throw off all our downstream comparisons. + +```sql +mark_real_diffs as ( + + select + *, + coalesce( + lag(grain_id) over (partition by entity_id order by updated_at_date), + 'first_record' + ) as previous_grain_id, + case + when grain_id != previous_grain_id then true + else false + end as is_real_diff + + from base_product + +), +``` + +Filter out everything that isn’t marked as a real difference, and now you’re dupe-free! + +```sql +filter_real_diffs as ( + + select * + + from mark_real_diffs + + where is_real_diff = true + +) + +select * from filter_real_diffs +``` + +## Step 3: Test your data + +> *What happens in this step? You check your data because you are thorough!* + +Good thing dbt has already built this for you. Add a [unique test](https://docs.getdbt.com/docs/building-a-dbt-project/tests#generic-tests) to your YAML model block for your `grain_id` in this de-duped staging model, and give it a dbt test! + +```yaml +models: + - name: my_model + columns: + - name: grain_id + tests: + - unique + - not_null +``` + +## Conclusion + +> This filtering logic is ideally done as upstream as possible at a base or staging layer to avoid terrible fan out when you start joining your tables. + +You star! I’m so glad you worked your way to the end, and now your data is squeaky clean. + +To recap, we took the following steps to identify and eliminate partial duplicates: + +1. Decided which columns we care about, which include: + 1. The column(s) that form the unique entity we're concerned with + 2. The column(s) that constitute attributes of that entity whose changes we want to track + 3. The column(s) that constitute our most reliable updating time dimension +2. Created a `surrogate_key` of all the above columns (except the timestamp, which we use for ordering), which captures the combination of values from those columns into a single column +3. Used this key to mark and remove duplicates within the partial set of columns we’re tracking + +These kinds of transformations not only help clean up your data, but they play a bigger part in crafting your data sets into what you need to capture in order to generate real value *and* contribute to real understanding of datasets among your data consumers. Remember that these datasets work for **you** — you are skilled enough to mold these datasets into your vision, to reflect the questions you and your customers want to answer. Nobody puts Baby in a corner! Not even data. + +![Dirty dancing - nobody puts baby in a corner!](/img/blog/2022-04-19-complex-deduplication/dancing-baby.gif) + +You don’t have to be pigeon-holed by the grain of the source data or the massive number of value changes captured by history tables. You decide what a clean dataset looks like, which columns are of value, and use those sweet, sweet analytics-engineering skills to build a model how you see fit. We’re all so proud of you! Carry on, friend. diff --git a/website/blog/2022-04-19-dbt-cloud-postman-collection.md b/website/blog/2022-04-19-dbt-cloud-postman-collection.md new file mode 100644 index 00000000000..7ea81e89181 --- /dev/null +++ b/website/blog/2022-04-19-dbt-cloud-postman-collection.md @@ -0,0 +1,184 @@ +--- +title: "Introducing the dbt Cloud API Postman Collection: a tool to help you scale your account management" +description: "Discover powerful dbt Cloud endpoints with this postman collection put together by Solution Architect Matt Winkler." +slug: dbt-cloud-api-postman-collection-announcement + +authors: [matt_winkler] + +tags: [dbt tutorials] +hide_table_of_contents: false + +date: 2022-05-10 +is_featured: true +--- +>:question: Who is this for: +>This is for advanced users of dbt Cloud that are interested in expanding their knowledge of the dbt API via an interactive Postman Collection. We only suggest diving into this once you have a strong knowledge of dbt + dbt Cloud. You have a couple of options to review the collection: +> +>* get a live version of the collection via [![Run in Postman](https://run.pstmn.io/button.svg)](https://god.gw.postman.com/run-collection/14183654-892ae7dc-e6a2-4165-8b57-1545dd69e4aa?action=collection%2Ffork&collection-url=entityId%3D14183654-892ae7dc-e6a2-4165-8b57-1545dd69e4aa%26entityType%3Dcollection%26workspaceId%3D048d09df-b9b5-4794-ad11-d0453ec3ecc4). +>* check out the [collection documentation](https://documenter.getpostman.com/view/14183654/UyxohieD#93c57cbf-3cb9-4c14-8c9a-278c19c5d6f1) to learn how to use it. + +The dbt Cloud API has well-documented endpoints for creating, triggering and managing dbt Cloud jobs. But there are other endpoints that aren’t well documented yet, and they’re extremely useful for end-users. These endpoints exposed by the API enable organizations not only to orchestrate jobs, but to manage their dbt Cloud accounts programmatically. This creates some really interesting capabilities for organizations to scale their dbt Cloud implementations. + +The main goal of this article is to spread awareness of these endpoints as the docs are being built & show you how to use them. + + + +You can use this blog post as an entry point to this [postman collection](https://documenter.getpostman.com/view/14183654/UVsSNiXC#auth-info-7ad22661-8807-406b-aec0-34a46b671aac) to help you automate previously manual tasks, such as managing dbt Cloud account infrastructure, creating dbt Cloud projects, database connections, and managing users. + +Please keep in mind that the collection is not an evergreen doc. We are actively developing and updating the API endpoints used to interact with dbt Cloud, so endpoint urls and / or expected request formats may change. Each endpoint in the collection provides comment capabilities, so please notify us there if something looks amiss. + +With all of that being said, why should dbt users care about automating dbt Cloud account management? + +## What problems does programmatic dbt Cloud account management solve? + +When first learning dbt Cloud and operating at a smaller scale, most end users tend to favor manual, GUI based workflows for creating and managing their account infrastructure. Many of our customers start off this way, but they usually end up running into these bottlenecks as the number of jobs and projects multiplies. Here are some examples of the kind of bottlenecks I hear our growing customers talk about. + +- “I find myself wasting time manually clicking through the UI to manage infrastructure, especially after deploying more than a handful of projects and environments.” +- “I don’t have peace of mind that my production environment is configured exactly as intended. If a new team member deletes or changes something, I have to run a fire drill to fix it.” +- “My organization requires me to run any environmental configuration changes through code review and version control.” + +We usually advise our customers to leverage API requests to automate these typically manual tasks, and you should, too! + +## Closing Thoughts + +Beyond the day-to-day process of managing their dbt Cloud accounts, many organizations benefit from being able to quickly replicate environments as they experiment with new dbt features and development patterns. Governance is another benefit of managing infrastructure in code, as resource definitions can be version controlled and inspected by the relevant teams before changes go live. These concepts are high on our minds as we look to provide additional capabilities to our customers in their use of dbt Cloud. Happy APIing! + +*Below this you’ll find a series of example requests - use these to guide you or [check out the Postman Collection](https://dbtlabs.postman.co/workspace/Team-Workspace~520c7ac4-3895-4779-8bc3-9a11b5287c1c/request/12491709-23cd2368-aa58-4c9a-8f2d-e8d56abb6b1dlinklink) to try it out yourself.* + +## Appendix + +### Examples of how to use the Postman Collection + +Let’s run through some examples on how to make good use of this Postman Collection. + +#### Migrating dbt Cloud Projects + +One common question we hear from customers is “How can we migrate resources from one dbt Cloud project to another?” Often, they’ll create a development project, in which users have access to the UI and can manually make changes, and then migrate selected resources from the development project to a production project once things are ready. + +There are several reasons one might want to do this, including: + +- Probably the most common is separating dev/test/prod environments across dbt Cloud projects to enable teams to build manually in a development project, and then automatically migrate those environments & jobs to a production project. +- Building “starter projects” they can deploy as templates for new teams onboarding to dbt from a learning standpoint. +- Some particularly security conscious customers may require version control and governance processes to run before any change to infrastructure, including their dbt Cloud accounts. + +Below, we show an example of migrating an environment and a job definition from a development project to a production project. Note that this assumes you already have both projects set up. You could take this automation process even further by creating new projects with repository and database connections via the API as well. Please refer to the collection for additional details. + +**Before you start**: Make sure to [get your API key](https://docs.getdbt.com/docs/dbt-cloud/dbt-cloud-api/user-tokens) and add it to the Authentication Header of your requests. + +Our example contains the following elements: + +![This diagram depicts how an API request works. The diagram depicts a Dev project and a Prod project. The Dev project contains two environments: a development and deployment environment. The deployment project contains a job. The diagram shows the deployment environment that contains the job being copied over to the Prod Project via API request.](/img/blog/2022-04-19-dbt-cloud-postman-collection/example-cloud-environment.png) + +### Setup + +Create a “development” and a “production” project in dbt Cloud using the UI +Set up a [data warehouse connection](https://docs.getdbt.com/docs/dbt-cloud/cloud-configuring-dbt-cloud/connecting-your-database) and [repository connection](https://docs.getdbt.com/docs/dbt-cloud/cloud-configuring-dbt-cloud/cloud-configuring-repositories) + +#### Pull the environment from the development project + +All of this information is obtainable from the API (see the postman collection), but you can also identify the correct IDs to use from the URL when logged in to dbt Cloud: + +![A screenshot of the dbt Cloud browser, with the URL highlighted as an example of where to find the correct ID number](/img/blog/2022-04-19-dbt-cloud-postman-collection/dbt-cloud-api-ID.png) + +- Account ID: 28885 +- Project ID: 86704 +- Environment ID: 75286 + +We’ll send a GET request to + +https://cloud.getdbt.com/api/v3/accounts/28885/projects/86704/environments/75286/ + +#### Push the environment to the production project + +We take the response from the GET request above, and then to the following: + +1. Adjust some of the variables for the new environment: + - Change the the value of the “project_id” field from 86704 to 86711 + - Change the value of the “name” field from “dev-staging” to “production–api-generated” + - Set the “custom_branch” field to “main” + +2. Send the POST request shown below to: https://cloud.getdbt.com/api/v3/accounts/28885/projects/86711/environments/ + +**Request body**: + +``` +{ + "id": null, + "account_id": 28885, + "project_id": 86711, + "credentials_id": 108731, + "name": "production–api-generated", + "dbt_version": "1.0.0", + "type": "deployment", + "state": 1, + "use_custom_branch": true, + "custom_branch": "main" +} +``` + +3. Note the environment ID returned in the response, as we’ll use to create a dbt Cloud job in the next step + +#### Pull the job definition from the dev project + +We send a GET request to: + +https://cloud.getdbt.com/api/v2/accounts/28885/jobs/72025/ + +#### Push the job definition to the prod project +1. Adjust some of the variables for the new job: + - Remove the “created_at”, “updated_at”, and “is_deferrable” fields. [Defer](https://docs.getdbt.com/reference/node-selection/defer) logic is out of scope for this post. + - Change the value of the “name” field to “production-run–api-generated” +2. Sent the POST request shown below to https://cloud.getdbt.com/api/v2/accounts/28885/jobs/ + +**Request body**: + +``` +{ + "execution": { + "timeout_seconds": 600 + }, + "generate_docs": false, + "run_generate_sources": false, + "id": null, + "account_id": {{account_id}}, + "project_id": 86711, + "environment_id": 75296, + "name": "production-run--api-generated", + "dbt_version": null, + "execute_steps": [ + "dbt build" + ], + "state": 1, + "deactivated": false, + "run_failure_count": 0, + "deferring_job_definition_id": null, + "lifecycle_webhooks": false, + "lifecycle_webhooks_url": null, + "triggers": { + "github_webhook": false, + "git_provider_webhook": false, + "custom_branch_only": true, + "schedule": false + }, + "settings": { + "threads": 4, + "target_name": "default" + }, + "schedule": { + "cron": "0 * * * *", + "date": { + "type": "every_day" + }, + "time": { + "type": "every_hour", + "interval": 1 + } + }, + "generate_sources": false, + "cron_humanized": "Every hour", + "next_run": null, + "next_run_humanized": null + } +``` + +And we’re done! We now have the basic mechanics in place for migrating dbt Cloud Objects. diff --git a/website/blog/2022-05-03-making-dbt-cloud-api-calls-using-dbt-cloud-cli.md b/website/blog/2022-05-03-making-dbt-cloud-api-calls-using-dbt-cloud-cli.md new file mode 100644 index 00000000000..2acd3bed53d --- /dev/null +++ b/website/blog/2022-05-03-making-dbt-cloud-api-calls-using-dbt-cloud-cli.md @@ -0,0 +1,327 @@ +--- +title: "Making dbt Cloud API calls using dbt-cloud-cli" +description: "Simo Tumelius shares how to use his dbt-cloud-cli to make more readable and streamlined dbt Cloud API calls." +slug: making-dbt-cloud-api-calls-using-dbt-cloud-cli + +authors: [simo_tumelius] + +tags: [data ecosystem] +hide_table_of_contents: false + +date: 2022-05-03 +is_featured: true +--- + +dbt Cloud is a hosted service that many organizations use for their dbt deployments. Among other things, it provides an interface for creating and managing deployment jobs. When triggered (e.g., cron schedule, API trigger), the jobs generate various artifacts that contain valuable metadata related to the dbt project and the run results. + +dbt Cloud provides a REST API for managing jobs, run artifacts and other dbt Cloud resources. Data/analytics engineers would often write custom scripts for issuing automated calls to the API using tools [cURL](https://curl.se/) or [Python Requests](https://docs.python-requests.org/en/latest/). In some cases, the engineers would go on and copy/rewrite them between projects that need to interact with the API. Now, they have a bunch of scripts on their hands that they need to maintain and develop further if business requirements change. If only there was a dedicated tool for interacting with the dbt Cloud API that abstracts away the complexities of the API calls behind an easy-to-use interface… Oh wait, there is: [the dbt-cloud-cli](https://github.com/data-mie/dbt-cloud-cli)! + + + +In this blog post I’ll shine some light on how the dbt-cloud-cli project came to be and how it can make a data/analytics engineer’s work easier. I’ll also walk you through an example use case where we download a dbt Cloud job run catalog.json artifact and implement a simple data catalog app using the same tools that were used in creating dbt-cloud-cli. + +## What is dbt-cloud-cli and why should you use it? + +What kicked off this project came from the fact that there is currently no easy-to-use interface for the dbt Cloud API. In order to make calls to the API you’d need to write custom scripts that use tools like cURL or Python Requests. There’s nothing inherently wrong with custom scripts but there is an overhead in writing and maintaining those scripts. + +Readability is also a factor the importance of which cannot be overstated. With most programming languages, [the ratio of time reading vs writing code is well over 10:1](https://app.works/the-importance-of-code-readability/#:~:text=What%20is%20code%20readability%3F,or%20add%20a%20new%20feature.). Good code is easily readable and understandable by ourselves and other developers and it minimizes the cognitive load of deciphering what was the original intention of the author. + +dbt-cloud-cli is a command line interface (CLI) that abstracts dbt Cloud API calls behind a user-friendly and elegant interface. The CLI is written in Python using [pydantic](https://pydantic-docs.helpmanual.io/) and [click](https://click.palletsprojects.com/en/8.0.x/). Let me demonstrate the difference in complexity and readability between cURL vs dbt-cloud-cli for triggering a dbt Cloud job run: + + + + +```bash +curl -H "Authorization:Token $DBT_CLOUD_API_TOKEN" -H "Content-Type:application/json" -d '{"cause":"Triggered using cURL"}' https://cloud.getdbt.com/api/v2/accounts/$DBT_CLOUD_ACCOUNT_ID/jobs/43167/run/ +``` + + + + +```js +dbt-cloud job run --job-id 43167 +``` + + + + +You probably agree that the latter example is definitely more elegant and easier to read. `dbt-cloud` handles the request boilerplate (e.g., api token in the header, endpoint URL) so that you don’t need to worry about authentication or remember which endpoint to use. Also, the CLI implements additional functionality (e.g., `--wait`) for some endpoints; for example, `dbt cloud job run --wait` will issue the job trigger, wait until the job finishes, fails or is cancelled and then prints out the job status response. + +In addition to CLI commands that interact with a single dbt Cloud API endpoint there are composite helper commands that call one or more API endpoints and perform more complex operations. One example of composite commands are `dbt-cloud job export` and `dbt-cloud job import` where, under the hood, the export command performs a `dbt-cloud job get` and writes the job metadata to a file and the import command reads job parameters from a JSON file and calls `dbt-cloud job create`. The export and import commands can be used in tandem to move dbt Cloud jobs between projects. Another example is the `dbt-cloud job delete-all` which fetches a list of all jobs using `dbt-cloud job list` and then iterates over the list prompting the user if they want to delete the job. For each job that the user agrees to delete a `dbt-cloud job delete` is performed. + +To install the CLI in your Python environment run `pip install dbt-cloud-cli` and you’re all set. You can use it locally in your development environment or e.g. in a GitHub actions workflow. + +## How the project came to be + +I’m a freelance data and analytics engineer and almost all of the projects I work with involve dbt Cloud one way or another. In a typical project, we’d set up a simple “run and test” job in dbt Cloud that is scheduled to run once or twice a day. Often there’d also be a [continuous integration job](https://docs.getdbt.com/docs/dbt-cloud/using-dbt-cloud/cloud-enabling-continuous-integration) that runs on Pull Requests in GitHub. + +These two job triggering methods (i.e., cron and PR trigger) are sufficient in most projects, but there are some cases where additional control over when a job is run or what else is executed in the job’s context is needed. For example, you may need to load data to your database before a job is run or download artifacts after the run is finished. + +In my case, we didn’t yet have an EL pipeline for an external data source. So, we hacked together a simple Python script for loading the data and ran the script as part of our CI workflow in GitHub Actions before triggering a dbt Cloud job. This would ensure that the data in our database was up-to-date before the job ran. + +Initially, we issued the dbt Cloud API requests to trigger job runs using cURL and it worked perfectly fine until we needed to implement a waiting loop that periodically checked the job status and returned when the job was finished. Luckily I found a Python script by Sean McIntyre ([see the dbt Discourse post](https://discourse.getdbt.com/t/triggering-a-dbt-cloud-job-in-your-automated-workflow-with-python/2573)) that does exactly this. + +I modified the script according to our needs and wrapped it in a `dbt-cloud job run` CLI command using click (actually the entry point wasn’t `dbt-cloud` at that time but you get the idea). Click (“Command Line Interface Creation Kit”) is a Python library for creating CLIs with as little code as necessary. Implementing a simple CLI using click only requires adding a few decorators (e.g., `group`, `command` and `option`) to the functions in your code and you’re good to go. + +Now we had exactly what we wanted and our CI workflow in GitHub actions looked slick: + +```js +- name: Trigger dbt Cloud job run + run: | + ./cool_script_bro.sh + dbt-cloud job run --job-id $DBT_CLOUD_JOB_ID +``` + +Fast forward a month or two and there was another client that needed something similar. I felt that this was an opportunity to open source the project not just to benefit me and my clients but also [the broader dbt community](https://www.getdbt.com/community/) (❤️). So, I moved the project to a public github repository with a goal of eventually covering all of the dbt Cloud API endpoints. + +While working with the initial 0.1.0 release that included only the `dbt-cloud job run` command I decided to have some fun and try how well pydantic (Python dataclasses on steroids!) and `click` worked together. I’m a big fan of `pydantic`, and I’ve used it in a wide variety of projects including machine learning models and automated testing software for a medical device. Even though Python has had built-in dataclasses since version 3.7, they fall short when it comes to data validation and general developer ergonomics (IMO) and that’s where `pydantic` comes in; among other things, `pydantic` implements a validator decorator that is used to define custom validations for model fields (e.g., CLI arguments). + +I refactored the `dbt-cloud-cli` code so that the CLI commands were now implemented as pydantic models where the model fields are the dbt Cloud API endpoint arguments. The `pydantic` model fields could now be translated to `click` arguments which resulted in the following CLI command implementation pattern: + +```python +import click +from dbt_cloud.command import DbtCloudJobGetCommand + +@click.group() +def dbt_cloud(): + pass + +@dbt_cloud.group() +def job(): + pass + +@job.command(help=DbtCloudJobGetCommand.get_description()) +@DbtCloudJobGetCommand.click_options +def get(**kwargs): + command = DbtCloudJobGetCommand.from_click_options(**kwargs) + execute_and_print(command) +``` + +After the initial release I started to expand to cover the rest of the dbt Cloud API endpoints. For a list of all the covered API endpoints and implemented CLI commands, see https://github.com/data-mie/dbt-cloud-cli. + +## Creating a data catalog app using dbt Cloud artifacts + +In this example we’ll download a `catalog.json` artifact from the latest run of a dbt Cloud job using `dbt-cloud run list` and `dbt-cloud get-artifact` and then write a simple Data Catalog CLI application using the same tools that are used in `dbt-cloud-cli` (i.e., `click` and `pydantic`). Let’s dive right in! + +The first command we need is the `dbt-cloud run list` which uses an [API V4 endpoint](https://docs.getdbt.com/dbt-cloud/api-v4#operation/list-account-runs) that returns runs sorted by creation date, with the most recent run appearing first. The command returns a JSON response that has one top-level attribute `data` that contains a list of runs. We’ll need to extract the `id` attribute of the first one and to do that we use [jq](https://stedolan.github.io/jq/): + +```js +latest_run_id=$(dbt-cloud run list --job-id $DBT_CLOUD_JOB_ID | jq .data[0].id -r) +``` + +Next, we use the `dbt-cloud get-artifact` command to download the `catalog.json` artifact: + +```js +dbt-cloud run get-artifact --run-id $latest_run_id --path catalog.json -f catalog.json +``` + +To explore the downloaded catalog file we’ll write a simple CLI application. The [catalog.json](https://schemas.getdbt.com/dbt/catalog/v1.json) has four top level properties: metadata, nodes, sources and errors. In this example we explore the nodes and sources only and leave the metadata and errors out. + +First, we need a `Catalog` abstraction that reflects the catalog JSON schema: + +```py +from typing import Optional, Dict, Any +from pydantic import BaseModel, Field + +class Stats(BaseModel): + """Represent node stats in the Catalog.""" + + id: str + label: str + value: Any + include: bool + description: str + + def __str__(self): + return f"{self.label}: {self.value}" + + +class Column(BaseModel): + """Represents a column in the Catalog.""" + + type: str + index: int + name: str + comment: Optional[str] + + def __str__(self): + return f"{self.name} (type: {self.type}, index: {self.index}, comment: {self.comment})" + + +class Node(BaseModel): + """Represents a node in the Catalog.""" + + unique_id: str + metadata: Dict[str, Optional[str]] + columns: Dict[str, Column] + stats: Dict[str, Stats] + + @property + def name(self): + return self.metadata["name"] + + @property + def database(self): + return self.metadata["database"] + + @property + def schema(self): + return self.metadata["schema"] + + @property + def type(self): + return self.metadata["type"] + + def __gt__(self, other): + return self.name > other.name + + def __lt__(self, other): + return self.name < other.name + + def __str__(self): + return f"{self.name} (type: {self.type}, schema: {self.schema}, database: {self.database})" + + +class Catalog(BaseModel): + """Represents a dbt catalog.json artifact.""" + + metadata: Dict + nodes: Dict[str, Node] + sources: Dict[str, Node] + errors: Optional[Dict] +``` + +The four abstractions (`Stats`,`Column`, `Node `and `Catalog`) all inherit [the pydantic BaseModel](https://pydantic-docs.helpmanual.io/usage/models/) which implements various methods for parsing files and other python objects into model instances. We’ll leave the parsing to pydantic (i.e., `BaseModel.parse_file` classmethod) so that we can focus solely on the app logic. + +The `CatalogExploreCommand` abstraction implements the CLI app which is then wrapped in a `click.command` that implements the CLI entry point. The `CatalogExploreCommand` class inherits `ClickBaseModel` that implements a `click_options` classmethod which we’ll use to decorate the entry point. This method is where the pydantic to click translation magic happens (i.e., pydantic model fields are translated [into click options](https://click.palletsprojects.com/en/8.0.x/options/)). Note that the app [uses inquirer](https://github.com/magmax/python-inquirer) in addition to `click` to create interactive “select option from a list” CLI prompts. + +```py +import click +from enum import Enum +from pathlib import Path +from pydantic import Field +from dbt_cloud.command.command import ClickBaseModel + +class NodeType(Enum): + SOURCE = "source" + NODE = "node" + + +class CatalogExploreCommand(ClickBaseModel): + """An inteactive application for exploring catalog artifacts.""" + + file: Path = Field(default="catalog.json", description="Catalog file path.") + title: str = Field( + default="Data Catalog", description="ASCII art title for the app." + ) + title_font: str = Field( + default="rand-large", + description="ASCII art title font (see https://github.com/sepandhaghighi/art#try-art-in-your-browser for a list of available fonts)", + ) + + def get_catalog(self) -> Catalog: + return Catalog.parse_file(self.file) + + def print_title(self): + from art import tprint + + tprint(self.title, font=self.title_font) + + def execute(self): + import inquirer + + self.print_title() + + while True: + node_type_options = [ + inquirer.List( + "node_type", + message="Select node type to explore", + choices=[node_type.value for node_type in NodeType], + ) + ] + node_type = NodeType(inquirer.prompt(node_type_options)["node_type"]) + self.explore(node_type=node_type) + if not click.confirm("Explore another node type?"): + break + + def explore(self, node_type: NodeType): + """Interactive exploration of nodes to explore and display their metadata""" + import inquirer + + catalog = self.get_catalog() + if node_type == NodeType.SOURCE: + nodes = list(catalog.sources.values()) + else: + nodes = list(catalog.nodes.values()) + + while True: + databases = sorted(set(map(lambda x: x.database, nodes))) + database_options = [ + inquirer.List("database", message="Select database", choices=databases) + ] + database = inquirer.prompt(database_options)["database"] + nodes_filtered = list(filter(lambda x: x.database == database, nodes)) + + schemas = sorted(set(map(lambda x: x.schema, nodes_filtered))) + schema_options = [ + inquirer.List("schema", message="Select schema", choices=schemas) + ] + schema = inquirer.prompt(schema_options)["schema"] + nodes_filtered = list(filter(lambda x: x.schema == schema, nodes_filtered)) + + node_options = [ + inquirer.List( + "node", message="Select node", choices=sorted(nodes_filtered) + ) + ] + node = inquirer.prompt(node_options)["node"] + click.echo(f"{node.name} columns:") + for column in node.columns.values(): + click.echo(f"- {column}") + click.echo("") + for stats in node.stats.values(): + if stats.id == "has_stats": + continue + click.echo(stats) + if not click.confirm(f"Explore another {node_type.value}?"): + break + + +@click.command(help=CatalogExploreCommand.get_description()) +@CatalogExploreCommand.click_options +def data_catalog(**kwargs): + command = CatalogExploreCommand.from_click_options(**kwargs) + command.execute() +``` + +The `CatalogExploreCommand.execute` method implements the interactive exploration logic. First the app prompts to select a node type to explore (`source` or `node`) and then it asks the user to select a database, a schema in the selected database and finally a model in the selected schema. The app then prints out the model columns and stats (if there are any). All this is wrapped in a loop with “Explore another node? [y/N]” and “Explore another node type? [y/N]” prompts for either continuing the loop or breaking out of it. + +I’ve included the app in the latest version of dbt-cloud-cli so you can test it out yourself! To use the app you need install dbt-cloud-cli with extra dependencies: + +```bash +pip install dbt-cloud-cli[demo] +``` + +Now you can the run app: + +```bash +dbt-cloud demo data-catalog --file catalog.json +``` + +## Parting thoughts + +To summarize, the `dbt-cloud-cli`I implements an easy-to-use command line interface for the dbt Cloud API which abstracts away the complexities of the API calls. The CLI has interfaces to many of the API endpoints and covering all of the endpoints is on the project’s roadmap. For a list of all the covered API endpoints and implemented CLI commands, see https://github.com/data-mie/dbt-cloud-cli. + +In addition to commands that interact with a single dbt Cloud API endpoint there are composite helper commands that call one or more API endpoints and perform more complex operations (e.g., `dbt-cloud job export` and `dbt-cloud job import`). + +The `dbt-cloud-cli` makes interacting with the dbt Cloud API a breeze compared to using and maintaining custom cURL/ Python Requests scripts. Furthermore, `dbt-cloud-cli` commands handle all the API call boilerplate under the hood so that you don’t need to google or memorize how to interact with the API. And when in doubt, just add a `--help` flag to a `dbt-cloud-cli` command and you’ll get a list of all the available commands or arguments. + + +PS. There are still API endpoints that haven’t been implemented in the CLI. If there’s an endpoint you’d like a CLI command for you can open an issue in the GitHub repository. All contributions to the project (be it documentation in README or new CLI commands) are welcome! If you have any questions on the project or how to contribute, feel free to drop me a DM in dbt Slack. diff --git a/website/blog/2022-05-17-stakeholder-friendly-model-names.md b/website/blog/2022-05-17-stakeholder-friendly-model-names.md new file mode 100644 index 00000000000..0e0ccad5c96 --- /dev/null +++ b/website/blog/2022-05-17-stakeholder-friendly-model-names.md @@ -0,0 +1,167 @@ +--- +title: "Stakeholder-friendly model names: Model naming conventions that give context" +description: "Your model names are usually made by engineers, for engineers. While that's great for maintainability, your end users won't have the same context into those model names as you do." +slug: stakeholder-friendly-model-names + +authors: [pat_kearns] + +tags: [analytics craft] +hide_table_of_contents: false + +date: 2022-05-17 +is_featured: true +--- + +Analytics engineers (AEs) are constantly navigating through the names of the models in their project, so naming is important for maintainability in your project in the way you access it and work within it. By default, dbt will use your model file name as the view or table name in the database. But this means the name has a life outside of dbt and supports the many end users who will potentially never know about dbt and where this data came from, but still access the database objects in the database or business intelligence (BI) tool. + +Model naming conventions are usually made by AEs, for AEs. While that’s useful for maintainability, it leaves out the people who model naming is supposed to primarily benefit: the end users. **Good model naming conventions should be created with one thing in mind: Assume your end-user will have no other context than the model name.** Folders, schema, and documentation can add additional context, but they may not always be present. Your model names will always be shown in the database. + + + +In this article, we’ll take a deeper look at why model naming conventions are important from the point-of-view of the stakeholders that actually use their output. We’ll explore: + +- Who those stakeholders are +- How they access your projects & what the user experience looks like +- What they are really looking for out of your model names +- Some model naming best practices you can follow to make everyone happy + +## Your model names and your end-user’s experience + +>“[Data folks], what we [create in the database]… echoes in eternity.” -Max(imus, Gladiator) + +Analytics Engineers are often centrally located in the company, sandwiched between data analysts and data engineers. This means everything AEs create might be read and need to be understood by both an analytics or customer-facing team and by teams who spend most of their time in code and the database. Depending on the audience, the scope of access differs, which means the user experience and context changes. Let’s elaborate on what that experience might look like by breaking end-users into two buckets: + +- Analysts / BI users +- Analytics engineers / Data engineers + +### The analyst’s user experience + +Analysts are interfacing with data from the outside in. They are in meetings with stakeholders, clients, customers, and management within the organization. These stakeholders want clearly articulated thoughts, answers, trends, insights from the analyst that will help move the needle forward, help the business grow, increase productivity, increase profitability, etc. With these goals in mind, they must form a hypothesis and prove their point with data. They will access the data via: + +- Precomputed views/tables in a BI tool +- Read-only access to the dbt Cloud IDE docs +- Full list of tables and views in their + +#### Precomputed views/tables in a BI tool + +Here we have drag and drop functionality and a skin over top of the underlying `database.schema.table` where the database object is stored. The BI Tool has been configured by an Analytics Engineer or Data Engineer to automatically join datasets as you click/drag/drop fields into your exploration. + +**How model names can make this painful:** +The end users might not even know what tables the data refers to, as potentially everything is joined by the system and they don’t need to write their own queries. If model names are chosen poorly, there is a good chance that the BI layer on top of the database tables has been renamed to something more useful for the analysts. This adds an extra step of mental complexity in tracing the lineage from data model to BI. + +#### Read only access to the dbt Cloud IDE docs +If Analysts want more context via documentation, they may traverse back to the dbt layer and check out the data models in either the context of the Project or Database. In the Project view, they will see the data models in the folder hierarchy present in your project’s repository. In the Database view you will see the output of the data models as present in your database, ie. `database / schema / object`. + +![A screenshot depicting the dbt Cloud IDE menu's Database view which shows you the output of your data models. Next to this view, is the Project view.](/img/blog/2022-05-17-stakeholder-friendly-model-names/project-view.png) + +**How model names can make this painful:** +For the Project view, generally abstracted department or organizational structures as folder names presupposes the reader/engineer knows what is contained within the folder beforehand or what that department actually does, or promotes haphazard clicking to open folders to see what is within. Organizing the final outputs by business unit or analytics function is great for end users but doesn't accurately represent all the sources and references that had to come together to build this output, as they often live in another folder. + +For the Database view, pray your team has been declaring a logical schema bucketing, or a logical model naming convention, otherwise you will have a long, alphabetized list of database objects to scroll through, where staging, intermediate, and final output models are all intermixed. Clicking into a data model and viewing the documentation is helpful, but you would need to check out the DAG to see where the model lives in the overall flow. + +#### The full dropdown list in their data warehouse. + +If they have access to Worksheets, SQL runner, or another way to write ad hoc sql queries, then they will have access to the data models as present in your database, ie. `database / schema / object`, but with less documentation attached, and more proclivity towards querying tables to check out their contents, which costs time and money. + +![A screenshot of the the SQL Runner menu within Looker showcasing the dropdown list of all data models present in the database.](/img/blog/2022-05-17-stakeholder-friendly-model-names/data-warehouse-dropdown.png) + +**How model names can make this painful:** +Without proper naming conventions, you will encounter `analytics.order`, `analytics.orders`, `analytics.orders_new` and not know which one is which, so you will open up a scratch statement tab and attempt to figure out which is correct: + +```sql +-- select * from analytics.order limit 10 +-- select * from analytics.orders limit 10 +select * from analytics.orders_new limit 10 +``` +Hopefully you get it right via sampling queries, or eventually find out there is a true source of truth defined in a totally separate area: `core.dim_orders`. + +The problem here is the only information you can use to determine what data is within an object or the purpose of the object is within the schema and model name. + +### The engineer’s user experience + +Analytics Engineers and Data Engineers are often the ones creating analytics code, using SQL to transform data in a way that builds trust across your team — with testing, documentation and transparency. These engineers will have additional rights and might access and interact with the project (or parts of it) from: + +- Within the BI tool +- Within the data warehouse +- Within the folder structure of dbt Cloud IDE +- Within the DAG (Directed Acyclical Graph) +- Within the Pull Request (PR) + +#### Within the BI tool + +This is largely the same as the Analyst experience above, except they likely built or are aware of the database objects exposed in the BI Tool. + +**How model names can make this painful:** +There is not much worse than spending all week developing on a task, submitting Pull Requests, getting reviews from team members, and then exposing data models in the BI Tool, only to realize a better naming of the data models would make a lot more sense in the context of the BI Tool. You are then faced with a choice: rename your data model in the BI Tool (over-label as a quick fix) or go back in the stack, rename models and all dependencies, submit a new PR, get reviews, run & test to ensure your quick fix doesn’t break anything, then continue to expose your correctly named model in the BI Tool, ensuring the same name persists throughout the whole lineage (long fix). + +#### Within the data warehouse +This is largely the same as the Analyst experience above, except they created the data models or are aware of their etymologies. They are likely more comfortable writing ad hoc queries, but also have the ability to make changes, which adds a layer of thought processing when working. + +**How model names can make this painful:** +It takes time to become a subject matter expert in the database. You will need to know which schema a subject lives in, what tables are the source of truth and/or output models, versus experiments, outdated objects, or building blocks used along the way. Working within this context, engineers know the history and company lore behind why a table was named that way or how its purpose may differ slightly from its name, but they also have the ability to make changes. + +Change management is hard; how many places would you need to update, rename, re-document, and retest to fix a poor naming choice from long ago? It is a daunting position, which can create internal strife when constrained for time over whether we should continually revamp and refactor for maintainability or focus on building new models in the same pattern as before. + +#### Within the folder structure of Cloud IDE +![A screenshot of the folder explorer within the dbt Cloud IDE that exposes the data model names.](/img/blog/2022-05-17-stakeholder-friendly-model-names/dbt-cloud-ide-folder.png) + +While developing within the IDE, you have almost the full range of information to reason about what is contained with a data model. You have a folder structure which will determine staging vs marts or any other helpful bucketing. You can see any configurations which might determine the target for your data model – database, schema, etc. You have documentation, both in line as comments and more formalized in descriptions in yml. Finally, you have the model name which should give you additional context. + +**How model names can make this painful:** +Within this context, model names do not seem as important, as they are surrounded by so much other contextual information. If you mistakenly rely on that contextual information to relay information to the end user, it will be lost when the context is removed. + +Without proper naming conventions, you are missing out on a way to determine lineage. You can reason about this with folder hierarchy, or by viewing the DAG, but that’s not always possible. + +#### Within the DAG + +By contrast, when viewing the DAG within the docs site or within the lineage tab, you get a lineage which adds more context to dependencies and directional flow. You get insight into how models are used as building blocks from left to right to transform your data from crude or normalized raw sources, into cleaned up modular derived pieces, and finally into the final outputs on the far right of the DAG, ready to be used by the analyst in infinite combinations to present it in ways to help clients, customers, and organizations make better decisions. + +![A screenshot of the lineage graph within dbt Cloud that showcases all data models within the project and their outputs.](/img/blog/2022-05-17-stakeholder-friendly-model-names/dag-view.png) + +**How model names can make this painful:** +The problem is that you will only see the model names (which become the nodes in the DAG), but you will not see folders, database/schema configurations, docs, etc. You can see the logical flow of data through your dbt pipeline, but without clearly defined model/node naming, the purpose of the model might be misconstrued, leading to wonky DAG pathways in the future. + +#### Within Pull Requests + +While reviewing code from someone else who is is contributing, you will see only the files that have been changed in the project’s repository. + +![A screenshot of the file names that have been listed in the "Files Changed" section of a GitHub Pull Request](/img/blog/2022-05-17-stakeholder-friendly-model-names/PR-view.png) + +**How model names can make this painful:** +This will severely limit the amount of information you see, because it will be localized to the changed files. You will still see changed folders and changed model names, but lack the total project context where those are helpful. Hopefully you have a robust pull request template and traditions of linking to the task ticket and providing context to why the work was completed this way, otherwise the person reviewing your changes will not have a lot of information at hand to make clear suggestions for improvement. + +## Model naming conventions that make everyone happy +While each of these examples are accessing the same thing (your SQL code and the database objects it creates), the context changes depending on how you access it and none of the methods show a complete picture by themselves. The only constant between all of them is the model name, which in turn becomes the database object name and the DAG node name. This is why it is important to focus on model naming conventions, in addition to, but with less emphasis on, folder structure and schema names, because the latter two will not persist to all access points. + +So what are some high level heuristics that analytics engineers can use to ensure the most information about a model’s purpose accompanies a model name? + +### Embed information in the name using an agreed upon pattern + +Practice verbosity in a reproducible way. Extra characters in a name are free. Potential errors caused by choosing the wrong database object or mental complexity as your DAG/project expands to entropy can cost a lot. + +#### Use a format like `___`. + +**`type/dag_stage`** + +Where in the DAG does this model live? This also correlates with whether this model is a modular building block or an output model for analysis. Something like `stg_` or `int_` is likely a cleanup or composable piece used within dbt and isn’t relevant for analysts. Something like `fct_`, `dim_` would be an output model that will be used in the BI Tool by analysts. This should not, however, be a declaration of materialization. You should be free to change the materialization of your model without needing to change the model name. + +**`source/topic`** + +Gives verbose context to the content. `stripe__payments` tells you what source system it comes from and what are the contents of the data. + +**`additional_context`** + +Adding a suffix for optional transformations can add clarity. `__daily` or `__pivoted` will tell you what transformation has happened to some other dataset. This should live at the end of the model name so that they remain together in the alphabetized list (e.g. `fct_paid_orders` and `fct_paid_orders__daily`) + +These 3 parts go from least granular (general) to most granular (specific) so you can scan a list of all models and see large categories at a glance and hone in on the models of interest without further context. + +### Coming up... + +In this part of the series, we talked about why the model name is the center of understanding for the purpose and content within a model. In the in the upcoming ["How We Structure Our dbt Projects"](https://docs.getdbt.com/guides/best-practices/how-we-structure/1-guide-overview) guide, you can explore how to use this naming pattern with more specific examples in different parts of your dbt DAG that cover regular use cases: + +- How would you name a model that is filtered on some columns +- Do we recommend naming snapshots in a specific way +- How would we name models in the case of: + - Internet user sessions + - Orders with customers, line items and payments + - Software as a Service models with Annually Recurring Revenue/Monthly Recurring Revenue churn etc... diff --git a/website/blog/2022-05-19-redshift-configurations-dbt-model-optimizations.md b/website/blog/2022-05-19-redshift-configurations-dbt-model-optimizations.md new file mode 100644 index 00000000000..239fa7148c6 --- /dev/null +++ b/website/blog/2022-05-19-redshift-configurations-dbt-model-optimizations.md @@ -0,0 +1,317 @@ +--- +title: "Optimizing dbt Models with Redshift Configurations" +description: "How to use the sort and dist configurations to optimize your Redshift query compute times" +slug: redshift-configurations-dbt-model-optimizations + +authors: [christine_berger] + +tags: [analytics craft] +hide_table_of_contents: false + +date: 2022-05-19 +is_featured: true +--- + +If you're reading this article, it looks like you're wondering how you can better optimize your Redshift queries - and you're *probably* wondering how you can do that in conjunction with dbt. + +In order to properly optimize, we need to understand **why** we might be seeing issues with our performance and **how** we can fix these with dbt [sort and dist configurations](https://docs.getdbt.com/reference/resource-configs/redshift-configs#using-sortkey-and-distkey). + + + +In this article, we’ll cover: + +- A simplified explanation of how Redshift clusters work +- What distribution styles are and what they mean +- Where to use distribution styles and the tradeoffs +- What sort keys are and how to use them +- How to use all these concepts to optimize your dbt models. + +Let’s fix this once and for all! + +## The Redshift cluster + +In order to understand how we should model in dbt for optimal performance on Redshift, I’m first going to step through a simplified explanation of the underlying architecture so that we can set up our examples for distributing and sorting. + +First, let’s visualize an example cluster: + +![Cluster.png](/img/blog/2022-05-19-redshift-configurations-dbt-model-optimizations/Cluster.png) + +This cluster has two nodes, which serve the purpose of storing data and computing some parts of your queries. You could have more than this, but for simplicity we’ll keep it at two. + +These two nodes are like the office spaces of two different people who have been assigned a portion of work for the same assignment based on the information they have in their respective offices. Upon completion of their work, they give their results back to their boss who then assembles the deliverable items and reports the combined information back to the stakeholder. + +Let's look at the data waiting to be loaded into Redshift: + +![Source-Data.png](/img/blog/2022-05-19-redshift-configurations-dbt-model-optimizations/Source-Data.png) + +You can see there are three tables of data here. When you load data into Redshift, the data gets distributed between the offices. In order to understand how that happens, let’s take a look at distribution styles. + +## What are distribution styles? + +Distribution styles determine how data will be stored between offices (our nodes). +Redshift has three distribution styles: + +- `all` +- `even` +- key-based + +Let’s dive into what these mean and how they work. + +### The `all` distribution style +An `all` distribution means that both workers get the same copies of data. +To implement this distribution on our tables in dbt, we would apply this +configuration to each of our models: +```python +{{ config(materialized='table', dist='all') }} +``` + +Here's a visualization of the data stored on our nodes: +![All-Distribution.png](/img/blog/2022-05-19-redshift-configurations-dbt-model-optimizations/All-Distribution.png) + +**When to use the `all` distribution**: + +This type of distribution is great for smaller data which doesn’t update frequently. Because `all` puts copies of our tables on all of our nodes, we’ll want to be sure we’re not giving our cluster extra work by needing to do this frequently. + +### The `even` distribution style +An `even` distribution means that both workers get close to equal amounts of data distributed to them. Redshift does this in a round-robin playing card style. + +To implement this distribution on our tables in dbt, we would apply this +configuration to each of our models: +```python +{{ config(materialized='table', dist='even') }} +``` + +Here's a visualization of the data stored on our nodes: +![Even-Distribution.png](/img/blog/2022-05-19-redshift-configurations-dbt-model-optimizations/Even-Distribution.png) + +Notice how our first worker received the first rows of our data**,** the second worker received the second rows, the first worker received the third rows, etc. + +**When to use the `even` distribution** + +This distribution type is great for a well-rounded workload by ensuring that each node has equal amounts of data. We’re not picky about *which* data each node handles, so the data can be evenly split between the nodes. That also means an equal amount of assignments are passed out resulting in no capacity wasted. + +### The key-based distribution style +A key-based distribution means that each worker is assigned data based on a specific identifying value. + +Let's distribute our **known_visitor_profiles** table by `person_id` by applying this configuration to the top of the model in dbt: + +```python +{{ config(materialized='table', dist='person_id') }} +``` + +Here's a visualization of the data stored on our nodes: +![Key-Based.png](/img/blog/2022-05-19-redshift-configurations-dbt-model-optimizations/Key-Based.png) + +It doesn’t look that different from `even`, right? The difference here is that because we’re using `person_id` as our distribution key, we ensure: + +- Node 1 will always get data associated with values 1, 3, 5 +- Node 2 will always get data associated with values 2, 4, 6 + +Let’s do this with another table to really see the effects. We'll apply the following configuration to our `visitors.sql` file: + +```python +{{ config(materialized='table', dist='person_id') }} +``` +Here's a visualization of the data stored on our nodes: +![Key-Based-2.png](/img/blog/2022-05-19-redshift-configurations-dbt-model-optimizations/Key-Based-2.png) + +You can see above that because we distributed `visitors` on `person_id` as well, the nodes received the associated data we outlined above. We did have some null `person_ids` - those will be treated as a key value and distributed to one node. + +**When to use key-based distribution** + +Key-based distribution is great for when you’re really stepping it up. If we can dial in to our commonly joined data, then we can leverage the benefits of **co-locating** the data on the same node. This means our worker can have the data they need to complete the tasks they have **without duplicating** the amount of storage we need. + +### Things to keep in mind when working with these configurations + +**Redshift has defaults.** +Redshift initially assigns an `all` distribution to your data, but switches seamlessly to an `even` distribution based on the growth of your data. This gives you time to model out your data without worrying too much about optimization. Reference what you learned above when you’re ready to start tweaking your modeling flows! + +**Distribution only works on stored data.** +These configurations don’t work on views or ephemeral models. +This is because the data needs to be stored in order to be distributed. That means that the benefits only happen using table or incremental materializations. + +**Applying sort and distribution configurations from dbt doesn’t affect how your raw data is sorted and distributed.** +Since dbt operates on top of raw data that’s already loaded into your warehouse, the following examples are geared towards optimizing your models *created with dbt*. + +You can still use what you learn from this guide to choose how to optimize from ingestion**,** however this would need to be implemented via your loading mechanism. For example if you’re using a tool like Fivetran or Stitch, you’ll want to consult their docs to find out whether you can set the sort and distribution on load through their interfaces. + +**Redshift is a columnar-store database.** +It doesn’t actually orient data values per row that it belongs to, but by column they belong to. This isn’t a necessary concept to understand for this guide, but in general columnar stores can be faster at retrieving data the more specific the selection you make. *While being selective of columns can optimize your model, I’ve found that it doesn’t have as tremendous an impact most of the time as setting sort and distribution configs.* As such, I won’t be covering this. + +# Handling joins: Where distribution styles shine + +Distribution styles *really* come in handy when we’re **handling joins**. Let’s work with an example. Say we have this query: + +```python +select +from visitors +left join known_visitor_profiles +on visitors.person_id = known_visitor_profiles.person_id +``` + +Now let’s look at what Redshift does per distribution style if we distribute both tables the same way. + +### All + +Using `all` copies our data sets and stores the entirety of each within each node. + +![All-Joining.gif](/img/blog/2022-05-19-redshift-configurations-dbt-model-optimizations/All-Joining.gif) + +In our offices example, that means our workers can do their load of the work in peace without being interrupted or needing to leave their office, since they each have all the information they need. + +The con here is that every time data needs to be distributed, it takes extra time and effort - we need to run to the copy machine, print copies for everyone, and pass them out to each office. It also means we have 2x the paper! + +This is fine if we have data that doesn’t update too frequently. + +### Even + +Using `even` distributes our data sets as described in the [What are Distribution Styles?](#what-are-distribution-styles) section (round-robin) to each node. The even distribution results in each node having data that they *may* or *may not* need for their assigned tasks. + +![Even-Joining.gif](/img/blog/2022-05-19-redshift-configurations-dbt-model-optimizations/Even-Joining.gif) + +In our scenario of office workers, that means that if our workers can’t find the data they need to complete their assignment in their own office they need to send a request for information to the other office to try to locate the data. This communication takes time! + +You can imagine how this would impact how long our query takes to complete. However, this distribution is usually a good starting point even with this impact because the workload to assemble data is shared in equal amounts and probably not too *skewed* - in other words, one worker isn’t sitting around with nothing to do while the other worker feverishly tries to work through stacks of information. + +### Key-based + +Our key-based distribution of `person_id` gave our nodes *assigned* data to work with. Here’s a refresher from the [What are Distribution Styles?](#what-are-distribution-styles) section: + +- Node 1 was distributed data associated with key values null, 1, 3, and 5. +- Node 2 was distributed data associated with key values 2, 4, and 6 + +![Key-Based-Joining.gif](/img/blog/2022-05-19-redshift-configurations-dbt-model-optimizations/Key-Based-Joining.gif) + +This means that when we join the two tables we distributed, the data is **co-located** on the same node and therefore our workers don’t need leave their offices to collect the data they need to complete their work. Cool, huh? + +## Where it breaks down 🚒 🔥 👩🏻‍🚒 + +You would think the most ideal distribution would be key-based. However, you can only assign **one key** to distribute by and that means if we have a query like this, we run into issues again: + +```python +select +from visitors +left join known_visitor_profiles + on visitors.person_id = known_visitor_profiles.person_id +left join unknown_visitor_profiles + on visitors.mask_id = anonymous_visitor_profiles.mask_id +``` + +How would you decide to distribute the `anonymous_visitor_profiles` data? + +![Key-Based-Joining-2.png](/img/blog/2022-05-19-redshift-configurations-dbt-model-optimizations/Key-Based-Joining-2.png) + +We have a few options: + +- **Distribute by `all`** +But if it’s a table that updates frequently, this may not be the best route. +![Key-Based-All.gif](/img/blog/2022-05-19-redshift-configurations-dbt-model-optimizations/Key-Based-All.gif) + + +- **Distribute by `even`** +But then our nodes need to communicate when `visitors` is joined to `anonymous_visitor_profiles`. + + If you decide to do something like this, you should consider what your *largest* datasets are first and distribute using appropriate keys to co-locate that data. Then, benchmark the run times with your additional tables distributed with all or even - the additional time may be something you can live with! +![Key-Based-Even.gif](/img/blog/2022-05-19-redshift-configurations-dbt-model-optimizations/Key-Based-Even.gif) + + +- **Distribute by key** +Distributing the `anonymous_visitor_profiles` with a key in this situation won’t really do anything, since you’re not co-locating any data! For example, we could change to distribute by `mask_id`, but then we’d have to distribute the `visitors` table by `mask_id` and then you’d end up in the same boat again with the `known_visitor_profiles` model! + +Thankfully with dbt, distributing isn’t our only option. + +## How to have your cake and eat it, too 🎂 + +Okay, so what if you want to have a key-based distribution, but you want to make those joins happen as well? + +This is where the power of dbt modeling really comes in! dbt allows you to break apart your queries into things that make sense. With each query, you can assign your distribution keys to each model, meaning you can have much more control. + +The following are some methods I’ve used in order to properly optimize run times, leveraging dbt’s ability to modularize models. + +:::note Note +I won’t get into our modeling methodology at dbt Labs in this article, but there are [plenty of resources](https://courses.getdbt.com/) to understand what might be happening in the following DAGs! +::: + +### Staggered joins + +![Staggered-Joins.png](/img/blog/2022-05-19-redshift-configurations-dbt-model-optimizations/Staggered-Joins.png) + +In this method, you piece out your joins based on the main table they’re joining to. For example, if you had five tables that were all joined using `person_id`, then you would stage your data (doing your clean up too, of course), distribute those by using `dist='person_id'`, and then marry them up in some table downstream. Now with that new table, you can choose the next distribution key you’ll need for the next process that will happen. In our example above, the next step is joining to the `anonymous_visitor_profiles` table which is distributed by `mask_id`, so the results of our join should also distribute by `mask_id`. + +### Resolve to a single key + +![Resolve-to-single-key](/img/blog/2022-05-19-redshift-configurations-dbt-model-optimizations/Resolve-to-single-key.png) + +This method takes some time to think about, and it may not make sense to do it depending on what you need. This is definitely balance between coherence, usability, and performance. + +The main point here is that you’re resolving the various keys and grains before the details are joined in. Because we’re not joining until the end, this means that only our intermediate tables get distributed based on the resolved keys and finally joined up in `dim_all_visitors`. + +Sometimes the work you’re doing downstream is much easier to do when you do some complex modeling up front! When you want or need it, you’ll know. + +# Sort keys + +Lastly, let’s talk about sort keys. No matter how we’ve **distributed** our data, we can define how data is sorted within our nodes. By setting a sort key, we’re telling Redshift to chunk our rows into blocks, which are then assigned a min and max value. Redshift can now use those min and max values to make an informed decision about which data it can skip scanning. + +Imagine that our office workers have no organization taking place with their documents - the papers are just added in the order they’re given. Now imagine that each worker needs to retrieve all paperwork associated to the person who wore a dog mask to the party. They would need to thumb through every drawer and every paper in their filing cabinets in order to pull out and assemble the information related to the dog-masked person. + +Let’s take a look at the information in our filing cabinet in both sorted and unsorted formats. Below is our `anonymous_visitor_profiles` table sorted by `mask_id`: + +![Sorting.gif](/img/blog/2022-05-19-redshift-configurations-dbt-model-optimizations/Sorting.gif) + +Once sorted, Redshift can keep track of what exists in blocks of information. This is equivalent to the information in our filing cabinet being organized into folders where items with mask ids starting with letters b through c are in located in one folder, mask ids starting with letters d through f are in another folder, and so on. Now our office worker can skip looking through the folder b-c and skip straight to d-f: + +![Scanning-Sort.gif](/img/blog/2022-05-19-redshift-configurations-dbt-model-optimizations/Scanning-Sort.gif) + +Even without setting an explicit distribution, this can help immensely with optimization. Here are some good places to apply it: + +- On any model you expect to be frequently filtered by range. +- Your ending models (often referred to as `marts`). Your stakeholders will be using these to slice and dice data. It’s best to sort based on how the data is most often filtered (This is most likely dates or datetimes!) +- On frequently joined keys. Redshift suggests you distribute **and** sort by these, as it allows Redshift to execute a sort merge join in which the sorting phase gets bypassed. + +# Parting thoughts + +Now that you know all about distribution, sorting, and how you can piece out your dbt models for better optimization, it should be much easier to make the decision on how to plan your optimization tactfully! + +I have some ending thoughts before you get into tweaking these configurations: + +### Let Redshift do its thing + +It’s nice to be able to sit back and watch how it performs without intervention! By allowing yourself the time to watch your models, you can be *much more* *targeted* with your optimization plans. + +### Document before tweaking + +If you’re about to tweak these configurations, make sure you document how long the model takes before the changes! If you have dev limits in place, you can still run a benchmark against the limit before and after the tweaks, although it *is* more ideal to work with larger amounts of data to really understand how it would affect processing once in production. I’ve been able to successfully test tweaks on limited data sets and it’s translated beautifully within production environments, but your milage may vary. + +### Test removing legacy `dist` styles and sort keys first + +If there are any sort keys or distribution styles already defined, remove those to see how your models do with the default. Having a bad sort key or distribution style can negatively impact your performance, which is why I suggest not configuring these on any net new modeling unless you’re sure about the impact. + +### Decide whether you you need to optimize at all! + +Identifying whether you need to change these configurations sometimes isn’t straightforward, especially when you have a lot going on in your model! Here’s some tips to help you out: + +- **Use the query optimizer** + If you have access to look at Redshift’s query optimizer in the Redshift console or have permissions to run an explain/explain analyze yourself, it can be helpful in drilling down to problematic areas. +- **Organize with CTEs** + You know we love CTEs - and in this instance they really help! I usually start troubleshooting a complex query by stepping through the CTEs of the problematic model. If the CTEs are executing logic in nicely rounded ways, it’s easy to find out which joins or statements are causing the issues. +- **Look for ways to clean up logic** + This can be things like too much logic used on a join key, a model handling too many transformations, or bad materialization assignments. + Sometimes all you need is a little code cleanup! +- **Step through joins one at a time** + If it's one join, it’s easy to understand which keys to optimize by. If there’s multiple joins, you might need to comment out joins in order to understand which present the most problems. It’s a good idea to benchmark each approach you take. + + Here’s an example workflow: + 1. Run the problematic model (I do this a couple of times to get a baseline average on runtime). Notate the build time. + 2. Comment out joins and one by one, run the model. Keep doing this until you find which join is causing unideal run times. + 3. Decide on how best to optimize the join: + - Optimize the logic or flow, such as moving the calculation on a key to a prior CTE or upstream model before the join. + - Optimizing the distribution, such as doing the join in an upstream model so you can facilitate co-location of the data. + - Optimizing the sort, such as identifying and assigning a frequently filtered column so that finding data is faster in downstream processing. + + + +Now you have a better understanding of how to leverage Redshift sort and distribution configurations in conjunction with dbt modeling to alleviate your modeling woes. + +If you have any more questions about Redshift and dbt, the #db-redshift channel in [dbt’s community Slack](https://www.getdbt.com/community/join-the-community/) is a great resource. + +Now get out there and optimize! 😊 diff --git a/website/blog/2022-05-24-joining-snapshot-complexity.md b/website/blog/2022-05-24-joining-snapshot-complexity.md new file mode 100644 index 00000000000..2d7065d76fc --- /dev/null +++ b/website/blog/2022-05-24-joining-snapshot-complexity.md @@ -0,0 +1,288 @@ +--- +title: "Tackling the complexity of joining snapshots" +description: "Tracking changes in your dataset over time by joining snapshots can be a complex proces. Learn how to tackle that complexity with Lauren Benezra" +slug: joining-snapshot-complexity + +authors: [lauren_benezra] + +tags: [analytics craft] +hide_table_of_contents: false + +date: 2022-05-26 +is_featured: true +--- + +Let’s set the scene. You are an [analytics engineer](https://www.getdbt.com/what-is-analytics-engineering/) at your company. You have several relational datasets flowing through your warehouse, and, of course, you can easily access and transform these tables through dbt. You’ve joined together the tables appropriately and have near-real time reporting on the relationships for each `entity_id` as it currently exists. + +But, at some point, your stakeholder wants to know how each entity is changing over time. Perhaps, it is important to understand the trend of a product throughout its lifetime. You need the history of each `entity_id` across all of your datasets, because each related table is updated on its own timeline. + +What is your first thought? Well, you’re a seasoned analytics engineer and you *know* the good people of dbt Labs have a solution for you. And then it hits you — the answer is [snapshots](https://docs.getdbt.com/docs/building-a-dbt-project/snapshots)! + + + +### What are snapshots and where do they get complex? + +Snapshots provide a picture of changes throughout history — a snapshot-in-time, if you will. When a value in a row of a raw table is updated, a new row is added to your snapshot-table, building a historical record of your data. + +Here’s an example of a dataset. + +| entity_id | important_status | updated_at | +| --- | --- | --- | +| 1 | available | 2021-11-15 16:00:0000 | +| 2 | not_available | 2021-11-15 15:30:0000 | + +When you apply a snapshot to this data, you’ll see the history of the data, and the `valid_from` and `valid_to` timestamps to capture when the row values were valid, and the values during those timespans. + +| entity_id | important_status | dbt_valid_from | dbt_valid_to | +| --- | --- | --- | --- | +| 1 | available | 2021-11-15 16:00:0000 | NULL | +| 1 | pending | 2021-11-10 08:00:000 | 2021-11-15 16:00:0000 | +| 1 | not_available | 2021-10-01 10:00:000 | 2021-11-10 08:00:000 | +| 2 | not_available | 2021-11-15 15:30:0000 | NULL | + +Snapshots are incredibly useful, but they do add a bit of complexity for joining tables downstream because you’ve added multiple rows of history per id. What happens when you have 10 snapshots that you want to join together, and you want to capture the history of all the datasets? + +Consider the complexity of the problem: you’ve successfully captured the history of all your tables using snapshots. You have `history_table_1` and `history_table_2`, and you want to join on a common key, `product_id`. However, we cannot just join on the primary key because each table has several rows of history for the same id, all valid across different timespans. + +`history_table_1`: + +| product_id | important_status | dbt_valid_from | dbt_valid_to | +| --- | --- | --- | --- | +| 1 | available | 2021-11-15 16:00:0000 | NULL | +| 1 | pending | 2021-11-10 08:00:000 | 2021-11-15 16:00:0000 | +| 1 | not_available | 2021-10-01 10:00:000 | 2021-11-10 08:00:000 | +| 2 | not_available | 2021-11-15 15:30:0000 | NULL | + +`history_table_2`: + +| product_id | order_id | product_order_id | order_status | dbt_valid_from | dbt_valid_to | +| --- | --- | --- | --- | --- | --- | +| 1 | A | 1A | available | 2021-11-15 16:00:0000 | NULL | +| 1 | A | 1A | pending | 2021-10-31 12:00:000 | 2021-11-15 16:00:0000 | +| 1 | B | 1B | available | 2021-11-15 15:30:0000 | NULL | +| 1 | B | 1B | pending | 2021-11-10 10:00:000 | 2021-11-15 15:30:0000 | +| 2 | C | 2C | available | 2021-11-10 15:00:0000 | NULL | + +This doesn’t look so bad. How complex can this get? Let’s take a look at the math. Say `historical_table_1` has _x_ historical rows per `product_id`, and _y_ ids total. That’s _x*y = n_ rows of data. `historical_table_2` has _z_ historical rows per `product_id`, and _w_ ids (_z*w = m_ rows). The subsequent join on `product_id` then [changes the complexity](https://www.freecodecamp.org/news/big-o-notation-why-it-matters-and-why-it-doesnt-1674cfa8a23c/) from _O(n)_ to _O(n\*m)_ very quickly (_x\*y\*z\*w_ possibilities!). The complexity continues to increase as we join together more and more historical tables. + +I know what you’re thinking — what a mess! Can’t we just join everything together, and snapshot the resulting table? This is not a bad thought. It would save you the trouble of thinking through a problem with _O(n\*m\*a\*b\*c\*d\*...\*q)_ complexity. And in some cases, this may capture all the history you need! + +However, it does not provide a solution to the problem initially posed. The historical records track when each table is valid, rather than when the joined table is valid, and this history for each dataset will only be reflected when you snapshot each table, and then join them, rather than joining and subsequently snapshotting the table. The `valid_from` and `valid_to` built into the joined-then-snapshotted table will only be built from `updated_at` timestamps where the joined table is updated, and thus changes in the underlying data may not be captured. We want to understand when the records are truly valid across all tables, meaning we need to take into account the valid timestamps from each individual dataset. + +Okay so we’ve ruled out the easy way to solve this question. So let’s tackle that _O(n\*m\*a\*b\*c\*d\*...\*q)_ problem! We can do it. + +### The action plan for our solution + +Ultimately, our goal is to capture the history for the `product_id` and join the rows that are valid at the same time. As a result, we can get a view of our data at a given point in time that accurately represents the valid state of any given date. + +For `historical_table_1` and `historical_table_2`, we will join on `product_id` where `historical_table_1.valid_from` to `historical_table_1.valid_to` has overlapping time with `historical_table_2.valid_from` to `historical_table_2.valid_to`. + +This boils down to the following steps: + +1. Get rid of dupes if needed +2. Snapshot your data tables +3. Future-proof your `valid_to` dates +4. Join all your tables to build a fanned out spine containing the grain ids onto which we will join the rest of the data +5. Join the snapshots to the data spine on the appropriate id in overlapping timespans, narrowing the valid timespans per row as more tables are joined +6. Clean up your columns in final +7. Optional addition of global variable to filter to current values only + +So let’s dive in! Head first! Step 1 is outlined in this blog post: [How to deduplicate partial duplicates](https://docs.getdbt.com/blog/how-we-remove-partial-duplicates). It only needs to be implemented if you are dealing with dupes in your data. If you don’t have duplicates in your data (wow! send me the number of your Data Engineer *ASAP*), you can skip this step. + +![backtothefuture.gif](/img/blog/2022-05-24-joining-snapshot-complexity/backtothefuture.gif) + +## Step 1: Ensure your data tables are duplicate free + +:::important What happens in this step? +Step 1 walks you through how to build a surrogate key from column values using a macro, and then removing said duplicates from your data. No duplicates? Skip to Step 2. +::: + +Why is this step important? Because you’ll be joining so many rows on the same id, and the valid timestamps for each row will determine the exact place to join one table to another. We cannot do this accurately with duplicates! (But also, you should be checking for dupes anyway because we are analytics engineers, right?) + +![clean-data-meme.png](/img/blog/2022-05-24-joining-snapshot-complexity/clean-data-meme.png) + +See [this blog post for deduping partial duplicates](https://docs.getdbt.com/blog/how-we-remove-partial-duplicates)! + +## Step 2: Snapshot your data + +:::important What happens in this step? +Step 2 walks you through how to snapshot your data. The example provided assumes you went through Step 1, but if you skipped that step, just snapshot your data based on the links provided below. +::: + +Do you know how to snapshot data? It is a simple Jinja block with some configs specified. There are so many explanations of how to implement these, so I’m not going to bore you. But you know I’ll throw you some links. [Boom.](https://blog.getdbt.com/track-data-changes-with-dbt-snapshots/) [And foobar!](https://docs.getdbt.com/docs/building-a-dbt-project/snapshots) + +You can snapshot by checking your `change_id` if you’ve implemented the removing-dupes logic from Step 1, or using the timestamp strategy, if you have a reliable timestamp. + +```sql +{% snapshot snp_product %} +{{ + config( + target_schema=generate_schema_name('snapshots'), + unique_key='assetid', + strategy='check', + check_cols=['change_id'] + ) +}} +select * from {{ ref('base_product') }} +{% endsnapshot %} +``` + +## Step 3: Future-proof your timestamps + +:::important What happens in this step? +Step 3 walks you through how to replace your snapshot `valid_to = NULL` value with a future-proof date to ensure smooth sailing through the snapshot joins. +::: + +Now that you’ve deduped and you’ve snapped, you need to future-proof! This is a step you cannot skip, because the joins we will do in the next steps will rely on `valid_to` to contain a date, rather than a `NULL`. + +:::note Note +This is a great place to set a global variable! You can define your future-proof variable in the dbt_project.yml file. +::: + +```jsx +vars: + future_proof_date: '9999-12-31' +``` + +And coalesce! + +```sql +coalesce(dbt_valid_to, cast('{{ var("future_proof_date") }}' as timestamp)) as valid_to +``` + +You will thank yourself later for building in a global variable. Adding important global variables will set your future-self up for success. Now, you can filter all your data to the current state by just filtering on `where valid_to = future_proof_date`*.* You can also ensure that all the data-bears with their data-paws in the data-honey jar are referencing the **same** `future_proof_date`, rather than `9998-12-31`, or `9999-12-31`, or `10000-01-01`, which will inevitably break something eventually. You know it will; don’t argue with me! Global vars for the win! + +## Step 4: Join all your tables together to build a fanned out id spine + +:::important What happens in this step? +Step 4 walks you through how to do your first join, in which you need to fan out the data spine to the finest grain possible and to include all the id onto which we will join the rest of the data. This step is crucial to joining the snapshots in subsequent steps. +::: + +Let’s look at how we’d do this with an example. You may have many events associated with a single `product_id`. Each `product_id` may have several `order_ids`, and each `order_id` may have another id associated with it. Which means that the grain of each table needs to be identified. The point here is that we need to build in an id at the finest grain. To do so, we’ll add in a [dbt_utils.surrogate_key](https://github.com/dbt-labs/dbt-utils/blob/main/macros/sql/surrogate_key.sql) in the staging models that live on top of the snapshot tables. + +Then, in your joining model, let’s add a CTE to build out our spine with all of our ids. + +```sql +build_spine as ( + historical_table_1.*, + historical_table_2.product_order_id, + historical_table_3.other_entity_grain_id, + ... +from historical_table_1 +left join + historical_table_2 + on historical_table_1.product_id = historical_table_2.product_id +left join + historical_table_3 + on historical_table_1.product_id = historical_table_3.product_id +... ) +``` + +The result will be all the columns from your first table, fanned out as much as possible by the added id columns. We will use these id columns to join the historical data from our tables. + +| product_id | important_status | dbt_valid_from | dbt_valid_to | product_order_id | +| --- | --- | --- | --- | --- | +| 1 | available | 2021-11-15 16:00:0000 | NULL | 1A | +| 1 | pending | 2021-11-10 08:00:000 | 2021-11-15 16:00:0000 | 1A | +| 1 | not_available | 2021-10-01 10:00:000 | 2021-11-10 08:00:000 | 1A | +| 1 | available | 2021-11-15 16:00:0000 | NULL | 1B | +| 1 | pending | 2021-11-10 08:00:000 | 2021-11-15 16:00:0000 | 1B | +| 1 | not_available | 2021-10-01 10:00:000 | 2021-11-10 08:00:000 | 1B | +| 2 | not_available | 2021-11-15 15:30:0000 | NULL | 2C | + +## Step 5: Join your snapshots onto id spine + +:::important What happens in this step? +Step 5 walks you through the logic of the snapshot join, and the macro that will make the joins simpler. +::: + +Now, I’m going to recommend you build individual CTEs with one join at a time. Why do we build a CTE with a single join, rather than all the joins in one? So many reasons, but there are two big ones. + +- **First**, this is complicated. You will need to troubleshoot, and the easiest way to enable troubleshooting is to separate your join logic in individual CTEs. By building your code this way, you can easily throw a `select * from last_cte` to check that your logic is doing what you think it should be doing before adding more complex joins. +- **Second**, you are using the `valid_from` and `valid_to` values of each newly joined table to determine the new `valid_from` and `valid_to` timestamps for the resulting table – where both rows are valid within the same timespans. While you could accomplish this in one big massive join, it will become very complex and difficult to troubleshoot when you run into funky results. + +### DRY — it’s macro time! + +This macro finishes your join CTE, which allows you to add columns from the new table you’re joining before calling the macro. It also assumes you’ve replaced your `valid_to = NULL` with an actual date type with an actual date that indicates a row is currently valid. + +Your parameters are `cte_join`, the table that is creating the spine of your final model, `cte_join_on`, which is the new table you’re joining onto the spine. The `valid_to` and `valid_from` values for both of these tables, and the ids onto which you are joining (named twice in case they have different column names, but in most instances these two parameters will be the same name). + +```sql +-- requires any extra columns from table_join_on to be listed prior to using this macro. +-- assumes we have replaced instances of valid_to = null with a future_proof_date = '9999-12-31'. + +{% macro join_snapshots(cte_join, cte_join_on, cte_join_valid_to, + cte_join_valid_from, cte_join_on_valid_to, cte_join_on_valid_from, + cte_join_id, cte_join_on_id) %} + + + {{cte_join}}.*, + greatest({{cte_join}}.{{cte_join_valid_from}}, + coalesce( {{cte_join_on}}.{{cte_join_on_valid_from}}, {{cte_join}}.{{cte_join_valid_from}})) + as add_{{cte_join_on}}_valid_from, + least({{cte_join}}.{{cte_join_valid_to}}, + coalesce({{cte_join_on}}.{{cte_join_on_valid_to}}, {{cte_join}}.{{cte_join_valid_to}})) as add_{{cte_join_on}}_valid_to + + from {{cte_join}} + left join {{cte_join_on}} on {{cte_join}}.{{cte_join_id}} = {{cte_join_on}}.{{cte_join_on_id}} + and (({{cte_join_on}}.{{cte_join_on_valid_from}} >= {{cte_join}}.{{cte_join_valid_from}} + and {{cte_join_on}}.{{cte_join_on_valid_from}} < {{cte_join}}.{{cte_join_valid_to}}) + or ({{cte_join_on}}.{{cte_join_on_valid_to}} >= {{cte_join}}.{{cte_join_valid_from}} + and {{cte_join_on}}.{{cte_join_on_valid_to}} < {{cte_join}}.{{cte_join_valid_to}})) + + +{% endmacro %} +``` + +The joining logic finds where the ids match and where the timestamps overlap between the two tables. We use the **greatest** `valid_from` and the **least** `valid_to` between the two tables to ensure that the new, narrowed timespan for the row is when the rows from both tables are valid. + +You should see something like this as your end result: + +| product_id | product_order_id | order_id | important_status | order_status | greatest_valid_from | least_valid_to | +| --- | --- | --- | --- | --- | --- | --- | +| 1 | 1A | A | available | available | 2021-11-15 16:00:0000 | 9999-12-31 | +| 1 | 1A | A | pending | pending | 2021-11-10 08:00:000 | 2021-11-15 16:00:0000 | +| 1 | 1A | A | not_available | pending | 2021-10-31 10:00:000 | 2021-11-10 08:00:000 | +| 1 | 1B | B | available | available | 2021-11-15 16:00:0000 | 9999-12-31 | +| 1 | 1B | B | pending | pending | 2021-11-10 08:00:000 | 2021-11-15 16:00:0000 | +| 1 | 1B | B | not_available | pending | 2021-10-01 10:00:000 | 2021-11-10 08:00:000 | +| 2 | 2C | C | not_available | available | 2021-11-15 15:30:0000 | 9999-12-31 | + +### Continue joining on your tables, and narrowing your valid timespans. + +Using the produced valid timestamps from the previous join as your new spine timestamps, continue joining the rest of your snapshots in this manner. + +## Step 6: Clean up your final table with a CTE (duh!) + +:::important What happens in this step? +Step 6 is to finish your code with a final, cleaned up CTE. +::: + +Your final CTE of your table should list only the columns that you want to keep. Clean up all the timestamp columns, and rename the narrowed `valid_from` and `valid_to` from your final join to the appropriate name. + +## Step 7: Optional -- add global variable for building historical vs current + +:::important What happens in this step? +Step 7 walks you through the option of building in a global variable to run only the most current data. +::: + +It could be useful to add a current records only variable to run your project. This is a fast way to skip the historical data, without having to build out new models, or filter on your historical table. You can have a separate job set up to target a new schema, and build tables with current data only, that are ready for the present-day reports. You’ll know this is right for your project if you a BI tool that doesn’t love to filter on big, history-filled tables (like Tableau), but would prefer to have easily accessible, ready to run tables. To build in this feature, add a global variable in the *dbt_project.yml,* so your `future_proof_date` has a friend: + +```jsx +future_proof_date: '9999-12-31' +current_records_only: true +``` + +And add a Jinja-if to your staging models, so that you’re asking your project to only build the data that is current, without having to override your snapshots: + +```sql +{% if var("current_records_only") %} + +where valid_to = cast('{{ var("future_proof_date") }}' as timestamp) + +{% endif %} +``` + +## Parting thoughts + +Friend, you're an absolute star. You’ve determined that you need to join several snapshots when each entity is in a valid state, which comes with a fair amount of complexity! With this logic we’ve broken down the problem into a few steps: getting rid of duplicates, snapshotting your data, replacing your currently-valid rows with a future-proof date, building your first join to complete the fanned out data spine, joining onto your data spine across valid timestamps, and then repeating this logic using a macro. After you join your first historical data to your data spine, be sure to check the results. One weird line of code can cause a mess of problems with all this complexity, so always check results along the way. Well done, be well, you’re doing a great job! diff --git a/website/blog/2022-06-30-coalesce-sql.md b/website/blog/2022-06-30-coalesce-sql.md new file mode 100644 index 00000000000..dc85daf8a53 --- /dev/null +++ b/website/blog/2022-06-30-coalesce-sql.md @@ -0,0 +1,84 @@ +--- +title: "COALESCE SQL function: Why we love it" +description: "The COALESCE SQL function is an incredibly useful function that allows you to fill in unhelpful blank values that may show up in your data." +slug: coalesce-sql-love-letter + +authors: [kira_furuichi] + +tags: [SQL Magic] +hide_table_of_contents: false + +date: 2022-05-08 +is_featured: false +--- + +It’s inevitable in the field of analytics engineering: you’re going to encounter moments when there’s mysterious or unhelpful blank values in your data. Null values surely have their time and place, but when you need those null values filled with more meaningful data, COALESCE comes to the rescue. + +COALESCE is an incredibly useful function that allows you to fill in unhelpful blank values that may show up in your data. In the words of analytics engineer [Lauren Benezra](https://docs.getdbt.com/author/lauren_benezra), you will probably almost never see a data model that doesn’t use COALESCE somewhere. + + + +> **What is a SQL Function?** +> At a high level, a function takes an input (or multiple inputs) and returns a manipulation of those inputs. Some common SQL functions are [EXTRACT](https://docs.getdbt.com/blog/extract-sql-love-letter/), [LOWER](https://docs.getdbt.com/blog/lower-sql-love-letter/), and [DATEDIFF](https://docs.getdbt.com/blog/datediff-sql-love-letter/). For example, the LOWER function takes a string value and returns an all lower-case version of that input string. + +## How to use the COALESCE function + +In formal terms, using the COALESCE function on a series of values will return the first non-null value.  + +The general syntax for using the COALESCE function looks like the following: + +```sql +coalesce(, ,...) +``` + +You can have as many input values/columns to the COALESCE function as you like, but remember: order is important here since the first non-null value is the one that is returned. In practice, you’ll likely only ever use the COALESCE function with two inputs: a column and the value you want to fill null values of that column with. + +> **See it in action:** +> The COALESCE function is used in the [surrogate_key](https://docs.getdbt.com/blog/sql-surrogate-keys) macro to replace null column values. + +### Data warehouse support for the COALESCE function + +Most, if not all, modern data warehouses support the COALESCE function; [Google BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/conditional_expressions#coalesce), [Amazon Redshift](https://docs.aws.amazon.com/redshift/latest/dg/r_COALESCE.html), [Snowflake](https://docs.snowflake.com/en/sql-reference/functions/coalesce.html), [Postgres](https://www.postgresqltutorial.com/postgresql-tutorial/postgresql-coalesce/), and [Databricks](https://docs.databricks.com/sql/language-manual/functions/coalesce.html) all support the COALESCE function. In addition, the syntax to use COALESCE is the same across all of them. + +## COALESCE SQL function example + +Let’s look at an actual example using COALESCE. Below, we have an `orders` with three column values: an `order_id`, `order_date`, and `order_status`. + +| **order_id** | **order_date** | **order_status** | +| ------------ | -------------- | ---------------- | +| 12389 | 2022-01-02 | | +| 34553 | 2020-04-23 | returned | +| 78411 | 2022-06-06 | | + +If you do a little exploration on this table, you would see that there are only two unique values for `order_status`: NULL and `returned`. As we said before, null values have their time and place, but if you first look at this table, the null value for an order could mean many things–has the order been processed? Was the order successful? + +In this `orders` table, you can assume here that any NULL `order_status` value means that the order was not returned. To make this more clear to anyone who looks at this table, you can utilize a COALESCE function to return a newer, more readable `order_status`. + +```sql +select + order_id, + order_date, + coalesce(order_status, 'not_returned') as order_status +from {{ ref('orders') }} +``` + +Running this query would return the following: + +| **order_id** | **order_date** | **order_status** | +| ------------ | -------------- | ---------------- | +| 12389 | 2022-01-02 | not_returned | +| 34553 | 2020-04-23 | returned | +| 78411 | 2022-06-06 | not_returned | + +Now, there are no null values in the `order_status` column since any null value was replaced by a `not_returned` string. Order 34553’s `order_status` remained unchanged because its original `order_status` was the first non-null value passed in the COALESCE function. By providing more context into what these null values mean, anyone who looks at this table can quickly understand the order status for a specific order. + +> **To replace or not to replace:** +> COALESCE has a straightforward use case—fill missing values with values you specify—but you also want to ensure you’re not changing non-empty values when using it. This is where the order of the input values to the COALESCE function are important: from left to right, the first non-null value is the one that’s returned. + +## Why we love it + +We checked our data team’s dbt project, and we used the COALESCE function over 100 times. We like the COALESCE function so much we named the [annual data conference on analytics engineering](https://coalesce.getdbt.com/) after it. + +At its core, the COALESCE function is an efficient way to fill in missing column values with values you specify. You can additionally use COALESCE across most, if not all, modern data warehouses and there’s [no tricky cross-database syntax like there is for DATEADD](https://docs.getdbt.com/blog/sql-dateadd). + +Thank you COALESCE for always finding our moments of emptiness, and filling them with valuable stuff. diff --git a/website/blog/2022-06-30-extract-sql-function.md b/website/blog/2022-06-30-extract-sql-function.md new file mode 100644 index 00000000000..b81a7254a76 --- /dev/null +++ b/website/blog/2022-06-30-extract-sql-function.md @@ -0,0 +1,85 @@ +--- +title: "EXTRACT SQL function: Why we love it" +description: "In this post, we’re going to give a deep-dive into the EXTRACT function, how it works, and why we use it. The EXTRACT function allows you to extract a specified date part from a date/time. " +slug: extract-sql-love-letter + +authors: [kira_furuichi] + +tags: [SQL Magic] +hide_table_of_contents: false + +date: 2022-05-15 +is_featured: false +--- +There are so many different date functions in SQL—you have [DATEDIFF](https://docs.getdbt.com/blog/datediff-sql-love-letter/), [DATEADD](https://docs.getdbt.com/blog/sql-dateadd), DATE_PART, and [DATE_TRUNC](https://docs.getdbt.com/date-trunc-sql) to name a few. They all have their different use cases and understanding how and when they should be used is a SQL fundamental to get down. Are any of those as easy to use as the EXTRACT function? Well, that debate is for another time… + +In this post, we’re going to give a deep dive into the EXTRACT function, how it works, and why we use it. + + + +The EXTRACT function allows you to extract a specified date part from a date/time. For example, if you were to extract the month from the date February 14, 2022, it would return 2 since February is the second month in the year. + +> **What is a SQL function?** +> At a high level, a function takes an input (or multiple inputs) and returns a manipulation of those inputs. Some common SQL functions are [COALESCE](https://docs.getdbt.com/blog/coalesce-sql-love-letter/), [LOWER](https://docs.getdbt.com/blog/lower-sql-love-letter/) and [DATEDIFF](https://docs.getdbt.com/blog/datediff-sql-love-letter/). For example, the COALESCE function takes a group of values and returns the first non-null value from that group. + +## How to use the EXTRACT function + +One of our favorite things about the EXTRACT function is how readable it is. Sometimes you may encounter SQL functions and not immediately understand what the arguments are and what the expected output should be. (We’re looking at you, SPLIT_PART.) The EXTRACT function isn’t like that. + +To use the EXTRACT function, you’ll simply specify the date part you want extracted out and the field you want to extract from. You can extract many different date parts, but you’ll most commonly see year, month, week of year, or quarter extracted from a date. + +```yaml +extract( from ) +``` + +Depending on the data warehouse you use, the value returned from an EXTRACT function is often a numeric value or the same date type as the input ``. Read the [documentation for your data warehouse](#data-warehouse-support-for-extract-function) to better understand EXTRACT outputs. + +> **Note:** +> You may additionally see a comma used in place of the ‘from’ in the EXTRACT function, like `extract(, )`. We feel that using that ‘from’ in the function makes it a little more readable. + +### The DATE_PART function + +You may also see the DATE_PART function used in place of the EXTRACT function. Both DATE_PART and EXTRACT perform the same functionality, it’s just a matter of preference on which one you want to use. + +> **Postgres & DATE_PART:** +> This is overly pedantic and you’ll likely never encounter an issue with DATE_PART and EXTRACT evaluating to differences in values that truly matter, but it’s worth noting. Postgres’ DATE_PART and EXTRACT functions would previously evaluate to the same output. However, with Postgres 14, the [EXTRACT function now returns a numeric type instead of an 8-byte float.](https://stackoverflow.com/questions/38442340/difference-between-extractyear-from-timestamp-function-and-date-partyear-t) + +### Data warehouse support for the EXTRACT function + +[Google BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/datetime_functions#extract), [Amazon Redshift](https://docs.aws.amazon.com/redshift/latest/dg/r_EXTRACT_function.html), [Snowflake](https://docs.snowflake.com/en/sql-reference/functions/extract.html), [Postgres](https://www.postgresqltutorial.com/postgresql-date-functions/postgresql-extract/), and [Databricks](https://docs.databricks.com/sql/language-manual/functions/extract.html) all support the EXTRACT function. In addition, the syntax to use EXTRACT is the same across all of them. + +## EXTRACT function example + +Let’s take this to an actual example! We’re going to use the [jaffle shop](https://github.com/dbt-labs/jaffle_shop/blob/main/models/orders.sql), a simple dataset and dbt project, to help us. The jaffle shop’s `orders` has some fields around an order’s status, order date, and order amount. + +You can extract different time-based values (weeks, months, years, etc.) from the `order_date` in  the `orders` model using the following code: + +```sql +select + order_id, + order_date, + extract(week from order_date) as order_week, + extract(month from order_date) as order_month, + extract(year from order_date) as order_year +from {{ ref('orders') }} +``` + +After running this query, your results would look a little something like this: + +| **order_id** | **order_date** | **order_week** | **order_month** | **order_year** | +| ------------ | -------------- | -------------- | --------------- | -------------- | +| 1 | 2018-01-01 | 1 | 1 | 2018 | +| 9 | 2018-01-12 | 2 | 1 | 2018 | +| 72 | 2018-03-23 | 12 | 3 | 2018 | + +As you can see, this query extracted the week of year, month of year, and year from the `order_date`. + +## Why we love it + +We’re going to be honest: EXTRACT isn’t the most widely used SQL function in our dbt project. However, EXTRACT has its time and place:  + +* Fiscal calendars: If your business uses fiscal years, or calendars that differ from the normal 12-month cycle, EXTRACT functions can help create alignment between fiscal calendars and normal calendars +* Ad hoc analysis: EXTRACT functions are useful in ad hoc analyses and queries when you need to look at values grouped by date periods or for period comparisons + +Extract is a consistent, helpful, and straightforward function–what more could we ask for from a ~~friend~~ function? + diff --git a/website/blog/2022-06-30-lower-sql-function.md b/website/blog/2022-06-30-lower-sql-function.md new file mode 100644 index 00000000000..353b11376b0 --- /dev/null +++ b/website/blog/2022-06-30-lower-sql-function.md @@ -0,0 +1,83 @@ +--- +title: "LOWER SQL function: Why we love it" +description: "The LOWER SQL Function allows you to return a string value as an all lowercase string. It’s an effective way to create consistent capitalization for string values across your data." +slug: lower-sql-love-letter + +authors: [kira_furuichi] + +tags: [SQL Magic] +hide_table_of_contents: false + +date: 2022-05-11 +is_featured: false +--- + +We’ve all been there: + +* In a user signup form, user A typed in their name as `Kira Furuichi`, user B typed it in as `john blust`, and user C wrote `DAvid KrevitT` (what’s up with that, David??) +* Your backend application engineers are adamant customer emails are in all caps +* All of your event tracking names are lowercase + +In the real world of human imperfection, opinions, and error, string values are likely to take inconsistent capitalization across different data sources (or even within the same data source). There’s always a little lack of rhyme or reason for why some values are passed as upper or lowercase, and it’s not worth the headache to unpack that. + +So how do you create uniformity for string values that you collect across all your data sources? The LOWER function! + + + +Using the LOWER function on a string value will return the input as an all lowercase string. It’s an effective way to create consistent capitalization for string values across your data. + +> **What is a SQL function?** +> At a high level, a function takes an input (or multiple inputs) and returns a manipulation of those inputs. Some common SQL functions are [COALESCE](https://docs.getdbt.com/blog/coalesce-sql-love-letter/), [EXTRACT](https://docs.getdbt.com/blog/extract-sql-love-letter), and [DATEDIFF](https://docs.getdbt.com/blog/datediff-sql-love-letter/). For example, the COALESCE function takes a group of values and returns the first non-null value from that group. + +## How to use the LOWER function + +The syntax for using the LOWER function looks like the following: + +```sql +lower('') +``` + +Executing this command in a SELECT statement will return the lowercase version of the input string. You may additionally use the LOWER function in WHERE clauses and joins. + +### Data warehouse support for the LOWER function + +[Google BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/string_functions#lower), [Amazon Redshift](https://docs.aws.amazon.com/redshift/latest/dg/r_LOWER.html), [Snowflake](https://docs.snowflake.com/en/sql-reference/functions/lower.html), [Postgres](https://www.postgresqltutorial.com/postgresql-string-functions/postgresql-letter-case-functions/), and [Databricks](https://docs.databricks.com/sql/language-manual/functions/lower.html) all support the LOWER function. In addition, the syntax to use LOWER is the same across all of them. + +## LOWER SQL function example + +Let’s take this to an actual example! Below, you’ll see the first three rows from the `customers` in the [jaffle_shop](https://github.com/dbt-labs/jaffle_shop), a simple dataset and dbt project, that has three columns: `customer_id`, `first_name`, and `last_name`. + +| **customer_id** | **first_name** | **last_name** | +| --------------- | -------------- | ------------- | +| 1 | Michael | P. | +| 2 | Shawn | M. | +| 3 | Kathleen | P. | + +You can lower the first name and last name of the `customers` model using the following code: + +```sql +select + customer_id, + lower(first_name) as first_name, + lower(last_name) as last_name +from {{ ref('customers') }} +``` + +After running this query, the `customers` table will look a little something like this: + +| **customer_id** | **first_name** | **last_name** | +| --------------- | -------------- | ------------- | +| 1 | michael | p. | +| 2 | shawn | m. | +| 3 | kathleen | p. | + +Now, all characters in the `first_name` and `last_name` columns are lowercase. + +> **Where do you lower?** +> Changing all string columns to lowercase to create uniformity across data sources typically happens in our dbt project’s [staging models](https://docs.getdbt.com/guides/best-practices/how-we-structure/2-staging). There are a few reasons for that: data cleanup and standardization, such as aliasing, casting, and lowercasing, should ideally happen in staging models to create downstream uniformity. It’s also more performant in downstream models that join on string values to join on strings that are of all the same casing versus having to join and perform lowercasing at the same time. + +## Why we love it + +Let’s go back to our chaotic trio of users A, B, and C who all used different capitalizations to type in their names. If you don’t create consistent capitalization for string values, how would a business user know what to exactly filter for in their BI tool? A business user could filter a name field on “John Blust” since that’s what they would expect it to look like, only to get zero results back. By creating a consistent capitalization format (upper or lowercase) for all string values in your data models, you, therefore, create some expectations for business users in your BI tool. + +There will most likely never be 100% consistency in your data models, but doing all that you can to mitigate that chaos will make your life and the life of your business users hopefully a little easier. Use the LOWER function to create a consistent casing for all strings in your data sources. diff --git a/website/blog/2022-07-05-date-trunc-sql-love-letter.md b/website/blog/2022-07-05-date-trunc-sql-love-letter.md new file mode 100644 index 00000000000..99f658590a6 --- /dev/null +++ b/website/blog/2022-07-05-date-trunc-sql-love-letter.md @@ -0,0 +1,100 @@ +--- +title: "DATE_TRUNC SQL function: Why we love it" +description: "The DATE_TRUNC function will truncate a date or time to the first instance for a given date part maintaining a date format. Wordy, wordy, wordy! What does this really mean?" +slug: date-trunc-sql + +authors: [kira_furuichi] + +tags: [sql magic] +hide_table_of_contents: true + +date: 2022-07-13 +is_featured: false +--- +In general, data people prefer the more granular over the less granular. [Timestamps > dates](https://docs.getdbt.com/blog/when-backend-devs-spark-joy#signs-the-data-is-sparking-joy), daily data > weekly data, etc.; having data at a more granular level always allows you to zoom in. However, you’re likely looking at your data at a somewhat zoomed-out level—weekly, monthly, or even yearly. To do that, you’re going to need a handy dandy function that helps you round out date or time fields. + +The DATE_TRUNC function will truncate a date or time to the first instance of a given date part. Wordy, wordy, wordy! What does this really mean? If you were to truncate `2021-12-13` out to its month, it would return `2021-12-01` (the first day of the month). + +Using the DATE_TRUNC function, you can truncate to the weeks, months, years, or other date parts for a date or time field. This can make date/time fields easier to read, as well as help perform cleaner time-based analyses. + + + +> **What is a SQL function?** +> At a high level, a function takes an input (or multiple inputs) and returns a manipulation of those inputs. Some common SQL functions are [COALESCE](https://getdbt.com/sql-foundations/coalesce-sql-love-letter/), [LOWER](https://getdbt.com/sql-foundations/lower-sql-love-letter/), and [EXTRACT](https://getdbt.com/sql-foundations/extract-sql-love-letter/). For example, the COALESCE function takes a group of values and returns the first non-null value from that group. + +Overall, it’s a great function to use to help you aggregate your data into specific date parts while keeping a date format. However, the DATE_TRUNC function isn’t your swiss army knife–it’s not able to do magic or solve all of your problems (we’re looking at you [star](https://getdbt.com/sql-foundations/star-sql-love-letter/)). Instead, DATE_TRUNC is your standard kitchen knife—it’s simple and efficient, and you almost never start cooking (data modeling) without it. + +## How to use the DATE_TRUNC function + +For the DATE_TRUNC function, there are two arguments you must pass in: + +* The date part: This is the days/months/weeks/years (level) you want your field to be truncated out to +* The date/time you want to be truncated + +The DATE_TRUNC function can be used in SELECT statements and WHERE clauses. + +Most, if not all, modern cloud data warehouses support some type of the DATE_TRUNC function. There may be some minor differences between the argument order for DATE_TRUNC across data warehouses, but the functionality very much remains the same. + +Below, we’ll outline some of the slight differences in the implementation between some of the data warehouses. + +### The DATE_TRUNC function in Snowflake and Databricks + +In [Snowflake](https://docs.snowflake.com/en/sql-reference/functions/date_trunc.html) and [Databricks](https://docs.databricks.com/sql/language-manual/functions/date_trunc.html), you can use the DATE_TRUNC function using the following syntax: + +```sql +date_trunc(, ) +``` + +In these platforms, the `` is passed in as the first argument in the DATE_TRUNC function. + +### The DATE_TRUNC function in Google BigQuery and Amazon Redshift + +In [Google BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/date_functions#date_trunc) and [Amazon Redshift](https://docs.aws.amazon.com/redshift/latest/dg/r_DATE_TRUNC.html), the `` is passed in as the first argument and the `` is the second argument. + +```sql +date_trunc(, ) +``` + +> **A note on BigQuery:** +> BigQuery’s DATE_TRUNC function supports the truncation of date types, whereas Snowflake, Redshift, and Databricks’ can be a date or timestamp data type. BigQuery also supports DATETIME_TRUNC and TIMESTAMP_TRUNC functions to support truncation of more granular date/time types. + +## A dbt macro to remember + +Why Snowflake, Amazon Redshift, Databricks, and Google BigQuery decided to use different implementations of essentially the same function is beyond us and it’s not worth the headache trying to figure that out. Instead of remembering if the`` or the `` comes first, (which, let’s be honest, we can literally never remember) you can rely on a dbt Core macro to help you get away from finicky syntax. + +With dbt v1.2, [adapters](https://docs.getdbt.com/docs/supported-data-platforms) now support [cross-database macros](https://docs.getdbt.com/reference/dbt-jinja-functions/cross-database-macros) to help you write certain functions, like [DATE_TRUNC](https://docs.getdbt.com/reference/dbt-jinja-functions/cross-database-macros#date_trunc) and [DATEDIFF](https://docs.getdbt.com/reference/dbt-jinja-functions/cross-database-macros#datediff), without having to memorize sticky function syntax. + +> **Note:** +> Previously, [dbt_utils](https://github.com/dbt-labs/dbt-utils), a package of macros and tests that data folks can use to help write more DRY code in their dbt project, powered cross-database macros. Now, cross-database macros are available **regardless if dbt utils is installed or not.** + +Using the [jaffle shop](https://github.com/dbt-labs/jaffle_shop/blob/main/models/orders.sql), a simple dataset and dbt project, you can truncate the `order_date` from the `orders` table using the dbt [DATE_TRUNC macro](https://docs.getdbt.com/reference/dbt-jinja-functions/cross-database-macros#date_trunc): + +```sql +select + order_id, + order_date, + {{ date_trunc("week", "order_date") }} as order_week, + {{ date_trunc("month", "order_date") }} as order_month, + {{ date_trunc("year", "order_date") }} as order_year +from {{ ref('orders') }} +``` + +Running the above would product the following sample results: + +| order_id | order_date | order_week | order_month | order_year | +|:---:|:---:|:---:|:---:|:---:| +| 1 | 2018-01-01 | 2018-01-01 | 2018-01-01 | 2018-01-01 | +| 70 | 2018-03-12 | 2018-03-12 | 2018-03-01 | 2018-01-01 | +| 91 | 2018-03-31 | 2018-03-26 | 2018-03-01 | 2018-01-01 | + +The `order_week`, `order_month`, and `order_year` fields are the truncated values from the `order_date` field. + +**A mild word of warning:** If you’re using the DATE_TRUNC function to modify fields or create new ones, it’s important that you use strong naming conventions for these fields. Since the output from the DATE_TRUNC function looks like a normal date, other data folks or business users may not understand that it’s an altered field and may mistake it for the actual date something happened. + +## Why we love it + +The DATE_TRUNC function is a great way to do data analysis and data modeling that needs to happen at a zoomed-out date part. It’s often used for time-based work, such as customer retention modeling or analysis. The DATE_TRUNC function also allows you to keep the date format of a field which allows for the most ease and compatibility in most BI (business intelligence) tools. + +TL;DR – DATE_TRUNC is a handy, widely-used SQL function—and dbt has made it even simpler to start using! + +*This post is a part of the SQL love letters—a series on the SQL functions the dbt Labs data team members use and love. You can find [the entire collection here](https://getdbt.com/sql-foundations/top-sql-functions).* diff --git a/website/blog/2022-07-05-datediff-sql-love-letter.md b/website/blog/2022-07-05-datediff-sql-love-letter.md new file mode 100644 index 00000000000..98845ab4867 --- /dev/null +++ b/website/blog/2022-07-05-datediff-sql-love-letter.md @@ -0,0 +1,93 @@ +--- +title: "DATEDIFF SQL function: Why we love it" +description: "The DATEDIFF function will return the difference in specified units (ex. days, weeks, years) between a start date/time and an end date/time. It’s a simple and widely used function that you’ll find yourself using more often than you expect." +slug: datediff-sql-love-letter + +authors: [kira_furuichi] + +tags: [sql magic] +hide_table_of_contents: false + +date: 2022-07-13 +is_featured: false +--- + +*“How long has it been since this customer last ordered with us?”* + +*“What is the average number of days to conversion?”* + +Business users will have these questions, data people will have to answer these questions, and the only way to solve them is by calculating the time between two different dates. Luckily, there’s a handy DATEDIFF function that can do that for you. + +The DATEDIFF function will return the difference in specified units (ex. days, weeks, years) between a start date/time and an end date/time. It’s a simple and widely used function that you’ll find yourself using more often than you expect. + + + +> **What is a SQL function?** +> At a high level, a function takes an input (or multiple inputs) and returns a manipulation of those inputs. Some common SQL functions are [COALESCE](https://getdbt.com/sql-foundations/coalesce-sql-love-letter/), [LOWER](https://getdbt.com/sql-foundations/lower-sql-love-letter/), and [EXTRACT](https://getdbt.com/sql-foundation/extract-sql-love-letter/). For example, the COALESCE function takes a group of values and returns the first non-null value from that group. + +DATEDIFF is a little bit like your favorite pair of socks; you’ll usually find the first one easily and feel like the day is going to be great. But for some reason, the matching sock requires a little digging in the drawer. DATEDIFF is this pair of socks—you’ll inevitably find yourself Googling the syntax almost every time you use it, but you can’t go through your day without using it. + +This post will go over how to use the DATEDIFF function across different data warehouses and how to write more standardized DATEDIFF functions using a dbt macro (or successfully find your socks as a pair in one go). + +## How to use the DATEDIFF function + +For the DATEDIFF function, there’s three elements, or arguments, passed in: + +* The date part: This is the days/months/weeks/years (unit) of the difference calculated +* The first (start) date/time +* The second (end) date/time + +The DATEDIFF function can be used in SELECT statements and WHERE clauses. + +Most, if not all, modern cloud data warehouses support some type of the DATEDIFF function. There may be some minor differences between the argument order and function name for DATEDIFF across data warehouses, but the functionality very much remains the same. + +Below, we’ll outline some of the slight differences in the implementation between some data warehouses. + +### DATEDIFF in Snowflake, Amazon Redshift, and Databricks + +The syntax for using the DATEDIFF function in [Snowflake](https://docs.snowflake.com/en/sql-reference/functions/datediff.html) and [Amazon Redshift](https://docs.aws.amazon.com/redshift/latest/dg/r_DATEDIFF_function.html), and [Databricks](https://docs.databricks.com/sql/language-manual/functions/datediff3.html) looks like the following: + +```sql +datediff(, , ) +``` + +> **A note on Databricks:** +> Databricks additionally supports a separate [DATEDIFF function](https://docs.databricks.com/sql/language-manual/functions/datediff.html) that takes only two arguments: a start date and an end date. The function will always return the difference between two dates in days. + +### DATEDIFF in Google BigQuery + +The syntax for using the DATEDIFF function in [Google BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/datetime_functions#datetime_diff) looks like the following: + +Three minor differences in the implementation here: + +* Unlike in Snowflake, Amazon Redshift, and Databricks where the `` is passed as the first argument, the `` is passed in as the last argument in Google BigQuery. +* Google BigQuery also calls the function DATETIME_DIFF with an additional underscore separating the function name. This is on-par with [Google BigQuery’s preference to have underscores in function names](https://cloud.google.com/bigquery/docs/reference/standard-sql/date_functions). +* The DATETIME_DIFF arguments are datetimes, not dates; Snowflake, Redshift, and Databricks’ DATEDIFF functions support multiple date types such as dates and timestamps. BigQuery also supports a separate [DATE_DIFF function](https://cloud.google.com/bigquery/docs/reference/standard-sql/date_functions#date_diff) that will return the difference between two `date` types, unlike the DATETIME_DIFF that only supports the `datetime` type. + +## A hero in the shadows: The DATEDIFF dbt macro! + +You may be able to memorize the syntax for the DATEDIFF function for the primary data warehouse you use. What happens when you switch to a different one for a new job or a new data stack? Remembering if there’s an underscore in the function name or which argument the `` is passed in as is… no fun and leads to the inevitable, countless “datediff in bigquery” Google searches. + +Luckily, [dbt-core](https://github.com/dbt-labs/dbt-core) has your back! dbt Core is the open source dbt product that helps data folks write their data transformations following software engineering best practices. + +With dbt v1.2, [adapters](https://docs.getdbt.com/docs/supported-data-platforms) now support [cross-database macros](https://docs.getdbt.com/reference/dbt-jinja-functions/cross-database-macros) to help you write certain functions, like [DATE_TRUNC](https://docs.getdbt.com/reference/dbt-jinja-functions/cross-database-macros#date_trunc) and [DATEDIFF](https://docs.getdbt.com/reference/dbt-jinja-functions/cross-database-macros#datediff), without having to memorize sticky function syntax. + +> **Note:** +> Previously, [dbt_utils](https://github.com/dbt-labs/dbt-utils), a package of macros and tests that data folks can use to help write more DRY code in their dbt project, powered cross-database macros. Now, cross-database macros are available **regardless if dbt utils is installed or not.** + +Using the [DATEDIFF macro](https://docs.getdbt.com/reference/dbt-jinja-functions/cross-database-macros#datediff), you can calculate the difference between two dates without having to worry about finicky syntax. Specifically, this means you could successfully run the *same code* across multiple databases without having to worry about the finicky differences in syntax. + +Using the [jaffle shop](https://github.com/dbt-labs/jaffle_shop/blob/main/models/orders.sql), a simple dataset and dbt project, we can calculate the difference between two dates using the dbt DATEDIFF macro: + +```sql +select + *, + {{ datediff("order_date", "'2022-06-09'", "day") }} +from {{ ref('orders') }} +``` + +This would return all fields from the `orders` table and the difference in days between order dates and June 9, 2022. + +Under the hood, this macro is taking your inputs and creating the appropriate SQL syntax for the DATEDIFF function *specific to your data warehouse.* + +*This post is a part of the SQL love letters—a series on the SQL functions the dbt Labs data team members use and love. You can find [the entire collection here](https://getdbt.com/sql-foundations/top-sql-functions).* diff --git a/website/blog/2022-07-12-change-data-capture.md b/website/blog/2022-07-12-change-data-capture.md new file mode 100644 index 00000000000..b765cec9c95 --- /dev/null +++ b/website/blog/2022-07-12-change-data-capture.md @@ -0,0 +1,380 @@ +--- +title: "Strategies for change data capture in dbt" +description: "Capturing a historical view of your data is complex. Grace Goheen walks you through how to do it in this blog!" +slug: change-data-capture + +authors: [grace_goheen] + +tags: [analytics craft] +hide_table_of_contents: false + +date: 2022-07-14 +is_featured: true +--- + + +There are many reasons you, as an analytics engineer, may want to capture the complete version history of data: + +- You’re in an industry with a very high standard for data governance +- You need to track big OKRs over time to report back to your stakeholders +- You want to build a window to view history with both forward and backward compatibility + +These are often high-stakes situations! So accuracy in tracking changes in your data is key. + + + +If you’ve encountered this problem before, you know it’s a tricky one. dbt is [idempotent](https://discourse.getdbt.com/t/understanding-idempotent-data-transformations/518) - it recreates tables at runtime with the `CREATE TABLE AS` syntax. Because of this, the ability to access a full picture of historical outputs isn't intrinsic to dbt. + +Let’s imagine a specific scenario. Joanne is an analytics engineer for a large e-commerce company. The head of sales just messaged her the following question: + +“Can you tell me the income for January 2022 for all clothing products?” + +On the surface, this may seem like a simple question. But what if the calculation of income has changed since January 2022? Should Joanne calculate the income using the current formula or the formula that was used in January 2022? What if the source data for January changed after the month closed? Should Joanne use the source data as it was on January 30th, 2022 or the source data as it is now? + +All of these questions bubble up to our main theme: *How can you capture historical versions of our data using dbt?* + +Sorry, Joanne. The TL;DR is - “it depends.” + +When I first encountered this problem, it took time and effort to: + +1. think through the possible solutions + +and + +2. determine which solution best suited my needs + +The goal of this article is to eliminate step one – to provide you with a menu of solutions I’ve encountered so you can spend less time ideating and more time considering the nuances of your specific use-case. + +I’ll start by discussing a basic version of the scenario I first encountered – a ⚠️ misapplication ⚠️ of dbt’s snapshot functionality. Then, I’ll outline a couple of solutions: + +- **Downstream Incremental Model**: Build an incremental model downstream of the model which contains your business logic to “grab” every point-in-time version +- **Upstream Snapshots**: Build snapshots on all of your sources to capture changes in your raw data and calculate all versions of history every time you execute a `dbt run` + +Finally, I’ll discuss the pros and cons of each solution to give you a head start on step two. + +## Scenario + +Let’s return to Joanne. Using dbt and her favorite BI tool, Joanne has created an income report to track monthly income for each product category. + +You can imagine her DAG as shown below, where `fct_income` captures income per month for each product category. + +![](/img/blog/2022-07-12-change-data-capture-metrics/fct-income-dag.png) + +Joanne executes a `dbt run` on January 30th, 2022 and queries the resulting table: + +```sql +select * from fct_income where month_year = "January 2022" +``` + +She gets the following output: + +| month_year | product_category | income | run_timestamp | +|:---:|:---:|:---:|:---:| +| January 2022 | clothing | 100 | 01/30/22 12:00:00 | +| January 2022 | electronics | 200 | 01/30/22 12:00:00 | +| January 2022 | books | 100 | 01/30/22 12:00:00 | + +But a few days later, her source data changes for January - a manufacturing cost was dated incorrectly, and now has been updated in the source. Joanne executes a `dbt run` again on February 3rd. Now when she queries `fct_income`, she gets the following output: + +| month_year | product_category | income | run_timestamp | +|:---:|:---:|:---:|:---:| +| January 2022 | clothing | **50** | 02/03/22 16:00:00 | +| January 2022 | electronics | **150** | 02/03/22 16:00:00 | +| January 2022 | books | **200** | 02/03/22 16:00:00 | + +A few days later, Joanne finds a bug in her `dbt code`. She fixes the bug and executes a dbt run again on February 10th. Now, when she queries `fct_income`, she gets the following output: + +| month_year | product_category | income | run_timestamp | +|:---:|:---:|:---:|:---:| +| January 2022 | clothing | **52** | 02/10/22 08:00:00 | +| January 2022 | electronics | **152** | 02/10/22 08:00:00 | +| January 2022 | books | **202** | 02/10/22 08:00:00 | + +When the head of sales messages Joanne the following question: “Can you tell me the income for January 2022 for all clothing products?”, she’s unsure which number to give: 100, 50, or 52. + +![](/img/blog/2022-07-12-change-data-capture-metrics/income-meme.png) + +Because of this complexity, she decides to capture the history of her income report so that she can easily swap between versions in her BI tool. + +Her goal is to capture **all** versions of the `fct_income` model for January. Something like this: + +| month_year | product_category | income | run_timestamp | +|:---:|:---:|:---:|:---:| +| January 2022 | clothing | 100 | 01/30/22 12:00:00 | +| January 2022 | electronics | 200 | 01/30/22 12:00:00 | +| January 2022 | books | 300 | 01/30/22 12:00:00 | +| January 2022 | clothing | 50 | 02/03/22 16:00:00 | +| January 2022 | electronics | 150 | 02/03/22 16:00:00 | +| January 2022 | books | 200 | 02/03/22 16:00:00 | +| January 2022 | clothing | 52 | 02/10/22 08:00:00 | +| January 2022 | electronics | 152 | 02/10/22 08:00:00 | +| January 2022 | books | 202 | 02/10/22 08:00:00 | + +In order to achieve this **long table of history**, she decides to start [snapshotting](https://docs.getdbt.com/docs/building-a-dbt-project/snapshots) her final model, `fct_income`. + +:::caution Don't be like Joanne +I'm including the code samples for completeness, but remember: the method described in this scenario of snapshotting a final model contradicts dbt Labs' best practices. Either of the solutions detailed later is a better approach. +::: + +```sql +{% snapshot snapshot_fct_income %} + +{{ + config( + target_database='analytics', + target_schema='snapshots', + unique_key='id', + strategy='check', + check_cols=['income'] + ) +}} + +select + month_year || ' - ' || product_category as id, + * +from {{ ref('fct_income') }} + +{% endsnapshot %} +``` + +The output of `snapshot_fct_income` looks like this: + +| id | month_year | product_category | income | run_timestamp | dbt_valid_from | dbt_valid_to | +|:---:|:---:|:---:|:---:|:---:|:---:|:---:| +| January 2022 - clothing | January 2022 | clothing | 100 | 01/30/22 12:00:00 | 01/30/22 12:00:00 | 02/03/22 16:00:00 | +| January 2022 - electronics | January 2022 | electronics | 200 | 01/30/22 12:00:00 | 01/30/22 12:00:00 | 02/03/22 16:00:00 | +| January 2022 - books | January 2022 | books | 300 | 01/30/22 12:00:00 | 01/30/22 12:00:00 | 02/03/22 16:00:00 | +| January 2022 - clothing | January 2022 | clothing | 50 | 02/03/22 16:00:00 | 02/03/22 16:00:00 | 02/10/22 08:00:00 | +| January 2022 - electronics | January 2022 | electronics | 150 | 02/03/22 16:00:00 | 02/03/22 16:00:00 | 02/10/22 08:00:00 | +| January 2022 - books | January 2022 | books | 200 | 02/03/22 16:00:00 | 02/03/22 16:00:00 | 02/10/22 08:00:00 | +| January 2022 - clothing | January 2022 | clothing | 52 | 02/10/22 08:00:00 | 02/10/22 08:00:00 | NULL | +| January 2022 - electronics | January 2022 | electronics | 152 | 02/10/22 08:00:00 | 02/10/22 08:00:00 | NULL | +| January 2022 - books | January 2022 | books | 202 | 02/10/22 08:00:00 | 02/10/22 08:00:00 | NULL | + +Each month now has multiple versions of income, and the sales department is responsible for determining which version is “correct.” + +In order to keep track of which version has been marked as “correct” by the sales department, Joanne creates a seed file to capture which version of the `fct_income` model is the correct one for each month. The output of her seed `income_report_versions` looks like this: + +| month_year | correct_version | comment | +|:---:|:---:|:---:| +| January 2022 | 02/10/22 08:00:00 | Approved by Lucy | + +Her final DAG now looks like this: + +![](/img/blog/2022-07-12-change-data-capture-metrics/income-report-versions-dag.png) + +She's snapshotting `fct_income`, joining the seed file with the snapshot, then exposing the final output to her BI tool. The final output of `stg_snapshot_fct_income` looks like this: + +| month_year | product_category | income | run_timestamp | correct_version | +|:---:|:---:|:---:|:---:|:---:| +| January 2022 | clothing | 100 | 01/30/22 12:00:00 | FALSE | +| January 2022 | electronics | 200 | 01/30/22 12:00:00 | FALSE | +| January 2022 | books | 300 | 01/30/22 12:00:00 | FALSE | +| January 2022 | clothing | 50 | 02/03/22 16:00:00 | FALSE | +| January 2022 | electronics | 150 | 02/03/22 16:00:00 | FALSE | +| January 2022 | books | 200 | 02/03/22 16:00:00 | FALSE | +| January 2022 | clothing | 52 | 02/10/22 08:00:00 | TRUE | +| January 2022 | electronics | 152 | 02/10/22 08:00:00 | TRUE | +| January 2022 | books | 202 | 02/10/22 08:00:00 | TRUE | + +This method *technically* works. Joanne can track what she needs: + +- source data changes +- business logic changes + +And she can easily switch versions by adding a filter on her BI layer. + +However, this method causes long job times and adds potentially unnecessary complexity – one of the reasons our [best practices](https://docs.getdbt.com/docs/building-a-dbt-project/snapshots#snapshot-query-best-practices) recommend only using snapshots to track changes in your source data, rather than your final models. + +Below, you’ll find two solutions that are more effective than snapshotting a final model, as well as the pros and cons of each method. + +## Solution #1: Downstream Incremental Model + +Instead of using snapshots, Joanne could create an [incremental model](https://docs.getdbt.com/docs/building-a-dbt-project/building-models/configuring-incremental-models) downstream of `fct_income` to “grab” every point-in-time version of `fct_income` – let’s call this incremental model `int_income_history` and assume it has the following config block: + +```sql +{{ + config( + materialized='incremental' + ) +}} +``` + +By materializing `int_income_history` as incremental but *not* including a `unique_key` config, dbt will only execute `INSERT` statements – new rows will be added, but old rows will remain unchanged. + +The rest of `int_income_history` would look like this: + +```sql +... + +select + * +from {{ ref('fct_income') }} +{% if is_incremental() %} + where true +{% endif %} +``` + +There are a few additional configs that Joanne might find helpful: + +- she can use the `on_schema_change` config to handle schema changes if new columns are added and/or deleted from `fct_income` +- she can also set the `full_refresh` config to false in order to prevent accidental loss of the historical data +- she can build this table in a custom `schema` if she wants to enforce specific role-based permissions for this historical table +- she can specify a time-grain `unique_key` if she wants to reduce the amount of versions being captured + - for example, if she only wants to capture the final version of each day she could set `unique_key = date_trunc('day', run_timestamp)`. This is excluded from the example below, as we are making the assumption that Joanne does indeed want to capture every version of `fct_income` + +The final config block for `int_income_history` might look something like this: + +```sql +{{ + config( + materialized='incremental', + full_refresh=false, + schema='history', + on_schema_change='sync_all_columns' + ) +}} +``` + +As a final step, Joanne would create `fct_income_history` to join in the seed file to determine which versions are “correct”. Her new DAG looks like this, where `int_income_history` is an incremental model without a unique key: + +![](/img/blog/2022-07-12-change-data-capture-metrics/int-income-history-dag.png) + +The final output of `fct_income_history` would look identical to `stg_snapshot_fct_income` from her initial approach: + +| month_year | product_category | income | run_timestamp | correct_version | +|:---:|:---:|:---:|:---:|:---:| +| January 2022 | clothing | 100 | 01/30/22 12:00:00 | FALSE | +| January 2022 | electronics | 200 | 01/30/22 12:00:00 | FALSE | +| January 2022 | books | 300 | 01/30/22 12:00:00 | FALSE | +| January 2022 | clothing | 50 | 02/03/22 16:00:00 | FALSE | +| January 2022 | electronics | 150 | 02/03/22 16:00:00 | FALSE | +| January 2022 | books | 200 | 02/03/22 16:00:00 | FALSE | +| January 2022 | clothing | 52 | 02/10/22 08:00:00 | TRUE | +| January 2022 | electronics | 152 | 02/10/22 08:00:00 | TRUE | +| January 2022 | books | 202 | 02/10/22 08:00:00 | TRUE | + +## Solution #2: Upstream Snapshots + +Alternatively, Joanne could snapshot her source data and add flexibility to her modeling so that all historical versions are calculated *at the same time*. Let’s look at our example. + +Joanne could track changes in the source data by adding snapshots directly on top of her raw data. + +![](/img/blog/2022-07-12-change-data-capture-metrics/snapshots-dag.png) + +This would *change the * of these `stg_` tables, so she would see a row for each version of each field. The staging models will contain the history of each record. + +Remember the source data change Joanne noticed — a manufacturing cost was dated incorrectly (Junkuary 2022 instead of January 2022). With this solution, the `costs_snapshot` model will pick up this change: + +```sql +{% snapshot costs_snapshot %} + +{{ + config( + target_database='analytics', + target_schema='snapshots', + unique_key='cost_id', + strategy='timestamp', + updated_at='updated_at' + ) +}} + +select * from {{ source('source', 'costs') }} + +{% endsnapshot %} +``` + +| cost_id | month_year | cost | updated_at | dbt_valid_from | dbt_valid_to | +|:---:|:---:|:---:|:---:|:---:|:---:| +| 1 | Junkuary 2022 | 50 | 01/15/22 12:00:00 | 01/15/22 12:00:00 | 02/03/22 12:00:00 | +| 1 | January 2022 | 50 | 02/03/22 12:00:00 | 02/03/22 12:00:00 | NULL | + +:::note Note +Because snapshots only capture changes detected at the time the dbt snapshot command is executed, it is technically possible to miss some changes to your source data. You will have to consider how often you want to run this snapshot command in order to capture the history you need. +::: + +The original `fct_income` model now calculates the income for each version of source data, every time Joanne executes a `dbt run`. In other words, the downstream `fct_` models are **version-aware**. Because of this, Joanne changes the name of `fct_income` to `fct_income_history` to be more descriptive. + +In order to track changes in business logic, she can apply each version of logic to the relevant records and union together. + +Remember the bug Joanne found in her dbt code. With this solution, she can track this change in business logic in the `stg_costs` model: + +```sql +-- apply the old logic for any records that were valid on or before the logic change +select + cost_id, + ..., + cost + tax as final_cost, -- old logic + 1 || ‘-’ || dbt_valid_from as version +from costs_snapshot +where dbt_valid_from <= to_timestamp('02/10/22 08:00:00') + +union all + +-- apply the new logic for any records that were valid after the logic change +select + cost_id, + ..., + cost as final_cost, -- new logic + 2 || ‘-’ || dbt_valid_from as version +from costs_snapshot +where to_timestamp('02/10/22 08:00:00') between dbt_valid_to and coalesce(dbt_valid_from, to_timestamp('01/01/99 00:00:00')) +``` +| cost_id | month_year | cost | tax | final_cost | version | +|:---:|:---:|:---:|:---:|:---:| :---:| +| 1 | Junkuary 2022 | 50 | 1 | 51 | 1 - 01/15/22 12:00:00 | +| 1 | January 2022 | 50 | 1 | 51 | 1 - 02/03/22 12:00:00 | +| 1 | January 2022 | 50 | 1 | 50 | 1 - 02/03/22 12:00:00 | + +The contents of the seed `income_report_versions` would look slightly different to match the change in version definition: + +| month_year | correct_version | comment | +|:---:|:---:|:---:| +| January 2022 | 2 - 02/03/22 12:00:00 | Approved by Lucy | + +After joining in the seed file (check out [Tackling the complexity of joining snapshots](https://docs.getdbt.com/blog/joining-snapshot-complexity)), her new DAG looks like this: + +![](/img/blog/2022-07-12-change-data-capture-metrics/final-dag.png) + +The final output of `fct_income_history` would accomplish the same goal as `stg_snapshot_fct_income` from her initial approach: + +| month_year | product_category | income | version | correct_version | +|:---:|:---:|:---:|:---:|:---:| +| January 2022 | clothing | 100 | 1 - 01/15/22 12:00:00 | FALSE | +| January 2022 | electronics | 200 | 1 - 01/15/22 12:00:00 | FALSE | +| January 2022 | books | 300 | 1 - 01/15/22 12:00:00 | FALSE | +| January 2022 | clothing | 50 | 1 - 02/03/22 12:00:00 | FALSE | +| January 2022 | electronics | 150 | 1 - 02/03/22 12:00:00 | FALSE | +| January 2022 | books | 200 | 1 - 02/03/22 12:00:00 | FALSE | +| January 2022 | clothing | 52 | 2 - 02/03/22 12:00:00 | TRUE | +| January 2022 | electronics | 152 | 2 - 02/03/22 12:00:00 | TRUE | +| January 2022 | books | 202 | 2 - 02/03/22 12:00:00 | TRUE | + +## Final thoughts + +Both of these solutions allow Joanne to achieve her desired output – a table containing all versions of income for a given month – while improving the workflow and the efficiency of the final model. + +However, each has its advantages and disadvantages. + +**Solution #1: Downstream Incremental Model** + +| Pros | Cons | +|:---:|:---:| +| incremental models without unique keys are fast | this isn't really the intended use of the incremental | +| | Joanne has no way to re-calculate prior versions if her historical table is accidentally lost | + +**Solution #2: Upstream Snapshots** + +| Pros | Cons | +|:---:|:---:| +| Joanne doesn't have to worry about losing historical data | snapshots are highly complex and require more institutional knowledge for Joanne's team | +| | every time Joanne wants to make a code change that affects her calculations, she'll have to remember to apply the change to each set of relevant records and union the outputs together | + +When deciding between the two solutions, you should consider the following: + +- How often is your source data changing? +- How many bug fixes do you anticipate? +- How fast do you need this job to be? +- How much visibility do you need into why a change in historic values occurred? + +💡 What do you think? Is there another, more optimal, solution? diff --git a/website/blog/2022-07-13-star-sql-love-letter.md b/website/blog/2022-07-13-star-sql-love-letter.md new file mode 100644 index 00000000000..87469dc2730 --- /dev/null +++ b/website/blog/2022-07-13-star-sql-love-letter.md @@ -0,0 +1,83 @@ +--- +title: "A star (generator) is born" +description: "One of the macros dbt utils offers is the `star` generator. This dbt macro is one of our favorites because it lets you select all the fields you want without writing the columns you don't." +slug: star-sql-love-letter + +authors: [kira_furuichi] + +tags: [sql magic] +hide_table_of_contents: false + +date: 2022-05-23 +is_featured: true +--- + + +We’ve likely been here: Table A has 56 columns and we want to select all but one of them (`column_56`). So here we go, let’s get started… + +```sql +select + column_1, + column_2, + column_3, + please_save_me… +from {{ ref('table_a') }} +``` + +At this point, you realize your will to continue typing out the next 52 columns has essentially dwindled down to nothing and you’re probably questioning the life choices that led you here. + +But what if there was a way to make these 56+ lines of code come down to a handful? Well, that’s where a handy [dbt macro](https://docs.getdbt.com/docs/building-a-dbt-project/jinja-macros) comes into play. + + + +## The `star` dbt macro + +dbt supports [dbt_utils](https://github.com/dbt-labs/dbt-utils), a [package of macros and tests](https://docs.getdbt.com/docs/building-a-dbt-project/package-management) that data folks can use to help them write more code in their dbt project. One of the macros dbt utils offers is the `star` generator. + +This macro: + +* Generates a comma-separated list of all fields that exist in the `from` [relation](https://docs.getdbt.com/reference/dbt-classes#relation) and excludes any fields listed in an `except` argument, +* Can optionally add a prefix to all generated fields using the `relation_alias` argument, +* And also concatenate prefixes and/or suffixes to all generated fields using the `prefix` and `suffix` arguments + +So what does this mean for the example from above? Instead of writing out all 55 columns, you can use the `star` macro to select all fields except the column you don’t want: + +```sql +select + {{ dbt_utils.star(from=ref('table_a'), except=['column_56'] }} +from {{ ref('table_a') }} +``` + +This dbt model compiles to: + +```sql +select + column_1, + column_2, + …, --imagine we weren’t lazy and wrote out all other columns + column_55 +from table_a +``` + +With the `star` macro, all of the columns except `column_56` are generated in a comma-separated list within the `select` statement. What was once 56+ lines of tedious, mind-numbing SQL becomes 3 lines using the `star` macro. You can also exclude multiple columns by passing in the column names to the `except` argument. + +If you want to alias all fields in a model with the same alias without having to explicitly rename them all, you can also use the `star` macro with the `relation_alias` argument passed in: + +```sql +select + {{ dbt_utils.star(from=ref('table_a'), relation_alias='my_new_alias') }} +from {{ ref('table_a') }} +``` + +Now, this will return all fields from `table_a` with the `my_new_alias.field_name` naming format. + +[Under the hood](https://github.com/dbt-labs/dbt-utils/blob/main/macros/sql/star.sql), the `star` macro is actually using another dbt utils macro ([get_filtered_columns_in_relation](https://github.com/dbt-labs/dbt-utils#get_filtered_columns_in_relation-source)) to loop through fields to either select, alias, and/or append some string values to them. + +## Why we love the `star` macro + +It’s no hidden fact: the Data Team at dbt Labs loves to use dbt util’s macros and tests when appropriate. We like dbt utils so much we created a March Madness Utils Bracket for them (not taking questions at this time) and we used the `star` macro alone over 30 times in our internal dbt repository. + +![](/img/blog/2022-07-13-star-sql-love-letter/utils-madness-1.png) + + +Overall, the `star` macro is a great way to dip your toes into the dbt utils package, write DRY code, and reduce your carpal tunnel. \ No newline at end of file diff --git a/website/blog/2022-07-19-migrating-from-stored-procs.md b/website/blog/2022-07-19-migrating-from-stored-procs.md new file mode 100644 index 00000000000..2140bc24dc1 --- /dev/null +++ b/website/blog/2022-07-19-migrating-from-stored-procs.md @@ -0,0 +1,225 @@ +--- +title: "Migrating from Stored Procedures to dbt" +description: "Stored procedures are great, but they eventually become hard to scale. dbt fixes that, but the migration process can seem daunting. Matt Winkler demystifies the process in this blog!" +slug: migrating-from-stored-procs + +authors: [matt_winkler] + +tags: [analytics craft] +hide_table_of_contents: false + +date: 2022-07-20 +is_featured: true +--- + +Stored procedures are widely used throughout the data warehousing world. They’re great for encapsulating complex transformations into units that can be scheduled and respond to conditional logic via parameters. However, as teams continue building their transformation logic using the stored procedure approach, we see more data downtime, increased data warehouse costs, and incorrect / unavailable data in production. All of this leads to more stressed and unhappy developers, and consumers who have a hard time trusting their data. + +If your team works heavily with stored procedures, and you ever find yourself with the following or related issues: + +- dashboards that aren’t refreshed on time +- It feels too slow and risky to modify pipeline code based on requests from your data consumers +- It’s hard to trace the origins of data in your production reporting + +It’s worth considering if an alternative approach with dbt might help. + + + +## Why use modular dbt models instead of stored procedures? + +We work with many analytics teams to refactor their stored procedure code into dbt. Many of them come in thinking that the upfront effort to modernize their approach to data transformation will be too much to justify. However, we see that in the long term this isn’t the case. + +For example, a dbt Cloud user achieved the following results when moving away from the stored procedure approach: + +### Improved Uptime + +Before migrating to dbt, the team was spending 6 - 8 hours per day on pipeline refreshes, making their investment in their data warehouse essentially worthless during that downtime. After migration, their uptime increased from 65% to 99.9%. This also has a drastic impact on data consumers’ confidence in the underlying pipelines. + +### Tackling New Use Cases +Further, the team was able to support new mission-critical use cases, which simply wouldn’t have been possible had the team continued using the same techniques they had historically. + +Now that we’ve discussed why moving from stored procs to dbt can make sense for many analytics teams, let’s discuss how the process works in a bit more detail. + +## What are the problems with stored procedures? +Some of the drawbacks to using stored procedures may not have been apparent historically, but they come to light when we consider modern expectations of data pipelines such as transparent documentation, testability, and reusability of code. For one, stored procedures don’t lend themselves well to documenting data flow, as the intermediate steps are a black box. Secondly, this also means that your stored procedures aren’t very testable. Finally, we often see logic from intermediate steps in one stored procedure copied almost line-for-line to others! This creates extra bloat across a development team’s codebase, which drags down team efficiency. + +We might visualize this situation as something like this: + +![Diagram of what a stored procedure data flow would look like. Hint: it's complicated](/img/blog/2022-07-19-migrating-from-stored-procs/stored-procs-diagram.png) + +## Why consider dbt as an alternative? + +dbt offers an approach that is self-documenting, testable, and encourages code reuse during development. One of the most important elements of working in dbt is embracing modularity when approaching data pipelines. In dbt, each business object managed by a data pipeline is defined in a separate model (think: orders data). These models are flexibly grouped into layers to reflect the progression from raw to consumption ready data. Working in this way, we create reusable components which helps avoid duplicating data and confusion among development teams. + +With dbt, we work towards creating simpler, more transparent data pipelines like this: + +![Diagram of what data flows look like with dbt. It's easier to trace lineage in this setup.](/img/blog/2022-07-19-migrating-from-stored-procs/dbt-diagram.png) + +Tight [version control integration](https://docs.getdbt.com/docs/guides/best-practices#version-control-your-dbt-project) is an added benefit of working with dbt. By leveraging the power of git-based tools, dbt enables you to integrate and test changes to transformation pipelines much faster than you can with other approaches. We often see teams who work in stored procedures making changes to their code without any notion of tracking those changes over time. While that’s more of an issue with the team’s chosen workflow than a problem with stored procedures per se, it does reflect how legacy tooling makes analytics work harder than necessary. + +## Methodologies for migrating from stored procedures to dbt + +Whether you’re working with T-SQL, PL/SQL, BTEQ, or some other SQL dialect, the process of migrating from the stored procedure approach to the dbt approach can typically be broken down into similar steps. Over the years, we’ve worked with many customers to convert confusing and hard-to-manage stored procedure code into modular dbt pipelines. Through our work, we’ve arrived at a few key best practices in undertaking this process, which we present below. + +If you’re interested in diving into further detail on this topic, please visit our [companion guide](https://docs.getdbt.com/guides/migration/tools/migrating-from-stored-procedures/1-migrating-from-stored-procedures) to learn more in-depth information about the refactoring process. + +### Step 0: Understand a bit about how dbt works + +If this is your first time running dbt, you may want to start with the [Introduction to dbt](https://docs.getdbt.com/docs/introduction) and the [Getting Started tutorial](https://docs.getdbt.com/tutorial/setting-up) before diving into refactoring. If you’re already familiar with building dbt models and pipelines, feel free to dive in! + +### Step 1: Understand how dbt and stored procedures are different + +Most folks who have written Stored Procedures in the past think about the world in terms of a stateful process that progresses line-by-line. You start out creating your tables, and then use to insert, update, and delete data, continually applying operations to the same base table throughout the course of a transformation. + +On the other hand, dbt takes a declarative approach to managing datasets by using SELECT statements to describe the set of data that should make up the table. The tables (or views) defined in this way represent each stage or unit of transformation work, and are assembled into a [Directed Acyclic Graph (DAG)](https://docs.getdbt.com/docs/introduction#what-makes-dbt-so-powerful) to determine the order in which each statement runs. As we’ll see, this achieves the same ends as procedural transformations, but instead of applying many operations to one dataset, we take a more modular approach. This makes it MUCH easier to reason about, document, and test transformation pipelines. + +### Step 2: Plan how to convert your stored procedure to dbt code + +In general, we've found that the recipe presented below is an effective conversion process. + +1. Map data flows in the stored procedure +2. Identify raw source data +3. Create a staging layer on top of raw sources for initial data transformations such as data type casting, renaming, etc. +4. Replace hard-coded table references with dbt [source()](https://docs.getdbt.com/docs/building-a-dbt-project/using-sources) and [ref()](https://docs.getdbt.com/reference/dbt-jinja-functions/ref) statements. This enables 1) ensuring things are run in the right order and 2) automatic documentation! +5. Map INSERTS and UPDATES in the stored procedure to SELECT in dbt models +6. Map DELETES in the stored procedure to WHERE filters in dbt models +7. If necessary, use [variables](https://docs.getdbt.com/docs/building-a-dbt-project/building-models/using-variables) in dbt to dynamically assign values at runtime, similar to arguments passed to a stored procedure. +8. Iterate on your process to refine the dbt [DAG](https://docs.getdbt.com/docs/introduction#what-makes-dbt-so-powerful) further. You could continue optimizing forever, but typically we find a good stopping point when the outputs from the stored procedure and final dbt models are at parity. + +Sometimes, we find ourselves confronted with code that’s so complex, the end user isn’t able to understand exactly what it’s doing. In these cases, it may not be possible to perform an apples-to-apples mapping of the process embedded in the original stored procedure, and it’s actually more efficient to scrap the whole thing and focus on working backwards to reproduce the desired output in dbt. Note the section on auditing results below as a key success driver in this situation. + +### Step 3: Execute + +Where the magic happens :). Jon “Natty” Natkins is developing a very robust how-to guide to walk through an example refactoring process from the ground up. To give a taste, we’ll show what the first few steps of the recipe described above look like in action, mapping from the original Stored Procedure approach to our new one using dbt. + +#### Stored procedure approach (using SQL server code): + +1. Define a temp table selecting data from a raw table and insert some data into it + +```sql +IF OBJECT_ID('tempdb..#temp_orders') IS NOT NULL DROP TABLE #temp_orders + SELECT messageid + ,orderid + ,sk_id + ,client + FROM some_raw_table + WHERE . . . + INTO #temp_orders +``` + +2. Run another INSERT from a second raw table + +```sql + INSERT INTO #temp_orders(messageid,orderid,sk_id, client) + SELECT messageid + ,orderid + FROM another_raw_table + WHERE . . . + INTO #temp_orders +``` + +3. Run a DELETE on the temp table to get rid of test data that lives in production + +```sql + DELETE tmp + FROM #temp_orders AS tmp + INNER JOIN + criteria_table cwo WITH (NOLOCK) + ON tmp.orderid = cwo.orderid + WHERE ISNULL(tmp.is_test_record,'false') = 'true' +``` + +We often see this process go on for quite some time (think: 1,000s of lines of code). To recap, the issues with this approach are: + +- Tracing the data flow becomes REALLY hard because the code is a) really long and b) not documented automatically. +- The process is stateful - Our example #temp_orders table evolves throughout the process, which means we have to juggle several different factors if we want to adjust it. +- It’s not easy to test. + +#### dbt approach + + +1. Identify the raw source tables, and then map each of the INSERT statements above into separate dbt models, and include an automatically generated WHERE statement to eliminate the test records from the third step above. + +```sql +— orders_staging_model_a.sql +{{ + config( + materialized='view' + ) +}} + +with raw_data as ( + select * + from {{ source('raw', 'some_raw_table')}} + where is_test_record = false +), + +cleaned as ( + select messageid, + orderid::int as orderid, + sk_id, + case when client_name in ['a', 'b', 'c'] then clientid else -1 end + from raw_data +) + +select * from cleaned +``` + +2. Write tests on the models to ensure our code is working at the proper grain + +```sql +version: 2 + +models: + - name: stg_orders + columns: + - name: orderid + tests: + - unique + - not_null +``` + +3. UNION the models together + +```sql +{{ + config( + materialized='table' + ) +}} + +with a as ( select * from {{ ref('stg_orders_a') }} ), +b as (select * from {{ ref('stg_orders_b') }} ), + +unioned as ( + select * from a + union all + select * from b +) + +select * from unioned +``` + +We’ve just created a modular, documentable, and testable approach to manage the same transformations as an alternative. + +![A dbt DAG that shows the output of the code you just implemented](/img/blog/2022-07-19-migrating-from-stored-procs/dbt-approach-model.png) + +### Step 4: Audit your results + +Any time you introduce a change to a technical process, it’s essential to check your results. Fortunately, dbt Labs maintains the [audit helper package](https://hub.getdbt.com/dbt-labs/audit_helper/0.0.2/) with exactly this use case in mind. The audit helper enables you to perform operations such as comparing row counts, and row by row validation on a table that’s updated by a legacy stored procedure to one that’s the result of a dbt pipeline in order to make sure the two are exactly the same (or, within a reasonable % deviation). This way, you have confidence that your new dbt pipeline is accomplishing the same goals of the transformation pipeline that existed before. + +## Summary + +We’ve highlighted several of the pain points of working with stored procedures (mainly the lack of traceability and data testing) and how the dbt approach can help. Well documented, modular, testable code makes for happy engineers and happy business users alike :handshake:. It also helps us save time and money by making pipelines more reliable and easy to update. + +Over time, this approach is much more extensible than continuing to stack code on top of an unwieldy process. It’s also automatically documented, and using tests ensures the pipeline is resilient to changes over time. We continue mapping the data flow from the existing stored procedure to the dbt data pipeline, iterating until we achieve the same outputs as before. + +We’d love to hear your feedback! You can find us on [slack](https://www.getdbt.com/community/), [github](https://github.com/dbt-labs/dbt-core), or [reach out](https://www.getdbt.com/contact/) to our sales team. + +## Appendix + +dbt Labs has developed a number of related resources you can use to learn more about working in dbt, and comparing our approach to others in the Analytics ecosystem. + +- [Refactoring legacy SQL to dbt](https://docs.getdbt.com/tutorial/refactoring-legacy-sql) +- [The case for the ELT workflow](https://www.getdbt.com/analytics-engineering/case-for-elt-workflow/) +- [Refactoring SQL for modularity](https://courses.getdbt.com/courses/refactoring-sql-for-modularity) +- [Data modeling techniques for modularity](https://www.getdbt.com/analytics-engineering/modular-data-modeling-technique/) diff --git a/website/blog/2022-07-26-configuring-grants.md b/website/blog/2022-07-26-configuring-grants.md new file mode 100644 index 00000000000..5888f6ca782 --- /dev/null +++ b/website/blog/2022-07-26-configuring-grants.md @@ -0,0 +1,209 @@ +--- +title: "Updating our permissioning guidelines: grants as configs in dbt Core v1.2" +description: "End consumers (like users and BI tools) will need to be granted the privilege to read the tables and views dbt creates in your warehouse. In v1.2, we introduced a `grants` config that is easier to use than hooks and uses syntax that is database agnostic." + +slug: configuring-grants + +authors: [jeremy_cohen, doug_beatty] + +tags: [dbt tutorials] +hide_table_of_contents: false + +date: 2022-07-26 +is_featured: true +--- + +If you’ve needed to grant access to a dbt model between 2019 and today, there’s a good chance you’ve come across the ["The exact grant statements we use in a dbt project"](https://discourse.getdbt.com/t/the-exact-grant-statements-we-use-in-a-dbt-project/430) post on Discourse. It explained options for covering two complementary abilities: +1. querying relations via the "select" privilege +1. using the schema those relations are within via the "usage" privilege + + + +## The solution then +Prior to dbt Core v1.2, we proposed three possible approaches (each coming with [caveats and trade-offs](#caveats-and-trade-offs-of-the-original-guidance)): + +1. Using `on-run-end` hooks to `grant select on all` tables/views dbt has just built +1. Using `post-hook` to grant `select` on a model as soon as it’s built +1. Using either default grants (future grants on Snowflake) or a combination of `post-hooks` and `on-run-end` hooks instead + +These options were the state of the art... until today! + +## What’s changed? + +In v1.2, we [introduced](https://www.getdbt.com/blog/teaching-dbt-about-grants) a [`grants` config](https://docs.getdbt.com/reference/resource-configs/grants) that works a lot like `post-hook`, with two key differences: + +- You configure `grants` as a structured dictionary rather than writing all the SQL yourself +- dbt will take *the most efficient path* to apply those grants + +### Why `grants` are better than hooks + +First of all, [hooks are hard](#issues-related-to-hooks)! Especially that nonsense around [nested curlies](https://docs.getdbt.com/docs/building-a-dbt-project/dont-nest-your-curlies). + +#### A problem then +Let’s say you’ve been working on an incremental model. Previously, you granted access on this incremental model directly to `reporter`, so people can query it downstream: + +```sql +-- models/my_incremental_model.sql + +{{ config( + materialized = 'incremental', + post_hook = ["grant select on {{ this }} to reporter"] +) }} + +select ... +``` + +Over time, this model took on more and more responsibilities and you decided to refactor the incremental model to feed a series of dedicated views instead. Thoughtfully, you also removed the `post_hook` that granted direct access to the incremental model: + +```sql +-- models/my_incremental_model.sql + +{{ config(materialized = 'incremental') }} + +select ... +``` + +**The problem?** Until you `--full-refresh` it, your incremental model is still granted to the `reporter` role! + +#### The solution today + +dbt’s new `grants` implementation takes account of this. It knows whether grants are “carried over” when a model is re-run based on its materialization and your database. It makes up the difference between the existing grants and the ones you actually want. + +Try it out! + +```sql + +-- models/my_incremental_model.sql + +{{ config( + materialized = 'incremental', + grants = {'select': ['another_user']} +) }} + +select ... +``` + +Run that, verify that `another_user` can select from your model. Then change your model and run it again: + +```sql +-- models/my_incremental_model.sql + +{{ config( + materialized = 'incremental', + grants = {'select': []} +) }} + +select ... +``` + +If you check your database, you should see that *no one* can select from the incremental model. You could also see, in the debug-level logs, that dbt has run a `revoke` statement. + +(Note that, if `grants` is missing or set to `{}`, dbt will understand that you don’t want it managing grants for this table. So it’s best to explicitly specify the privilege, and that you want *no one* to have it!) + +Great! Now that you’re using the `grants` feature in dbt v1.2, you’ve just given this more thought than you should ever need to again 😎 + +## Is there still a place for hooks? + +Yes, indeed! Some areas that stand out: +- [Granting permissions on other object types](#granting-permissions-on-other-object-types) like granting usage on a schema +- [Advanced permissions](#advanced-permissions-or-other-operations) like row-level access + +### Granting permissions on other object types + +For now, it’s still necessary to grant `usage` on schemas to users that will need to select from objects in those schemas. Even though dbt creates schemas at the start of runs, there isn’t really a way to configure *schemas as their own objects* within dbt. + +Here's a couple ways you could approach it: +- Option A -- simple and familiar -- hooks to the rescue +- Option B -- too clever by half -- use the dbt graph to infer which schemas need "usage" + +#### Option A: simple and familiar + +```yaml +on-run-end: + # better as a macro + - "{% for schema in schemas %}grant usage on schema {{ schema }} to reporter;{% endfor %}" +``` + +Upside: Short, sweet, to the point. + +Downside: we need to repeat the same list of roles here that we specified in our `grants` config. + +#### Option B: Too clever by half + +Now that `grants` is a real config in dbt, available via dbt metadata, you can do all sorts of fun things with it. For instance, figure out which schemas have at least one object granting `select` to a role, and then grant `usage` on that schema to that role! + +```sql +-- macros/operations/reporting_grants.sql +{% macro grant_usage_on_schemas_where_select() %} + /* + Note: This is pseudo code only, for demonstration purposes + For every role that can access at least one object in a schema, + grant 'usage' on that schema to the role. + That way, users with the role can run metadata queries showing objects + in that schema (a common need for BI tools) + */ + {% set schema_grants = {} %} + {% if execute %} + {% for node in graph.nodes.values() %} + {% set grants = node.config.get('grants') %} + {% set select_roles = grants['select'] if grants else [] %} + {% if select_roles %} + {% set database_schema = node.database ~ "." ~ node.schema %} + {% if database_schema in database_schemas %} + {% do schema_grants[database_schema].add(select_roles) %} + {% else %} + {% do schema_grants.update({database_schema: set(select_roles)}) %} + {% endif %} + {% endif %} + {% endfor %} + {% endif %} + {% set grant_list %} + {% for schema in schema_grants %} + {% for role in schema_grants[schema] %} + grant usage on schema {{ schema }} to {{ role }}; + {% endfor %} + {% endfor %} + {% endset %} + {{ return(grant_list) }} +{% endmacro %} +``` + +This is certainly too clever -- but you get the idea, and an illustration of what's possible! + +You can even do this at the *start* of the run, right after dbt creates its schemas, rather than waiting until the end. (Although it’s not a huge deal to wait.) + +```yaml +on-run-start: + - {{ grant_usage_on_schemas_where_select() }} +``` + +### Advanced permissions (or other operations) + +Want to restrict access to specific rows in a table for specific users? Or dynamically mask column values depending on who’s asking? + +The approach varies by database: in Snowflake, you’ll still want a `post-hook` to apply a [row access policy](https://docs.snowflake.com/en/user-guide/security-row-intro.html) or a column [masking policy](https://docs.snowflake.com/en/sql-reference/sql/create-masking-policy.html) to your table whereas in Databricks you'd use [dynamic view functions](https://docs.databricks.com/security/access-control/table-acls/object-privileges.html#dynamic-view-functions). + +It’s good to have hooks and operations as a method to utilize cutting-edge database capabilities. Any cases that become a wide and clearly demonstrated need can be upgraded by being built into `dbt-core`. + +## Appendix + +### Caveats and trade-offs of the original guidance +`on-run-end` hooks: +> for the period of time between when a model runs, and the end of the run, no one will be able to query that model, instead they’ll get a “permission denied” error. This creates downtime in your BI tool.” + +`manage grants` privilege: +> It is worth noting that this privilege *is* a global privilege – now anyone using the `transformer` role can change grants on any object as though they are the owner of the object. Up to you if you’re comfortable with this! If not, you may want to use a combination of `post-hooks` and `on-run-end` hooks instead 🙂” + +The biggest problems: + +- Even if you wrote the [DRYest](https://en.wikipedia.org/wiki/Don't_repeat_yourself) code you could, there are still *thousands* of projects who have all written the same exact [DCL](https://en.wikipedia.org/wiki/Data_control_language) statements, wrapped in the same exact macros. +- Default + future grants—our original recommendation, back in 2019— are *tricky.* They often require extra permissions (superuser status!), they take effect automatically, and they don’t fly for folks at many organizations with tighter security policies. + +### Issues related to hooks +This is just a sample of the issues we've seen: +- [Post hooks that call macros get parsed with execute = False #2370](https://github.com/dbt-labs/dbt-core/issues/2370) +- [get_relation returns none in hook context #2938](https://github.com/dbt-labs/dbt-core/issues/2938) +- [this.is_view and this.is_table not working in BigQuery inside a hook #3529](https://github.com/dbt-labs/dbt-core/issues/3529) +- [custom table schema path of {{ this }} parsed in correctly in post-hook macro #3985](https://github.com/dbt-labs/dbt-core/issues/3985) +- [Post-hook doesn't resolve custom schema #4023](https://github.com/dbt-labs/dbt-core/issues/4023) +- [[CT-80] [Bug] post-hook macro generates SQL with incorrect source table #4606](https://github.com/dbt-labs/dbt-core/issues/4606) diff --git a/website/blog/2022-07-26-pre-commit-dbt.md b/website/blog/2022-07-26-pre-commit-dbt.md new file mode 100644 index 00000000000..3873e46e3ae --- /dev/null +++ b/website/blog/2022-07-26-pre-commit-dbt.md @@ -0,0 +1,268 @@ +--- +title: "Enforcing rules at scale with pre-commit-dbt" +description: "Making sure everyone is following best practices on large dbt projects is hard. How can you enforce rules at scale? Benoit Perigaud shares a dbt package to help you do just that." +slug: enforcing-rules-pre-commit-dbt +authors: [benoit_perigaud] +tags: [analytics craft] +hide_table_of_contents: false + +date: 2022-08-03 +is_featured: true +--- + +At dbt Labs, we have [best practices](https://docs.getdbt.com/docs/guides/best-practices) we like to follow for the development of dbt projects. One of them, for example, is that all models should have at least `unique` and `not_null` tests on their primary key. But how can we enforce rules like this? + +That question becomes difficult to answer in large dbt projects. Developers might not follow the same conventions. They might not be aware of past decisions, and reviewing pull requests in git can become more complex. When dbt projects have hundreds of models, it's hard to know which models do not have any tests defined and aren't enforcing your conventions. + + + +One potential solution is to leverage the open-source package [pre-commit-dbt](https://github.com/offbi/pre-commit-dbt), created by dbt community members, that can be used to automatically run tests before committing files to git or as part of CI steps. In this article, I'll walk you through the strategy I use to implement this package and enforce rules at scale. + +## What are pre-commit and pre-commit-dbt? + +pre-commit is a framework that can be used to automatically run tests before committing files to git, leveraging git hooks. + +In our case, we will use the ability of pre-commit to run automated tests but I will also explain below how to use it with the flags `--all-files` or `--files` to leverage the same tests on a predefined list of dbt models. + +On the other hand, pre-commit-dbt defines dbt specific tests and actions (called [hooks](https://github.com/offbi/pre-commit-dbt/blob/main/HOOKS.md)) for the [pre-commit](https://pre-commit.com/) framework. + +There are currently over 20 tests that have been created but here 2 examples that we will leverage: + +- `check-model-has-tests`: Check the model has a number of tests. +- `check-model-has-properties-file`: Check the model has a properties file (also called schema file). + +## Implementing pre-commit-dbt & adding tests + +Let’s take the example of a project with more than 300 models. Dozens of people have committed to the project, a PR review process is in place, but sometimes, with multiple models in the same PR, tracking if tests have been added or not is not easy and we know that not all models are tested today even if they should. + +To remediate this let’s follow those 4 steps: + +![Flow graph that describes the steps in defining a strategy for implementing this package on a dbt project with more than 300 models.](/img/blog/2022-07-26-pre-commit-dbt/define-strategy.png) + +### 1. Define our rules and create a pre-commit config file + +pre-commit-dbt provides a range of tests that can be run on the models of our dbt project. In the case of a project which has existed for some time and which might not be entirely following best practices, I would recommend selecting a small subset of tests, fixing the project and adding more tests later on. + +In our example, let’s just start by saying that we want: +- all our models to have been added to a YAML file +- all our models to include some tests + +To configure pre-commit, we have to create a file called `.pre-commit-config.yaml` at the root of our dbt project and add the following content: + +```yaml +repos: +- repo: https://github.com/offbi/pre-commit-dbt + rev: v1.0.0 + hooks: + - id: dbt-docs-generate + - id: check-model-has-properties-file + name: Check that all models are listed in a YAML file + files: ^models/ + - id: check-model-has-tests + name: Check that all models have tests + files: ^models/ +``` + +A few notes about this file: +- We start with a dbt-docs-generate to ensure that the command `dbt docs generate` is run before checking our models. This is required because pre-commit-dbt reads from the artifacts `catalog.json` and `manifest.json` and those files can be generated by generating the documentation +- The `files` argument is a regular expression. `^models/` is going to apply the test to all our models whose path starts with `models`, i.e. all the models of our project. If we wanted to run the test only for the models in the mart folder, we could write `^models/mart`. There are a few handy tools online to define and test regular expressions; one of them is https://regex101.com/ +- We could also provide values for the parameter `exclude` if we wanted to exclude specific files or folders +- We could have added a parameter to the hook `check-model-has-tests` to mention how many tests each model is supposed to have (see [here](https://github.com/offbi/pre-commit-dbt/blob/main/HOOKS.md#check-model-has-tests)) + +Now that we have defined our configuration file, the next step will depend on whether we are using dbt via dbt Cloud or dbt Core via the CLI. + +If we are using dbt Cloud, let’s jump to [step 4](#4-make-it-part-of-the-periodic-checks), where we will set up pre-commit-dbt as part of the CI process, otherwise, with dbt Core we can go to step 2. + +### 2. Understand the scope of the changes required + +With our configuration file created, we can now set up our computer to do some checks locally. + +#### Activating a Python virtual environment + +If we are using dbt in a Python virtual environment, let’s activate this environment. If not, we should really create a Python virtual environment ([more info here](https://docs.python.org/3/library/venv.html)) and activate it before installing pre-commit. + +We could technically skip this step but might then end up getting issues on our computer with different Python packages conflicting with each other. + +#### Installing and running pre-commit + +Once in the Python virtual environment, installing pre-commit is as straightforward as running `python -m pip install pre-commit`. + +A normal next step after installing pre-commit is to run a `pre-commit install` to install the git hooks and run tests automatically, but in our case, let’s wait a bit! We will cover this in step 4. + +Instead, we can do a `pre-commit run --all-files`, which will run all the tests defined in our configuration file on all the files in our dbt project. + +[![Animation showing the output in the Terminal after running the above commands](https://asciinema.org/a/lTmefht77ZEr6kmP7DymaxjRF.svg)](https://asciinema.org/a/lTmefht77ZEr6kmP7DymaxjRF) + +In my case, I can see that my model called `customers.sql` has not been added to any YAML file and has no test defined. + +In the case of a large project, the number of issues might be much bigger. If we use zsh as our shell, wildcard expansion can be used and we could run `pre-commit run --files models/mart/*` if we wanted to run all the checks only in the models stored under mart. + +### 3. Decide what needs to be fixed immediately + +Once we have the list of models that either don’t exist in the YAML files or that don’t have any test defined, we can decide if we want to fix all of them at once or not. + +What we will see in step 4 is that even if not all models are fixed at once, the CI step and the git hooks can lead to better project hygiene, forcing every model that is being modified to be tested. + +In my example above, with just one model to fix, it is easy to create a PR with the changes, but if hundreds of models show up, you might decide to only fix the most important ones at first (your mart for example) and fix the other ones later on. + +### 4. Make it part of the periodic checks +The last step of our flow is to make those pre-commit checks part of the day-to-day activities, running on the dbt models that are newly created or modified. That way, even if we don’t fix all our models at once, if they get modified at some points, tests will need to be added for the PR to be merged. + +Adding periodic pre-commit checks can be done in 2 different ways, through CI (Continuous Integration) actions, or as git hooks when running dbt locally + +#### a) Adding pre-commit-dbt to the CI flow (works for dbt Cloud and dbt CLI users) + +The example below will assume GitHub actions as the CI engine but similar behavior could be achieved in any other CI tool. + +As described before, we need to run a `dbt docs generate` in order to create updated artifacts used in the pre-commit hooks. + +For that reason, we will need our CI step to execute this command, which will require setting up a `profiles.yml` file providing dbt the information to connect to the data warehouse. Profiles files will be different for each data warehouse ([example here](https://docs.getdbt.com/reference/warehouse-profiles/snowflake-profile)). + +In our case, let’s create a file called `profiles.yml` at the root of our dbt project, with the following information: + +```yaml +​​jaffle_shop: + target: ci + outputs: + ci: + type: postgres + host: + user: + password: "{{ env_var('DB_PASSWORD') }}" + port: 5432 + dbname: + schema: ci + threads: 4 +``` + +We don’t want to save the password of our user in a clear text file. For that purpose, we use the ability to read it from an environment variable. The next step is to save the value of our password as a secret in GitHub. In our GitHub repository, under Settings > Security > Secrets > Action, let’s create a secret called DB_PASSWORD to store our sensitive password. + +Finally, we can create a new YAML file to define our GitHub action. e.g. `.github/workflows/pre_commit_checks.yml` The name is not important but this file must be saved under the folders `.github/workflows/` (create those if they don’t exist yet) + +```yaml +name: pre-commit-check + +on: + pull_request: + branches: + - main + +jobs: + pre-commit-pip: + name: Install pre-commit via pip + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: ['ubuntu-latest'] + python-version: [3.8] + + # Set environment variables used throughout workflow + env: + DBT_PROFILES_DIR: . + DB_PASSWORD: ${{ secrets.DB_PASSWORD }} + + steps: + + - name: Checkout branch + uses: actions/checkout@v2 + + # Using bash and pip to install dbt and pre-commit + # Update the dbt installation command to include the adapter you need + - name: Install dbt and pre-commit + shell: bash -l {0} + run: | + python -m pip install dbt-postgres pre-commit + + # This action will output all the files that are being created and modified in our PR + - name: Get changed files + id: get_file_changes + uses: trilom/file-changes-action@v1.2.4 + with: + output: ' ' + + # Transforming the output of get_file_changes to a string we can use for our next step + # We want to take in account both new files and files that have been modified + - name: Get changed .sql files in /models to lint + id: get_files_to_lint + shell: bash -l {0} + run: | + # Set the command in the $() brackets as an output to use in later steps + echo "::set-output name=files::$( + # Issue where grep regular expressions don't work as expected on the + # Github Actions shell, check dbt/models/ folder + echo \ + $(echo ${{ steps.get_file_changes.outputs.files_modified }} | + tr -s ' ' '\n' | + grep -E '^models.*[.]sql$' | + tr -s '\n' ' ') \ + $(echo ${{ steps.get_file_changes.outputs.files_added }} | + tr -s ' ' '\n' | + grep -E '^models.*[.]sql$' | + tr -s '\n' ' ') + )" + + # Finally run pre-commit + - name: Run pre-commit + shell: bash -l {0} + run: | + pre-commit run --files ${{ steps.get_files_to_lint.outputs.files }} +``` + +The code is documented and should be self-explanatory, in a nutshell, we perform the following steps: +- Mention that this action and all the steps should be run for every PR to main +- Retrieve the code from our PR +- Install dbt and pre-commit +- Identify the files modified in our PR and format them as a list of models separated by spaces +- Execute a `pre-commit run --files` on the models we just modified or created + +Once we push those changes to our repo to a custom branch and create a PR to main, we see the following: + +The GitHub action is running: + +![Screenshot of a GitHub action executing on a PR that is running the pre-commit-check test](/img/blog/2022-07-26-pre-commit-dbt/testing-running.png) + +The step fails because I missed some tests and it tells me what model is failing: + +![Screenshot of the errors logs for the failed pre-commit-check test on the PR shown previously](/img/blog/2022-07-26-pre-commit-dbt/error-logs.png) + +The result of the check is also shown in the PR directly: + +![Screenshot of the failed test shown directly in the PR "checks" interface](/img/blog/2022-07-26-pre-commit-dbt/checks-failed.png) + + +With that information, I could now go back to dbt, document my model customers and push those new changes to my repo for another check to be performed. + +We could set up rules that prevent any change to be merged if the GitHub action fails. Alternatively, this action step can be defined as merely informational. + +#### b) Installing the pre-commit git hooks (for dbt CLI users) + +If we develop locally with the dbt CLI, we could also execute `pre-commit install` to install the git hooks. What it means then is that every time we want to commit code in git, the pre-commit hooks will run and will prevent us from committing if any step fails. + +If we want to commit code without performing all the steps of the pre-hook we could use the environment variable SKIP or the git flag `--no-verify` as described [in the documentation](https://pre-commit.com/#temporarily-disabling-hooks). (e.g. we might want to skip the auto `dbt docs generate` locally to prevent it from running at every commit and rely on running it manually from time to time) + +And if we install the hooks and realize that we don’t want them anymore, we just need to delete the folder `.git/hooks/` + +#### c) So tests in CI, or git hooks locally? + +Those two configurations are not exclusive but complementary. +- Having the hooks set up locally ensures that all our models follow our conventions even before pushing them to our repo, ensuring that the CI step will pass correctly. +- And the GitHub action as CI test is a great safeguard for people using the dbt Cloud IDE or local developers who either have not installed the hooks or tried to push changes with the `--no-verify` flag + +![A meme that reads "Why not both?"](/img/blog/2022-07-26-pre-commit-dbt/why-not-both-meme.png) + +## Taking this solution further + +We now have a process to ensure that the rules we are setting around testing required in our dbt models are enforced through automated steps. + +What next? Going back to the diagram at the beginning of this post, we can now think of new rules we want to automate and modify our pre-commit file and GitHub actions to increase the quality of our dbt project. + +It is important though to keep in mind a good balance between setting enough rules and automation to ensure a project of good quality and setting too many of them, taking time from more value-added work and potentially slowing down the overall analytics development process. + +![A diagram that adds additional steps to the original diagram shown in the beginning of the article. This solution includes a cyclical step for continuously adding new rules and leveraging a SQL linter.](/img/blog/2022-07-26-pre-commit-dbt/next-strategy.png) + +- We could for example add SQLFluff as a SQL Linter to show us what SQL code is not following the rules that we have defined +- Or we could add more pre-commit-dbt checks like check-model-name-contract to make sure that all our model names are following the correct naming convention +- Or we could add a check on our YAML files to verify if they are all indented correctly + +If you have any questions about this process or want to share how you are using pre-commit and CI to increase the quality of your dbt project, feel free to jump in dbt Slack and post in [#i-made-this](https://getdbt.slack.com/archives/C01NH3F2E05) or [#dbt-deployment-and-orchestration](https://getdbt.slack.com/archives/CMZ2Q9MA9) ! diff --git a/website/blog/2022-07-27-getting-started-with-the-dbt-semantic-layer.md b/website/blog/2022-07-27-getting-started-with-the-dbt-semantic-layer.md new file mode 100644 index 00000000000..63253c7b9a3 --- /dev/null +++ b/website/blog/2022-07-27-getting-started-with-the-dbt-semantic-layer.md @@ -0,0 +1,173 @@ +--- +title: "Getting started with the dbt Semantic Layer" +description: "Heard about dbt Metrics or the dbt Semantic Layer and curious to give them a try? Callum McCann digs into what they are, walks through an example, and discusses how they all fit together!" +slug: getting-started-with-the-dbt-semantic-layer + +authors: [callum_mccann] + +tags: [dbt product updates] +hide_table_of_contents: false + +date: 2022-07-27 +is_featured: true +--- + +# Getting started with the dbt Semantic Layer + +> TLDR: The Semantic Layer is made up of a combination of open-source and SaaS offerings and is going to change how your team defines and consumes metrics. + +At last year's Coalesce, Drew showed us the future[^1] - a vision of what metrics in dbt could look like. Since then, we've been getting the infrastructure in place to make that vision a reality. We wanted to share with you where we are today and how it fits into the broader picture of [where we're going](https://www.getdbt.com/blog/dbt-semantic-layer). + +To those who haven't followed this saga with the intensity of [someone watching their investments on the crypto market](https://mobile.twitter.com/scannergr1/status/1536198701215109122/photo/1), we're rolling out this new resource to help you better understand the dbt Semantic Layer and provide clarification on the following things: + +1. What is the dbt Semantic Layer? +2. How do I use it? +3. What is publicly available now? +4. What is still in development? + +With that, lets get into it! + + + +> Some of you might have been around when this was initially being referred to as the Metrics Layer. As we evaluated the long term plans for what this part of dbt was going to become, we realized that naming it the Semantic Layer better reflected its capabilities and where we plan on taking it. + +## What is the dbt Semantic Layer? + +The dbt Semantic Layer is a new part of dbt to help improve precision and consistency while expanding flexibility and capability in the modern data stack. Our maestro of metrics, Drew Banin, [released a blog post detailing the vision of where we're going here](https://www.getdbt.com/blog/dbt-semantic-layer). The first use case that we are addressing is one that most practicioners **and** stakeholders are familiar with - metrics. We'll walk through what this looks like in practice later on in this post. + +Under the hood, the dbt Semantic layer is collection of several components - some of these are part of dbt Core, some part of dbt Cloud, and some are net new functionality. They all [combine together like Voltron](https://www.youtube.com/watch?v=5rPSLQxMT8w) to create a single experience through which business users can query data in the context of the metric that is most familiar to them. And the best part is that they can do it in systems they are already comfortable using. + +***What will this look like for my data consumers and business stakeholders?*** + +Ultimately, this looks like people being able to interact with trusted datasets in the tools that they are comfortable with (and eventually new tools designed specifically around metrics). + +An example that we’ve found helpful is [ARR](https://www.zuora.com/billing-topics/annual-recurring-revenue/#:~:text=Annual%20Recurring%20Revenue%2C%20or%20ARR,for%20a%20single%20calendar%20year). A business-critical metric to SaaS companies, ARR can be a tricky calculation to keep consistent across all of the tools used in the business. With the dbt Semantic Layer, this definition would live in dbt and the logic to create the dataset for that metric would be consistent across all different consuming experiences. Best of all, definition changes would get reflected in downstream tools, so you no longer need to manually search and update every downstream dependency. Callum of 3 years ago is jumping with joy. + +***That’s good and all, but what does this look like for practitioners to use?*** + +The dbt Semantic layer is comprised of the following components[^2]: + +**Available Today** + +- **[`metric` node in dbt Core :](https://docs.getdbt.com/docs/building-a-dbt-project/metrics)** Similar to `models` or `sources` , this is a specific node type in dbt Core. It is the definition of a time-series aggregation over a table that supports zero or more dimensions. The resulting node is stored in the `manifest.json` just like `models` and referenced in the DAG. +- **[`dbt_metrics` package:](https://github.com/dbt-labs/dbt_metrics)** this package provides macros that combine the version-controlled metric definition and query-time parameters (like dimensions, a time grain, and secondary calculations) to generate a SQL query which calculates the metric value. +- **[dbt Cloud Metadata API](https://docs.getdbt.com/docs/dbt-cloud/dbt-cloud-api/metadata/metadata-overview):** a GraphQL API which supports arbitrary queries over the metadata produced by dbt Cloud jobs. Contains metadata related to the accuracy, recency, configuration, and structure of the views and tables in the warehouse, as well as much more. + +**New** + +- **dbt Server:** this component wraps dbt Core in a persistent server that is responsible for handling RESTful API requests for dbt operations. It’s a thin interface that is primarily responsible for performance and reliability in production environments. +- **dbt Cloud proxy server:** this component enables dbt Cloud to dynamically rewrite requests to a data warehouse and compile dbt-SQL into raw SQL that the database understands. It then returns the dataset produced by the raw SQL to the platform that sent it. + +![Untitled](/img/blog/2022-07-27-getting-started-with-the-dbt-semantic-layer/semantic-layer-description.png) + +### Understanding how and when to use metrics? + +> Use of metrics and the metrics package is recommended for experienced dbt users and early adopters who want to explore this functionality. + +Let's walk through an example of how you can use the components above to get started today using our old friend - [the Jaffle Shop](https://github.com/dbt-labs/jaffle_shop_metrics). We'll take a look at how you can start defining and testing metrics today as well as how you'll interact with them once the new components are released. + +**When to use Metrics** + +The first question you need to ask is, *Should we be using metrics?* + +It is our belief that metrics are not a one-size fits all solution. They are designed for core business metrics where consistency and precision are of key importance, not for exploratory use cases or ad hoc analysis. Our shorthand way of determining whether the metric should be defined in dbt has been - *is this something our teams need to report on?* + +So, let’s say the CFO of our Jaffle comes to us on a Monday morning and commands the data team to overhaul how we're reporting on Revenue. Our Regional Manager Jim and Sales Director Pam[^3] have been giving him different reports! Right now its a mess of tools and inconsistencies - Jim’s numbers are defined in Tableau and say one thing, Pam’s within Hex and say another! The CFO is frustrated with it and wants a cohesive experience across the company where everyone has the same numbers for revenue. It passes the report test, it’s an important business metric; away we go! + +**Defining the Metric with Metric Node** + +In this example, we’ll say that both Jim and Pam are pulling from a table created by dbt called `orders`. It currently contains fields for `amount` and all different methods of payment_amounts, such as credit cards or gift cards. Jim has been calculating revenue by summing up the `credit_card_amount` and `gift_card_amount` fields, as he forgot to update his definition when the business added coupons and bank transfers payments. Meanwhile, Pam is correctly summing the `amount` field but hasn’t accounted for return orders that shouldn’t be counted! + +The first step is creating a unified definition for what revenue is. In order to do this, we will create the following yml definition within our dbt repo: + +```yaml +version: 2 + +metrics: + - name: revenue + label: Revenue + model: ref('orders') + description: "The total revenue of our jaffle business" + + type: sum + sql: amount + + timestamp: order_date + time_grains: [day, week, month, year] + + dimensions: + - customer_status + - has_coupon_payment + - has_bank_transfer_payment + - has_credit_card_payment + - has_gift_card_payment + + filters: + - field: status + operator: '=' + value: "'completed'" +``` + +This metric has now been defined in the dbt metadata and can be seen in the DAG! + +![Untitled](/img/blog/2022-07-27-getting-started-with-the-dbt-semantic-layer/metrics-dag.png) + +**Running The Metric Package To calculate the metric** + +In order to ensure that both Jim and Pam are retrieving the same numbers for their metric, we’ll need them to both run a metrics `calculate` query. In this example, we’re not interested in the specific payment types and only want to see revenue broken up by `week` and `customer_status`. + +```sql +select * +from {{ metrics.calculate( + metric('revenue'), + grain='week', + dimensions=['customer_status'] +) }} +``` +This would return a dataset that looks like this: + +| date_week | customer_status | revenue | +| --- | --- | --- | +| 2018-01-01 | Churn Risk | 43 | +| 2018-01-01 | Churned | 0 | +| 2018-01-01 | Healthy | 26 | +| 2018-01-08 | Churn Risk | 27 | + +Jim and Pam would then be able to reference the `revenue` column within the newly created dataset and never have to worry about the calculation of revenue ever again[^4]! The world is perfect and [balance has been restored.](https://www.youtube.com/watch?v=d1EnW4kn1kg) + +**In the near future with dbt Server** + +When dbt Server releases later this year, the flow of how metrics are consumed will change significantly. Your organization will no longer need to materialize each metric within a model in order to take advantage of the metric definition. Instead, you’ll be able to directly query dbt Server with the metric code provided and have the correct dataset returned to your BI tool of choice. + +Additionally, integration partners will have built out experiences around Metrics using the Metadata API to create unique and creative ways for consumers to obtain metric data while abstracting away complexity. For example, a box that allows the user to select from a list of metrics, time grains, dimensions, and secondary calculation and then have the correct information returned to them regardless of the selection! + +### So what is publicly available now? + +Right now, the two main open-source components that are publicly available are the [`metric` node](https://docs.getdbt.com/docs/building-a-dbt-project/metrics) within dbt Core and the `dbt_metrics` package. Combined, these two can operate an introductory semantic layer experience by allowing analytics engineers to define metrics and then query that metric via the metrics package. + +These two components are a static experience that have to be defined in the dbt project (as the selected dimensions are defined at model creation) but are useful for those who want to ensure that metrics remain consistent across every BI tool. If you identify with any of the following conditions, you could be a good fit for implementing this as it exists today: + +- You want to prepare your organization for the full Semantic Layer launch. +- Your organization has at least a few key metrics +- Your organization uses 1 or more BI tools +- Your organization occasionally has issues around different metric calculations +- Your organization wants a centralized location for all metrics so everyone in the business knows where to look + +All of these are great reasons to begin exploring implementing metrics in your dbt project! If you’re curious about what an implementation of this might look like, we recommend referencing the [jaffle_shop_metrics](https://github.com/dbt-labs/jaffle_shop_metrics) repo! + +### What is still in development? + +Both the dbt Cloud proxy server and dbt Server are currently in development, with a scheduled release of later this year. If you’re curious about testing them once they are released, we recommend keeping an eye on our product announcements and then reaching out once they become publicly available! + +### What if I have questions? + +If you have any questions about those components, or metrics in general, please feel free to post in the #dbt-metrics-and-server channel on dbt Slack! I hang around there and am always willing to chat metrics! + +### Footnotes +[^1]: That future may not have mentioned robots but I'm holding out for [Jetson's style morning machine](https://www.youtube.com/watch?v=-0S3Jf-NxdI) to help me get ready in the morning. + +[^2]: We’re specifically calling out the licensing because there is a lot of confusion in the community around what is open-source and what isn’t. This is only becoming trickier with the introduction of the BSL licensing, which ensures users can run their own server but it cannot be sold as a cloud service. For more information on why these licensing types were picked, we recommend [Tristan’s blog around licensing dbt.](https://www.getdbt.com/blog/licensing-dbt/). The big takeaway around licensing is that you can still run components of the dbt Semantic Layer even if you aren’t a dbt Cloud customer! + +[^3]: Full transparency, I've never seen the Office. The awkward humor makes me so uncomfortable that I have to turn off the TV. Apologies if the titles of the characters are incorrect. + +[^4]: Psych! They’re definitely interested in the calculation of ARR. In fact, they don’t really trust the numbers **unless** they understand how it’s calculated. This is where they could use the Metadata API in order to query all the information about the metric, such as definition, run-time, acceptable dimensions, etc. Right now Jim and Pam would need to query the API directly but in the future we expect there to be a number of different ways to obtain this information, ranging from [direct integration with the BI tool](https://learn.hex.tech/docs/connect-to-data/data-connections/dbt-integration) all the way to having that information materialized in a dbt information schema! *For current tabular alternatives, there are some interesting macros in the newly released [dbt-project-evaluator package](https://github.com/dbt-labs/dbt-project-evaluator). Take a look there if you’re curious about materializing your metric information!* \ No newline at end of file diff --git a/website/blog/2022-08-12-how-we-shaved-90-minutes-off-long-running-model.md b/website/blog/2022-08-12-how-we-shaved-90-minutes-off-long-running-model.md new file mode 100644 index 00000000000..09cb9c4c178 --- /dev/null +++ b/website/blog/2022-08-12-how-we-shaved-90-minutes-off-long-running-model.md @@ -0,0 +1,293 @@ +--- +title: "How we shaved 90 minutes off our longest running model" +description: "Monitoring large, complex projects can be difficult. When you're running 1,000+ models in a day, how do you know which of those consistently take the longest to run? In this article, Bennie Regenold and Barr Yaron show the benefits of the Model Timing tab in dbt Cloud." +slug: how-we-shaved-90-minutes-off-model +authors: [bennie_regenold, barr_yaron] +tags: [analytics craft] +hide_table_of_contents: false + +date: 2022-08-18 +is_featured: true +--- + +When running a job that has over 1,700 models, how do you know what a “good” runtime is? If the total process takes 3 hours, is that fantastic or terrible? While there are many possible answers depending on dataset size, complexity of modeling, and historical run times, the crux of the matter is normally “did you hit your SLAs”? However, in the cloud computing world where bills are based on usage, the question is really “did you hit your SLAs _and stay within budget_”? + +Here at dbt Labs, we used the Model Timing tab in our internal analytics dbt project to help us identify inefficiencies in our incremental dbt Cloud job that eventually led to major financial savings, and a path forward for periodic improvement checks. + + + +## Your new best friend: The Model Timing tab + +The dbt Labs internal project is a beast! Our daily incremental dbt Cloud job runs 4x/day and invokes over 1,700 models. We like to sift through our dbt Cloud job using the [Model Timing](https://docs.getdbt.com/docs/dbt-cloud/using-dbt-cloud/cloud-model-timing-tab) tab in dbt Cloud. The `Model Timing` dashboard displays the model composition, order, and run time for every job run in dbt Cloud (for team and enterprise plans). The top 1% of model durations are automatically highlighted, which makes it easy to find bottlenecks in our runs. You can see that our longest running model stuck out like a sore thumb -- here's an example of our incremental job before a fix was applied: + +![Model Timing tab before picture](/img/blog/2022-08-12-model-timing/model_timing_before.png) + +As you can see, it's straightforward to identify the model that's causing the long run times and holding up other models. The model `fct_dbt_invocations` takes, on average, 1.5 hours to run. This isn't surprising, given that it's a relatively large dataset (~5B records) and that we're performing several intense SQL calculations. Additionally, this model calls an [ephemeral model](https://docs.getdbt.com/docs/building-a-dbt-project/building-models/materializations#ephemeral) named `dbt_model_summary` that also does some heavy lifting. Still, we decided to explore if we could refactor this model and make it faster. + +After refactoring this code, we ended up swapping the ephemeral model `dbt_model_summary` to an incremental model that took the bulk of the processing out of the main `fct_dbt_invocations` model. Instead of recalculating this complex logic every run, we pull only new data and run that logic on the smaller subset of those records. The combined run time of the new `dbt_model_summary` and `fct_dbt_invocations` is now ~15-20 minutes, a savings of over an hour per run! + +![Model Timing tab after picture](/img/blog/2022-08-12-model-timing/model_timing_after.png) + +## Identifying the problem + +This project runs on Snowflake, so all the examples below show the Snowflake UI. However, it is possible to do a similar style of analysis in any data warehouse. + +Also, this blog post represents a pretty technical deep dive. If everything you read here doesn't line up immediately, that's ok! We recommend reading through this article, then brushing up on cloud data warehouses and query optimization to help supplement the learnings here. + +### Unpacking the query plan + +Finding this long running query was step one. Since it was so dominant in the Model Timing tab, it was easy to go straight to the problematic model and start looking for ways to improve it. The next step was to check out what the Snowflake query plan looked like. + +There are a few ways you can do this: either find the executed query in the `History` tab of the Snowflake UI, or grab the compiled code from dbt and run it in a worksheet. As it’s running, you can click on the `Query ID` link to see the plan. More details on this process are available in your provider’s documentation ([Snowflake](https://docs.snowflake.com/en/user-guide/ui-query-profile.html), [BigQuery](https://cloud.google.com/bigquery/docs/query-plan-explanation), [Redshift](https://docs.aws.amazon.com/redshift/latest/dg/c-the-query-plan.html), [Databricks](https://docs.databricks.com/sql/admin/query-profile.html)). + +Below you can see the query plan for `fct_dbt_invocations`, which includes the logic from `dbt_model_summary`: + +![Snowflake query plan](/img/blog/2022-08-12-model-timing/snowflake_query_plan.png) + +From the query profile, it was easy to find the issue. There are two window functions that account for over 90% of the run time when we factor in the table scan needed to retrieve the data. Additionally, there is nearly 1TB worth of data that is [spilled to remote storage](https://github.com/dbt-labs/docs.getdbt.com/discussions/1550) as part of this query. Within Snowflake, [remote storage is considerably slower](https://docs.snowflake.com/en/user-guide/ui-query-profile.html?_ga=2.162889724.1914632094.1659383329-1610273913.1651521575&_gac=1.229438062.1658341107.Cj0KCQjwz96WBhC8ARIsAATR2516I_11uMuOf0cXXe0zlyOBUXLap5CfVvKnpGwTb3bLqC5tHwlurxcaAskEEALw_wcB#queries-too-large-to-fit-in-memory:~:text=This%20spilling%20can%20have%20a%20profound%20effect%20on%20query%20performance%20(especially%20if%20remote%20disk%20is%20used%20for%20spilling).%20To%20alleviate%20this%2C%20we%20recommend%3A) to both write and read from, so any data that’s on the remote drive will really slow down a query. We’ve found the problem! + +### Understanding the data + +Once we identified the issue, we had to find a way to fix it. + +First, it’s good to have a high level understanding of the underlying data for `fct_dbt_invocations`. Any time you issue a command to dbt (run, test, build, snapshot, etc.), we track certain pieces of metadata about that run. We call these “invocations,” and as you can imagine, dbt is invoked *a lot*. The table this query is running against is filtered, but still has somewhere in the neighborhood of 5 billion rows. The relevant pieces of data that we are using in this query include project IDs, model IDs, and an anonymized hash key representing the raw model contents to know if a model changed. + +If you’re curious, here’s a look at the query for `dbt_model_summary` before any changes were made: + +```sql +{{config(materialized = 'ephemeral')}} + +with model_execution as ( + + select * from {{ ref('stg_dbt_run_model_events') }} + +), + +diffed as ( + + select *, + + row_number() over ( + partition by project_id, model_id + order by dvce_created_tstamp + ) = 1 as is_new, + + /* + The `mode` window function returns the most common content hash for a + given model on a given day. We use this a proxy for the 'production' + version of the model, running in deployment. When a different hash + is run, it likely reflects that the model is undergoing development. + */ + + contents != mode(contents) over ( + partition by project_id, model_id, dvce_created_tstamp::date + ) as is_changed + + from model_execution + +), + +final as ( + + select + invocation_id, + max(model_complexity) as model_complexity, + max(model_total) as count_models, + sum(case when is_new or is_changed then 1 else 0 end) as count_changed, + sum(case when skipped = true then 1 else 0 end) as count_skip, + sum(case when error is null or error = 'false' then 0 else 1 end) as count_error, + sum(case when (error is null or error = 'false') and skipped = false then 1 else 0 end) as count_succeed + + from diffed + group by 1 + +) + +select * from final +``` + +The window functions referenced above are answering the following questions: + +- `row_number()` + - *Is this the first time that this specific model has run in a project?* + - Note: this grain is at the project level +- `mode()` + - *Is this the most frequent version of the model that ran today (based on the hashed contents)?* + - Note: this grain is at the model + run date level + +## Moving to solutions + +### Attempt #1: Optimizing our objects and materializations + +Given the size and complexity of this query, the first few approaches we took didn’t focus on changing the query as much as optimizing our objects and materializations. + +The two window functions (`row_number()` and `mode()` in the `diffed` above) were in an [ephemeral model](https://docs.getdbt.com/docs/building-a-dbt-project/building-models/materializations#ephemeral) which isn’t stored in the data warehouse, but is instead executed in-memory at run time. Since it was obvious our virtual warehouse was running out of memory (remote storage spillage), we tried swapping that to a view, then a table materialization. Neither of these improved the run time significantly, so we tried clustering the table. However, since our two window functions are at different grains there wasn’t a great clustering key we found for this. + +### Attempt #2: Moving to an incremental model + +The final strategy we tried, which ended up being the solution we implemented, was to swap the ephemeral model (`dbt_model_summary`) to an [incremental model](https://docs.getdbt.com/docs/building-a-dbt-project/building-models/configuring-incremental-models). Since we’re calculating metrics based on historical events (**first** model run, most frequent model run **today**), an incremental model let us perform the calculation for all of history once in an initial build, then every subsequent build only needs to look at a much smaller subset of the data to run it’s calculations. + +One of the biggest problems with the ephemeral model was remote spillage due to lack of memory, so having a smaller dataset to run the calculation against made a massive impact. Snowflake can easily calculate a daily mode or a first model run when we only had to look at a sliver of the data each time. + +Swapping from ephemeral to incremental can be simple, but in this case we are calculating at two grains and need more than just the data loaded since the prior run. + +- `row_number()` + - To get the first time a model was run, we need every invocation of that model to see if this is the first one. Still, we don’t need the full history, just the subset that changed today. This is handled in the `new_models` CTE you can see below. +- `mode()` + - Since we’re calculating a daily mode, we actually need the full day’s worth of data every time this incremental model runs. We do that by applying the `::date` operator to our incremental logic to always pull a full days (or multiple days) worth of history each time. + +This let to slightly more complex logic in the model, as you can see below: + +```sql +{{config(materialized = 'incremental', unique_key = 'invocation_id')}} + +with model_execution as ( + + select * + from {{ ref('stg_dbt_run_model_events') }} + where + 1=1 + {% if target.name == 'dev' %} + + and collector_tstamp >= dateadd(d, -{{var('testing_days_of_data')}}, current_date) + + {% elif is_incremental() %} + + --incremental runs re-process a full day everytime to get an accurate mode below + and collector_tstamp > (select max(max_collector_tstamp)::date from {{ this }}) + + {% endif %} + +), + +{# When running rull refresh we have access to all records, so this logis isn't needed #} +{% if is_incremental() %} +new_models as ( + + select + project_id, + model_id, + invocation_id, + dvce_created_tstamp, + true as is_new + from {{ ref('stg_dbt_run_model_events') }} as base_table + where + exists ( + select 1 + from model_execution + where + base_table.project_id = model_execution.project_id + and base_table.model_id = model_execution.model_id + ) + qualify + row_number() over(partition by project_id, model_id order by dvce_created_tstamp) = 1 + + +), +{% endif %} + +diffed as ( + + select model_execution.*, + + {% if is_incremental() %} + + new_models.is_new, + + {% else %} + + row_number() over ( + partition by project_id, model_id + order by dvce_created_tstamp + ) = 1 as is_new, + + {% endif %} + + /* + The `mode` window function returns the most common content hash for a + given model on a given day. We use this a proxy for the 'production' + version of the model, running in deployment. When a different hash + is run, it likely reflects that the model is undergoing development. + */ + + model_execution.contents != mode(model_execution.contents) over ( + partition by model_execution.project_id, model_execution.model_id, model_execution.dvce_created_tstamp::date + ) as is_changed + + from model_execution + {% if is_incremental() %} + left join new_models on + model_execution.project_id = new_models.project_id + and model_execution.model_id = new_models.model_id + and model_execution.invocation_id = new_models.invocation_id + and model_execution.dvce_created_tstamp = new_models.dvce_created_tstamp + {% endif %} + +), + +final as ( + + select + invocation_id, + max(collector_tstamp) as max_collector_tstamp, + max(model_complexity) as model_complexity, + max(model_total) as count_models, + sum(case when is_new or is_changed then 1 else 0 end) as count_changed, + sum(case when skipped = true then 1 else 0 end) as count_skip, + sum(case when error is null or error = 'false' then 0 else 1 end) as count_error, + sum(case when (error is null or error = 'false') and skipped = false then 1 else 0 end) as count_succeed + + from diffed + group by 1 + +) + +select * from final +``` + +The astute reader will notice that the entire `new_models` CTE is wrapped in an `{% if is_incremental() %}` block. That’s because when the model is ran incrementally we need the full history of model runs for the given model. This means we have to join back to the main table to get that full history. However, when we’re running this as a full refresh (or on the initial load), we already have the full history of runs in the query, so we don’t need to join back to the table. This additional piece of `{% if is_incremental() %}` dropped the full refresh run time down from over 2 hours to just under 30 minutes. This is a one time savings (or however often we have to full refresh), but is well worth the slightly more complex logic. + +## Difficulty with testing + +A major challenge in testing and implementing our changes was the volume of data needed for comparison testing. Again, the biggest problem we had was that our virtual warehouse was running out of memory, so trying to do performance testing on a subset of the data had misleading results (our testing was a subset of 10 million records). Since this query runs just fine on a small set of data (think the incremental runs), when we were initially trying to performance test the new vs old it looked like there was no real benefit to the incremental model. This led to many wasted hours of trying to figure out why we weren’t seeing an improvement. + +Eventually, we figured out that we needed to test this on the full dataset to see the impact. In the cloud warehousing world where you pay-for-use this has very easy to track cost implications. However, you have to spend money to make money, so we decided the increased cost associated with testing this on the full dataset was worth the expense. + +To start with, we [cloned](https://docs.snowflake.com/en/sql-reference/sql/create-clone.html) the entire prod schema to a testing schema, which is a free operation in Snowflake. Then, we did an initial build of the new `dbt_model_summary` model since it was switching from ephemeral to incremental. Once that was complete, we were able to delete out a few days worth of data from both `dbt_model_summary` and `fct_dbt_invocations` to see how long an incremental run would take. This represented the true day-to-day runs, and the results were fantastic! The combined run time of both models dropped from 1.5 hours to 15-20 minutes for incremental runs. + +## Benefits of the improvement + +The end result of this improvement saves a nice chunk of change. Since this query was running 4 times per day and took 1.5 hours per run, this change is saving roughly 5 hours per day in run time. Given that this on Snowflake, we can calculate the savings based on their public pricing. Currently for the Enterprise edition of Snowflake it costs $3/credit, and a medium warehouse consumes 4 credits/hour. Putting this all together, that’s a savings of ~$1800/month. + +The cost savings are great, but there are two other “time based” benefits that come from faster runs: + +1. Since this process runs 4 times daily, there is a limit to the length any given run can take, and in turn how many metrics we can calculate. By saving time on the longest running metrics it frees up runtime for us to add new logic to our runs. This generally leads to happier end consumers because they get more information to work with. +2. If the need ever arises to refresh our data more frequently, we now have some runway to do that. While these particular models will never be near-real-time, we could realistically get more up-to-date information since we can now process the data faster. + +## Conclusion + +Developing an analytic code base is an ever-evolving process. What worked well when the dataset was a few million records may not work as well on billions of records. As your code base and data evolve, be on the lookout for areas of improvement. This article showed a very specific example around two models, but the general principals can be applied to any code base: + +1. **Periodically review your run times** + + This is made easy with the [Model Timing tab](https://docs.getdbt.com/docs/dbt-cloud/using-dbt-cloud/cloud-model-timing-tab) in dbt Cloud. You can quickly go to any run to see the model composition, order, and run time for every run in dbt Cloud. The longest running models stick out like a sore thumb! + +2. **Use the query analyzer from your data warehouse** + + Once you’ve found the problematic model (or models!), use the query analyzer to find which part of the model takes the longest to run. The graphical tree provided gives you a more fine grained view into what is going on. Some tips to look out for: + + - Window functions on large data sets + - Cross joins + - OR joins + - Snowflake specifically: spilling to remote disk +3. **Try a few different approaches** + + There is seldom one solution to a problem, especially in a system as complex as a data warehouse. Don’t get too bogged down on a single solution, and instead try a few different strategies to see their impact. If you can’t commit to fully rewriting the logic, see if clustering/partitioning the table will help. Sometimes a bigger warehouse really is the solution. If you don’t try, you’ll never know. + +4. **Test on representative data** + + Testing on a [subset of data](https://docs.getdbt.com/guides/legacy/best-practices#limit-the-data-processed-when-in-development) is a great general practice. It allows you to iterate quickly, and doesn’t waste resources. However, there are times when you need to test on a larger dataset for problems like disk spillage to come to the fore. Testing on large data is hard and expensive, so make sure you have a good idea of the solution before you commit to this step. + +5. **Repeat** + + Remember that your code and data evolves and grows. Be sure to keep an eye on run times, and repeat this process as needed. Also, keep in mind that a developer’s time and energy are a cost as well, so going after a handful of big-hitting items less frequently may be better than constantly rewriting code for incremental gains. diff --git a/website/blog/2022-08-17-managing-surrogate-keys-in-dbt.md b/website/blog/2022-08-17-managing-surrogate-keys-in-dbt.md new file mode 100644 index 00000000000..cae25bc4b96 --- /dev/null +++ b/website/blog/2022-08-17-managing-surrogate-keys-in-dbt.md @@ -0,0 +1,230 @@ +--- +title: "Surrogate keys in dbt: Integers or hashes?" +description: "Wondering how to build a data model with surrogate keys? Dave Connors walks you through two strategies." +slug: managing-surrogate-keys + +authors: [dave_connors] + +tags: [analytics craft] +hide_table_of_contents: false + +date: 2022-08-24 +is_featured: true +--- + +Those who have been building data warehouses for a long time have undoubtedly encountered the challenge of building surrogate keys on their data models. Having a column that uniquely represents each entity helps ensure your data model is complete, does not contain duplicates, and able to join across different data models in your warehouse. + +Sometimes, we are lucky enough to have data sources with these keys built right in — Shopify data synced via their API, for example, has easy-to-use keys on all the tables written to your warehouse. If this is not the case, or if you build a data model with a compound key (aka the data is unique across multiple dimensions), you will have to rely on some strategy for creating and maintaining these keys yourself. How can you do this with dbt? Let’s dive in. + + + +## How were surrogate keys managed in the past? + +Before the advent of the analytical warehouse tools we use today, the data warehouse architecture had a few key constraints that led to the rise of the Kimball-style warehouse with a snowflake schema. This was because storage was expensive — it was more efficient to store data as few times as possible, and rely on joins to connect data tog ether when a report required it. And to make those joins efficient, it became standard practice to use **monotonically increasing integer surrogate keys (MIISKs)**, a fancy way to say “count each record starting at one” so that your data model would look something like this (you are a cheesemonger): + +| product_id | product_name | created_by | created_at | +| --- | --- | --- | --- | +| 1 | mozzarella | 23 | 0001-05-05 | +| 2 | cheddar | 24 | 1150-02-03 | +| 3 | gruyere | 25 | 1655-04-03 | + +| order_line_id | order_id | product_id | amount | created_at | +| --- | --- | --- | --- | --- | +| 1 | 1 | 3 | 40 | 2022-07-01 | +| 2 | 2 | 1 | 50 | 2022-07-05 | +| 3 | 3 | 1 | 10 | 2022-07-07 | +| 4 | 3 | 2 | 30 | 2022-07-07 | + +| order_id | customer_id | created_at | +| --- | --- | --- | +| 1 | 5 | 2022-07-01 | +| 2 | 8 | 2022-07-05 | +| 3 | 10 | 2022-07-07 | + +There are some clear benefits here! + +- There are clear, intuitive relationships between these entities! +- The fact that the keys here are small integers, the database can a) not worry about storage costs for this data b) index this field easily, making joins quick and efficient. + +However, there are also some clear maintenance issues here. Making updates to, say, your products table will require some careful surgical work to ensure the association of cheddar to id 2 is never accidentally changed. You may have heard of the phrase “load your dims before your facts” — this refers to the careful work required to maintain this referential integrity. Additionally, you need to know about the *exact state of the data* before making any updates. This data is **stateful**, making it rigid and more difficult to work with should there be any losses to this data. Imagine trying to rebuild these relationships from scratch! + +## MIISKs in dbt + +If this is your preferred modeling approach, dbt can absolutely support this workflow! This will likely require you to take advantage of built-in warehouse functionality to generate these MIISKs — in Snowflake, we can use [sequences](https://docs.snowflake.com/en/user-guide/querying-sequences.html), which are objects built exactly for this purpose. We’ll use Snowflake as the example here, but this approach can likely be adapted for other warehouses as well. + +### Creating and maintaining sequences + +In order to properly maintain the sequence of the surrogate keys in your data models, we’ll need to build and maintain a sequence for each table that needs one. In order to do this at scale, we’ll make use of the [meta](https://docs.getdbt.com/reference/resource-configs/meta) config of dbt model. This configuration allows you to define any metadata dictionary that you want. Using this, we can programmatically apply a surrogate key configuration for each model that needs one, and reference that configuration in a macro to properly create and update surrogate keys when necessary. + +Here’s an example configuration: + +```yaml +# assign the surrogate key config to your model + +version: 2 + +models: + - name: dim_customers + description: all customers + config: + meta: + surrogate_key: true +``` + +This metadata can then be leveraged in a macro in an `on-run-start` operation to ensure all sequences exist for all models that need one before the models execute. + +```yaml +# in macros/generate_sequences.sql + +{% macro generate_sequences() %} + + {% if execute %} + + {% set models = graph.nodes.values() | selectattr('resource_type', 'eq', 'model') %} + {# parse through the graph object, find all models with the meta surrogate key config #} + {% set sk_models = [] %} + {% for model in models %} + {% if model.config.meta.surrogate_key %} + {% do sk_models.append(model) %} + {% endif %} + {% endfor %} + + {% endif %} + + {% for model in sk_models %} + + {% if flags.FULL_REFRESH or model.config.materialized == 'table' %} + {# regenerate sequences if necessary #} + + create or replace sequence {{ model.database }}.{{ model.schema }}.{{ model.name }}_seq; + + {% else %} + {# create only if not exists for incremental models #} + + create sequence if not exists {{ model.database }}.{{ model.schema }}.{{ model.name }}_seq; + + {% endif %} + + {% endfor %} + +{% endmacro %} + +``` + +You can see in the above macro that we’re baking a naming convention here — for any model, the name of the sequence will exist in the same database and schema and follow the naming convention `_seq`. Adhering to this pattern allows us to also create an easy macro to increment the sequences in our model definitions without having to hard code the sequence name in every model that needs a surrogate key. + +```yaml +# in macros/increment_sequence.sql + +{%- macro increment_sequence() -%} + + {{ this.name }}_seq.nextval + +{%- endmacro -%} +``` + +So your model code looks like: + +```yaml +# in dim_customers +... + +with cte_name as ( + ... +) +... + +select + + {{ increment_sequence() }} as customer_id, + first_name, + last_name + +from cte_name + +... +``` + +### Caveats + +Despite the relative simplicity of this strategy, there are a handful of drawbacks with regard to making sure these sequences work the way we want them to. + +- **dbt Run errors -** If an incremental model that has surrogate keys maintained in this way *fails* due to some SQL error, we may end up with gaps in our surrogate key. When dbt goes to execute the model, the sequence is queried, and therefore incremented, but the model failure prevents changes to the target table model. That means the next time we run the model, the incremental model will start on the wrong value, and we may end up with a column that looks like this: + + | surrogate_key_id | + | --- | + | 1 | + | 2 | + | 3 | + | 4 | + | 5 | x + | 8 | + + In fact, most cloud platforms [can’t guarantee](https://docs.snowflake.com/en/user-guide/querying-sequences.html#:~:text=Snowflake%20does%20not%20guarantee%20generating%20sequence%20numbers%20without%20gaps.%20The%20generated%20numbers%20consistently%20increase%20in%20value%20(or%20decrease%20in%20value%20if%20the%20step%20size%20is%20negative)%20but%20are%20not%20necessarily%20contiguous) that sequences will be generated without gaps because of their use of parallel processing, even if we *don’t* have a dbt run error — because queries will be spread across multiple compute clusters, each step might query the sequence at different times, which makes it possible to have an out of order sequence result. This is a major consideration in using sequences — if that’s a deal breaker, you may need additional SQL logic in our models (like a `row_number()` function) to guarantee your keys are monotonically increasing. + +- **Views -** Because sequences in Snowflake increment on every query, using them as the surrogate keys for views would mean every time the view is queried, the sequence would increment and therefore change. This strategy would only work for table or incremental models. +- **Ordering -** Since sequences will be regenerated on every run for tables, and every time an incremental model is regenerated, the order of the resulting query determines which records get assigned to each key. In order to maintain referential integrity (i.e. product_id 1 always means mozzarella), you need to build in `ORDER BY` statements to your models. This can cause adverse performance during table builds. +- **“Load your dims before your facts” -** This strategy can also lead to some very messy DAGs in order to keep relationships intact in your project. As mentioned above, it’s imperative that each product record results in the same surrogate key value every time dbt is run. Additionally, this means that any table that needs to read from this table needs to run downstream of that initial process. This can lead to bottlenecks at runtime. + +Even though configuring MIISKs with sequences can be pretty well automated, it’s a bit of a brittle process that relies on a lot of assumptions and requires a whole lot of bandwidth from the data team to recreate the warehouse should anything go haywire. + +## Hashed surrogate keys + +An alternative to using the traditional MIISK strategy is to use cryptographic hashing functions to *derive the surrogate key values from the data itself,* a fancy way of saying “create a random string for every unique combination of values you find in my table”. These hashing functions are **deterministic**, meaning the same set of inputs will always produce the same output. In our SQL models, we can pass the column or columns that represent to the grain to this hashing function and voilà, a consistent, unique identifier is generated automatically! This has been packaged up in the `surrogate_key()` macro in the `dbt_utils` package ([source](https://github.com/dbt-labs/dbt-utils#surrogate_key-source)), and works across warehouse providers! Check out our SQL Magic post that dives deeper into this function [here](https://docs.getdbt.com/blog/sql-surrogate-keys). + +```sql +# in models/reports/daily_user_orders.sql +with + +orders as ( + select * from {{ ref('fct_orders') }} +), + +agg as ( + + select + date_trunc(day, order_date) as report_date + user_id, + count(*) as total_orders + from orders + group by 1,2 + +), + +final as ( + + select + {{ dbt_utils.surrogate_key([ + 'report_date', + 'user_id' + ]) + }} as unique_key, + * + from agg + +) + +select * from final +``` + +Using hashed keys makes our transformations — every dbt run results in the same exact outputs every time. I can safely delete all my non-source objects in my warehouse, execute a dbt run and be right back where I started (though I wouldn’t necessarily recommend this 😅). + +The analytical warehouses we use now no longer have the same constraints that traditional warehouses had — joins on strings aren’t notably less performant than those on integers, and storing slightly larger values in the surrogate key column is peanuts given the relative cost of storage on these platforms. This strategy also removes the need for tight coupling of transformations to propagate the surrogate key values across our project — anywhere the inputs for the surrogate keys are present, the hashing function produces the same keys, so we can take advantage of parallel processing in our warehouse and avoid the bottlenecks we had before. + +### Caveats + +This strategy is not without its caveats either! + + +- **Collisions -** Although it's *exceedingly* rare, depending on the hashing algorithm you use, it's possible for two different sets of inputs to produce the same outputs, causing erroneous duplicate records in your dataset. Using an MD5 hash (the default for the `dbt_utils.surrogate_key` macro), you have a 50% of a collision when you get up to 2^64 records (1.84 x 10E19 aka a whole lot of data). While [very very very unlikely](https://docs.getdbt.com/terms/surrogate-key#a-note-on-hashing-algorithms), it’s certainly something to consider for truly massive datasets. +- **Datatypes -** If you’re in the process of migrating legacy code to a new warehouse provider, you likely have some constraints on the datatype of your keys from the consumers of your datasets, and may have some issues converting to a string-based key. Luckily, some warehouse providers have hash functions that output integer values (like Snowflake’s `MD5_UPPER/LOWER_64` functions). However, these have fewer bits in the hashing function, so may lead to collision issues on big data sets. +- **Performance -** Hashed keys generally result in long string-type values. On massive datasets on some warehouses, this could cause some performance issues. Unlike MIISKs, string values can’t be easily partitioned to improve query performance. Luckily, as described in the above bullet point, you can choose to utilize hashing functions that output other, more performant datatypes! +- **Storage -** As mentioned above, hash keys will end up with higher storage costs than their MIISK counterparts. Given that the cost of storage in cloud warehouses is extremely cheap, it’s unlikely to be worth the effort to optimize for storage costs. + +## OK, so which one? + +Surrogate keys are a critical component of a logical data model, and as with most anything, you’ve got options when it comes to generating and maintaining them with dbt. Your business’s unique constraints with respect to maintenance overhead, performance, and data size will likely be the primary drivers for your decision. It will also be important to consider your stakeholders’ needs — are they used to seeing data in a particular format? are there one hundred dashboards that will explode if you change some keys from an integer to a string? For many orgs, this is a non-trivial decision! + +For my money, the simplicity of using hashed keys far outweighs the potential benefits of having MIISKs in your data model. Building with dbt works best when all parts of your project are idempotent, and hashed keys require close to zero maintenance. The cost of time spent rebuilding your surrogate keys in your data models if you can’t recreate them with a simple `dbt run` usually offsets any modest performance and storage gains you might be able to achieve with MIISKs. + +Big thanks to [Mike Fuller](https://github.com/mikegfuller) and [Bennie Regenold](https://github.com/bennieregenold7) for help ideating on this blog! diff --git a/website/blog/2022-08-22-narrative-modeling.md b/website/blog/2022-08-22-narrative-modeling.md new file mode 100644 index 00000000000..71252279873 --- /dev/null +++ b/website/blog/2022-08-22-narrative-modeling.md @@ -0,0 +1,236 @@ +--- +title: "Narrative modeling: How structure can tell a story" +description: "Analytics engineers work in the space between technical and business understanding, but tried-and-true modeling patterns often default to the technical. In this article, Ian Fahey makes a case for a pattern of modeling that follows the narrative of the business it represents." +slug: narrative-modeling +authors: [ian_fahey] +tags: [analytics craft] +hide_table_of_contents: false + +date: 2022-08-22 +is_featured: true +--- + +The larger a data ecosystem gets, the more its users and stakeholders expect consistency. As the ratio of data models to team members (to say nothing of stakeholders to team members) skyrockets, an agreed-upon modeling pattern often acts as scaffolding around that growth. + +The biggest tool in the toolbox today, dimensional modeling, offers enough consistency to make it the dominant approach in the space, but what might be possible if we shut that toolbox, took a break from our workbench, and instead strolled over to our bookshelf? + +In other words, what if we told a story? + +# The stakeholder’s hydra + +“When ***business questions*** come, they come not single spies, but in battalions.” - noted data professional William Shakespeare + +This is, perhaps, a more collaborative way to describe the analytics engineer / stakeholder relationship than “if you give a mouse a cookie.” + +After all, business questions *should* multiply, following the path from “What happened?” to “Why did that happen?” to “How can we predict what happens in the future?” and finally “How can we make something else happen instead?” + +What does this look like in practice? Let’s take an example: + +*How many orders came in last week?* + +With a straightforward question, formal modeling principles may not be important. You have the source data you need and the information requested. Name it something that works and move on. It’s that simple. + +It’s *not* that simple. + +*How many of the placed orders were fulfilled within three days?* + +*How many items were in each order?* + +*How many of the orders were returning customers?* + +Business curiosity is the quintessential hydra (just look at a dbt DAG), and the analytics engineer should know better than to think a single head is the end of it. + +With an exponential growth in scope, however, comes a question of consistency. Modeling at scale is often easier with a structural framework. Specifically, principled naming conventions and database design help analytics engineers keep flow through stylistic decisions to focus on the request at hand, while providing other team members the ability to support follow-up questions on models they may not have built in the first place. + +# The leading solution + +So what conventions should we use in our projects? + +History and gravity have pulled many a team towards [dimensional modeling](https://docs.getdbt.com/terms/dimensional-modeling), building business molecules out of atomic fcts and dims. This approach benefits from well-deserved “if it ain’t broke” adoption as well as a commanding market share of data team practices. + +Within this framework, our business question would likely be answered from a table called `fct_orders`, because an order is, in a sense, an event. It might have a `customer_id` field that ties it to another model, `dim_customers`. + +These are actually common examples of a fact/dim structure, and if we have this tried-and-true approach, it may not make sense to seek another one. Any alternative would have to have similarly reliable conventions while offering some additional benefit to be worth the departure from the norm. + +But what if that additional benefit was clarity? + +# Introducing narrative modeling + +In the past, I’ve used a framework I call *narrative modeling*, naming and structuring data models so that they tell the story of the business. Unlike dimensional modeling, which was born out of a need to solve a technical problem (expensive data storage), the principles of narrative modeling are people-oriented: + +- Navigating an analytical database should be intuitive and educational +- Traversing the underlying code for an analytical database should be intuitive and stakeholder-friendly +- Adding to an analytical database should be intuitive and scaleable + +Out of those principles came three primary conventions: event tables, details tables, and entity schemas. + +## Event tables + +First, the backbone of a good narrative is the plot: what happened? In our example, *How many orders came in last week?* + +To answer this question, we still need one row per order placed, with timestamps so that we can filter down to specific time periods (e.g. last week). But what should we name it? + +Every principle of narrative modeling included the word “intuitive”. With that in mind, let’s call this table `order_placed`. + +In narrative modeling, we’d call `order_placed` an *event table*. Event tables have the naming convention of `subject_verb` . + +If this looks similar to `fct_` tables, it is! However, the benefit of `order_placed`over `fct_orders` appears when you need an additional order-level event. For instance, *How many orders were fulfilled last week?* + +- In dimensional modeling, you already used `fct_orders`, so you likely would need to rename that model. This can result in naming conventions like `fct_order_placement` and `fct_order_fulfillment` which can feel like reporting on two separate entities rather than two things that can happen to orders. +- In narrative modeling, the sky’s the limit as we stand up `order_fulfilled` alongside `order_placed` with room for `order_cancelled` and all matter of other steps along an order’s flow. + +Now we can model out the narrative thrust of an order, but events can be a little dry without a fleshed-out protagonist. How would we describe our hero, a single order? + +## Details tables + +In narrative modeling, details tables are where a user can expect to find more descriptive information about a particular business entity. + +In the example of orders, an `order_details` table might contain fields like: + +- `customer_id` +- `items_ordered` +- `payment_method` + +Initially, it might seem as though these should just be fields on `order_placed` and, for those examples, it’s a reasonable point[^1]. Consider instead the following: + +- `items_fulfilled` +- `days_to_fulfillment` + +One can imagine a stakeholder wanting to know all five of these data points, but the context for them comes from multiple events in the order’s flow. A `_details` table allows us to assemble a broad bank of knowledge about a given entity (in this case, an order) in one place. If data refresh is performant enough, this could even be the place to surface true snapshot fields like `status` or`current_location`. + +So we have everything that happened to our order and everything we’d want to know about it. Now let’s put it all together…literally. + +## Entity schemas + +I mentioned above that navigating an analytical database should be intuitive and educational. Given the building blocks of event and details tables described above, the intuitive part could be considered complete just by naming convention. If all of our data models were in a single schema, then the following tables would likely sort together: + +- `order_cancelled` +- `order_details` +- `order_fulfilled` +- `order_placed` + +Keeping related information grouped seems sufficient for usability. Then again, I’ve seen enough analytical databases where the database and schema have the same name (e.g. `DATA_MARTS.DATA_MARTS.*`) to see an opportunity for building a database that describes the business as soon as you open it. + +Throughout our example, `order` has been an entity we want to know a lot about. Any undertaking that creates business questions will have dozens if not hundreds of entities that people care about. Even in our example, we’ve glanced off other entities, such as `item` and `customer`. + +Grouping the models for each entity under a schema named for that entity builds out a database that describes the scope of the business in simple terms, while also allowing stakeholders using the database to navigate more purposefully, expanding schemas rather than scrolling tables in a single mega-schema. + +- `analytics` database + - `customer` schema + - `customer_details` + - `customer_created` + - `item` schema + - `item_details` + - `item_fulfilled` + - `order` schema + - `order_cancelled` + - `order_details` + - `order_fulfilled` + - `order_placed` + +This structuring principle can also help address the boogeyman of business entity resolution, overlapping names. If you’re a business that orders parts regularly and then fulfills customer orders, the question *How many orders came in last week?* can get a lot more confusing. At a fast-moving company, a new hire could be asked the question and answer in the wrong context completely[^2], because the tenured stakeholder can no longer imagine mixing them up. + +If instead, the database had schemas for`parts_order` and`customer_order`, that same new hire hits the database, sees those schemas, and thinks “Oh, there are two types…I should probably ask which.” That distinction can be a lot harder to spot in a single analytics schema. + +Intuitive *and* educational. + +# Let’s get visual + +One of the most powerful ways for stakeholders to conceptualize the flow of data through a dbt project is through the DAG visualization in dbt docs. If we consider it a goal of ours to capture business knowledge and have conversations about how we ascertain that knowledge, let’s consider how the two options manifest in their DAGS: + +### Dimensional modeling + +![Untitled](/img/blog/2022-08-22-narrative-modeling/dimensional-modeling-dag.png) + +In this approach, we have the standard `fct` and `dim` tables and a clean DAG flow. Let’s consider some possible shortcomings: + +- Because I made this flow, I know that the `fct_shipments` to `dim_order_items` to `fct_orders` represents a knowledge flow. A package got shipped with items in it, meaning those items themselves are now shipped and if all of the items in a given order are shipped, then the entire order is fulfilled. However, for a new person to learn that in this approach, they would need to enter the models themselves and look at the SQL for *why* they are dependencies. +- We called the table `fct_orders` because orders are events. Because we can conceive of a stakeholder wanting to identify *cancelled* orders, we take an `int` / `fct` approach, but now the intent of `fct` feels a little murky. It captures an event, *order placement*, at which time we *don’t know* it will be cancelled. We could potentially create `dim_orders` and `fct_order_placements` if we want to capture both, but that suggests the `fct` / `dim` design is much more of a choice, one different developers in your codebase might approach differently. + +In general, the dimensional DAG can begin to feel like it’s not for a user who *only* has a business context, which can keep the structural decision-making purely on the analytics engineer or at best only the most technically-adept stakeholders. + +### Narrative modeling + +![Untitled](/img/blog/2022-08-22-narrative-modeling/narrative-modeling-dag.png) + +How does this compare to the above? + +- Now we’re being explicit about our dependencies. We’re telling the viewer we infer items were shipped from packages being shipped, then use those items to identify when an order was entirely fulfilled. +- The order placement and fulfillment steps are both explicit, flowing into an `order_details` table where we can also calculate `days_to_fulfillment` +- The DAG does look a little more complex, with additional nodes and a broader base of final models on the right compared to the slimming effect of the dimensional modeling. This potential drawback could use some contextualization: + - First, we are being more explicit about the business questions we are answering, so each of the milestones of an `order` that might have previously been tucked into the CTEs of `fct_orders` is now a node unto itself + - Second, remember the hydra? Ideally, business questions beget business answers beget new business questions. If the knowledge base needs to expand, it’s reasonable that the DAG might as well. The key, however, is validating that each model is answering a question someone is asking + +To that final point, if presented with the DAG from the narrative modeling approach, stakeholders can participate in the conversation. One can imagine a stakeholder looking at the flow and saying “Interesting that we say an order is fulfilled when each item *ships.* Perhaps we should get shipper data and declare an order fulfilled when all items are *received*.” Because we took the modeling structure as far as possible into business concepts, we can have a conversation on methodology without shouting over a great contextual distance. + +# Benefits in practice + +### Stakeholders find it easier to participate in data modeling + +- They don’t need to learn the idiosyncrasies of fct/dim structuring (e.g. idea that only some business datapoints are called facts). +- The discrete models are framed as events or entities in the business, which means the stakeholder can compare the model’s logic to their subject matter expertise. + +### Intangible business steps are easier to model + +- Knowledge gaps are captured accurately. For instance, if the best way you know that a shipment was received by a customer is that a truck driver scanned it out of the system, you can model `shipment_scanned_out` as an explicit model, followed by an implicit`shipment_received` model referencing it. This stores in code the company’s current point-of-view that the scanning action is the best information available +- Certain business decisions directly drive data transformations. If an entire package costs $50.00 to ship and it has multiple items inside, shipping cost could be attributed to each item via weight or product value. In either case, teams can capture this attribution as `item_apportioned_shipping_cost`. + +### Users can tie business concepts to source data + +- While the schema structure above is focused on business entities, there are still ample use cases for [staging and intermediate tables](https://docs.getdbt.com/guides/best-practices/how-we-structure/1-guide-overview). +- After cleaning up source data with staging tables, use the same “what happened” approach to more technical events, creating a three-node dependency from `stg_snowplow_events` to `int_page_click_captured` to `user_refreshed_cart` and thus answering the question “where do we get online user behavior information?” in a quick visit to the DAG in dbt docs. + +# Should your team use it? + +Narrative modeling primarily values comprehension as an outcome of data modeling, which can be a high priority for… + +- …companies with a high stakeholder-to-data-team-member ratio. +- …companies with SQL-savvy stakeholders +- …companies looking to on-board new team members at a high rate (as the project in this case is a sketch of the business itself) +- …companies who can dedicate staffing and time to writing strong documentation so that the doors to the models can be thrown open. + +Narrative modeling might not be the right fit for… + +- …companies where storage spend, even in cloud warehouses, needs to be closely tracked. After all, fct/dim models emerged from a need to optimize data storage. +- …companies with BI tools that rely heavily on multi-entity tables. This can generally still work with narrative modeling, however, if there is an additional layer of standard datasets being modeled out of the shared components of your narrative models (to insure data stays in step across contexts). + +# A neverending story + +There’s a classic movie called Desk Set in which Katharine Hepburn runs the reference desk of a major TV network and Spencer Tracy comes in to install a research computer in her department. In gladiatorial bouts of banter, the movie investigates the concept of knowledge and, in particular, how human it should be. At one point, Tracy’s Richard Sumner runs Hepburn’s Bunny Watson through a chunky “train left the station” word problem and I think about her response (abbreviated below) all the time. + +**Richard Sumner:** Now, a train started out at Grand Central, with seventeen passengers aboard and a crew of nine. At 125th Street, four got off and nine got on. At White Plains, three got off and one got on. At Chappaqua, nine got off and four got on. And at each successive stop thereafter, nobody got off, nobody got on till the train reached its next-to-the-last stop, where five people got off and one got on. Then it reached the terminal. + +**Richard Sumner:** How many people got off at Chappaqua? + +**Bunny Watson:** Nine. + +**Richard Sumner:** Uh, would you mind telling me how you arrived at that conclusion? + +**Bunny Watson:** Spooky, isn't it? Did you notice that there are also nine letters in Chappaqua? + +**Richard Sumner:** Are you in the habit of associating words with the number of letters in them? + +**Bunny Watson:** I associate many things with many things. + +**Richard Sumner:** I see. Hmm. + +**Bunny Watson:** Aren't you going to ask me how many people got off at White Plains? Three. + +**Richard Sumner:** But there are ten letters in White Plains. + +**Bunny Watson:** No. Eleven. + +**Richard Sumner:** [beat] But only three got off there. + +**Bunny Watson:** You see, I've only ever been to White Plains three times in my whole life. + +Much like Mr. Sumner, we would be hard-pressed to teach a computer to answer questions the way Bunny does. Her accumulated knowledge and how she accesses it is deeply human. Why, then, do we so often take the accumulated knowledge of subject matter experts across our business and abstract it AWAY from its context to capture it in a data model? Put another way, why do we store business answers in a way that, over time, forgets the questions? + +Narrative modeling can help structure the data with questions and answers stored side-by-side, allowing us to be reference librarians with a killer card catalog. We can model out the expertise of the finance team or the marketing team or the product team in their own words, which keeps the context for not only the next person to join *those* teams, but also the next person to join our own. + +And so, in the face of battalions of business questions, we can become a host unto ourselves. + +### Footnotes +[^1]: However, in terms of the upstream commerce data, it’s conceivable for items to be added to an order as discrete events first before a final order placement event. An API endpoint for an order being placed might not need to know what’s in the cart, but rather just the who and the when. At that point, it’s dealer’s choice whether to join in items for order_placed or order_details + +[^2]: Ask me how I know! diff --git a/website/blog/2022-08-22-unit-testing-dbt-package.md b/website/blog/2022-08-22-unit-testing-dbt-package.md new file mode 100644 index 00000000000..80c0ad639a7 --- /dev/null +++ b/website/blog/2022-08-22-unit-testing-dbt-package.md @@ -0,0 +1,219 @@ +--- +title: "An introduction to unit testing your dbt Packages" +description: "Traditionally, integration tests have been the primary strategy for testing dbt Packages. In this post, Yu Ishikawa walks us through adding in unit testing as well." +slug: unit-testing-dbt-packages +authors: [yu_ishikawa] +tags: [dbt tutorials] +hide_table_of_contents: false + +date: 2022-08-25 +is_featured: true +--- + +_Editors note - this post assumes working knowledge of dbt Package development. For an introduction to dbt Packages check out [So You Want to Build a dbt Package](https://docs.getdbt.com/blog/so-you-want-to-build-a-package)._ + +It’s important to be able to test any dbt Project, but it’s even more important to make sure you have robust testing if you are developing a [dbt Package](https://docs.getdbt.com/docs/building-a-dbt-project/package-management). + +I love dbt Packages, because it makes it easy to extend dbt’s functionality and create reusable analytics resources. Even better, we can find and share dbt Packages which others developed, finding great packages in [dbt hub](https://hub.getdbt.com/). However, it is a bit difficult to develop complicated dbt macros, because dbt on top of [Jinja2](https://palletsprojects.com/p/jinja/) is lacking some of the functionality you’d expect for software development - like unit testing. + +In this article, I would like to share options for unit testing your dbt Package - first through discussing the commonly used pattern of integration testing and then by showing how we can implement unit tests as part of our testing arsenal. + + +## Unit Testing vs. Integration Testing + +Unit testing and integration testing are two common paradigms in create well-tested code. For a great deep dive into the difference between the two check out [this article](https://circleci.com/blog/unit-testing-vs-integration-testing/) from the CircleCI team. At a high level: + +- **Integration tests** are tests which operate against the entire integrated project or application. +- **Unit tests** are tests which verify a single element within a software project, such as an individual function or macro. + +Many dbt Packages use integration tests as their primary testing methodology. For example [dbt-utils](https://github.com/dbt-labs/dbt-utils) has [the integration_tests directory](https://github.com/dbt-labs/dbt-utils/tree/main/integration_tests) so that we can run integration tests by using the generic tests and macros contained within the package. The integration tests directory is essentially a standard dbt project within the dbt-utils package that is tested much the same way any dbt project would be. + +To use the integration tests - you’d simply run `dbt test` within the `integration_tests` directory. The tests execute as normal - meaning you can use your favorite methods of running CI against your dbt project to ensure that your integration tests are passing. + +Integration tests can help give you peace of mind that your package is performing as expected - but they have some drawbacks. Macros and generic tests frequently call other macros and the deeper dependency calls get, the more difficult it becomes to debug your macros using only integration tests. + +In this scenario it can be helpful to go beyond integration tests and implement unit tests for your macros. These unit tests can be run with a [dbt run operation](https://docs.getdbt.com/reference/commands/run-operation). Let’s take a look at a quick example of how this can be done. + +Consider a dbt Package called dbt_sample_package . We would like to implement a simple macro to create a string literal from a string text in a macro named `to_literal` in the file `macros/to_literal.sql`. + +```sql +-- macros/to_literal.sql +{% macro to_literal(text) %} + + '{{- text -}}' + +{% endmacro %} +``` + +--- + +To implement a unit testing macro corresponding to the `to_literal` macro we can create a macro to test our original macro in `integration_tests/macros/test_to_literal.sql`. + +Then we call the `to_literal` macro in the testing macro. and if the result isn’t the same as expected, we raise an error using the [exceptions.raise_compiler_error macro](https://docs.getdbt.com/reference/dbt-jinja-functions/exceptions). + +```sql +-- integration_tests/macros/test_to_literal.sql +{% macro test_to_literal() %} + + {% = dbt_sample_package.to_literal('test string') %} + + {% if result != "'test string'" %} + + {{ exceptions.raise_compiler_error('The test is failed') }} + + {% endif %} + +{% endmacro %} +``` + +--- + +By doing that, we can call the testing macro in the dbt project of integration tests using `dbt run-operation`. + +```shell +dbt run-operation test_to_literal +``` + +--- + +If we want to run all tests with a single command, it would be good to bundle them in a macro. Moreover, we can call the macro with `dbt run-operation`. + +```sql +-- integration_tests/macros/run_unit_tests.sql +{% macro run_unit_tests() %} + + {% do test_to_literal() %} + + {% do another_test() %} + +{% endmacro %} +``` + +--- + +## Unit tests for multiple adapters + +Your dbt Package may support multiple adapters. If you are a postgres user, you understand that the preceding `to_literal` macro doesn’t work on postgres because the expression to deal with string literal is different. So, we have to implement a macro to handle a special case of postgres. Now, we implement the subsequent macro called `postgres__to_literal` in `macros/to_literal.sql` in addition to the implementation above. + +```sql +-- macros/to_literal.sql +{% macro to_literal(text) %} + + {{ return(adapter.dispatch('to_literal', 'dbt_sample_package')(text)) }} + +{% endmacro %} + +{% macro default__to_literal(text) %} + + '{{- text -}}' + +{% endmacro %} + +{% macro postgress__to_literal(text) %} + + '{{- text -}}' + +{% endmacro %} +``` + +--- + +You may think of how we can implement unit testing macros efficiently. We can use the [the adapter.dispatch macro](https://docs.getdbt.com/reference/dbt-jinja-functions/dispatch) even in unit testing macros. As we separate the behavior for postgres, we can implement an independent unit testing macro for postgres as well. + +```sql +-- integration_tests/macros/test_to_literal.sql +{% macro test_to_literal() %} + + {{ return(adapter.dispatch('test_to_literal', 'integration_tests')(text)) }} + +{% endmacro %} + +{% macro default__test_to_literal() %} + + {% result = dbt_sample_package.to_literal('test string') %} + + {% if result != "'test string'" %} + + {{ exceptions.raise_compiler_error('The test is failed') }} + + {% endif %} + +{% endmacro %} + +{% macro postgres__test_to_literal() %} + + {% result = dbt_sample_package.to_literal('test string') %} + + {% if result != "E'test string'" %} + + {{ exceptions.raise_compiler_error('The test is failed') }} + + {% endif %} + +{% endmacro%} +``` + +--- + +We can then select unit tests based on the specified adapter. Let’s assume we have different dbt profiles corresponding to BigQuery and postgres. By specifying a dbt profile based on the adapter, we can select what testing macros are called internally. + +```shell +# Run unit tests on BigQuery +dbt run-operation run_unit_tests --profile bigquery +# `default__test_to_literal` is internally called. + +# Run unit tests on postgres +dbt run-operation run_unit_tests --profile postgres +# `postgres__test_to_literal` is internally called. +``` + +--- + +## Introducing dbt-unittest + +It’s historically been a challenge to do unit testing in your dbt packaging as Jinja2 doesn’t offer a built-in unit testing feature. But, we have good news: dbt provides the `exceptions.raise_compiler_error` macro so that we raise errors within a `dbt run-operation`. Using this, I implemented a dbt Package called [yu-iskw/dbt-unittest](https://hub.getdbt.com/yu-iskw/dbt_unittest/latest/), which is inspired by [python’s unittest module](https://docs.python.org/3/library/unittest.html), to enhance unit testing of dbt Package development. + +[GitHub - yu-iskw/dbt-unittest: A dbt Package provides macros for unit testing](https://github.com/yu-iskw/dbt-unittest) + +Using this, we can re-implement the example using the `dbt_unittest.assert_equals` macro and the implementation gets much simpler. + +```sql +-- integration_tests/macros/test_to_literal.sql +{% macro test_to_literal() %} + + {{ return(adapter.dispatch('test_to_literal', 'integration_tests')(text)) }} + +{% endmacro %} + +{% macro default__test_to_literal() %} + + {% result = dbt_sample_package.to_literal('test string') %} + + {{ dbt_unittest.assert_equals(result, "'test string'") }} + +{% endmacro %} + +{% macro postgres__test_to_literal() %} + + {% result = dbt_sample_package.to_literal('test string') %} + + {{ dbt_unittest.assert_equals(result, "E'test string'") }} + +{% endmacro %} +``` + +--- + +I practiced the idea even in the development of `yu-iskw/dbt-unittest`. The actual testing macros are located [here](https://github.com/yu-iskw/dbt-unittest/tree/main/integration_tests/macros/tests). Moreover, we are able to implement the continuous integration workflow as regular software development. For instance, I implemented [a workflow with GitHub Actions](https://github.com/yu-iskw/dbt-unittest/blob/main/.github/workflows/unit-tests.yml). It enables me to notice there is something wrong with changes. + +Aside from that, it would be great to take a look at other dbt Packages for integration testing and unit testing on dbt hub. For instance, [the dbt_datamocktool package](https://hub.getdbt.com/mjirv/dbt_datamocktool/latest/) is another useful package for unit testing dbt projects. We can create mock CSV seeds to stand in for the sources and refs that your models use and test that the model produces the desired output. That would be useful to mock testing data for your dbt project. + +## Summary + +In this article we’ve: + +- Introduced two approaches for testing your dbt Packages +- Demonstrated a simple unit testing example +- Shown how you can use existing tools to help build out your unit testing capabilities + +Hopefully this is helpful to you in your dbt Package development journey. diff --git a/website/blog/2022-08-31-august-product-update.md b/website/blog/2022-08-31-august-product-update.md new file mode 100644 index 00000000000..5826db17a24 --- /dev/null +++ b/website/blog/2022-08-31-august-product-update.md @@ -0,0 +1,64 @@ +--- +title: "August 2022 dbt Update: v1.3 beta, Tech Partner Program, and Coalesce!" +description: "Coalesce is less than 2 months away!" +slug: dbt-product-update-2022-august +authors: [lauren_craigie] + +tags: [dbt updates] +hide_table_of_contents: false + +date: 2022-08-31 +is_featured: false +--- + +Semantic layer, Python model support, the new dbt Cloud UI and IDE… there’s a lot our product team is excited to share with you at [Coalesce](https://coalesce.getdbt.com/register?utm_medium=email&utm_source=hs_email&utm_campaign=q3-2023_coalesce-2022_awareness&utm_content=connect_product-update_) in a few weeks. + +But *how* these things fit together—because of where dbt Labs is headed—is what I’m most excited to discuss. + +You’ll hear more in [Tristan’s keynote](https://coalesce.getdbt.com/agenda/keynote-the-end-of-the-road-for-the-modern-data-stack-you-know), but this feels like a good time to remind you that Coalesce isn’t just for answering tough questions… it’s for surfacing them. For sharing challenges we’ve felt in silos, finding the people you want to solve them with, and spending the rest of the year chipping away at them. As Tristan says in his latest blog, [that’s how this industry moves forward](https://www.getdbt.com/blog/finding-our-next-big-problem/). + +[REGISTER NOW](https://coalesce.getdbt.com/register?utm_medium=email&utm_source=hs_email&utm_campaign=q3-2023_coalesce-2022_awareness&utm_content=connect_product-update_) + + + +## **What's new** + +- **dbt Core v1.3 beta:** Do you use Python for analytics? The first beta prerelease of dbt Core v1.3—including support for dbt models written in Python—is [ready to explore](https://docs.getdbt.com/guides/migration/versions/upgrading-to-v1.3)! Check it out, and read more about dbt supported Python models [in our docs](https://docs.getdbt.com/docs/building-a-dbt-project/building-models/python-models). +- **Technology Partner Program:** We just launched our new [Technology Partner Program](https://www.getdbt.com/blog/dbt-labs-technology-partner-program/) with 40+ friends in the Modern Data Stack to provide consistent support for seamless integrations joint-users can trust. Check our new [dbt Cloud integrations page](http://www.getdbt.com/product/integrations) for what’s available today! +- **Single-tenant users:** dbt Cloud v1.1.60 is now available on dbt Cloud Enterprise. + +## What’s better + +- **dbt Cloud UI:** The [new dbt Cloud UI](https://www.getdbt.com/blog/the-dbt-cloud-ui-is-getting-a-makeover/) is in beta, and can be opted-into by any multi-tenant dbt Cloud customer. Cleaned-up interface, better ergonomics, fewer clicks to frequently-used screens. +- **dbt Cloud IDE:** Did you catch [Staging last month](https://www.getdbt.com/blog/staging-highlights-the-latest-from-dbt-labs/) (our quarterly product update)? The dbt Cloud IDE has been overhauled for greater speed and performance, and is now in beta—[enroll to check it out!](https://bit.ly/dbt-cloud-ide-beta) + +## New resources + +**Things to try** 🛠️ + +- **dbt_artifacts v1.2.0:** [Brooklyn Data Co just shipped a pretty significant re-write to the dbt_artifacts package](https://brooklyndata.co/blog/dbt-artifacts-v100). Capture all the metadata generated by dbt at the end of an invocation (project nodes, success rate, test results, etc), and store directly in Snowflake, Databricks, or BigQuery for immediate analysis. +- **dbt YAML validator using JSON schema**: If you do any development in VS Code, [this repo unlocks autocomplete and validation for dbt’s YAML files](https://github.com/dbt-labs/dbt-jsonschema/). Find those tests that never ran because you messed up the indentation. *Not that that would ever happen to you.* +- **dbt Exposures for Hightouch**: [Exposures](https://docs.getdbt.com/docs/building-a-dbt-project/exposures) in dbt allow you to quickly see how downstream data applications are making use of your dbt models and sources. These don’t have to just represent dashboards in BI tools though — [you can now represent your Hightouch syncs as dbt exposures too](https://hightouch.com/blog/introducing-dbt-exposures-for-hightouch/). +- **Are you a certified dbt developer?** We recently launched our new [Analytics Engineering certification](https://www.getdbt.com/certifications/analytics-engineer-certification-exam/) program, and would love to hear what you think. We personally dug [this writeup from Charles Verleyen](https://medium.com/astrafy/dbt-exam-feedback-8d07a0593648) on what to expect, and exactly how much experience/prep he recommends. + +**Things to read 📚** + +- **How to enforce rules at scale:** It’s best practice to add model tests in dbt, but can you require it? [In his latest blog](https://docs.getdbt.com/blog/enforcing-rules-pre-commit-dbt), Benoit Perigaud (dbt Labs Senior Analytics Engineer) shares how to use the pre-commit-dbt package to do just that. +- **How we shaved 90 minutes off a model:** [Check out how we used the model timing tab](https://docs.getdbt.com/blog/how-we-shaved-90-minutes-off-model) in dbt Cloud to find and re-architect our longest running model. +- **How to decide between hashed or integer surrogate keys:** Dave Connors (dbt Labs Senior Analytics Engineer) [breaks down the pros and cons of each approach](https://docs.getdbt.com/blog/managing-surrogate-keys) in dbt. +- **How to think about dbt Python models in Snowpark:** [Eda Johnson](https://www.linkedin.com/in/eda-johnson-saa-csa-pmp-0a2783/) wrote a nice primer on [how to approach dbt-supported Python models in Snowflake](https://medium.com/snowflake/a-first-look-at-the-dbt-python-models-with-snowpark-54d9419c1c72) with Snowpark Python. +- **dbt Labs is officially partnering with Monte Carlo**: The partnership makes it simple for analytics engineers to [supplement dbt testing with end-to-end observability](https://www.getdbt.com/blog/monte-carlo-dbt-labs-partnering-for-more-reliable-data/). +- **How Comcast accidentally invented a feature store in 2013:** What a genuinely delightful read. Josh Berry details the [peak and pits of a fast-moving data science team](https://towardsdatascience.com/features-are-not-just-for-data-scientists-6319406ac071) that transcended an initial aversion to documentation to build “Rosetta.” + +**Consulting corner** 🌎 + +I just discovered the treasure trove of excellent resources from dbt Labs consulting partners, and want to start sharing more here. Here’s a few you might have missed over the summer: + +- **Reduce ETL costs:** I’ve only just seen [this blog](https://www.mighty.digital/blog/how-dbt-helped-us-reduce-our-etl-costs-significantly) from Mighty Digital, but found it to be a super practical (and concise) introductory guide to rethinking your ETL pipeline with dbt. +- **Explore data:** [Part two of a series on exploring data](https://vivanti.com/2022/07/28/exploring-data-with-dbt-part-2-extracting/) brought to you by Vivanti. This post focuses on working with objects in dbt, but I also recommend the preceding post if you want to see how they spun up their stack. +- **Track historical changes:** [](https://blog.montrealanalytics.com/using-dbt-snapshots-with-dev-prod-environments-e5ed63b2c343)Snapshots are a pretty handy feature for tracking changes in dbt, but they’re often overlooked during initial onboarding. [Montreal Analytics explains how to set them up](https://blog.montrealanalytics.com/using-dbt-snapshots-with-dev-prod-environments-e5ed63b2c343) in dev/prod environments +- **Learn dbt:** Have some new faces on the data team that might need an introduction to dbt? Our friends at GoDataDriven are hosting a [virtual dbt Learn Sept 12-14](https://www.tickettailor.com/events/dbtlabs/752537). + +Thank you! + +*This month’s newsletter was brought to you by: Joel, Gloria, Azzam, Amos, and me (Lauren)* \ No newline at end of file diff --git a/website/blog/2022-09-07-leverage-accounting-principles-when-finacial-modeling.md b/website/blog/2022-09-07-leverage-accounting-principles-when-finacial-modeling.md new file mode 100644 index 00000000000..bf1acdcaa24 --- /dev/null +++ b/website/blog/2022-09-07-leverage-accounting-principles-when-finacial-modeling.md @@ -0,0 +1,168 @@ +--- +title: "Leverage Accounting Principles when Modeling Financial Data" +description: "Modeling financial data is rarely ever easy (or fun). Thankfully, there are accounting principles that can be leveraged to ensure your financial models are complete and accurate." +slug: financial-modeling-accounting-principles +authors: [joe_markiewicz] +tags: [analytics craft] +hide_table_of_contents: false + +date: 2022-09-07 +is_featured: true +--- + +Analyzing financial data is rarely ever “fun.” In particular, generating and analyzing financial statement data can be extremely difficult and leaves little room for error. If you've ever had the misfortune of having to generate financial reports for multiple systems, then you will understand how incredibly frustrating it is to reinvent the wheel each time. + +This process can include a number of variations, but usually involves spending hours, days, or weeks working with Finance to: +- Understand what needs to go into the reports +- Model said reports +- Validate said reports +- Make adjustments within your model +- Question your existence +- Validate said reports again + +You can imagine how extremely time consuming this process can be. Thankfully, you can leverage core accounting principles and other tools to more easily and effectively generate actionable financial reports. This way, you can spend more time diving into deeper financial analyses. + + + +I will detail how you are able to leverage these principles, but before I dive in I would be remiss not to mention the dbt packages that are available for popular financial data sources that you can leverage! If you are using Fivetran and currently utilize either Netsuite, QuickBooks, Xero, or Sage Intacct, then you are able to skip the line and use the pre-built reports right out of the box. See below for links to the relevant packages: +- [Netsuite dbt package](https://github.com/fivetran/dbt_netsuite) +- [QuickBooks dbt package](https://github.com/fivetran/dbt_quickbooks) +- [Xero dbt package](https://github.com/fivetran/dbt_xero) +- [Sage Intacct dbt package](https://github.com/fivetran/dbt_sage_intacct) + +These packages generate the three basic financial statement reports (plus a few bonus models) your Finance team will need: +- General Ledger/Transaction Detail: a ledger of all posted transactions within an organization. +- Balance Sheet: a summary of the financial balances within an organization. The quintessential accounting calculation (Assets = Liabilities + Equity). +- Profit and Loss/Income Statement: a report detailing the revenues and expenses within an organization. + +By simply installing the package you can get those reports in your in a matter of minutes, allowing you to bypass the cycle outlined prior. However, if you do not utilize one of these sources with Fivetran, there is nothing to fear! I will detail the modeling principles used in each of these packages. + +Below are the modeling principles I leverage whenever I begin a new financial data modeling adventure. These steps are in order and should be followed as such. + +## Step 1: Understanding the Source Schema +Each normalized financial data source I have worked with is structured in either one of two ways: a single that contains all transactions for the company **OR** a header and line item detail table for each transaction type. Both schema designs have their pros and cons. + +The single transaction table makes it easier to get started with your financial modeling and generating your end reports. However, it doesn’t give you a good view of what type of transactions are included within the table. In order to gain an understanding of the transaction types, you will need to spend some time querying the table to identify what transactions are (and are not) included. See the [Fivetran Netsuite ERD](https://fivetran.com/docs/applications/netsuite-suiteanalytics#schemainformation) as an example of the single transaction table schema. + +Similarly, the header and line item detail table schema version is great for understanding what types of transactions have taken place across the company. However, this schema structure is quite difficult when needing to do downstream analyses. For example, you are required to join the header and line item tables together before unioning them with the other transaction objects in order to holistically view all transactions together. See the [Fivetran QuickBooks ERD](https://fivetran.com/docs/applications/quickbooks#schemainformation) as an example of the header and line item table schema. + +Regardless of which scenario you find your financial data in, it is best to take some time to gain an understanding of the schema design. The next step is going to involve using the raw table(s) to begin the financial modeling journey. + +![](/img/blog/2022-09-07-leverage-accounting-principles-when-financial-modeling/hobbit-adventure.gif) + +## Step 2: Generating the General Ledger/Transaction Detail Report +The General Ledger/Transaction Detail report rests at the core of every company's financial story. This report will contain every verifiable transaction (cash coming in, cash going out, etc.) that has taken place within the company, but with a fun accounting twist! + +Okay, it may not be fun, or a twist, but this report will include an important piece of the accounting puzzle for each transaction. Yes, I am going to be talking about debits and credits (aka double entry accounting). + +Each transaction will detail how the entry impacts the bottom line as either a debit or a credit to a relevant account. This is invaluable to us for downstream modeling of the Balance Sheet in particular. The debit and credit method of accounting is critical to the matching principle where each item of revenue should match to an item of expense. Think of it like there should always be an offsetting action for each transaction. If you purchase coffee beans to sell to customers, you will debit the coffee beans and credit cash. This has an impact by increasing your asset (coffee beans) and also decreasing your asset (cash). Perfectly balanced, as all things should be. + +I highly recommend finding a cozy spot on your couch and reading up on [double entry accounting](https://www.fool.com/the-ascent/small-business/accounting/articles/double-entry-accounting/) before modeling your General Ledger/Transaction Detail model. Luckily, I have found the majority of financial data sources that leverage the single transaction detail table also handle the double entry accounting for you within the table (see Sage Intacct as an example). However, if your source resembles the header and line item schema design, then you will likely need to ensure you are accounting for the double entries within your models before rolling up all your transactions into a single table. + +I highly recommend taking a look at how this was modeled for each transaction type within the dbt_quickbooks [double entry transaction models](https://github.com/fivetran/dbt_quickbooks/tree/main/models/double_entry_transactions). Below is a great snippet from the double entry folder which shows how the double entry method is accounted for within the model by using a union (notice the account_id changing to reflect the impact of the transaction on the different accounts). +```sql +select + transaction_id, + transaction_date, + customer_id, + vendor_id, + amount, + payed_to_account_id as account_id, + 'debit' as transaction_type, + 'bill' as transaction_source +from bill_join + +union all + +select + transaction_id, + transaction_date, + customer_id, + vendor_id, + amount, + payable_account_id as account_id, + 'credit' as transaction_type, + 'bill' as transaction_source +from bill_join +``` + +Once you ensure you’re properly accounting for the double entry method in the individual transaction type models, you can union all the transaction type models together to create a single table with all transaction types. + +At this point, regardless of which schema design you began with, you should be at the same place with a single table that contains all your transactions (and their offsetting entry) across the company! Now you can start joining in your dimensional fields such as vendor name, account name, account type, and account classification to name a few. Okay, now that I mention account classification, it is a crucial component for building your end financial models and I should talk more about it. + +![](/img/blog/2022-09-07-leverage-accounting-principles-when-financial-modeling/top-gun-classified.gif) + +## Step 3: Verify the Account Classifications +All financial data sources will have some variation of the company chart of accounts. Typically this is in the form of the accounts table. This table is able to be joined to the General Ledger to enrich your transactions with the corresponding account information. This is an extremely important piece of the equation as you want to make sure the transactions are impacting the right accounts and are being classified correctly. The account classification allows you to identify if the account is either an Asset, Liability, Equity, Expense or Revenue account. In turn, this then serves as the key component in generating the Balance Sheet and Income Statement reports. + +Sometimes you will get lucky and the account classification will be provided within the accounts table (like in [dbt_xero](https://github.com/fivetran/dbt_xero_source/blob/0d1d2c02dbb8e1f8371e703651a704127181c88f/models/stg_xero__account.sql#L30)). If it is not, then you will need to add some logic to your accounts model to accurately set the classification. Typically, the logic involves referencing the account type to determine the classification (for example, an Accounts Payable account type should map to a Liability classification). Thankfully, this has been applied to a number of open source projects and can be leveraged by your team! I recommend taking a look at how the [dbt_quickbooks](https://github.com/fivetran/dbt_quickbooks/blob/43282a8cf77670f6e2ac657167dd19c1014ba111/models/intermediate/int_quickbooks__account_classifications.sql#L23-L35) packages map classifications. Likewise, the [dbt_sage_intacct](https://github.com/fivetran/dbt_sage_intacct/blob/4feec47da41fcc28325913dbae5597132ddccd66/models/intermediate/int_sage_intacct__account_classifications.sql#L12-L22) implementation follows the same logic, but instead allows for more flexibility in the form of variables that can be modified and edited if the Chart of Accounts on the finance side changes. + +Once you verify, or create, the account classification field, you are safe to join the account (and other dimensional) tables with your General Ledger table. Now that everything is joined together, you will start to see the tapestry of the financial history unfolding before your eyes. Beautiful, isn’t it. Time really flies when you are having fun. Actually, now that I am on the topic of time, I can’t wait to talk about the next step. Aggregating your General Ledger data by a date period! + +![](/img/blog/2022-09-07-leverage-accounting-principles-when-financial-modeling/office-its-a-date.gif) + +## Step 4: General Ledger by Period and the Date Spine +As of right now, your Finance team is probably ecstatic that they currently have a fully functional (and, most importantly, accurate) General Ledger available. While this is great, it can be quite difficult to generate the final financial statements with the data in this format. It will be much easier to wrangle the data if it is aggregated into date periods by account. While you can aggregate by whichever period you like, I suggest aggregating by month, as it allows you and your Finance team to slice and dice by month/quarter/annual to your liking. In order to achieve this, you are going to use our best friend - the date spine. + +Using a combination of jinja and the date spine macros, you will be able to create a table that contains each month from the beginning of the company’s financial history. While it may be daunting, I recommend taking a look at how the date spine is generated within the dbt_quickbooks [general_ledger_date_spine](https://github.com/fivetran/dbt_quickbooks/blob/main/models/intermediate/int_quickbooks__general_ledger_date_spine.sql) model. You can see how the date spine references the General Ledger model and finds the minimum and maximum date to generate the complete spine. This ensures you are not generating any less or more data than is needed for our downstream analyses. + +Once the date spine is created, you should generate a new model to aggregate your General Ledger data by month. In addition to simply aggregating your General Ledger data by month, you will want to make sure you consider the accounts beginning, ending, and net change balance month over month. Calculating these extra fields makes for a seamless Balance Sheet and Income Statement reporting down the line. + +Before generating the beginning, ending, and net change balances for each month, it is important to know that not all classifications will have the same behavior for these fields. Asset, Liability, and Equity accounts will always have a beginning, ending, and net change balance as the accounts have rolling totals that change over time. Conversely, Revenue and Expense accounts only have a net change balance. Calculating these fields can be a multi-/model process. The process should look something along the lines of the following: + +- Aggregate your General Ledger data by month +- Create a cumulative balance for balance sheet accounts +- Generate a beginning and ending balance for balance sheet accounts using the cumulative balance +- Join the General Ledger data with your date spine +- Fill in the empty month records with relevant data showing 0 in net change + +I recommend referencing the dbt_quickbooks [general_ledger_balances](https://github.com/fivetran/dbt_quickbooks/blob/main/models/intermediate/int_quickbooks__general_ledger_balances.sql) model as an example of how to best follow the above steps. Once these steps are completed, you should have a model that includes an entry for every month and every account with the beginning, ending, and net change balances. + +There has been a lot to retain up to this point, but you are almost ready to finish the process and generate the final financial statements without any additional adjustments. Before you get there, you need to capture the Retained Earnings/Adjusted Income entries! + +![](/img/blog/2022-09-07-leverage-accounting-principles-when-financial-modeling/crown-adjustment.gif) + +## Step 5: Retained Earnings / Adjusted Income + +A piece that is commonly forgotten is the need to account for retained earnings/adjusted income within your balance sheet calculation. In a nutshell, this calculation is your net income/loss for a given period. Since you decided to take the approach of generating the report by month, you will simply need to calculate the Revenue minus Expenses for each given period and express this as unique entries. + +Thankfully, the bulk of the heavy lifting has already been completed in Step 4 and you can leverage this work to generate the Retained Earnings/Adjusted Income records. By first taking the Revenue records and then subtracting those by the Expense records, you can arrive at the desired outcome. One thing to call out is that you will need to create unique field names for these records as you are essentially generating new data. See the [quickbooks_retained_earnings](https://github.com/fivetran/dbt_quickbooks/blob/main/models/intermediate/int_quickbooks__retained_earnings.sql) model for how this was calculated. + +With that, you are finally at the last piece of aggregating the General Ledger by Period! Combining the Retained Earnings/Adjusted Income model with the General Ledger by Period model. + +![](/img/blog/2022-09-07-leverage-accounting-principles-when-financial-modeling/captain-planet-combine.gif) + +## Step 6: Finish the General Ledger by Period Model + +Union the General Ledger by Period model with your Retained Earnings/Adjusted Income model. Just like that, you finished the hardest part of this equation! You now have a fully usable table that contains every single month across your financial history and can see the respective account entry for that month. Bonus points as well for not forgetting about the Retained Earnings/Adjusted Income entries that will be invaluable during the Balance Sheet calculations. + +Now you can finally move into the last steps and generate the Balance Sheet and Income Statement/Profit and Loss statements. + +![](/img/blog/2022-09-07-leverage-accounting-principles-when-financial-modeling/devil-prada-glacial-pace.gif) + +## Step 7: Generate the Balance Sheet Report + +To create the Balance Sheet, you can now simply reference your General Ledger by Period and filter for balance sheet account classifications. Bada Bing... you have your Balance Sheet and can slice and dice by period to your heart's content! ❤️ ⚖️ + +Wow that was easy. It can’t be that simple to generate the Income Statement/Profit and Loss report, right? + +![](/img/blog/2022-09-07-leverage-accounting-principles-when-financial-modeling/supranos-bada-bing.gif) + +## Step 8: Generate the Income Statement / Profit and Loss Report + +To create the Income Statement/Profit and Loss report you can now simply reference your General Ledger by Period and filter for income statement account classifications. Bada Boom... you have your Income Statement/Profit and Loss report and can slice and dice by period to your heart's content! ❤️ 💸 + +Geez, I wasn't kidding. It really is that easy! + +![](/img/blog/2022-09-07-leverage-accounting-principles-when-financial-modeling/supranos-boom.gif) + +# That’s a wrap! +You just walked through a _quick_ 8 step process to take your financial data from raw to comprehensive financial statements. I have little doubts you are currently being given a calzone party by your entire Finance team for generating the perfect financial reports! + +![](/img/blog/2022-09-07-leverage-accounting-principles-when-financial-modeling/parks-and-rec-ben-wyatt.gif) + +This is by no means a simple process, but the silver lining is that this is similarly performed by countless other analysts. You now have the knowledge to go forth and wrangle your own financial data with the same principles other analysts have used. Additionally, with the advent of dbt packages you can directly leverage the past work of other analysts by using the pre-built financial models without any modifications on your end! + +It is important to note that each business may differ greatly from one another. The above principles may not translate 1-to-1 exactly, but they may be slightly modified to fit your business use case. Additionally, the dbt packages may also encounter a similar “one size does not fit all” scenario. That being said, the dbt packages are maintained by passionate individuals who are always excited and willing to grow the package. If you use a dbt package solution and notice your numbers do not tie out, I would encourage opening an Issue to engage in a discourse with the maintainers and community. There may just be an update that can be applied to enhance the package and tie out your financial statements. The dbt packages are a great example of a community of analysts working together to develop pre-built data models for others to leverage. + +In the end, these outlined core principles and packages are intended to be leveraged by your present and future selves. I hope they have been helpful and I look forward to hearing your thoughts. Until next time, I’ll calc-you-later! diff --git a/website/blog/2022-09-08-konmari-your-query-migration.md b/website/blog/2022-09-08-konmari-your-query-migration.md new file mode 100644 index 00000000000..62e0f613a56 --- /dev/null +++ b/website/blog/2022-09-08-konmari-your-query-migration.md @@ -0,0 +1,133 @@ +--- +title: "KonMari your data: Planning a query migration using the Marie Kondo method" +description: "Do your data models spark joy? Let’s talk about how to apply the KonMari Method to a new data migration project." +slug: marie-kondo-query-migration +authors: [lauren_benezra] +tags: [analytics craft] +hide_table_of_contents: false + +date: 2022-09-08 +is_featured: true +--- + +If you’ve ever heard of Marie Kondo, you’ll know she has an incredibly soothing and meditative method to tidying up physical spaces. Her KonMari Method is about categorizing, discarding unnecessary items, and building a sustainable system for keeping *stuff*. + +As an analytics engineer at your company, doesn’t that last sentence describe your job perfectly?! I like to think of the practice of analytics engineering as applying the KonMari Method to data modeling. Our goal as Analytics Engineers is not only to organize and clean up data, but to design a sustainable and scalable transformation project that is easy to navigate, grow, and consume by downstream customers. + +Let’s talk about how to apply the KonMari Method to a new migration project. Perhaps you’ve been tasked with unpacking the kitchen in your new house; AKA, you’re the engineer hired to move your legacy SQL queries into dbt and get everything working smoothly. That might mean you’re grabbing a query that is 1500 lines of SQL and reworking it into modular pieces. When you’re finished, you have a performant, scalable, easy-to-navigate data flow. That does take a bit of planning, but you’ll see that we can take this… + +![buried in boxes](/img/blog/2022-09-08-konmari-your-query-migration/buried-in-boxes.webp) + +to THIS! + +![cat perched in kitchen](/img/blog/2022-09-08-konmari-your-query-migration/cat_kitchen.jpeg) + +That’s the power of the KonMari Method. Let’s apply the method specifically to data: + +**KonMari Method** + +1. Commit yourself and stakeholders to tidying up this project +2. Imagine the ideal state of this query +3. Finish discarding unnecessary models and columns +4. Tidy by category +5. Follow the right order—downstream to upstream +6. Validate that the result *sparks joy*, AKA, satisfies all of the consumers’ needs + +Are you ready to tidy?! Summon Marie Kondo! + +![Marie Kondo](/img/blog/2022-09-08-konmari-your-query-migration/mariekondo.gif) + +Think about when you moved to a new house. Maybe, at some point during the packing process, you got annoyed and just started labeling everything as “kitchen stuff”, rather than what was actually put in the boxes. (Isn’t this…everyone?!) So now, in your new kitchen, you’ve got tons of boxes labeled “kitchen stuff” and you don’t know where everything goes, or how to organize everything. You start to unpack, and your housemates come into the kitchen and ask, why is the Tupperware above the fridge? And why the cooking utensils are in the drawer furthest from the stove? + +![nachka-cat.gif](/img/blog/2022-09-08-konmari-your-query-migration/nachka-cat.gif) + +Before you build, you need to plan. And before you plan, you need to get everyone on the same page to understand how they use the kitchen, so you can organize a kitchen that makes sense to the people who use it. So let’s jump into step one. + +## Step 1: Commit yourself and stakeholders to tidying up this project + +This may feel like an unnecessary step, but haven’t you ever started migrating a new query, only to find out that it was no longer being used? Or people found it so difficult to consume that they instead created their own queries? Or you carved out precious time for this project, but the people you need to be involved have not? Or maybe your consumers expected you to have completed this project yesterday...*Initiate anxiety-stomachache now*. + +Take the opportunity to meet with your stakeholders, and get everyone on the same page. These are likely your report-readers, and your report-builders. + +Your *readers* are the stakeholders who are not the boots-on-the-ground engineers or analysts, but rather the people who rely on the output of the engineering and analysis — Head of Marketing, Head of Sales, etc. — these are your housemates who come into the kitchen searching for a fork to eat the dinner prepared for them. + +The *builders* are the post-dbt data analysts — they transform your thoughtfully-curated tables into beautiful analysis dashboards and reports to answer the readers’ questions — Marketing Analyst, Tableau Guru, Looker Developer — these are your housemates who use your meticulously organized kitchen to cook delicious meals. + +You might be thinking, why would I bother the report-reader, when I have the report-builder? Remember, your reader needs to know where the forks live. In this step, it is crucial to set up an *initial* meeting with all of these people to make sure you’re on the same page about what is being built and why. Then you’ll be able to find one person in the group who can be your phone-a-friend for context questions. + +Here are some example questions you’ll want to ask in this initial meeting: + +- How is this data table currently being utilized? +- What transformations are being performed *on top* of this table? Aggregations? Filters? Adjustments? Joins? +- What are the pain points you face with this table? Slow to query? Incorrect outputs? Missing columns? Unnecessary columns? +- What questions do you want this table to answer? Can those questions be broken apart? i.e., Can this table be broken up into smaller tables, each of which answers a different part of the question? Or is it best as one table? +- How can we bucket these sources? Think consumption — where are these subqueries going to be consumed downstream? Do these sources make sense to join upstream? +- If the original table output is incorrect, do they have a table with correct data that we can validate against? How will we know if it is correct? + +## Step 2: Imagine the ideal state of your project + +This is my favorite part. If you dive in to all the boxes labeled “kitchen stuff” with no plan, you’ll end up moving things around multiple times until it feels right. Sometimes, you won’t even get to a place where it feels right before your housemates jumble everything up, because they use the kitchen differently than you. You need the kitchen to flow with the way that you *and* your housemates use the kitchen — if you know that the silverware goes in the drawer closest to the dishwasher, and the cups and glasses go in the cabinet next to the sink, and the mugs go above the coffee pot, you’ll unpack once and everyone will be able to navigate the kitchen with ease. + +Let’s plan how to unpack our query. This may be what you’re working with: 30+ sources all packed into one SUPER query 🦸. + +![many-to-one DAG](/img/blog/2022-09-08-konmari-your-query-migration/many-to-one-dag.png) + +Or, perhaps you’re migrating a stored procedure, and you have DAG Spaghetti that you’re contending with, as [Matt talks through in this article](/blog/migrating-from-stored-procs). + +![spaghetti data DAG](/img/blog/2022-09-08-konmari-your-query-migration/spaghetti-data-dag.png) + +Now we can look at the details of this code, and start to categorize. You can start building out what this may look like as a DAG in a process mapping tool, like [Whimsical](https://whimsical.com/). + +Where can you break a massive query apart, and pull pieces out to create modularizations? Or, where can you combine repeated code to answer a more general question? + +- Use your buckets identified in your initial meetings with clients to identify where you can create re-usable intermediate models. +- Locate repeated joins and subqueries to identify more intermediate models. +- Figure out which sources aren’t really providing answers to the questions, and remove them from your design. + +Perhaps your redesigned DAG looks something like this — you have intermediate models and joins carved out, creating modular, reusable pieces of code ([read more on that here!](https://www.getdbt.com/analytics-engineering/modular-data-modeling-technique/)). You’ve created a data flow devoid of circular logic, and your end-table has all the necessary components to answer your stakeholders’ questions. + +**Before you accuse me of wishful thinking, this is the result of a real client project! We broke up almost 1500 lines of code in a single query into this beautiful waterfall. Marie Kondo would be proud.* + +![fully konmarid project](/img/blog/2022-09-08-konmari-your-query-migration/fully-konmarid-project.png) + +While you don’t *have to* design your flow this way, it is incredibly important to consider modularity, readability, scalability, and performance in your design. Design with intention! Remember, don’t put your forks too far from the dishwasher. + +## Step 3: Finish discarding unnecessary models and columns + +As you’re pulling items out of your “kitchen stuff” boxes, you may discover that you have Tupperware bottoms without lids, broken dishes, and eight cake pans. Who needs eight cake pans?! No one. There’s some clean out you can do with your kitchen stuff, as well as your data models. + +Now that you have your design, and your notes from your stakeholder meeting, you can start going through your query and removing all the unnecessary pieces. + +Here are a few things to look for: + +- Get rid of unused sources — [there’s a package for that!](https://hub.getdbt.com/dbt-labs/dbt_project_evaluator/latest/) +- Remove columns that are being brought in with import CTEs, but are just clogging your query +- Only bring in the columns you need (this is especially true for BigQuery and Redshift for performance purposes) +- Where you can, do the same with rows! Is a filter being applied in the final query, that could be moved to a CTE, or maybe even an intermediate model? +- Remember that in most cases, it is more performant to filter and truncate the data before the joins take place + +## Steps 4 & 5: Tidy by category and follow the right order—upstream to downstream + +We are ready to unpack our kitchen. Use your design as a guideline for [modularization](/guides/best-practices/how-we-structure/1-guide-overview). + +- Build your staging tables first, and then your intermediate tables in your pre-planned buckets. +- Important, reusable joins that are performed in the final query should be moved upstream into their own modular models, as well as any joins that are repeated in your query. +- Remember that you don’t want to make these intermediate tables *too* specific. Don’t apply filters if it causes the model to be consumable by only one query downstream. If you do this, you aren’t creating a scalable project, you’re just recreating the same issue as your original query, but spread amongst mulitple models, which will be hard to untangle later. + +Your final query should be concretely defined — is it a fact or dimension table? Is it a report table? What are the stepping stones to get there? What’s the most performant way to [materialize](/docs/building-a-dbt-project/building-models/materializations)? + +Build with the goal to scale — when might you need these intermediate models again? Will you need to repeat the same joins? Hopefully you’ve designed with enough intention to know the answer to that last one is “no.” Avoid repeating joins! + +## Step 6: Validate that the result *sparks joy*, AKA, satisfies all of the consumers’ needs + +When you walk into your newly unpacked kitchen, and the counters are organized, you can unload the dishwasher because the location of the forks is intuitive. You ask your housemate to make dinner for everyone, and they navigate the kitchen with ease! + +Ask yourself these questions: + +- Does my finished build design spark joy? Meaning, have I executed my build reflective of my scalable design? +- Is it easy to navigate? Is it easy to understand? +- Are all of the pieces easy to consume, when I need to utilize the modularity in the future? +- Does my final query perform well, and answer all of the consumers’ needs? + +If your answer is yes to these questions, you’ve sparked JOY. Well done friend! If the answer is no, consider which pieces need to be planned again. If your code isn’t scalable, or easy for consumers to use, start from step one again — gather your consumers, try to understand where communication broke down, and redesign. + diff --git a/website/blog/2022-09-13-the-case-against-cherry-picking.md b/website/blog/2022-09-13-the-case-against-cherry-picking.md new file mode 100644 index 00000000000..84a70e08392 --- /dev/null +++ b/website/blog/2022-09-13-the-case-against-cherry-picking.md @@ -0,0 +1,180 @@ +--- +title: "The case against `git cherry pick`: Recommended branching strategy for multi-environment dbt projects" +description: "This is...a cherry picking trashpost." +slug: the-case-against-git-cherry-picking +authors: [grace_goheen] +tags: [analytics craft] +hide_table_of_contents: false + +date: 2022-09-13 +is_featured: true +--- + +## Why do people cherry pick into upper branches? + +The simplest branching strategy for making code changes to your dbt project repository is to have a **single main branch** with your production-level code. To update the `main` branch, a developer will: + +1. Create a new feature branch directly from the `main` branch +1. Make changes on said feature branch +1. Test locally +1. When ready, open a pull request to merge their changes back into the `main` branch + +![Basic git workflow](/img/blog/2022-09-13-the-case-against-cherry-picking/1_basic_git_workflow.png) + +If you are just getting started in dbt and deciding which branching strategy to use, this approach–often referred to as “continuous deployment” or “direct promotion”–is the way to go. It provides many benefits including: + +- Fast promotion process to get new changes into production +- Simple branching strategy to manage + +The main risk, however, is that your `main` branch can become susceptible to bugs that slip through the pull request approval process. In order to have more intensive testing and QA before merging code changes into production, some organizations may decide to **create one or more branches between the feature branches and `main`**. + + + +:::caution Don't over-engineer your branching strategy +Before adding additional primary branches, ask yourself - "is this risk *really* worth adding complexity to my developers' workflow"? Most of the time, the answer is no. Organizations that use a simple, single-main-branch strategy are (almost always) more successful long term. This article is for those who *really absolutely must* use a multi-environment dbt project. +::: + +For example, a single dbt project repository might have a hierarchy of 3 primary branches: `dev`, `staging`, and `prod`. To update the prod branch, a developer will: + +1. Create a new feature branch directly from the `dev` branch +2. Make changes on that feature branch +3. Test locally +4. When ready, open a pull request to merge their changes back into the `dev` branch + +In this hierarchical promotion, once a set of feature branches are vetted in `dev`: + +5. The entire `dev` branch is merged into the `staging` branch + +After a final review of the `staging` branch: + +6. The entire `staging` branch is merged into the `prod` branch + +![Multi-environment workflow](/img/blog/2022-09-13-the-case-against-cherry-picking/2_multienvironment.png) + +While this approach—often referred to as “continuous delivery” or “indirect promotion”—is more complex, it allows for a higher level of protection for your production code. You can think of these additional branches as layers of protective armor. The more layers you have, the harder it will be to move quickly and nimbly on the battlefield, but you’ll also be less likely to sustain injuries. If you’ve ever played D&D, you’ll understand this tradeoff. + +Because these additional branches slow down your development workflow, organizations may be tempted to add *more complexity* to increase their speed—selecting individual changes to merge into upper branches (in our example, `staging` and `prod`), rather than waiting to promote an entire branch. That’s right, I’m talking about the beast that is **cherry picking into upper branches**. + +:::info What is cherry picking? + +`git cherry-pick` is a git command that allows you to apply individual commits from one branch into another branch. + +::: + +In theory, cherry picking seems like a good solution: it allows you to select individual changes for promotion into upper branches to unblock developers and increase speed. + +In practice, however, when cherry picking is used this way, it introduces more risk and complexity and (in my opinion) is not worth the tradeoff. Cherry picking into upper environments can lead to: + +- Greater risk in breaking hierarchical relationship of primary branches +- Flawed testing practices that don’t account for dependent code changes +- Increase chance of merge conflicts, draining developer time and prone to human error + +![Gru meets cherry picking](/img/blog/2022-09-13-the-case-against-cherry-picking/3_gru.jpg) + +## If you’re not testing changes independently, you shouldn’t promote them independently + +If you’ve attempted a branching strategy that involves cherry picking into upper environments, you’ve probably encountered a scenario like this, where feature branches are only tested in combination with others: + +![Feature branches tested in combination with others](/img/blog/2022-09-13-the-case-against-cherry-picking/4_scenario_1.png) + +1. Alex wants to make a code change, so they create a new branch from `dev` called `feature_alex` +1. Becca has a different code change she’s working on, so she creates a new branch from dev called `feature_becca` +1. Alex’s changes are approved, so they merge `feature_alex` into `dev`. +1. Becca’s changes are approved, so she merges `feature_becca` into `dev`. +1. Carol is working on something else, so she creates a new branch from `dev` called `feature_carol`. +1. Carol’s changes are approved, so she merges `feature_carol` into `dev`. +1. The testing team notices an issue with Carol’s new addition to `dev`. +1. Alex and Becca’s changes are urgent and need to be promoted soon, they can’t wait for Carol to fix her work. Alex and Becca cherry-pick their changes from `dev` into `staging`. +1. During final checks, the team notices an issue with Alex’s changes in `staging`. +1. Becca is adamant that her changes need to be promoted to production immediately. She can’t wait for Alex to fix their work. Becca cherry-picks her changes from `staging` into `prod`. + +**What’s the problem?** + +In the example above, the team has only ever tested `feature_becca` *in combination with* `feature_alex` —so there’s no guarantee that `feature_becca`’s changes will be successful on their own. What if `feature_becca` was relying on a change included in `feature_alex`? Because testing of branches is not conducted independently, it’s risky to merge independently. + +## Feature branches contain more than meets the eye + +Let’s imagine another version of the story, where Carol’s changes are the only ones that are ultimately merged into `prod`: + +![Feature branches contain more than meets the eye...](/img/blog/2022-09-13-the-case-against-cherry-picking/5_scenario_2.png) + +1. Alex wants to make a code change, so they create a new branch from `dev` called `feature_alex`. +1. Becca has a different code change she’s working on, so she creates a new branch from `dev` called `feature_becca`. +1. Alex’s changes are approved, so they merge `feature_alex` into `dev`. +1. Becca’s changes are approved, so she merges `feature_becca` into `dev`. +1. Carol is working on something else, so she creates a new branch from `dev` called `feature_carol`. +1. Carol’s changes are approved, so she merges `feature_carol` into `dev`. +1. The testing team approves the entire `dev` branch. +1. `dev` is merged into `staging`. +1. During final checks, the team notices an issue with Alex and Becca’s changes in `staging`. +1. Carol is adamant that her changes need to be promoted to production immediately. She can’t wait for Alex or Becca to fix their work. Carol cherry-picks her changes from `staging` into `prod`. + +**What’s the difference?** + +Because `feature_carol` was created *after* `feature_alex` and `feature_becca` were already merged back into `dev`, `feature_carol` is *dependent* on the changes made in the other two branches. `feature_carol` not only contains its own changes, it *also* carries the changes from `feature_alex` and `feature_becca`. Even if Carol recognizes this and only cherry-picks the *individual* *commits* from `feature_carol`, she’s still not in the clear because of the previously mentioned testing dependency. `feature_carol`’s commits have only ever been tested *in combination with* `feature_alex` and `feature_becca`. + +## Repeated merge conflicts drain development time + +In order to avoid this dependency issue, your team might have the idea to create feature branches directly from `prod` (instead of `dev`). If we imagine the previous scenario with this alteration, however, we can easily see why this doesn’t work either: + +![Development branches made from prod](/img/blog/2022-09-13-the-case-against-cherry-picking/6_scenario_3.png) + +1. Alex wants to make a code change, so they create a new branch from `prod` called `feature_alex`. +1. Becca has a different code change she’s working on, so she creates a new branch from `prod` called `feature_becca`. +1. Alex’s changes are approved, so they merge `feature_alex` into `dev`. +1. Becca’s changes are approved, so she merges `feature_becca` into `dev`. +1. Carol is working on something else, so she creates a new branch from `prod` called `feature_carol`. +1. Carol’s changes are approved, so she merges `feature_carol` into `dev`. +1. The testing team approves the entire `dev` branch. +1. `dev` is merged into `staging`. +1. During final checks, the team notices an issue with Alex and Becca’s changes in `staging`. +1. Carol is adamant that her changes need to be promoted to production immediately. She can’t wait for Alex or Becca to fix their work. Carol cherry-picks her changes from `staging` into `prod`. + +Now, `feature_carol` only contains its individual changes—the team can merge her branch independently into `dev`, `staging`, and ultimately `prod` without worrying about accidentally pulling along the changes from the other two branches. + +**What’s the problem?** + +A new issue emerges, however, if `feature_alex` or `feature_becca` alter the *same lines of code* as `feature_carol`. When `feature_carol` is merged into each of the primary branches, Carol will have to solve merge conflicts every time in the exact same way to ensure the hierarchy of the branches remain consistent. This takes time and is prone to human error. + +## What to do instead: The recommended branching strategy for multi-environment dbt projects + +![Bernie is begging you to stop cherry picking](/img/blog/2022-09-13-the-case-against-cherry-picking/7_bernie.jpg) + +In the end, **cherry picking into upper branches** is a branching strategy that causes more trouble than it’s worth. + +Instead, if you decide to use a branching strategy that involves multiple primary branches (such as `dev`, `staging`, and `prod`): + +- Protect your `dev` branch with a dbt cloud [CI job](https://docs.getdbt.com/docs/dbt-cloud/using-dbt-cloud/cloud-enabling-continuous-integration) +- Ensure thorough code reviews (check out our recommended [PR template](https://docs.getdbt.com/blog/analytics-pull-request-template)) +- Only promote each primary branch hierarchically into each other + +![Hierarchical branching strategy](/img/blog/2022-09-13-the-case-against-cherry-picking/2_multienvironment.png) + +If issues arise during testing on the `dev` or `staging` branch, the developers should create additional branches as necessary to fix the bugs until the *entire* branch is ready to be promoted. + +As mentioned previously, this approach does have a clear disadvantage—it might take longer to fix all of the bugs found during testing, which can lead to: + +- Delayed deployments +- Code freezes on `dev`, creating a backup of out-dated feature branches waiting to be merged + +Thankfully, we can mitigate these delays by doing rigorous testing on the *individual* feature branches, ensuring the team is extremely confident about the change *prior* to merging the feature branch into `dev`. + +Additionally, developers may supplement the above workflow by creating hotfixes to quickly resolve bugs in upper environments + +:::info What is a hotfix? + +A `hotfix` is a branch that is created to quickly patch a bug typically in your production code. If a high-stakes bug was discovered in `prod`, a hotfix branch would be created from `prod`, then merged into `prod` as well as *all subordinate branches* (`dev` and `staging`) once the change has been approved. Similarly, if a high-stakes bug were discovered in `staging`, a hotfix branch would be created from `staging`, then merged into `staging` as well as *all subordinate branches* (`dev`) once the change has been approved. This allows you to fix a bug in an upper environment without having to wait for the next full promotion cycle, but also ensures the hierarchy of your primary branches is not lost. + +::: + +Even with its challenges, hierarchical branch promotion is the recommended branching strategy when handling multiple primary branches because it: + +- Simplifies your development process: Your team runs more efficiently with less complex rules to follow +- Prevents merge conflicts: You save developer time by avoiding developers having to manually resolve sticky merge conflicts over and over +- Ensures the code that's tested is the code that is ultimately merged into production: You avoid crisis scenarios where unexpected bugs sneak into production + +Now I’ll admit it: this blog post was mostly just a venting session, providing me a cathartic outlet to rage against cherry picking (my Slack dms are open if you want to see all of the memes that *didn’t* make it into this post). + +And you may be left thinking… ok, jeez Grace, I won’t cherry pick into upper branches. But how do I *actually* set up my dbt project to properly use hierarchical branch promotion? + +Don’t worry, a guide and training course are on the way ;) diff --git a/website/blog/2022-09-28-analyst-to-ae.md b/website/blog/2022-09-28-analyst-to-ae.md new file mode 100644 index 00000000000..b6d03b81782 --- /dev/null +++ b/website/blog/2022-09-28-analyst-to-ae.md @@ -0,0 +1,163 @@ +--- +title: "Analysts make the best analytics engineers" +description: "You often hear of the disgruntled analyst becoming the analytics engineer..and loving it? In this article, Brittany walks through what makes analysts ripe for analytics engineering." +slug: analysts-make-the-best-aes +authors: [brittany_krauth] +tags: [analytics craft] +hide_table_of_contents: false + +date: 2022-09-29 +is_featured: true +--- + +When you were in grade school, did you ever play the “Telephone Game”? The first person would whisper a word to the second person, who would then whisper a word to the third person, and so on and so on. At the end of the line, the final person would loudly announce the word that they heard, and alas! It would have morphed into a new word completely incomprehensible from the original word. That’s how life feels without an analytics engineer on your team. + +So let’s say that you have a business question, you have the raw data in your , and you’ve got dbt up and running. You’re in the perfect position to get this curated dataset completed quickly! Or are you? + + + +You’ve got three steps that stand between you and your finished curated dataset. *If you don’t have an analytics engineer*, then the work may be split up like this: + +![The in series development workflow](/img/blog/2022-09-28-analyst-to-ae/old_workflow.png) + +The first step is that your analyst will start researching the stakeholder’s request and will try to boil it down to a high-impact question that will drive the business. What do they really want to know? For example, your stakeholder might come to you with the following: + +***“We need to be able to track usage of our product, and we’d like to have some data around Active Users.”*** + +Analysts are experts at taking broad statements and turning them into specific pieces of work. + +“Some data” could mean: + +1. A single KPI with a trendline over time +1. A dashboard broken out into various categories +1. A filterable and queryable table for ad-hoc analysis + +“Active Users” could mean: + +1. Users that logged in during a fixed time period +1. Users with a session longer than a certain amount of time +1. Users that interacted with a particular feature + +From there, the analyst will build out the initial documentation and write down what they want the final dataset to look like. If your analyst is not trained as an analytics engineer, this is the point that they will need to hand the project over to a data engineer to build the [model](https://docs.getdbt.com/docs/building-a-dbt-project/building-models). + +The first time that a team of analysts and data engineers builds a curated dataset, they will often expect this process to be a straight line to completion. Expectations are that the process will look something like this: + +![The expectation](/img/blog/2022-09-28-analyst-to-ae/first_loop.png) + +What quickly becomes apparent is that this push for a linear process often ends up creating three unanticipated “loops”: + +![The reality](/img/blog/2022-09-28-analyst-to-ae/multiple_loops.png) + +## Loop 1: Reacting to findings in the raw data + +Let’s say that your analyst has defined the business need as an `Active Users` dataset with “Unique users that log in during a given day”. The analyst will try to do as much discovery work up-front as possible, because it’s hard to predict exactly what you’ll find in the raw data. When a data engineer gets stuck writing a model, they’ll need to reach out to the analyst for some additional discovery. When an analyst-turned-analytics-engineer has a question while writing a model, they don’t need to wait to talk to anyone, and they can begin researching it immediately. Which brings us to our first point: + +

Analysts already know the data that they want.

+ +If the raw `Login` dataset below contains two different date (`Login_Date` and `Session_Date`) fields, a data engineer would be stuck. They can’t just guess because using the wrong date field will create an entirely different metric! So they must go back to the analyst for clarity on which field to use. We’ve just had a full loop with two hand-offs, and the data engineer hasn’t even begun building the model yet. + +| Login_Date | Session_Date | User_Id | +|------------|--------------|---------| +| 2022-08-01 | 2022-08-01 | 123 | +| 2022-08-01 | 2022-08-03 | 123 | +| 2022-08-04 | 2022-08-04 | 975 | +| 2022-08-04 | 2022-08-04 | NULL | + +In comparison, your new analytics engineer could quickly pivot based on the findings in the raw data. They can skip the endless loops of “discovery”, because they can react in the moment. When they see the two date fields for `Login_Date` and `Session_Date`, they can instantly apply their product knowledge, compare against examples, or reach out to their business contacts to diagnose the difference and select the correct date for the model. + +If the business need includes looking at `Active Users` by `Groups A, B, and C`, then that adds an extra layer of complexity. Without an analytics engineer, you’ll see extra loops and hand-offs to finalize all the business logic, how to handle NULL values, and even just the final format. + +**Model format returned by data engineering** + +| Date | Active Users Group A | Active Users Group B | Active Users Group C | +|------------|----------------------|----------------------|----------------------| +| 2022-08-01 | 34 | 60 | 61 | +| 2022-08-02 | 77 | 86 | 37 | +| 2022-08-03 | 71 | 9 | 6 | +| 2022-08-04 | 63 | 87 | 10 | + +**Model format needed for the BI tool** + +| Date | Group | Active Users | +|------------|---------|--------------------| +| 2022-08-01 | Group A | 34 | +| 2022-08-01 | Group B | 60 | +| 2022-08-01 | Group C | 61 | +| 2022-08-02 | Group A | 77 | +| 2022-08-02 | Group B | 86 | +| 2022-08-02 | Group C | 37 | + +## Loop 2: Reacting to unexpected results + +Analysts are the first (and sometimes only) line of defense to catch data quality issues. Once a dataset is aggregated down to a single number to answer a business question, it’s often impossible to know if there’s an incorrect filter or wrong set of logic. + +When a model is built for the first time, all parties often “don’t know what they don’t know”. As the analyst digs into the curated dataset, they will find updates that need to be made to the model. Hence, our second point: + +

Analysts question everything.

+ +`Group A` for `Active Users` may be focused on `Participant` roles. The stakeholder had explained to the analyst that they want to exclude any `Admins` that will have a different experience in the product. + +| User_Id | Location | Role | Level | Zone | +|---------|------------|-------------|-------|------| +| 123 | California | Editor | AAA | 1 | +| 427 | Utah | Participant | ABA | 1 | +| 864 | Georgia | Admin | CCC | 3 | + +A data engineer working off of a “build list” will add a filter for `WHERE Role = 'Participant'`. During the data validation step, the analyst would discover that there is actually a third `Role` of `Editor` that no one was aware of. This would create a loop where the data engineer would have to edit the model to replace it with `WHERE Role != 'Admin'`. + +The analyst caught the issue because they have the appropriate context to validate the dataset. Analysts work directly with the stakeholder, so they’ll also be more familiar with company-specific and department-specific acronyms. + +**As we all know, data validation is an art, not a science.** Analysts will employ everything from a “sniff test” (view a random sample of rows) to individual examples (one-to-one exact matching to another system). An analyst will have to use their experience to know when the dataset is “good enough” for the stakeholder and their question since 100% accuracy might not be the goal. And if we're being honest, sometimes being directionally correct is all that’s needed to make a business decision. + +An analyst is able to identify which areas do *not* need to be 100% accurate, which means they can also identify which areas *do* need to be 100% accurate. + +> dbt makes it very quick to add [data quality tests](https://docs.getdbt.com/docs/building-a-dbt-project/tests). In fact, it’s so quick, that it’ll take an analyst longer to write up what tests they want than it would take for an analyst to completely finish coding them. + +When data quality issues are identified by the business, we often see that analysts are the first ones to be asked: + +- Why are over half of the `User_Ids` now showing as NULL? +- Why is this chart showing a User’s `Location` that’s not in the USA? +- Why is the dashboard filter saying that all User’s `Zones` are Zone 2? + +This familiarity with what types of data quality issues are the most important to the business means that an analyst can often identify in advance which automated tests should be added to a data model. + +## Loop 3: Reacting to mismatched documentation + +There’s nothing worse than coming back to view a curated dataset months later (or maybe after someone on the team has offboarded) and learning that there is nothing written to explain why certain logic exists. Or worse, the documentation exists but it no longer matches what the model actually does. Which brings us to our third and final point: + +

Analysts understand the pain of a poorly documented dataset.

+ +It’s much easier to keep to a naming guide when the writer has a deep understanding of the data and how it’s referenced by the business. Analysts are often asked repeat questions by stakeholders, which is extra incentive to create great documentation from the beginning. + +> A data engineer will document a dataset based on what they needed to know to build it. An analyst with analytics engineering skills will document a dataset based on *how to use it going forward.* + +If we want to know how certain logic was built technically, then we can reference the SQL code in dbt docs. If we want to know *why* a certain logic was built into that specific model, then that’s where we’d turn to the documentation. + +- Example of not-so-helpful documentation ([dbt docs can](https://docs.getdbt.com/docs/building-a-dbt-project/documentation) build this dynamically): + - `Case when Zone = 1 and Level like 'A%' then 'True' else 'False' end as GroupB` +- Example of better, more descriptive documentation (add to your dbt markdown file or column descriptions): + - Group B is defined as Users in Zone 1 with a Level beginning with the letter 'A'. These users are accessing our new add-on product that began in Beta in August 2022. It's recommended to filter them out of the main Active Users metric. + +In the second example, the documentation is written with the stakeholder and business in mind, and analysts are experts at this translation of the technical to the non-technical. + +## Are you convinced? + +Teach your analyst to be an analytics engineer, so they can do their own model building for curated datasets. You’ll start to see their process evolve into multiple smaller iterations, as they add fields and test them as they build. No loops, no hand-offs, and no Telephone Game. Your new workflow will look a little like this: + +![Parallel development](/img/blog/2022-09-28-analyst-to-ae/new_workflow.png) + +Instead of trying to define all the various groups of `Active Users` at once, an analytics engineer can be validating the `Group A` rows, while adding `Group B` to their local environment, while still working with the stakeholder on the definition of `Group C`. + +**All this to say: Your analyst turned analytics engineer is the key to unlocking fast development of curated datasets with next-level data quality and documentation.** + +### How to empower your analysts to level up their skillset + +Here are some next steps to get you started on converting your analysts to analytics engineers: + +1. Many analysts are already very comfortable querying data using SQL Select statements. For those that aren’t, challenge them to start pulling data for ad-hoc requests using SQL. Ask them to compare some of the common transformations in your BI tool to SQL functions or rebuild them using CTEs. This will prepare them for learning about dbt SQL models. +1. Start incorporating peer review as part of the dashboard publishing process. Also, consider how you set up your dashboard environments (do you have a local development area, a review area, and a published area?). This will prepare them for learning about Git, development environments, and version control. +1. Talk to your analyst about how they decide to create alerts in your BI tool, or any regular reviews that they do of existing dashboards for data accuracy. And what are the current data governance practices that each dashboard follows (Data Dictionary? Style Guide?). This will prepare them for learning about the dbt `.yml` file. + +Learn more on how to apply a fresh framework to existing analytics projects to upskill your ***Analyst to an Analytics Engineer*** at my [Coalesce 2022 presentation](https://coalesce.getdbt.com/agenda/analyst-to-analytics-engineer). I hope to see you there! + + diff --git a/website/blog/authors.yml b/website/blog/authors.yml new file mode 100644 index 00000000000..7bea8c29395 --- /dev/null +++ b/website/blog/authors.yml @@ -0,0 +1,357 @@ +david_krevitt: + name: David Krevitt + job_title: Marketing + image_url: /img/blog/authors/dkrevitt.jpg + organization: dbt Labs + description: Laziness is a virtue + links: + - url: https://twitter.com/dkrevitt + icon: fa-twitter + +jason_ganz: + name: Jason Ganz + job_title: Developer Experience + organization: dbt Labs + image_url: /img/blog/authors/jasnonaz.jpeg + links: + - url: https://twitter.com/jasnonaz + icon: fa-twitter + +sanjana_sen: + name: Sanjana Sen + job_title: Analytics Engineer + organization: dbt Labs + image_url: /img/blog/authors/sanjana.png + links: + - url: https://twitter.com/sqlsanj + icon: fa-twitter + +lauren_craigie: + name: Lauren Craigie + job_title: Product Marketing + organization: dbt Labs + image_url: /img/blog/authors/craigie.png + links: + - url: https://twitter.com/crai_fish + icon: fa-twitter + +andrew_escay: + name: Andrew Escay + job_title: Analytics Engineer + organization: dbt Labs + image_url: /img/blog/authors/aescay.jpeg + links: + - url: https://twitter.com/_aescay + icon: fa-twitter + +jess_williams: + name: Jess Williams + job_title: Head of Professional Services + organization: dbt Labs + image_url: /img/blog/authors/jess.png + links: + - url: https://www.linkedin.com/in/jessdwilliams/ + icon: fa-linkedin + +pat_kearns: + name: Pat Kearns + job_title: Senior Analytics Engineer + organization: dbt Labs + image_url: /img/blog/authors/pkearns.png + links: + - url: https://www.linkedin.com/in/pat-kearns/ + icon: fa-linkedin + +amy_chen: + name: Amy Chen + job_title: Senior Partner Engineer + organization: dbt Labs + image_url: /img/blog/authors/achen.png + links: + - url: https://www.linkedin.com/in/yuanamychen/ + icon: fa-linkedin + +joel_labes: + name: Joel Labes + job_title: Senior Developer Experience Advocate + organization: dbt Labs + image_url: /img/blog/authors/jlabes.png + links: + - url: https://www.linkedin.com/in/joel-labes/ + icon: fa-linkedin + - url: https://twitter.com/joellabes + icon: fa-twitter + +claire_carroll: + name: Claire Carroll + job_title: Analytics Engineer + organization: analyticsengineers.club + image_url: /img/blog/authors/claire.jpeg + links: + - url: https://twitter.com/clairebcarroll + icon: fa-twitter + - url: https://github.com/clrcrl + icon: fa-github + - url: https://www.linkedin.com/in/clrcrl/ + icon: fa-linkedin + +dave_connors: + name: Dave Connors + job_title: Senior Analytics Engineer + organization: dbt Labs + image_url: /img/blog/authors/dconnors.jpeg + links: + - url: https://github.com/dave-connors-3 + icon: fa-github + - url: https://www.linkedin.com/in/daveconnors3/ + icon: fa-linkedin + +ross_turk: + name: Ross Turk + job_title: VP Marketing + organization: Datakin + image_url: /img/blog/authors/ross-turk.png + links: + - url: https://mobile.twitter.com/rossturk + icon: fa-twitter + - url: https://github.com/rossturk + icon: fa-github + +sung_chung: + name: Sung Won Chung + job_title: Solutions Architect + organization: dbt Labs + image_url: /img/blog/authors/sung.jpeg + links: + - url: https://www.linkedin.com/in/sungwonchung1/ + icon: fa-linkedin + +seth_rosen: + name: Seth Rosen + job_title: Co-Founder & CEO + organization: TopCoat Data + description: Seth Rosen is co-founder and CEO of TopCoat Data - a platform for helping organizations build analytical applications. Prior to founding TopCoat, Seth helped companies of all sizes build custom data apps on top of the modern data stack through his consultancy, Hashpath. When he’s not tweeting and thinking about data, he’s tweeting while parenting two toddlers. + image_url: /img/blog/authors/seth-rosen.jpeg + links: + - url: https://twitter.com/sethrosen + icon: fa-twitter + - url: https://www.linkedin.com/in/sdrosen/ + icon: fa-linkedin + +donny_flynn: + name: Donny Flynn + job_title: Customer Data Architect + organization: Census + description: Donny Flynn is a customer data architect at Census - a reverse ETL product that helps companies operationalize analytics. Prior to joining Census, Donny built out the data stack at Owner and led a data team at Chiper. When not doing data work, he's most likely watching Chicago sports. + image_url: /img/blog/authors/dflynn.jpeg + links: + - url: https://twitter.com/donmandonguy + icon: fa-twitter + - url: https://www.linkedin.com/in/donny-flynn-578149a4/ + icon: fa-linkedin + +izzy_erekson: + name: Izzy Erekson + job_title: Solutions Architect + organization: dbt Labs + image_url: /img/blog/authors/izzy.jpeg + +nate_sooter: + name: Nate Sooter + job_title: Manager of BI Operations + organization: Smartsheet + image_url: /img/blog/authors/nate-sooter.jpeg + links: + - url: https://twitter.com/natesooter + icon: fa-twitter + - url: https://www.linkedin.com/in/nathansooter + icon: fa-linkedin + +kira_furuichi: + name: Kira Furuichi + job_title: Technical Writer + organization: dbt Labs + image_url: /img/blog/authors/kira-furuichi.png + links: + - url: https://www.linkedin.com/in/kira-furuichi/ + icon: fa-linkedin + +simon_podhajsky: + name: Simon Podhajsky + job_title: Data Lead + organization: iLife Technologies + description: > + Simon Podhajsky is a lapsed neuroscientist turned data everything at iLife + Technologies, a startup that seeks to digitize the life insurance agency. + image_url: /img/blog/authors/simon-podhajsky.jpeg + links: + - url: https://www.linkedin.com/in/simonpodhajsky/ + icon: fa-linkedin + - url: https://twitter.com/sim_pod + icon: fa-twitter + +viraj_parekh: + name: Viraj Parekh + job_title: Field CTO + organization: Astronomer + image_url: /img/blog/authors/viraj-parekh.jpeg + links: + - url: https://www.linkedin.com/in/viraj-parekh-46114689/ + icon: fa-linkedin + +josh_fell: + name: Josh Fell + job_title: Ecosystem Engineer + organization: Astronomer + image_url: /img/blog/authors/josh-fell.jpeg + links: + - url: https://www.linkedin.com/in/josh-fell/ + icon: fa-linkedin + +simo_tumelius: + name: Simo Tumelius + job_title: Freelance Data and Analytics Engineer + image_url: /img/blog/authors/simo-tumelius.jpeg + links: + - url: https://www.linkedin.com/in/simo-tumelius-00a27a162/ + icon: fa-linkedin + +matt_winkler: + name: Matt Winkler + job_title: Senior Solutions Architect + organization: dbt Labs + description: Matt is an ex-data scientist who chose to embrace the simplicity of using SQL to manage and testing data pipelines with dbt. He previously worked as a hands-on ML practitioner, and consulted with Fortune 500 clients to build and maintain ML Ops pipelines using (mostly) AWS Sagemaker. He lives in the Denver area, and you can say hello on dbt Slack or on LinkedIn. + image_url: /img/blog/authors/matt-winkler.jpeg + links: + - url: https://www.linkedin.com/in/matt-winkler-4024263a/ + +jonathan_natkins: + name: Jon "Natty" Natkins + job_title: Regional Director, Solutions Architecture + organization: dbt Labs + description: Natty also writes about startups, equity, data, and more in his Substack called [Semi-Structured](http://semistructured.substack.com/). + image_url: /img/blog/authors/jonathan-natkins.jpeg + links: + - url: https://www.linkedin.com/in/nattyice/ + icon: fa-linkedin + - url: https://twitter.com/nattyice + icon: fa-twitter + +lauren_benezra: + name: Lauren Benezra + job_title: Analytics Engineer + organization: dbt Labs + image_url: /img/blog/authors/lauren-benezra.jpeg + links: + - url: https://www.linkedin.com/in/lbenezra/ + icon: fa-linkedin + +christine_berger: + name: Christine Berger + job_title: Senior Analytics Engineer + organization: dbt Labs + image_url: /img/blog/authors/christine-berger.jpeg + +grace_goheen: + name: Grace Goheen + job_title: Analytics Engineer + organization: dbt Labs + image_url: /img/blog/authors/grace-goheen.jpeg + links: + - url: https://www.linkedin.com/in/gracegoheen/ + icon: fa-linkedin + +jeremy_cohen: + name: Jeremy Cohen + job_title: Product Manager + organization: dbt Labs + image_url: /img/blog/authors/jerco.jpeg + +doug_beatty: + name: Doug Beatty + job_title: Senior Developer Experience Advocate + organization: dbt Labs + image_url: /img/blog/authors/dbeatty.jpeg + +callum_mccann: + name: Callum McCann + job_title: Senior Developer Experience Advocate + organization: dbt Labs + description: Callum works on metrics and is either talking about that or obsessing about his dog. + image_url: /img/blog/authors/callum-mccann.jpg + links: + - url: https://www.linkedin.com/in/callum-mccann-38628a89/ + icon: fa-linkedin + - url: https://twitter.com/callumpmccann + icon: fa-twitter + +benoit_perigaud: + name: Benoit Perigaud + job_title: Senior Analytics Engineer + organization: dbt Labs + image_url: /img/blog/authors/benoit-perigaud.jpeg + links: + - url: https://www.linkedin.com/in/benoit-perigaud/ + icon: fa-linkedin + +bennie_regenold: + name: Bennie Regenold + job_title: Analytics Engineer + organization: dbt Labs + image_url: /img/blog/authors/bennie-regenold.png + links: + - url: https://www.linkedin.com/in/benjaminregenold/ + icon: fa-linkedin + +barr_yaron: + name: Barr Yaron + job_title: Product Manager + organization: dbt Labs + image_url: /img/blog/authors/barr-yaron.png + links: + - url: https://www.linkedin.com/in/barryaron/ + icon: fa-linkedin + +ian_fahey: + name: Ian Fahey + job_title: Analytics Engineer + organization: dbt Labs + image_url: /img/blog/authors/ian-fahey.png + links: + - url: https://www.linkedin.com/in/ianmfahey/ + icon: fa-linkedin + - url: https://twitter.com/Cavorax + icon: fa-twitter + +joe_markiewicz: + name: Joe Markiewicz + job_title: Analytics Engineering Manager (Fivetran dbt package maintainer) + description: Joe is a dbt package maintainer/manager at Fivetran by day, and a cat obsessed video game developer by night. Actually, Joe is cat obsessed all day. + organization: Fivetran + image_url: /img/blog/authors/joe-markiewicz.jpeg + links: + - url: https://www.linkedin.com/in/joseph-markiewicz-8224a990/ + icon: fa-linkedin + - url: https://twitter.com/JoeMarkiewicz17 + icon: fa-twitter + +yu_ishikawa: + name: Yu Ishikawa + job_title: Senior Data Privacy Engineer + organization: Ubie + image_url: /img/blog/authors/yu-ishikawa.jpg + links: + - url: https://www.linkedin.com/in/yuishikawa0301 + icon: fa-linkedin + +brittany_krauth: + name: Brittany Krauth + job_title: Manager, Analytics & Insights + description: Brittany Krauth works as Manager, Analytics & Insights supporting Degreed's upskilling platform. Brittany is passionate about building a company-wide data-driven culture. She has worked in various analytical roles, from a focus on predictive analytics to data visualization to process improvements. In addition, she holds a BS in Industrial Engineering from Georgia Tech. In her spare time, Brittany competes in dog agility and trains donkeys. + organization: Degreed + image_url: /img/blog/authors/brittany-krauth.png + links: + - url: https://www.linkedin.com/in/brittanykrauth + icon: fa-linkedin + + diff --git a/website/blog/categories.yml b/website/blog/categories.yml new file mode 100644 index 00000000000..2a45e6529e2 --- /dev/null +++ b/website/blog/categories.yml @@ -0,0 +1,25 @@ +# Note +# These are not required to add tags to blog posts +# This adds the tag to the Categories sidebar +# and allows to add custom descriptions for tags + +- name: analytics craft + display_title: Analytics craft + description: The art of being an analytics practitioner. + is_featured: true +- name: data ecosystem + display_title: Data ecosystem + description: Walkthroughs of how top data practitioners use tools in the modern data stack. + is_featured: true +- name: dbt tutorials + display_title: dbt tutorials + description: Best practices in the usage of our favorite data transformation tool. + is_featured: true +- name: dbt updates + display_title: dbt product updates + description: An archive of monthly product updates from the dbt Labs team. + is_featured: true +- name: SQL magic + display_title: SQL magic + description: Stories of dbt developers making SQL sing across warehouses. + is_featured: true diff --git a/website/blog/ctas.yml b/website/blog/ctas.yml new file mode 100644 index 00000000000..21a02255400 --- /dev/null +++ b/website/blog/ctas.yml @@ -0,0 +1,12 @@ +# name property should not be changed once set +# or references to CTA will break +- name: coalesce + header: Missed Coalesce? + subheader: The annual conference dedicated to the advancement of analytics engineering wrapped up on December 10th. + button_text: Watch the talks + url: https://getdbt.com/coalesce-2021/ +- name: setup + header: "Just Getting Started?" + subheader: Check out guides on getting your warehouse set up and connected to dbt Cloud. + button_text: Learn more + url: https://docs.getdbt.com/guides/getting-started/getting-set-up diff --git a/website/blog/maching-learning-dbt-baton-pass.md b/website/blog/maching-learning-dbt-baton-pass.md new file mode 100644 index 00000000000..7046ecb296a --- /dev/null +++ b/website/blog/maching-learning-dbt-baton-pass.md @@ -0,0 +1,180 @@ +--- +title: "dbt + Machine Learning: What makes a great baton pass?" +description: "Working with machine learning in dbt can be clunky. Explore three tool paths that makes the baton pass between analytics engineering & machine learning smooth." +slug: maching-learning-dbt-baton-pass + +authors: [sung_chung, izzy_erekson] + +tags: [data ecosystem] +hide_table_of_contents: false + +date: 2022-03-10 +is_featured: true +--- +_Special Thanks: Emilie Schario, Matt Winkler_ + +dbt has done a great job of building an elegant, common interface between data engineers, analytics engineers, and any data-y role, by uniting our work on SQL. This unification of tools and workflows creates interoperability between what would normally be distinct teams within the data organization. + +I like to call this interoperability a “baton pass.” Like in a relay race, there are clear handoff points & explicit ownership at all stages of the process. But there’s one baton pass that’s still relatively painful and undefined: the handoff between machine learning (ML) engineers and analytics engineers. + +In my experience, the initial collaboration workflow between ML engineering & analytics engineering starts off strong but eventually becomes muddy during the maintenance phase. This eventually leads to projects becoming unusable and forgotten. + +In this article, we’ll explore a real-life baton pass between ML engineering and analytics engineering and highlighting where things went wrong. + + + +By doing so, we can hopefully solve this breakdown by answering questions like: + +- Do we need a better Jupyter notebook? +- Should we increase the SQL surface area to build ML models? +- Should we leave that to non-SQL interfaces(Python/Scala/etc.)? +- Does this have to be an either/or future? + +Whatever the interface evolves into, it must center people, create a low bar and high ceiling, and focus on outcomes and not the mystique of high learning curves. + +**TL;DR: There’s an ownership problem in the ML engineering & analytics engineering workflow. Luckily, the Modern Data Stack is making this baton pass smoother. This post will walk you through a recent project where I was able to see firsthand how these systems can work together to provide models that are built for long term accuracy and maintainability.** + +## What does a baton pass look like today? + +As an analytics engineer, I was paired with a ML engineer to determine when a customer will churn and what actions we could take to prevent it. We labored over a solution, the mechanics kind of worked, we presented to business stakeholders that wanted this, and 1 month later we were hopeful but skeptical. New data changes caused model drift, so the ML engineer logged a ticket for the data engineer/analytics engineer to fix…3 months later, no one remembered we did this. Does this sound familiar? + +This happens because the “normal” way of doing things lacks long-term & explicit ownership. But how do these breakdowns happen? + +### Here’s what happened + +After some initial planning, I knew we had this raw data living somewhere in our . It was easy to make sense of this starting point for our work together. I wrote dbt transformations to massage this raw data and joined a couple tables together based on intuition of what variables mattered: daily active usage, number of users, amount paid, historical usage, etc. + +The ML engineer stepped in from here. She was used to doing her statistics and preprocessing in python [pandas](https://pandas.pydata.org/) and [scikit-learn](https://scikit-learn.org/stable/index.html). Before she opened up her Jupyter notebook, we had a heart-to-heart conversation and realized the same work could be done through dbt. Preprocessing could be done through this [open source dbt package](https://github.com/omnata-labs/dbt-ml-preprocessing/tree/1.1.0/#dbt-ml-preprocessing) and there were plenty of others like it in the [package registry](https://hub.getdbt.com/). + +![image of table with macro names and connector compatibility](/img/blog/2022-02-18-machine-learning-dbt-baton-pass/macro-names.png) + +The ML engineer got the preprocessing steps (think: one-hot encoding, feature scaling, imputation) finalized. She used SQL to read the dbt models (tables) into a Jupyter notebook to perform model training. After iterating on the machine learning models and tracking model fit (think: AUC/Precision/Recall (for classification)), she ran the model over dbt-created tables and output the predicted results as a table in the database. To keep documentation clean, she [configured a source](https://docs.getdbt.com/docs/building-a-dbt-project/using-sources/) within the dbt project to reflect this predicted results table. It wasn’t intuitive, but it was better than leaving it out of dbt docs. + +Finally, she created a dashboard on top of this table to publicize model accuracy over time to end users. To schedule this, we went to the data engineer to string together the above in [Airflow](https://discourse.getdbt.com/t/orchestrating-fivetran-and-dbt-with-airflow/2079) everyday at 8am and called it done. + +### Core Behaviors and Results (Where things went wrong) + +Let’s parse out the job-to-be-done we’re seeing in our story. + +![Image flowchart of the story's Jobs to be Done workflow](/img/blog/2022-02-18-machine-learning-dbt-baton-pass/JTBD-workflow.png) + +| Jobs to be Done | Intended Results | Role | +| --- | --- | --- | +| Extract and load raw data into database | SQL-ready data | Data Engineer | +| Transforming data for business user consumption | Data is coherent to make decisions from | Analytics Engineer, ML engineer | +| Working with structured, tabular data | Unified and practical workflow | Analytics Engineer, ML engineer | +| Working in SQL | Unified and practical workflow | Analytics Engineer, ML engineer | +| Equipping users with documentation to understand how data outputs are created and how to use them | Trust and context for data | Analytics Engineer, ML engineer | +| Testing transformed data outputs | Trusted data | Analytics Engineer | +| Testing pre-processing data outputs | Trusted data | ML engineer | +| Training and deploying machine learning models(primarily in python) | Make predictive decisions | ML engineer | +| Testing and maintaining machine learning table outputs over time | Prove predicted results match reality even when data inputs change over time | Data Engineer, Analytics Engineer, ML engineer ??? | + +Our story starts with unity and a baton pass develops over time until we end with what looks more like playing hot potato. The building narrative is something I was proud of with my fellow ML engineer. The maintenance and validation of the machine learning output workflow is something we weren’t proud of. This happened because we were missing something critical: **we weren’t united on who should do what in the long term** (think: source data changes cascaded through the transformation->pre-processing->training steps->monitoring performance.) No wonder business users shrugged their shoulders at our results after 1 month because we assumed the other role would hold that baton pass forever. + +Let’s make this simple: + +- **“Who makes data AND machine learning pipelines maintainable over time when data changes?”** + +If we get this question right, it makes answering this question easier: **“How do we get people to use our work?”** + +## How are tools evolving to heal the gap between analytics engineering & machine learning? + +Let’s focus this question even more: What’s being done about the “maintenance over time” problem in our workflow? What would your team have done differently? + +### Build a better notebook experience that makes dbt and python more interoperable + +Gluing together notebooks and dbt isn’t the most elegant experience today. It’d be nice to schedule notebooks in sync with my dbt jobs. All so I can better diagnose my problems in ML model drift. + +#### Hex + +• [Hex](https://docs.hex.tech/product-docs): Notebook experience with quality of life improvements. SQL query results can be read in as dataframes after running. dbt integration to verify data quality during development. Build parameterized data apps and give audiences one less context switch to a BI dashboard. + +#### Modelbit + +- [Modelbit](https://www.modelbit.com/): Bring your own notebook with a huge quality of life improvement - enable dbt to call versioned ML models as external functions in SQL. + +#### How would this change my story? + +My ML engineer would know the quality of input data created by dbt before starting machine learning development. I could schedule this notebook in sync with my dbt jobs and know instantly if my **ML model drift is caused by data quality vs. model logic.** +Also, I would create a data app (in Hex) where users plug in different input scenarios that feed into the predictive model. Even better, I could track versions of my ML models deployed over time in Modelbit + Hex and deploy ML external functions as [dbt macros](https://docs.getdbt.com/docs/building-a-dbt-project/jinja-macros/#macros) + (by the way: how is this not more normal?!). + +![Image showing the notebook and dbt synchronization](/img/blog/2022-02-18-machine-learning-dbt-baton-pass/notebook-dbt-sync.png) + +![Screenshot of code snippet for modelbit api integration](/img/blog/2022-02-18-machine-learning-dbt-baton-pass/modelbit-api.png) + +#### What are the tradeoffs? + +I’d still have to export my predictive results back to the database and configure them as sources for dbt docs(depends if Modelbit is involved). People wouldn’t know at a glance the data lineage to power this notebook. But my gut tells me the tradeoff would be worth it because the ML engineer knows where to start problem solving even if the solution wasn’t readily available through SQL. + +### Bring machine learning to the SQL workflow + +What if…SQL could do more than what we think it can or even should? + +#### MindsDB + +- [MindsDB](https://mindsdb.com/): Open source layer on top of a database using SQL syntax to create predictive models. Machine learning computation takes place in the MindsDB layer. + +#### Continual + +- [Continual](https://docs.continual.ai/dbt-example/): Directly create a dbt model to predict your results. Evaluates ML models to use based on your dbt model configuration. [Machine learning computation takes place in this layer and data warehouses where applicable (think: Snowpark API, Databricks)](https://docs.continual.ai/architecture/#relationship-to-your-data-warehouse). + +#### Bigquery ML + +- [BigQuery ML](https://cloud.google.com/bigquery-ml/docs/introduction): Use BigQuery-specific syntax to create machine learning models within the database and apply them as functions to your SQL to predict results. You get to [import your own TensorFlow](https://cloud.google.com/bigquery-ml/docs/making-predictions-with-imported-tensorflow-models#importing_models) + models! + +#### Redshift ML + +- [Redshift ML](https://aws.amazon.com/redshift/features/redshift-ml/): Use Redshift-specific syntax to create machine learning models within the database and apply them as functions to your SQL to predict results. You get to bring your own models too! + +#### How would this change my story? + +My ML engineer and I would get to unite on SQL even more. Wherever the pipeline broke in the (-ML) process, **SQL would be our entry-point together** to figure out the problem. For simple machine learning problems (e.g., linear regression, classification), I would more easily understand and even own the full pipeline – with the advice and review of my ML engineer of course. And for Continual, I would elegantly add my machine learning model as an exposure (see below). + +Beyond fixing problems once they arise, this workflow would avoid much of the complexity involved in building ML Ops pipelines: massive amounts of [extra infrastructure](https://dl.acm.org/doi/10.5555/2969442.2969519) (think: where does my python code run?). As a ML engineer, I want to live in a world where I can manage exploration, training, versioning, and inference from one control plane. **In-warehouse ML has the potential to make that real.** + +![Image of lineage graph for unified machine learning and analytics engineering DAG expressed in SQL](/img/blog/2022-02-18-machine-learning-dbt-baton-pass/lineage-graph.png) + +#### What are the tradeoffs? + +This wouldn’t solve for the ML engineer and her desire to inject custom ML models into this workflow without major effort (think: Jupyter notebooks if Continual isn’t her cup of tea). Also, if I wanted to build analyses on top of these predictions…I’d still have to configure them as sources in my dbt project (still a bit clunky). But my gut tells me the tradeoff would be worth it. Our shared SQL interface maintains ML models for months in a reality where fixing problems in SQL is easier than SQL, python, notebooks, BI dashboard (think: cognitive overload). + +### Make dbt integrate with multi-lingual support + +It may be worth having python scripts live side by side dbt jobs and configurations. I can get better lineage and have one less tool to context switch to. + +#### fal + +- [fal](https://github.com/fal-ai/fal): Makes dbt and python interoperable. Read in a dbt model as a pandas dataframe using a [ref statement](https://github.com/fal-ai/fal/blob/b20874ab957f8eb0f65c56d82e6bb85c717de4c6/examples/write_jupyter_notebook.md#example-9-use-dbt-from-a-jupyter-notebook)! + +#### How would this change my story? + +**A ref statement would mean the same thing to both my ML engineer and me.** + +We would work in the same dbt project for the entire workflow, not just part of it. We would align python scripts to dbt configurations for better lineage (see below). + +![Screenshot of fal installation instructions](/img/blog/2022-02-18-machine-learning-dbt-baton-pass/fal-install-1.png) + +![Second screenshot of fal installation instructions](/img/blog/2022-02-18-machine-learning-dbt-baton-pass/fal-install-2.png) + +#### What are the tradeoffs of this tool path? + +When things would go wrong, it’d still be a messy jumble to figure out how SQL changes inform python changes and vice versa. And I would need to care about which infrastructure my python code is running on. But my gut tells me the tradeoff would be worth it because there’d be less notebooks to schedule, and it’d be easier to align machine learning logic to dbt logic. + +## What outcomes matter? + +This is the part of the story where you want me to declare a winner, but there isn’t one because I see a future where all of them can win. + +What matters to me is what matters to you: “Which tradeoffs matter to get me enjoying working with my teammates and fixing problems more easily in my ELT-ML pipeline?” + +My hope is that: + +- When something goes wrong, it’s clearer where to start solving +- People are excited about baton passing work back and forth, less playing hot potato +- People have deep pride in a predictive analytics workflow that works +- Everyone gets to work on more interesting problems than clunkily fixing a machine learning pipeline across 5 browser tabs +- **And most importantly, people use our collective gosh darn work to make real decisions** + +I’m less interested in the tools than understanding if this problem is one we can agree is painful enough to solve in the first place. Is this your story? Which future excites you? Which scares you? diff --git a/website/blog/metadata.yml b/website/blog/metadata.yml new file mode 100644 index 00000000000..549e5dd04d2 --- /dev/null +++ b/website/blog/metadata.yml @@ -0,0 +1,24 @@ +# Set custom blog metadata +featured_image: "" + +# This CTA lives in right sidebar on blog index +featured_cta: "staging" + +# How many featured posts to show on blog index +featured_posts_count: 4 + +# How many featured posts by tag to show on blog index +featured_tag_posts_count: 3 + +# How many posts which aren't in featured post section should show +regular_posts_count: 15 + +# Show or hide hero title, description, cta from blog index +show_title: true +show_description: true +hero_button_url: "/blog/welcome" +hero_button_text: "Start here" +hero_button_new_tab: false + +# Show or hide sidebar on blog post page +show_left_sidebar: false diff --git a/website/cypress.config.js b/website/cypress.config.js new file mode 100644 index 00000000000..0ce0dfeda3c --- /dev/null +++ b/website/cypress.config.js @@ -0,0 +1,12 @@ +const { defineConfig } = require("cypress"); + +module.exports = defineConfig({ + e2e: { + setupNodeEvents(on, config) { + // implement node event listeners here + }, + baseUrl: 'https://docs.getdbt.com', + chromeWebSecurity: false, + video: false + }, +}); diff --git a/website/cypress/e2e/docs.cy.js b/website/cypress/e2e/docs.cy.js new file mode 100644 index 00000000000..50f0ba09dae --- /dev/null +++ b/website/cypress/e2e/docs.cy.js @@ -0,0 +1,543 @@ +describe('docs.getdbt.com docs tab', () => { + before(function () { + Cypress.on('uncaught:exception', (err, runnable) => { + // returning false here prevents Cypress from + // failing the test + return false; + }); + }); + + beforeEach(() => { + cy.visit('/docs/introduction'); + }); + + it('verifies all the introduction page links work and go to the correct pages', () => { + cy.get(':nth-child(2) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/docs/supported-data-platforms`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get(':nth-child(1) > .menu__list > :nth-child(3) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/docs/core-versions`, `${Cypress.config('baseUrl')}/docs/introduction`) + }) + + it('verifies all the building a dbt project page links work and go to the correct pages', () => { + cy.get('.theme-doc-sidebar-menu > :nth-child(2) > :nth-child(1) > .menu__link').click() + cy.get(':nth-child(2) > .menu__list > :nth-child(1) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/docs/building-a-dbt-project/projects`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get(':nth-child(2) > .menu__list > .theme-doc-sidebar-item-category > .menu__list-item-collapsible > .menu__link').click() + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 350ms ease-in-out 0s;"] > .theme-doc-sidebar-item-category > .menu__list > :nth-child(1) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/docs/building-a-dbt-project/building-models`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 350ms ease-in-out 0s;"] > .theme-doc-sidebar-item-category > .menu__list > :nth-child(2) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/docs/building-a-dbt-project/building-models/materializations`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 350ms ease-in-out 0s;"] > .theme-doc-sidebar-item-category > .menu__list > :nth-child(3) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/docs/building-a-dbt-project/building-models/configuring-incremental-models`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 350ms ease-in-out 0s;"] > .theme-doc-sidebar-item-category > .menu__list > :nth-child(4) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/docs/building-a-dbt-project/building-models/using-custom-aliases`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 350ms ease-in-out 0s;"] > .theme-doc-sidebar-item-category > .menu__list > :nth-child(5) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/docs/building-a-dbt-project/building-models/using-custom-schemas`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 350ms ease-in-out 0s;"] > .theme-doc-sidebar-item-category > .menu__list > :nth-child(6) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/docs/building-a-dbt-project/building-models/using-custom-databases`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 350ms ease-in-out 0s;"] > .theme-doc-sidebar-item-category > .menu__list > :nth-child(7) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/docs/building-a-dbt-project/building-models/using-variables`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 350ms ease-in-out 0s;"] > :nth-child(3) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/docs/building-a-dbt-project/tests`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 350ms ease-in-out 0s;"] > :nth-child(4) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/docs/building-a-dbt-project/documentation`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 350ms ease-in-out 0s;"] > :nth-child(5) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/docs/building-a-dbt-project/using-sources`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 350ms ease-in-out 0s;"] > :nth-child(6) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/docs/building-a-dbt-project/seeds`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 350ms ease-in-out 0s;"] > :nth-child(7) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/docs/building-a-dbt-project/snapshots`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 350ms ease-in-out 0s;"] > :nth-child(8) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/docs/building-a-dbt-project/exposures`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 350ms ease-in-out 0s;"] > :nth-child(9) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/docs/building-a-dbt-project/jinja-macros`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 350ms ease-in-out 0s;"] > :nth-child(10) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/docs/building-a-dbt-project/hooks-operations`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 350ms ease-in-out 0s;"] > :nth-child(11) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/docs/building-a-dbt-project/package-management`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 350ms ease-in-out 0s;"] > :nth-child(12) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/docs/building-a-dbt-project/analyses`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 350ms ease-in-out 0s;"] > :nth-child(13) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/docs/building-a-dbt-project/metrics`, `${Cypress.config('baseUrl')}/docs/introduction`) + }) + + it('verifies all the running a dbt project page links work and go to the correct pages', () => { + cy.get(':nth-child(3) > .menu__list-item-collapsible > .menu__link').click() + cy.get(':nth-child(3) > .menu__list > :nth-child(1) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/docs/running-a-dbt-project/using-the-dbt-ide`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get(':nth-child(3) > .menu__list > :nth-child(2) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/docs/running-a-dbt-project/using-the-cli`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get(':nth-child(3) > .menu__list > :nth-child(3) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/docs/running-a-dbt-project/dbt-api`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get(':nth-child(3) > .menu__list > :nth-child(4) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/docs/running-a-dbt-project/running-dbt-in-production`, `${Cypress.config('baseUrl')}/docs/introduction`) + }) + + it('verifies all the contributing page links work and go to the correct pages', () => { + cy.get(':nth-child(4) > .menu__list-item-collapsible > .menu__link').click() + cy.get(':nth-child(4) > .menu__list > :nth-child(1) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/docs/contributing/oss-expectations`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get(':nth-child(4) > .menu__list > :nth-child(2) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/docs/contributing/contributor-license-agreements`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get(':nth-child(4) > .menu__list > :nth-child(3) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/docs/contributing/building-a-new-adapter`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get(':nth-child(4) > .menu__list > :nth-child(4) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/docs/contributing/testing-a-new-adapter`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get(':nth-child(4) > .menu__list > :nth-child(5) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/docs/contributing/documenting-a-new-adapter`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get(':nth-child(4) > .menu__list > :nth-child(6) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/docs/contributing/slack-rules-of-the-road`, `${Cypress.config('baseUrl')}/docs/introduction`) + }) + + it('verifies all the about page links work and go to the correct pages', () => { + cy.get(':nth-child(5) > .menu__list-item-collapsible > .menu__link').click() + cy.get(':nth-child(5) > .menu__list > :nth-child(1) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/docs/about/license`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get(':nth-child(5) > .menu__list > :nth-child(2) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/docs/about/viewpoint`, `${Cypress.config('baseUrl')}/docs/introduction`) + }) + + it('verifies all the frequently asked questions - accounts page links work and go to the correct pages', () => { + // frequently asked questions collapsible section takes the user + // to an index page + cy.get(':nth-child(6) > .menu__list-item-collapsible > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/docs/faqs`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(1) > .menu__list-item-collapsible > .menu__link').click() + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(1) > .menu__list > :nth-child(1) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/faqs/Accounts/change-billing`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(1) > .menu__list > :nth-child(2) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/faqs/Accounts/configurable-snapshot-path`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(1) > .menu__list > :nth-child(3) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/faqs/Accounts/dbt-specific-jinja`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(1) > .menu__list > :nth-child(4) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/faqs/Accounts/git-account-in-use`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(1) > .menu__list > :nth-child(5) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/faqs/Accounts/payment-accepted`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(1) > .menu__list > :nth-child(6) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/faqs/Accounts/slack`, `${Cypress.config('baseUrl')}/docs/introduction`) + }) + + it('verifies all the frequently asked questions - core page links work and go to the correct pages', () => { + cy.get(':nth-child(6) > .menu__list-item-collapsible > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/docs/faqs`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(2) > .menu__list-item-collapsible > .menu__link').click() + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(2) > .menu__list > :nth-child(1) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/faqs/Core/install-pip-best-practices.md`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(2) > .menu__list > :nth-child(2) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/faqs/Core/install-pip-os-prereqs.md`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(2) > .menu__list > :nth-child(3) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/faqs/Core/install-python-compatibility`, `${Cypress.config('baseUrl')}/docs/introduction`) + }) + + it('verifies all the frequently asked questions - docs page links work and go to the correct pages', () => { + cy.get(':nth-child(6) > .menu__list-item-collapsible > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/docs/faqs`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(3) > .menu__list-item-collapsible > .menu__link').click() + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(3) > .menu__list > :nth-child(1) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/faqs/Docs/document-all-columns`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(3) > .menu__list > :nth-child(2) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/faqs/Docs/document-other-resources`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(3) > .menu__list > :nth-child(3) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/faqs/Docs/documenting-macros`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(3) > .menu__list > :nth-child(4) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/faqs/Docs/long-descriptions`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(3) > .menu__list > :nth-child(5) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/faqs/Docs/sharing-documentation`, `${Cypress.config('baseUrl')}/docs/introduction`) + }) + + it('verifies all the frequently asked questions - environments page links work and go to the correct pages', () => { + cy.get(':nth-child(6) > .menu__list-item-collapsible > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/docs/faqs`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(4) > .menu__list-item-collapsible > .menu__link').click() + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(4) > .menu__list > :nth-child(1) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/faqs/Environments/beta-release`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(4) > .menu__list > :nth-child(2) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/faqs/Environments/diff-database-environment`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(4) > .menu__list > :nth-child(3) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/faqs/Environments/profile-env-vars`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(4) > .menu__list > :nth-child(4) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/faqs/Environments/profile-name`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(4) > .menu__list > :nth-child(5) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/faqs/Environments/target-names`, `${Cypress.config('baseUrl')}/docs/introduction`) + }) + + it('verifies all the frequently asked questions - git page links work and go to the correct pages', () => { + cy.get(':nth-child(6) > .menu__list-item-collapsible > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/docs/faqs`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(5) > .menu__list-item-collapsible > .menu__link').click() + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(5) > .menu__list > :nth-child(1) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/faqs/Git/gitignore`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(5) > .menu__list > :nth-child(2) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/faqs/Git/gitlab-authentication`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(5) > .menu__list > :nth-child(3) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/faqs/Git/gitlab-selfhosted`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(5) > .menu__list > :nth-child(4) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/faqs/Git/google-cloud-repo`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(5) > .menu__list > :nth-child(5) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/faqs/Git/managed-repo`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(5) > .menu__list > :nth-child(6) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/faqs/Git/run-on-pull`, `${Cypress.config('baseUrl')}/docs/introduction`) + }) + + it('verifies all the frequently asked questions - jinja page links work and go to the correct pages', () => { + cy.get(':nth-child(6) > .menu__list-item-collapsible > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/docs/faqs`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(6) > .menu__list-item-collapsible > .menu__link').click() + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(6) > .menu__list > :nth-child(1) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/faqs/Jinja/jinja-whitespace`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(6) > .menu__list > :nth-child(2) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/faqs/Jinja/quoting-column-names`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(6) > .menu__list > :nth-child(3) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/faqs/Jinja/which-jinja-docs`, `${Cypress.config('baseUrl')}/docs/introduction`) + }) + + it('verifies all the frequently asked questions - models page links work and go to the correct pages', () => { + cy.get(':nth-child(6) > .menu__list-item-collapsible > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/docs/faqs`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(7) > .menu__list-item-collapsible > .menu__link').click() + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(7) > .menu__list > :nth-child(1) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/faqs/Models/available-configurations`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(7) > .menu__list > :nth-child(2) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/faqs/Models/available-materializations`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(7) > .menu__list > :nth-child(3) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/faqs/Models/configurable-model-path`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(7) > .menu__list > :nth-child(4) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/faqs/Models/create-a-schema`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(7) > .menu__list > :nth-child(5) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/faqs/Models/create-dependencies`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(7) > .menu__list > :nth-child(6) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/faqs/Models/insert-records`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(7) > .menu__list > :nth-child(7) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/faqs/Models/model-custom-schemas`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(7) > .menu__list > :nth-child(8) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/faqs/Models/reference-models-in-another-project`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(7) > .menu__list > :nth-child(9) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/faqs/Models/removing-deleted-models`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(7) > .menu__list > :nth-child(10) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/faqs/Models/run-downtime`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(7) > .menu__list > :nth-child(11) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/faqs/Models/source-quotes`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(7) > .menu__list > :nth-child(12) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/faqs/Models/specifying-column-types`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(7) > .menu__list > :nth-child(13) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/faqs/Models/sql-dialect`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(7) > .menu__list > :nth-child(14) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/faqs/Models/unique-model-names`, `${Cypress.config('baseUrl')}/docs/introduction`) + }) + + it('verifies all the frequently asked questions - project page links work and go to the correct pages', () => { + cy.get(':nth-child(6) > .menu__list-item-collapsible > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/docs/faqs`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(8) > .menu__list-item-collapsible > .menu__link').click() + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(8) > .menu__list > :nth-child(1) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/faqs/Project/dbt-source-freshness`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(8) > .menu__list > :nth-child(2) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/faqs/Project/debugging-jinja`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(8) > .menu__list > :nth-child(3) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/faqs/Project/define-a-column-type`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(8) > .menu__list > :nth-child(4) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/faqs/Project/docs-for-multiple-projects`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(8) > .menu__list > :nth-child(5) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/faqs/Project/example-projects`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(8) > .menu__list > :nth-child(6) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/faqs/Project/exclude-table-from-freshness`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(8) > .menu__list > :nth-child(7) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/faqs/Project/multiple-resource-yml-files`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(8) > .menu__list > :nth-child(8) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/faqs/Project/project-name`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(8) > .menu__list > :nth-child(9) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/faqs/Project/properties-not-in-config`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(8) > .menu__list > :nth-child(10) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/faqs/Project/resource-yml-name`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(8) > .menu__list > :nth-child(11) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/faqs/Project/schema-yml-name`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(8) > .menu__list > :nth-child(12) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/faqs/Project/separate-profile`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(8) > .menu__list > :nth-child(13) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/faqs/Project/source-has-bad-name`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(8) > .menu__list > :nth-child(14) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/faqs/Project/source-in-different-database`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(8) > .menu__list > :nth-child(15) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/faqs/Project/structure-a-project`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(8) > .menu__list > :nth-child(16) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/faqs/Project/which-materialization`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(8) > .menu__list > :nth-child(17) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/faqs/Project/which-schema`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(8) > .menu__list > :nth-child(18) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/faqs/Project/why-not-write-dml`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(8) > .menu__list > :nth-child(19) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/faqs/Project/why-so-many-macros`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(8) > .menu__list > :nth-child(20) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/faqs/Project/why-version-2`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(8) > .menu__list > :nth-child(21) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/faqs/Project/yaml-file-extension`, `${Cypress.config('baseUrl')}/docs/introduction`) + }) + + it('verifies all the frequently asked questions - runs page links work and go to the correct pages', () => { + cy.get(':nth-child(6) > .menu__list-item-collapsible > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/docs/faqs`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(9) > .menu__list-item-collapsible > .menu__link').click() + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(9) > .menu__list > :nth-child(1) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/faqs/Runs/checking-logs`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(9) > .menu__list > :nth-child(2) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/faqs/Runs/failed-prod-run`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(9) > .menu__list > :nth-child(3) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/faqs/Runs/failed-tests`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(9) > .menu__list > :nth-child(4) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/faqs/Runs/run-downstream-of-seed`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(9) > .menu__list > :nth-child(5) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/faqs/Runs/run-one-model`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(9) > .menu__list > :nth-child(6) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/faqs/Runs/run-one-snapshot`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(9) > .menu__list > :nth-child(7) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/faqs/Runs/running-model-downstream-of-source`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(9) > .menu__list > :nth-child(8) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/faqs/Runs/snapshot-frequency`, `${Cypress.config('baseUrl')}/docs/introduction`) + }) + + it('verifies all the frequently asked questions - seeds page links work and go to the correct pages', () => { + cy.get(':nth-child(6) > .menu__list-item-collapsible > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/docs/faqs`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(10) > .menu__list-item-collapsible > .menu__link').click() + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(10) > .menu__list > :nth-child(1) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/faqs/Seeds/build-one-seed`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(10) > .menu__list > :nth-child(2) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/faqs/Seeds/full-refresh-seed`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(10) > .menu__list > :nth-child(3) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/faqs/Seeds/leading-zeros-in-seed`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(10) > .menu__list > :nth-child(4) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/faqs/Seeds/load-raw-data-with-seed`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(10) > .menu__list > :nth-child(5) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/faqs/Seeds/seed-custom-schemas`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(10) > .menu__list > :nth-child(6) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/faqs/Seeds/seed-datatypes`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(10) > .menu__list > :nth-child(7) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/faqs/Seeds/seed-hooks`, `${Cypress.config('baseUrl')}/docs/introduction`) + }) + + it('verifies all the frequently asked questions - snapshots page links work and go to the correct pages', () => { + cy.get(':nth-child(6) > .menu__list-item-collapsible > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/docs/faqs`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(11) > .menu__list-item-collapsible > .menu__link').click() + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(11) > .menu__list > :nth-child(1) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/faqs/Snapshots/snapshot-hooks`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(11) > .menu__list > :nth-child(2) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/faqs/Snapshots/snapshot-schema-changes`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(11) > .menu__list > :nth-child(3) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/faqs/Snapshots/snapshot-target-schema`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(11) > .menu__list > :nth-child(4) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/faqs/Snapshots/snapshotting-freshness-for-one-source`, `${Cypress.config('baseUrl')}/docs/introduction`) + }) + + it('verifies all the frequently asked questions - tests page links work and go to the correct pages', () => { + cy.get(':nth-child(6) > .menu__list-item-collapsible > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/docs/faqs`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(12) > .menu__list-item-collapsible > .menu__link').click() + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(12) > .menu__list > :nth-child(1) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/faqs/Tests/available-tests`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(12) > .menu__list > :nth-child(2) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/faqs/Tests/configurable-data-path`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(12) > .menu__list > :nth-child(3) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/faqs/Tests/configurable-data-test-path`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(12) > .menu__list > :nth-child(4) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/faqs/Tests/custom-test-thresholds`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(12) > .menu__list > :nth-child(5) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/faqs/Tests/recommended-tests`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(12) > .menu__list > :nth-child(6) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/faqs/Tests/test-one-model`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(12) > .menu__list > :nth-child(7) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/faqs/Tests/testing-seeds`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(12) > .menu__list > :nth-child(8) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/faqs/Tests/testing-sources`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(12) > .menu__list > :nth-child(9) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/faqs/Tests/uniqueness-two-columns`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(12) > .menu__list > :nth-child(10) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/faqs/Tests/when-to-test`, `${Cypress.config('baseUrl')}/docs/introduction`) + }) + + it('verifies all the frequently asked questions - troubleshooting page links work and go to the correct pages', () => { + cy.get(':nth-child(6) > .menu__list-item-collapsible > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/docs/faqs`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(13) > .menu__list-item-collapsible > .menu__link').click() + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(13) > .menu__list > :nth-child(1) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/faqs/Troubleshooting/access-gdrive-credential`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(13) > .menu__list > :nth-child(2) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/faqs/Troubleshooting/access_token_error`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(13) > .menu__list > :nth-child(3) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/faqs/Troubleshooting/dispatch-could-not-find-package`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(13) > .menu__list > :nth-child(4) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/faqs/Troubleshooting/git-revlist-error`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(13) > .menu__list > :nth-child(5) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/faqs/Troubleshooting/gitignore`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(13) > .menu__list > :nth-child(6) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/faqs/Troubleshooting/gitlab-authentication`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(13) > .menu__list > :nth-child(7) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/faqs/Troubleshooting/nonetype-ide-error`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(13) > .menu__list > :nth-child(8) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/faqs/Troubleshooting/partial-parsing-error`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(13) > .menu__list > :nth-child(9) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/faqs/Troubleshooting/runtime-error-could-not-find-profile`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(13) > .menu__list > :nth-child(10) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/faqs/Troubleshooting/runtime-packages.yml`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(13) > .menu__list > :nth-child(11) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/faqs/Troubleshooting/sql-errors`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(13) > .menu__list > :nth-child(12) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/faqs/Troubleshooting/unused-model-configurations`, `${Cypress.config('baseUrl')}/docs/introduction`) + }) + + it('verifies all the frequently asked questions - warehouse page links work and go to the correct pages', () => { + cy.get(':nth-child(6) > .menu__list-item-collapsible > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/docs/faqs`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(14) > .menu__list-item-collapsible > .menu__link').click() + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(14) > .menu__list > :nth-child(1) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/faqs/Warehouse/bq-impersonate-service-account-setup`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(14) > .menu__list > :nth-child(2) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/faqs/Warehouse/bq-impersonate-service-account-why`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(14) > .menu__list > :nth-child(3) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/faqs/Warehouse/connecting-to-two-dbs-not-allowed`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(14) > .menu__list > :nth-child(4) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/faqs/Warehouse/database-privileges`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(14) > .menu__list > :nth-child(5) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/faqs/Warehouse/loading-data`, `${Cypress.config('baseUrl')}/docs/introduction`) + + cy.get('[style="display: block; overflow: visible; height: auto; will-change: height; transition: height 357ms ease-in-out 0s;"] > :nth-child(14) > .menu__list > :nth-child(6) > .menu__link').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/faqs/Warehouse/sample-profiles`, `${Cypress.config('baseUrl')}/docs/introduction`) + }) +}) \ No newline at end of file diff --git a/website/cypress/e2e/homepage.cy.js b/website/cypress/e2e/homepage.cy.js new file mode 100644 index 00000000000..6ffee3454f0 --- /dev/null +++ b/website/cypress/e2e/homepage.cy.js @@ -0,0 +1,61 @@ +const sizes = ['iphone-x', [768, 1024], [1280, 720]] + +describe('docs.getdbt.com homepage', () => { + before(function () { + Cypress.on('uncaught:exception', (err, runnable) => { + // returning false here prevents Cypress from + // failing the test + return false; + }); + }); + + beforeEach(() => { + cy.visit('/'); + }); + + sizes.forEach((size) => { + it('verifies all the button links work and go to the correct page', () => { + if (Cypress._.isArray(size)) { + cy.viewport(size[0], size[1]) + } else { + cy.viewport(size) + } + + cy.get('[style="max-width:var(--ifm-container-width);margin:calc(2vh) auto calc(2vh)"] > :nth-child(1) > .card > .card__footer > .button').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/docs/introduction`, `${Cypress.config('baseUrl')}/`) + + cy.get('[style="max-width:var(--ifm-container-width);margin:calc(2vh) auto calc(2vh)"] > :nth-child(2) > .card > .card__footer > .button').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/guides/getting-started`, `${Cypress.config('baseUrl')}/`) + + cy.get('[style="max-width:var(--ifm-container-width);margin:calc(2vh) auto calc(2vh)"] > :nth-child(3) > .card > .card__footer > .button').invoke('removeAttr', 'target').click() + cy.checkLinksNotBroken('https://www.getdbt.com/dbt-learn/', `${Cypress.config('baseUrl')}/`) + + cy.get(':nth-child(2) > :nth-child(2) > :nth-child(1) > .card > .card__footer > .button').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/docs/introduction`, `${Cypress.config('baseUrl')}/`) + + cy.get(':nth-child(2) > :nth-child(2) > :nth-child(2) > .card > .card__footer > .button').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/reference/dbt_project.yml`, `${Cypress.config('baseUrl')}/`) + + cy.get(':nth-child(2) > :nth-child(2) > :nth-child(3) > .card > .card__footer > .button').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/docs/faqs`, `${Cypress.config('baseUrl')}/`) + + cy.get(':nth-child(4) > :nth-child(1) > .card > .card__footer > .button').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/docs/dbt-cloud/cloud-overview`, `${Cypress.config('baseUrl')}/`) + + cy.get(':nth-child(4) > :nth-child(2) > .card > .card__footer > .button').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/docs/dbt-cloud/dbt-cloud-api/cloud-apis`, `${Cypress.config('baseUrl')}/`) + + cy.get(':nth-child(2) > :nth-child(1) > .card > .card__footer > .button').contains('Get Advice').invoke('removeAttr', 'target').click() + cy.checkLinksNotBroken('https://discourse.getdbt.com/', `${Cypress.config('baseUrl')}/`) + + cy.get(':nth-child(2) > :nth-child(2) > .card > .card__footer > .button').contains('Join us on Slack').then(($button => { + cy.wrap($button).should('have.attr', 'href').and('eq', 'http://community.getdbt.com/') + cy.wrap($button).invoke('removeAttr', 'target').click() + })) + cy.checkLinksNotBroken('https://www.getdbt.com/community/', `${Cypress.config('baseUrl')}/`) + + cy.get(':nth-child(2) > :nth-child(3) > .card > .card__footer > .button').contains('View Projects').click() + cy.checkLinksNotBroken(`${Cypress.config('baseUrl')}/faqs/project/example-projects`, `${Cypress.config('baseUrl')}/`) + }) + }) +}) \ No newline at end of file diff --git a/website/cypress/support/commands.js b/website/cypress/support/commands.js new file mode 100644 index 00000000000..ed44b0f8810 --- /dev/null +++ b/website/cypress/support/commands.js @@ -0,0 +1,32 @@ +// *********************************************** +// This example commands.js shows you how to +// create various custom commands and overwrite +// existing commands. +// +// For more comprehensive examples of custom +// commands please read more here: +// https://on.cypress.io/custom-commands +// *********************************************** +// +// +// -- This is a parent command -- +// Cypress.Commands.add('login', (email, password) => { ... }) +// +// +// -- This is a child command -- +// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... }) +// +// +// -- This is a dual command -- +// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... }) +// +// +// -- This will overwrite an existing command -- +// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... }) +Cypress.Commands.add('byTestId', (testId) => {`[data-testid=${testId}]`}); +Cypress.Commands.add('checkLinksNotBroken', (desiredPage, originalPage) => { + cy.url().should('eq', desiredPage) + cy.get('body').should('not.contain', 'Page Not Found') + cy.go('back') + cy.url().should('eq', originalPage) +}) diff --git a/website/cypress/support/e2e.js b/website/cypress/support/e2e.js new file mode 100644 index 00000000000..0e7290a13d9 --- /dev/null +++ b/website/cypress/support/e2e.js @@ -0,0 +1,20 @@ +// *********************************************************** +// This example support/e2e.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' + +// Alternatively you can use CommonJS syntax: +// require('./commands') \ No newline at end of file diff --git a/website/dbt-global-variables.js b/website/dbt-global-variables.js new file mode 100644 index 00000000000..608cd246a4e --- /dev/null +++ b/website/dbt-global-variables.js @@ -0,0 +1,20 @@ +/* + * Full Documentation at: + * https://www.notion.so/dbtlabs/Versioning-on-Docusaurus-c6a4a41a66cd4ea2970854cc42cb5b70#1803b9cb666442e5ac8885cf0bba321f + * + */ + +exports.dbtVariables = { + // Example global variable with versioning + // If version 0.21 or lower is selected + // "Old Example String" will replace "Example String" + exampleString: { + name: "Example String", + versions: [ + { + "name": "Old Example String", + "version": "0.21" + } + ] + } +} diff --git a/website/dbt-versions.js b/website/dbt-versions.js new file mode 100644 index 00000000000..63e49e70e5d --- /dev/null +++ b/website/dbt-versions.js @@ -0,0 +1,62 @@ +exports.versions = [ + { + version: "1.3", + EOLDate: "2023-10-07", // TODO estimated for now + isPrerelease: true, + }, + { + version: "1.2", + EOLDate: "2023-07-26", + }, + { + version: "1.1", + EOLDate: "2023-04-28", + }, + { + version: "1.0", + EOLDate: "2023-12-03" + }, + { + version: "0.21", + EOLDate: "2022-06-30" + }, + { + version: "0.20", + EOLDate: "2022-06-30" + } +] + +exports.versionedPages = [ + { + "page": "docs/building-a-dbt-project/building-models/python-models", + "firstVersion": "1.3", + }, + { + "page": "reference/dbt-jinja-functions/set", + "firstVersion": "1.2", + }, + { + "page": "reference/dbt-jinja-functions/zip", + "firstVersion": "1.2", + }, + { + "page": "reference/dbt-jinja-functions/cross-database-macros", + "firstVersion": "1.2", + }, + { + "page": "reference/resource-configs/grants", + "firstVersion": "1.2", + }, + { + "page": "docs/contributing/testing-a-new-adapter", + "firstVersion": "1.1", + }, + { + "page": "reference/dbt-jinja-functions/selected_resources", + "firstVersion": "1.1", + }, + { + "page": "reference/dbt-jinja-functions/print", + "firstVersion": "1.1", + } +] diff --git a/website/docs/community/maintaining-a-channel.md b/website/docs/community/maintaining-a-channel.md new file mode 100644 index 00000000000..856082e238d --- /dev/null +++ b/website/docs/community/maintaining-a-channel.md @@ -0,0 +1,37 @@ +--- +title: "Maintaining a Slack channel" +id: "maintaining-a-channel" +--- + +## TL;DR + +There are three things you should do to be a good channel maintainer in the [dbt Slack community](https://community.getdbt.com/): + +- Once you see some folks in the channel, post initial conversation topics to help them get to know each other. +- Keep an eye out in #introductions for folks who might benefit from your new channel. For example if someone works in the space or on the same problems, then direct them to the channel. +- Make sure folks follow the [Rules of the Road](https://docs.getdbt.com/docs/contributing/slack-rules-of-the-road) in the channel. If you notice someone is not following one, gently remind them of the rule in thread, and, ideally, provide an example of how they can rephrase their message or where they can redirect it. If you have a question about how to proceed, just post it in #ask-a-moderator with a screenshot or link to the thread and someone will give you advice. + +## Scope of the Role + +A maintainer can be a dbt Labs employee, but does not have to be. *Slack channel maintainer* is philosophically similar to OSS maintainer. At the onset, the channel maintainer will help build up this new space in Slack and stir up conversation during the first few weeks of the channel's existence. They are someone who stays on top of feedback and encourages generative contributions. This is not necessarily someone who is the generator of content and contributions, or answers every question. + +## Initial Instructions + +1. Review the [Rules of the Road](https://docs.getdbt.com/docs/contributing/slack-rules-of-the-road) and [Code of Conduct](https://www.getdbt.com/community/code-of-conduct) and please let the the folks who created the channel know that you read both documents and you agree to be mindful of them. +2. If you are a vendor, review the [Vendor Guidelines](https://www.getdbt.com/community/vendor-guidelines). +3. Add the Topic and Description to the channel. @Mention your name in the channel Description, identifying yourself as the maintainer. Ex: *Maintainer: First Last (pronouns).* If you are a vendor, make sure your Handle contains your affiliation. +4. Complete or update your Slack profile by making sure your Company (in the ‘What I do’ field), Pronouns, and Handle, if you’re a vendor, are up-to-date. +5. Post initial conversation topics once a few folks get in the channel to help folks get to know each other. Check out this [example introductory post](https://getdbt.slack.com/archives/C02FXAZRRDW/p1632407767005000). +6. Stir up conversation during the first few weeks of the channel's existence. As you get started, answer the questions you can or help find someone with answers, seed discussions about once a week, and making sure folks follow the Rules of the Road. + +## Long-term Expectations + +- Maintaining the channel, checking in and being active on a regular basis by answering folks' questions, and seeding discussions. Want an example? Check out [this poll](https://getdbt.slack.com/archives/C022A67TLFL/p1628279819038800). +- For guidance on how to answer a question, see [Answering Community Questions](https://www.getdbt.com/community/answering-community-questions). If you are not sure how to answer a lingering or unanswered question, you can post about it in #ask-a-moderator or direct it to another channel, if relevant. +- If the channel is an industry channel, it’s helpful to monitor [#introductions](https://getdbt.slack.com/archives/CETJLH1V3) and invite people. Keep an eye out for folks who might benefit from being in the new channel if they mention they are working in the space, or are thinking about some of these problems. +- Make sure folks follow the [Rules of the Road](https://docs.getdbt.com/docs/contributing/slack-rules-of-the-road). For example, if you notice someone is not following one, gently remind them of the rule in thread, and, ideally, provide an example of how they can rephrase their message or where they can redirect it. If you have a question about how to proceed, just post about it in #ask-a-moderator with a link to the thread or screenshot and someone will give you advice. +- In tools channels, sharing customer stories and product updates is very okay in this channel because folks expect that when they join. However, please avoid any direct sales campaigns, pricing offers, etc. +- If you have any questions/doubts about the [Rules of the Road](https://docs.getdbt.com/docs/contributing/slack-rules-of-the-road) or [Vendor Guidelines](https://www.getdbt.com/community/vendor-guidelines), please post a question in #ask-a-moderator about what sort of things the community expects from interactions with vendors. +- A reminder that we never DM anyone in Slack without their permission in public channel or some prior relationship. +- A reminder that @ here/all/channel are disabled. +- Use and encourage the use of threads 🧵 to keep conversations tidy! diff --git a/website/docs/dbt-cli/configure-your-profile.md b/website/docs/dbt-cli/configure-your-profile.md index 80f6c875ae4..1f025fe13a8 100644 --- a/website/docs/dbt-cli/configure-your-profile.md +++ b/website/docs/dbt-cli/configure-your-profile.md @@ -9,7 +9,7 @@ description: "Configure your profile using the command line." ## Connecting to your warehouse using the command line -When you invoke dbt from the command line, dbt parses your `dbt_project.yml` and obtains the `profile` name, which dbt needs to connect to your data warehouse. +When you invoke dbt from the command line, dbt parses your `dbt_project.yml` and obtains the `profile` name, which dbt needs to connect to your . @@ -24,7 +24,18 @@ profile: 'jaffle_shop' dbt then checks your `profiles.yml` file for a profile with the same name. A profile contains all the details required to connect to your data warehouse. -This file generally lives outside of your dbt project to avoid sensitive credentials being check in to version control. By default, dbt expects the `profiles.yml` file to be located in the `~/.dbt/` directory. + + +By default, dbt expects the `profiles.yml` file to be located in the `~/.dbt/` directory. + + + + +dbt will search the current working directory for the `profiles.yml` file and will default to the `~/.dbt/` directory if not found. + + + +This file generally lives outside of your dbt project to avoid sensitive credentials being checked in to version control, but `profiles.yml` can be safely checked in when [using environment variables](#advanced-using-environment-variables) to load sensitive credentials. @@ -59,7 +70,7 @@ A profile consists of _targets_, and a specified _default target_. Each _target_ specifies the type of warehouse you are connecting to, the credentials to connect to the warehouse, and some dbt-specific configurations. -The credentials you need to provide in your target varies across warehouses – sample profiles for each supported warehouse are available in the [Supported Adapters](available-adapters) section. +The credentials you need to provide in your target varies across warehouses &mdash sample profiles for each supported warehouse are available in the [Supported Data Platforms](supported-data-platforms) section. **Pro Tip:** You may need to surround your password in quotes if it contains special characters. More details [here](https://stackoverflow.com/a/37015689/10415173). @@ -89,7 +100,7 @@ dbt supports multiple targets within one profile to encourage the use of separat A typical profile for an analyst using dbt locally will have a target named `dev`, and have this set as the default. -You may also have a `prod` target within your profile, which creates the objects in your production schema. However, since it's often desirable to perform production runs on a schedule, we recommend deploying your dbt project on a separate machine to your local machine. As such, most dbt users will only have a dev target in their profile on their local machine. +You may also have a `prod` target within your profile, which creates the objects in your production schema. However, since it's often desirable to perform production runs on a schedule, we recommend deploying your dbt project to a separate machine other than your local machine. Most dbt users only have a `dev` target in their profile on their local machine. If you do have multiple targets in your profile, and want to use a target other than the default, you can do this using the `--target` option when issuing a dbt command. @@ -101,7 +112,7 @@ To ensure the user credentials you use in your target allow dbt to run, you will * read source data * create schemas¹ -* read system tables +* read system tables :::info Running dbt without create schema privileges @@ -143,7 +154,25 @@ You can use a different number of threads than the value defined in your target ## Advanced: Customizing a profile directory -By default, dbt expects your `profiles.yml` file to be located in the `~/.dbt/` directory. To check the expected location of your `profiles.yml` file for your installation of dbt, you can run the following: +The parent directory for `profiles.yml` is determined using the following precedence: + + + +1. `--profiles-dir` option +1. `DBT_PROFILES_DIR` environment variable +1. `~/.dbt/` directory + + + + +1. `--profiles-dir` option +1. `DBT_PROFILES_DIR` environment variable +1. current working directory +1. `~/.dbt/` directory + + + +To check the expected location of your `profiles.yml` file for your installation of dbt, you can run the following: ```bash $ dbt debug --config-dir @@ -152,13 +181,13 @@ To view your profiles.yml file, run: open /Users/alice/.dbt ``` -You may want to have your `profiles.yml` file stored in a different directory – for example, if you are using environment variables to load your credentials, you might choose to include this file in your version controlled dbt project, and direct dbt to load the file from there. +You may want to have your `profiles.yml` file stored in a different directory than `~/.dbt/` – for example, if you are [using environment variables](#advanced-using-environment-variables) to load your credentials, you might choose to include this file in the root directory of your dbt project. Note that the file always needs to be called `profiles.yml`, regardless of which directory it is in. -There are two ways to direct dbt to a different location for your `profiles.yml` file: +There are multiple ways to direct dbt to a different location for your `profiles.yml` file: -**1. Use the `--profiles-dir` option when executing a dbt command** +### 1. Use the `--profiles-dir` option when executing a dbt command This option can be used as follows: ``` @@ -167,13 +196,12 @@ $ dbt run --profiles-dir path/to/directory If using this method, the `--profiles-dir` option needs to be provided every time you run a dbt command. -**2. Use the `DBT_PROFILES_DIR` environment variable to change the default location** +### 2. Use the `DBT_PROFILES_DIR` environment variable to change the default location Specifying this environment variable overrides the directory that dbt looks for your `profiles.yml` file in. You can specify this by running: ``` $ export DBT_PROFILES_DIR=path/to/directory ``` -If the `--profiles-dir` option is used in a dbt command, it will take precedence over this environment variable. ## Advanced: Using environment variables -Credentials can either be placed directly into the `profiles.yml` file, or they can be loaded from environment variables. This is especially useful for production deployments of dbt. You can find more information about using environment variables [here](env_var). +Credentials can be placed directly into the `profiles.yml` file or loaded from environment variables. Using environment variables is especially useful for production deployments of dbt. You can find more information about environment variables [here](env_var). diff --git a/website/docs/dbt-cli/install/docker.md b/website/docs/dbt-cli/install/docker.md index cc212775753..9597ed3c56d 100644 --- a/website/docs/dbt-cli/install/docker.md +++ b/website/docs/dbt-cli/install/docker.md @@ -3,8 +3,52 @@ title: "Use Docker to install dbt" description: "You can use Docker to install dbt and adapter plugins from the command line." --- -By v1.0.0, dbt Core and all adapter plugins maintained by dbt Labs will be available as official Docker images, -and available from a public registry. -We recommend you use Docker to install in production because it includes dbt Core and all of its dependencies. You might might also use a Docker to install and develop locally if you don't have your python environment set up. +dbt Core and all adapter plugins maintained by dbt Labs are available as [Docker](https://docs.docker.com/) images, and distributed via [GitHub Packages](https://docs.github.com/en/packages/learn-github-packages/introduction-to-github-packages). -More information coming soon! +Using a prebuilt Docker image to install dbt Core in production has a few benefits: it already includes dbt-core, one or more database adapters, and pinned versions of all their dependencies. By contrast, `pip install dbt-core dbt-` takes longer to run, and will always install the latest compatible versions of every dependency. + +You might also be able to use Docker to install and develop locally if you don't have a Python environment set up. Note that running dbt in this manner can be significantly slower if your operating system differs from the system that built the Docker image. If you're a frequent local developer, we recommend that you install dbt Core via [Homebrew](homebrew) or [pip](pip) instead. + +### Prerequisites +* You've installed Docker. For more information, see the [Docker](https://docs.docker.com/) site. +* You understand which database adapter(s) you need. For more information, see [About dbt adapters](/dbt-cli/install/overview#about-dbt-adapters). +* You understand how dbt Core is versioned. For more information, see [About dbt Core versions](core-versions). +* You have a general understanding of the dbt, dbt workflow, developing locally in the command line interface (CLI). For more information, see [About dbt](/docs/introduction#how-do-i-use-dbt). + +### Install a dbt Docker image from Github Packages + +Offical dbt docker images are hosted as [packages in the `dbt-labs` GitHub organization](https://github.com/orgs/dbt-labs/packages?visibility=public). We maintain images and tags for every version of every database adapter, as well as two tags that update as new versions as released: +- `latest`: Latest overall version of dbt-core + this adapter +- `..latest`: Latest patch of dbt-core + this adapter for `.` version family. For example, `1.1.latest` includes the latest patches for dbt Core v1.1. + +Install an image using the `docker pull` command: +``` +docker pull ghcr.io/dbt-labs/: +``` + +### Running a dbt Docker image in a container + +The `ENTRYPOINT` for dbt Docker images is the command `dbt`. You can bind-mount your project to `/usr/app` and use dbt as normal: +``` +docker run \ +--network=host +--mount type=bind,source=path/to/project,target=/usr/app \ +--mount type=bind,source=path/to/profiles.yml,target=/root/.dbt/ \ + \ +ls +``` + +Notes: +* Bind-mount sources _must_ be an absolute path +* You may need to make adjustments to the docker networking setting depending on the specifics of your data warehouse or database host. + +### Building your own dbt Docker image + +If the pre-made images don't fit your use case, we also provide a [`Dockerfile`](https://github.com/dbt-labs/dbt-core/blob/main/docker/Dockerfile) and [`README`](https://github.com/dbt-labs/dbt-core/blob/main/docker/README.md) that can be used to build custom images in a variety of ways. + +In particular, the Dockerfile supports building images: +- Images that all adapters maintained by dbt Labs +- Images that install one or more third-party adapters +- Images against another system architecture + +Please note that, if you go the route of building your own Docker images, we are unable to offer dedicated support for custom use cases. If you run into problems, you are welcome to [ask the community for help](getting-help) or [open an issue](oss-expectations#issues) in the `dbt-core` repository. If many users are requesting the same enhancement, we will tag the issue `help_wanted` and invite community contribution. diff --git a/website/docs/dbt-cli/install/from-source.md b/website/docs/dbt-cli/install/from-source.md index 782461dfb46..fe07d2a90ce 100644 --- a/website/docs/dbt-cli/install/from-source.md +++ b/website/docs/dbt-cli/install/from-source.md @@ -8,7 +8,7 @@ dbt Core and almost all of its adapter plugins are open source software. As such To download form source, you would clone the repositories from GitHub, making a local copy, and then install the local version using `pip`. -Downloading and building dbt Core will enable you to contribute to the project by fixing a bug or implementing a sought-after feature. For more details, read the [contributing guidelines](https://github.com/dbt-labs/dbt/blob/HEAD/CONTRIBUTING.md). +Downloading and building dbt Core will enable you to contribute to the project by fixing a bug or implementing a sought-after feature. For more details, read the [contributing guidelines](https://github.com/dbt-labs/dbt-core/blob/HEAD/CONTRIBUTING.md). ### Installing dbt Core @@ -36,6 +36,6 @@ You do _not_ need to install `dbt-core` before installing an adapter plugin -- t To install in editable mode, such as while contributing, use `pip install -e .` instead. - - - + + + diff --git a/website/docs/dbt-cli/install/homebrew.md b/website/docs/dbt-cli/install/homebrew.md index aeeecb8c174..5556f2d82d5 100644 --- a/website/docs/dbt-cli/install/homebrew.md +++ b/website/docs/dbt-cli/install/homebrew.md @@ -28,7 +28,7 @@ brew install git brew tap dbt-labs/dbt ``` -Now you're ready to install dbt. Once you know [which adapter](available-adapters) you're using, you can install it as `dbt-`. For instance, if using Postgres: +Now you're ready to install dbt. Once you know [which adapter](supported-data-platforms) you're using, you can install it as `dbt-`. For instance, if using Postgres: ```shell brew install dbt-postgres diff --git a/website/docs/dbt-cli/install/overview.md b/website/docs/dbt-cli/install/overview.md index a5848dc4efe..8d90e0c2462 100644 --- a/website/docs/dbt-cli/install/overview.md +++ b/website/docs/dbt-cli/install/overview.md @@ -14,4 +14,4 @@ You can install dbt Core on the command line by using one of these recommended m ## About dbt adapters -dbt works with a number of different databases, query engines, and other SQL-speaking technologies. It does this by using a dedicated _adapter_ for each. When you install dbt, you'll also want to install the specific adapter for your database. For more details, see the [list of available adapters](available-adapters). +dbt works with a number of different data platforms (databases, query engines, and other SQL-speaking technologies). It does this by using a dedicated _adapter_ for each. When you install dbt, you'll also want to install the specific adapter for your database. For more details, see [Supported Data Platforms](supported-data-platforms). diff --git a/website/docs/dbt-cli/install/pip.md b/website/docs/dbt-cli/install/pip.md index f6e1d378e72..1c7c4c486a3 100644 --- a/website/docs/dbt-cli/install/pip.md +++ b/website/docs/dbt-cli/install/pip.md @@ -5,13 +5,13 @@ description: "You can use pip to install dbt Core and adapter plugins from the c You need to use `pip` to install dbt Core on Windows or Linux operating systems. You should use [Homebrew](install/homebrew) for installing dbt Core on a MacOS. -You can install dbt Core and plugins using `pip` because they are Python modules distributed on [PyPi](https://pypi.org/project/dbt/). We recommend using virtual environments when installing with `pip`. +You can install dbt Core and plugins using `pip` because they are Python modules distributed on [PyPI](https://pypi.org/project/dbt/). We recommend using virtual environments when installing with `pip`. - - - + + + -Once you know [which adapter](available-adapters) you're using, you can install it as `dbt-`. For instance, if using Postgres: +Once you know [which adapter](supported-data-platforms) you're using, you can install it as `dbt-`. For example, if using Postgres: ```shell pip install dbt-postgres @@ -50,7 +50,7 @@ pip install dbt-core ### `pip install dbt` -Note that, as of v1.0.0, `pip install dbt` is no longer supported and will raise an explicit error. Since v0.13, the PyPi package named `dbt` was a simple "pass-through" of `dbt-core` and the four original database adapter plugins. For v1, we formalized that split. +Note that, as of v1.0.0, `pip install dbt` is no longer supported and will raise an explicit error. Since v0.13, the PyPI package named `dbt` was a simple "pass-through" of `dbt-core` and the four original database adapter plugins. For v1, we formalized that split. If you have workflows or integrations that relied on installing the package named `dbt`, you can achieve the same behavior going forward by installing the same five packages that it used: diff --git a/website/docs/docs/about/overview.md b/website/docs/docs/about/overview.md index 079b868b0eb..f4ab1e6396b 100644 --- a/website/docs/docs/about/overview.md +++ b/website/docs/docs/about/overview.md @@ -5,7 +5,7 @@ id: "overview" # What is dbt? -dbt (data build tool) is a productivity tool that helps analysts get more done and produce higher quality results. +dbt is a productivity tool that helps analysts get more done and produce higher quality results. Analysts commonly spend 50-80% of their time modeling raw data—cleaning, reshaping, and applying fundamental business logic to it. dbt empowers analysts to do this work better and faster. @@ -13,9 +13,9 @@ dbt's primary interface is its CLI. Using dbt is a combination of editing code i # How does dbt work? -dbt has two core workflows: building data models and testing data models. (We call any transformed view of raw data a data model.) +dbt has two core workflows: building data models and testing data models. (We call any transformed of raw data a data model.) -To create a data model, an analyst simply writes a SQL `SELECT` statement. dbt then takes that statement and builds it in the database, materializing it as either a view or a table. This model can then be queried by other models or by other analytics tools. +To create a data model, an analyst simply writes a SQL `SELECT` statement. dbt then takes that statement and builds it in the database, materializing it as either a view or a . This model can then be queried by other models or by other analytics tools. To test a data model, an analyst asserts something to be true about the underlying data. For example, an analyst can assert that a certain field should never be null, should always hold unique values, or should always map to a field in another table. Analysts can also write assertions that express much more customized logic, such as “debits and credits should always be equal within a given journal entry”. dbt then tests all assertions against the database and returns success or failure responses. @@ -23,7 +23,7 @@ To test a data model, an analyst asserts something to be true about the underlyi One dbt user has this to say: *“At this point when I have a new question, I can answer it 10-100x faster than I could before.”* Here’s how: -- dbt allows analysts avoid writing boilerplate DML and DDL: managing transactions, dropping tables, and managing schema changes. All business logic is expressed in SQL `SELECT` statements, and dbt takes care of materialization. +- dbt allows analysts avoid writing boilerplate and : managing transactions, dropping tables, and managing schema changes. All business logic is expressed in SQL `SELECT` statements, and dbt takes care of . - dbt creates leverage. Instead of starting at the raw data with every analysis, analysts instead build up reusable data models that can be referenced in subsequent work. - dbt includes optimizations for data model materialization, allowing analysts to dramatically reduce the time their queries take to run. @@ -48,7 +48,7 @@ While there are a large number of great languages for manipulating data, we’ve # What databases does dbt currently support? -View the full list of supported databases, warehouses, and query engines [here](available-adapters). +See [Supported Data Platforms](supported-data-platforms) to view the full list of supported databases, warehouses, and query engines. # How do I get started? diff --git a/website/docs/docs/about/viewpoint.md b/website/docs/docs/about/viewpoint.md index d8ad02a9d9e..9601a3fd46f 100644 --- a/website/docs/docs/about/viewpoint.md +++ b/website/docs/docs/about/viewpoint.md @@ -41,7 +41,7 @@ Bad data can lead to bad analyses, and bad analyses can lead to bad decisions. A Your analysis is a software application, and, like every other software application, people are going to have questions about how to use it. Even though it might seem simple, in reality the “Revenue” line you’re showing could mean dozens of things. Your code should come packaged with a basic description of how it should be interpreted, and your team should be able to add to that documentation as additional questions arise. ### Modularity -If you build a series of analyses about your company’s revenue, and your colleague does as well, you should use the same input data. Copy-paste is not a good approach here — if the definition of the underlying set changes, it will need to be updated everywhere it was used. Instead, think of the schema of a data set as its public interface. Create tables, views, or other data sets that expose a consistent schema and can be modified if business logic changes. +If you build a series of analyses about your company’s revenue, and your colleague does as well, you should use the same input data. Copy-paste is not a good approach here — if the definition of the underlying set changes, it will need to be updated everywhere it was used. Instead, think of the schema of a data set as its public interface. Create tables, views, or other data sets that expose a consistent schema and can be modified if business logic changes. ## Analytic code is an asset The code, processes, and tooling required to produce that analysis are core organizational investments. We believe a mature analytics organization’s workflow should have the following characteristics so as to protect and grow that investment: @@ -67,4 +67,4 @@ Here’s one example of an automated workflow: - code is tested, and - code is deployed. -Workflows like this should be built to execute with a single command. \ No newline at end of file +Workflows like this should be built to execute with a single command. diff --git a/website/docs/docs/available-adapters.md b/website/docs/docs/available-adapters.md deleted file mode 100644 index 40526c56e70..00000000000 --- a/website/docs/docs/available-adapters.md +++ /dev/null @@ -1,55 +0,0 @@ ---- -title: "Available adapters" -id: "available-adapters" ---- - -dbt connects to and runs SQL against your database, warehouse, platform, or query engine. It works by using a dedicated **adapter** for each technology. All the adapters listed below are open source and free to use, just like dbt. - -Any adapter can be installed from PyPi using `pip`. The installation will include `dbt-core` and any other required dependencies, which may include other adapter plugins. Read more about [installing dbt](dbt-cli/install/overview). - -### dbt Labs Supported - -In addition to maintaining `dbt-core`, [dbt Labs](https://github.com/dbt-labs) maintains a set of adapters for some of the most common databases, warehouses, and platforms. (✅ indicates "full support.") - -| Adapter for | Documentation | Core features | dbt Cloud | Install from PyPi | -| ------------ | ------------- | ------------- | --------- | ----------------- | -| Postgres | [Profile Setup](postgres-profile) | ✅ | ✅ | `pip install dbt-postgres` | -| Redshift | [Profile Setup](redshift-profile), [Configuration](redshift-configs) | ✅ | ✅ | `pip install dbt-redshift` | -| BigQuery | [Profile Setup](bigquery-profile), [Configuration](bigquery-configs) | ✅ | ✅ | `pip install dbt-bigquery` | -| Snowflake | [Profile Setup](snowflake-profile), [Configuration](snowflake-configs) | ✅ | ✅ | `pip install dbt-snowflake` | -| Apache Spark | [Profile Setup](spark-profile), [Configuration](spark-configs) | ✅ | ✅ | `pip install dbt-spark[PyHive]` | -| Databricks | [Profile Setup](spark-profile#odbc), [Configuration](spark-configs#databricks-configurations) | ✅ | ✅ | `pip install dbt-spark[ODBC]` | -| Presto | [Profile Setup](presto-profile) | partial support | | `pip install dbt-presto` | - -### Vendor Supported - -These adapter plugins are built and maintained by the same people who build and maintain the complementary data technology. - -| Adapter for | Documentation | Install from PyPi | -| ------------ | ------------- | ----------------- | -| Materialize ([dbt-materialize](https://github.com/MaterializeInc/materialize/blob/main/misc/dbt-materialize)) | [Profile Setup](materialize-profile) | `pip install dbt-materialize` | -| Rockset ([dbt-rockset](https://github.com/rockset/dbt-rockset)) | [Profile Setup](rockset-profile) | `pip install dbt-rockset` | -| Starburst & Trino ([dbt-trino](https://github.com/starburstdata/dbt-trino)) | [Profile Setup](trino-profile) | `pip install dbt-trino` - -### Community Supported - -These adapter plugins are contributed and maintained by members of the community 🌱 - -| Adapter for | Documentation | Notes | Install from PyPI | -|------------------------|---------------------------------------|---------------------------|------------------------------| -| SQL Server & Azure SQL | [Profile Setup](mssql-profile) | SQL Server 2016 and later | `pip install dbt-sqlserver` | -| Azure Synapse | [Profile Setup](azuresynapse-profile) | Azure Synapse 10+ | `pip install dbt-synapse` | -| Exasol Analytics | [Profile Setup](exasol-profile) | Exasol 6.x and later | `pip install dbt-exasol` | -| Oracle Database | [Profile Setup](oracle-profile) | Oracle 11+ | `pip install dbt-oracle` | -| Dremio | [Profile Setup](dremio-profile) | Dremio 4.7+ | `pip install dbt-dremio` | -| ClickHouse | [Profile Setup](clickhouse-profile) | ClickHouse 20.11+ | `pip install dbt-clickhouse` | - -Community-supported plugins are works in progress, and all users are encouraged to contribute by testing and writing code. If you're interested in contributing: -- Join the dedicated channel in [dbt Slack](https://community.getdbt.com/) (e.g. #db-sqlserver, #db-athena) -- Check out the open issues in the plugin's source repository - -Note that, while no community plugins are currently supported in dbt Cloud, we expect this to change in the near future. - -## Creating a new adapter - -dbt can be extended to any SQL-speaking database, warehouse, data lake, query engine, or analytical platform by means of an _adapter plugin_. These plugins can be built as separate Python modules, and dbt will discover them if they are installed on your system. If you see something missing from the lists above, and you're interested in developing an integration, read more about [building a new adapter](building-a-new-adapter). diff --git a/website/docs/docs/building-a-dbt-project/analyses.md b/website/docs/docs/building-a-dbt-project/analyses.md index 2f67ba33b98..2368c9b817d 100644 --- a/website/docs/docs/building-a-dbt-project/analyses.md +++ b/website/docs/docs/building-a-dbt-project/analyses.md @@ -46,4 +46,4 @@ To compile this analysis into runnable sql, run: dbt compile ``` -Then, look for the compiled SQL file in `target/compiled/{project name}/analyses/running_total_by_account.sql`. This sql can then be pasted into a data visualization tool, for instance. Note that no `running_total_by_account` relation will be materialized in the database as this is an `analysis`, not a `model`. \ No newline at end of file +Then, look for the compiled SQL file in `target/compiled/{project name}/analyses/running_total_by_account.sql`. This sql can then be pasted into a data visualization tool, for instance. Note that no `running_total_by_account` relation will be materialized in the database as this is an `analysis`, not a `model`. diff --git a/website/docs/docs/building-a-dbt-project/building-models.md b/website/docs/docs/building-a-dbt-project/building-models.md index 2dce6f08499..3477ed45734 100644 --- a/website/docs/docs/building-a-dbt-project/building-models.md +++ b/website/docs/docs/building-a-dbt-project/building-models.md @@ -13,16 +13,24 @@ id: "building-models" :::info Building your first models -If you're new to dbt, we recommend that you check out our [Getting Started Tutorial](tutorial/1-setting-up.md) to build your first dbt project with models. +If you're new to dbt, we recommend that you check out our [Getting Started guide](/guides/getting-started) to build your first dbt project with models. ::: + + +In v1.3, dbt Core is adding support for **Python models**. + +dbt's Python capabilities are an extension of its capabilities with SQL models, which are introduced in the discussion and examples below. If you're new to dbt, we recommend that you read this page first, before reading: ["Python Models"](python-models) + + + A model is a `select` statement. Models are defined in `.sql` files (typically in your `models` directory): - Each `.sql` file contains one model / `select` statement - The name of the file is used as the model name - Models can be nested in subdirectories within the `models` directory -When you execute the [`dbt run` command](run), dbt will build this model in your data warehouse by wrapping it in a `create view as` or `create table as` statement. +When you execute the [`dbt run` command](run), dbt will build this model in your by wrapping it in a `create view as` or `create table as` statement. For example, consider this `customers` model: @@ -56,7 +64,7 @@ left join customer_orders using (customer_id) -When you execute `dbt run`, dbt will build this as a view named `customers` in your target schema: +When you execute `dbt run`, dbt will build this as a named `customers` in your target schema: ```sql create view dbt_alice.customers as ( @@ -87,22 +95,22 @@ create view dbt_alice.customers as ( ``` Why a _view_ named `dbt_alice.customers`? By default dbt will: -* create models as views +* create models as views * build models in a target schema you define -* use your file name as the view or table name in the database +* use your file name as the view or name in the database You can use _configurations_ to change any of these behaviors — more on that below. ### FAQs - - - - - + + + + + ## Configuring models Configurations are "model settings" that can be set in your `dbt_project.yml` file, _and_ in your model file using a `config` block. Some example configurations include: -* Change the [materialization](materializations) that a model uses — a materialization determines the SQL that dbt uses to create the model in your warehouse. +* Change the [materialization](materializations) that a model uses — a determines the SQL that dbt uses to create the model in your warehouse. * Build models into separate [schemas](using-custom-schemas). * Apply [tags](resource-configs/tags) to a model. @@ -148,15 +156,15 @@ Importantly, configurations are applied hierarchically — a configuration appli You can learn more about configurations in the [reference docs](model-configs). ### FAQs - - + + ## Building dependencies between models By using the [`ref` function](ref) in the place of table names in a query, you can build dependencies between models. Use the name of another model as the argument for `ref`. -* Manage separate environments — dbt will replace the model specified in the `ref` function with the database name for the table (or view). Importantly, this is environment-aware — if you're running dbt with a target schema named `dbt_alice`, it will select from an upstream table in the same schema. Check out the tabs above to see this in action. +* Manage separate environments — dbt will replace the model specified in the `ref` function with the database name for the (or view). Importantly, this is environment-aware — if you're running dbt with a target schema named `dbt_alice`, it will select from an upstream table in the same schema. Check out the tabs above to see this in action. Additionally, the `ref` function encourages you to write modular transformations, so that you can re-use models, and reduce repeated code. @@ -255,12 +263,12 @@ You can also document and test models — skip ahead to the section on [testing] ## Additional FAQs - - - - - - - - - + + + + + + + + + diff --git a/website/docs/docs/building-a-dbt-project/building-models/configuring-incremental-models.md b/website/docs/docs/building-a-dbt-project/building-models/configuring-incremental-models.md index 0f37a2bc7ad..6df02ada930 100644 --- a/website/docs/docs/building-a-dbt-project/building-models/configuring-incremental-models.md +++ b/website/docs/docs/building-a-dbt-project/building-models/configuring-incremental-models.md @@ -3,15 +3,17 @@ title: "Configuring incremental models" id: "configuring-incremental-models" --- -## What is an incremental model? -Incremental models are built as tables in your data warehouse – the first time a model is run, the table is built by transforming _all_ rows of source data. On subsequent runs, dbt transforms _only_ the rows in your source data that you tell dbt to filter for, inserting them into the table that has already been built (the target table). +## About incremental models + +Incremental models are built as tables in your . The first time a model is run, the is built by transforming _all_ rows of source data. On subsequent runs, dbt transforms _only_ the rows in your source data that you tell dbt to filter for, inserting them into the target table which is the table that has already been built. Often, the rows you filter for on an incremental run will be the rows in your source data that have been created or updated since the last time dbt ran. As such, on each dbt run, your model gets built incrementally. Using an incremental model limits the amount of data that needs to be transformed, vastly reducing the runtime of your transformations. This improves warehouse performance and reduces compute costs. -## How do I use the incremental materialization? -Like the other materializations built into dbt, incremental models are defined with `select` statements, with the the materialization defined in a config block. +## Using incremental materializations + +Like the other materializations built into dbt, incremental models are defined with `select` statements, with the materialization defined in a config block. ```sql {{ config( @@ -24,11 +26,12 @@ select ... ``` To use incremental models, you also need to tell dbt: -* how to filter the rows on an incremental run. -* the uniqueness constraint of the model (if any). +* How to filter the rows on an incremental run. +* The uniqueness constraint of the model (if any). ### Filtering rows on an incremental run + To tell dbt which rows it should transform on an incremental run, wrap valid SQL that filters for these rows in the `is_incremental()` macro. Often, you'll want to filter for "new" rows, as in, rows that have been created since the last time dbt ran this model. The best way to find the timestamp of the most recent run of this model is by checking the most recent timestamp in your target table. dbt makes it easy to query your target table by using the "[{{ this }}](this)" variable. @@ -64,16 +67,46 @@ from raw_app_data.events :::tip Optimizing your incremental model -For more complex incremental models that make use of CTEs, you should consider the impact of the position of the `is_incremental()` macro on query performance. On some warehouses, filtering your records early can vastly improve the run time of your query! +For more complex incremental models that make use of Common Table Expressions (CTEs), you should consider the impact of the position of the `is_incremental()` macro on query performance. In some warehouses, filtering your records early can vastly improve the run time of your query! ::: ### Defining a uniqueness constraint (optional) -`unique_key` is an optional parameter for incremental models that specifies a field which should be unique within your model. If the unique key of an existing row in your target table matches one of your incrementally transformed rows, the existing row will be updated. This ensures that you don't have multiple rows in your target table for a single row in your source data. -You can define `unique_key` in a configuration block at the top of your model. The `unique_key` should be a single field name that is present in your model definition. While some databases support using expressions (eg. `concat(user_id, session_number)`), this syntax is not universally supported, so is not recommended. If you do not have a single field that is unique, consider first creating such a field in your model. +A `unique_key` determines whether a record has new values and should be updated. By using `unique_key`, you can ensure that each row from the source table is represented by a single row in your incremental model, without duplicates. Not specifying a `unique_key` will result in append-only behavior, which means dbt inserts all rows returned by the model's SQL into the preexisting target table without regard for whether the rows represent duplicates. + + + +This optional parameter for incremental models specifies a field that can uniquely identify each row within your model. You can define `unique_key` in a configuration block at the top of your model. If your model doesn't contain a single field that is unique, but rather a combination of columns, we recommend that you create a single column that can serve as unique identifier (by concatenating and hashing those columns), and pass it into your model's configuration. -As an example, consider a model that calculates the number of daily active users (DAUs), based on an event stream. As source data arrives, you will want to recalculate the number of DAUs for both the day that dbt last ran, and any days since then. The model would look as follows: + + + + +This optional parameter for incremental models specifies a field (or combination of fields) that can uniquely identify each row within your model. You can define `unique_key` in a configuration block at the top of your model, and it can be a list in addition to a single column name. + +The `unique_key` should be supplied in your model definition as a string representing a simple column or a list of single quoted column names that can be used together, for example, `['col1', 'col2', …])`. + +:::tip +In cases where you need multiple columns in combination to uniquely identify each row, we recommend you pass these columns as a list (`unique_key = ['user_id', 'session_number']`), rather than a string expression (`unique_key = 'concat(user_id, session_number)'`). + +By using the first syntax, which is more universal, dbt can ensure that the columns will be templated into your incremental model materialization in a way that's appropriate to your database. +::: + + + +When you define a `unique_key`, you'll see this behavior for each row of "new" data returned by your dbt model: + +* If the same `unique_key` is present in the "new" and "old" model data, dbt will update/replace the old row with the new row of data. The exact mechanics of how that update/replace takes place will vary depending on your database and [incremental strategy](#about-incremental_strategy). +* If the `unique_key` is _not_ present in the "old" data, dbt will insert the entire row into the table. + +:::info +While common incremental strategies, such as`delete+insert` + `merge`, might use `unique_key`, others don't. For example, the `insert_overwrite` strategy does not use `unique_key`, because it operates on partitions of data rather than individual rows. For more information, see [About incremental_strategy](#about-incremental_strategy). +::: + +#### `unique_key` example + +Consider a model that calculates the number of daily active users (DAUs), based on an event stream. As source data arrives, you will want to recalculate the number of DAUs for both the day that dbt last ran, and any days since then. The model would look as follows: @@ -135,6 +168,7 @@ The `is_incremental()` macro will return `True` if: Note that the SQL in your model needs to be valid whether `is_incremental()` evaluates to `True` or `False`. ## How do incremental models work behind the scenes? + dbt's incremental materialization works differently on different databases. Where supported, a `merge` statement is used to insert new records and update existing records. On warehouses that do not support `merge` statements, a merge is implemented by first using a `delete` statement to delete records in the target table that are to be updated, and then an `insert` statement. @@ -179,7 +213,7 @@ The possible values for `on_schema_change` are: * `ignore`: Default behavior (see below). * `fail`: Triggers an error message when the source and target schemas diverge * `append_new_columns`: Append new columns to the existing table. Note that this setting does *not* remove columns from the existing table that are not present in the new data. -* `sync_all_columns`: Adds any new columns to the existing table, and removes any columns that are now missing. Note that this is *inclusive* of data type changes. On BigQuery, changing column types requires a full table scan; be mindful of the trade-offs when implementing. +* `sync_all_columns`: Adds any new columns to the existing table, and removes any columns that are now missing. Note that this is *inclusive* of data type changes. On BigQuery, changing column types requires a full scan; be mindful of the trade-offs when implementing. **Note**: None of the `on_schema_change` behaviors backfill values in old records for newly added columns. If you need to populate those values, we recommend running manual updates, or triggering a `--full-refresh`. @@ -193,7 +227,7 @@ Similarly, if you remove a column from your incremental model, and execute a `db Instead, whenever the logic of your incremental changes, execute a full-refresh run of both your incremental model and any downstream models. -## What is an incremental_strategy? +## About incremental_strategy On some adapters, an optional `incremental_strategy` config controls the code that dbt uses to build incremental models. Different approaches may vary by effectiveness depending on the volume of data, @@ -226,7 +260,7 @@ or: config( materialized='incremental', unique_key='date_day', - incremental_strategy='insert_overwrite', + incremental_strategy='delete+insert', ... ) }} diff --git a/website/docs/docs/building-a-dbt-project/building-models/materializations.md b/website/docs/docs/building-a-dbt-project/building-models/materializations.md index 3b71b096943..de9275ec6b5 100644 --- a/website/docs/docs/building-a-dbt-project/building-models/materializations.md +++ b/website/docs/docs/building-a-dbt-project/building-models/materializations.md @@ -4,9 +4,11 @@ id: "materializations" --- ## Overview -Materializations are strategies for persisting dbt models in a warehouse. There are four types of materializations built into dbt. They are: -- table -- view + +Materializations are strategies for persisting dbt models in a warehouse. There are four types of materializations built into dbt. They are: + +- +- - incremental - ephemeral @@ -69,7 +71,7 @@ When using the `view` materialization, your model is rebuilt as a view on each r * Views are best suited for models that do not do significant transformation, e.g. renaming, recasting columns. ### Table -When using the `table` materialization, your model is rebuilt as a table on each run, via a `create table as` statement. +When using the `table` materialization, your model is rebuilt as a on each run, via a `create table as` statement. * **Pros:** Tables are fast to query * **Cons:** * Tables can take a long time to rebuild, especially for complex transformations @@ -88,10 +90,10 @@ When using the `table` materialization, your model is rebuilt as a table on each * Use incremental models when your `dbt run`s are becoming too slow (i.e. don't start with incremental models) ### Ephemeral -`ephemeral` models are not directly built into the database. Instead, dbt will interpolate the code from this model into dependent models as a common table expression. +`ephemeral` models are not directly built into the database. Instead, dbt will interpolate the code from this model into dependent models as a common expression. * **Pros:** * You can still write reusable logic - * Ephemeral models can help keep your data warehouse clean by reducing clutter (also consider splitting your models across multiple schemas by [using custom schemas](using-custom-schemas)). + * Ephemeral models can help keep your clean by reducing clutter (also consider splitting your models across multiple schemas by [using custom schemas](using-custom-schemas)). * **Cons:** * You cannot select directly from this model. * Operations (e.g. macros called via `dbt run-operation` cannot `ref()` ephemeral nodes) diff --git a/website/docs/docs/building-a-dbt-project/building-models/python-models.md b/website/docs/docs/building-a-dbt-project/building-models/python-models.md new file mode 100644 index 00000000000..3289a1fbf69 --- /dev/null +++ b/website/docs/docs/building-a-dbt-project/building-models/python-models.md @@ -0,0 +1,713 @@ +--- +title: "Python models" +--- + +:::info Prerelease + +dbt Core v1.3, currently available as a release candidate, adds Python models to dbt. Note that only [specific data platforms](#specific-data-platforms) support dbt-py models. + +We encourage you to: +- Read [the original discussion](https://github.com/dbt-labs/dbt-core/discussions/5261) that proposed this feature. +- Contribute to [best practices for developing Python models in dbt](https://github.com/dbt-labs/docs.getdbt.com/discussions/1811). +- Weigh in on [next steps for Python models, beyond v1.3](https://github.com/dbt-labs/dbt-core/discussions/5742). +- Join the **#beta-feedback-python-models** channel in the [dbt Community Slack](https://www.getdbt.com/community/join-the-community/). + +Below, you'll see sections entitled "❓ **Our questions**." We are excited to release a first narrow set of functionality in v1.3, which will solve real use cases. We also know this is a first step into a much wider field of possibility. We don't pretend to have all the answers. We're excited to keep developing our opinionated recommendations and next steps for product development—and we want your help. Comment in the GitHub discussions; leave thoughts in Slack; bring up dbt + Python in casual conversation with colleagues and friends. +::: + +## About Python models in dbt + +dbt Python ("dbt-py") models will help you solve use cases that can't be solved with SQL. You can perform analyses using tools available in the open source Python ecosystem, including state-of-the-art packages for data science and statistics. Before, you would have needed separate infrastructure and orchestration to run Python transformations in production. By defining your Python transformations in dbt, they're just models in your project, with all the same capabilities around testing, documentation, and lineage. + + + +Python models are supported in dbt Core 1.3 and above. Learn more about [upgrading your version in dbt Cloud](https://docs.getdbt.com/docs/dbt-cloud/cloud-configuring-dbt-cloud/cloud-upgrading-dbt-versions) and [upgrading dbt Core versions](https://docs.getdbt.com/docs/core-versions#upgrading-to-new-patch-versions). + +To read more about Python models, change the docs version to 1.3 or higher in the menu above. + + + + + + + + +```python +import ... + +def model(dbt, session): + + my_sql_model_df = dbt.ref("my_sql_model") + + final_df = ... # stuff you can't write in SQL! + + return final_df +``` + + + + + +```yml +version: 2 + +models: + - name: my_python_model + + # Document within the same codebase + description: My transformation written in Python + + # Configure in ways that feel intuitive and familiar + config: + materialized: table + tags: ['python'] + + # Test the results of my Python transformation + columns: + - name: id + # Standard validation for 'grain' of Python results + tests: + - unique + - not_null + tests: + # Write your own validation logic (in SQL) for Python results + - [custom_generic_test](writing-custom-generic-tests) +``` + + + + + + +The prerequisites for dbt Python models include using an adapter for a data platform that supports a fully featured Python runtime. In a dbt Python model, all Python code is executed remotely on the platform. None of it is run by dbt locally. We believe in clearly separating _model definition_ from _model execution_. In this and many other ways, you'll find that dbt's approach to Python models mirrors its longstanding approach to modeling data in SQL. + +We've written this guide assuming that you have some familiarity with dbt. If you've never before written a dbt model, we encourage you to start by first reading ["dbt Models"](building-models). Throughout, we'll be drawing connections between Python models and SQL models, as well as making clear their differences. + +### What is a Python model? + +A dbt Python model is a function that reads in dbt sources or other models, applies a series of transformations, and returns a transformed dataset. DataFrame operations define the starting points, the end state, and each step along the way. + +This is similar to the role of CTEs in dbt SQL models. We use CTEs to pull in upstream datasets, define (and name) a series of meaningful transformations, and end with a final `select` statement. You can run the compiled version of a dbt SQL model to see the data included in the resulting view or table. When you `dbt run`, dbt wraps that query in `create view`, `create table`, or more complex DDL to save its results in the database. + +Instead of a final `select` statement, each Python model returns a final DataFrame. Each DataFrame operation is "lazily evaluated." In development, you can preview its data, using methods like `.show()` or `.head()`. When you run a Python model, the full result of the final DataFrame will be saved as a table in your data warehouse. + +dbt Python models have access to almost all of the same configuration options as SQL models. You can test them, document them, add `tags` and `meta` properties to them, grant access to their results to other users, and so on. You can select them by their name, their file path, their configurations, whether they are upstream or downstream of another model, or whether they have been modified compared to a previous project state. + +### Defining a Python model + +Each Python model lives in a `.py` file in your `models/` folder. It defines a function named **`model()`**, which takes two parameters: +- **`dbt`**: A class compiled by dbt Core, unique to each model, enables you to run your Python code in the context of your dbt project and DAG. +- **`session`**: A class representing your data platform’s connection to the Python backend. The session is needed to read in tables as DataFrames, and to write DataFrames back to tables. In PySpark, by convention, the `SparkSession` is named `spark`, and available globally. For consistency across platforms, we always pass it into the `model` function as an explicit argument called `session`. + +The `model()` function must return a single DataFrame. On Snowpark (Snowflake), this can be a Snowpark or pandas DataFrame. Via PySpark (Databricks + BigQuery), this can be a Spark, pandas, or pandas-on-Spark DataFrame. For more about choosing between pandas and native DataFrames, see ["DataFrame API + syntax"](#dataframe-api--syntax). + +When you `dbt run --select python_model`, dbt will prepare and pass in both arguments (`dbt` and `session`). All you have to do is define the function. This is how every single Python model should look: + + + +```python +def model(dbt, session): + + ... + + return final_df +``` + + + + +### Referencing other models + +Python models participate fully in dbt's directed acyclic graph (DAG) of transformations. Use the `dbt.ref()` method within a Python model to read in data from other models (SQL or Python). If you want to read directly from a raw source table, use `dbt.source()`. These methods return DataFrames pointing to the upstream source, model, seed, or snapshot. + + + +```python +def model(dbt, session): + + # DataFrame representing an upstream model + upstream_model = dbt.ref("upstream_model_name") + + # DataFrame representing an upstream source + upstream_source = dbt.source("upstream_source_name", "table_name") + + ... +``` + + + +Of course, you can `ref()` your Python model in downstream SQL models, too: + + + +```sql +with upstream_python_model as ( + + select * from {{ ref('my_python_model') }} + +), + +... +``` + + + +### Configuring Python models + +Just like SQL models, there are three ways to configure Python models: +1. In `dbt_project.yml`, where you can configure many models at once +2. In a dedicated `.yml` file, within the `models/` directory +3. Within the model's `.py` file, using the `dbt.config()` method + +Calling the `dbt.config()` method will set configurations for your model right within your `.py` file, similar to the `{{ config() }}` macro in `.sql` model files: + + + +```python +def model(dbt, session): + + # setting configuration + dbt.config(materialized="table") +``` + + + +There's a limit to how fancy you can get with the `dbt.config()` method. It accepts _only_ literal values (strings, booleans, and numeric types). Passing another function or a more complex data structure is not possible. The reason is that dbt statically analyzes the arguments to `config()` while parsing your model without executing your Python code. If you need to set a more complex configuration, we recommend you define it using the [`config` property](resource-properties/config) in a yaml file. + +#### Accessing project context + +dbt Python models don't use Jinja to render compiled code. Python models have limited access to global project contexts compared to SQL models. That context is made available from the `dbt` class, passed in as an argument to the `model()` function. + +Out of the box, the `dbt` class supports: +- Returning DataFrames referencing the locations of other resources: `dbt.ref()` + `dbt.source()` +- Accessing the database location of the current model: `dbt.this()` (also: `dbt.this.database`, `.schema`, `.identifier`) +- Determining if the current model's run is incremental: `dbt.is_incremental` + +It is possible to extend this context by "getting" them via `dbt.config.get()` after they are configured in the [model's config](/reference/model-configs). This includes inputs such as `var`, `env_var`, and `target`. If you want to use those values to power conditional logic in your model, we require setting them through a dedicated `.yml` file config: + + + +```yml +version: 2 + +models: + - name: my_python_model + config: + materialized: table + target_name: "{{ target.name }}" + specific_var: "{{ var('SPECIFIC_VAR') }}" + specific_env_var: "{{ env_var('SPECIFIC_ENV_VAR') }}" +``` + + + +Then, within the model's Python code, use the `dbt.config.get()` function to _access_ values of configurations that have been set: + + + +```python +def model(dbt, session): + target_name = dbt.config.get("target_name") + specific_var = dbt.config.get("specific_var") + specific_env_var = dbt.config.get("specific_env_var") + + orders_df = dbt.ref("fct_orders") + + # limit data in dev + if target_name == "dev": + orders_df = orders_df.limit(500) +``` + + + +### Materializations + +Python models support two materializations: +- `table` +- `incremental` + +Incremental Python models support all the same [incremental strategies](configuring-incremental-models#about-incremental_strategy) as their SQL counterparts. The specific strategies supported depend on your adapter. + +Python models can't be materialized as `view` or `ephemeral`. Python isn't supported for non-model resource types (like tests and snapshots). + +For incremental models, like SQL models, you will need to filter incoming tables to only new rows of data: + + + +
+ + + +```python +import snowflake.snowpark.functions as F + +def model(dbt, session): + dbt.config(materialized = "incremental") + df = dbt.ref("upstream_table") + + if dbt.is_incremental: + + # only new rows compared to max in current table + max_from_this = f"select max(updated_at) from {dbt.this}" + df = df.filter(df.updated_at >= session.sql(max_from_this).collect()[0][0]) + + # or only rows from the past 3 days + df = df.filter(df.updated_at >= F.dateadd("day", F.lit(-3), F.current_timestamp())) + + ... + + return df +``` + + + +
+ +
+ + + +```python +import pyspark.sql.functions as F + +def model(dbt, session): + dbt.config(materialized = "incremental") + df = dbt.ref("upstream_table") + + if dbt.is_incremental: + + # only new rows compared to max in current table + max_from_this = f"select max(updated_at) from {dbt.this}" + df = df.filter(df.updated_at >= session.sql(max_from_this).collect()[0][0]) + + # or only rows from the past 3 days + df = df.filter(df.updated_at >= F.date_add(F.current_timestamp(), F.lit(-3))) + + ... + + return df +``` + + + +
+ +
+ +**Note:** Incremental models are supported on BigQuery/Dataproc for the `merge` incremental strategy. The `insert_overwrite` strategy is not yet supported. + +## Python-specific functionality + +### Defining functions + +In addition to defining a `model` function, the Python model can import other functions or define its own. Here's an example, on Snowpark, defining a custom `add_one` function: + + + +```python +def add_one(x): + return x + 1 + +def model(dbt, session): + dbt.config(materialized="table") + temps_df = dbt.ref("temperatures") + + # warm things up just a little + df = temps_df.withColumn("degree_plus_one", add_one(temps_df["degree"])) + return df +``` + + + +At present, Python functions defined in one dbt model can't be imported and reused in other models. See the ["Code reuse"](#code-reuse) section for the potential patterns we're considering. + +### Using PyPI packages + +You can also define functions that depend on third-party packages, so long as those packages are installed and available to the Python runtime on your data platform. See notes on "Installing Packages" for [specific data warehouses](#specific-data-warehouses). + +In this example, we use the `holidays` package to determine if a given date is a holiday in France. For simplicity and consistency across platforms, the code below uses the pandas API. The exact syntax, and the need to refactor for multi-node processing, still varies. + + + +
+ + + +```python +import holidays + +def is_holiday(date_col): + # Chez Jaffle + french_holidays = holidays.France() + is_holiday = (date_col in french_holidays) + return is_holiday + +def model(dbt, session): + dbt.config( + materialized = "table", + packages = ["holidays"] + ) + + orders_df = dbt.ref("stg_orders") + + df = orders_df.to_pandas() + + # apply our function + # (columns need to be in uppercase on Snowpark) + df["IS_HOLIDAY"] = df["ORDER_DATE"].apply(is_holiday) + + # return final dataset (Pandas DataFrame) + return df +``` + + + +
+ +
+ + + +```python +import holidays + +def is_holiday(date_col): + # Chez Jaffle + french_holidays = holidays.France() + is_holiday = (date_col in french_holidays) + return is_holiday + +def model(dbt, session): + dbt.config( + materialized = "table", + packages = ["holidays"] + ) + + orders_df = dbt.ref("stg_orders") + + df = orders_df.to_pandas_on_spark() # Spark 3.2+ + # df = orders_df.toPandas() in earlier versions + + # apply our function + df["is_holiday"] = df["order_date"].apply(is_holiday) + + # convert back to PySpark + df = df.to_spark() # Spark 3.2+ + # df = session.createDataFrame(df) in earlier versions + + # return final dataset (PySpark DataFrame) + return df +``` + + + +
+ +
+ +#### Configuring packages + +We encourage you to explicitly configure required packages and versions so dbt can track them in project metadata. This configuration is required for the implementation on some platforms. If you need specific versions of packages, specify them. + + + +```python +def model(dbt, session): + dbt.config( + packages = ["numpy==1.23.1", "scikit-learn"] + ) +``` + + + + + +```yml +version: 2 + +models: + - name: my_python_model + config: + packages: + - "numpy==1.23.1" + - scikit-learn +``` + + + +#### UDFs + +You can use the `@udf` decorator or `udf` function to define an "anonymous" function and call it within your `model` function's DataFrame transformation. This is a typical pattern for applying more complex functions as DataFrame operations, especially if those functions require inputs from third-party packages. +- [Snowpark Python: Creating UDFs](https://docs.snowflake.com/en/developer-guide/snowpark/python/creating-udfs.html) +- ["PySpark functions: udf"](https://spark.apache.org/docs/latest/api/python/reference/pyspark.sql/api/pyspark.sql.functions.udf.html) + + + +
+ + + +```python +import snowflake.snowpark.types as T +import snowflake.snowpark.functions as F +import numpy + +def register_udf_add_random(): + add_random = F.udf( + # use 'lambda' syntax, for simple functional behavior + lambda x: x + numpy.random.normal(), + return_type=T.FloatType(), + input_types=[T.FloatType()] + ) + return add_random + +def model(dbt, session): + + dbt.config( + materialized = "table", + packages = ["numpy"] + ) + + temps_df = dbt.ref("temperatures") + + add_random = register_udf_add_random() + + # warm things up, who knows by how much + df = temps_df.withColumn("degree_plus_random", add_random("degree")) + return df +``` + + + +**Note:** Due to a Snowpark limitation, it is not currently possible to register complex named UDFs within stored procedures, and therefore dbt Python models. We are looking to add native support for Python UDFs as a project/DAG resource type in a future release. For the time being, if you want to create a "vectorized" Python UDF via the Batch API, we recommend either: +- Writing [`create function`](https://docs.snowflake.com/en/developer-guide/udf/python/udf-python-batch.html) inside a SQL macro, to run as a hook or run-operation +- [Registering from a staged file](https://docs.snowflake.com/ko/developer-guide/snowpark/reference/python/_autosummary/snowflake.snowpark.udf.html#snowflake.snowpark.udf.UDFRegistration.register_from_file) within your Python model code + +
+ +
+ + + +```python +from pyspark.sql.types as T +import pyspark.sql.functions as F +import numpy + +# use a 'decorator' for more readable code +@F.udf(returnType=T.DoubleType()) +def add_random(x): + random_number = numpy.random.normal() + return x + random_number + +def model(dbt, session): + dbt.config( + materialized = "table", + packages = ["numpy"] + ) + + temps_df = dbt.ref("temperatures") + + # warm things up, who knows by how much + df = temps_df.withColumn("degree_plus_random", add_random("degree")) + return df +``` + + + +
+ +
+ +#### Code reuse + +Currently, Python functions defined in one dbt model cannot be imported and reused in other models. This is something we'd like dbt to support. There are two patterns we're considering: +1. Creating and registering **"named" UDFs**. This process is different across data platforms and has some performance limitations. (Snowpark does support ["vectorized" UDFs](https://docs.snowflake.com/en/developer-guide/udf/python/udf-python-batch.html): Pandas-like functions that can be executed in parallel.) +2. Using **private Python packages**. In addition to importing reusable functions from public PyPI packages, many data platforms support uploading custom Python assets and registering them as packages. The upload process looks different across platforms, but your code’s actual `import` looks the same. + +:::note ❓ Our questions + +- Should dbt have a role in abstracting over UDFs? Should dbt support a new type of DAG node, `function`? Would the primary use case be code reuse across Python models or defining Python-language functions that can be called from SQL models? +- How can dbt help users when uploading or initializing private Python assets? Is this a new form of `dbt deps`? +- How can dbt support users who want to test custom functions? If defined as UDFs: "unit testing" in the database? If "pure" functions in packages: encourage adoption of `pytest`? + +💬 Discussion: ["Python models: package, artifact/object storage, and UDF management in dbt"](https://github.com/dbt-labs/dbt-core/discussions/5741) +::: + +### DataFrame API and syntax + +Over the past decade, most people writing data transformations in Python have adopted DataFrame as their common abstraction. dbt follows this convention by returning `ref()` and `source()` as DataFrames, and it expects all Python models to return a DataFrame. + +A DataFrame is a two-dimensional data structure (rows and columns). It supports convenient methods for transforming that data, creating new columns from calculations performed on existing columns. It also offers convenient ways for previewing data while developing locally or in a notebook. + +That's about where the agreement ends. There are numerous frameworks with their own syntaxes and APIs for DataFrames. The [pandas](https://pandas.pydata.org/docs/) library offered one of the original DataFrame APIs, and its syntax is the most common to learn for new data professionals. Most newer DataFrame APIs are compatible with pandas-style syntax, though few can offer perfect interoperability. This is true for Snowpark and PySpark, which have their own DataFrame APIs. + +When developing a Python model, you will find yourself asking these questions: + +**Why Pandas?** It's the most common API for DataFrames. It makes it easy to explore sampled data and develop transformations locally. You can “promote” your code as-is into dbt models and run it in production for small datasets. + +**Why _not_ Pandas?** Performance. Pandas runs "single-node" transformations, which cannot benefit from the parallelism and distributed computing offered by modern data warehouses. This quickly becomes a problem as you operate on larger datasets. Some data platforms support optimizations for code written using Pandas' DataFrame API, preventing the need for major refactors. For example, ["Pandas on PySpark"](https://spark.apache.org/docs/latest/api/python/getting_started/quickstart_ps.html) offers support for 95% of Pandas functionality, using the same API while still leveraging parallel processing. + +:::note ❓ Our questions +- When developing a new dbt Python model, should we recommend Pandas-style syntax for rapid iteration and then refactor? +- Which open source libraries provide compelling abstractions across different data engines and vendor-specific APIs? +- Should dbt attempt to play a longer-term role in standardizing across them? + +💬 Discussion: ["Python models: the Pandas problem (and a possible solution)"](https://github.com/dbt-labs/dbt-core/discussions/5738) +::: + +### Limitations + +Python models have capabilities that SQL models do not. They also have some drawbacks compared to SQL models: + +- **Time and cost.** Python models are slower to run than SQL models, and the cloud resources that run them can be more expensive. Running Python requires more general-purpose compute. That compute might sometimes live on a separate service or architecture from your SQL models. **However:** We believe that deploying Python models via dbt—with unified lineage, testing, and documentation—is, from a human standpoint, **dramatically** faster and cheaper. By comparison, spinning up separate infrastructure to orchestrate Python transformations in production and different tooling to integrate with dbt is much more time-consuming and expensive. +- **Syntax differences** are even more pronounced. Over the years, dbt has done a lot, via dispatch patterns and packages such as `dbt_utils`, to abstract over differences in SQL dialects across popular data warehouses. Python offers a **much** wider field of play. If there are five ways to do something in SQL, there are 500 ways to write it in Python, all with varying performance and adherence to standards. Those options can be overwhelming. As the maintainers of dbt, we will be learning from state-of-the-art projects tackling this problem and sharing guidance as we develop it. +- **These capabilities are very new.** As data warehouses develop new features, we expect them to offer cheaper, faster, and more intuitive mechanisms for deploying Python transformations. **We reserve the right to change the underlying implementation for executing Python models in future releases.** Our commitment to you is around the code in your model `.py` files, following the documented capabilities and guidance we're providing here. + +As a general rule, if there's a transformation you could write equally well in SQL or Python, we believe that well-written SQL is preferable: it's more accessible to a greater number of colleagues, and it's easier to write code that's performant at scale. If there's a transformation you _can't_ write in SQL, or where ten lines of elegant and well-annotated Python could save you 1000 lines of hard-to-read Jinja-SQL, Python is the way to go. + +## Specific data platforms + +In their initial launch, Python models are supported on three of the most popular data platforms: Snowflake, Databricks, and BigQuery/GCP (via Dataproc). Both Databricks and GCP's Dataproc use PySpark as the processing framework. Snowflake uses its own framework, Snowpark, which has many similarities to PySpark. + + + +
+ +**Additional setup:** Snowpark Python is in Public Preview - Open and enabled by default for all accounts. You will need to [acknowledge and accept Snowflake Third Party Terms](https://docs.snowflake.com/en/developer-guide/udf/python/udf-python-packages.html#getting-started) to use Anaconda packages. + +**Installing packages:** Snowpark supports several popular packages via Anaconda. The complete list is at https://repo.anaconda.com/pkgs/snowflake/. Packages are installed at the time your model is being run. Different models can have different package dependencies. If you are using third-party packages, Snowflake recommends using a dedicated virtual warehouse for best performance rather than one with many concurrent users. + +**About "sprocs":** dbt submits Python models to run as "stored procedures," which some people call "sprocs" for short. By default, dbt will create a named sproc containing your model's compiled Python code, and then "call" it to execute. Snowpark has a Private Preview feature for "temporary" or "anonymous" stored procedures ([docs](https://docs.snowflake.com/en/LIMITEDACCESS/call-with.html)), which are faster and leave a cleaner query history. If this feature is enabled for your account, you can switch it on for your models by configuring `use_anonymous_sproc: True`. We plan to switch this on for all dbt + Snowpark Python models in a future release. + + + +```yml +# I asked Snowflake Support to enable this Private Preview feature, +# and now my dbt-py models run even faster! +models: + use_anonymous_sproc: True +``` + + + +**Docs:** ["Developer Guide: Snowpark Python"](https://docs.snowflake.com/en/developer-guide/snowpark/python/index.html) + +
+ +
+ +**Submission methods:** Databricks supports a few different mechanisms to submit PySpark code, each with relative advantages. Some are better for supporting iterative development, while others are better for supporting lower-cost production deployments. The options are: +- `all_purpose_cluster` (default): dbt will run your Python model using the cluster ID configured as `cluster` in your connection profile or for this specific model. These clusters are more expensive but also much more responsive. We recommend using an interactive all-purpose cluster for quicker iteration in development. + - `create_notebook: True`: dbt will upload your model's compiled PySpark code to a notebook in the namespace `/Shared/dbt_python_model/{schema}`, where `{schema}` is the configured schema for the model, and execute that notebook to run using the all-purpose cluster. The appeal of this approach is that you can easily open the notebook in the Databricks UI for debugging or fine-tuning right after running your model. Remember to copy any changes into your dbt `.py` model code before re-running. + - `create_notebook: False` (default): dbt will use the [Command API](https://docs.databricks.com/dev-tools/api/1.2/index.html#run-a-command), which is slightly faster. +- `job_cluster`: dbt will upload your model's compiled PySpark code to a notebook in the namespace `/Shared/dbt_python_model/{schema}`, where `{schema}` is the configured schema for the model, and execute that notebook to run using a short-lived jobs cluster. For each Python model, Databricks will need to spin up the cluster, execute the model's PySpark transformation, and then spin down the cluster. As such, job clusters take longer before and after model execution, but they're also less expensive, so we recommend these for longer-running Python models in production. To use the `job_cluster` submission method, your model must be configured with `job_cluster_config`, which defines key-value properties for `new_cluster`, as defined in the [JobRunsSubmit API](https://docs.databricks.com/dev-tools/api/latest/jobs.html#operation/JobsRunsSubmit). + +You can configure each model's `submission_method` in all the standard ways you supply configuration: + +```python +def model(dbt, session): + dbt.config( + submission_method="all_purpose_cluster", + create_notebook=True, + cluster_id="abcd-1234-wxyz" + ) + ... +``` +```yml +version: 2 +models: + - name: my_python_model + config: + submission_method: job_cluster + job_cluster_config: + spark_version: ... + node_type_id: ... +``` +```yml +# dbt_project.yml +models: + project_name: + subfolder: + # set defaults for all .py models defined in this subfolder + +submission_method: all_purpose_cluster + +create_notebook: False + +cluster_id: abcd-1234-wxyz +``` + +If not configured, `dbt-spark` will use the built-in defaults: the all-purpose cluster (based on `cluster` in your connection profile) without creating a notebook. The `dbt-databricks` adapter will default to the cluster configured in `http_path`. We encourage explicitly configuring the clusters for Python models in Databricks projects. + +**Installing packages:** When using all-purpose clusters, we recommend installing packages which you will be using to run your Python models. + +**Docs:** +- [PySpark DataFrame syntax](https://spark.apache.org/docs/latest/api/python/reference/pyspark.sql/api/pyspark.sql.DataFrame.html) +- [Databricks: Introduction to DataFrames - Python](https://docs.databricks.com/spark/latest/dataframes-datasets/introduction-to-dataframes-python.html) + +
+ +
+ +The `dbt-bigquery` adapter uses a service called Dataproc to submit your Python models as PySpark jobs. That Python/PySpark code will read from your tables and views in BigQuery, perform all computation in Dataproc, and write the final result back to BigQuery. + +**Submission methods.** Dataproc supports two submission methods: `serverless` and `cluster`. Dataproc Serverless does not require a ready cluster, which saves on hassle and cost—but it is slower to start up, and much more limited in terms of available configuration. For example, Dataproc Serverless supports only a small set of Python packages, though it does include `pandas`, `numpy`, and `scikit-learn`. (See the full list [here](https://cloud.google.com/dataproc-serverless/docs/guides/custom-containers#example_custom_container_image_build), under "The following packages are installed in the default image"). Whereas, by creating a Dataproc Cluster in advance, you can fine-tune the cluster's configuration, install any PyPI packages you want, and benefit from faster, more responsive runtimes. + +Use the `cluster` submission method with dedicated Dataproc clusters you or your organization manage. Use the `serverless` submission method to avoid managing a Spark cluster. The latter may be quicker for getting started, but both are valid for production. + +**Additional setup:** +- Create or use an existing [Cloud Storage bucket](https://cloud.google.com/storage/docs/creating-buckets) +- Enable Dataproc APIs for your project + region +- If using the `cluster` submission method: Create or use an existing [Dataproc cluster](https://cloud.google.com/dataproc/docs/guides/create-cluster) with the [Spark BigQuery connector initialization action](https://github.com/GoogleCloudDataproc/initialization-actions/tree/master/connectors#bigquery-connectors). (Google recommends copying the action into your own Cloud Storage bucket, rather than using the example version shown in the screenshot below.) + + + +The following configurations are needed to run Python models on Dataproc. You can add these to your [BigQuery profile](bigquery-profile), or configure them on specific Python models: +- `gcs_bucket`: Storage bucket to which dbt will upload your model's compiled PySpark code. +- `dataproc_region`: GCP region in which you have enabled Dataproc (for example `us-central1`) +- `dataproc_cluster_name`: Name of Dataproc cluster to use for running Python model (executing PySpark job). Only required if `submission_method: cluster`. + +```python +def model(dbt, session): + dbt.config( + submission_method="cluster", + dataproc_cluster_name="my-favorite-cluster" + ) + ... +``` +```yml +version: 2 +models: + - name: my_python_model + config: + submission_method: serverless +``` + +Any user or service account that runs dbt Python models will need the following permissions, in addition to permissions needed for BigQuery ([docs](https://cloud.google.com/dataproc/docs/concepts/iam/iam)): +``` +dataproc.clusters.use +dataproc.jobs.create +dataproc.jobs.get +dataproc.operations.get +storage.buckets.get +storage.objects.create +storage.objects.delete +``` + +**Installing packages:** If you are using a Dataproc Cluster (as opposed to Dataproc Serverless), you can add third-party packages while creating the cluster. + +Google recommends installing Python packages on Dataproc clusters via initialization actions: +- [How initialization actions are used](https://github.com/GoogleCloudDataproc/initialization-actions/blob/master/README.md#how-initialization-actions-are-used) +- [Actions for installing via `pip` or `conda`](https://github.com/GoogleCloudDataproc/initialization-actions/tree/master/python) + +You can also install packages at cluster creation time by [defining cluster properties](https://cloud.google.com/dataproc/docs/tutorials/python-configuration#image_version_20): `dataproc:pip.packages` or `dataproc:conda.packages`. + + + +**Docs:** +- [Dataproc overview](https://cloud.google.com/dataproc/docs/concepts/overview) +- [PySpark DataFrame syntax](https://spark.apache.org/docs/latest/api/python/reference/pyspark.sql/api/pyspark.sql.DataFrame.html) + +
+ +
+ +
diff --git a/website/docs/docs/building-a-dbt-project/building-models/using-custom-aliases.md b/website/docs/docs/building-a-dbt-project/building-models/using-custom-aliases.md index a893a29c2ff..5675c64ae3a 100644 --- a/website/docs/docs/building-a-dbt-project/building-models/using-custom-aliases.md +++ b/website/docs/docs/building-a-dbt-project/building-models/using-custom-aliases.md @@ -8,10 +8,10 @@ id: "using-custom-aliases" When dbt runs a model, it will generally create a relation (either a `table` or a `view`) in the database. By default, dbt uses the filename of the model as the identifier for this relation in the database. This identifier can optionally be overridden using the `alias` model configuration. ### Why alias model names? -The names of schemas and tables are effectively the "user interface" of your data warehouse. Well-named schemas and tables can help provide clarity and direction for consumers of this data. In combination with [custom schemas](using-custom-schemas), model aliasing is a powerful mechanism for designing your warehouse. +The names of schemas and tables are effectively the "user interface" of your . Well-named schemas and tables can help provide clarity and direction for consumers of this data. In combination with [custom schemas](using-custom-schemas), model aliasing is a powerful mechanism for designing your warehouse. ### Usage -The `alias` config can be used to change the name of a model's identifier in the database. The following table shows examples of database identifiers for models both with, and without, a supplied `alias`. +The `alias` config can be used to change the name of a model's identifier in the database. The following shows examples of database identifiers for models both with, and without, a supplied `alias`. | Model | Config | Database Identifier | | ----- | ------ | ------------------- | @@ -84,7 +84,7 @@ The default implementation of `generate_alias_name` simply uses the supplied `al #### Ambiguous database identifiers -Using aliases, it's possible to accidentally create models with ambiguous identifiers. Given the following two models, dbt would attempt to create two views with _exactly_ the same names in the database (ie. `sessions`): +Using aliases, it's possible to accidentally create models with ambiguous identifiers. Given the following two models, dbt would attempt to create two views with _exactly_ the same names in the database (ie. `sessions`): ```sql -- models/snowplow_sessions.sql diff --git a/website/docs/docs/building-a-dbt-project/building-models/using-custom-schemas.md b/website/docs/docs/building-a-dbt-project/building-models/using-custom-schemas.md index 0757f746c9a..3a66d914db9 100644 --- a/website/docs/docs/building-a-dbt-project/building-models/using-custom-schemas.md +++ b/website/docs/docs/building-a-dbt-project/building-models/using-custom-schemas.md @@ -50,8 +50,9 @@ models:
-# Understanding custom schemas -## Why does dbt concatenate the custom schema to the target schema? +## Understanding custom schemas + +### Why does dbt concatenate the custom schema to the target schema? When first using custom schemas, it's common to assume that a model will be built in schema that matches the `schema` configuration exactly, for example, a model that has the configuration `schema: marketing`, would be built in the `marketing` schema. However, dbt instead creates it in a schema like `_marketing` by default – there's good reason for this! In a typical setup of dbt, each dbt user will use a separate target schema (see [Managing Environments](using-custom-schemas#managing-environments)). If dbt created models in a schema that matches a model's custom schema exactly, every dbt user would create models in the same schema. @@ -60,7 +61,7 @@ Further, the schema that your development models are built in would be the same If you prefer to use different logic for generating a schema name, you can change the way dbt generates a schema name (see below). -## How does dbt generate a model's schema name? +### How does dbt generate a model's schema name? Under the hood, dbt uses a macro called `generate_schema_name` to determine the name of the schema that a model should be built in. The code for the macro that expresses the current logic follows: ```sql @@ -80,15 +81,16 @@ Under the hood, dbt uses a macro called `generate_schema_name` to determine the {%- endmacro %} ``` -# Advanced custom schema configuration -## Changing the way dbt generates a schema name +## Advanced custom schema configuration + +### Changing the way dbt generates a schema name If your dbt project includes a macro that is also named `generate_schema_name`, dbt will _always use the macro in your dbt project_ instead of the default macro. Therefore, to change the way dbt generates a schema name, you should add a macro named `generate_schema_name` to your project, where you can then define your own logic. Note: dbt ignores any custom `generate_schema_name` macros that are part of a package installed in your project. -## An alternative pattern for generating schema names +### An alternative pattern for generating schema names A frequently used pattern for generating schema names is to change the behavior based on dbt's environment, such that: - In prod: @@ -116,14 +118,14 @@ If you want to use this pattern, you'll need a `generate_schema_name` macro in y **Note:** When using this macro, you'll need to set the target name in your job specifically to "prod" if you want custom schemas to be applied. -## generate_schema_name arguments +### generate_schema_name arguments | Argument | Description | Example | | -------- | ----------- | ------- | | custom_schema_name | The configured value of `schema` in the specified node, or `none` if a value is not supplied | `marketing` | | node | The `node` that is currently being processed by dbt | `{"name": "my_model", "resource_type": "model",...}` | -## Jinja context available in generate_schema_name +### Jinja context available in generate_schema_name If you choose to write custom logic to generate a schema name, it's worth noting that not all variables and methods are available to you when defining this logic. In other words: the `generate_schema_name` macro is compiled with a limited Jinja context. The following context methods _are_ available in the `generate_schema_name` macro: @@ -139,11 +141,11 @@ The following context methods _are_ available in the `generate_schema_name` macr | Other macros in your packages | Macro | ✅ | -### Which vars are available in generate_schema_name? +#### Which vars are available in generate_schema_name? -Variable semantics have changed in dbt v0.17.0. See the [migration guide](upgrading-to-0-17-0) +Variable semantics have changed in dbt v0.17.0. See the [migration guide](/guides/migration/versions) for more information on these changes. @@ -151,7 +153,7 @@ for more information on these changes. Globally-scoped variables and variables defined on the command line with [--vars](using-variables) are accessible in the `generate_schema_name` context. -# Managing environments +## Managing environments In the `generate_schema_name` macro examples shown above, the `target.name` context variable is used to change the schema name that dbt generates for models. If the `generate_schema_name` macro in your project uses the `target.name` context variable, you must additionally ensure that your different dbt environments are configured appropriately. While you can use any naming scheme you'd like, we typically recommend: - **dev**: Your local development environment; configured in a `profiles.yml` file on your computer. diff --git a/website/docs/docs/building-a-dbt-project/building-models/using-variables.md b/website/docs/docs/building-a-dbt-project/building-models/using-variables.md index 6cd324e69cd..72c8ba01298 100644 --- a/website/docs/docs/building-a-dbt-project/building-models/using-variables.md +++ b/website/docs/docs/building-a-dbt-project/building-models/using-variables.md @@ -3,14 +3,14 @@ title: "Using variables" id: "using-variables" --- -dbt provides a mechanism, [variables](dbt-jinja-functions/var), to provide data to models for +dbt provides a mechanism, [variables](reference/dbt-jinja-functions/var), to provide data to models for compilation. Variables can be used to [configure timezones](https://github.com/dbt-labs/snowplow/blob/0.3.9/dbt_project.yml#L22), [avoid hardcoding table names](https://github.com/dbt-labs/quickbooks/blob/v0.1.0/dbt_project.yml#L23) or otherwise provide data to models to configure how they are compiled. -To use a variable in a model, hook, or macro, use the `{{ var('...') }}` function. More information on the `var` function can be found [here](dbt-jinja-functions/var). +To use a variable in a model, hook, or macro, use the `{{ var('...') }}` function. More information on the `var` function can be found [here](/reference/dbt-jinja-functions/var). -Variables can defined in two ways: +Variables can be defined in two ways: 1. In the `dbt_project.yml` file 2. On the command line @@ -20,7 +20,7 @@ Variables can defined in two ways: :::info New in v0.17.0 The syntax for specifying vars in the `dbt_project.yml` file has changed in -dbt v0.17.0. See the [migration guide](migration-guide/upgrading-to-0-17-0) +dbt v0.17.0. See the [migration guide](/guides/migration/versions) for more information on these changes. ::: @@ -67,7 +67,7 @@ $ dbt run --vars '{"key": "value"}' ``` The `--vars` argument accepts a YAML dictionary as a string on the command line. -YAML is convenient because it does not require strict quoting as with JSON. +YAML is convenient because it does not require strict quoting as with . Both of the following are valid and equivalent: diff --git a/website/docs/docs/building-a-dbt-project/documentation.md b/website/docs/docs/building-a-dbt-project/documentation.md index bdb65031b9c..a3e99f5927f 100644 --- a/website/docs/docs/building-a-dbt-project/documentation.md +++ b/website/docs/docs/building-a-dbt-project/documentation.md @@ -4,9 +4,11 @@ id: "documentation" --- ## Related documentation + * [Declaring properties](configs-and-properties) * [`dbt docs` command](cmd-docs) -* [`doc` Jinja function](dbt-jinja-functions/doc) +* [`doc` Jinja function](/reference/dbt-jinja-functions) +* If you're new to dbt, we recommend that you check out our [Getting Started Tutorial](guides/getting-started/getting-set-up) to build your first dbt project, complete with documentation. ## Assumed knowledge * [Tests](building-a-dbt-project/tests) @@ -17,19 +19,14 @@ Good documentation for your dbt models will help downstream consumers discover a dbt provides a way to generate documentation for your dbt project and render it as a website. The documentation for your project includes: * **Information about your project**: including model code, a DAG of your project, any tests you've added to a column, and more. -* **Information about your data warehouse**: including column data types, and table sizes. This information is generated by running queries against the information schema. +* **Information about your **: including column data types, and sizes. This information is generated by running queries against the information schema. +Importantly, dbt also provides a way to add **descriptions** to models, columns, sources, and more, to further enhance your documentation. -Here's a screenshot of an example docs site (you can find the whole site [here](https://www.getdbt.com/mrr-playbook/#!/overview)): +Here's an example docs site: -Importantly, dbt also provides a way to add **descriptions** to models, columns, sources, and more, to further enhance your documentation. - -:::info Creating documentation for the first time -If you're new to dbt, we recommend that you check out our [Getting Started Tutorial](setting-up) to build your first dbt project, complete with documentation. -::: - ## Adding descriptions to your project To add descriptions to your project, use the `description:` key in the same files where you declare [tests](building-a-dbt-project/tests), like so: @@ -68,12 +65,12 @@ First, run `dbt docs generate` — this command tells dbt to compile relevant in Then, run `dbt docs serve` to use these `.json` files to populate a local website. ## FAQs - - - - - - + + + + + + ## Using Docs Blocks @@ -87,7 +84,7 @@ To declare a docs block, use the jinja `docs` tag. Docs blocks must be uniquely This table contains clickstream events from the marketing website. -The events in this table are recorded by \[Snowplow](http://github.com/snowplow/snowplow) and piped into the warehouse on an hourly basis. The following pages of the marketing site are tracked: +The events in this table are recorded by [Snowplow](http://github.com/snowplow/snowplow) and piped into the warehouse on an hourly basis. The following pages of the marketing site are tracked: - / - /about - /team @@ -185,7 +182,7 @@ From a docs page, you can click the green button in the bottom-right corner of t -In this example, the `fct_subscription_transactions` model only has one direct parent. By clicking the "Expand" button in the top-right corner of the window, we can pivot the graph horizontally and view the full lineage for our model. This lineage is filterable using the `--select` and `--exclude` flags, which are consistent with the semantics of [model selection syntax](node-selection/syntax). Further, you can right-click to interact with the DAG, jump to documentation, or share links to your graph visualization with your coworkers. +In this example, the `fct_subscription_transactions` model only has one direct parent. By clicking the "Expand" button in the top-right corner of the window, we can pivot the graph horizontally and view the full lineage for our model. This lineage is filterable using the `--select` and `--exclude` flags, which are consistent with the semantics of [model selection syntax](node-selection/syntax). Further, you can right-click to interact with the DAG, jump to documentation, or share links to your graph visualization with your coworkers. @@ -197,9 +194,9 @@ The `dbt docs serve` command is only intended for local/development hosting of t ::: -dbt's documentation website was built in a way that makes it easy to host on the web. The site itself is "static", meaning that you don't need any type of "dynamic" server to serve the docs. Some common methods for hosting the docs are: +dbt's documentation website was built to make it easy to host on the web. The site is "static,” meaning you don't need any "dynamic" servers to serve the docs. You can host your documentation in several ways: -1. [dbt Cloud](cloud-generating-documentation) -2. [Host on S3](https://docs.aws.amazon.com/AmazonS3/latest/dev/WebsiteHosting.html) (optionally [with IP access restrictions](https://docs.aws.amazon.com/AmazonS3/latest/dev/example-bucket-policies.html#example-bucket-policies-use-case-3)) -3. [Publish on Netlify](https://discourse.getdbt.com/t/publishing-dbt-docs-to-netlify/121) -4. Spin up a web server like Apache/Nginx +* Use [dbt Cloud](cloud-generating-documentation) +* Host on [Amazon S3](https://docs.aws.amazon.com/AmazonS3/latest/dev/WebsiteHosting.html) (optionally [with IP access restrictions](https://docs.aws.amazon.com/AmazonS3/latest/dev/example-bucket-policies.html#example-bucket-policies-use-case-3)) +* Publish with [Netlify](https://discourse.getdbt.com/t/publishing-dbt-docs-to-netlify/121) +* Use your own web server like Apache/Nginx diff --git a/website/docs/docs/building-a-dbt-project/exposures.md b/website/docs/docs/building-a-dbt-project/exposures.md index 44cba161b5b..a2ad5301ee9 100644 --- a/website/docs/docs/building-a-dbt-project/exposures.md +++ b/website/docs/docs/building-a-dbt-project/exposures.md @@ -51,7 +51,7 @@ exposures: ### Available properties _Required:_ -- **name** (must be unique among exposures) +- **name** (must be unique among exposures and you must use the [snake case](https://en.wikipedia.org/wiki/Snake_case) naming convention) - **type**: one of `dashboard`, `notebook`, `analysis`, `ml`, `application` (used to organize in docs site) - **owner**: email @@ -59,7 +59,7 @@ _Expected:_ - **depends_on**: list of refable nodes (`ref` + `source`) _Optional:_ -- **url** +- **url**: enables the link to **View this exposure** in the upper right corner of the generated documentation site - **maturity**: one of `high`, `medium`, `low` - **owner**: name @@ -82,7 +82,3 @@ When we generate our documentation site, you'll see the exposure appear: - -## Exposures are new! - -Exposures were introduced in dbt v0.18.1, with a limited set of supported types and properties. If you're interested in requesting or contributing additional properties, check out issue [dbt#2835](https://github.com/dbt-labs/dbt-core/issues/2835). diff --git a/website/docs/docs/building-a-dbt-project/hooks-operations.md b/website/docs/docs/building-a-dbt-project/hooks-operations.md index 94a979fd544..620ad9e8a7f 100644 --- a/website/docs/docs/building-a-dbt-project/hooks-operations.md +++ b/website/docs/docs/building-a-dbt-project/hooks-operations.md @@ -8,16 +8,16 @@ id: "hooks-operations" * [on-run-start & on-run-end](on-run-start-on-run-end) * [`run-operation` command](run-operation) -## Assumed knowledge +### Assumed knowledge * [Project configurations](reference/dbt_project.yml.md) * [Model configurations](model-configs) * [Macros](jinja-macros#macros) -## Getting started +## Getting started with hooks and operations Effective database administration sometimes requires additional SQL statements to be run, for example: -- Granting privileges on an table / view - Creating UDFs +- Managing row- or column-level permissions - Vacuuming tables on Redshift - Creating partitions in Redshift Spectrum external tables - Resuming/pausing/resizing warehouses in Snowflake @@ -25,18 +25,55 @@ Effective database administration sometimes requires additional SQL statements t - Create a share on Snowflake - Cloning a database on Snowflake -dbt provides two different interfaces for you to version control and execute these statements as part of your dbt project — hooks and operations. +dbt provides hooks and operations so you can version control and execute these statements as part of your dbt project. + +## About hooks -### Hooks Hooks are snippets of SQL that are executed at different times: * `pre-hook`: executed _before_ a model, seed or snapshot is built. * `post-hook`: executed _after_ a model, seed or snapshot is built. * `on-run-start`: executed at the _start_ of `dbt run`, `dbt seed` or `dbt snapshot` * `on-run-end`: executed at the _end_ of `dbt run`, `dbt seed` or `dbt snapshot` -Hooks are defined in your `dbt_project.yml` file. Pre- and post-hooks can also be defined in a `config` block. +Hooks are a more-advanced capability that enable you to run custom SQL, and leverage database-specific actions, beyond what dbt makes available out-of-the-box with standard materializations and configurations. + + + + + +If (and only if) you can't leverage the [`grants` resource-config](/reference/resource-configs/grants), you can use `post-hook` to perform more advanced workflows: + +* Need to apply `grants` in a more complex way, which the dbt Core v1.2 `grants` config does not (yet) support. +* Need to perform post-processing that dbt does not support out-of-the-box. For example, `analyze table`, `alter table set property`, `alter table ... add row access policy`, etc. + +### Examples using hooks + +You can use hooks to trigger actions at certain times when running an operation or building a model, seed, or snapshot. + +For more information about when hooks can be triggered, see reference sections for [`on-run-start` and `on-run-end` hooks](on-run-start-on-run-end) and [`pre-hook`s and `post-hook`s](pre-hook-post-hook). + +You can use hooks to provide database-specific functionality not available out-of-the-box with dbt. For example, you can use a `config` block to run an `ALTER TABLE` statement right after building an individual model using a `post-hook`: + + + +```sql +{{ config( + post_hook=[ + "alter table {{ this }} ..." + ] +) }} +``` + + + + + + + + +### Examples using hooks -Here's a minimal example of using hooks to grant privileges. You can find more information in the reference sections for [`on-run-start` and `on-run-end` hooks](on-run-start-on-run-end) and [`pre-hook`s and `post-hook`s](pre-hook-post-hook). +Here's a minimal example of using hooks to grant privileges. For more information, see [`on-run-start` & `on-run-end` hooks](on-run-start-on-run-end) and [`pre-hook` & `post-hook`](pre-hook-post-hook) reference sections. @@ -69,13 +106,96 @@ select ... -:::tip Calling a macro in a hook +You should use database-specific syntax when appropriate: -You can also use a [macro](jinja-macros#macros) to bundle up hook logic. Check out some of the examples in the reference sections for [on-run-start and on-run-end hooks](on-run-start-on-run-end) and [pre- and post-hooks](pre-hook-post-hook), + -::: +
+ + + +```sql +{{ config( + post_hook=[ + 'grant `roles/bigquery.dataViewer` on {{ this.type }} {{ this }} to "user:someone@yourcompany.com"' + ] +) }} + +select ... + +``` + + + +
+ +
+ + + +```sql +{{ config( + post_hook=[ + "grant select on {{ this }} to `someone@yourcompany.com`" + ] +) }} + +select ... + +``` + + + +
+ +
+ + + +```sql +{{ config( + post_hook=[ + "grant select on {{ this }} to reporter" + ] +) }} + +select ... + +``` + + + +
+ +
+ + + +```sql +{{ config( + post_hook=[ + "grant select on {{ this }} to role reporter" + ] +) }} + +select ... + +``` + + + +
+ +
+ +
+ +### Calling a macro in a hook + +You can also use a [macro](jinja-macros#macros) to bundle up hook logic. Check out some of the examples in the reference sections for [on-run-start and on-run-end hooks](on-run-start-on-run-end) and [pre- and post-hooks](pre-hook-post-hook). + +## About operations -### Operations Operations are [macros](jinja-macros#macros) that you can run using the [`run-operation` command](run-operation) command. As such, operations aren't actually a separate resource in your dbt project — they are just a convenient way to invoke a macro without needing to run a model. :::info Explicitly execute the SQL in an operation @@ -115,9 +235,10 @@ Full usage docs can for the `run-operation` command can be found [here](run-oper ## Additional examples + These examples from the community highlight some of the use-cases for hooks and operations! -* [In-depth discussion of granting privileges using hooks and operations](https://discourse.getdbt.com/t/the-exact-grant-statements-we-use-in-a-dbt-project/430) +* [In-depth discussion of granting privileges using hooks and operations, for dbt Core versions prior to 1.2](https://discourse.getdbt.com/t/the-exact-grant-statements-we-use-in-a-dbt-project/430) * [Staging external tables](https://github.com/dbt-labs/dbt-external-tables) * [Performing a zero copy clone on Snowflake to reset a dev environment](https://discourse.getdbt.com/t/creating-a-dev-environment-quickly-on-snowflake/1151/2) * [Running `vacuum` and `analyze` on a Redshift warehouse](https://github.com/dbt-labs/redshift/tree/0.2.3/#redshift_maintenance_operation-source) diff --git a/website/docs/docs/building-a-dbt-project/jinja-macros.md b/website/docs/docs/building-a-dbt-project/jinja-macros.md index 06683dc140f..701487bf62c 100644 --- a/website/docs/docs/building-a-dbt-project/jinja-macros.md +++ b/website/docs/docs/building-a-dbt-project/jinja-macros.md @@ -5,7 +5,7 @@ id: "jinja-macros" ## Related reference docs * [Jinja Template Designer Documentation](https://jinja.palletsprojects.com/page/templates/) (external link) -* [dbt Jinja context](dbt-jinja-functions) +* [dbt Jinja context](/reference/dbt-jinja-functions) * [Macro properties](macro-properties) ## Overview @@ -148,19 +148,19 @@ You can also qualify a macro in your own project by prefixing it with your [pack ## FAQs - - - - - - - + + + + + + + ## dbtonic Jinja Just like well-written python is pythonic, well-written dbt code is dbtonic. -### Favor readability over DRY-ness +### Favor readability over -ness Once you learn the power of Jinja, it's common to want to abstract every repeated line into a macro! Remember that using Jinja can make your models harder for other users to interpret — we recommend favoring readability when mixing Jinja with SQL, even if it means repeating some lines of SQL in a few places. If all your models are macros, it might be worth re-assessing. ### Leverage package macros @@ -172,7 +172,7 @@ Writing a macro for the first time? Check whether we've open sourced one in [dbt ```sql -- 🙅 This works, but can be hard to maintain as your code grows -{% for payment_methods in ["bank_transfer", "credit_card", "gift_card"] %} +{% for payment_method in ["bank_transfer", "credit_card", "gift_card"] %} ... {% endfor %} diff --git a/website/docs/docs/guides/managing-environments.md b/website/docs/docs/building-a-dbt-project/managing-environments.md similarity index 90% rename from website/docs/docs/guides/managing-environments.md rename to website/docs/docs/building-a-dbt-project/managing-environments.md index f2c429d3791..a62b584bd51 100644 --- a/website/docs/docs/guides/managing-environments.md +++ b/website/docs/docs/building-a-dbt-project/managing-environments.md @@ -10,7 +10,7 @@ In software engineering, environments are used to enable engineers to develop an In traditional software engineering, different environments often use completely separate architecture. For example, the dev and prod versions of a website may use different servers and databases. -Data warehouses can also be designed to have separate environments – the _production_ environment refers to the relations (i.e. schemas, tables, and views) that your end users query (often through a BI tool). +Data warehouses can also be designed to have separate environments – the _production_ environment refers to the relations (i.e. schemas, tables, and views) that your end users query (often through a BI tool). ## How do I maintain different environments with dbt? dbt makes it easy to maintain separate production and development environments through the use of targets within a profile. A typical profile when using dbt locally (i.e. running from your command line) will have a target named `dev`, and have this set as the default. This means that while making changes, your objects will be built in your _development_ target, without affecting production queries made by your end users. Once you are confident in your changes, you can deploy the code to _production_, by running your dbt project with a _prod_ target. diff --git a/website/docs/docs/building-a-dbt-project/metrics.md b/website/docs/docs/building-a-dbt-project/metrics.md index 9ff80519349..d8c63163437 100644 --- a/website/docs/docs/building-a-dbt-project/metrics.md +++ b/website/docs/docs/building-a-dbt-project/metrics.md @@ -1,32 +1,25 @@ --- title: "Metrics" id: "metrics" -description: "When you define metrics in dbt projects, you encode crucial business logic in tested, version-controlled code." +description: "When you define metrics in dbt projects, you encode crucial business logic in tested, version-controlled code. The dbt metrics layer helps you standardize metrics within your organization." +keywords: + - dbt metrics layer --- +* **v1.3.0**: Metrics have been moved out of the experimental phase * **v1.0.0**: Metrics are new and experimental +## About Metrics -:::info Metrics are new -v1.0.0 includes an initial version of metrics, following a [vibrant community discussion](https://github.com/dbt-labs/dbt-core/issues/4071). Try them out, and let us know what you think! -::: - -:::caution Metrics are experimental -v1.0 includes metrics, but they should be considered an _unstable_ API because they are experimental and subject to change. We reserve the right to make breaking changes to the metrics schema in future **minor** versions, but will aim for backwards compatibility when possible. -::: - -## About metrics - -A metric is a timeseries aggregation over a table that supports zero or more dimensions. Some examples of metrics include: +A metric is a timeseries aggregation over a that supports zero or more dimensions. Some examples of metrics include: - active users -- churn rate -- mrr (monthly recurring revenue) +- monthly recurring revenue (mrr) -In v1.0, dbt supports metric definitions as a new node type. Like [exposures](exposures), metrics participate in the dbt DAG and can be expressed in YAML files. By defining metrics in dbt projects, you encode crucial business logic in tested, version-controlled code. Further, you can expose these metrics definitions to downstream tooling, which drives consistency and precision in metric reporting. +In v1.0, dbt supports metric definitions as a new node type. Like [exposures](exposures), metrics appear as nodes in the directed acyclic graph (DAG) and can be expressed in YAML files. Defining metrics in dbt projects encodes crucial business logic in tested, version-controlled code. Further, you can expose these metrics definitions to downstream tooling, which drives consistency and precision in metric reporting. ### Benefits of defining metrics @@ -38,12 +31,21 @@ As with Exposures, you can see everything that rolls up into a metric (`dbt ls - -## Declaring a metric +## Defining a metric -You can define metrics in `.yml` files nested under a `metrics:` key. +You can define metrics in `.yml` files nested under a `metrics:` key. Metric names must: +- contain only letters, numbers, and underscores (no spaces or special characters) +- begin with a letter +- contain no more than 250 characters + +For a short human-friendly name with title casing, spaces, and special characters, use the `label` property. + +### Example definition + + ```yaml # models/marts/product/schema.yml @@ -54,53 +56,437 @@ models: ... metrics: - - name: new_customers + - name: rolling_new_customers label: New Customers model: ref('dim_customers') - description: "The number of paid customers using the product" + [description](description): "The 14 day rolling count of paying customers using the product" - type: count - sql: user_id # superflous here, but shown as an example + calculation_method: count_distinct + expression: user_id # superfluous here, but shown as an example timestamp: signup_date - time_grains: [day, week, month] + time_grains: [day, week, month, quarter, year] dimensions: - plan - country + window: + count: 14 + period: day + filters: - field: is_paying - value: true + operator: 'is' + value: 'true' + - field: lifetime_value + operator: '>=' + value: '100' + - field: company_name + operator: '!=' + value: "'Acme, Inc'" + - field: signup_date + operator: '>=' + value: "'2020-01-01'" + + # general properties + [config](resource-properties/config): + enabled: true | false + treat_null_values_as_zero: true | false + + [meta](resource-configs/meta): {team: Finance} +``` + + + + +```yaml +# models/marts/product/schema.yml + +version: 2 + +models: + - name: dim_customers + ... + +metrics: + - name: rolling_new_customers + label: New Customers + model: ref('dim_customers') + description: "The 14 day rolling count of paying customers using the product" + + type: count_distinct + sql: user_id # superfluous here, but shown as an example + + timestamp: signup_date + time_grains: [day, week, month, quarter, year] + + dimensions: + - plan + - country + + filters: + - field: is_paying + operator: 'is' + value: 'true' + - field: lifetime_value + operator: '>=' + value: '100' + - field: company_name + operator: '!=' + value: "'Acme, Inc'" + - field: signup_date + operator: '>=' + value: "'2020-01-01'" meta: {team: Finance} ``` + + + + +:::caution + +- You cannot define metrics on [ephemeral models](https://docs.getdbt.com/docs/building-a-dbt-project/building-models/materializations#ephemeral). To define a metric, the materialization must have a representation in the data warehouse. + +::: + + +### Available properties +Metrics can have many declared **properties**, which define aspects of your metric. More information on [properties and configs can be found here](https://docs.getdbt.com/reference/configs-and-properties). + + + +| Field | Description | Example | Required? | +|-------------|-------------------------------------------------------------|---------------------------------|-----------| +| name | A unique identifier for the metric | new_customers | yes | +| model | The dbt model that powers this metric | dim_customers | yes (no for `derived` metrics)| +| label | A short for name / label for the metric | New Customers | no | +| description | Long form, human-readable description for the metric | The number of customers who.... | no | +| calculation_method | The method of calculation (aggregation or derived) that is applied to the expression | count_distinct | yes | +| expression | The expression to aggregate/calculate over | user_id | yes | +| timestamp | The time-based component of the metric | signup_date | yes | +| time_grains | One or more "grains" at which the metric can be evaluated. For more information, see the "Custom Calendar" section. | [day, week, month, quarter, year] | yes | +| dimensions | A list of dimensions to group or filter the metric by | [plan, country] | no | +| window | A dictionary for aggregating over a window of time. Used for rolling metrics such as 14 day rolling average. Acceptable periods are: [`day`,`week`,`month`, `year`] | {count: 14, period: day} | no | +| filters | A list of filters to apply before calculating the metric | See below | no | +| config | [Optional configurations](https://github.com/dbt-labs/dbt_metrics#accepted-metric-configurations) for calculating this metric | {treat_null_values_as_zero: true} | no | +| meta | Arbitrary key/value store | {team: Finance} | no | + + + + + +| Field | Description | Example | Required? | +|-------------|-------------------------------------------------------------|---------------------------------|-----------| +| name | A unique identifier for the metric | new_customers | yes | +| model | The dbt model that powers this metric | dim_customers | yes (no for `derived` metrics)| +| label | A short for name / label for the metric | New Customers | no | +| description | Long form, human-readable description for the metric | The number of customers who.... | no | +| type | The method of calculation (aggregation or derived) that is applied to the expression | count_distinct | yes | +| sql | The expression to aggregate/calculate over | user_id | yes | +| timestamp | The time-based component of the metric | signup_date | yes | +| time_grains | One or more "grains" at which the metric can be evaluated | [day, week, month, quarter, year] | yes | +| dimensions | A list of dimensions to group or filter the metric by | [plan, country] | no | +| filters | A list of filters to apply before calculating the metric | See below | no | +| meta | Arbitrary key/value store | {team: Finance} | no | + + + + +### Available calculation methods + + +The method of calculation (aggregation or derived) that is applied to the expression. + + +The type of calculation (aggregation or expression) that is applied to the sql property. + + + +| Metric Calculation Method Metric Type | Description | +|----------------|----------------------------------------------------------------------------| +| count | This metric type will apply the `count` aggregation to the specified field | +| count_distinct | This metric type will apply the `count` aggregation to the specified field, with an additional distinct statement inside the aggregation | +| sum | This metric type will apply the `sum` aggregation to the specified field | +| average | This metric type will apply the `average` aggregation to the specified field | +| min | This metric type will apply the `min` aggregation to the specified field | +| max | This metric type will apply the `max` aggregation to the specified field | +|derived expression | This metric type is defined as any _non-aggregating_ calculation of 1 or more metrics | + + + +### Derived Metrics +In v1.2, support was added for `derived` metrics (previously named `expression`), which are defined as non-aggregating calculations of 1 or more metrics. An example of this would be `{{metric('total_revenue')}} / {{metric('count_of_customers')}}`. + + By defining these metrics, you are able to create metrics like: +- ratios +- subtractions +- any arbitrary calculation + +As long as the two (or more) base metrics (metrics that comprise the `derived` metric) share the specified `time_grains` and `dimensions`, those attributes can be used in any downstream metrics macro. + +An example definition of an `derived` metric is: + + + + +```yaml +# models/marts/product/schema.yml +version: 2 + +models: + - name: dim_customers + ... + +metrics: + - name: average_revenue_per_customer + label: Average Revenue Per Customer + description: "The average revenue received per customer" + + calculation_method: derived + expression: "{{metric('total_revenue')}} / {{metric('count_of_customers')}}" + + timestamp: order_date + time_grains: [day, week, month, quarter, year] + dimensions: + - had_discount + - order_country + +``` + + -
+ + +### Expression Metrics +In v1.2, support was added for `expression` metrics, which are defined as non-aggregating calculations of 1 or more metrics. By defining these metrics, you are able to create metrics like: +- ratios +- subtractions +- any arbitrary calculation + +As long as the two+ base metrics (the metrics that comprise the `expression` metric) share the specified `time_grains` and `dimensions`, those attributes can be used in any downstream metrics macro. + +An example definition of an `expression` metric is: + + + + +```yaml +# models/marts/product/schema.yml +version: 2 -### Metrics properties +models: + - name: dim_customers + ... + +metrics: + - name: average_revenue_per_customer + label: Average Revenue Per Customer + description: "The average revenue received per customer" + + type: expression + sql: "{{metric('total_revenue')}} / {{metric('count_of_customers')}}" + + timestamp: order_date + time_grains: [day, week, month, quarter, year] + dimensions: + - had_discount + - order_country + +``` + + +### Filters +Filters should be defined as a list of dictionaries that define predicates for the metric. Filters are combined using AND clauses. For more control, users can (and should) include the complex logic in the model powering the metric. + +All three properties (`field`, `operator`, `value`) are required for each defined filter. + +Note that `value` must be defined as a string in YAML, because it will be compiled into queries as part of a string. If your filter's value needs to be surrounded in quotes inside the query (e.g. text or dates), use `"'nested'"` quotes: + +```yml + filters: + - field: is_paying + operator: 'is' + value: 'true' + - field: lifetime_value + operator: '>=' + value: '100' + - field: company_name + operator: '!=' + value: "'Acme, Inc'" + - field: signup_date + operator: '>=' + value: "'2020-01-01'" +``` + +## Querying Your Metric +You can dynamically query metrics directly in dbt and verify them before running a job in the deployment environment. To query your defined metric, you must have the [dbt_metrics package](https://github.com/dbt-labs/dbt_metrics) installed. Information on how to [install packages can be found here](https://docs.getdbt.com/docs/building-a-dbt-project/package-management#how-do-i-add-a-package-to-my-project). + +Use the following [metrics package](https://hub.getdbt.com/dbt-labs/metrics/latest/) installation code in your packages.yml file and run `dbt deps` to install the metrics package: + + + +```yml +packages: + - package: dbt-labs/metrics + version: [">=1.3.0", "<1.4.0"] +``` + + + + + +```yml +packages: + - package: dbt-labs/metrics + version: [">=0.3.0", "<0.4.0"] +``` + + + + + +```yml +packages: + - package: dbt-labs/metrics + version: [">=0.2.0", "<0.3.0"] +``` + + + +Once the package has been installed with `dbt deps`, make sure to run the `dbt_metrics_calendar_model` model as this is required for macros used to query metrics. More information on this, and additional calendar functionality, can be found in the [project README](https://github.com/dbt-labs/dbt_metrics#calendar). + +### Querying metrics with `metrics.calculate` +Use the `metrics.calculate` macro along with defined metrics to generate a SQL statement that runs the metric aggregation to return the correct metric dataset. Example below: + + + +```sql +select * +from {{ metrics.calculate( + metric('new_customers'), + grain='week', + dimensions=['plan', 'country'] +) }} +``` + + + + + +```sql +select * +from {{ metrics.calculate( + metric_name='new_customers', + grain='week', + dimensions=['plan', 'country'] +) }} +``` + + + +### Supported inputs +The example above doesn't display all the potential inputs you can provide to the macro. + +You may find some pieces of functionality, like secondary calculations, complicated to use. We recommend reviewing the [package README](https://github.com/dbt-labs/dbt_metrics) for more in-depth information about each of the inputs that are not covered in the table below. + + +| Input | Example | Description | Required | +| ----------- | ----------- | ----------- | -----------| +| metric_listmetric_name | `metric('some_metric)'`, [`metric('some_metric)'`, `metric('some_other_metric)'`]`'metric_name'` | The metric(s) to be queried by the macro. If multiple metrics required, provide in list format.The name of the metric | Required | +| grain | `day`, `week`, `month`, `quarter`, `year` | The time grain that the metric will be aggregated to in the returned dataset | Required | +| dimensions | [`plan`, `country`] | The dimensions you want the metric to be aggregated by in the returned dataset | Optional | +| secondary_calculations | [`metrics.period_over_period(comparison_strategy="ratio", interval=1, alias="pop_1wk")`] | Performs the specified secondary calculation on the metric results. Examples include period over period calculations, rolling calcultions, and period to date calculations. | Optional | +| start_date | `2022-01-01` | Limits the date range of data used in the metric calculation by not querying data before this date | Optional | +| end_date | `2022-12-31` | Limits the date range of data used in the metric claculation by not querying data after this date | Optional | +| where | `plan='paying_customer'` | A sql statment, or series of sql statements, that alter the **final** CTE in the generated sql. Most often used to limit the data to specific values of dimensions provided | Optional | + +#### Secondary Calculations +Secondary calculations are window functions you can add to the metric calculation and perform on the primary metric or metrics. + +You can use them to compare values to an earlier period, calculate year-to-date sums, and return rolling averages. You can add custom secondary calculations into dbt projects - for more information on this, reference the [package README](https://github.com/dbt-labs/dbt_metrics#secondary-calculations). + +### Developing metrics with `metrics.develop` + + + +There may be times you want to test what a metric might look like before defining it in your project. In these cases, use the `develop` metric, which allows you to provide metric(s) in a contained yml so you can simulate what a defined metric might look like in your project. + +```sql +{% set my_metric_yml -%} +{% raw %} + +metrics: + -- The name of the metric does not need to be develop_metric + - name: develop_metric + model: ref('fact_orders') + label: Total Discount ($) + timestamp: order_date + time_grains: [day, week, month, quarter, year] + calculation_method: average + expression: discount_total + dimensions: + - had_discount + - order_country + +{% endraw %} +{%- endset %} + +select * +from {{ metrics.develop( + develop_yml=my_metric_yml, + metric_list=['develop_metric'] + grain='month' + ) + }} +``` + +**Important caveat** - The metric list input for the `metrics.develop` macro takes in the metric names themselves, not the `metric('name')` statement that the `calculate` macro uses. Using the example above: + +- ✅ `['develop_metric']` +- ❌ `[metric('develop_metric')]` + + + + + +There may be times you want to test what a metric might look like before defining it in your project. In these cases, the `develop` metric, which allows you to provide a single metric in a contained yml so you can simulate what a defined metric might look like in your project. + + +```sql +{% set my_metric_yml -%} +{% raw %} + +metrics: + - name: develop_metric + model: ref('fact_orders') + label: Total Discount ($) + timestamp: order_date + time_grains: [day, week, month, quarter, year] + type: average + sql: discount_total + dimensions: + - had_discount + - order_country + +{% endraw %} +{%- endset %} + +select * +from {{ metrics.develop( + develop_yml=my_metric_yml + grain='month' + ) + }} +``` -You can see how these properties are used in the [example YAML file](#declaring-a-metric). + -| Field | Description | Example | Required? | -|-------------|-----------------------------------------------------------|-----------------------------------|-----------| -| name | Unique identifier for the metric | new_customers | Yes | -| model | The dbt model that powers this metric | dim_customers | Yes | -| label | A short name / label for the metric | New Customers | No | -| description | Long form, human-readable description for the metric | "The number of paid customers..." | No | -| type | Type of calculation to perform when evaluating a metric | count_distinct | Yes | -| sql | Expression to aggregate or calculate over | user_id | Yes | -| timestamp | Time-based component of the metric | signup_date | Yes | -| time_grains | One or more "grains" at which the metric can be evaluated | [day, week, month] | Yes | -| dimensions | List of dimensions to group or filter the metric by | plan
country | No | -| filters | List of filters to apply before calculating the metric | field: is_paying
value: true | No | -| meta | Arbitrary key/value store | {team: Finance} | No | + -## Ongoing discussions +Functionality for `develop` is only supported in v1.2 and higher. Please navigate to those versions for information about this method of metric development. -- Should we define metrics be defined on top of more strongly typed **attributes**, rather than columns? [dbt-core#4090](https://github.com/dbt-labs/dbt-core/issues/4090) -- Should metrics include support for joins? How should dbt know about foreign-key relationships between models? [dbt-core#4125](https://github.com/dbt-labs/dbt-core/issues/4125) -- Should metrics inherit configurations from the models on which they are defined? Should it be possible to define metrics directly on models/columns, like tests? + -These are just a start! We welcome you to check out open issues on GitHub, and join the conversation. diff --git a/website/docs/docs/building-a-dbt-project/package-management.md b/website/docs/docs/building-a-dbt-project/package-management.md index 610f2c36902..7c8a7cfa99a 100644 --- a/website/docs/docs/building-a-dbt-project/package-management.md +++ b/website/docs/docs/building-a-dbt-project/package-management.md @@ -8,10 +8,10 @@ Software engineers frequently modularize code into libraries. These libraries he In dbt, libraries like these are called _packages_. dbt's packages are so powerful because so many of the analytic problems we encountered are shared across organizations, for example: * transforming data from a consistently structured SaaS dataset, for example: - * turning [Snowplow](https://hub.getdbt.com/dbt-labs/snowplow/latest/), [Segment](https://hub.getdbt.com/dbt-labs/segment/latest/) or [Heap](https://hub.getdbt.com/dbt-labs/heap/latest/) pageviews into sessions + * turning [Snowplow](https://hub.getdbt.com/dbt-labs/snowplow/latest/) or [Segment](https://hub.getdbt.com/dbt-labs/segment/latest/) pageviews into sessions * transforming [AdWords](https://hub.getdbt.com/dbt-labs/adwords/latest/) or [Facebook Ads](https://hub.getdbt.com/dbt-labs/facebook_ads/latest/) spend data into a consistent format. * writing dbt macros that perform similar functions, for example: - * [generating SQL](https://github.com/dbt-labs/dbt-utils#sql-helpers) to union together two relations, pivot columns, or construct a surrogate key + * [generating SQL](https://github.com/dbt-labs/dbt-utils#sql-helpers) to union together two relations, pivot columns, or construct a * creating [custom schema tests](https://github.com/dbt-labs/dbt-utils#schema-tests) * writing [audit queries](https://hub.getdbt.com/dbt-labs/audit_helper/latest/) * building models and macros for a particular tool used in your data stack, for example: @@ -100,13 +100,13 @@ Both of the following configurations would successfully install `0.4.5a2` of `db ```yaml packages: - - package: tailsdotcom/dbt_artifacts + - package: brooklyn-data/dbt_artifacts version: 0.4.5a2 ``` ```yaml packages: - - package: tailsdotcom/dbt_artifacts + - package: brooklyn-data/dbt_artifacts version: [">=0.4.4", "<0.4.6"] install-prerelease: true ``` @@ -145,8 +145,10 @@ As of v0.14.0, dbt will warn you if you install a package using the `git` syntax ### Private packages -#### SSH Key Method -Private packages can be cloned via SSH and an SSH key. When you use SSH keys to authenticate to your git remote server, you don’t need to supply your username and password each time. Read more about SSH keys, how to generate them, and how to add them to your git provider here: [Github](https://docs.github.com/en/github/authenticating-to-github/connecting-to-github-with-ssh) and [GitLab](https://docs.gitlab.com/ee/ssh/). +#### SSH Key Method (Command Line only) +If you're using the Command Line, private packages can be cloned via SSH and an SSH key. + +When you use SSH keys to authenticate to your git remote server, you don’t need to supply your username and password each time. Read more about SSH keys, how to generate them, and how to add them to your git provider here: [Github](https://docs.github.com/en/github/authenticating-to-github/connecting-to-github-with-ssh) and [GitLab](https://docs.gitlab.com/ee/ssh/). @@ -158,13 +160,16 @@ packages: +If you're using dbt Cloud, the SSH key method will not work, but you can use the [HTTPS Git Token Method](https://docs.getdbt.com/docs/building-a-dbt-project/package-management#git-token-method). + + #### Git Token Method This method allows the user to clone via HTTPS by passing in a git token via an environment variable. Be careful of the expiration date of any token you use, as an expired token could cause a scheduled run to fail. Additionally, user tokens can create a challenge if the user ever loses access to a specific repo. :::info dbt Cloud Usage If you are using dbt Cloud, you must adhere to the naming conventions for environment variables. Environment variables in dbt Cloud must be prefixed with either `DBT_` or `DBT_ENV_SECRET_`. Environment variables keys are uppercased and case sensitive. When referencing `{{env_var('DBT_KEY')}}` in your project's code, the key must match exactly the variable defined in dbt Cloud's UI. -::: +::: In GitHub: diff --git a/website/docs/docs/building-a-dbt-project/projects.md b/website/docs/docs/building-a-dbt-project/projects.md index 7b3ec98d950..349696a1fe6 100644 --- a/website/docs/docs/building-a-dbt-project/projects.md +++ b/website/docs/docs/building-a-dbt-project/projects.md @@ -18,7 +18,7 @@ A project may also contain a number of other resources, such as [snapshots](snap :::info Creating your first dbt project -If you're new to dbt, we recommend that you check out our [Getting Started Tutorial](tutorial/1-setting-up.md) to build your first dbt project. +If you're new to dbt, we recommend that you check out our [Getting Started guide](/guides/getting-started) to build your first dbt project. ::: @@ -38,20 +38,16 @@ To create a new dbt project when developing in dbt Cloud: 1. Create a dbt Cloud account [here](https://cloud.getdbt.com/signup/). If your organization already has a dbt Cloud account, ask an admin to add you as a Developer. 2. If you created a new account, a new project should automatically be created. If you were added to an existing account: - * Click the hamburger menu, then `Account Settings`, then `Projects`. - * Name your project, and click `Save`. There's no need to fill in the other details. - * Click the hamburger menu, and then `Home`. - * Switch the project in the header bar to your new "dbt Tutorial" project. + * Click the gear icon to the top right, then **Projects** under Account Settings. + * Name your project, and click **Continue**. There's no need to fill in the other details. 3. Complete the project setup flow: - * Connect to your data warehouse + * Connect to your * Add a repository — either choose a managed repository, or connect to an existing, but bare, repository. - + -4. Go to the `Develop` interface by either: - * Selecting `Start Developing`, or - * Selecting the hamburger menu, and then `Develop`. -5. Select `Initialize a project` to create your project. You should see a directory structure with `.sql` and `.yml` files that were generated by the `init` command. +4. Click **Develop** in the top left. +5. If this is the first time you are setting up this project, then select **Initialize a project** to create your project. You will see a directory structure with `.sql` and `.yml` files generated by running the `init` command. @@ -59,7 +55,7 @@ To create a new dbt project when developing in dbt Cloud: To create a new dbt project, run: ```bash -$ dbt init [project-name] +$ dbt init [project_name] ``` This will create a new directory in your current path (i.e. at `./[project-name]`. @@ -70,8 +66,8 @@ This will create a new directory in your current path (i.e. at `./[project-name] ### FAQs - - + + ## Using an existing project diff --git a/website/docs/docs/building-a-dbt-project/seeds.md b/website/docs/docs/building-a-dbt-project/seeds.md index d540562d74b..a0b935461f5 100644 --- a/website/docs/docs/building-a-dbt-project/seeds.md +++ b/website/docs/docs/building-a-dbt-project/seeds.md @@ -8,9 +8,9 @@ id: "seeds" * [`seed` command](seed) ## Getting started -Seeds are CSV files in your dbt project (typically in your `seeds` directory), that dbt can load into your data warehouse using the `dbt seed` command. +Seeds are CSV files in your dbt project (typically in your `seeds` directory), that dbt can load into your using the `dbt seed` command. -Seeds can be referenced in downstream models the same way as referencing models — by using the `ref` [function](dbt-jinja-functions/ref). +Seeds can be referenced in downstream models the same way as referencing models — by using the [`ref` function](/reference/dbt-jinja-functions/ref). Because these CSV files are located in your dbt repository, they are version controlled and code reviewable. Seeds are best suited to static data which changes infrequently. @@ -21,6 +21,8 @@ Good use-cases for seeds: Poor use-cases of dbt seeds: * Loading raw data that has been exported to CSVs +* Any kind of production data containing sensitive information. For example +personal identifiable information (PII) and passwords. ## Example @@ -39,7 +41,7 @@ GB,United Kingdom -2. Run the `dbt seed` [command](seed) command — a new table will be created in your warehouse in your target schema, named `country_codes` +2. Run the `dbt seed` [command](seed) command — a new will be created in your warehouse in your target schema, named `country_codes` ``` $ dbt seed @@ -59,7 +61,7 @@ Done. PASS=1 ERROR=0 SKIP=0 TOTAL=1 3. Refer to seeds in downstream models using the `ref` function. - + ```sql -- This refers to the table created from seeds/country_codes.csv @@ -76,12 +78,12 @@ Seeds are configured in your `dbt_project.yml`, check out the [seed configuratio You can document and test seeds in yaml by declaring properties — check out the docs on [seed properties](seed-properties) for more information. ## FAQs - - - - - - - - - + + + + + + + + + diff --git a/website/docs/docs/building-a-dbt-project/snapshots.md b/website/docs/docs/building-a-dbt-project/snapshots.md index 386048be8dd..1e3fe6bc7da 100644 --- a/website/docs/docs/building-a-dbt-project/snapshots.md +++ b/website/docs/docs/building-a-dbt-project/snapshots.md @@ -11,7 +11,7 @@ id: "snapshots" ## Getting started ### What are snapshots? -Commonly, analysts need to "look back in time" at some previous state of data in their mutable tables. While some source data systems are built in a way that makes accessing historical data possible, this is often not the case. dbt provides a mechanism, **snapshots**, which records changes to a mutable table over time. +Commonly, analysts need to "look back in time" at some previous state of data in their mutable tables. While some source data systems are built in a way that makes accessing historical data possible, this is often not the case. dbt provides a mechanism, **snapshots**, which records changes to a mutable over time. Snapshots implement [type-2 Slowly Changing Dimensions](https://en.wikipedia.org/wiki/Slowly_changing_dimension#Type_2:_add_new_row) over mutable source tables. These Slowly Changing Dimensions (or SCDs) identify how a row in a table changes over time. Imagine you have an `orders` table where the `status` field can be overwritten as the order is processed. @@ -57,6 +57,12 @@ select * from {{ source('jaffle_shop', 'orders') }} +:::info Preview or Compile Snapshots in IDE + +It is not possible to "preview data" or "compile sql" for snapshots in dbt Cloud. Instead, run the `dbt snapshot` command in the IDE by completing the following steps. + +::: + When you run the [`dbt snapshot` command](snapshot): * **On the first run:** dbt will create the initial snapshot table — this will be the result set of your `select` statement, with additional columns including `dbt_valid_from` and `dbt_valid_to`. All records will have a `dbt_valid_to = null`. * **On subsequent runs:** dbt will check which records have changed or if any new records have been created: @@ -66,6 +72,7 @@ When you run the [`dbt snapshot` command](snapshot): Snapshots can be referenced in downstream models the same way as referencing models — by using the [ref](ref) function. ## Example + To add a snapshot to your project: 1. Create a file in your `snapshots` directory with a `.sql` file extension, e.g. `snapshots/orders.sql` @@ -205,7 +212,7 @@ The `check` strategy requires the following configurations: :::caution check_cols = 'all' -The `check` snapshot strategy can be configured to track changes to _all_ columns by supplying `check_cols = 'all'`. It is better to explicitly enumerate the columns that you want to check. Consider using a [surrogate key](https://github.com/dbt-labs/dbt-utils#surrogate_key-source) to condense many columns into a single column. +The `check` snapshot strategy can be configured to track changes to _all_ columns by supplying `check_cols = 'all'`. It is better to explicitly enumerate the columns that you want to check. Consider using a to condense many columns into a single column. ::: @@ -278,7 +285,7 @@ There are a number of snapshot-specific configurations: | [target_database](target_database) | The database that dbt should render the snapshot table into | No | analytics | | [target_schema](target_schema) | The schema that dbt should render the snapshot table into | Yes | snapshots | | [strategy](strategy) | The snapshot strategy to use. One of `timestamp` or `check` | Yes | timestamp | -| [unique_key](unique_key) | A primary key column or expression for the record | Yes | id | +| [unique_key](unique_key) | A column or expression for the record | Yes | id | | [check_cols](check_cols) | If using the `check` strategy, then the columns to check | Only if using the `check` strategy | ["status"] | | [updated_at](updated_at) | If using the `timestamp` strategy, the timestamp column to compare | Only if using the `timestamp` strategy | updated_at | | [invalidate_hard_deletes](invalidate_hard_deletes) | Find hard deleted records in source, and set `dbt_valid_to` current time if no longer exists | No | True | @@ -306,7 +313,7 @@ Snapshots cannot be rebuilt. As such, it's a good idea to put snapshots in a sep Your models should then select from these snapshots, treating them like regular data sources. As much as possible, snapshot your source data in its raw form and use downstream models to clean up the data #### Use the `source` function in your query. -This helps when understanding data lineage in your project. +This helps when understanding data lineage in your project. #### Include as many columns as possible. In fact, go for `select *` if performance permits! Even if a column doesn't feel useful at the moment, it might be better to snapshot it in case it becomes useful – after all, you won't be able to recreate the column later. @@ -319,11 +326,11 @@ If you apply business logic in a snapshot query, and this logic changes in the f Basically – keep your query as simple as possible! Some reasonable exceptions to these recommendations include: * Selecting specific columns if the table is wide. -* Doing light transformation to get data into a reasonable shape, for example, unpacking a JSON blob to flatten your source data into columns. +* Doing light transformation to get data into a reasonable shape, for example, unpacking a blob to flatten your source data into columns. ## Snapshot meta-fields -Snapshot tables will be created as a clone of your source dataset, plus some additional meta-fields*. +Snapshot tables will be created as a clone of your source dataset, plus some additional meta-fields*. | Field | Meaning | Usage | | -------------- | ------- | ----- | @@ -337,9 +344,10 @@ Snapshot tables will be created as a clone of your source dataset, plus some add For the `timestamp` strategy, the configured `updated_at` column is used to populate the `dbt_valid_from`, `dbt_valid_to` and `dbt_updated_at` columns.
+ Details for the timestamp strategy -Snapshot query results at `2019-01-01 11:00`: - +Snapshot query results at `2019-01-01 11:00` + | id | status | updated_at | | -- | ------- | ---------------- | | 1 | pending | 2019-01-01 10:47 | @@ -370,8 +378,9 @@ Snapshot results (note that `11:30` is not used anywhere): For the `check` strategy, the current timestamp is used to populate each column
+ Details for the check strategy -Snapshot query results at `2019-01-01 11:00`: +Snapshot query results at `2019-01-01 11:00` | id | status | | -- | ------- | @@ -400,9 +409,9 @@ Snapshot results: ## FAQs - - - - - - + + + + + + diff --git a/website/docs/docs/building-a-dbt-project/tests.md b/website/docs/docs/building-a-dbt-project/tests.md index d66e349831a..04fa4f43506 100644 --- a/website/docs/docs/building-a-dbt-project/tests.md +++ b/website/docs/docs/building-a-dbt-project/tests.md @@ -27,7 +27,7 @@ There are two ways of defining tests in dbt: Defining tests is a great way to confirm that your code is working correctly, and helps prevent regressions when your code changes. Because you can use them over and over again, making similar assertions with minor variations, generic tests tend to be much more common—they should make up the bulk of your dbt testing suite. That said, both ways of defining tests have their time and place. :::tip Creating your first tests -If you're new to dbt, we recommend that you check out our [Getting Started Tutorial](tutorial/1-setting-up.md) to build your first dbt project with models and tests. +If you're new to dbt, we recommend that you check out our [Getting Started guide](/guides/getting-started) to build your first dbt project with models and tests. ::: ## Singular tests @@ -101,7 +101,7 @@ In plain English, these tests translate to: * `unique`: the `order_id` column in the `orders` model should be unique * `not_null`: the `order_id` column in the `orders` model should not contain null values * `accepted_values`: the `status` column in the `orders` should be one of `'placed'`, `'shipped'`, `'completed'`, or `'returned'` -* `relationships`: each `customer_id` in the `orders` model exists as an `id` in the `customers` table (also known as referential integrity) +* `relationships`: each `customer_id` in the `orders` model exists as an `id` in the `customers` (also known as referential integrity) Behind the scenes, dbt constructs a `select` query for each test, using the parametrized query from the generic test block. These queries return the rows where your assertion is _not_ true; if the test returns zero rows, your assertion passes. @@ -236,7 +236,6 @@ where {{ column_name }} is null - ## Storing test failures @@ -257,15 +256,14 @@ Note that, if you elect to store test failures: ## FAQs - - - - - - - - - + + + + + + + + + +For more on version support and future releases, see [Understanding dbt Core versions](core-versions). + +#### What will actually happen on the end of support date? + +1 year post a minor version release of v1.X, we will try to run our users' projects on the latest release of dbt if they have not already upgraded their projects themselves. In a post dbt v1.0 world, there won't be breaking changes between minor versions of dbt, so we might be reasonably successful at upgrading our users' versions for them. However, our strong preference is for accounts to try to manage the upgrade process themselves which is a more cautious way to prevent failures to their production pipelines. We will give accounts consistent communication that they're hitting the end of their supported window, so they can plan accordingly. #### What should you be doing today? -Your migration to v1.0.0 will progress much smoother if you **begin transitioning to more recent versions of dbt as soon as possible.** -Why? Because attempting to upgrade 6 minor versions at one time (v0.15.0 —> v.0.21.0) implies 6x the potential for breaking changes vs. upgrading a single minor version. +You should **upgrade to v1.0 as soon as you can** - and we recommend that you proceed **slowly and steadily**. + +Why? Because attempting to upgrade 6 minor versions at one time (v0.15.0 —> v0.21.0) implies 6x the potential for breaking changes, versus upgrading a single minor version. Refactoring code is much easier when you're updating a well-defined, constrained surface area. Doing things incrementally is the way to go. @@ -53,7 +66,7 @@ Additionally upgrading to more recent versions of dbt Core will enable better pe | dbt Cloud Feature | dbt Core Version Needed | | ------------- | -------------- | -| [Environment variable secret scrubbing](/docs/dbt-cloud/using-dbt-cloud/cloud-environment-variables#handling-secrets)| v0.21.0+ | +| [Environment variable secret scrubbing](/docs/dbt-cloud/using-dbt-cloud/cloud-environment-variables#handling-secrets)| v1.0+ | | DAG in the IDE | v0.20.0+| | [Metadata API](/docs/dbt-cloud/dbt-cloud-api/metadata/metadata-overview.md) |v0.19.0+| | [Dashboard status tiles](/docs/dbt-cloud/using-dbt-cloud/cloud-dashboard-status-tiles) | v0.19.0+ | @@ -61,4 +74,4 @@ Additionally upgrading to more recent versions of dbt Core will enable better pe #### Need help upgrading? -If you want more advice on how to upgrade your dbt projects, check out our [migration guides](docs/guides/migration-guide/upgrading-to-0-21-0) and our [upgrading Q&A page](docs/dbt-cloud/cloud-configuring-dbt-cloud/cloud-upgrading-dbt-versions). +If you want more advice on how to upgrade your dbt projects, check out our [migration guides](/guides/migration/versions/) and our [upgrading Q&A page](docs/dbt-cloud/cloud-configuring-dbt-cloud/cloud-upgrading-dbt-versions). diff --git a/website/docs/docs/dbt-cloud/cloud-configuring-dbt-cloud/cloud-configuring-repositories.md b/website/docs/docs/dbt-cloud/cloud-configuring-dbt-cloud/cloud-configuring-repositories.md index 4640ae301e9..604528be825 100644 --- a/website/docs/docs/dbt-cloud/cloud-configuring-dbt-cloud/cloud-configuring-repositories.md +++ b/website/docs/docs/dbt-cloud/cloud-configuring-dbt-cloud/cloud-configuring-repositories.md @@ -3,7 +3,7 @@ title: "Configuring repositories" id: "cloud-configuring-repositories" --- -### Configuring PR template URLs +## Configure pull request (PR) template URLs When changes are committed on a branch in the IDE, dbt Cloud can prompt users to open a new Pull Request for the code changes. To enable this functionality, ensure @@ -44,6 +44,14 @@ https://github.com/dbt-labs/jaffle_shop/compare/master..my-branch +## Configure custom branches + +By default in Development Environments, dbt Cloud attempts to reference the `main` branch in connected repositories. If you want to use a different default branch name, you can configure dbt Cloud with a custom branch setting. + +For example, you can use the `develop` branch of a connected repository. Edit an environment, then in "General settings" select **Only run on a custom branch** , and in "Custom branch" type **develop** or the name of your custom branch. + + + ## Example templates Some common URL templates are provided below, but please note that the exact @@ -77,5 +85,5 @@ https://console.aws.amazon.com/codesuite/codecommit/repositories//pull-req ### Azure DevOps ``` -https://dev.azure.com///_git/dbt/pullrequestcreate?sourceRef={{source}}&targetRef={{destination}} +https://dev.azure.com///_git//pullrequestcreate?sourceRef={{source}}&targetRef={{destination}} ``` diff --git a/website/docs/docs/dbt-cloud/cloud-configuring-dbt-cloud/cloud-import-a-project-by-git-url.md b/website/docs/docs/dbt-cloud/cloud-configuring-dbt-cloud/cloud-import-a-project-by-git-url.md index 38d3510d536..3f5c387217e 100644 --- a/website/docs/docs/dbt-cloud/cloud-configuring-dbt-cloud/cloud-import-a-project-by-git-url.md +++ b/website/docs/docs/dbt-cloud/cloud-configuring-dbt-cloud/cloud-import-a-project-by-git-url.md @@ -63,6 +63,8 @@ Open the AWS CodeCommit console and choose your repository. Copy the SSH URL fro In the newly created Repository details page, you'll see a "Deploy Key" field. Copy the contents of this field as you'll need it for step 3. +**Note:** The dbt Cloud-generated public key is the only key that will work in the next step. Any other key that has been generated outside of dbt Cloud will not work. + #### Step 3: Grant dbt Cloud AWS User access Open up the newly created dbt Cloud user in the AWS IAM Console. Choose the "Security Credentials" tab and then click "Upload SSH public key". Paste in the contents of the "Public Key" field from the dbt Cloud Repository page. @@ -72,6 +74,11 @@ Once you've created the key, you'll see an "SSH key ID" for it. You'll need to w You're all set! Once support handles your request, your project is set up and you can begin executing dbt runs from dbt Cloud. ### Azure DevOps +:::info Use Azure DevOps? + +If you use Azure DevOps and you are on the dbt Cloud Enterprise plan, you can import your repo directly using [dbt Cloud's Azure DevOps Integration](connecting-azure-devops). Connecting your repo via the Azure DevOps Application [enables Continuous Integration](cloud-enabling-continuous-integration-with-github). + +::: To add a deploy key to an Azure DevOps account, navigate to the "SSH public keys" page in the User Settings of your user's Azure DevOps account or a service user's account. We recommend using a dedicated service user for the integration to ensure that dbt Cloud's connection to Azure DevOps is not interrupted by changes to user permissions. diff --git a/website/docs/docs/dbt-cloud/cloud-configuring-dbt-cloud/cloud-installing-the-github-application.md b/website/docs/docs/dbt-cloud/cloud-configuring-dbt-cloud/cloud-installing-the-github-application.md index 10667856b9b..59e3d813a5d 100644 --- a/website/docs/docs/dbt-cloud/cloud-configuring-dbt-cloud/cloud-installing-the-github-application.md +++ b/website/docs/docs/dbt-cloud/cloud-configuring-dbt-cloud/cloud-installing-the-github-application.md @@ -1,43 +1,57 @@ --- -title: "Connecting your GitHub Account" +title: "Connecting your GitHub account" id: "cloud-installing-the-github-application" sidebar_label: "Connecting GitHub" --- ## Overview -Connecting your GitHub account to dbt Cloud unlocks exciting and compelling functionality in dbt Cloud. Once your GitHub account is connected, you can: -- [Trigger CI builds](cloud-enabling-continuous-integration-with-github) when Pull Requests are opened in GitHub -- Log into dbt Cloud via OAuth through GitHub -- Add new repos to Cloud in a single click (no need to fuss with Deploy Keys) +Connecting your GitHub account to dbt Cloud provides convenience and another layer of security to dbt Cloud: +- Log into dbt Cloud using OAuth through GitHub. +- Import new GitHub repositories with a couple clicks during dbt Cloud project setup. +- Clone repos using HTTPS rather than SSH. +- Trigger [Continuous integration](cloud-enabling-continuous-integration-with-github) builds when pull requests are opened in GitHub. +To connect GitHub in dbt Cloud: +1. A GitHub organization owner must first [install the dbt Cloud application](/cloud-installing-the-github-application#installing-dbt-cloud-in-your-github-account) in your team's GitHub account. +2. All other dbt Cloud developers on the account need to [personally authenticate with GitHub](/cloud-installing-the-github-application#personally-authenticate-with-github) from dbt Cloud. + +If you are the GitHub organization owner tasked with the installation of the dbt Cloud app in step 1, you will also be automatically personally authenticated after completion, so step 2 will be taken care of. This means teams of one only need to complete step 1. :::info Use GitHub On-Premise? -This method will not work for On-Premise GitHub deployments. Please reference our -[Importing a project by git url](docs/dbt-cloud/cloud-configuring-dbt-cloud/cloud-import-a-project-by-git-url#github) to setup your connection. This alternative method does not include the benefits mentioned above. +If you're using an On-Premise GitHub deployment, this method will not work for your account. Please instead reference our +docs on [importing a project by git URL](docs/dbt-cloud/cloud-configuring-dbt-cloud/cloud-import-a-project-by-git-url#github) to set up your connection. This alternative connection method does not include the benefits of the native integration mentioned above. ::: -## Linking dbt Cloud to your GitHub account +## Installing dbt Cloud in your GitHub account + +A GitHub organization owner needs to connect and configure the dbt Cloud app for their GitHub organization. If you are a team of one or wish to connect your personal GitHub account, then these instructions also apply to you. -To link your dbt Cloud account to your GitHub account, navigate to your [user profile](https://cloud.getdbt.com/#/profile/) and click the [Integrations section](https://cloud.getdbt.com/#/profile/integrations/). Here you can link your GitHub account to dbt Cloud. +To link your dbt Cloud account to your team's GitHub account, navigate to Your Profile settings by clicking the gear icon in the top right. Select **Linked Accounts** in the left menu. - + -On the next page, you can select a GitHub organization to install the dbt Cloud application into. +In the Linked Accounts section, you can set up your GitHub account connection to dbt Cloud by clicking **Link** to the right of GitHub. This redirects you to your account on GitHub where you will be asked to install and configure the dbt Cloud application. Select the GitHub organization and repositories dbt Cloud should access. - + The dbt Cloud GitHub App requires the following permissions: - Read access to metadata -- Read and write access to checks, code, commit statuses, pull requests, and workflows (new!) +- Read and write access to checks, code, commit statuses, pull requests, and workflows + +Once you grant access to the app, you will be redirected back to dbt Cloud and shown a linked account success state. You are now personally authenticated too, and your team members can begin [connecting their profiles](/cloud-installing-the-github-application#personally-authenticate-with-github). -## Usage notes +## Configuring the dbt Cloud app in your GitHub account +If you are your GitHub organization owner, you can also configure the dbt Cloud GitHub application to have access to only select repositories. This configuration must be done in GitHub, but we provide an easy link in dbt Cloud to start this process. + -A GitHub organization owner needs to connect and configure the dbt Cloud app for their organization. Users on the Developer or Team plans do not need to each connect to GitHub, but it is recommended to do so. Users on the Enterprise plan must each connect their GitHub accounts, as dbt Cloud will enforce the repository's access permissions for every user in the IDE. +## Personally authenticate with GitHub +dbt Cloud developers on the Enterprise plan must each connect their GitHub profiles to dbt Cloud, as every developer's read / write access for the dbt repo is checked in the dbt Cloud IDE. dbt Cloud developers on the Team plan do not need to each connect their profiles to GitHub, but it is still recommended to do so. -## Connect your personal GitHub account +To connect a personal GitHub account, dbt Cloud developers should navigate to Your Profile settings by clicking the gear icon in the top right, then select **Linked Accounts** in the left menu. -To connect your personal GitHub account, navigate to your [User Profile](https://cloud.getdbt.com/#/profile/) select the [Integrations section](https://cloud.getdbt.com/#/profile/integrations/) from the left sidebar. Under “GitHub”, if your account is already connected, you’ll see "Your user account is linked to a GitHub account with username <your-github-username>." +If your GitHub account is not connected, you’ll see "No connected account". Select **Link** to begin the setup process. You’ll be redirected to GitHub, and asked to authorize dbt Cloud in a grant screen. + -If your account is not connected, you’ll see "This account is not linked to a GitHub account.” Click the button to begin the setup process. You’ll be redirected to GitHub, and then back into dbt Cloud. When you are redirected to dbt Cloud, you should now see your connected account. The next time you log into dbt Cloud, you will be able to do so via OAuth through GitHub. +Once you approve authorization, you will be redirected to dbt Cloud, and you should now see your connected account. The next time you log into dbt Cloud, you will be able to do so via OAuth through GitHub, and if you're on the Enterprise plan, you're ready to use the dbt Cloud IDE. diff --git a/website/docs/docs/dbt-cloud/cloud-configuring-dbt-cloud/cloud-setting-up-bigquery-oauth.md b/website/docs/docs/dbt-cloud/cloud-configuring-dbt-cloud/cloud-setting-up-bigquery-oauth.md index 48349020dab..21f385837f5 100644 --- a/website/docs/docs/dbt-cloud/cloud-configuring-dbt-cloud/cloud-setting-up-bigquery-oauth.md +++ b/website/docs/docs/dbt-cloud/cloud-configuring-dbt-cloud/cloud-setting-up-bigquery-oauth.md @@ -7,51 +7,68 @@ title: "Setting up BigQuery OAuth" This guide describes a feature of the dbt Cloud Enterprise plan. If you’re interested in learning more about an Enterprise plan, contact us at sales@getdbt.com. ::: +### Overview -dbt Cloud supports [OAuth authentication](https://cloud.google.com/bigquery/docs/authentication) with BigQuery. When BigQuery OAuth is enabled, users can interact with the BigQuery warehouse as individual users, rather than leveraging a shared service level authentication. -:::info Some Pre-Work Required +dbt Cloud supports developer [OAuth](https://cloud.google.com/bigquery/docs/authentication) with BigQuery, providing an additional layer of security for dbt enterprise users. When BigQuery OAuth is enabled for a dbt Cloud project, all dbt Cloud developers must authenticate with BigQuery in order to use the dbt Cloud IDE. The project's deployment environments will still leverage the BigQuery service account key set in the project credentials. -Before setting up a Client ID & Secret, you'll have to have your existing BigQuery Settings in order. We recommend using a Service Account JSON file, and have a walkthrough for that [here](setting-up#generate-bigquery-credentials) - you will also need to set up an [OAuth Consent Screen](https://support.google.com/cloud/answer/6158849) if you haven't already! -::: +To set up BigQuery OAuth in dbt Cloud, a BigQuery admin must: +1. [Create a BigQuery OAuth 2.0 client ID and secret](/cloud-setting-up-bigquery-oauth#creating-a-bigquery-oauth-20-client-id-and-secret) in BigQuery. +2. [Configure the connection](/cloud-setting-up-bigquery-oauth#configure-the-connection-in-dbt-cloud) in dbt Cloud. + +To use BigQuery in the dbt Cloud IDE, all developers must: +1. [Authenticate to BigQuery](/cloud-setting-up-bigquery-oauth#authenticating-to-bigquery) in the their profile credentials. + -### Configuring a Client ID & Secret -To enable BigQuery OAuth, you will need a Client ID & Secret for [authentication](https://cloud.google.com/bigquery/docs/authentication) with BigQuery to manage the OAuth connection between dbt Cloud and BigQuery. +### Creating a BigQuery OAuth 2.0 client ID and secret +To get started, you need to create a client ID and secret for [authentication](https://cloud.google.com/bigquery/docs/authentication) with BigQuery. This client ID and secret will be stored in dbt Cloud to manage the OAuth connection between dbt Cloud users and BigQuery. -In the BigQuery console you'll want to navigate to the Credentials page: +In the BigQuery console, navigate to **APIs & Services** and select **Credentials**: - + -There you'll see your existing Keys, Client IDs and Service Accounts - you'll want to click the "Create Credentials" button at the top and follow the steps, like this: +On the **Credentials** page, you can see your existing keys, client IDs, and service accounts. - +Set up an [OAuth consent screen](https://support.google.com/cloud/answer/6158849) if you haven't already. Then, click **+ Create Credentials** at the top of the page and select **OAuth client ID**. -For the fields we recommend the following: +Fill in the application details as follows: | Config | Value | | ------ | ----- | | **Application type** | Web application | | **Name** | dbt Cloud | -| **Authorized Javascript origins** | `https://cloud.getdbt.com` | -| **Authorized Redirect URIs** | `https://cloud.getdbt.com/complete/bigquery` | +| **Authorized Javascript origins** | https://cloud.getdbt.com | +| **Authorized Redirect URIs** | https://cloud.getdbt.com/complete/bigquery | +If you're a dbt Cloud single tenant customer, you need to replace `cloud.getdbt.com` with the hostname of +your dbt Cloud instance. -:::info Deployment Nuance +Then click **Create** to create the BigQuery OAuth app and see the app client ID and secret values. These values are available even if you close the app screen, so this isn't the only chance you have to save them. -If you're using a deployment other than the standard dbt Cloud multi-tenant, you'll need to replace `cloud.getdbt.com` with the hostname of -your cloud instance here! + -::: -Then, click the blue Create button, which will display your Client ID and Client Secret, with handy clipboard buttons for copying into other screens, which is exactly what we're about to do. These values will continue to be available in your Credentials screen in perpetuity, *this is not the only chance you have to access them*. +### Configure the Connection in dbt Cloud +Now that you have an OAuth app set up in BigQuery, you'll need to add the client ID and secret to dbt Cloud. To do so: + - go to [Settings](https://cloud.getdbt.com/next/settings/profile) + - on the left, select **Projects** under **Account Settings** + - choose your project from the list + - select **Connection** to edit the connection details + - add the client ID and secret from the BigQuery OAuth app under the **OAuth2.0 Settings** section -### Configure the Connection in dbt Cloud + -Back in dbt Cloud, you'll want to navigate to your Connection page for BigQuery. There you'll be able to click the Edit button in the top corner to enable writing into the OAuth 2.0 Settings boxes near the bottom. +### Authenticating to BigQuery +Once the BigQuery OAuth app is set up for a dbt Cloud project, each dbt Cloud user will need to authenticate with BigQuery in order to use the IDE. To do so: +- go to the [Credentials](https://cloud.getdbt.com/next/settings/profile#credentials) section +- choose your project from the list +- select **Authenticate BigQuery Account** + - +You will then be redirected to BigQuery and asked to approve the drive, cloud platform, and BigQuery scopes, unless the connection is less privileged. + -With Editing enabled, you can copy paste the Client ID and the Client Secret you created in BigQuery into their respective boxes, and return to the top of the page, to Save your new OAuth Credentials. +Select **Allow**. This redirects you back to dbt Cloud. You should now be an authenticated BigQuery user, ready to use the dbt Cloud IDE. \ No newline at end of file diff --git a/website/docs/docs/dbt-cloud/cloud-configuring-dbt-cloud/cloud-upgrading-dbt-versions.md b/website/docs/docs/dbt-cloud/cloud-configuring-dbt-cloud/cloud-upgrading-dbt-versions.md index aa38f3f4773..ba8b3a60bf2 100644 --- a/website/docs/docs/dbt-cloud/cloud-configuring-dbt-cloud/cloud-upgrading-dbt-versions.md +++ b/website/docs/docs/dbt-cloud/cloud-configuring-dbt-cloud/cloud-upgrading-dbt-versions.md @@ -3,9 +3,9 @@ title: "Upgrading dbt versions in Cloud" id: "cloud-upgrading-dbt-versions" --- -This Q&A guide should help you figure out what changes you might need to make to successfully upgrade your version of dbt Core in dbt Cloud. As a reminder, we recommend everyone upgrade to the most recent version of dbt, as we will not support running all versions of dbt in Cloud indefinitely. We document which versions of dbt Core we support [here](docs/dbt-cloud/cloud-configuring-dbt-cloud/cloud-choosing-a-dbt-version#supported-versions). +This Q&A guide should help you figure out what changes you might need to make to successfully upgrade your version of dbt Core in dbt Cloud. As a reminder, we recommend everyone upgrade to the most recent version of dbt, as we will not support all versions of dbt in Cloud indefinitely. We document which versions of dbt Core we support [here](docs/dbt-cloud/cloud-configuring-dbt-cloud/cloud-choosing-a-dbt-version#supported-versions). -There aren't many breaking changes between versions, and it may be the case that you don't need to change any code to upgrade to a newer version of dbt in dbt Cloud. You may only need to change the settings in your environment or job to call a more recent version of dbt - directions to do so can be found [here](/docs/dbt-cloud/cloud-configuring-dbt-cloud/cloud-choosing-a-dbt-version.md). +There aren't many breaking changes between minor versions, and it may be the case that you don't need to change any code to upgrade to a newer version of dbt in dbt Cloud. There are only breaking changes between minor versions of dbt before dbt 1.0. Minor releases starting with dbt 1.0, do not have breaking code changes. If there are no code changes needed, all you have to do is [change the settings](/docs/dbt-cloud/cloud-configuring-dbt-cloud/cloud-choosing-a-dbt-version.md) in your environment or job to run a more recent version of dbt. ### How to run the latest version of dbt in Cloud @@ -37,7 +37,7 @@ Existing projects will see non-breaking deprecation warnings. You can change thr ```yml -model-paths: ["models"] # formerly named "model-paths" +model-paths: ["models"] # formerly named "source-paths" seed-paths: ["data"] # formerly named "data-paths" clean-targets: - "target" @@ -48,10 +48,10 @@ clean-targets: - Do you select tests using the old names for test types? (`test_type:schema`, `test_type:data`, `--schema`, `--data`) - Do you have custom macro code that calls the (undocumented) global macros `column_list`, `column_list_for_create_table`, `incremental_upsert`? -- Do you have custom scripts that parse dbt JSON artifacts? +- Do you have custom scripts that parse dbt artifacts? - (BigQuery only) Do you use dbt's legacy capabilities around ingestion-time-partitioned tables? -If you believe your project might be affected, read more details in the migration guide [here](/docs/guides/migration-guide/upgrading-to-1-0-0). +If you believe your project might be affected, read more details in the migration guide [here](/guides/migration/versions/upgrading-to-v1.0).
@@ -62,9 +62,9 @@ If you believe your project might be affected, read more details in the migratio - Do you select specific sources to check freshness (`dbt snapshot-freshness --select `)? - Do you have custom scripts that parse dbt JSON artifacts? -- (Snowflake only) Do you have custom macros or materializations that depend on using transactions, such as statement blocks with `auto_begin=True`? +- (Snowflake only) Do you have custom macros or materializations that depend on using transactions, such as statement blocks with `auto_begin=True`? -If you believe your project might be affected, read more details in the migration guide [here](/docs/guides/migration-guide/upgrading-to-0-21-0). +If you believe your project might be affected, read more details in the migration guide [here](/guides/migration/versions).
@@ -78,7 +78,7 @@ If you believe your project might be affected, read more details in the migratio - Does your project use `adapter.dispatch` or the `spark_utils` package? - Do you have custom scripts that parse dbt JSON artifacts? -If you believe your project might be affected, read more details in the migration guide [here](/docs/guides/migration-guide/upgrading-to-0-20-0). +If you believe your project might be affected, read more details in the migration guide [here](/guides/migration/versions). @@ -101,7 +101,7 @@ See **Upgrading to v0.17.latest from v0.16** below for more details. - Do you have custom scripts that parse dbt JSON artifacts? - Do you have any custom materializations? -If you believe your project might be affected, read more details in the migration guide [here](/docs/guides/migration-guide/upgrading-to-0-19-0). +If you believe your project might be affected, read more details in the migration guide [here](/guides/migration/versions). @@ -112,7 +112,7 @@ If you believe your project might be affected, read more details in the migratio - Do you directly call `adapter_macro`? -If you believe your project might be affected, read more details in the migration guide [here](/docs/guides/migration-guide/upgrading-to-0-18-0). +If you believe your project might be affected, read more details in the migration guide [here](/guides/migration/versions). @@ -190,7 +190,7 @@ models: ```
-If you believe your project might be affected, read more details in the migration guide [here](/docs/guides/migration-guide/upgrading-to-0-17-0). +If you believe your project might be affected, read more details in the migration guide [here](/guides/migration/versions). @@ -202,7 +202,7 @@ If you believe your project might be affected, read more details in the migratio - Do you use the custom `generate_schema_name` macro? - Do you use `partition_by` config for BigQuery models? -If you believe your project might be affected, read more details in the migration guide [here](/docs/guides/migration-guide/upgrading-to-0-16-0). +If you believe your project might be affected, read more details in the migration guide [here](/guides/migration/versions). @@ -214,7 +214,7 @@ If you believe your project might be affected, read more details in the migratio - Do you have a custom materialization? - Do you have a macro that accesses `Relations` directly? -If you believe your project might be affected, read more details in the migration guide [here](/docs/guides/migration-guide/upgrading-to-0-15-0). +If you believe your project might be affected, read more details in the migration guide [here](/guides/migration/versions).
@@ -225,18 +225,18 @@ If you believe your project might be affected, read more details in the migratio - Do you use the custom `generate_schema_name` macro? - Do you use the `—non-destructive` flag? -If you believe your project might be affected, read more details in the migration guide [here](/docs/guides/migration-guide/upgrading-to-0-14-0). +If you believe your project might be affected, read more details in the migration guide [here](/guides/migration/versions).
#### Testing your changes before upgrading -Once you have an idea about what code changes you'll need to make, you can start implementing them. We recommend that you create a separate dbt project, `Upgrade Project`, to test your changes before making them live in your main dbt project. In your `Upgrade Project`, connect to the same repository that you use for your main dbt project, but this time, set the development environment [settings](docs/dbt-cloud/cloud-configuring-dbt-cloud/cloud-choosing-a-dbt-version) to run the latest version of dbt Core. Next check out a branch `dbt-version-upgrade`, make the appropriate updates to your project (if needed), and see if your dbt project compiles and runs with the new version of dbt in the IDE. If jumping directly to the latest version of dbt is too far of a leap for your project, try iteratively getting your project to work on each successive minor version. There are years of development and a handful of breaking changes between two distant versions of dbt (e.g. 0.14 --> 0.20). There are far fewer between two subsequent versions of dbt, which is why upgrading regularly is important. +Once you have an idea about what code changes you'll need to make, you can start implementing them. We recommend that you create a separate dbt project, **Upgrade Project**, to test your changes before making them live in your main dbt project. In your **Upgrade Project**, connect to the same repository that you use for your main dbt project, but this time, set the development environment [settings](docs/dbt-cloud/cloud-configuring-dbt-cloud/cloud-choosing-a-dbt-version) to run the latest version of dbt Core. Next check out a branch `dbt-version-upgrade`, make the appropriate updates to your project (if needed), and see if your dbt project compiles and runs with the new version of dbt in the IDE. If jumping directly to the latest version of dbt is too far of a leap for your project, try iteratively getting your project to work on each successive minor version. There are years of development and a handful of breaking changes between two distant versions of dbt (e.g. 0.14 --> 1.0). There are far fewer between two subsequent versions of dbt, which is why upgrading regularly is important. Once you have your project compiling and running on the latest version of dbt in the development environment for your `dbt-version-upgrade` branch, try replicating one of your production jobs to run off your branch's code. You can do this by creating a new deployment environment for testing, setting the custom branch to 'ON' and referencing your `dbt-version-upgrade` branch. You'll also need to set the dbt version in this environment to the latest dbt Core version. - + Then add a job to the new testing environment that replicates one of the production jobs your team relies on. If that job runs smoothly, you should be all set to merge your branch into main and change your development and deployment environments in your main dbt project to run off the newest version of dbt Core. diff --git a/website/docs/docs/dbt-cloud/cloud-configuring-dbt-cloud/cloud-using-a-managed-repository.md b/website/docs/docs/dbt-cloud/cloud-configuring-dbt-cloud/cloud-using-a-managed-repository.md index 25ae7bf8f8d..e5b347e0f05 100644 --- a/website/docs/docs/dbt-cloud/cloud-configuring-dbt-cloud/cloud-using-a-managed-repository.md +++ b/website/docs/docs/dbt-cloud/cloud-configuring-dbt-cloud/cloud-using-a-managed-repository.md @@ -3,13 +3,18 @@ title: "Using a dbt Cloud managed repository" id: "cloud-using-a-managed-repository" --- -If you do not already have a git repository for your dbt project, you can let dbt Cloud manage a repository for you. Managed repositories are a great way to trial dbt without needing to spin a new repository. +If you do not already have a git repository for your dbt project, you can let dbt Cloud manage a repository for you. Managed repositories are a great way to trial dbt without needing to create a new repository. -To create a managed repository, choose the "Managed" option when creating a repository in dbt Cloud. Next, supply the name for the repository -- something like "analytics" or "dbt-models" is a good choice. +To set up a project with a managed repository: -Once saved, dbt Cloud will host and manage this repository for you. If in the future you choose to host this repository yourself, you can contact support to have the contents of your repo transferred to you. +1. From your Account settings in dbt Cloud, select the project you want to set up with a managed repository. If the project already has a repository set up, you need to edit the repository settings and disconnect the existing repository. +2. Click **Edit** for the project. +3. Under Repository, click **Configure repository**. +4. Select **Managed**. +5. Enter a name for the repository. For example, "analytics" or "dbt-models." +6. Click **Create**. + - +dbt Cloud will host and manage this repository for you. If in the future you choose to host this repository yourself, you can contact support to have the contents of your repo transferred to you. - -** We do not recommend productionizing with a managed repository. This is because you will not be able to use git features like pull requests which are part of our recommended version control best practices. +** We do not recommend using a managed repository in a production environment. You will not be able to use git features like pull requests which are part of our recommended version control best practices. diff --git a/website/docs/docs/dbt-cloud/cloud-configuring-dbt-cloud/connecting-azure-devops.md b/website/docs/docs/dbt-cloud/cloud-configuring-dbt-cloud/connecting-azure-devops.md new file mode 100644 index 00000000000..976615c1723 --- /dev/null +++ b/website/docs/docs/dbt-cloud/cloud-configuring-dbt-cloud/connecting-azure-devops.md @@ -0,0 +1,31 @@ +--- +title: "Connecting your Azure DevOps Account" +id: "connecting-azure-devops" +sidebar_label: "Connecting Azure DevOps" +--- + + + +:::info +You can still use dbt Cloud with Azure DevOps before this feature is generally available by [following these instructions](docs/dbt-cloud/cloud-configuring-dbt-cloud/cloud-import-a-project-by-git-url#azure-devops). +::: + + + + +## About Azure DevOps and dbt Cloud + +You can connect your Azure DevOps account in dbt Cloud to unlock new product experiences: + +- Import new Azure DevOps repos with a couple clicks during dbt Cloud project setup. +- Clone repos using HTTPS rather than SSH +- Enforce user authorization with OAuth 2.0. +- Carry Azure DevOps user repository permissions (read / write access) through to dbt Cloud IDE's git actions. +- Trigger Continuous integration (CI) builds when pull requests are opened in Azure DevOps. + +To connect Azure DevOps in dbt Cloud: + +1. An account admin needs to [set up an Active Directory application and add it to dbt Cloud](docs/dbt-cloud/cloud-configuring-dbt-cloud/setup-azure). +2. dbt Cloud developers need to [personally authenticate with Azure DevOps](docs/dbt-cloud/cloud-configuring-dbt-cloud/authenticate-azure) from dbt Cloud. + + diff --git a/website/docs/docs/dbt-cloud/cloud-configuring-dbt-cloud/connecting-gitlab.md b/website/docs/docs/dbt-cloud/cloud-configuring-dbt-cloud/connecting-gitlab.md index 56f15050ba6..6fe1244d25c 100644 --- a/website/docs/docs/dbt-cloud/cloud-configuring-dbt-cloud/connecting-gitlab.md +++ b/website/docs/docs/dbt-cloud/cloud-configuring-dbt-cloud/connecting-gitlab.md @@ -6,70 +6,115 @@ sidebar_label: "Connecting GitLab" ## Overview -Connecting your GitLab account to dbt Cloud unlocks exciting and compelling functionality in dbt Cloud. Once your GitLab account is connected, you can: -- [Trigger CI builds](cloud-enabling-continuous-integration-with-github) when Merge Requests are opened in GitLab -- Import new repos with one click -- Carry GitLab permissions through to dbt Cloud IDE's git actions -## For Developer and Team tiers +Connecting your GitLab account to dbt Cloud provides convenience and another layer of security to dbt Cloud: +- Import new GitLab repos with a couple clicks during dbt Cloud project setup. +- Clone repos using HTTPS rather than SSH. +- Carry GitLab user permissions through to dbt Cloud IDE's git actions. +- Trigger [Continuous integration](cloud-enabling-continuous-integration-with-github) builds when merge requests are opened in GitLab. -To connect your personal GitLab account, navigate to your [Profile](https://cloud.getdbt.com/#/profile/) and select [Integrations](https://cloud.getdbt.com/#/profile/integrations/) from the left sidebar. +The steps to integrate GitLab in dbt Cloud depend on your plan. If you are on: +- the Developer or Team plan, read these [instructions](/connecting-gitlab#for-dbt-cloud-developer-and-team-tiers). +- the Enterprise plan, jump ahead to these [instructions](/connecting-gitlab#for-the-dbt-cloud-enterprise-tier). -If your account is not connected, click the button `Link your GitLab account` to continue the setup process. - +## For dbt Cloud Developer and Team tiers -You should be redirected to GitLab and prompted to sign into your account. GitLab will then ask for your explicit authorization: +To connect your GitLab account: +1. Navigate to Your Profile settings by clicking the gear icon in the top right. +2. Select **Linked Accounts** in the left menu. +3. Click **Link** to the right of your GitLab account. + + + +When you click **Link**, you will be redirected to GitLab and prompted to sign into your account. GitLab will then ask for your explicit authorization: -Once you've accepted, you should be redirected back to dbt Cloud, and you'll see that your account has been linked. +Once you've accepted, you should be redirected back to dbt Cloud, and you'll see that your account has been linked to your profile. + + +## For the dbt Cloud Enterprise tier + +dbt Cloud enterprise customers have the added benefit of bringing their own GitLab OAuth application to dbt Cloud. This tier benefits from extra security, as dbt Cloud will: +- Enforce user authorization with OAuth. +- Carry GitLab's user repository permissions (read / write access) through to dbt Cloud IDE's git actions. + +In order to connect GitLab in dbt Cloud, a GitLab account admin must: +1. [Set up a GitLab OAuth application](/cloud-configuring-dbt-cloud/connecting-gitlab#setting-up-a-gitlab-oauth-application). +2. [Add the GitLab app to dbt Cloud](/connecting-gitlab#adding-the-gitlab-oauth-application-to-dbt-cloud). + +Once the admin completes those steps, dbt Cloud developers need to: +1. [Personally authenticate with GitLab](cloud-configuring-dbt-cloud/connecting-gitlab#personally-authenticating-with-gitlab) from dbt Cloud. - -## For Enterprise tier +### Setting up a GitLab OAuth application +We recommend that before you set up a project in dbt Cloud, a GitLab account admin set up an OAuth application in GitLab for use in dbt Cloud. -Before developers can personally authenticate in GitLab, account admins need to set up a GitLab application. +For more detail, GitLab has a [guide for creating a Group Application](https://docs.gitlab.com/ee/integration/oauth_provider.html#group-owned-applications). -Account admins should navigate to `Account Settings` and click on the `Integrations` tab. +In GitLab, navigate to your group settings and select **Applications**. Here you'll see a form to create a new application. - + +In GitLab, when creating your Group Application, input the following: -Admins can create a Group Owned Application in GitLab - [GitLab has a guide for that here](https://docs.gitlab.com/ee/integration/oauth_provider.html#group-owned-applications). +| Field | Value | +| ------ | ----- | +| **Name** | dbt Cloud | +| **Redirect URI** | https://cloud.getdbt.com/complete/gitlab | +| **Confidential** | ✔️ | +| **Scopes** | ✔️ api | -In GitLab, when creating your Group Owned Application, input the following: -- `Name` - We recommend `dbt Cloud` -- `Redirect URI` - You should copy-paste this from your Account Integrations page in dbt Cloud, but it is likely `https://cloud.getdbt.com/complete/gitlab` -- Check the `Confidential` box -- Check the `api` Scope +dbt Cloud single tenant customers need to replace **cloud.getdbt.com** with the hostname of +your dbt Cloud instance. -The application form in GitLab should look like this: +The application form in GitLab should look as follows when completed: - + -Click `Save application` in GitLab, and GitLab will then generate an Application ID and Secret. You can copy-paste those values back into the form on your dbt Cloud's Integrations page. +Click **Save application** in GitLab, and GitLab will then generate an **Application ID** and **Secret**. These values will be available even if you close the app screen, so this is not the only chance you have to save them. - +### Adding the GitLab OAuth application to dbt Cloud +After you've created your GitLab application, you need to provide dbt Cloud information about the app. In dbt Cloud, account admins should navigate to **Account Settings**, click on the **Integrations** tab, and expand the GitLab section. -Note that if you're using the regular consumer version of GitLab, you'll want to use the standard `https://gitlab.com` for your GitLab instance - if your organization is using a hosted version of GitLab, you'll want to use the hostname provided by your organization: `https://gitlab.yourgreatcompany.com/`. + -Once the form is complete in dbt Cloud, click the button `Connect to GitLab`. +In dbt Cloud, input the following values: -GitLab will then ask for your explicit authorization: +| Field | Value | +| ------ | ----- | +| **GitLab Instance** | https://gitlab.com | +| **Application ID** | *copy value from GitLab app* | +| **Secret** | *copy value from GitLab app* | + +Note, if you have a special hosted version of GitLab, modify the **GitLab Instance** to use the hostname provided for your organization instead - for example https://gitlab.yourgreatcompany.com/. + +Once the form is complete in dbt Cloud, click **Save**. + +You will then be redirected to GitLab and prompted to sign into your account. GitLab will ask for your explicit authorization: -And you're all set! +Once you've accepted, you should be redirected back to dbt Cloud, and your integration is ready for developers on your team to [personally authenticate with](/connecting-gitlab#personally-authenticating-with-gitlab). + +### Personally authenticating with GitLab +dbt Cloud developers on the Enterprise plan must each connect their GitLab profiles to dbt Cloud, as every developer's read / write access for the dbt repo is checked in the dbt Cloud IDE. -Non-admins on Enterprise accounts can authenticate by going to `Profile` and then `Integrations` and clicking the `Link your GitLab account` button. +To connect a personal GitLab account, dbt Cloud developers should navigate to Your Profile settings by clicking the gear icon in the top right, then select **Linked Accounts** in the left menu. - +If your GitLab account is not connected, you’ll see "No connected account". Select **Link** to begin the setup process. You’ll be redirected to GitLab, and asked to authorize dbt Cloud in a grant screen. + + + +Once you approve authorization, you will be redirected to dbt Cloud, and you should see your connected account. You're now ready to start developing in the dbt Cloud IDE. ## Troubleshooting -### Errors importing a repository +### Errors when importing a repository on dbt Cloud project set up If you do not see your repository listed, double-check that: - Your repository is in a Gitlab group you have access to. dbt Cloud will not read repos associated with a user. -If you do see your repository listed but are unable to import the repository successfully, double-check that: -- You are a maintainer on that repository (only users with maintainer permissions can set up repository connections) +If you do see your repository listed, but are unable to import the repository successfully, double-check that: +- You are a maintainer of that repository. Only users with maintainer permissions can set up repository connections. + +If you imported a repository using the dbt Cloud native integration with GitLab, you should be able to see the clone strategy is using a `deploy_token`. If it's relying on an SSH key, this means the repository was not set up using the native GitLab integration, but rather using the generic git clone option. The repository must be reconnected in order to get the benefits described above. \ No newline at end of file diff --git a/website/docs/docs/dbt-cloud/cloud-configuring-dbt-cloud/connecting-your-database.md b/website/docs/docs/dbt-cloud/cloud-configuring-dbt-cloud/connecting-your-database.md index cb1ae76f65c..e10b2bd1e2c 100644 --- a/website/docs/docs/dbt-cloud/cloud-configuring-dbt-cloud/connecting-your-database.md +++ b/website/docs/docs/dbt-cloud/cloud-configuring-dbt-cloud/connecting-your-database.md @@ -3,40 +3,44 @@ title: "Connecting your database" id: "connecting-your-database" --- +You can connect to your database in dbt Cloud by clicking the gear in the top right and then selecting **Account Settings**. From the Account Settings page, click **+ New Project**. + ## IP Restrictions dbt Cloud will always connect to your warehouse from the following IP addresses. Be sure to allow traffic from these IPs in your firewall, and include them in any database grants. -- 52.45.144.63 -- 54.81.134.249 -- 52.22.161.231 +| Region/Deployment | IP Addresses | +| ------ | ----------- | +| US (cloud.getdbt.com) | 52.45.144.63
54.81.134.249
52.22.161.231 | +| EMEA (emea.dbt.com) | 3.123.45.39
3.126.140.248
3.72.153.148 | +| Virtual Private dbt | Ask [Support](https://docs.getdbt.com/guides/legacy/getting-help#dbt-cloud-support) for your IPs | -- `54.81.134.249` and `52.22.161.231` were added in November, 2020 +- November 2020 — add the IPs `54.81.134.249` and `52.22.161.231` +- September 2022 — Add EMEA IPs +Allowing these IP addresses only enables the connection to your . However, you might want to send API requests from your restricted network to the dbt Cloud API. For example, you could use the API to send a POST request that [triggers a job to run](https://docs.getdbt.com/dbt-cloud/api-v2#operation/triggerRun). Using the dbt Cloud API requires that you allow the `cloud.getdbt.com` subdomain. For more on the dbt Cloud architecture, see "[Deployment architecture](deployment-architecture)." + -## Connecting to Redshift and Postgres +## Connecting to Postgres, Redshift, and AlloyDB -The following fields are required when creating a Redshift connection: +The following fields are required when creating a Postgres, Redshift, or AlloyDB connection: | Field | Description | Examples | | ----- | ----------- | -------- | -| Host Name | The hostname of the Postgres or Redshift database to connect to. This can either be a hostname an IP address. | `xxx.us-east-1.amazonaws.com` | +| Host Name | The hostname of the Postgres, Redshift, or AlloyDB database to connect to. This can either be a hostname or an IP address. | `xxx.us-east-1.amazonaws.com` | | Port | Usually 5432 (Postgres) or 5439 (Redshift) | `5439` | | Database | The logical database to connect to and run queries against. | `analytics` | - - - ### Connecting via an SSH Tunnel -To connect to a Postgres or Redshift instance via an SSH tunnel, check the "Use SSH Tunnel" option when creating your connection. When configuring the tunnel, you'll need to supply the hostname, username, and port for the bastion server. +To connect to a Postgres, Redshift, or AlloyDB instance via an SSH tunnel, select the **Use SSH Tunnel** option when creating your connection. When configuring the tunnel, you must supply the hostname, username, and port for the bastion server. Once the connection is saved, a public key will be generated and displayed for the Connection. You can copy this public key to the bastion server to authorize dbt Cloud to connect to your database via the bastion server. @@ -48,12 +52,13 @@ The following fields are required when creating a Snowflake connection: | Field | Description | Examples | | ----- | ----------- | -------- | -| Account | The Snowflake account to connect to. Take a look [here](snowflake-profile#account) to determine what the account field should look like based on your region.| `db5261993`,`db5261993.east-us-2.azure` | -| Role | An optional field indicating what role should be assumed after connecting to Snowflake | `transformer` | +| Account | The Snowflake account to connect to. Take a look [here](snowflake-profile#account) to determine what the account field should look like based on your region.| | +| Role | A mandatory field indicating what role should be assumed after connecting to Snowflake | `transformer` | | Database | The logical database to connect to and run queries against. | `analytics` | | Warehouse | The virtual warehouse to use for running queries. | `transforming` | -![Snowflake connection details](/img/docs/dbt-cloud/snowflake-conn-details.png) + +**Note:** A crucial part of working with dbt atop Snowflake is ensuring that users (in development environments) and/or service accounts (in deployment to production environments) have the correct permissions to take actions on Snowflake! Here is documentation of some [example permissions to configure Snowflake access](snowflake-permissions). ### Username / Password @@ -64,7 +69,8 @@ Development or Deployment credentials in a dbt project. Simply enter your Snowfl username (specifically, the `login_name`) and the corresponding user's Snowflake `password` to authenticate dbt Cloud to run queries against Snowflake on behalf of a Snowflake user. -![Snowflake username/password auth](/img/docs/dbt-cloud/snowflake-userpass-auth.png) +**Note**: The schema field in the **Developer Credentials** section is a required field. + ### Key Pair **Available in:** Development environments, Deployment environments @@ -81,19 +87,26 @@ Finally, set the "Private Key" and "Private Key Passphrase" fields in the "Edit Credentials" page to finish configuring dbt Cloud to authenticate with Snowflake using a key pair. -**Note:** At this time ONLY Encrypted Private Keys are supported by dbt Cloud -- you **must** add the passphrase that will be used to decrypt the and will receive an error if the `PRIVATE KEY PASSPHRASE` field is empty. +**Note:** At this time ONLY Encrypted Private Keys are supported by dbt Cloud, and the keys must be of size 4096 or smaller. -![Snowflake keypair auth](/img/docs/dbt-cloud/snowflake-keypair-auth.png) +In order to successfully fill in the Private Key field, you **must** include the commented lines below when you add the passphrase. Leaving the `PRIVATE KEY PASSPHRASE` field empty will return an error - have a look at the examples below: + +**Example:** +```sql +-----BEGIN ENCRYPTED PRIVATE KEY----- +< encrypted private key contents here > +-----END ENCRYPTED PRIVATE KEY----- +``` + ### Snowflake OAuth + **Available in:** Development environments, Enterprise plans only The OAuth auth method permits dbt Cloud to run development queries on behalf of a Snowflake user without the configuration of Snowflake password in dbt Cloud. For -more information on configuring a Snowflake OAuth connection in dbt Cloud, please see -[the docs on setting up Snowflake OAuth](setting-up-enterprise-snowflake-oauth). - -![Configuring Snowflake OAuth for a connection](/img/docs/dbt-cloud/dbt-cloud-enterprise/1bd0c42-Screen_Shot_2020-03-10_at_6.20.05_PM.png) +more information on configuring a Snowflake OAuth connection in dbt Cloud, please see [the docs on setting up Snowflake OAuth](setting-up-enterprise-snowflake-oauth). + ## Connecting to BigQuery @@ -101,7 +114,7 @@ more information on configuring a Snowflake OAuth connection in dbt Cloud, pleas :::info Uploading a service account JSON keyfile -While the fields in a BigQuery connection can be specified manually, we recommend uploading a service account JSON keyfile to quickly and accurately configure a connection to BigQuery. +While the fields in a BigQuery connection can be specified manually, we recommend uploading a service account keyfile to quickly and accurately configure a connection to BigQuery. ::: @@ -136,7 +149,6 @@ more information on the initial configuration of a BigQuery OAuth connection in [the docs on setting up BigQuery OAuth](cloud-setting-up-bigquery-oauth). As an end user, if your organization has set up BigQuery OAuth, you can link a project with your personal BigQuery account in your personal Profile in dbt Cloud, like so: - ## Connecting to Databricks @@ -161,7 +173,7 @@ The following fields are available when creating a Databricks connection: | Endpoint | The ID of the endpoint to connect to (required if using Databricks SQL) | 0123456789 | | User | Optional | dbt_cloud_user | - + ## Connecting to Apache Spark diff --git a/website/docs/docs/dbt-cloud/cloud-configuring-dbt-cloud/setup-azure.md b/website/docs/docs/dbt-cloud/cloud-configuring-dbt-cloud/setup-azure.md new file mode 100644 index 00000000000..b620341fdf1 --- /dev/null +++ b/website/docs/docs/dbt-cloud/cloud-configuring-dbt-cloud/setup-azure.md @@ -0,0 +1,294 @@ +--- +title: "Set up Azure DevOps" +id: "setup-azure" +description: "You can set up your Azure DevOps by creating an Azure AD app and adding it to dbt Cloud." +sidebar_label: "Set up Azure DevOps" +--- + + + + + +## Overview + +To use our native integration with Azure DevOps in dbt Cloud, an account admin needs to set up an Azure Active Directory (Azure AD) app. We recommend setting up a separate [Azure AD application than used for SSO](/setting-up-enterprise-sso-with-azure-active-directory). + +1. [Register an Azure AD app](#register-an-azure-ad-app). +2. [Add permissions to your new app](#add-permissions-to-your-new-app). +3. [Add another redirect URI](#add-another-redirect-URI). +4. [Connect Azure DevOps to your new app](#connect-azure-devops-to-your-new-app). +5. [Add your Azure AD app to dbt Cloud](#add-your-azure-ad-app-to-dbt-cloud). + +Once the the Azure AD app is added to dbt Cloud, an account admin must also connect a service user via OAuth, which will be used to power headless actions in dbt Cloud such as deployment runs and CI. +1. [Connecting a Service User](#connecting-a-service-user). + + +Once the Azure AD app is added to dbt Cloud and the service user is connected, then dbt Cloud developers can personally authenticate in dbt Cloud from Azure DevOps. For more on this, see [Authenticate with Azure DevOps](docs/dbt-cloud/cloud-configuring-dbt-cloud/authenticate-azure). + +## Register an Azure AD app + +1. Sign into you Azure portal and click **Azure Active Directory** under Azure services. +2. Select **App registrations** in the left panel. +3. Select **New registration**. The form for creating a new Active Directory app opens. +4. Provide a name for your app. We recommend using, "dbt Labs Azure DevOps App". +5. Select **Accounts in any organizational directory (Any Azure AD directory - Multitenant)** as the Supported Account Types. +Many customers ask why they need to select Multitenant instead of Single tenant, and they frequently get this step wrong. Microsoft considers Azure DevOps (formerly called Visual Studio) and Azure Active Directory as separate tenants, and in order for this Active Directory application to work properly, you must select Multitenant. +6. Add a redirect URI by selecting **Web** and typing in `https://cloud.getdbt.com/complete/azure_active_directory`. If you have a custom dbt Cloud URL be sure to use the appropriate domain. +7. Click **Register**. + + + +Here's what your app should look before registering it: + + + + +## Add permissions to your new app + +Provide your new app access to Azure DevOps: + +1. Select **API permissions** in the left navigation panel. +2. Remove the **Microsoft Graph / User Read** permission. +3. Click **Add a permission**. +4. Select **Azure DevOps**. +5. Select the **user_impersonation** permission. This is the only permission available for Azure DevOps. + + + +## Add another redirect URI + +You also need to add another redirect URI to your Azure AD application. This redirect URI will be used to authenticate the service user for headless actions in deployment environments. + +1. Navigate to your Azure AD application. +2. Select the link next to **Redirect URIs** +3. Click **Add URI** and add the URI, making sure to use the appropriate domain if you have a custom dbt Cloud URL: +`https://cloud.getdbt.com/complete/azure_active_directory_service_user` +4. Click **Save**. + + + + + + +## Connect Azure DevOps to your new app +If you have already connected your Azure DevOps account to Active Directory, then you can proceed to [Connecting a service user](#connecting-a-service-user). However, if you're just getting set up, connect Azure DevOps to the Active Directory App you just created: + +1. From your Azure DevOps account, select **Organization settings** in the bottom left. +2. Navigate to Azure Active Directory. +3. Click **Connect directory**. +4. Select the directory you want to connect. +5. Click **Connect**. + + + +## Add your Azure AD app to dbt Cloud + +Once you connect your Azure AD app and Azure DevOps, you need to provide dbt Cloud information about the app: + +1. Navigate to your account settings in dbt Cloud. +2. Select **Integrations**. +3. Scroll to the Azure DevOps section. +4. Complete the form: + - **Azure DevOps Organization:** Must match the name of your Azure DevOps organization exactly. + - **Application (client) ID:** Found in the Azure AD App. + - **Client Secrets:** You need to first create a secret in the Azure AD App under **Client credentials**. Make sure to copy the **Value** field in the Azure AD App and paste it in the **Client Secret** field in dbt Cloud. You are responsible for the Azure AD app secret expiration and rotation. + - **Directory(tenant) ID:** Found in the Azure AD App. + + +Your Azure AD app should now be added to your dbt Cloud Account. People on your team who want to develop in dbt Cloud's IDE can now personally [authorize Azure DevOps from their profiles](dbt-cloud/cloud-configuring-dbt-cloud/authenticate-azure). + +## Connecting a service user + +Because Azure DevOps forces all authentication to be linked to a user's permissions, we recommend you create a "service user" in Azure DevOps whose permissions will be used to power headless actions in dbt Cloud such as dbt Cloud project repo selection, deployment runs, and CI. A service user is a pseudo user set up in the same way an admin would set up a real user, but it's given permissions specifically scoped for service to service interactions. You should avoid linking authentication to a real Azure DevOps user because if this person leaves your organization, dbt Cloud will lose privileges to the dbt Azure DevOps repositories, causing production runs to fail. + +### More on Service Users + +A service user account must have the following Azure DevOps permissions for all Azure DevOps projects and repos you want accessible in dbt Cloud. Read more about how dbt Cloud uses each permission in the following paragraphs. + + - **Project Reader** + - **ViewSubscriptions** + - **EditSubscriptions** + - **DeleteSubscriptions** * + - **PullRequestContribute** + - **GenericContribute** + +\* Note: **DeleteSubscriptions** permission might be included in **EditSubscriptions** depending on your version of Azure. + +Some of these permissions are only accessible via the Azure DevOps API, for which documentation can be found [here](https://docs.microsoft.com/en-us/azure/devops/organizations/security/namespace-reference?view=azure-devops). We’ve also detailed more information on Azure DevOps API usage below to help accelerate the set up. Alternatively, you can use the Azure DevOps UI to enable permissions, but you cannot get the least permissioned set. + +:::info Provide the service user with required permissions before setting up a dbt Cloud project +This service user's permissions will also power which repositories a team can select from during dbt project set up, so an Azure DevOps admin must grant at minimum Project Reader access to the service user before setting up a project in dbt Cloud. +::: + +
+ ViewSubscriptions +

+ +**Security Namespace ID:** cb594ebe-87dd-4fc9-ac2c-6a10a4c92046 + +**Namespace:** ServiceHooks + +**Permission:** +```json +{ + "bit": 1, + "displayName": "View Subscriptions", + "name": "ViewSubscriptions" +} +``` + +**Uses:** To view existing Azure DevOps service hooks subscriptions + +**Token (where applicable - API only):** +- PublisherSecurity for access to all projects +- PublisherSecurity/ for per project access + +**UI/API:** API only + +
+ +
+ EditSubscriptions +

+ +**Security Namespace ID:** cb594ebe-87dd-4fc9-ac2c-6a10a4c92046 + +**Namespace:** ServiceHooks + +**Permission:** +```json +{ + "bit": 2, + "displayName": "Edit Subscription", + "name": "EditSubscriptions" +} + +``` + +**Uses:** To add or update existing Azure DevOps service hooks subscriptions + +**Token (where applicable - API only):** +- PublisherSecurity for access to all projects +- PublisherSecurity/ for per project access + +**UI/API:** API only + +
+ +
+ DeleteSubscriptions +

+ +**Security Namespace ID:** cb594ebe-87dd-4fc9-ac2c-6a10a4c92046 + +**Namespace:** ServiceHooks + +**Permission:** +```json +{ + "bit": 4, + "displayName": "Delete Subscriptions", + "name": "DeleteSubscriptions" +} + + +``` + +**Uses:** To delete any redundant Azure DevOps service hooks subscriptions + + +**Token (where applicable - API only):** +- PublisherSecurity for access to all projects +- PublisherSecurity/ for per project access + +**UI/API:** API only + +**Additional Notes:** This permission has been deprecated in recent Azure DevOps versions. Edit Subscriptions (bit 2) has Delete permissions. + + +
+ +
+ PullRequestContribute +

+ +**Security Namespace ID:** 2e9eb7ed-3c0a-47d4-87c1-0ffdd275fd87 + +**Namespace:** Git Repositories + +**Permission:** +```json +{ + "bit": 16384, + "displayName": "Contribute to pull requests", + "name": "PullRequestContribute" +} + +``` + +**Uses:** To post Pull Request statuses to Azure DevOps + + +**Token (where applicable - API only):** +- repoV2 for access to all projects +- repoV2/ for per project access +- repoV2// for per repo access + + +**UI/API:** UI and API + +**Additional Notes:** This permission is automatically inherited if Project Reader/Contributor/Administrator is set in the UI. + + +
+ +
+ GenericContribute +

+ +**Security Namespace ID:** 2e9eb7ed-3c0a-47d4-87c1-0ffdd275fd87 + +**Namespace:** Git Repositories + +**Permission:** +```json +{ + "bit": 4, + "displayName": "Contribute", + "name": "GenericContribute" +} + + +``` + +**Uses:** To post commit statuses to Azure DevOps + + +**Token (where applicable - API only):** +- repoV2 for access to all projects +- repoV2/ for access to a single project at a time +- repoV2// for access to a single repo at a time + + +**UI/API:** UI and API + +**Additional Notes:** This permission is automatically inherited if Project Contributor/Administrator is set in the UI. + + +
+ +You must connect your service user before setting up a dbt Cloud project, as the the service user's permissions determine which projects dbt Cloud can import. + +To connect the service user: +1. An admin must first be signed into the service user's Azure DevOps account. +2. The admin should click **Link Azure Service User** in dbt Cloud. +3. The admin will be directed to Azure DevOps and must accept the Azure AD app's permissions. +4. Finally, the admin will be redirected to dbt Cloud, and the service user will be connected. + + +Once connected, dbt Cloud displays the email address of the service user so you know which user's permissions are enabling headless actions in deployment environments. To change which account is connected, disconnect the profile in dbt Cloud, sign into the alternative Azure DevOps service account, and re-link the account in dbt Cloud. + +:::info Service user authentication expiration +dbt Cloud will refresh the authentication for the service user on each run triggered by the scheduler, API, or CI. If your account does not have any active runs for over 90 days, an admin will need to manually refresh the authentication of the service user by disconnecting and reconnecting the service user's profile via the OAuth flow described above in order to resume headless interactions like project set up, deployment runs, and CI. + +::: diff --git a/website/docs/docs/dbt-cloud/cloud-dbt-cloud-support.md b/website/docs/docs/dbt-cloud/cloud-dbt-cloud-support.md index bccc6c4db56..80a11ad90ca 100644 --- a/website/docs/docs/dbt-cloud/cloud-dbt-cloud-support.md +++ b/website/docs/docs/dbt-cloud/cloud-dbt-cloud-support.md @@ -6,7 +6,7 @@ id: "cloud-dbt-cloud-support" Welcome to dbt Cloud Support! Our purpose is to assist dbt Cloud users as they work through implementing and utilizing dbt Cloud at their organizations. Have a question you can't find an answer to in [our docs](https://docs.getdbt.com/), [dbt discourse](https://discourse.getdbt.com/), or [Stack Overflow](https://stackoverflow.com/questions/tagged/dbt)? dbt Support is here to `dbt help` you! -Check out our guide on [getting help](https://docs.getdbt.com/docs/guides/getting-help) - half of the problem is often knowing where to look... and how to ask good questions! +Check out our guide on [getting help](/guides/legacy/getting-help) - half of the problem is often knowing where to look... and how to ask good questions! Types of questions dbt Support will assist you with: - **How do I...** - set up a dbt Cloud project? diff --git a/website/docs/docs/dbt-cloud/cloud-ide/ide-beta.md b/website/docs/docs/dbt-cloud/cloud-ide/ide-beta.md new file mode 100644 index 00000000000..7e114b9dc70 --- /dev/null +++ b/website/docs/docs/dbt-cloud/cloud-ide/ide-beta.md @@ -0,0 +1,221 @@ +--- +title: "Develop in the dbt Cloud IDE (beta)" +id: "ide-beta" +--- + + + +:::info Join our beta + +If you’d like to try the dbt Cloud IDE for multi-tenant instances, please [sign up](https://docs.google.com/forms/d/e/1FAIpQLSdlU65gqTZPyGAUc16SkxqTc50NO9vdq_KGx1Mjm_4FB_97FA/viewform) to join the beta. To learn more about the beta features, you can read this documentation. + +::: + +## Overview + +The dbt Cloud integrated development environment (IDE) is where you can build, test, run, and version control your dbt projects directly from your browser. The IDE is the fastest and most reliable way to deploy dbt, and provides a real-time editing and execution environment for your dbt project -- no command line use required. + +To develop in dbt Cloud IDE (beta), you need to meet these requirements: + + +- Your dbt project must be compatible with dbt v0.15.0. The dbt IDE is powered by the [dbt-rpc](reference/commands/rpc) which was overhauled in dbt v0.15.0. +- You must have a [Developer License](dbt-cloud/access-control/cloud-seats-and-users). +- Currently only multi-tenant instances of dbt Cloud can develop in the updated beta version of the Cloud IDE. Single-tenant instances will soon be able to opt into this Beta release. +- Your dbt repository (in dbt Cloud) must have `write` access enabled. See [Connecting your GitHub Account](docs/dbt-cloud/cloud-configuring-dbt-cloud/cloud-installing-the-github-application) and [Importing a project by git URL](docs/dbt-cloud/cloud-configuring-dbt-cloud/cloud-import-a-project-by-git-url) for detailed setup instructions. + + +The IDE is a single interface for building, testing, running, and version controlling dbt projects from your browser. Anyone can use the IDE, from new dbt developers to seasoned practitioners. + + +To use the dbt Cloud IDE, you need to log in with a dbt Cloud account and click **Develop** at the top of the page. + +You can refer to [Getting Started with dbt Cloud](https://docs.getdbt.com/guides/getting-started) to quickly get set up and perform some key tasks. For more information, see the following articles. + +- [What is dbt?](docs/introduction#what-else-can-dbt-do) +- [Building your first project](guides/getting-started/building-your-first-project) +- [dbt Learn courses](https://courses.getdbt.com/collections) +- [Using Git](https://docs.github.com/en/github/getting-started-with-github/using-git) + +**Is there a cost to using the dbt Cloud IDE?** + +Not at all! You can use dbt Cloud when you sign up for the Free [Developer plan](https://www.getdbt.com/pricing/), which comes with one developer seat. If you’d like to access more features or have more developer seats, you can upgrade your account to the Team or Enterprise plan. See dbt [Pricing plans](https://www.getdbt.com/pricing/) for more details. + +**Can I be a contributor to dbt Cloud?** + +Anyone can contribute to the dbt project. And whether it's a dbt package, a plugin, dbt-core, or this documentation site, contributing to the open source code that supports the dbt ecosystem is a great way to level yourself up as a developer, and give back to the community. See [Contributing](/docs/contributing/oss-expectations) for details on what to expect when contributing to the dbt open source software (OSS). + +**What is the difference between developing on the dbt Cloud IDE and on the CLI?** + +There are two main ways to develop with dbt: using the web-based IDE in dbt Cloud or using the command-line interface (CLI) in dbt Core. + +- **dbt Cloud IDE** - dbt Cloud is a Web-based application that allows you to develop dbt projects with the IDE, includes a purpose-built scheduler, and provides an easier way to share your dbt documentation with your team. The IDE is a faster and more reliable way to deploy your dbt models, and provides a real-time editing and execution environment for your dbt project. + +- **dbt Core CLI** - The CLI uses [dbt Core](docs/introduction), an [open-source](https://github.com/dbt-labs/dbt) software that’s freely available. You can build your dbt project in a code editor, like Jetbrains or VSCode, and run dbt commands from the command line. + +**What type of support is provided with dbt Cloud?** + +The global dbt Support team is available to help dbt Cloud users by email or in-product live chat. Developer and Team accounts offer 24x5 support, while Enterprise customers have priority access and options for custom coverage. + +If you have project-related or modeling questions, you can use our dedicated [GitHub Discussions](https://docs.getdbt.com/docs/contributing/long-lived-discussions-guidelines) or [dbt Community Slack](http://getdbt.slack.com) to get help as well. + +## dbt Cloud IDE features + +With dbt Cloud IDE, you can: + +- Write modular SQL models with `select` statements and the [`ref()`](/reference/dbt-jinja-functions/ref) function +- Test every model before deploying them to production +- Share the generated documentation of your models with all data stakeholders +- Deploy safely using development environments like how git-enabled version control enables collaboration and a return to previous states + + +**Find and replace** + +Press Command-F or Ctrl-F to open the find and replace bar in the upper right corner of the current file in the IDE. The IDE highlights your search results in the current file and code outline. You can use the up and down arrows to see the match highlighted in the current file when there are multiple matches. To replace the text with something else, use the left arrow. + +**Search across files** + +You can quickly search over all files in the IDE on your current project. To search, open the search bar by pressing Command-O or Ctrl-O to find text across all files in your current project. and write your file name. You can view the results under the search text, which are grouped into files containing the match. You can click on the results to view it in the IDE. + +**Keyboard shortcuts** + +There are default keyboard shortcuts that can help make development more productive and easier for everyone. Press Fn-F1 to view a list of all of them. + +**Multiple selections** + +You can make multiple selections for quick and simultaneous edits. The below commands are a common way to add more cursors and allow you to insert cursors below or above with ease. + +- Option-Command-Down arrow +- Option-Command-Up arrow +- Press Option and click on an area + + + +**File explorer** + +The File explorer on the left side of the IDE allows you to organize your project and manage your files and folders. Click the three dot menu associated with the file or folder to create, rename, and delete it. + +**Drag and drop** + +You can also drag and drop files located in the file explorer. Use the file breadcrumb on the top of the IDE for quick, linear navigation. You can access adjacent files in the same file by right clicking on the breadcrumb file. + + + +**Organize tabs** + +You can move your tabs around to reorganize your work in the IDE. You can also right click on a tab to view and select a list of actions to take. + + + +## Development in the dbt Cloud IDE Beta + +With the IDE, you can compile dbt code into SQL and run it against your database directly. It leverages the open-source [dbt-rpc](https://docs.getdbt.com/reference/commands/rpc) plugin to intelligently recompile only the changes in your project. + +The dbt Cloud IDE Beta brings the startup and interaction time for dbt project development down from minutes to seconds. + +In dbt, SQL files can contain Jinja, a lightweight templating language. Using Jinja in SQL provides a way to use control structures (e.g. `if` statements and `for` loops) in your queries. It also lets you share SQL code through `macros`. + +You can invoke dbt commands, compile jinja into query, preview data from the warehouse, visualize a directed acyclic graph (DAG), and more. + +**Hot and cold start** + +You can launch the dbt Cloud IDE from a cold start or a hot start. + +- **Cold start** -- The process of starting an IDE session for the first time. Cold starting the IDE can take about 30 seconds to load. Behind the scene, dbt is provisioning a dedicated server for you to build a dbt project. After this step finishes, the IDE is ready for use. In the meantime, dbt is also starting up the dbt-rpc container to interact with dbt-core. You don’t need to wait for this to finish before the IDE is ready for editing. + +- **Hot start** -- The process of resuming an existing IDE session (within 3 hours of the last activity). Hot starting is faster and takes less than 3 seconds to load. This is because the environment is already available and you’re simply resuming your session. + +dbt Labs closely monitors these two start modes as key performance metrics to help ensure consistent and reliable experiences. + +**Work retention** + +You must save your work to avoid losing it. The dbt Cloud IDE needs an explicit action to save your changes. There are three ways your work is stored: + +- **Unsaved, local code** -- Any code you write is automatically available from your browser’s storage. You can see your changes but will lose it if you switch branches or browsers (another device or browser). +- **Saved but uncommitted code** -- When you save a file, the data gets stored in your local storage (EFS storage). If you switch branches but don’t _commit_ your saved changes, you will lose your changes. +- **Committed code** -- Your git branch repository contains all your changes. You can check out other branches or switch browsers without losing your changes. + + +**Run projects** + +You can also *build*, *run* *and test* dbt projects directly in the dbt IDE using our ‘Build’ feature. You can use dbt's [rich model selection syntax](https://docs.getdbt.com/reference/node-selection/syntax) to [run dbt commands](https://docs.getdbt.com/reference/dbt-commands) directly within dbt Cloud. + +The IDE updates in real-time as models, tests, seeds, and operations are run. If a model or test fails, you can review the logs to find and fix the issue. + + + +**Lineage tab** + +The visual in the Lineage tab adds more context to your dependencies and directional flow. + +You get to see how models are used as building blocks from left to right to transform your data from crude or normalized raw sources, into cleaned-up modular derived pieces, and finally into the final outputs on the far right of the DAG, ready to be used by the analyst in infinite combinations to present it in ways to help clients, customers, and organizations make better decisions. + +You can access files in the lineage tab by double clicking on a particular model. + +**Command bar + status** + +You can enter and run commands from the command bar at the bottom of the IDE. Use the [rich model selection syntax](https://docs.getdbt.com/reference/node-selection/syntax) to [run dbt commands](https://docs.getdbt.com/reference/dbt-commands) directly within dbt Cloud. You can also view the history, status, and logs of previous runs by clicking **History**. + +:::info Note + +For your convenience, dbt Cloud automatically includes ‘`dbt`’ as a prefix to your command so you don’t need to enter it. You can also type the ‘`dbt`’ prefix in your command. +::: + + +The status icon on the lower right corner of the IDE gives you an indicator of the health of your project. You can identify errors by clicking on the status icon for more details or by clicking **Restart the IDE**. + +**Generating and viewing documentation** + +To generate your project’s documentation (docs) in the IDE, enter `docs generate` or `dbt docs generate` in the command bar. This command generates the docs for your dbt project as it currently exists in development. + +After you generate a successful run, you can view your [documentation](https://docs.getdbt.com/docs/building-a-dbt-project/documentation) for your dbt project in real time. You can inspect and verify what your project's documentation will look like before you deploy your changes to production. + +Click **View Docs** on top of the file explorer to see the latest version of your documentation rendered in a new browser window. + + + +## Version control basics + +A [version control](https://en.wikipedia.org/wiki/Version_control) system allows you and your teammates to work collaboratively, safely, and simultaneously on a single project. Version control helps you track all the code changes made in the dbt Cloud IDE. + +When you develop in the dbt Cloud IDE, you can leverage Git directly to version control your code from your browser. This means you can branch, commit, push, and pull code with a couple of clicks - no command line required! + +You can create a separate branch to develop and make changes. The changes you make aren’t merged into the main branch unless it successfully passes tests. This helps keep the code organized and improves productivity by making the development process smooth. + + + +:::info Note +To use version control, make sure you are connected to a Git repository in the IDE. +::: + +**Common git terms** + + +| Name | Definition | +| --- | --- | +| Repository or repo | A repository is a directory that stores all the files, folders, and content needed for your project. You can think of this as an object database of the project, storing everything from the files themselves to the versions of those files, commits, and deletions. Repositories are not limited by user, and can be shared and copied.| +| Branch | A branch is a parallel version of a repository. It is contained within the repository, but does not affect the primary or main branch allowing you to work freely without disrupting the _live_ version. When you've made the changes you want to make, you can merge your branch back into the main branch to publish your changes | +| Checkout | The checkout command is used to create a new branch, change your current working branch to a different branch, or switch to a different version of a file from a different branch. | +| Commit | A commit is a user’s change to a file (or set of files). When you make a commit to save your work, Git creates a unique ID that allows you to keep a record of the specific changes committed along with who made them and when. Commits usually contain a commit message which is a brief description of what changes were made. | +| Main | The primary, base branch of all repositories. All committed and accepted changes should be on the Main (or master) branch. In the dbt Cloud IDE, the “Main” branch will be read-only. This is because any changes/edits to code cannot and should not be made directly in the base branch. A new branch should be created in order to make any changes to your project | +| Merge | Merge takes the changes from one branch and adds them into another (usually main) branch. These commits are usually first requested via pull request before being merged by a maintainer. | +| Pull Request | If someone has changed code on a separate branch of a project and wants it to be reviewed to add to the main branch, they can submit a pull request. Pull requests ask the repo maintainers to review the commits made, and then, if acceptable, merge the changes upstream. A pull happens when adding the changes to the main branch. | +| Push | A push updates a remote branch with the commits made to the current branch. You are literally “pushing” your changes onto the remote. | +| Remote | This is the version of a repository or branch that is hosted on a server. Remote versions can be connected to local clones so that changes can be synced. | + + +**The Git button in the IDE** + +The git button in the dbt Cloud IDE allows you to apply the concept of version control to your project. This page provides descriptions of each git button command and what they do: + +| Name | Actions | +| --- | --- | +| Abort merge | This option allows you to cancel a merge that had conflicts. Please note that all the changes will be reset, and this operation cannot be reverted, so make sure to commit or save all your changes before you start a merge. | +| Change branch | This option will allow you to change between branches (checkout). | +| Commit and push | Committing is similar to saving any changes made within your repo. In the above situation, the changes being saved or committed are the initialization of the project. The required files and folders are being added. When you make changes to your code in the future, you'll need to commit them as well. This allows you to record what changes were made when they were made, and who made them. | +| Create new branch | This allows you to branch off of your base branch and edit your project. You’ll notice after initializing your project that the “main branch will be read-only. This is because any changes to code cannot and should not be made directly in the base branch. A new branch should be created in order to make any changes to your project. | +| Initialize your project | This is done when first setting up your project. Initializing a project creates all required directories and files within an empty repository. Note: This option will not display if your repo isn't completely empty (i.e. includes a README file). Once you click **initialize your project** you'll want to click **commit** to finish setting up your project. | +| Open pull request | This allows you to open a pull request in Git for peers to review changes before merging into the base branch.| +| Pull changes from master/main | This option is available if you are on any local branch that is behind the remote version of the base branch or the remote version of the branch that you're currently on. | +| Pull from remote | This option is available if you’re on the local base branch and changes have recently been pushed to the remote version of the branch. As such, pulling in changes from the remote repo will allow you to pull in the most recent version of the base branch. | +| Reclone Your Repository | This allows you to reset your repository back to a fresh clone from your remote. You can use this option when you need to reclone your repo or if there are any git-related errors you’re experiencing in the dbt Cloud IDE. Reclone your repository is not available in the beta launch | +| Refresh git state | This enables you to pull new branches from a different remote branch to your local branch with just one command. | diff --git a/website/docs/docs/dbt-cloud/cloud-ide/the-dbt-ide.md b/website/docs/docs/dbt-cloud/cloud-ide/the-dbt-ide.md index 8f27ffba06f..a85aae18510 100644 --- a/website/docs/docs/dbt-cloud/cloud-ide/the-dbt-ide.md +++ b/website/docs/docs/dbt-cloud/cloud-ide/the-dbt-ide.md @@ -4,15 +4,18 @@ id: "the-dbt-ide" --- -:::info Prerequisites - -You must have a dbt Cloud account to use the IDE. Consult the guide on [using the dbt IDE](using-the-dbt-ide). Don't have an account? You can get started for free [here](https://www.getdbt.com/signup). +:::info Beta Feature +The revamped dbt Cloud IDE is now in beta! Check out the [IDE features](docs/dbt-cloud/cloud-ide/ide-beta), and [submit your expression of interest](https://docs.google.com/forms/d/e/1FAIpQLSdlU65gqTZPyGAUc16SkxqTc50NO9vdq_KGx1Mjm_4FB_97FA/viewform) to join the new Cloud IDE Beta group. ::: The dbt Integrated Development Environment (IDE) provides a realtime editing and execution environment for your dbt project. In the dbt IDE, you can write, run, test, and version control the code in your dbt project from your browser -- no command line use required. +**Prerequisites**: + +You must have a dbt Cloud account to use the IDE. Consult the guide on [using the dbt IDE](using-the-dbt-ide). Don't have an account? You can get started for free [here](https://www.getdbt.com/signup). + ## Compiling and Running SQL In the dbt IDE, you can compile dbt code into SQL and execute it against your database directly. The IDE leverages the open-source [dbt server](rpc) to intelligently recompile only the parts of your project that have changed. This brings the cycle time for dbt project development down from minutes to seconds. diff --git a/website/docs/docs/dbt-cloud/cloud-ide/the-ide-git-button.md b/website/docs/docs/dbt-cloud/cloud-ide/the-ide-git-button.md index 6d2fd4a079a..24539d26db0 100644 --- a/website/docs/docs/dbt-cloud/cloud-ide/the-ide-git-button.md +++ b/website/docs/docs/dbt-cloud/cloud-ide/the-ide-git-button.md @@ -1,7 +1,9 @@ --- title: "The IDE Git Button" +id: the-ide-git-button --- + The git button in the IDE allows you to apply the concept of [version control](dbt-cloud/cloud-ide/the-dbt-ide#version-control) to your project. This page provides descriptions of each git button command and what they do. **Initialize your project**: This is done when first setting up your project. Initializing a project will create all required directories and files within an empty repository. Note: This option will not display if your repo isn't completely empty (i.e. includes a README file). diff --git a/website/docs/docs/dbt-cloud/cloud-ide/viewing-docs-in-the-ide.md b/website/docs/docs/dbt-cloud/cloud-ide/viewing-docs-in-the-ide.md index 45256e7a6e1..545ca1bc8e4 100644 --- a/website/docs/docs/dbt-cloud/cloud-ide/viewing-docs-in-the-ide.md +++ b/website/docs/docs/dbt-cloud/cloud-ide/viewing-docs-in-the-ide.md @@ -14,10 +14,9 @@ To generate documentation in the IDE, run the `dbt docs generate` command in the Command Bar in the IDE. This command will generate the Docs for your dbt project as it exists in development in your IDE session. - + After generating your documentation, you can click the "view docs" button to see the latest version of your documentation rendered in a new browser window. - - + diff --git a/website/docs/docs/dbt-cloud/cloud-overview.md b/website/docs/docs/dbt-cloud/cloud-overview.md index 760d26e8a5c..f61c537707b 100644 --- a/website/docs/docs/dbt-cloud/cloud-overview.md +++ b/website/docs/docs/dbt-cloud/cloud-overview.md @@ -1,47 +1,46 @@ --- -title: "Overview" +title: "About dbt Cloud" id: "cloud-overview" --- -[dbt Cloud](https://www.getdbt.com/product/) is a hosted service that helps data analysts and engineers productionize dbt deployments. It comes equipped with turnkey support for scheduling jobs, CI/CD, serving documentation, monitoring & alerting, and an Integrated Developer Environment (IDE). -dbt Cloud’s generous Developer (free) plan and deep integration with dbt Core make it well suited for data teams small and large alike. +[dbt Cloud](https://www.getdbt.com/product/) is a hosted service that helps data analysts and engineers productionize dbt deployments. It comes equipped with turnkey support for scheduling jobs, CI/CD, serving documentation, monitoring & alerting, and an integrated developer environment (IDE). -[Get started with dbt Cloud](https://www.getdbt.com/signup/) +dbt Cloud’s generous Developer (free) plan and deep integration with dbt Core make it well suited for data teams small and large alike. +You can get started with dbt Cloud by [Signing up](https://www.getdbt.com/signup/). -### Develop dbt projects -Using the [dbt IDE](the-dbt-ide), you can develop, run, and version control dbt projects on the web. +## Develop dbt projects - +You can use the [dbt IDE](the-dbt-ide) to develop, run, and version control dbt projects on the web. -### Schedule and run dbt jobs in production +## Schedule and run dbt jobs in production Set up custom schedules to run your production dbt jobs. dbt Cloud's comprehensive scheduling interface makes it possible to schedule jobs by day of week, time of day, or a recurring interval. - + -### Democratize access to logs +## Democratize access to logs -dbt Cloud makes it easy to view in-progress and historical logs for your dbt runs. From Cloud's web interface, you can view and download the run logs for your dbt invocations. If you're happy ssh'ing into a cron server and running `tail -f` on a logfile, then this feature is *not* for you! +dbt Cloud makes it easy to view in-progress and historical logs for your dbt runs. From dbt Cloud, you can view and download the run logs for your dbt invocations. If you're happy ssh'ing into a cron server and running `tail -f` on a logfile, then this feature is *not* for you! - + -### Generate and distribute documentation +## Generate and distribute documentation dbt Cloud hosts and authorizes access to dbt project documentation. After enabling documentation for a given job, you can click the "View Documentation" button to see the latest documentation for that job. Because these docs are generated on a schedule, they're always up to date! Simply invite your coworkers to dbt Cloud to share your project's documentation with the rest of your team. More info about enabling docs for your jobs can be found [here](cloud-generating-documentation). - + -### Enable Continuous Integration +## Enable Continuous Integration :::info Available on the Basic Tier -Continuous Integration functionality is available to accounts on the Basic Tier or higher. +Continuous integration functionality is available to accounts on the Basic Tier or higher. ::: -dbt Cloud can be configured to run your dbt projects in a temporary schema when new commits are pushed to open Pull Requests. When the Cloud job completes, a status will be shown for the PR inside of GitHub. This build-on-PR functionality is a great way to catch bugs before deploying to production, and an essential tool in any analysts belt. More info on enabling CI workflows in dbt Cloud can be found [here](cloud-enabling-continuous-integration). +dbt Cloud can be configured to run your dbt projects in a temporary schema when new commits are pushed to open pull requests. When the Cloud job completes, a status will be shown for the PR inside of GitHub. This build-on-PR functionality is a great way to catch bugs before deploying to production, and an essential tool in any analysts belt. More info on enabling CI workflows in dbt Cloud can be found [here](cloud-enabling-continuous-integration). diff --git a/website/docs/docs/dbt-cloud/cloud-quickstart.md b/website/docs/docs/dbt-cloud/cloud-quickstart.md index b756c8f5d59..b4821e36b59 100644 --- a/website/docs/docs/dbt-cloud/cloud-quickstart.md +++ b/website/docs/docs/dbt-cloud/cloud-quickstart.md @@ -17,11 +17,11 @@ Let's get started! ## Create a connection -dbt Cloud uses this connection to _connect_ to your database when running jobs and transformation queries. Depending on the type of data warehouse you're using, you'll need to supply [different configuration parameters](docs/dbt-cloud/cloud-configuring-dbt-cloud/connecting-your-database). dbt Cloud natively supports connections to Snowflake, BigQuery, Redshift, Apache Spark, Databricks, and Postgres. +dbt Cloud uses this connection to _connect_ to your database when running jobs and transformation queries. Depending on the type of you're using, you'll need to supply [different configuration parameters](docs/dbt-cloud/cloud-configuring-dbt-cloud/connecting-your-database). dbt Cloud natively supports connections to Snowflake, BigQuery, Redshift, Apache Spark, Databricks, and Postgres. After picking a data warehouse type, a form will be generated where you can populate your warehouse's credentials. These credentials are encrypted at rest, and dbt Cloud never stores credentials in plaintext. - + ## Connect a repository @@ -40,13 +40,13 @@ Environments specify the information required to run dbt for your project. New d Scheduled dbt jobs can be configured in Deployment environments. These deployment environments must be configured with deployment credentials. Unlike Development credentials which run with the permissions of a human being, deployment credentials should be configured with a service account database user. We recommend configuring deployment environments to run as a user named dbt_cloud (or similar) in your database. -To create an Environment, click the hamburger button in the upper left-hand corner of the Cloud UI and select Environments from the menu. You’ll then click the “New Environment” button where you can specify the dbt version and custom branch (if applicable) that dbt Cloud should use to build your project. Additionally, the deployment credentials for the Environment can be configured on this page. +To create an environment, click **Deploy** in the upper left and select **Environments** from the menu. You can then click **Create Environment** where you can specify the dbt version and custom branch (if applicable) that dbt Cloud should use to build your project. Additionally, the deployment credentials for the environment can be configured on this page. ## Create a new job -Now that dbt Cloud is able to clone your dbt repo and connect to your warehouse, you're ready to create a new job! To create a job, navigate to the Jobs page from the left sidebar, then click the "New Job" button. In the job creation interface, you can specify the environment that the job should use, as well as commands and configuration for your new job. +Now that dbt Cloud is able to clone your dbt repo and connect to your warehouse, you're ready to create a new job! To create a job, click **Deploy** in the upper left and select **Jobs**. On the next page, click **Create Job**. In the Create New Job page, you can specify the environment that the job should use, as well as commands and configuration for your new job. @@ -54,6 +54,8 @@ Job schedules can be configured from the job creation interface. You can either -## Alternatives +## Other ways to quickly connect dbt Cloud -If you are interested in trialing dbt Cloud with Snowflake, you can use [Snowflake Partner Connect](https://docs.snowflake.com/en/user-guide/ecosystem-partner-connect.html) to spin up a dbt Cloud account with all of the key objects created (deployment and development environments, git repository, and sample job). All you need is a Snowflake Account with access to the ACCOUNTADMIN role to go into Partner Connect and find the dbt tile to set up a dedicated environment for test driving. +You may also jump-start your dbt Cloud onboarding by using one of the following Partner Connect integrations: + - [Snowflake Partner Connect](setting-up-snowflake#option-1-connect-dbt-cloud-and-snowflake-with-partner-connect) + - [Databricks Partner Connect](setting-up-databricks#option-1-connect-dbt-cloud-and-databricks-with-partner-connect) diff --git a/website/docs/docs/dbt-cloud/dbt-cloud-api/admin-cloud-api.md b/website/docs/docs/dbt-cloud/dbt-cloud-api/admin-cloud-api.md index e677299eabb..499d2e904c7 100644 --- a/website/docs/docs/dbt-cloud/dbt-cloud-api/admin-cloud-api.md +++ b/website/docs/docs/dbt-cloud/dbt-cloud-api/admin-cloud-api.md @@ -11,5 +11,3 @@ The dbt Cloud Administrative API is enabled by default for _Team_ and _Enterpris - and more Reference documentation for the dbt Cloud Administrative v2 API can be found [here](/dbt-cloud/api-v2). - -Reference documentation for the under construction dbt Cloud Administrative v4 API can be found [here](/dbt-cloud/api-v4). diff --git a/website/docs/docs/dbt-cloud/dbt-cloud-api/metadata/metadata-overview.md b/website/docs/docs/dbt-cloud/dbt-cloud-api/metadata/metadata-overview.md index e5b6428978c..4799a0254d8 100644 --- a/website/docs/docs/dbt-cloud/dbt-cloud-api/metadata/metadata-overview.md +++ b/website/docs/docs/dbt-cloud/dbt-cloud-api/metadata/metadata-overview.md @@ -1,12 +1,22 @@ --- -title: "Metadata API Overview" +title: "Metadata API" id: "metadata-overview" --- -Every time that dbt Cloud runs a dbt project, it generates metadata which pertains to the accuracy, recency, configuration, and structure of the views and tables in the warehouse. dbt Cloud serves a GraphQL API which supports arbitrary queries over this metadata; the endpoint for this API is `https://metadata.cloud.getdbt.com/graphql`. This API is an incredibly rich resource for evaluating data health longitudinally or at a point in time. +## About the metadata API + +Every time that dbt Cloud runs a dbt project, it generates metadata which pertains to the accuracy, recency, configuration, and structure of the views and tables in the warehouse. dbt Cloud serves a GraphQL API which supports arbitrary queries over this metadata; the endpoint for this API is `https://metadata.cloud.getdbt.com/graphql`. This API is an incredibly rich resource for evaluating data health longitudinally or at a point in time. + +## Prerequisites + +The metadata API is available to accounts on the _Team_ and _Enterprise_ plans, for any version >= dbt v0.19.0. Please note that artifacts generated with a version of dbt _less than_ v0.19.0 will not be accessible via the dbt Cloud metadata API. For information on upgrading, see "[Version migration guides](https://docs.getdbt.com/guides/migration/versions)." + +## How to browse the API We also provide a [graphical explorer](https://metadata.cloud.getdbt.com/graphiql) for this API where you can run ad-hoc queries or browse the schema. As GraphQL provides a self-describing API, the schema shown in the GraphiQL interface is an accurate representation of the graph and fields available to query on at any point in time. -The metadata API is available to accounts on the _Team_ and _Enterprise_ plans, for any version >= dbt v0.19.0. Please note that artifacts generated with a version of dbt _less than_ v0.19.0 will not be accessible via the dbt Cloud Metadata API. +## Retention limits for data + +You can use the metadata API to query data from the previous 3 months. For example, if today was March 1, you could query data back to January 1st. *We are continuously expanding the capabilities of the metadata API and we welcome your feedback and suggestions at metadata@dbtlabs.com.* diff --git a/website/docs/docs/dbt-cloud/dbt-cloud-api/metadata/metadata-querying.md b/website/docs/docs/dbt-cloud/dbt-cloud-api/metadata/metadata-querying.md index e90a13a11bc..8a1965c1cb7 100644 --- a/website/docs/docs/dbt-cloud/dbt-cloud-api/metadata/metadata-querying.md +++ b/website/docs/docs/dbt-cloud/dbt-cloud-api/metadata/metadata-querying.md @@ -2,7 +2,7 @@ title: "Querying the Metadata API" id: "metadata-querying" --- -Accounts on the _Team_ and _Enterprise_ plans can query the dbt Metadata API. +Accounts on the _Team_ and _Multi-Tenant Enterprise_ plans can query the dbt Metadata API. ## Authorization diff --git a/website/docs/docs/dbt-cloud/dbt-cloud-api/metadata/schema/schema-metadata-metric.mdx b/website/docs/docs/dbt-cloud/dbt-cloud-api/metadata/schema/schema-metadata-metric.mdx new file mode 100644 index 00000000000..1b7d371ffa3 --- /dev/null +++ b/website/docs/docs/dbt-cloud/dbt-cloud-api/metadata/schema/schema-metadata-metric.mdx @@ -0,0 +1,57 @@ +--- +title: "Metric" +id: "metadata-schema-metric" +--- + +import { ArgsTable, SchemaTable } from "./schema"; + +The metric object allows you to query information about [metrics](https://docs.getdbt.com/docs/building-a-dbt-project/metrics). + +### Arguments + +When querying for a `metric`, the following arguments are available. Note that if you do not include a runId, it will default to the most recent run of the specified job: + + + +Below we show some illustrative example queries and outline the schema (all possible fields you can query) of this metric object. + +### Example Queries +#### Metric information + +The example query below outputs information about a metric. Note that you can also add any field from the Model endpoint -- here we are simply selecting name. This includes schema, database, uniqueId, columns and more -- find documentation [here](https://docs.getdbt.com/docs/dbt-cloud/dbt-cloud-api/metadata/schema/metadata-schema-model). + + +```graphql +{ + metric(jobId: 123, uniqueId: "metric.jaffle_shop.new_customers") { + uniqueId + name + packageName + tags + label + runId + description + type + sql + timestamp + timeGrains + dimensions + meta + resourceType + filters { + field + operator + value + } + model { + name + } + } +} + +``` + +### Fields +When querying for a `metric`, the following fields are available: + + diff --git a/website/docs/docs/dbt-cloud/dbt-cloud-api/metadata/schema/schema-metadata-metrics.mdx b/website/docs/docs/dbt-cloud/dbt-cloud-api/metadata/schema/schema-metadata-metrics.mdx new file mode 100644 index 00000000000..48a882318c2 --- /dev/null +++ b/website/docs/docs/dbt-cloud/dbt-cloud-api/metadata/schema/schema-metadata-metrics.mdx @@ -0,0 +1,58 @@ +--- +title: "Metrics" +id: "metadata-schema-metrics" +--- + +import { ArgsTable, SchemaTable } from "./schema"; + +The metrics object allows you to query information about [metrics](https://docs.getdbt.com/docs/building-a-dbt-project/metrics). + +### Arguments + +When querying for `metrics`, the following arguments are available. Note that if you do not include a runId, it will default to the most recent run of the specified job: + + + +Below we show some illustrative example queries and outline the schema (all possible fields you can query) of this metrics object. + +### Example Queries +#### Metrics information + +The example query returns information about all metrics in this job. + +```graphql +{ + metrics(jobId: 123) { + uniqueId + name + packageName + tags + label + runId + description + type + sql + timestamp + timeGrains + dimensions + meta + resourceType + filters { + field + operator + value + } + model { + name + } + } +} + +``` + +### Fields +metrics has access to the *same fields* as the [metric node](/docs/dbt-cloud/dbt-cloud-api/metadata/schema/metadata-schema-metric). The difference is that metrics can output a list, so instead of querying for fields for one specific metric, you can query for those parameters for all metrics in a run. + +When querying for `metrics`, the following fields are available: + + diff --git a/website/docs/docs/dbt-cloud/dbt-cloud-api/metadata/schema/schema-metadata-model.mdx b/website/docs/docs/dbt-cloud/dbt-cloud-api/metadata/schema/schema-metadata-model.mdx index 19c2f051c6d..9643cc84399 100644 --- a/website/docs/docs/dbt-cloud/dbt-cloud-api/metadata/schema/schema-metadata-model.mdx +++ b/website/docs/docs/dbt-cloud/dbt-cloud-api/metadata/schema/schema-metadata-model.mdx @@ -56,6 +56,27 @@ The example query below could be useful if we wanted to understand information a } ``` +#### Column-level information + +You can use the following example query to understand more about the columns of a given model. Note that this will only work if the job has generated documentation. For example it will work with the command `dbt docs generate`. + +```graphql +{ + model(jobId: 123, uniqueId: "model.jaffle_shop.dim_user") { + columns{ + name + index + type + comment + description + tags + meta + } + } +} +``` + + ### Fields When querying for a `model`, the following fields are available: diff --git a/website/docs/docs/dbt-cloud/dbt-cloud-api/metadata/schema/schema-metadata-modelByEnv.mdx b/website/docs/docs/dbt-cloud/dbt-cloud-api/metadata/schema/schema-metadata-modelByEnv.mdx new file mode 100644 index 00000000000..657987039f0 --- /dev/null +++ b/website/docs/docs/dbt-cloud/dbt-cloud-api/metadata/schema/schema-metadata-modelByEnv.mdx @@ -0,0 +1,44 @@ +--- +title: "Model By Environment" +id: "metadata-schema-modelByEnv" +--- + +import { ArgsTable, SchemaTable } from "./schema"; + + + +This model by environment object allows you to query information about a particular model based on `environmentId`. + +The [example query](#example-query) illustrates a few fields you can query in this `modelByEnvironment` object. Refer to [Fields](#fields) to see the entire schema, which provides all possible fields you can query. + +### Arguments + +When querying for `modelByEnvironment`, you can use the following arguments. + + + + +### Example Query + +You can use the `environment_id` and `model_unique_id` to return the model and its execution time for the last 10 times it was run, regardless of which job ran it! + +```graphql +{ + modelByEnvironment( + environmentId: 1, + uniqueId:"model.jaffle_shop.dim_user", + lastRunCount:10, + withCatalog: false + ){ + uniqueId + jobId, + runId, + executionTime + } +} +``` + +### Fields +When querying for `modelByEnvironment`, you can use the following fields. + + diff --git a/website/docs/docs/dbt-cloud/dbt-cloud-api/metadata/schema/schema-metadata-snapshots.mdx b/website/docs/docs/dbt-cloud/dbt-cloud-api/metadata/schema/schema-metadata-snapshots.mdx new file mode 100644 index 00000000000..7d061ff0e0c --- /dev/null +++ b/website/docs/docs/dbt-cloud/dbt-cloud-api/metadata/schema/schema-metadata-snapshots.mdx @@ -0,0 +1,45 @@ +--- +title: "Snapshots" +id: "metadata-schema-snapshots" +--- + +import { ArgsTable, SchemaTable } from "./schema"; + +The snapshots object allows you to query information about all snapshots in a given job. + +### Arguments + +When querying for `snapshots`, the following arguments are available. Note that if you do not include a runId, it will default to the most recent run of the specified job: + + + +Below we show some illustrative example queries and outline the schema of this snapshots object. + +### Example Query +As we noted above, database, schema, and identifier are all optional arguments. This means that with this endpoint, you can: +- Find a specific snapshot by providing `..` +- Find all of the snapshots in a database and/or schema by providing `` and/or `` + +#### Finding snapshots information for a job +The example query returns information about all snapshots in this job. + +```graphql +{ + snapshots(jobId: 123) { + uniqueId + name + executionTime + environmentId + executeStartedAt + executeCompletedAt + } +} + +``` + +### Fields +Snapshots has access to the *same fields* as the [Snapshot node](/docs/dbt-cloud/dbt-cloud-api/metadata/schema/metadata-schema-snapshots). The difference is that Snapshots can output a list, so instead of querying for fields for one specific snapshot, you can query for those parameters for all snapshots within a jobID, database, etc. + +When querying for `snapshots`, the following fields are available: + + diff --git a/website/docs/docs/dbt-cloud/dbt-cloud-api/metadata/schema/schema.jsx b/website/docs/docs/dbt-cloud/dbt-cloud-api/metadata/schema/schema.jsx index 17386adf669..47b6ddaf9cc 100644 --- a/website/docs/docs/dbt-cloud/dbt-cloud-api/metadata/schema/schema.jsx +++ b/website/docs/docs/dbt-cloud/dbt-cloud-api/metadata/schema/schema.jsx @@ -91,7 +91,19 @@ export const SchemaTable = ({ nodeName }) => { fields { name description - type { name description kind ofType { name description} } + type { + name + description + kind + ofType { + name + description + ofType { + name + description + } + } + } } } }`}), @@ -121,8 +133,11 @@ export const SchemaTable = ({ nodeName }) => { {name} {type.kind==='LIST' ? - [{type.ofType.name}] : - {type.name} + [{type.ofType.ofType ? type.ofType.ofType.name : type.ofType.name }] : + (type.ofType ? + {type.ofType.name} : + {type.name} + ) } {description} diff --git a/website/docs/docs/dbt-cloud/dbt-cloud-api/service-tokens.md b/website/docs/docs/dbt-cloud/dbt-cloud-api/service-tokens.md index 8b444f5200f..b91fa9511fb 100644 --- a/website/docs/docs/dbt-cloud/dbt-cloud-api/service-tokens.md +++ b/website/docs/docs/dbt-cloud/dbt-cloud-api/service-tokens.md @@ -1,38 +1,89 @@ --- -title: "Service Account Tokens" +title: "Service account tokens" id: "service-tokens" +description: "Service account tokens help you define permissions for securing access to your dbt Cloud account and its projects." --- -## Overview -Service Account Admin API tokens are like [User API tokens](user-tokens), but they belong to an -_account_, rather than _a user_. +## About service tokens -As such, they may be suitable for system-level integrations that do not run on behalf of any one user. Service Account Admin tokens may only be created or modified by users with Account Admin (Enterprise plan) or Owner (Team plan) permissions on an account. Service Account tokens may be revoked if they become lost or compromised. +Service account tokens enable you to securely authenticate with the dbt Cloud API by assigning each token a narrow set of permissions that more precisely manages access to the API. While similar to [User API tokens](user-tokens), service account tokens belong to an account rather than a user. -### Service Account Admin API tokens +You can use service account tokens for system-level integrations that do not run on behalf of any one user. Assign any permission sets available in dbt Cloud to your service account token, which can vary slightly depending on your plan: - +* Enterprise plans can apply any permission sets available to service tokens. +* Team plans can apply Account Admin, Member, Job Admin, Read-Only, and Metadata permissions sets to service tokens. - - Service Account Admin tokens were launched in February, 2021 +You can assign as many permission sets as needed to one token. For more on permissions sets, see "[Enterprise Permissions](docs/dbt-cloud/access-control/enterprise-permissions)." - +## Generating service account tokens -Service Account Admin API tokens currently have full read+write access to an account, so please use them with caution. +In the Account Settings view of dbt Cloud, you can click on the Service Account tokens page and generate a new token. Create and save your token somewhere safe. -#### Generating a Service Account Admin Token +:::caution Note -In the Account Settings view of dbt Cloud, you can click on the Service Account tokens page and generate a new Account Admin token. Create and save your token. Please note that you will not be able to view this token again after its is generated, so store it somewhere safe for later use. +You will not be able to view this token again after generating it, so store the token somewhere safe for later use. -### Metadata Only Service Account Tokens +::: - +## Permissions for service account tokens - - Metadata Only Service Account tokens were launched in April, 2021 +You can assign service account tokens any permission set available in dbt Cloud. When you assign a permission set to a token, you will also be able to choose whether to grant that permissions to all projects in the account or to specific projects. - +### Team plans using service account tokens -dbt Cloud users can create metadata only service account based API Tokens to authorize requests to the metadata API. +The following permissions can be assigned to a service account token on a Team plan. -#### Generating a Metadata Only Service Account Token +**Account Admin**
+Account Admin service tokens have full `read + write` access to an account, so please use them with caution. A Team plan refers to this permission set as an "Owner role." For more on these permissions, see [Account Viewer](docs/dbt-cloud/access-control/enterprise-permissions#account-admin). -In the Account Settings view of dbt Cloud, you can click on the Service Account tokens page and generate a new Metadata Only token. Create and save your Metadata Only token. Please note that you will not be able to view this token again after its is generated, so store it somewhere safe for later use. +**Metadata Only**
+Metadata only service tokens can authorize requests to the metadata API. + +**Job Admin**
+Job admin service tokens can authorize requests for viewing, editing, and creating environments, triggering runs, and viewing historical runs. + +**Member**
+Member service tokens can authorize requests for viewing and editing resources, triggering runs, and inviting members to the account. Tokens assigned the Member permission set will have the same permissions as a Member user. For more information about Member users, see "[Self-service permissions](/dbt-cloud/access-control/self-service-permissions)". + +**Read-only**
+Read-only service tokens can authorize requests for viewing a read-only dashboard, viewing generated documentation, and viewing source freshness reports. + +### Enterprise plans using service account tokens + +The following permissions can be assigned to a service account token on an Enterprise plan. For more details about these permissions, see "[Enterprise permissions](/docs/dbt-cloud/access-control/enterprise-permissions)." + +**Account Admin**
+Account Admin service tokens have full `read + write` access to an account, so please use them with caution. For more on these permissions, see [Account Viewer](docs/dbt-cloud/access-control/enterprise-permissions#account-admin). + +**Metadata Only**
+Metadata only service tokens can authorize requests to the metadata API. + +**Job Admin**
+Job Admin service tokens can authorize request for viewing, editing, and creating environments, triggering runs, and viewing historical runs. For more on these permissions, see [Account Viewer](docs/dbt-cloud/access-control/enterprise-permissions#job-admin). + +**Account Viewer**
+Account Viewer service tokens have read only access to dbt Cloud accounts. For more on these permissions, see [Account Viewer](docs/dbt-cloud/access-control/enterprise-permissions#account-viewer) on the Enterprise Permissions page. + +**Admin**
+Admin service tokens have unrestricted access to projects in dbt Cloud accounts. You have the option to grant that permission all projects in the account or grant the permission only on specific projects. For more on these permissions, see [Admin Service](docs/dbt-cloud/access-control/enterprise-permissions#admin-service) on the Enterprise Permissions page. + +**Git Admin**
+Git admin service tokens have all the permissions listed in [Git admin](/docs/dbt-cloud/access-control/enterprise-permissions#git-admin) on the Enterprise Permissions page. + +**Database Adminn**
+Database admin service tokens have all the permissions listed in [Database admin](/docs/dbt-cloud/access-control/enterprise-permissions#database-admin) on the Enterprise Permissions page. + +**Team Admin**
+Team admin service tokens have all the permissions listed in [Team admin](/docs/dbt-cloud/access-control/enterprise-permissions#team-admin) on the Enterprise Permissions page. + +**Job Viewer**
+Job viewer admin service tokens have all the permissions listed in [Job viewer](/docs/dbt-cloud/access-control/enterprise-permissions#job-viewer) on the Enterprise Permissions page. + +**Developer**
+Developer service tokens have all the permissions listed in [Developer](/docs/dbt-cloud/access-control/enterprise-permissions#developer) on the Enterprise Permissions page. + +**Analyst**
+Analyst admin service tokens have all the permissions listed in [Analyst](/docs/dbt-cloud/access-control/enterprise-permissions#analyst) on the Enterprise Permissions page. + +**Stakeholder**
+Stakeholder service tokens have all the permissions listed in [Stakeholder](/docs/dbt-cloud/access-control/enterprise-permissions#stakeholder) on the Enterprise Permissions page. diff --git a/website/docs/docs/dbt-cloud/dbt-cloud-api/user-tokens.md b/website/docs/docs/dbt-cloud/dbt-cloud-api/user-tokens.md index 642c4837ebf..6ebf160dda4 100644 --- a/website/docs/docs/dbt-cloud/dbt-cloud-api/user-tokens.md +++ b/website/docs/docs/dbt-cloud/dbt-cloud-api/user-tokens.md @@ -1,5 +1,5 @@ --- -title: "User Tokens" +title: "User tokens" id: "user-tokens" --- diff --git a/website/docs/docs/dbt-cloud/dbt-cloud-enterprise.md b/website/docs/docs/dbt-cloud/dbt-cloud-enterprise.md index 3dc80086ecf..e545662c2d2 100644 --- a/website/docs/docs/dbt-cloud/dbt-cloud-enterprise.md +++ b/website/docs/docs/dbt-cloud/dbt-cloud-enterprise.md @@ -18,3 +18,6 @@ This section describes features of the dbt Cloud Enterprise plan. If you’re in ### Permissions - [Access Control](/docs/dbt-cloud/access-control/access-control-overview) - [Enterprise Permissions](/docs/dbt-cloud/access-control/enterprise-permissions) + +### Audit log +- [Using the Audit log](/audit-log) \ No newline at end of file diff --git a/website/docs/docs/dbt-cloud/dbt-cloud-enterprise/audit-log.md b/website/docs/docs/dbt-cloud/dbt-cloud-enterprise/audit-log.md new file mode 100644 index 00000000000..f179c0c1f84 --- /dev/null +++ b/website/docs/docs/dbt-cloud/dbt-cloud-enterprise/audit-log.md @@ -0,0 +1,175 @@ +--- +title: "Using the audit log for dbt Cloud Enterprise" +id: audit-log +description: "You can troubleshoot possible issues and provide security audits by reviewing event activity in your organization." +sidebar_label: "Using the audit log" +--- + +To review actions performed by people in your organization, dbt provides logs of audited user and system events. The dbt Cloud audit log lists events triggered in your organization within the last 90 days. + +Use the audit log to quickly review the actions performed by members of your organization. The audit log includes details such as who performed the action, what the action was, and when it was performed. You can use these details to troubleshoot access issues, perform security audits, or analyze specific events. + +You must be an **Account Admin** to access the audit log and this feature is only available on Enterprise plans. + +## Accessing the audit log + +To access audit log, click the gear icon in the top right, then click **Audit Log**. + +
+ + + +
+ +## Understanding the audit log + +On the audit log page, you will see a list of various events and their associated event data. Each of these events show the following information in dbt: + +* **Event name**: Action that was triggered +* **Agent**: User who triggered that action/event +* **Timestamp**: Local timestamp of when the event occurred + +### Event details + +Click the event card to see the details about the activity that triggered the event. This view provides important details, including when it happened and what type of event was triggered. For example, if someone changes the settings for a job, you can use the event details to see which job was changed (type of event: `v1.events.job_definition.Changed`), by whom (person who triggered the event: `actor`), and when (time it was triggered: `created_at_utc`). For types of events and their descriptions, see [Events in audit log](#events-in-audit-log). + +The event details provides the key factors of an event: + +| Name | Description | +| -------------------- | --------------------------------------------- | +| account_id | Account ID of where the event occurred | +| actor | Actor that carried out the event - User or Service | +| actor_id | Unique ID of the actor | +| actor_ip | IP address of the actor | +| actor_name | Identifying name of the actor | +| created_at_utc | UTC timestamp on when the event occurred | +| event_type | Unique key identifying the event | +| id | Unique ID of the event | +| service | Service that carried out the action | +| source | Source of the event - dbt Cloud UI or API | +| v1.events.event_type | This key will be different for each event and will match the event_type. This data will include all the details about the object(s) that was changed. | + +## Audit log events + +The audit log supports various events for different objects in dbt Cloud. You will find events for authentication, environment, jobs, service tokens, groups, user, project, permissions, license, connection, repository, and credentials. + +### Authentication + +| Event Name | Event Type | Description | +| -------------------------- | ---------------------------------------- | ------------------------------------------------------ | +| Auth Provider Changed | v1.events.auth_provider.Changed | Authentication provider settings changed | +| Credential Login Failed | v1.events.auth.CredentialsLoginFailed | User login via username and password failed | +| Credential Login Succeeded | v1.events.auth.CredentialsLoginSucceeded | User successfully logged in with username and password | +| SSO Login Failed | v1.events.auth.SsoLoginFailed | User login via SSO failed | +| SSO Login Succeeded | v1.events.auth.SsoLoginSucceeded | User successfully logged in via SSO + +### Environment + +| Event Name | Event Type | Description | +| ------------------- | ----------------------------- | ------------------------------------ | +| Environment Added | v1.events.environment.Added | New environment successfully created | +| Environment Changed | v1.events.environment.Changed | Environment settings changed | +| Environment Removed | v1.events.environment.Removed | Environment successfully removed | + +### Jobs + +| Event Name | Event Type | Description | +| ----------- | --------------------------------- | ---------------------------- | +| Job Added | v1.events.job_definition.Added | New Job successfully created | +| Job Changed | v1.events.job_definition.Changed | Job settings changed | +| Job Removed | v1.events.job_definition.Removed | Job definition removed | + +### Service Token + +| Event Name | Event Type | Description | +| --------------------- | -------------------------------- | ------------------------------------------ | +| Service Token Created | v1.events.service_token.Created | New Service Token was successfully created | +| Service Token Revoked | v1.events.service_token.Revoked | Service Token was revoked | + +### Group + +| Event Name | Event Type | Description | +| ------------- | ----------------------------- | ------------------------------ | +| Group Added | v1.events.user_group.Added | New Group successfully created | +| Group Changed | v1.events.user_group.Changed | Group settings changed | +| Group Removed | v1.events.user_group.Changed | Group successfully removed | + +### User + +| Event Name | Event Type | Description | +| ---------------------------- | ----------------------------------- | ----------------------------------------------- | +| Invite Added | v1.events.invite.Added | User invitation added and sent to the user | +| Invite Redeemed | v1.events.invite.Redeemed | User redeemed invitation | +| User Added to Account | v1.events.account.UserAdded | New user added to the account | +| User Added to Group | v1.events.user_group_user.Added | An existing user is added to a group | +| User Removed from Account | v1.events.account.UserRemoved | User removed from the account +| User Removed from Group | v1.events.user_group_user.Removed | An existing user is removed from a group | +| Verification Email Confirmed | v1.events.user.jit.email.Confirmed | Email verification confirmed by user | +| Verification Email Sent | v1.events.user.jit.email.Sent | Email verification sent to user created via JIT | + +### Project + +| Event Name | Event Type | Description | +| --------------- | ------------------------- | ------------------------ | +| Project Added | v1.events.project.Added | New project added | +| Project Changed | v1.events.project.Changed | Project settings changed | +| Project Removed | v1.events.project.Removed | Project is removed | + +### Permissions + +| Event Name | Event Type | Description | +| ----------------------- | ---------------------------- | ------------------------------ | +| User Permission Added | v1.events.permission.Added | New user permissions are added | +| User Permission Removed | v1.events.permission.Removed | User permissions are removed | + +### License + +| Event Name | Event Type | Description | +| ----------------------- | ------------------------------ | ----------------------------------------- | +| License Mapping Added | v1.events.license\_map.Added | New user license mapping is added | +| License Mapping Changed | v1.events.license\_map.Changed | User license mapping settings are changed | +| License Mapping Removed | v1.events.license\_map.Removed | User license mapping is removed | + +### Connection + +| Event Name | Event Type | Description | +| ------------------ | ---------------------------- | ------------------------------------------ | +| Connection Added | v1.events.connection.Added | New Data Warehouse connection added | +| Connection Changed | v1.events.connection.Changed | Data Warehouse Connection settings changed | +| Connection Removed | v1.events.connection.Removed | Data Warehouse connection removed | + +### Repository + +| Event Name | Event Type | Description | +| ------------------ | ---------------------------- | --------------------------- | +| Repository Added | v1.events.repository.Added | New repository added | +| Repository Changed | v1.events.repository.Changed | Repository settings changed | +| Repository Removed | v1.events.repository.Removed | Repository removed | + +### Credentials + +| Event Name | Event Type | Description | +| -------------------------------- | ----------------------------- | -------------------------------- | +| Credentials Added to Project | v1.events.credentials.Added | Project credentials added | +| Credentials Changed in Project | v1.events.credentials.Changed | Credentials changed in project | +| Credentials Removed from Project | v1.events.credentials.Removed | Credentials removed from project | + +## Searching the audit log + +You can search the audit log to find a specific event or actor, which is limited to the ones listed in [Events in audit log](#events-in-audit-log). The audit log successfully lists historical events spanning the last 90 days. You can search for an actor or event using the search bar, and then narrow your results using the time window. + +
+ + + +
+ +## Exporting logs + +You can use the audit log to export historical audit results for security, compliance, and analysis purposes. You can export data for up to the last 90 days. Click the **Export CSV** button to download a CSV file of all the events that occurred in your organization over the last 90 days. + +
+ + + +
diff --git a/website/docs/docs/dbt-cloud/dbt-cloud-enterprise/setting-up-enterprise-sso-with-azure-active-directory.md b/website/docs/docs/dbt-cloud/dbt-cloud-enterprise/setting-up-enterprise-sso-with-azure-active-directory.md index 803e3e52481..58aca1f5b10 100644 --- a/website/docs/docs/dbt-cloud/dbt-cloud-enterprise/setting-up-enterprise-sso-with-azure-active-directory.md +++ b/website/docs/docs/dbt-cloud/dbt-cloud-enterprise/setting-up-enterprise-sso-with-azure-active-directory.md @@ -19,7 +19,7 @@ Currently supported features include: ## Configuration -dbt Cloud supports both single tenant and multitenant Azure Active Directory SSO +dbt Cloud supports both single tenant and multi-tenant Azure Active Directory SSO Connections. For most Enterprise purposes, you will want to use the single tenant flow when creating an Azure AD Application. @@ -31,7 +31,7 @@ need to select the appropriate directory and then register a new application. 1. Under **Manage**, select **App registrations** 2. Click **+ New Registration** to begin creating a new application 3. Supply configurations for the **Name** and **Supported account types** - fields as shown in the table below. + fields as shown in the below. | Field | Value | | ----- | ----- | @@ -42,11 +42,6 @@ need to select the appropriate directory and then register a new application. Redirect URI values for single-tenant and multi-tenant deployments. For most enterprise use-cases, you will want to use the single-tenant Redirect URI. -:::note VPC Deployment -If you are deploying dbt Cloud into a VPC, you should use the hostname where -the dbt Cloud application is deployed instead of `https://cloud.getdbt.com` in -the **Redirect URI** input. -::: | Application Type | Redirect URI | | ----- | ----- | @@ -118,7 +113,7 @@ Under **Properties** check the toggle setting for **User assignment required?** 17. Click **+New client secret** 18. Name the client secret "dbt Cloud" (or similar) to identify the secret 19. Select **Never** as the expiration value for this secret -20. Click **Add** to finish creating the client secret +20. Click **Add** to finish creating the client secret value (not the client secret ID) 21. Record the generated client secret somewhere safe. Later in the setup process, we'll use this client secret in dbt Cloud to finish configuring the integration. @@ -139,33 +134,25 @@ Under **Properties** check the toggle setting for **User assignment required?** To complete setup, follow the steps below in the dbt Cloud application. -### Enable Azure AD Native Auth (beta) - -- For users accessing dbt Cloud at cloud.getdbt.com, contact your account manager to - gain access to the Azure AD Native auth configuration UI -- For users accessing dbt Cloud deployed in a VPC, enable the `native_azure` - feature flag in the dbt Cloud admin backend. - ### Supplying credentials -24. Navigate to the **Enterprise > Single Sign On** page under Account -Settings. +24. Go to [Settings](https://cloud.getdbt.com/next/settings/profile). On the left side, select **Single Sign On** under **Account Settings**. 25. Click the **Edit** button and supply the following SSO details: | Field | Value | | ----- | ----- | | **Log in with** | Azure AD Single Tenant | | **Client ID** | Paste the **Application (client) ID** recorded in the steps above | -| **Client Secret** | Paste the **Client Secret** recorded in the steps above | +| **Client Secret** | Paste the **Client Secret** (remember to use the Secret Value instead of the Secret ID) recorded in the steps above | | **Tenant ID** | Paste the **Directory (tenant ID)** recorded in the steps above | | **Domain** | Enter the domain name for your Azure directory (eg. `fishtownanalytics.com`). Only users with accounts in this directory with this primary domain will be able to log into the dbt Cloud application. Optionally, you may specify a CSV of domains which are _all_ authorized to access your dbt Cloud account (eg. `fishtownanalytics.com, fishtowndata.com`) Ensure that the domain(s) match the values configured on user accounts in Azure | | **Slug** | Enter your desired login slug. Users will be able to log into dbt Cloud by navigating to `https://cloud.getdbt.com/enterprise-login/`. Login slugs must be unique across all dbt Cloud accounts, so pick a slug that uniquely identifies your company. | - + 26. Click **Save** to complete setup for the Azure AD SSO integration. From - here, you can navigate to the URL generated for your account's _slug_ to + here, you can navigate to the login URL generated for your account's _slug_ to test logging in with Azure AD. :::success Logging in @@ -175,7 +162,7 @@ by navigating to the URL: `https://cloud.getdbt.com/enterprise-login/` ::: -*Note:* If your dbt account is configured with a single-tenant cloud or on-premise installation, the `cloud.getdbt.com` domain in the URL above will be replaced with a different value. +*Note:* If your dbt account is a VPC deployment, your login URL will use the domain supplied to you by your dbt Labs account team, instead of the domain `cloud.getdbt.com`. ## Setting up RBAC @@ -184,7 +171,7 @@ Now you have completed setting up SSO with Azure AD, the next steps will be to s ## Troubleshooting Tips -Ensure that the domain name under which user accounts exist in Azure matches the domain supplied in the SSO configuration on the dbt side. +Ensure that the domain name under which user accounts exist in Azure matches the domain you supplied in [Supplying credentials](#supplying-credentials) when you configured SSO. - + diff --git a/website/docs/docs/dbt-cloud/dbt-cloud-enterprise/setting-up-snowflake-sso.md b/website/docs/docs/dbt-cloud/dbt-cloud-enterprise/setting-up-snowflake-sso.md index f4c3733f8d8..2b1bad5a563 100644 --- a/website/docs/docs/dbt-cloud/dbt-cloud-enterprise/setting-up-snowflake-sso.md +++ b/website/docs/docs/dbt-cloud/dbt-cloud-enterprise/setting-up-snowflake-sso.md @@ -67,7 +67,7 @@ from Enter the Client ID and Client Secret into dbt Cloud to complete the creation of your Connection. - + ### Authorize Developer Credentials @@ -75,7 +75,7 @@ Once Snowflake SSO is enabled, users on the project will be able to configure th ### SSO OAuth Flow Diagram -![image](https://user-images.githubusercontent.com/46451573/84427818-841b3680-abf3-11ea-8faf-693d4a39cffb.png) + Once a user has authorized dbt Cloud with Snowflake via their identity provider, Snowflake will return a Refresh Token to the dbt Cloud application. dbt Cloud is then able to exchange this refresh token for an Access Token which can then be used to open a Snowflake connection and execute queries in the dbt Cloud IDE on behalf of users. @@ -91,6 +91,11 @@ If you are planning to set up the same Snowflake account to different dbt Cloud ### Troubleshooting #### Invalid consent request -When clicking on the `Connect Snowflake Account` successfully redirects you to the Snowflake login page, but you receive an `Invalid consent request` error, your Snowflake user may not have access to the Snowflake role defined on the development credentials in dbt Cloud. Double-check that you have access to that role and if the role name has been correctly entered in as Snowflake is case sensitive. +When clicking on the `Connect Snowflake Account` successfully redirects you to the Snowflake login page, but you receive an `Invalid consent request` error. This could mean: +* Your user might not have access to the Snowflake role defined on the development credentials in dbt Cloud. Double-check that you have access to that role and if the role name has been correctly entered in as Snowflake is case sensitive. +* You're trying to use a role that is in the [BLOCKED_ROLES_LIST](https://docs.snowflake.com/en/user-guide/oauth-partner.html#blocking-specific-roles-from-using-the-integration), such as `ACCOUNTADMIN`. +#### Server error 500 +If you experience a 500 server error when redirected from Snowflake to dbt Cloud, double check that you have whitelisted [dbt Cloud's IP addresses](https://docs.getdbt.com/docs/dbt-cloud/cloud-configuring-dbt-cloud/connecting-your-database) on a Snowflake account level. +Enterprise customers who have single-tenant deployments will have a different range of IP addresses (network CIDR ranges) to whitelist. diff --git a/website/docs/docs/dbt-cloud/dbt-cloud-enterprise/setting-up-sso-with-google-gsuite.md b/website/docs/docs/dbt-cloud/dbt-cloud-enterprise/setting-up-sso-with-google-gsuite.md index 56ffcc20418..f70b55c2921 100644 --- a/website/docs/docs/dbt-cloud/dbt-cloud-enterprise/setting-up-sso-with-google-gsuite.md +++ b/website/docs/docs/dbt-cloud/dbt-cloud-enterprise/setting-up-sso-with-google-gsuite.md @@ -49,7 +49,7 @@ Client Secret for use in dbt Cloud. | ---------------------- | ------------ | ------ | | **Application type** | internal | required | | **Application name** | dbt Cloud | required | -| **Application logo** | Download the logo here | optional | +| **Application logo** | Download the logo here | optional | | **Authorized domains** | `getdbt.com` | If deploying into a VPC, use the domain for your deployment | | **Scopes** | `email, profile, openid` | The default scopes are sufficient | @@ -105,10 +105,10 @@ Settings. - **Log in with**: GSuite - **Client ID**: Paste the Client ID generated in the steps above - **Client Secret**: Paste the Client Secret generated in the steps above - - **Domain in GSuite**: Enter the domain name for your GSuite account (eg. `fishtownanalytics.com`). + - **Domain in GSuite**: Enter the domain name for your GSuite account (eg. `dbtlabs.com`). Only users with an email address from this domain will be able to log into your dbt Cloud account using GSuite auth. Optionally, you may specify a CSV of domains - which are _all_ authorized to access your dbt Cloud account (eg. `fishtownanalytics.com, fishtowndata.com`) + which are _all_ authorized to access your dbt Cloud account (eg. `dbtlabs.com, fishtowndata.com`) - **Slug**: Enter your desired login slug. Users will be able to log into dbt Cloud by navigating to `https://cloud.getdbt.com/enterprise-login/`. Login slugs must be unique across all dbt Cloud accounts, so pick a slug that uniquely @@ -118,11 +118,12 @@ Settings. dropped into the GSuite OAuth flow and prompted to log into dbt Cloud with your work email address. If authentication is successful, you will be redirected back to the dbt Cloud application. -4. On the **Verify SSO Credentials** page, verify that a `groups` entry is +4. On the **Credentials** page, verify that a `groups` entry is present, and that it reflects the groups you are a member of in GSuite. If - you do not see a `groups` entry in the IdP attribute list, consult the - Troubleshooting steps below. - + you do not see a `groups` entry in the IdP attribute list, consult the following + Troubleshooting steps. + + If the verification information looks appropriate, then you have completed the configuration of GSuite SSO. Members of your team should now be able to log @@ -135,6 +136,12 @@ Now you have completed setting up SSO with GSuite, the next steps will be to set ## Troubleshooting +### Invalid client error + +If you experience an `Error 401: invalid_client` when authorizing with GSuite, double check that: + - The Client ID provided matches the value generated in the GCP API Credentials page. + - Ensure the Domain Name(s) provided matches the one(s) for your GSuite account. + ### OAuth errors If OAuth verification does not complete successfully, double check that: @@ -143,7 +150,7 @@ If OAuth verification does not complete successfully, double check that: GCP Credentials page - An Authorized Domain was provided in the OAuth Consent Screen configuration If authentication with the GSuite API succeeds but you do not see a -`groups` entry on the **Verify SSO Credentials** page, then you may not have +`groups` entry on the **Credentials** page, then you may not have permissions to access Groups in your GSuite account. Either request that your GSuite user is granted the ability to request groups from an administrator, or have an administrator log into dbt Cloud and authorize the GSuite integration. diff --git a/website/docs/docs/dbt-cloud/dbt-cloud-enterprise/setting-up-sso-with-okta.md b/website/docs/docs/dbt-cloud/dbt-cloud-enterprise/setting-up-sso-with-okta.md index d02ec323973..0fc27c5d8ef 100644 --- a/website/docs/docs/dbt-cloud/dbt-cloud-enterprise/setting-up-sso-with-okta.md +++ b/website/docs/docs/dbt-cloud/dbt-cloud-enterprise/setting-up-sso-with-okta.md @@ -52,7 +52,7 @@ Click **Create** to continue the setup process. On the **General Settings** page, enter the following details:: * **App name**: dbt Cloud -* **App logo** (optional): You can optionally [download the dbt logo](https://drive.google.com/file/d/1w_Yj7QK-ULP4ebtKbrbvGo04pWlg0Y7S/view), +* **App logo** (optional): You can optionally [download the dbt logo](https://www.getdbt.com/ui/img/dbt-icon.png), and upload it to Okta to use as the logo for this app. Click **Next** to continue. diff --git a/website/docs/docs/dbt-cloud/dbt-cloud-enterprise/setting-up-sso-with-saml-2.0.md b/website/docs/docs/dbt-cloud/dbt-cloud-enterprise/setting-up-sso-with-saml-2.0.md index db31d58a96b..2e007d0a9c4 100644 --- a/website/docs/docs/dbt-cloud/dbt-cloud-enterprise/setting-up-sso-with-saml-2.0.md +++ b/website/docs/docs/dbt-cloud/dbt-cloud-enterprise/setting-up-sso-with-saml-2.0.md @@ -21,46 +21,37 @@ provider in order to configure Single Sign On and [role-based access control](ac ## Generic SAML 2.0 integrations -_Use this section if you are configuring an identity provider besides Okta._ +You can use the instructions in this section to configure an identity provider besides Okta. -### Configuration in your identity provider +### Configure your identity provider -_Note: You'll need administrator access to your SAML 2.0 compliant identity provider to follow this guide. -This approach will work with any SAML 2.0 compliant identity provider._ +You'll need administrator access to your SAML 2.0 compliant identity provider to configure the identity provider. You can use the following instructions with any SAML 2.0 compliant identity provider. ### Creating the application -First, log into your SAML 2.0 identity provider and create a new application. -When promoted, configure the application with the following details: - - **Platform:** Web - - **Sign on method:** SAML 2.0 - - **App name:** dbt Cloud - - **App logo (optional):** You can optionally [download the dbt logo](https://drive.google.com/file/d/1fnsWHRu2a_UkJBJgkZtqt99x5bSyf3Aw/view?usp=sharing), and use as the logo for this app. +1. Log into your SAML 2.0 identity provider and create a new application. +2. When promoted, configure the application with the following details: + - **Platform:** Web + - **Sign on method:** SAML 2.0 + - **App name:** dbt Cloud + - **App logo (optional):** You can optionally [download the dbt logo](https://drive.google.com/file/d/1fnsWHRu2a_UkJBJgkZtqt99x5bSyf3Aw/view?usp=sharing), and use as the logo for this app. #### Configuring the application -:::info - -This guide assumes that your dbt Cloud instance is running at -https://cloud.getdbt.com. If your deployment is running at a different url, then -substitute cloud.getdbt.com for the url of your instance. - -::: +The following steps assume your dbt Cloud instance is running at `https://cloud.getdbt.com`. If your deployment is running at a different url, then substitute ` cloud.getdbt.com` for the url of your instance. To complete this section, you will need to create a login slug. This slug controls the URL where users on your account can log into your application. Login slugs are typically the lowercased name of your organization -separated with dashes. For example, the login slug for _dbt Labs_ would be _dbt-labs_. +separated with dashes. For example, the login slug for dbt Labs would be `dbt-labs`. Login slugs must be unique across all dbt Cloud accounts, so pick a slug that uniquely identifies your company. -When prompted for the SAML 2.0 application configurations, supply the following -values: +When prompted for the SAML 2.0 application configurations, supply the following values: - Single sign on URL: `https://cloud.getdbt.com/complete/saml` - Audience URI (SP Entity ID): `https://cloud.getdbt.com/` - Relay State: `` -Additionally, you may configure the IdP attributes passed from your identity -provider into dbt Cloud. We recommend using the following values: +Additionally, you may configure the IdP attributes passed from your identity provider into dbt Cloud. We recommend using the following values: | name | name format | value | description | @@ -75,15 +66,16 @@ use role-based access control in dbt Cloud, also configure your identity provider to provide group membership information in user attribute called `groups`: - | name | name format | value | description | | ---- | ----------- | ----- | ----------- | | groups | Unspecified | `` | The groups a user belongs to in the IdP | -Note: You may use a restricted group attribute statement to limit the groups set +:::info Note +You may use a restricted group attribute statement to limit the groups set to dbt Cloud for each authenticated user. For example, if all of your dbt Cloud groups start with `DBT_CLOUD_...`, you may optionally apply a filter like `Starts With: DBT_CLOUD_`. Please contact support if you have any questions. +::: ### Collect integration secrets @@ -101,10 +93,9 @@ After creating the Okta application, follow the instructions in the [dbt Cloud S section to complete the integration. ## Okta integration +You can use the instructions in this section to configure Okta as your identity provider. -_Use this section if you are configuring Okta as your identity provider_. - -First, log into your Okta account. Using the Admin dashboard, create a new app. +1. Log into your Okta account. Using the Admin dashboard, create a new app. -On the following screen, select the following configurations: -- **Platform**: Web -- **Sign on method**: SAML 2.0 +2. Select the following configurations: + - **Platform**: Web + - **Sign on method**: SAML 2.0 -Click **Create** to continue the setup process. +3. Click **Create** to continue the setup process. ` + * **Single sign on URL**: `https://cloud.getdbt.com/complete/okta` + * **Audience URI (SP Entity ID)**: `https://cloud.getdbt.com/` + * **Relay State**: `` - - -Use the **Attribute Statements** and **Group Attribute Statements** forms to -map your organization's Okta User and Group Attributes to the format that -dbt Cloud expects. + -Expected **User Attribute Statements**: +2. Map your organization's Okta User and Group Attributes to the format that +dbt Cloud expects by using the Attribute Statements and Group Attribute Statements forms. -| Name | Name format | Value | Description | -| -------------- | ----------- | -------------------- | -------------------------- | -| `email` | Unspecified | `${user.email}` | _The user's email address_ | -| `first_name` | Unspecified | `${user.firstName}` | _The user's first name_ | -| `last_name` | Unspecified | `${user.lastName}` | _The user's last name_ | +3. The following table illustrates expected User Attribute Statements: + | Name | Name format | Value | Description | + | -------------- | ----------- | -------------------- | -------------------------- | + | `email` | Unspecified | `${user.email}` | _The user's email address_ | + | `first_name` | Unspecified | `${user.firstName}` | _The user's first name_ | + | `last_name` | Unspecified | `${user.lastName}` | _The user's last name_ | -Expected **Group Attribute Statements**: +4. The following table illustrates expected **Group Attribute Statements**: -| Name | Name format | Filter | Value | Description | -| -------- | ----------- | ------------- | ----- | ------------------------------------- | -| `groups` | Unspecified | Matches regex | `.*` | _The groups that the user belongs to_ | + | Name | Name format | Filter | Value | Description | + | -------- | ----------- | ------------- | ----- | ------------------------------------- | + | `groups` | Unspecified | Matches regex | `.*` | _The groups that the user belongs to_ | -**Note:** You may use a more restrictive Group Attribute Statement than the -example shown above. For example, if all of your dbt Cloud groups start with +You can instead use a more restrictive Group Attribute Statement than the +example shown in the previous steps. For example, if all of your dbt Cloud groups start with `DBT_CLOUD_`, you may use a filter like `Starts With: DBT_CLOUD_`. **Okta only returns 100 groups for each user, so if your users belong to more than 100 IdP groups, you will need to use a more restrictive filter**. Please contact @@ -187,12 +172,13 @@ support if you have any questions. title="Configure the app's User and Group Attribute Statements" /> -Click **Next** to continue. +5. Click **Next** to continue. ### Finish Okta setup -Select *I'm an Okta customer adding an internal app*, and select *This is an -internal app that we have created*. Click **Finish** to finish setting up the +1. Select *I'm an Okta customer adding an internal app*. +2. Select *This is an internal app that we have created*. +3. Click **Finish** to finish setting up the app. +3. After creating the Okta application, follow the instructions in the [dbt Cloud Setup](#dbt-cloud-setup) +section to complete the integration. + +## Google integration + +Use this section if you are configuring Google as your identity provider. + +### Configure the Google application + +1. Sign into your **Google Admin Console** via an account with super administrator privileges. +2. From the Admin console Home page, go to **Apps** and then click **Web and mobile apps**. +3. Click **Add**, then click **Add custom SAML app**. +4. Click **Next** to continue. +5. Make these changes on the App Details page: + - Name the custom app + - Upload an app logo (optional) + - Click **Continue**. + +### Configure SAML Settings + +1. Go to the **Google Identity Provider details** page. +2. Download the **IDP metadata**. +3. Copy the **SSO URL** and **Entity ID** and download the **Certificate** (or **SHA-256 fingerprint**, if needed). +4. Enter the following values on the **Service Provider Details** window: + - **ACS URL**: `https://cloud.getdbt.com/complete/saml` + - **Audience URI (SP Entity ID)**: `https://cloud.getdbt.com/` + - **Start URL**: (if needed) +5. The default **Name ID** is the primary email. Multi-value input is not supported. +6. Use the **Attribute mapping** page to map your organization's Google Directory Attributes to the format that +dbt Cloud expects. +7. Click **Add another mapping** to map additional attributes. + +Expected **Attributes**: + +| Name | Name format | Value | Description | +| -------------- | ----------- | -------------------- | -------------------------- | +| `First name` | Unspecified | `first_name` | The user's first name. | +| `Last name` | Unspecified | `last_name` | The user's last name. | +| `Primary email`| Unspecified | `email` | The user's email address. | + +8. Click **Finish** to continue. + + +### Finish Google setup + +1. From the Admin console Home page, go to **Apps** and then click **Web and mobile apps**. +2. Select your SAML app. +3. Click **User access**. +4. To turn on or off a service for everyone in your organization, click **On for everyone** or **Off for everyone**, and then click **Save**. +5. Ensure that the email addresses your users use to sign in to the SAML app match the email addresses they use to sign in to your Google domain (Changes typically take effect in minutes, but can take up to 24 hours). + ### Finish setup -After creating the Okta application, follow the instructions in the [dbt Cloud Setup](#dbt-cloud-setup) -section to complete the integration. +After creating the Google application, follow the instructions in the [dbt Cloud Setup](#dbt-cloud-setup) +## Azure integration -## dbt Cloud Setup +If you're using Azure Active Directory (Azure AD), the instructions below will help you configure it as your identity provider. -### Providing IdP values +### Create Azure AD Enterprise application +Follow these steps to set up single sign-on (SSO) with dbt Cloud: -To complete setup, follow the steps below in dbt Cloud. First, navigate to the -**Enterprise > Single Sign On** page under Account Settings. Next, click -the **Edit** button and supply the following SSO details: +1. Log into your Azure account. +2. In the Azure AD portal, select **Enterprise applications** and click **+ New application**. +3. Select **Create your own application**. +4. Name the application "dbt Cloud" or another descriptive name. +5. Select **Integrate any other application you don't find in the gallery (Non-gallery)** as the application type. +6. Click **Create**. +7. You can find the new application by clicking **Enterprise applications** and selecting **All applications**. +8. Click the application you just created and follow the instructions for configuring it in [Configuring SAML endpoints in AD](#configuring-saml-endpoints-in-ad). +9. Select **Single sign-on** under Manage in the left navigation. +10. Click **Set up single sign on** under Getting Started. +11. Click **SAML** in "Select a single sign-on method" section. +12. Click **Edit** in the Basic SAML Configuration section. +13. Use the following table to complete the required fields and connect to dbt: -| Field | Value | -| ----- | ----- | -| Log in with | SAML 2.0 | -| Identity Provider SSO Url | Paste the **Identity Provider Single Sign-On URL** shown in the IdP setup instructions | -| Identity Provider Issuer | Paste the **Identity Provider Issuer** shown in the IdP setup instructions | -| X.509 Certificate | Paste the **X.509 Certificate** shown in the IdP setup instructions | -| Slug | Enter your desired login slug. | + | Field | Value | + | ----- | ----- | + | **Identifier (Entity ID)** | Base URL for dbt Cloud. Use `https://cloud.getdbt.com/` or `https://YOUR_COMPANY.getdbt.com/` for a single tenant instance. | + | **Reply URL (Assertion Consumer Service URL)** | Use `https://cloud.getdbt.com/complete/saml` or `https://YOUR_COMPANY.getdbt.com/complete/saml` for a single tenant instance. | + | **Relay State** | The slug you will configure in dbt Cloud. It's usually your company name, but you can pick anything you'd like. | +14. Click **Save** at the top of the form. - +#### Creating SAML Attributes in AD + +From the Set up Single Sign-On with SAML page: + +1. Click **Edit** in the User Attributes & Claims section. +2. Leave the claim under "Required claim" as is. +3. Delete all claims under "Additional claims." +4. Click **Add new claim** and add these three new claims: -Click **Save** to complete setup for the SAML 2.0 integration. + | Name | Source attribute | + | ----- | ----- | + | **email** | user.mail | + | **first_name** | user.givenname | + | **last_name** | user.surname | -### Test the integration -After setup is complete, you can navigate to the URL generated for your account's _slug_ to +5. Click **Add a group claim** from User Attributes and Claims. +6. If you'll assign users directly to the enterprise application, select **Security Groups**. If not, select **Groups assigned to the application**. +7. Set **Source attribute** to **Group ID**. +8. Under **Advanced options**, check **Customize the name of the group claim** and specify **Name** to **groups**. + +**Note:** Keep in mind that the Group ID in Azure AD maps to that group's GUID. It should be specified in lowercase for the mappings to work as expected. The Source Attribute field alternatively can be set to a different value of your preference. + + +9. After creating the Azure application, follow the instructions in the [dbt Cloud Setup](#dbt-cloud-setup) section to complete the integration. + +## dbt Cloud Setup + +### Providing IdP values to dbt Cloud + +To complete setup, follow the steps below in dbt Cloud: + +1. Navigate to the **Account Settings** and then click on **Single Sign On**. +2. Click **Edit** on the upper right corner. +3. Provide the following SSO details: + + | Field | Value | + | ----- | ----- | + | Log in with | SAML 2.0 | + | Identity Provider SSO Url | Paste the **Identity Provider Single Sign-On URL** shown in the IdP setup instructions | + | Identity Provider Issuer | Paste the **Identity Provider Issuer** shown in the IdP setup instructions | + | X.509 Certificate | Paste the **X.509 Certificate** shown in the IdP setup instructions | + | Slug | Enter your desired login slug. | + + +4. Click **Save** to complete setup for the SAML 2.0 integration. +5. After completing the setup, you can navigate to the URL generated for your account's _slug_ to test logging in with your identity provider. Additionally, users added the the SAML 2.0 app will be able to log in to dbt Cloud from the IdP directly. @@ -260,5 +344,7 @@ Users in your IdP will now be able to log into the application by navigating to `https://cloud.getdbt.com/enterprise-login/` ### Setting up RBAC + After configuring an identity provider, you will be able to set up [role-based access control](/access-control/enterprise-permissions) for your account. + diff --git a/website/docs/docs/dbt-cloud/dbt-cloud-enterprise/sso-overview.md b/website/docs/docs/dbt-cloud/dbt-cloud-enterprise/sso-overview.md index f47323fa886..14c0e57955e 100644 --- a/website/docs/docs/dbt-cloud/dbt-cloud-enterprise/sso-overview.md +++ b/website/docs/docs/dbt-cloud/dbt-cloud-enterprise/sso-overview.md @@ -37,3 +37,34 @@ The diagram below explains the basic process by which users are provisioned in d Then, assign all of these (and only these) to the user license. This step will also remove any permissions that the user should not have based on the current SSO group mappings. - **dbt Cloud Application**: After these steps, the user is redirected into the dbt Cloud application, and they can begin to use the application normally. +## SSO Enforcement + +:::info Security Update + +Please read the following update if you've enabled SSO but still have non-admin users logging in with a password. The changes outlined here will be released after September 15, 2022. + +::: + +Starting September 15, 2022, we will be making these security changes to SSO to increase the security posture of your environment: + +* **SSO Enforcement:** If you have SSO turned on in your organization, dbt Cloud will enforce SSO-only logins for all non-admin users. If an Account Admin already has a password, they can continue logging in with a password. +* **SSO Re-Authentication:** dbt Cloud will prompt you to re-authenticate using your SSO provider every 24 hours to ensure high security. + +### How should non-admin users log in? + +Non-admin users that currently login with a password will no longer be able to do so. They must login using the dbt Enterprise Login URL or an identity provider (IdP). For example, Okta, Azure AD, etc. + +### Security best practices + +There are a few scenarios that might require you to login with a password. We recommend these security best-practices for the two most common scenarios: +* **Onboarding partners and contractors** - We highly recommend that you add partners and contractors to your Identity Provider. IdPs like Okta and Azure Active Directory (AAD) offer capabilities explicitly for temporary employees. We highly recommend that you reach out to your IT team to provision an SSO license for these situations. Using an IdP highly secure, reduces any breach risk, and significantly increases the security posture of your dbt Cloud environment. +* **Identity Provider is down -** Account admins will continue to be able to log in with a password which would allow them to work with your Identity Provider to troubleshoot the problem. + +### Next steps for non-admin users currently logging in with passwords + +If you have any non-admin users logging into dbt Cloud with a password today: + +1. Ensure that all users have a user account in your identity provider and are assigned dbt Cloud so they won’t lose access. +2. Alert all dbt Cloud users that they won’t be able to use a password for logging in anymore unless they are already an Admin with a password. +3. We **DO NOT** recommend promoting any users to Admins just to preserve password-based logins because you will reduce security of your dbt Cloud environment. +** diff --git a/website/docs/docs/dbt-cloud/deployments/architecture.md b/website/docs/docs/dbt-cloud/deployments/architecture.md index f792f5f4727..53026b580cb 100644 --- a/website/docs/docs/dbt-cloud/deployments/architecture.md +++ b/website/docs/docs/dbt-cloud/deployments/architecture.md @@ -13,7 +13,7 @@ The dbt Cloud application is comprised of a set of static components, as well as #### Static Application Components -- **api gateway**: The api gateway is the entrypoint for all client requests to dbt Cloud. The api gateway serves static content, and contains logic for routing requests within the dbt Cloud application. +- **api gateway**: The API gateway is the entrypoint for all client requests to dbt Cloud. The api gateway serves static content, and contains logic for routing requests within the dbt Cloud application. - **app**: The app is the dbt Cloud application server. It consists of a Django application capable of serving dbt Cloud REST API requests. - **scheduler**: The scheduler is a continuously running process that orchestrates background jobs in dbt Cloud. It consists of two components: the scheduler container which provisions dynamic resources just-in-time, and the background cleanup container which performs maintenance tasks on the dbt Cloud database, including flushing logs from dbt runs out into the object store. @@ -32,7 +32,7 @@ In addition to the application components, there are a few critical dependencies ### Data Warehouse Interaction -dbt Cloud's primary role is as a data processor, not a data store. The dbt Cloud application enables users to dispatch SQL to the warehouse for transformation purposes. However, it is possible for users to dispatch SQL that returns customer data into the dbt Cloud application. This data is never persisted and will only exist in memory on the instance in question. In order to properly lock down customer data, it is critical that proper data warehouse permissioning is applied to prevent improper access or storage of sensitive data. +dbt Cloud's primary role is as a data processor, not a data store. The dbt Cloud application enables users to dispatch SQL to the warehouse for transformation purposes. However, it is possible for users to dispatch SQL that returns customer data into the dbt Cloud application. This data is never persisted and will only exist in memory on the instance in question. In order to properly lock down customer data, it is critical that proper permissioning is applied to prevent improper access or storage of sensitive data. ### Deployment Architecture diff --git a/website/docs/docs/dbt-cloud/january-2020-pricing-updates.md b/website/docs/docs/dbt-cloud/january-2020-pricing-updates.md index d68826789b9..a548d8b2a3d 100644 --- a/website/docs/docs/dbt-cloud/january-2020-pricing-updates.md +++ b/website/docs/docs/dbt-cloud/january-2020-pricing-updates.md @@ -37,4 +37,4 @@ The Team plan is built for teams collaborating on the analytics engineering work - 50 read only seats - API Access -Price: **$50/developer/month** \ No newline at end of file +Price: **$50/developer/month** diff --git a/website/docs/docs/dbt-cloud/on-premises/dependencies.md b/website/docs/docs/dbt-cloud/on-premises/dependencies.md index de07556fb06..4f50844e6a5 100644 --- a/website/docs/docs/dbt-cloud/on-premises/dependencies.md +++ b/website/docs/docs/dbt-cloud/on-premises/dependencies.md @@ -33,7 +33,7 @@ During initial installation, the KOTS appliance can be directly downloaded from - `quay.io`: Some dependencies of Replicated are hosted as public images in the Quay.io registry. - `hub.docker.com`: Some dependencies of Replicated are hosted as public images in Docker Hub. -Replicated maintains a list of Replicated-owned IPs for IP access restriction purposes at https://github.com/replicatedhq/ips/blob/master/ip_addresses.json. +Replicated maintains a list of Replicated-owned IPs for IP access restriction purposes at https://github.com/replicatedhq/ips/blob/main/ip_addresses.json. #### dbt Cloud Appliance Installation and Upgrades @@ -61,7 +61,7 @@ To install the dbt Cloud appliance or perform updates, some external connections ``` -Replicated maintains a list of Replicated-owned IPs for IP access restriction purposes at https://github.com/replicatedhq/ips/blob/master/ip_addresses.json. +Replicated maintains a list of Replicated-owned IPs for IP access restriction purposes at https://github.com/replicatedhq/ips/blob/main/ip_addresses.json. #### Ongoing Access diff --git a/website/docs/docs/dbt-cloud/on-premises/setup.md b/website/docs/docs/dbt-cloud/on-premises/setup.md index 1e0d9bf0516..b0823e6e655 100644 --- a/website/docs/docs/dbt-cloud/on-premises/setup.md +++ b/website/docs/docs/dbt-cloud/on-premises/setup.md @@ -85,7 +85,7 @@ Each user can have a specific role on each account. For more information on each A new version of dbt Cloud will appear on the Version History page in your Configuration Console anytime any of the following happen: -- A new version of the dbt Cloud code is released. This typically happens every two weeks, and each new version will be accompanied by a [changelog](/docs/dbt-cloud/cloud-changelog). +- A new version of the dbt Cloud code is released. This typically happens every two weeks, and each new version will be accompanied by a [changelog](/docs/dbt-cloud/release-notes). - Any configuration change is applied to your application via the Configuration Console. - Anytime an edit is applied to your Kubernetes configs via the overlays mechanism built into kots. diff --git a/website/docs/docs/dbt-cloud/on-premises/usage-statistics.md b/website/docs/docs/dbt-cloud/on-premises/usage-statistics.md index ad143e48b6e..aa7759aa4b1 100644 --- a/website/docs/docs/dbt-cloud/on-premises/usage-statistics.md +++ b/website/docs/docs/dbt-cloud/on-premises/usage-statistics.md @@ -21,7 +21,7 @@ Usage statistics are tracked once weekly, and include the following information: - The number of developer and read only licenses utilized in each account - The version of dbt Cloud installed in the on-premises environment -This information is sent as a JSON payload to usage.getdbt.com. A typical +This information is sent as a payload to usage.getdbt.com. A typical payload looks like: ```json diff --git a/website/docs/docs/dbt-cloud/release-notes.md b/website/docs/docs/dbt-cloud/release-notes.md new file mode 100644 index 00000000000..95a0d6b0a07 --- /dev/null +++ b/website/docs/docs/dbt-cloud/release-notes.md @@ -0,0 +1,13 @@ +--- +title: "dbt Cloud Release Notes" +id: "release-notes" +description: "Release notes for dbt Cloud" +--- + +dbt provides release notes for dbt Cloud so you can see recent and historical changes. Generally, you'll see release notes for these changes: + +* New products and features (new) +* Performance improvements and feature enhancements (enhancement) +* Bug fixes (fix) + +Release notes will be grouped by month. For customers using dbt Virtual Private Cloud, you will see a tag for changes available in your versioned release. diff --git a/website/docs/docs/dbt-cloud/release-notes/05-Sept-2022/liststeps-endpoint-deprecation.md b/website/docs/docs/dbt-cloud/release-notes/05-Sept-2022/liststeps-endpoint-deprecation.md new file mode 100644 index 00000000000..07eb72986f2 --- /dev/null +++ b/website/docs/docs/dbt-cloud/release-notes/05-Sept-2022/liststeps-endpoint-deprecation.md @@ -0,0 +1,15 @@ +--- +title: "List Steps API endpoint deprecation warning" +id: "liststeps-endpoint-deprecation.md" +description: "List Steps API deprecation" +sidebar_label: "Deprecation: List Steps API endpoint" +tags: [Sept-15-2022] +--- + +On October 14th, 2022 dbt Labs is deprecating the [List Steps](https://docs.getdbt.com/dbt-cloud/api-v2#tag/Runs/operation/listSteps) API endpoint. From October 14th, any GET requests to this endpoint will fail. Please prepare to stop using the List Steps endpoint as soon as possible. + +dbt Labs will continue to maintain the [Get Run](https://docs.getdbt.com/dbt-cloud/api-v2#tag/Runs/operation/getRunById) endpoint, which is a viable alternative depending on the use case. + +You can fetch run steps for an individual run with a GET request to the following URL: + +`https://cloud.getdbt.com/api/v2/accounts/{accountId}/runs/{runId}/?include_related=["run_steps"]` diff --git a/website/docs/docs/dbt-cloud/release-notes/05-Sept-2022/metadata-api-data-retention-limits.md b/website/docs/docs/dbt-cloud/release-notes/05-Sept-2022/metadata-api-data-retention-limits.md new file mode 100644 index 00000000000..ede9ba66793 --- /dev/null +++ b/website/docs/docs/dbt-cloud/release-notes/05-Sept-2022/metadata-api-data-retention-limits.md @@ -0,0 +1,11 @@ +--- +title: "Query the previous three months of data using the metadata API" +id: "metadata-api-data-retention-limits.md" +description: "Metadata API data retention limits" +sidebar_label: "Fix: Metadata API data retention limits" +tags: [Sept-29-2022] +--- + +In order to make the metadata API more scalable and improve its latency, we’ve implemented data retention limits. The metadata API can now query data from the previous three months. For example, if today was March 1, you could query data back to January 1st. + +For more information, see "[Metadata API](/docs/dbt-cloud/dbt-cloud-api/metadata/metadata-overview.md)" diff --git a/website/docs/docs/dbt-cloud/release-notes/06-Aug-2022/ide-improvement-beta.md b/website/docs/docs/dbt-cloud/release-notes/06-Aug-2022/ide-improvement-beta.md new file mode 100644 index 00000000000..9cb5827e9de --- /dev/null +++ b/website/docs/docs/dbt-cloud/release-notes/06-Aug-2022/ide-improvement-beta.md @@ -0,0 +1,36 @@ +--- +title: "Enhancement: New Cloud IDE beta" +id: "ide-improvements-beta.md" +description: "Adding IDE performance and reliability improvements" +sidebar_label: "Enhancement: New cloud IDE beta" +tags: [Aug-16-2022] +--- + +:::info Beta feature +Read more about the [Cloud IDE beta](https://www.getdbt.com/blog/staging-highlights-the-latest-from-dbt-labs/) and [submit your expression of interest](https://docs.google.com/forms/d/e/1FAIpQLSdlU65gqTZPyGAUc16SkxqTc50NO9vdq_KGx1Mjm_4FB_97FA/viewform) to join the new Cloud IDE beta group. + +::: + +Building code on the dbt Cloud integrated development environment (IDE) should be seamless, and the tool that you’re using should not add more distractions to the data work that is often already confusing and difficult. + +We're now excited to start rolling out the IDE Beta version, which focuses on performance and reliability improvements. + +The classic IDE currently has severe performance and reliability issues. It takes a long time to start up the IDE, and the interactions (saving or committing) are slow. + +Our focus is on performance and reliability, particularly around the following four metrics: + +- Spinner time for cold start = Time that you see a spinner in a brand new session. +- Spinner time for hot start = Time that you see a spinner when you resume an existing session (return within 3 hours). +- Time to save = Time between saving a file and the IDE being ready for edit. +- Time to git = Time between making a commit and the IDE being ready for edit. + +**Improvements:** + +To address the issue, we rebuilt the IDE and made some significant architectural changes to the way we work. These changes will help improve the IDE performance and reliability: + +- Your IDE spinner and interaction time will be faster, regardless of the size of your dbt project. + - Instead of fetching and downloading all the contents for the files during any change, the IDE only needs the file tree/name. This means that starting up the IDE should no longer depend on the size of the dbt project. This also helps make the interaction with the IDE (saving files and committing changes) more snappy. + +- Your IDE spinner time will be quicker as you can access it without needing to wait for the rpc server to finish getting ready. + + diff --git a/website/docs/docs/dbt-cloud/release-notes/06-Aug-2022/support-redshift-ra3.md b/website/docs/docs/dbt-cloud/release-notes/06-Aug-2022/support-redshift-ra3.md new file mode 100644 index 00000000000..b70783a2ed9 --- /dev/null +++ b/website/docs/docs/dbt-cloud/release-notes/06-Aug-2022/support-redshift-ra3.md @@ -0,0 +1,18 @@ +--- +title: "Enhancement: Support for cross-database sources on Redshift RA3 instances" +id: "support-redshift-ra3.md" +description: "Adding support for cross-database queries for RA3" +sidebar_label: "Enhancement: Support for RA3" +tags: [Aug-31-2022, 1.1.61.5] + +--- + +Cross-database queries for RA3 instances are now supported by dbt Cloud projects using a Redshift connection. + +With cross-database queries, you can seamlessly query data from any database in the cluster, regardless of which database you are connected to with dbt. + +The [connection configuration](https://docs.getdbt.com/reference/warehouse-profiles/redshift-profile) `ra3_node` has been defaulted to `true`. This allows users to: + +- benefit from the full RA3 nodes’ capabilities, +- generate appropriate dbt documentation. + diff --git a/website/docs/docs/dbt-cloud/release-notes/07-July-2022/render-lineage-feature.md b/website/docs/docs/dbt-cloud/release-notes/07-July-2022/render-lineage-feature.md new file mode 100644 index 00000000000..cc2478ee11e --- /dev/null +++ b/website/docs/docs/dbt-cloud/release-notes/07-July-2022/render-lineage-feature.md @@ -0,0 +1,16 @@ +--- +title: "Enhancement: Large DAG feature" +id: "render-lineage-feature" +description: "Add a render button to visualize large DAGs" +sidebar_label: "Enhancement: Large DAG feature" +tags: [July-5-2022, v1.1.56] + +--- + +You can now select **Render Lineage** to visualize large DAGs. + +Large DAGs can take a long time (10 or more seconds, if not minutes) to render and can cause browsers to crash. + +The new button prevents large DAGs from rendering automatically. Instead, you can select **Render Lineage** to load the visualization. This should affect about 15% of the DAGs. + + diff --git a/website/docs/docs/dbt-cloud/release-notes/08-May-2022/gitlab-auth.md b/website/docs/docs/dbt-cloud/release-notes/08-May-2022/gitlab-auth.md new file mode 100644 index 00000000000..d468f557fa2 --- /dev/null +++ b/website/docs/docs/dbt-cloud/release-notes/08-May-2022/gitlab-auth.md @@ -0,0 +1,11 @@ +--- +title: "Refresh expired access tokens in the IDE when using GitLab" +id: "gitlab-auth" +description: "Adding support for expiring OAuth access tokens." +sidebar_label: "Enhancement: Refreshing GitLab OAuth Access" +tags: [May-19-2022, v1.1.52] +--- + +On May 22, GitLab changed how they treat [OAuth access tokens that don't expire](https://docs.gitlab.com/ee/update/deprecations.html#oauth-tokens-without-expiration). We updated our IDE logic to handle OAuth token expiration more gracefully. Now, the first time your token expires after 2 hours of consecutive IDE usage, you will have to re-authenticate in GitLab to refresh your expired OAuth access token. We will handle subsequent refreshes for you if you provide the authorization when you re-authenticate. + +This additional security layer in the IDE is available only to the dbt Cloud enterprise plan. diff --git a/website/docs/docs/dbt-cloud/release-notes/09-April-2022/audit-log.md b/website/docs/docs/dbt-cloud/release-notes/09-April-2022/audit-log.md new file mode 100644 index 00000000000..610c0618ae2 --- /dev/null +++ b/website/docs/docs/dbt-cloud/release-notes/09-April-2022/audit-log.md @@ -0,0 +1,11 @@ +--- +title: "Audit log" +id: "audit-log" +description: "Review actions performed by people in your organization." +sidebar_label: "New: Audit log" + +tags: [April-26-2022] +--- + + +To review actions performed by people in your organization, dbt provides logs of audited user and system events. The dbt Cloud audit log lists events triggered in your organization within the last 90 days. The audit log includes details such as who performed the action, what the action was, and when it was performed. More details in the [docs](dbt-cloud/dbt-cloud-enterprise/audit-log). diff --git a/website/docs/docs/dbt-cloud/release-notes/09-April-2022/credentials-saved.md b/website/docs/docs/dbt-cloud/release-notes/09-April-2022/credentials-saved.md new file mode 100644 index 00000000000..971c83a4a2a --- /dev/null +++ b/website/docs/docs/dbt-cloud/release-notes/09-April-2022/credentials-saved.md @@ -0,0 +1,9 @@ +--- +title: "Credentials no longer accidentally wiped when editing an environment" +id: "credentials-saved" +description: "Credentials are now saved when editing an environment." +sidebar_label: "Fix: Credentials saved" +tags: [April-29-2022 v1.1.51] +--- + +We resolved a bug where when updating unencrypted fields (e.g. threads, schema name) in an environment setting would cause secret fields (e.g. password, keypair, credential details) to be deleted from that environment. Now users can freely update environment settings without fear of unintentionally wiping credentials. diff --git a/website/docs/docs/dbt-cloud/release-notes/09-April-2022/email-verification.md b/website/docs/docs/dbt-cloud/release-notes/09-April-2022/email-verification.md new file mode 100644 index 00000000000..4beff1b5506 --- /dev/null +++ b/website/docs/docs/dbt-cloud/release-notes/09-April-2022/email-verification.md @@ -0,0 +1,10 @@ +--- +title: "Email verification" +description: "dbt Cloud users created via SAML JIT will now confirm identity via email to activate their account." +sidebar_label: "New: Email verification" +sidebar_position: 1 + +tags: [April-26-2022, v1.1.48] +--- + +To enhance the security of user creation, dbt Cloud users created using SAML Just-in-Time (JIT) will now confirm identity via email to activate their account. Using email to confirm identity ensures the user still has access to the same email address they use to login via SAML. diff --git a/website/docs/docs/dbt-cloud/release-notes/09-April-2022/scheduler-improvements.md b/website/docs/docs/dbt-cloud/release-notes/09-April-2022/scheduler-improvements.md new file mode 100644 index 00000000000..02d3f1bf401 --- /dev/null +++ b/website/docs/docs/dbt-cloud/release-notes/09-April-2022/scheduler-improvements.md @@ -0,0 +1,9 @@ +--- +title: "Scheduler performance improvements" +id: "scheduler-improvements" +description: "scheduler, which has much faster prep times, especially at the top of the hour." +sidebar_label: "Improvement: Scheduler performance" +tags: [April-19-2022] +--- + +We rolled out our new distributed scheduler, which has much faster prep times, especially at the top of the hour. We share more about our work and improvements in our [product news blog post](https://www.getdbt.com/blog/a-good-problem-to-have/). diff --git a/website/docs/docs/dbt-cloud/release-notes/10-March-2022/ide-timeout-message.md b/website/docs/docs/dbt-cloud/release-notes/10-March-2022/ide-timeout-message.md new file mode 100644 index 00000000000..2f1fa321753 --- /dev/null +++ b/website/docs/docs/dbt-cloud/release-notes/10-March-2022/ide-timeout-message.md @@ -0,0 +1,13 @@ +--- +title: "Spotty internet issues no longer cause a session time out message" +id: "ide-timeout-message" +description: "We fixed an issue where a spotty internet connection could cause the “IDE session timed out” message to appear unexpectedly. People using a VPN were most likely to see this issue." +sidebar_label: "Fix: Session time out" +tags: [v1.1.47, March-10-2022] +--- + +We fixed an issue where a spotty internet connection could cause the “IDE session timed out” message to appear unexpectedly. People using a VPN were most likely to see this issue. + +We updated the health check logic so it now excludes client-side connectivity issues from the IDE session check. If you lose your internet connection, we no longer update the health-check state. Now, losing internet connectivity will no longer cause this unexpected message. + + diff --git a/website/docs/docs/dbt-cloud/release-notes/10-March-2022/prep-and-waiting-time.md b/website/docs/docs/dbt-cloud/release-notes/10-March-2022/prep-and-waiting-time.md new file mode 100644 index 00000000000..9ff5986b4da --- /dev/null +++ b/website/docs/docs/dbt-cloud/release-notes/10-March-2022/prep-and-waiting-time.md @@ -0,0 +1,12 @@ +--- +title: "Dividing queue time into waiting and prep time" +id: "prep-and-waiting-time" +description: "dbt Cloud now shows waiting time and prep time for a run." +sidebar_label: "Enhancement: Waiting time and prep time" + +tags: [v1.1.46, March-02-2022] +--- + +dbt Cloud now shows "waiting time" and "prep time" for a run, which used to be expressed in aggregate as "queue time". Waiting time captures the time dbt Cloud waits to run your job if there isn't an available run slot or if a previous run of the same job is still running. Prep time represents the time it takes dbt Cloud to ready your job to run in your cloud data warehouse. + + diff --git a/website/docs/docs/dbt-cloud/release-notes/11-February-2022/DAG-updates-more.md b/website/docs/docs/dbt-cloud/release-notes/11-February-2022/DAG-updates-more.md new file mode 100644 index 00000000000..57ef3b1a65a --- /dev/null +++ b/website/docs/docs/dbt-cloud/release-notes/11-February-2022/DAG-updates-more.md @@ -0,0 +1,13 @@ +--- +title: "DAG updates and performance improvements" +description: "Clicking a node in the DAG opens a model or config file in new tab in the IDE." +id: "DAG-updates-more" +sidebar_label: "DAG updates and more" +tags: [v1.1.44, February-02-2022] +--- + +Love the DAG in the IDE as much as we do? Now when you click on a node in the DAG, the model or config file will open as a new tab in the IDE, so you can directly view or edit the code. We'll continue to ship better developer ergonomic functionality throughout the year. + +#### Performance improvements and enhancements + +* Updated recommended dbt commands in the IDE to include dbt Core v1.0 commands, such as "build" and the "--select" argument. \ No newline at end of file diff --git a/website/docs/docs/dbt-cloud/release-notes/11-February-2022/service-tokens-more.md b/website/docs/docs/dbt-cloud/release-notes/11-February-2022/service-tokens-more.md new file mode 100644 index 00000000000..671608a803a --- /dev/null +++ b/website/docs/docs/dbt-cloud/release-notes/11-February-2022/service-tokens-more.md @@ -0,0 +1,17 @@ +--- +title: "Service tokens and bug fixes" +is: "service-tokens-more" +description: "Service tokens can now be assigned granular permissions to enforce least privilege access." +sidebar_label: "Service tokens and more" +tags: [v1.1.45, February-16-2022] +--- + +Service tokens can now be assigned granular permissions to enforce least privilege access. If you're on Enterprise, you can assign any enterprise permission set to newly issued service tokens. If you're on Teams, you can assign the Job Admin permission set to newly issued service tokens. We highly recommend you re-issue service tokens with these new permissions to increase your security posture! See docs [here](https://docs.getdbt.com/docs/dbt-cloud/dbt-cloud-api/service-tokens#permissions-for-service-account-tokens). + +#### New products and features + +- We are joining the [GitHub secret scanning partner program](https://docs.github.com/en/developers/overview/secret-scanning-partner-program) to better secure your token against accidental public exposure and potential fraudulent usage. + +#### Bug fixes + +- Credentials are no longer accidentally deleted when a user updates an environment setting. diff --git a/website/docs/docs/dbt-cloud/release-notes/12-January-2022/IDE-autocomplete-more.md b/website/docs/docs/dbt-cloud/release-notes/12-January-2022/IDE-autocomplete-more.md new file mode 100644 index 00000000000..f45fddddfd5 --- /dev/null +++ b/website/docs/docs/dbt-cloud/release-notes/12-January-2022/IDE-autocomplete-more.md @@ -0,0 +1,14 @@ +--- +title: "Autocomplete snippets for SQL and YAML files in IDE" +id: "ide-timeout-message" +description: "Autocomplete snippets for SQL and YAML files in IDE" +sidebar_label: "Autocomplete in IDE and more" +tags: [v1.1.43, January-19-2022] +--- + +Some noteworthy improvements include autocomplete snippets for sql and yaml files in the IDE, which are available for use now! We also added a [new metric layer page](https://docs.getdbt.com/docs/dbt-cloud/using-dbt-cloud/cloud-metrics-layer) to docs.getdbt.com to help you begin thinking about the metrics layer in dbt Cloud. + +#### Performance improvements and enhancements + +* Branch names now default to "main" instead of "master" in new managed and unmanaged Git repositories. +* Update IDE autocomplete snippets. diff --git a/website/docs/docs/dbt-cloud/release-notes/12-January-2022/model-timing-more.md b/website/docs/docs/dbt-cloud/release-notes/12-January-2022/model-timing-more.md new file mode 100644 index 00000000000..6f49fe5d336 --- /dev/null +++ b/website/docs/docs/dbt-cloud/release-notes/12-January-2022/model-timing-more.md @@ -0,0 +1,15 @@ +--- +title: "Model timing for Multi-tenant Team and Enterprise accounts" +id: "model-timing-more" +description: "Model timing is now available for Multi-tenant Team and Enterprise accounts, plus performance improvements." +sidebar_label: "Model timing and more" + +tags: [v1.1.42, January-05-2022] +--- +#### New products and features + +We started the new year with a gift! Multi-tenant Team and Enterprise accounts can now use the new [Model timing](https://docs.getdbt.com/docs/dbt-cloud/using-dbt-cloud/cloud-model-timing-tab) tab in dbt Cloud. You can use this tab to further explore long-running models to see if they need refactoring or rescheduling. + +#### Performance improvements and enhancements + +* We added client-side naming validation for file or folder creation. diff --git a/website/docs/docs/dbt-cloud/dbt-cloud-changelog.md b/website/docs/docs/dbt-cloud/release-notes/13-dbt-cloud-changelog-2019-2020.md similarity index 54% rename from website/docs/docs/dbt-cloud/dbt-cloud-changelog.md rename to website/docs/docs/dbt-cloud/release-notes/13-dbt-cloud-changelog-2019-2020.md index 18980d64e83..7da7dad0a98 100644 --- a/website/docs/docs/dbt-cloud/dbt-cloud-changelog.md +++ b/website/docs/docs/dbt-cloud/release-notes/13-dbt-cloud-changelog-2019-2020.md @@ -1,397 +1,13 @@ --- -title: "dbt Cloud - Changelog" -id: "cloud-changelog" -sidebar_label: Changelog -description: "Changelog for the dbt Cloud application" ---- -## dbt Cloud v1.1.38 (October 27, 2021) -Have you used the [Metadata API](https://docs.getdbt.com/docs/dbt-cloud/dbt-cloud-api/metadata/metadata-overview) yet? The Metadata API is available to customers on the Team and Enterprise plans, and with it, you can learn tons about your dbt project, if it's running dbt v0.19.0 or later. You can now query information about _any_ run, not just the last run of a job. Mo' data, mo' fun! - - -## dbt Cloud v1.1.37 (October 13, 2021) -dbt v0.21 is now available in dbt Cloud. The big change with this release is it introduces the `dbt build` command. `dbt build` logically does everything you'd want to do in your DAG. It runs your models, tests your tests, snapshots your snapshots, and seeds your seeds. It does this, resource by resource, from left to right across your DAG. dbt build is an opinionated task. It’s the culmination of all we’ve built- running models with resilient materializations, prioritizing data quality with tests, updating fixtures with seeds, capturing slowly changing dimensions with snapshot. Give it a try! - -#### New products and features -- We have a new beta feature, which we're calling Model Bottlenecks. It allows you to visually see how long it takes to build models in each run, so you can see clearly which models are taking the longest. If you're interested in learning more, check out #beta-feedback-model-bottlenecks in the dbt community Slack, and we can add you to the beta. - -## dbt Cloud v1.1.36 (September 29, 2021) -Check out the release candidate for `dbt v0.21.0`! Also tab switching in the dbt Cloud IDE now keeps track of your scroll position - at last! - -#### Bug fixes -- Some Redshift customers were experiencing timeouts on runs. We've since fixed this bug by keeping the session alive longer. - -#### Performance improvements and enhancements -- You won't lose track of the code snippets you were looking at when you switch back and forth between tabs in the dbt Cloud IDE, as we now keep track of your scroll position. - -## dbt Cloud v1.1.35 (September 15, 2021) -Have you ever been working in the IDE, taken a several hour break from developing, and when you returned to your work, the IDE started behaving in unexpected ways? Your develop session became inactive, without any notification. Well, that silent failure won’t happen anymore! dbt Cloud now will let you know when you have to refresh your IDE so you can continue to pick up work where you last left off. - -#### New products and features -- dbt v0.20.2 is released in dbt Cloud. - -#### Performance improvements and enhancements -- Set default threads to 4 for new jobs and in development creds. - -#### Bug fixes -- The user is now prompted to refresh the page when in a disconnected IDE state. -- dbt tasks that fail or error are now correctly ordered in the run drawer history. - - -## dbt Cloud v1.1.34 (September 1, 2021) -We just launched our beta for supporting environment variables in dbt Cloud. Environment variables are exciting because they allow you to clone private packages. If you’re interested in joining the beta, check out the #beta-feedback-for-env-vars channel in dbt Slack for more information. - -#### Performance improvements and enhancements -Our IDE SQL drawer got a fresh new look, and it now has improved accessibility. - - -## dbt Cloud v1.1.33 (August 18, 2021) -We added a DAG in the IDE, so that you can see your model dependencies as you develop! If you haven’t seen the DAG visualization yet, take a moment to spin up the IDE, navigate to the Lineage tab, and click-click-click around in there — it is legitimately a brand new modality for developing dbt projects, and it’s something worth being excited about! - -#### New products and features -- [Dashboard Status Tiles](https://docs.getdbt.com/docs/dbt-cloud/using-dbt-cloud/cloud-dashboard-status-tiles) can now be embedded on dashboards (or anywhere you can embed an iFrame) to give immediate insight into data freshness and quality. This helps dbt project maintainers build trust internally about the data that end users are seeing. -- We shipped DAG in the IDE to GA! -- Support for `dbt v0.20.1` in Cloud. - -#### Bug fixes -- Databricks users will now be able to see and update the token/schema for deployment environments. -- Some Github users were experiencing a broken profile image in dbt Cloud. This should be fixed if users disconnect and reconnect their Github accounts. - - -## dbt Cloud v1.1.32 (August 4, 2021) -The Metadata API is now in GA! When dbt Cloud invokes certain commands like run, test, seed, etc, dbt generates metadata in the form of [artifacts](https://docs.getdbt.com/reference/artifacts/dbt-artifacts). These artifacts give you tons of information about project set up, run times, test details, compiled SQL, and so much more. Now dbt Cloud serves a GraphQL API which supports arbitrary queries over these artifacts, so you can retrieve the metadata you want almost instantaneously. - -#### New products and features -- The Metadata API is the start of our metadata product suite. Learn more about how to use the Metadata API [here](https://docs.getdbt.com/docs/dbt-cloud/dbt-cloud-api/metadata/metadata-overview). -- dbt Enterprise customers using GitHub now get better fine grained access control in their dbt projects. dbt will enforce git permissions for every developer to ensure that read / write policies in GitHub carry through to the IDE. - - -## dbt Cloud v1.1.31 (July 21, 2021) -We’ve improved the tabbing experience in the IDE. Tabs now work much more intuitively, and you don’t have to worry about losing your work anymore! - -#### New products and features -- We are working to release a DAG directly in the IDE, so that when you’re developing, you have a clear idea of where the model you’re working on sits in the dependency graph. If you’re interested in testing out the feature early, head over to the `#beta-feedback-for-ide-dag` channel in the dbt Slack, and we’ll get the new product feature-flagged on your account! -- Added dbt 0.20.0 to Cloud - -#### Bug fixes -- Users will now be able to initialize any project that doesn't contain a `dbt_project.yml` file, regardless of whether or not there are pre-existing files and/or commits to that repo. - -#### Performance improvements and enhancements -- We've been working on some nice improvements to tabs in our IDE. We’ve fixed deficiencies with tabs that caused users to lose work if they didn’t hit save regularly enough. Additionally, opening, closing, and the order of the tabs work much more smoothly. -- You may have noticed that there is now a source freshness checkbox in your execution settings when you configure a job on dbt Cloud. Selecting this checkbox will run `dbt source freshness` as the first step in your job, but it will not break subsequent steps if it fails. Updated source freshness documentation available [here](https://docs.getdbt.com/docs/dbt-cloud/using-dbt-cloud/cloud-snapshotting-source-freshness). -- Added a new endpoint to allow API key rotation via `POST https://cloud.getdbt.com/api/v2/users/{user-id}/apiKey` - - -## dbt Cloud v1.1.30 (July 7, 2021) -We shipped a resizable folder pane in the IDE, and we're hearing great things! "My quality of life has greatly increased with this little update!" Hope this helps everyone else enjoy the IDE a little more too. - -#### New products and features -- Resizable folder pane in the IDE: Have you ever developed in the IDE and not been able to see the full name of your model because you couldn’t adjust the width of the file pane? Yeah, us too. Now you’ll be able to adjust your project’s file tree width to be as wide or as narrow as you’d like. It’s these small things that make developing in the IDE so much easier. - -#### Bug fixes -- Made some changes to GitLab webhooks so that the status of the dbt run gets properly updated in GitLab. -- Resolved an issue where users saw a blank screen rather than the SSO reauthentication page. - -#### Performance improvements and enhancements -- Refreshed the design of the repository import page. - - -## dbt Cloud v1.1.29 (June 23, 2021) -We're heads down working on a handful of new features that we're going to share at the end of this month. The finish line is in sight. In the meantime, check out our latest release candidates for dbt Core. The biggest changes are better tests, providing consistency, configurability, and persistence. Additionally, we've refactored partial parsing and introduced an experimental parser; both are set to off by default. - -#### New products and features -- Add support for latest Core release candidates to dbt Cloud: v0.19.2-rc2 and v0.20.0-rc1 - -#### Bug fixes -- Add a safeguard for the SSO reauth page to avoid 401 interceptors - -#### Performance improvements and enhancements -- Ensure navigation bar is in dark mode when IDE is set to dark mode - - -## dbt Cloud v1.1.28 (June 9, 2021) -We shipped a far better experience for GitLab users. Be sure to check out new CI features that are now available for customers using GitLab. Additionally, all developers should test out Slim CI which will speed up their model builds. - -#### New products and features - -- `Slim CI`: We’ve made Slim CI available for all our cloud customers! With Slim CI, you don't have to rebuild and test all your models; you can instruct dbt Cloud to run jobs on only modified or new resources. If you are a GitHub or GitLab user, try creating a new job that runs on pull requests and you can signal to dbt to run only on these modified resources by including the `state:modified+` argument. Read more about Slim CI [here](https://docs.getdbt.com/docs/dbt-cloud/using-dbt-cloud/cloud-enabling-continuous-integration-with-github#slim-ci). - -- Native GitLab authentication for dbt Cloud Developer and Team Tiers: We’ve shipped native GitLab auth into GA. You can now import new GitLab repos with a couple clicks, trigger CI builds when Merge Requests are opened in GitLab, and carry GitLab permissions through to dbt Cloud IDE's git actions. Read how to set up native GitLab auth [here](https://docs.getdbt.com/docs/dbt-cloud/cloud-configuring-dbt-cloud/connecting-gitlab). - -#### Bug fixes -- Allow users to select artifacts from a job that runs source freshness on jobs with the source freshness execution settings set to `ON`. -- Resolve `RUN ONLY ON CUSTOM BRANCH?` button to toggle on and off properly. -- Retain information in a `Statement` tab when the page is refreshed. -- Unsaved changes in the IDE are now saved when committing work. -- Drop temporary schemas in the data warehouse for closed or merged GitLab merge requests. - -#### Performance improvements and enhancements -- Behind the scenes, we’ve been moving off of Angular and onto React. We’ve started the process of migrating the central pieces of our UI over - the first of which is the main navigation. We think this will have a big impact on our ability to reduce UI bugs and improve user experience. -- Added support for dbt 0.19.2rc2 + 0.20.0rc1 in dbt Cloud. - - -## dbt Cloud v1.1.27 (May 26, 2021) - -A lot of improvements coming for GitLab webhooks and native auth. We also fixed a number of bugs in the IDE. Our goal is for you to never see an infinite spinner again! - -#### Enhancements - -- Add dbt v0.19.2rc1 and v0.20.0b1 -- Add an open/closable overlay for the DAG -- Disable department dropdown -- Add DAG flags, button, and tab context -- Add run source freshness option to jobs -- Implement conditional redirecting after GitLab app integration -- Add Develop Pod Support for Rook and Ceph file storage -- Show all common actions for valid top level commands - -#### Fixed - -- Fix link to documentation -- Disable the "Restart IDE" Button while the IDE is loading -- Continue canceling runs when we run into deleted accounts -- Fix SSO re-auth page -- Fix blank verify email page -- Resolve git refresh regression -- Fix missing "Run on Merge" button in Job creation/edit form- -- Warn users they have unsaved changes -- Updates test command suggestions and regex for common action suggestions -- Updates order of stylesheet import to fix missing border bug -- Fix GitLab PR link for Run Page -- Fix infinite spinner for missing environment or development credentials -- Fix infinite spinner when user is missing dev credentials -- Do not try to push if awaiting a merge -- Fix deleting schemas -- Fix favicon reference - -## dbt Cloud v1.1.26 (May 12, 2021) - -If you haven't seen it yet, spin up the IDE: the command bar now has recent actions (you can up-arrow like on the command line) as well as some hardcoded suggestions that will auto-populate your active model, if there is one. Check it out! Other fixes and adjustments as well, as we all get ready for Staging this Thursday - exciting week for the Product org over at ol' Fishtown! - -#### Enhancements - -- Made dbt default version on env 0.19.1 -- Rolled out new command line experience to all customers -- Post webhook triggered run status back to gitlab -- Temporary tabs can also populate the model from manifest -- Check command line content is minimally valid -- Allow user to restart server when develop pod crashes -- Prevent overflow of menu items - -#### Fixed - -- Handle validation error for improper remote URLs in the Scheduler -- Refactor exception logging out of GitRepo and into exception handlers -- Required tags returning null from core no longer causing infinite spinner -- Removed deleted repos while fetching repository for sending commit statuses -- Refactor git provider service -- Resolve files with special characters becoming forever dirty -- Disable input when RPC command running & add button when command bar is empty -- Updating button for the Cancel/Enter button on commandline -- Fix connection setup to always use the project referenced in the route -- Fix "View data sources" URL in environment page -- Add support for clicking on previously run commands and updating the text inside of the commandline -- Fix sources URL in environments page -- Fix metadata token not allowed API response - -## dbt Cloud v1.1.25 (April 28, 2021) - -Exciting things coming down the pipe - ongoing enhancements to the command bar experience in the IDE, doing some work to ensure that more git providers are presented with a first class experience in Cloud, as well as assorted bug fixes - "I must have bug fixes, always and always" - that was Monet I think - -#### Enhancements - -- Made a grip of visual updates to the new command bar work -- Moved to using the active model name instead of a placeholder in command bar work -- Added user ability to delete connections, remove association from a given project. -- Added verification of dbt version for command bar beta feature flag - -#### Fixed +title: "Changelog 2019 and 2020" +id: "dbt-cloud-changelog-2019-2020" +sidebar_label: Changelog (2019 and 2020) +description: "2019 and 2020 Changelog for the dbt Cloud application" -- Removed testing prop that keeps drawer open -- Added double encoding to handle Snowflake roles with spaces -- Fixed account switching in user notifications -- Handled invalid Azure SSO group responses -- Fixed error which only showed common actions when run drawer was closed -- Allowed unencrypted adapter fields to be edited -- Fixed bugs with file and folder renaming, alongside associated tab state - - -## dbt Cloud v1.1.24 (April 14, 2021) - -Phew! As our company grows, so too does our changelog! Look at all these! The big chunks you'll see here are related to some ongoing in-IDE work, focused on the command bar experience, as well as some partner & connection work (see the Gits, Databricks, and so forth), and of course ongoing longer-term bets around metadata! - -#### Enhancements - -- Added onFocus and onBlur properties to populate and remove "dbt" in command bar -- Enabled executing command on enter if user's cursor is in the command bar -- Added Metadata API access button to account settings -- Added feature flag for displaying only recent actions -- Added dbt 0.19.1 -- Added regex validation to Databrick's hostname web-form field -- Updated Connection Edit to allow adapter editing -- Enabled self-service Github and GitLab integration disconnection -- Added link to docs for license map & handle duplicate error gracefully -- Moved deferred job execution to execution settings. -- Recorded user command history -- Enabled new file creation flow - -#### Fixed - -- Added styling class to popup to ensure text is readable -- Fixed sourcemaps syntax for dev commands -- Added timeout and retry to dbt deps -- Updated databricks schema field type and add error handling to ConnectionSetup -- Fixed Bigquery private keys & convert text to textarea -- Fixed last used datetime in the service token UI -- Added missing token URI to Bigquery connection edit -- Prevent multiple develop sessions for one user -- Fixed SchemaForm validating non-displayed fields -- Fixed required fields for Bigquery connection JSON uploads -- Fixed self selection as deferred job -- Always create a Monaco model on tab open if no matching model exists -- Fixed tab dirty indicator on open tab -- Fixed password reset flow -- Fixed docs and sources links in dashboard page for read only users -- Fixed truncating first_name to 30 characters - - -## dbt Cloud v1.1.23 (March 31, 2021) - -Some backend work, some frontend work, some bug fixes: a nice mix for this release. A few user facing changes you may have noticed already are the persistence of dark/light mode settings across refresh (no more blinding IDE!), branches in the IDE being categorized by Active vs. Removed from Remote, and a tidier new file creation flow, with the file tree expanding to show the new file and opening a new tab to populate the said file! - -#### Enhancements - -- Splitting Local-only and Remote branches into different sections of the dropdown selector -- Update Profile Integrations to include SSO info -- Upgrade to Tailwind 2.0 and FUI 0.0.5 -- Allow users to create metadata tokens from the UI -- Support manually-managed group memberships -- SSO: resolve bug w/ first & last names acting up -- Integrate Delighted for NPS surveys -- Add dbt 0.19.1rc1 to Cloud -- Add an account-level setting to require users to re-authenticate via SSO -- Read-only metadata ServiceToken for Cloud -- Persist IDE light mode / dark mode across refresh -- Categorize & order git branches -- Improve new file creation flow - -#### Fixed - -- Check for an empty repository before checking matching remote -- Increase wait if run was finished recently -- Support default branches through git when a custom branch is not specified -- Don't download logs for skipped steps -- API Gateway is no longer flooded with errors due to IDE blindly polling dead Develop pod -- Fix user license creation via admin interface -- Adjusted addition of global .gitignore - - -## dbt Cloud v1.1.22 (March 17, 2021) - -Rolling out a few long-term bets to ensure that our beloved dbt Cloud does not fall over for want of memory, as well as a grip of bug fixes and error messaging improvements (error messages should be helpful, not scolding or baffling, after all!) - -#### Enhancements - -- Release Scribe to 100% of multi-tenant accounts -- Update language for SQL drawer empty state -- Reduce Scribe memory usage - -#### Fixed - -- Fix NoSuchKey error -- Guarantee unique notification settings per account, user, and type -- Fix for account notification settings -- Dont show deleted projects on notifications page -- Fix unicode error while decoding last_chunk -- Show more relevant errors to customers -- Groups are now editable by non-sudo requests -- Normalize domain names across inputs/outputs -- Redirect auth failed errors back to appropriate page with error description - - -## dbt Cloud v1.1.21 (March 3, 2021) - -This changelog wraps up work on what we've been calling the SQL Drawer in the IDE - some design nudges, some interface adjustments, overall a cleaner and snappier experience. If you haven't dipped into the IDE in a while it's worth taking a look! Some back-end work as well, making SSO and role based admin easier and more broadly available for Enterprise level folks, along with your usual assortment of bug squashes and iterations. - - -#### Enhancements - -- Styling and copy adjustments in the Cloud IDE -- Open self-service role based access control to all Enterprise customers -- Update AuthProvider UI to enable SAML and Okta -- Add a SAML auth redirect URL - -#### Fixed - -- Add param to admin project mapper to included soft deleted projects -- Fix delaying logs when we are waiting for a model to finish executing -- Saving GSuite auth provider form triggers an authorize -- Scribe populates truncated debug logs when runs are executing -- Delay attempts for non-200 status codes -- Add logic to support select fields in adapter UI -- Undo clobbering groups - - -## dbt Cloud v1.1.20 (February 17, 2021) - -Continued stability and quality of life improvements for folks with multiple accounts and projects - no longer will you have to remember the chronological order of birth of your accounts and projects, as they'll be ordered by the much easier to parse (for human brains anyway) alphabetical order. We're also shipping some experience improvements in the SQL Drawer at the bottom half of the IDE. - -#### Enhancements - -- Deleted Info and Logs IDE Tabs, logs will now be displayed in Results Tab -- Removed service token feature flag -- List Jobs dropdown in alphabetical order -- List Account and Project dropdowns in alphabetica order -- Pre-join Job Definition results to speed up scheduler -- Combine scheduler queries to speedup runtime by about 30% - -#### Fixed - -- Fix issue with source freshness for 0.19.0 - - -## dbt Cloud v1.1.19 (February 3, 2021) - -The latest release of dbt (Oh Nineteen Oh) is now available for your enjoyment on dbt Cloud! We're also releasing some service token pieces here, though they're not quite ready for wide release yet. Moving forward, Oh Nineteen Oh will probably end up being the minimum version required to run the Metadata API & Metadata Toolkit, so, this is a big release! - -#### Enhancements - -- Added dbt 0.19.0 :heart_eyes_cat: -- Allowed account-wide service tokens to create connections -- Added integration for service token UI and API -- Authorized requests that supply a service token - -#### Fixed - -- Added logic to show the entered service token name prior to the request completing -- Fixed endlessly running rpc queries with non-working cancel button on IDE refresh - - -## dbt Cloud v1.1.18 (January 20, 2021) - -Most notable things here are around foundational work toward future feature releases, as well as strong assurances of future stability for dbt Cloud, and ensuring future sales tax compliance (which we understand turns out to be quite important!) - turns out to be a quite future-looking release! - -#### Enhancements - -- Add service tokens UI (stubbed) behind a feature flag -- Fixing and Upgrading social-auth -- Add dbt Spark 0.19.0rc1 -- Adds the reconciliation of persisted file content and tab state when navigating into the IDE -- Adds the reconciliation of persisted file content and tab state between IDE sessions -- Read logs from scribe and stop logging to db -- Upgrade social auth 3.3.3 -- Add warning logs for social auth failures -- Add dbt 0.19.0rc1 - -#### Fixed - -- Prevent social-auth from updating first or last name -- Page through Stripe results when listing subscriptions -- Prevent enqueueing runs in deleted projects -- Fix IDE git actions causing open tab contents to be lost on IDE re-entry -- Add DBT_CLOUD_CONTEXT environment variable -- Add logic to hide IP whitelist message for on-prem customers -- fix 0.19.0rc1 run image dependencies +tags: [v1.1.16, v1.1.15, v1.1.14, v1.1.13, v1.1.12, v1.1.11, v1.1.10, v1.1.09, v1.1.08, v1.1.07, v1.1.06, v1.1.05, v1.1.04, v1.1.03, v1.1.02, v1.1.01, v0.5.0] +--- +Welcome to the 2019 and 2020 changelog for the dbt Cloud application! You can use this changelog to see the highlights of what was new, fixed, and enhanced during this time period. ## dbt Cloud v1.1.16 (December 23, 2020) @@ -581,7 +197,7 @@ initial support for a GitLab integration and self-service RBAC configuration. ## dbt Cloud v1.1.7 [September 3, 2020] This release adds a Release Candidate for [dbt -v0.18.0](migration-guide/upgrading-to-0-18-0) and +v0.18.0](/guides/migration/versions) and includes bugfixes and improvements to the Cloud IDE and job scheduler. @@ -629,7 +245,7 @@ significantly. - Add merge conflict resolution, a merge commit workflow, and merge abort workflow to the IDE - Deprecate dbt versions prior to 0.13.0 - Refactor to cut job scheduler loop time -- Reduce extra database calls to account table in job scheduler loop +- Reduce extra database calls to account in job scheduler loop - [On-premises] Allow clients to disable authentication for SMTP - [On-premises] Allow disabling of TLS for SMTP - [On-premises] Making k8s access mode for IDE pods an environment variable @@ -815,7 +431,7 @@ This release includes bugfixes around how permissions are applied to runs and ru - Fixed receiving arbitrary remote_url when creating a git url repository. - Fixed issue when handling non-resource specific errors from RPC server in IDE. - Fixed a bug where the scheduler would stop if the database went away. -- Fixed IDE query results table not supporting horizontal scrolling. +- Fixed IDE query results not supporting horizontal scrolling. #### Changed diff --git a/website/docs/docs/dbt-cloud/release-notes/14-dbt-cloud-changelog-2021.md b/website/docs/docs/dbt-cloud/release-notes/14-dbt-cloud-changelog-2021.md new file mode 100644 index 00000000000..fa8e5bf34ed --- /dev/null +++ b/website/docs/docs/dbt-cloud/release-notes/14-dbt-cloud-changelog-2021.md @@ -0,0 +1,420 @@ +--- +title: "Changelog 2021" +id: "dbt-cloud-changelog-2021" +sidebar_label: Changelog (2021) +description: "2021 Changelog for the dbt Cloud application" + +tags: [v1.1.41, v1.1.40, v1.1.39, v1.1.38, v1.1.37, v1.1.36, v1.1.35, v1.1.34, v1.1.33, v1.1.32, v1.1.31, v1.1.30, v1.1.29, v1.1.28, v1.1.27, v1.1.26, v1.1.25, v1.1.24, v1.1.23, v1.1.22, v1.1.21, v1.1.20, v1.1.19, v1.1.18] +--- + +Welcome to the 2021 changelog for the dbt Cloud application! You can use this changelog to see highlights of what was new, fixed, and enhanced. + +## dbt Cloud v1.1.41 (December 8, 2021) + +It's one of the best weeks of the year - it's [Coalesce](https://coalesce.getdbt.com/)! We'll have some exciting product announcements to share! Did somebody say [metrics](https://coalesce.getdbt.com/talks/keynote-metric-system/) and [dbt Core v1.0](https://coalesce.getdbt.com/talks/dbt-v10-reveal/)?! + +#### New products and features + +- dbt v1.0 is now available in dbt Cloud... nbd. + + +#### Performance improvements and enhancements + +- Now whenever you log back into dbt Cloud, you'll return to the account and project that you most recently were working in! + + +## dbt Cloud v1.1.39 (November 10, 2021) +We shipped environment variables in dbt Cloud. Environment variables create a way to separate code from configuration - allowing you to set config based on context and keep secrets like git tokens securely stored. + +#### New products and features +- You can now add environment variables to your dbt Cloud project. Why does this matter? Environment variables are a fundamental building block of a dbt project, which until now, we only enabled in dbt Core. They power many use cases such as cloning private packages, limiting the amount of data that is processed in development environments, changing your data sources depending on the environment, and more. Read about environment variables in our [blog post](https://blog.getdbt.com/introducing-environment-variables-in-dbt-cloud/) or [docs](https://docs.getdbt.com/docs/dbt-cloud/using-dbt-cloud/cloud-environment-variables). + + +## dbt Cloud v1.1.38 (October 27, 2021) +Have you used the [Metadata API](https://docs.getdbt.com/docs/dbt-cloud/dbt-cloud-api/metadata/metadata-overview) yet? The Metadata API is available to customers on the Team and Enterprise plans, and with it, you can learn tons about your dbt project, if it's running dbt v0.19.0 or later. You can now query information about _any_ run, not just the last run of a job. Mo' data, mo' fun! + + +## dbt Cloud v1.1.37 (October 13, 2021) +dbt v0.21 is now available in dbt Cloud. The big change with this release is it introduces the `dbt build` command. `dbt build` logically does everything you'd want to do in your DAG. It runs your models, tests your tests, snapshots your snapshots, and seeds your seeds. It does this, resource by resource, from left to right across your DAG. dbt build is an opinionated task. It’s the culmination of all we’ve built- running models with resilient materializations, prioritizing data quality with tests, updating fixtures with seeds, capturing slowly changing dimensions with snapshot. Give it a try! + +#### New products and features +- We have a new beta feature, which we're calling Model Bottlenecks. It allows you to visually see how long it takes to build models in each run, so you can see clearly which models are taking the longest. If you're interested in learning more, check out #beta-feedback-model-bottlenecks in the dbt community Slack, and we can add you to the beta. + +## dbt Cloud v1.1.36 (September 29, 2021) +Check out the release candidate for `dbt v0.21.0`! Also tab switching in the dbt Cloud IDE now keeps track of your scroll position - at last! + +#### Bug fixes +- Some Redshift customers were experiencing timeouts on runs. We've since fixed this bug by keeping the session alive longer. + +#### Performance improvements and enhancements +- You won't lose track of the code snippets you were looking at when you switch back and forth between tabs in the dbt Cloud IDE, as we now keep track of your scroll position. + +## dbt Cloud v1.1.35 (September 15, 2021) +Have you ever been working in the IDE, taken a several hour break from developing, and when you returned to your work, the IDE started behaving in unexpected ways? Your develop session became inactive, without any notification. Well, that silent failure won’t happen anymore! dbt Cloud now will let you know when you have to refresh your IDE so you can continue to pick up work where you last left off. + +#### New products and features +- dbt v0.20.2 is released in dbt Cloud. + +#### Performance improvements and enhancements +- Set default threads to 4 for new jobs and in development creds. + +#### Bug fixes +- The user is now prompted to refresh the page when in a disconnected IDE state. +- dbt tasks that fail or error are now correctly ordered in the run drawer history. + + +## dbt Cloud v1.1.34 (September 1, 2021) +We just launched our beta for supporting environment variables in dbt Cloud. Environment variables are exciting because they allow you to clone private packages. If you’re interested in joining the beta, check out the #beta-feedback-for-env-vars channel in dbt Slack for more information. + +#### Performance improvements and enhancements +Our IDE SQL drawer got a fresh new look, and it now has improved accessibility. + + +## dbt Cloud v1.1.33 (August 18, 2021) +We added a DAG in the IDE, so that you can see your model dependencies as you develop! If you haven’t seen the DAG visualization yet, take a moment to spin up the IDE, navigate to the Lineage tab, and click-click-click around in there — it is legitimately a brand new modality for developing dbt projects, and it’s something worth being excited about! + +#### New products and features +- [Dashboard Status Tiles](https://docs.getdbt.com/docs/dbt-cloud/using-dbt-cloud/cloud-dashboard-status-tiles) can now be embedded on dashboards (or anywhere you can embed an iFrame) to give immediate insight into data freshness and quality. This helps dbt project maintainers build trust internally about the data that end users are seeing. +- We shipped DAG in the IDE to GA! +- Support for `dbt v0.20.1` in Cloud. + +#### Bug fixes +- Databricks users will now be able to see and update the token/schema for deployment environments. +- Some Github users were experiencing a broken profile image in dbt Cloud. This should be fixed if users disconnect and reconnect their Github accounts. + + +## dbt Cloud v1.1.32 (August 4, 2021) +The Metadata API is now in GA! When dbt Cloud invokes certain commands like run, test, seed, etc, dbt generates metadata in the form of [artifacts](https://docs.getdbt.com/reference/artifacts/dbt-artifacts). These artifacts give you tons of information about project set up, run times, test details, compiled SQL, and so much more. Now dbt Cloud serves a GraphQL API which supports arbitrary queries over these artifacts, so you can retrieve the metadata you want almost instantaneously. + +#### New products and features +- The Metadata API is the start of our metadata product suite. Learn more about how to use the Metadata API [here](https://docs.getdbt.com/docs/dbt-cloud/dbt-cloud-api/metadata/metadata-overview). +- dbt Enterprise customers using GitHub now get better fine-grained access control in their dbt projects. dbt will enforce git permissions for every developer to ensure that read / write policies in GitHub carry through to the IDE. + + +## dbt Cloud v1.1.31 (July 21, 2021) +We’ve improved the tabbing experience in the IDE. Tabs now work much more intuitively, and you don’t have to worry about losing your work anymore! + +#### New products and features +- We are working to release a DAG directly in the IDE, so that when you’re developing, you have a clear idea of where the model you’re working on sits in the dependency graph. If you’re interested in testing out the feature early, head over to the `#beta-feedback-for-ide-dag` channel in the dbt Slack, and we’ll get the new product feature-flagged on your account! +- Added dbt 0.20.0 to Cloud + +#### Bug fixes +- Users will now be able to initialize any project that doesn't contain a `dbt_project.yml` file, regardless of whether or not there are pre-existing files and/or commits to that repo. + +#### Performance improvements and enhancements +- We've been working on some nice improvements to tabs in our IDE. We’ve fixed deficiencies with tabs that caused users to lose work if they didn’t hit save regularly enough. Additionally, opening, closing, and the order of the tabs work much more smoothly. +- You may have noticed that there is now a source freshness checkbox in your execution settings when you configure a job on dbt Cloud. Selecting this checkbox will run `dbt source freshness` as the first step in your job, but it will not break subsequent steps if it fails. Updated source freshness documentation available [here](https://docs.getdbt.com/docs/dbt-cloud/using-dbt-cloud/cloud-snapshotting-source-freshness). +- Added a new endpoint to allow API key rotation via `POST https://cloud.getdbt.com/api/v2/users/{user-id}/apiKey` + + +## dbt Cloud v1.1.30 (July 7, 2021) +We shipped a resizable folder pane in the IDE, and we're hearing great things! "My quality of life has greatly increased with this little update!" Hope this helps everyone else enjoy the IDE a little more too. + +#### New products and features +- Resizable folder pane in the IDE: Have you ever developed in the IDE and not been able to see the full name of your model because you couldn’t adjust the width of the file pane? Yeah, us too. Now you’ll be able to adjust your project’s file tree width to be as wide or as narrow as you’d like. It’s these small things that make developing in the IDE so much easier. + +#### Bug fixes +- Made some changes to GitLab webhooks so that the status of the dbt run gets properly updated in GitLab. +- Resolved an issue where users saw a blank screen rather than the SSO reauthentication page. + +#### Performance improvements and enhancements +- Refreshed the design of the repository import page. + + +## dbt Cloud v1.1.29 (June 23, 2021) +We're heads down working on a handful of new features that we're going to share at the end of this month. The finish line is in sight. In the meantime, check out our latest release candidates for dbt Core. The biggest changes are better tests, providing consistency, configurability, and persistence. Additionally, we've refactored partial parsing and introduced an experimental parser; both are set to off by default. + +#### New products and features +- Add support for latest Core release candidates to dbt Cloud: v0.19.2-rc2 and v0.20.0-rc1 + +#### Bug fixes +- Add a safeguard for the SSO reauth page to avoid 401 interceptors + +#### Performance improvements and enhancements +- Ensure navigation bar is in dark mode when IDE is set to dark mode + + +## dbt Cloud v1.1.28 (June 9, 2021) +We shipped a far better experience for GitLab users. Be sure to check out new CI features that are now available for customers using GitLab. Additionally, all developers should test out Slim CI which will speed up their model builds. + +#### New products and features + +- `Slim CI`: We’ve made Slim CI available for all our cloud customers! With Slim CI, you don't have to rebuild and test all your models; you can instruct dbt Cloud to run jobs on only modified or new resources. If you are a GitHub or GitLab user, try creating a new job that runs on pull requests and you can signal to dbt to run only on these modified resources by including the `state:modified+` argument. Read more about Slim CI [here](https://docs.getdbt.com/docs/dbt-cloud/using-dbt-cloud/cloud-enabling-continuous-integration-with-github#slim-ci). + +- Native GitLab authentication for dbt Cloud Developer and Team Tiers: We’ve shipped native GitLab auth into GA. You can now import new GitLab repos with a couple clicks, trigger CI builds when Merge Requests are opened in GitLab, and carry GitLab permissions through to dbt Cloud IDE's git actions. Read how to set up native GitLab auth [here](https://docs.getdbt.com/docs/dbt-cloud/cloud-configuring-dbt-cloud/connecting-gitlab). + +#### Bug fixes +- Allow users to select artifacts from a job that runs source freshness on jobs with the source freshness execution settings set to `ON`. +- Resolve `RUN ONLY ON CUSTOM BRANCH?` button to toggle on and off properly. +- Retain information in a `Statement` tab when the page is refreshed. +- Unsaved changes in the IDE are now saved when committing work. +- Drop temporary schemas in the data warehouse for closed or merged GitLab merge requests. + +#### Performance improvements and enhancements +- Behind the scenes, we’ve been moving off of Angular and onto React. We’ve started the process of migrating the central pieces of our UI over - the first of which is the main navigation. We think this will have a big impact on our ability to reduce UI bugs and improve user experience. +- Added support for dbt 0.19.2rc2 + 0.20.0rc1 in dbt Cloud. + + +## dbt Cloud v1.1.27 (May 26, 2021) + +A lot of improvements coming for GitLab webhooks and native auth. We also fixed a number of bugs in the IDE. Our goal is for you to never see an infinite spinner again! + +#### Enhancements + +- Add dbt v0.19.2rc1 and v0.20.0b1 +- Add an open/closable overlay for the DAG +- Disable department dropdown +- Add DAG flags, button, and tab context +- Add run source freshness option to jobs +- Implement conditional redirecting after GitLab app integration +- Add Develop Pod Support for Rook and Ceph file storage +- Show all common actions for valid top level commands + +#### Fixed + +- Fix link to documentation +- Disable the "Restart IDE" Button while the IDE is loading +- Continue canceling runs when we run into deleted accounts +- Fix SSO re-auth page +- Fix blank verify email page +- Resolve git refresh regression +- Fix missing "Run on Merge" button in Job creation/edit form- +- Warn users they have unsaved changes +- Updates test command suggestions and regex for common action suggestions +- Updates order of stylesheet import to fix missing border bug +- Fix GitLab PR link for Run Page +- Fix infinite spinner for missing environment or development credentials +- Fix infinite spinner when user is missing dev credentials +- Do not try to push if awaiting a merge +- Fix deleting schemas +- Fix favicon reference + +## dbt Cloud v1.1.26 (May 12, 2021) + +If you haven't seen it yet, spin up the IDE: the command bar now has recent actions (you can up-arrow like on the command line) as well as some hardcoded suggestions that will auto-populate your active model, if there is one. Check it out! Other fixes and adjustments as well, as we all get ready for Staging this Thursday - exciting week for the Product org over at ol' Fishtown! + +#### Enhancements + +- Made dbt default version on env 0.19.1 +- Rolled out new command line experience to all customers +- Post webhook triggered run status back to gitlab +- Temporary tabs can also populate the model from manifest +- Check command line content is minimally valid +- Allow user to restart server when develop pod crashes +- Prevent overflow of menu items + +#### Fixed + +- Handle validation error for improper remote URLs in the Scheduler +- Refactor exception logging out of GitRepo and into exception handlers +- Required tags returning null from core no longer causing infinite spinner +- Removed deleted repos while fetching repository for sending commit statuses +- Refactor git provider service +- Resolve files with special characters becoming forever dirty +- Disable input when RPC command running & add button when command bar is empty +- Updating button for the Cancel/Enter button on commandline +- Fix connection setup to always use the project referenced in the route +- Fix "View data sources" URL in environment page +- Add support for clicking on previously run commands and updating the text inside of the commandline +- Fix sources URL in environments page +- Fix metadata token not allowed API response + +## dbt Cloud v1.1.25 (April 28, 2021) + +Exciting things coming down the pipe - ongoing enhancements to the command bar experience in the IDE, doing some work to ensure that more git providers are presented with a first class experience in Cloud, as well as assorted bug fixes - "I must have bug fixes, always and always" - that was Monet I think + +#### Enhancements + +- Made a grip of visual updates to the new command bar work +- Moved to using the active model name instead of a placeholder in command bar work +- Added user ability to delete connections, remove association from a given project. +- Added verification of dbt version for command bar beta feature flag + +#### Fixed + +- Removed testing prop that keeps drawer open +- Added double encoding to handle Snowflake roles with spaces +- Fixed account switching in user notifications +- Handled invalid Azure SSO group responses +- Fixed error which only showed common actions when run drawer was closed +- Allowed unencrypted adapter fields to be edited +- Fixed bugs with file and folder renaming, alongside associated tab state + + +## dbt Cloud v1.1.24 (April 14, 2021) + +Phew! As our company grows, so too does our changelog! Look at all these! The big chunks you'll see here are related to some ongoing in-IDE work, focused on the command bar experience, as well as some partner & connection work (see the Gits, Databricks, and so forth), and of course ongoing longer-term bets around metadata! + +#### Enhancements + +- Added onFocus and onBlur properties to populate and remove "dbt" in command bar +- Enabled executing command on enter if user's cursor is in the command bar +- Added Metadata API access button to account settings +- Added feature flag for displaying only recent actions +- Added dbt 0.19.1 +- Added regex validation to Databrick's hostname web-form field +- Updated Connection Edit to allow adapter editing +- Enabled self-service Github and GitLab integration disconnection +- Added link to docs for license map & handle duplicate error gracefully +- Moved deferred job execution to execution settings. +- Recorded user command history +- Enabled new file creation flow + +#### Fixed + +- Added styling class to popup to ensure text is readable +- Fixed sourcemaps syntax for dev commands +- Added timeout and retry to dbt deps +- Updated databricks schema field type and add error handling to ConnectionSetup +- Fixed Bigquery private keys & convert text to textarea +- Fixed last used datetime in the service token UI +- Added missing token URI to Bigquery connection edit +- Prevent multiple develop sessions for one user +- Fixed SchemaForm validating non-displayed fields +- Fixed required fields for Bigquery connection JSON uploads +- Fixed self selection as deferred job +- Always create a Monaco model on tab open if no matching model exists +- Fixed tab dirty indicator on open tab +- Fixed password reset flow +- Fixed docs and sources links in dashboard page for read only users +- Fixed truncating first_name to 30 characters + + +## dbt Cloud v1.1.23 (March 31, 2021) + +Some backend work, some frontend work, some bug fixes: a nice mix for this release. A few user facing changes you may have noticed already are the persistence of dark/light mode settings across refresh (no more blinding IDE!), branches in the IDE being categorized by Active vs. Removed from Remote, and a tidier new file creation flow, with the file tree expanding to show the new file and opening a new tab to populate the said file! + +#### Enhancements + +- Splitting Local-only and Remote branches into different sections of the dropdown selector +- Update Profile Integrations to include SSO info +- Upgrade to Tailwind 2.0 and FUI 0.0.5 +- Allow users to create metadata tokens from the UI +- Support manually-managed group memberships +- SSO: resolve bug w/ first & last names acting up +- Integrate Delighted for NPS surveys +- Add dbt 0.19.1rc1 to Cloud +- Add an account-level setting to require users to re-authenticate via SSO +- Read-only metadata ServiceToken for Cloud +- Persist IDE light mode / dark mode across refresh +- Categorize & order git branches +- Improve new file creation flow + +#### Fixed + +- Check for an empty repository before checking matching remote +- Increase wait if run was finished recently +- Support default branches through git when a custom branch is not specified +- Don't download logs for skipped steps +- API Gateway is no longer flooded with errors due to IDE blindly polling dead Develop pod +- Fix user license creation via admin interface +- Adjusted addition of global .gitignore + + +## dbt Cloud v1.1.22 (March 17, 2021) + +Rolling out a few long-term bets to ensure that our beloved dbt Cloud does not fall over for want of memory, as well as a grip of bug fixes and error messaging improvements (error messages should be helpful, not scolding or baffling, after all!) + +#### Enhancements + +- Release Scribe to 100% of multi-tenant accounts +- Update language for SQL drawer empty state +- Reduce Scribe memory usage + +#### Fixed + +- Fix NoSuchKey error +- Guarantee unique notification settings per account, user, and type +- Fix for account notification settings +- Dont show deleted projects on notifications page +- Fix unicode error while decoding last_chunk +- Show more relevant errors to customers +- Groups are now editable by non-sudo requests +- Normalize domain names across inputs/outputs +- Redirect auth failed errors back to appropriate page with error description + + +## dbt Cloud v1.1.21 (March 3, 2021) + +This changelog wraps up work on what we've been calling the SQL Drawer in the IDE - some design nudges, some interface adjustments, overall a cleaner and snappier experience. If you haven't dipped into the IDE in a while it's worth taking a look! Some back-end work as well, making SSO and role based admin easier and more broadly available for Enterprise level folks, along with your usual assortment of bug squashes and iterations. + + +#### Enhancements + +- Styling and copy adjustments in the Cloud IDE +- Open self-service role based access control to all Enterprise customers +- Update AuthProvider UI to enable SAML and Okta +- Add a SAML auth redirect URL + +#### Fixed + +- Add param to admin project mapper to included soft deleted projects +- Fix delaying logs when we are waiting for a model to finish executing +- Saving GSuite auth provider form triggers an authorize +- Scribe populates truncated debug logs when runs are executing +- Delay attempts for non-200 status codes +- Add logic to support select fields in adapter UI +- Undo clobbering groups + + +## dbt Cloud v1.1.20 (February 17, 2021) + +Continued stability and quality of life improvements for folks with multiple accounts and projects - no longer will you have to remember the chronological order of birth of your accounts and projects, as they'll be ordered by the much easier to parse (for human brains anyway) alphabetical order. We're also shipping some experience improvements in the SQL Drawer at the bottom half of the IDE. + +#### Enhancements + +- Deleted Info and Logs IDE Tabs, logs will now be displayed in Results Tab +- Removed service token feature flag +- List Jobs dropdown in alphabetical order +- List Account and Project dropdowns in alphabetica order +- Pre-join Job Definition results to speed up scheduler +- Combine scheduler queries to speedup runtime by about 30% + +#### Fixed + +- Fix issue with source freshness for 0.19.0 + + +## dbt Cloud v1.1.19 (February 3, 2021) + +The latest release of dbt (Oh Nineteen Oh) is now available for your enjoyment on dbt Cloud! We're also releasing some service token pieces here, though they're not quite ready for wide release yet. Moving forward, Oh Nineteen Oh will probably end up being the minimum version required to run the Metadata API & Metadata Toolkit, so, this is a big release! + +#### Enhancements + +- Added dbt 0.19.0 :heart_eyes_cat: +- Allowed account-wide service tokens to create connections +- Added integration for service token UI and API +- Authorized requests that supply a service token + +#### Fixed + +- Added logic to show the entered service token name prior to the request completing +- Fixed endlessly running rpc queries with non-working cancel button on IDE refresh + + +## dbt Cloud v1.1.18 (January 20, 2021) + +Most notable things here are around foundational work toward future feature releases, as well as strong assurances of future stability for dbt Cloud, and ensuring future sales tax compliance (which we understand turns out to be quite important!) - turns out to be a quite future-looking release! + +#### Enhancements + +- Add service tokens UI (stubbed) behind a feature flag +- Fixing and Upgrading social-auth +- Add dbt Spark 0.19.0rc1 +- Adds the reconciliation of persisted file content and tab state when navigating into the IDE +- Adds the reconciliation of persisted file content and tab state between IDE sessions +- Read logs from scribe and stop logging to db +- Upgrade social auth 3.3.3 +- Add warning logs for social auth failures +- Add dbt 0.19.0rc1 + +#### Fixed + +- Prevent social-auth from updating first or last name +- Page through Stripe results when listing subscriptions +- Prevent enqueueing runs in deleted projects +- Fix IDE git actions causing open tab contents to be lost on IDE re-entry +- Add DBT_CLOUD_CONTEXT environment variable +- Add logic to hide IP whitelist message for on-prem customers +- fix 0.19.0rc1 run image dependencies + diff --git a/website/docs/docs/dbt-cloud/using-dbt-cloud/artifacts.md b/website/docs/docs/dbt-cloud/using-dbt-cloud/artifacts.md index 000dbd28330..b8a9f3bdbb2 100644 --- a/website/docs/docs/dbt-cloud/using-dbt-cloud/artifacts.md +++ b/website/docs/docs/dbt-cloud/using-dbt-cloud/artifacts.md @@ -1,26 +1,31 @@ --- -title: "Building and Configuring Artifacts" +title: "Building and configuring artifacts" id: "artifacts" +description: "Use artifacts to power your automated docs site and source freshness data." --- -## dbt Cloud Artifacts +When running dbt jobs, dbt Cloud generates and saves *artifacts*. You can use these artifacts, like `manifest.json`, `catalog.json`, and `sources.json` to power different aspects of dbt Cloud, namely: [dbt Docs](documentation) and [source freshness reporting](cloud-snapshotting-source-freshness). -When dbt Cloud runs dbt jobs, it generates and saves *artifacts*. These artifacts, like `manifest.json`, `catalog.json`, and `sources.json` are used to power different aspects of dbt Cloud, namely: [dbt Docs](documentation) and [source freshness reporting](cloud-snapshotting-source-freshness). +## Create dbt Cloud Artifacts -While every dbt Cloud job will produce artifacts, typically there is only one production job for a given project. If you select a production job on the Project Settings page, dbt Cloud will render links to the production Documentation and Source Freshness artifacts generated for that project in the nav sidebar. +While running any job can produce artifacts, you should only associate one production job with a given project to produce the project's artifacts. You can designate this connection in the **Project details** page. To access this page, click the gear icon in the upper right, select **Account Settings**, select your project, and click **Edit** in the lower right. Under **Artifacts**, select the jobs you want to produce documentation and source freshness artifacts for. - + -### Documentation +If you don't see your job listed, you might need to edit the job and select **Run source freshness** and **Generate docs on run**. + + -Once a job has been selected from the Documentation drop-down menu in your project settings, dbt Cloud's left-hand navbar will update to include a link to documentation for this job. This link will always point to the latest version of the documentation for your account! +When you add a production job to a project, dbt Cloud updates the content and provides links to the production documentation and source freshness artifacts it generated for that project. You can see these links by clicking **Deploy** in the upper left, selecting **Jobs**, and then selecting the production job. From the job page, you can select a specific run to see how artifacts were updated for that run only. +### Documentation +When set up, dbt Cloud updates the **Documentation** link in the upper left so it links to documentation for this job. This link always points to the latest version of the documentation for your account! ### Source Freshness -As with Documentation, configuring a job for the Source Freshness artifact setting will update dbt Cloud's left-hand navbar to include a link to the latest Source Freshness report for the selected job. +As with Documentation, configuring a job for the Source Freshness artifact setting also updates the Data Sources link under **Deploy**. The new link points to the latest Source Freshness report for the selected job. diff --git a/website/docs/docs/dbt-cloud/using-dbt-cloud/cloud-dashboard-status-tiles.md b/website/docs/docs/dbt-cloud/using-dbt-cloud/cloud-dashboard-status-tiles.md index 06855c2136b..564305834ec 100644 --- a/website/docs/docs/dbt-cloud/using-dbt-cloud/cloud-dashboard-status-tiles.md +++ b/website/docs/docs/dbt-cloud/using-dbt-cloud/cloud-dashboard-status-tiles.md @@ -1,6 +1,7 @@ --- -title: "Dashboard Status Tiles" +title: "Dashboard status tiles" id: "cloud-dashboard-status-tiles" +description: "Embed Status Tiles in your dashboards to provide consumers with contextual information about the quality and freshness of data." --- ## Overview @@ -51,3 +52,12 @@ Looker does not allow you to directly embed HTML, and instead requires creating - Once you have set up your custom visualization, you can use it on any dashboard! You can configure it with the exposure name, jobID, and token relevant to that dashboard. + +### Tableau +Tableau does not require you to embed an iFrame. You only need to use a Web Page object on your Tableau Dashboard and a URL in the following format: + +``` +https://metadata.cloud.getdbt.com/exposure-tile?name=&jobId=&token= +``` + + diff --git a/website/docs/docs/dbt-cloud/using-dbt-cloud/cloud-enabling-continuous-integration-with-github.md b/website/docs/docs/dbt-cloud/using-dbt-cloud/cloud-enabling-continuous-integration-with-github.md index 85978ca9470..83afc9cce33 100644 --- a/website/docs/docs/dbt-cloud/using-dbt-cloud/cloud-enabling-continuous-integration-with-github.md +++ b/website/docs/docs/dbt-cloud/using-dbt-cloud/cloud-enabling-continuous-integration-with-github.md @@ -1,103 +1,203 @@ --- -title: "Enabling CI" +title: "Enabling Continuous Integration (CI)" id: "cloud-enabling-continuous-integration" +description: "You can enable CI to test every single change prior to deploying the code to production just like in a software development workflow." --- ## Overview -dbt Cloud makes it easy to test every single change you make prior to deploying that code into production. Once you've [connected your GitHub account](cloud-installing-the-github-application) or [your GitLab account](connecting-gitlab), you can configure jobs to run when new Pull Requests (referred to as Merge Requests in GitLab) are opened against your dbt repo. When these jobs complete, their statuses will be shown directly in the Pull Request. This makes it possible to deploy new code to production with confidence. +dbt Cloud makes it easy to test every single code change you make prior to deploying that new logic into production. Once you've connected your [GitHub account](cloud-installing-the-github-application), [GitLab account](connecting-gitlab), or [Azure DevOps account](connecting-azure-devops), you can configure jobs to run when new pull requests are opened against your dbt repo. + +dbt Cloud will build the models affected by the new pull request code change in a temp schema, which acts as a quasi-staging environment, and will also run the tests that you've written for these models as a check. When the CI job completes, the run status will be shown directly in the pull request. This makes it possible to deploy new code to production with confidence. :::info Draft Pull Requests -Jobs will _not_ be triggered by draft Pull Requests. If you would like jobs to run on each new commit, please mark your Pull Request as `Ready for review`. +Jobs will _not_ be triggered by draft pull requests. If you would like jobs to run on each new commit, please mark your pull request as **Ready for review**. ::: -:::info GitLab Webhooks Compatability and Availability - -If you previously configured your dbt project by providing a GitLab git URL, you need to reconfigure the repository to connect through [native GitLab authentication](connecting-gitlab), as we cannot enable webhooks for your project through SSH. +:::info GitLab Compatibility GitLab Webhooks are available to only GitLab users who have a paid or self-hosted GitLab account. ::: -GitHub Example: - +:::info Common Errors +If you previously configured your dbt project by providing a generic git URL that clones using SSH, you need to [reconfigure the project](cloud-enabling-continuous-integration#reconnecting-your-dbt-project-to-use-dbt-clouds-native-integration-with-github-gitlab-or-azure-devops) to connect through dbt Cloud's native integration with GitHub, GitLab, or Azure DevOps instead. +::: + +## Understanding dbt Cloud Slim CI +When a [dbt Cloud CI job is set up](cloud-enabling-continuous-integration#configuring-a-dbt-cloud-ci-job), dbt Cloud will listen for webhooks from GitHub, GitLab, or Azure DevOps indicating that a new PR has been opened or updated with new commits. When one of these webhooks is received, dbt Cloud will enqueue a new run of the CI job. Crucially, this run will build into a temporary schema using the prefix `dbt_cloud_pr_`. This schema isolation acts as a quasi-staging environment, so that you can see the builds resulting from the code associated with the PR's commit sha. The unique schema name can be found in the run details for the given run, as shown below. -GitLab Example: - + -## Enabling Continuous Integration (CI) +After completing the dbt run, dbt Cloud will update the pull request in GitHub, GitLab, or Azure DevOps with a status message indicating the results of the run. The status message will state whether the models and tests ran successfully or not. You can enable a setting in your git provider that makes "successful pull request checks" a requirement to merge code. And finally, once the pull request is closed or merged, dbt Cloud will delete the temporary schema from your . -To enable runs on Pull Requests, navigate to the Job Settings page for the relevant job. In the "Triggers" section of the page, switch to the "Webhooks" tab, and then click the checkbox next to `RUN ON PULL REQUESTS?` as shown below. +### GitHub pull request example - +The green checkmark means the dbt builds and tests were successful. The *Details* link shown here will navigate you to the relevant CI run in dbt Cloud. + +### GitLab pull request example -## Understanding CI in dbt Cloud +The green checkmark means the dbt builds and tests were successful. Clicking the dbt Cloud pop up will navigate you to the relevant CI run in dbt Cloud. + -When Pull Request builds are enabled, dbt Cloud will listen for webhooks from GitHub or GitLab indicating that a new PR has been opened or updated with new commits. When one of these webhooks is received, dbt Cloud will enqueue a new run of the specified job. Crucially, this run will be configured to build into a special, [temporary schema](building-models/using-custom-schemas) using the prefix `dbt_cloud`. The name of these temporary schemas will be unique for each PR, and is shown in the Run Details page for the given run. This temporary schema will allow you to inspect the relations built by dbt Cloud, directly in your data warehouse. +### Azure DevOps pull request example - +The green checkmark means the dbt builds and tests were successful. Clicking **pipeline** navigates you to the relevant CI run in dbt Cloud. + -When the run is complete, dbt Cloud will update the PR in GitHub or MR in GitLab with a status message indicating the results of the run. Once the PR is closed or merged, dbt Cloud will delete the temporary schema from your data warehouse. +## Configuring a dbt Cloud CI job -## Slim CI +Setting up a CI job is very similiar to setting up a normal production job that runs on a schedule; however, a CI job has some noteable differences. -With Slim CI, you don't have to rebuild and test all your models. You can instruct dbt Cloud to run jobs on only modified or new resources. +There are a few components that define a Slim CI job. +- The Slim CI job must defer to a production job. +- The Slim CI job commands need to have a `state:modified+` selector to build only new or changed models and their downstream dependents. Importantly, state comparison can only happen when there is a deferred job seleted to compare state to. +- The Slim CI job must be triggered by pull request. -When creating or editing a job in dbt Cloud, you can set your execution settings to defer to a previous run state. Use the drop menu to select which **production** job you want to defer to. +#### Deferral and State Comparison + +When creating a job in dbt Cloud, you can set your execution settings to defer to a previous run state. Use the dropdown menu to select which *production* job you want to defer to. -When a job is selected, dbt Cloud will surface the artifacts from that job's most recent successful run. dbt will then use those artifacts to determine the set of new and modified resources. In your job commands, you can signal to dbt to run only on these modified resources and their children by including the `state:modified+` argument. +When a job is selected, dbt Cloud will look at the artifacts from that job's most recent successful run. dbt will then use those artifacts to determine the set of new and modified resources. + +In your job commands, you can signal to dbt to run only on these modified resources and their children by including the `state:modified+` argument. As example: ``` -dbt seed --select state:modified+ -dbt run --select state:modified+ -dbt test --select state:modified+ +dbt build --select state:modified+ ``` -Because dbt Cloud manages deferral and state environment variables, there is no need to specify `--defer` or `--state` flags. **Note:** Both jobs need to be running dbt v0.18.0 or newer. +Because dbt Cloud manages deferral and state environment variables, there is no need to specify `--defer` or `--state` flags. **Note:** Both jobs need to be running dbt v0.18.0 or later. To learn more about state comparison and deferral in dbt, read the docs on [state](understanding-state). -## Smart Reruns +#### Using a webhook trigger + +In the **Triggers** section of the jobs settings, switch to the **Webhooks** tab, and then check the box next to **Run on Pull Requests?** as shown below. + + + +This tells dbt Cloud to run the job whenever a pull request or commit is made, rather than on a schedule. Be sure to turn the schedule of the job off if you don't want it to also run on a time-based cadence. + + + +## Fresh Rebuilds + +As an extension of the Slim CI feature, dbt Cloud can rerun and retest only the things that are fresher compared to a previous run. + + -As an extension of the Slim CI feature, dbt Cloud can rerun and retest only the things that failed and had errors. +Only supported by v1.1 or newer. -When a job is selected, dbt Cloud will surface the artifacts from that job's most recent successful run. dbt will then use those artifacts to determine the set of error/fail resources. In your job commands, you can signal to dbt to run and test only on these error/fail results and their children by including the `result:error+` and `result:fail+` argument. + + + + +Only supported by v1.1 or newer. + +:::caution Experimental functionality +The `source_status` selection is experimental and subject to change. During this time, ongoing improvements may limit this feature’s availability and cause breaking changes to its functionality. +::: + +When a job is selected, dbt Cloud will surface the artifacts from that job's most recent successful run. dbt will then use those artifacts to determine the set of fresh sources. In your job commands, you can signal to dbt to run and test only on these fresher sources and their children by including the `source_status:fresher+` argument. This requires both previous and current state to have the `sources.json` artifact be available. Or plainly said, both job states need to run `dbt source freshness`. As example: ```bash -dbt build --select result:error+ result:fail+ +# Command step order +dbt source freshness +dbt build --select source_status:fresher+ ``` - -More example commands in [Pro-tips for workflows](/docs/guides/best-practices.md#pro-tips-for-workflows) + + +More example commands in [Pro-tips for workflows](/guides/legacy/best-practices.md#pro-tips-for-workflows). + +## Limitations + +If your temporary PR schemas aren't dropping after a merge or close of the PR, it's likely due to the below scenarios. Open and review the toggles below for recommendations on how to resolve this: + +
+ You used dbt Cloud environment variables in your connection settings page +
+
To resolve this, remove environment variables in your connections settings.
+
+
+
+ You have an empty/blank default schema +
+
To change this, edit and fill in your default schema.
+
+
+
+ You have overridden the generate_schema_name macro +
+
To resolve this, change your macro so that the temporary PR schema name contains the default prefix and review the guidance below: +

+ • ✅ Temporary PR schema name contains the prefix dbt_cloud_pr_ (like dbt_cloud_pr_123_456_marketing)

+ • ❌ Temporary PR schema name doesn't contain the prefix dbt_cloud_pr_ (like marketing).

+
+
+
+
+ You have overridden the generate_database_name macro +
+
If you assume that the project's default connection is to a database named analytics, review the guidance below to resolve this: +

+ • ✅ Database remains the same as the connection default (like analytics)

+ • ❌ Database has changed from the default connection (like dev).

+
+
+
+ + +Make the necessary changes to your project and double-check if the temporary PR schemas drop after a merge or close of the PR. ## Troubleshooting -### Reconnecting your dbt project to use a native GitHub or GitLab repo +### Reconnecting your dbt project to use dbt Cloud's native integration with GitHub, GitLab, or Azure DevOps -If your dbt project relies on a Git URL and SSH to connect to your GitHub or GitLab repo, you need to disconnect your repo and reconnect it with native Github or GitLab auth in order to enable webhooks. +If your dbt project relies the generic git clone method that clones using SSH and deploy keys to connect to your dbt repo, you need to disconnect your repo and reconnect it using the native GitHub, GitLab, or Azure DevOps integration in order to enable dbt Cloud Slim CI. -First, make sure you have [native GitHub authentication](cloud-installing-the-github-application) or [native GitLab authentication](connecting-gitlab) set up. After you have gone through those steps, head to `Account Settings` -> `Projects` and click on the project you'd like to reconnect through native GitHub or GitLab auth. Then click on the repository link. +First, make sure you have the [native GitHub authentication](cloud-installing-the-github-application), [native GitLab authentication](connecting-gitlab), or [native Azure DevOps authentication](connecting-azure-devops) set up depending on which git provider you use. After you have gone through those steps, head to **Account Settings**, select **Projects** and click on the project you'd like to reconnect through native GitHub, GitLab, or Azure DevOps auth. Then click on the repository link. -Once you're in the repository page, you can click the `Edit` button and then the `Disconnect Repository` button at the bottom. +Once you're in the repository page, click **Edit** and then click **Disconnect Repository** at the bottom. -Confirm that you'd like to disconnect your repository. You should then see a new `Configure a repository` link in your old repository's place. Click through to the configuration page, which will look like this: +Confirm that you'd like to disconnect your repository. You should then see a new **Configure a repository** link in your old repository's place. Click through to the configuration page: -Select the `GitHub` or `GitLab` tab and reselect your repository. That should complete the setup and enable you to use webhooks in your jobs configuration. +Select the **GitHub**, **GitLab**, or **AzureDevOps** tab and reselect your repository. That should complete the setup of the project and enable you to set up a dbt Cloud CI job. ### Error messages that refer to schemas from previous PRs If you receive a schema-related error message referencing a *previous* PR, this is usually an indicator that you are not using a production job for your deferral and are instead using *self*. If the prior PR has already been merged, the prior PR's schema may have been dropped by the time the Slim CI job for the current PR is kicked off. To fix this issue, select a production job run to defer to instead of self. + + +### Production job runs failing at the **Clone Git Repository** step + +dbt Cloud can only checkout commits that belong to the original repository. dbt Cloud _cannot_ checkout commits that belong to a fork of that repository. + +If you receive the following error message at the **Clone Git Repository** step of your job run: + +``` +Error message: +Cloning into '/tmp/jobs/123456/target'... +Successfully cloned repository. +Checking out to e845be54e6dc72342d5a8f814c8b3316ee220312... +Failed to checkout to specified revision. +git checkout e845be54e6dc72342d5a8f814c8b3316ee220312 +fatal: reference is not a tree: e845be54e6dc72342d5a8f814c8b3316ee220312 +``` + +Double-check that your PR isn't trying to merge using a commit that belongs to a fork of the repository attached to your dbt project. + diff --git a/website/docs/docs/dbt-cloud/using-dbt-cloud/cloud-environment-variables.md b/website/docs/docs/dbt-cloud/using-dbt-cloud/cloud-environment-variables.md index 9b239a8e079..42ba512e745 100644 --- a/website/docs/docs/dbt-cloud/using-dbt-cloud/cloud-environment-variables.md +++ b/website/docs/docs/dbt-cloud/using-dbt-cloud/cloud-environment-variables.md @@ -1,10 +1,11 @@ --- -title: Environment Variables +title: Environment variables id: "cloud-environment-variables" +description: "Use environment variables to customize the behavior of your dbt project." --- Environment variables can be used to customize the behavior of a dbt project depending on where the project is running. See the docs on -[env_var](dbt-jinja-functions/env_var) for more information on how to call the jinja function `{{env_var('DBT_KEY','OPTIONAL_DEFAULT')}}` in your project code. +[env_var](/reference/dbt-jinja-functions/env_var) for more information on how to call the jinja function `{{env_var('DBT_KEY','OPTIONAL_DEFAULT')}}` in your project code. :::info Environment Variable Naming and Prefixing Environment variables in dbt Cloud must be prefixed with either `DBT_` or `DBT_ENV_SECRET_`. Environment variables keys are uppercased and case sensitive. When referencing `{{env_var('DBT_KEY')}}` in your project's code, the key must match exactly the variable defined in dbt Cloud's UI. @@ -27,7 +28,7 @@ There are four levels of environment variables: **Setting environment variables at the project and environment level** -To set environment variables at the project and environment level, head over to the Environments section in your main navigation pane. You'll see a view to list all your environments and a view to set and update environment variables. Make sure you're in the environment variable view. +To set environment variables at the project and environment level, click **Deploy** in the top left, then select **Environments**. Click **Environments Variables** to add and update your environment variables. @@ -35,8 +36,7 @@ To set environment variables at the project and environment level, head over to You'll notice there is a `Project Default` column. This is a great place to set a value that will persist across your whole project, independent of where the code is run. We recommend setting this value when you want to supply a catch-all default or add a project-wide token or secret. - -To the right of the `Project Default` column are all your environments. Values set at the environment level take priority over the project level default value. This is where you can tell dbt Cloud to intepret an environment value differently in your Staging vs. Production environment, as example. +To the right of the `Project Default` column are all your environments. Values set at the environment level take priority over the project level default value. This is where you can tell dbt Cloud to interpret an environment value differently in your Staging vs. Production environment, as example. @@ -46,7 +46,7 @@ To the right of the `Project Default` column are all your environments. Values s You may have multiple jobs that run in the same environment, and you'd like the environment variable to be interpretted differently depending on the job. -When setting up or editing a job, you will see a button in the Environment section to `Set Environment Variables`. Clicking on that button will take you to a section where you can override environment variable values set at the environment or project level. +When setting up or editing a job, you will see a section where you can override environment variable values defined at the environment or project level. @@ -59,7 +59,7 @@ Every job runs in a specific, deployment environment, and by default, a job will **Overriding environment variables at the personal level** -Developers may also want to set a personal value override for an environment variable while developing in the dbt IDE. By default, dbt Cloud will look to use environment variable values set in the project's development environment. To see and override these values, developers should head to their Profile and then select their project under Credentials and scroll to the Environment Variables section. +You can also set a personal value override for an environment variable when you develop in the dbt integrated developer environment (IDE). By default, dbt Cloud uses environment variable values set in the project's development environment. To see and override these values, click the gear icon in the top right. Under "Your Profile," click **Credentials** and select your project. Click **Edit** and make any changes in "Environment Variables." @@ -83,12 +83,12 @@ There are some known issues with partial parsing of a project and changing envir ### Handling secrets -While all environment variables are encrypted at rest in dbt Cloud, dbt Cloud has additional capabilities for managing environment variables with secret or otherwise sensitive values. If you want a particular environment variable to be scrubbed from all logs and error messages, in addition to obfuscating the value in the UI, you can prefix the key with `DBT_ENV_SECRET_`. This functionality is supported from `dbt v0.21.0` and on. +While all environment variables are encrypted at rest in dbt Cloud, dbt Cloud has additional capabilities for managing environment variables with secret or otherwise sensitive values. If you want a particular environment variable to be scrubbed from all logs and error messages, in addition to obfuscating the value in the UI, you can prefix the key with `DBT_ENV_SECRET_`. This functionality is supported from `dbt v1.0` and on. -**Note**: An environment variable can be used to store a [git token for repo cloning](/cloud-environment-variables#clone-private-packages). We recommend you make the git token's permissions read only in order to practice good security hygiene. If a user were to unintentionally write the environment variable storing the token to the database, the token would be exposed. +**Note**: An environment variable can be used to store a [git token for repo cloning](/cloud-environment-variables#clone-private-packages). We recommend you make the git token's permissions read only and consider using a machine account or service user's PAT with limited repo access in order to practice good security hygiene. ### Special environment variables @@ -101,7 +101,7 @@ dbt Cloud has a number of pre-defined variables built in. The following environm - `DBT_CLOUD_PROJECT_ID`: The ID of the dbt Cloud Project for this run - `DBT_CLOUD_JOB_ID`: The ID of the dbt Cloud Job for this run - `DBT_CLOUD_RUN_ID`: The ID of this particular run -- `DBT_CLOUD_RUN_REASON_CATEGORY`: The "category" of the trigger for this run (one of: `scheduled`, `github_pull_request`, `gitlab_merge_request`, `other`) +- `DBT_CLOUD_RUN_REASON_CATEGORY`: The "category" of the trigger for this run (one of: `scheduled`, `github_pull_request`, `gitlab_merge_request`, `azure_pull_request`, `other`) - `DBT_CLOUD_RUN_REASON`: The specific trigger for this run (eg. `Scheduled`, `Kicked off by `, or custom via `API`) **Git details** diff --git a/website/docs/docs/dbt-cloud/using-dbt-cloud/cloud-generating-documentation.md b/website/docs/docs/dbt-cloud/using-dbt-cloud/cloud-generating-documentation.md index dc8590b2cad..31f3f95c430 100644 --- a/website/docs/docs/dbt-cloud/using-dbt-cloud/cloud-generating-documentation.md +++ b/website/docs/docs/dbt-cloud/using-dbt-cloud/cloud-generating-documentation.md @@ -1,19 +1,41 @@ --- -title: "Generating Documentation" +title: "Generating documentation in dbt Cloud" id: "cloud-generating-documentation" +description: "Automatically generate project documentation as you run jobs." --- -## Enabling documentation +dbt enables you to generate documentation for your project and data warehouse, and renders the documentation in a website. For more information, see [Documentation](/docs/building-a-dbt-project/documentation). -Documentation can be enabled for a job in dbt Cloud by checking the "Generate docs?" checkbox on the Job Settings page, as shown below. Once this setting is enabled, subsequent runs of the job will automatically include a step to generate documentation. +## Set up a documentation job - +You can set up documentation for a job in dbt Cloud when you edit your job settings or create a new job. You need to configure the job to generate docs when it runs, then link that job to your project. + +To set up a job to generate docs: + +1. In the top left, click **Deploy** and select **Jobs**. +2. Create a new job or select an existing job and click **Settings**. +3. Under "Execution Settings," select **Generate docs on run**. + + +4. Click **Save**. Proceed to [configure project documentation](#configure-project-documentation) so your project generates the documentation when this job runs. + + +## Configure project documentation + +You configure project documentation to generate documentation when the job you set up in the previous section runs. In the project settings, specify the job that generates documentation artifacts for that project. Once you configure this setting, subsequent runs of the job will automatically include a step to generate documentation. + +1. Click the gear icon in the top right. +2. Select **Projects** and click the project that needs documentation. +3. Click **Edit**. +4. Under "Artifacts," select the job that should generate docs when it runs. + +5. Click **Save**. ## Viewing documentation -To view the latest documentation for a job, click the "View Latest Documentation" button from the Job Details page. This link will always navigate you to the most recent version of your project's documentation in dbt Cloud. +Once you have a job set up to generate documentation for your project, then click **Documentation** in the top left. Your project's documentation should open. This link will always navigate you to the most recent version of your project's documentation in dbt Cloud. - + ## Easy access diff --git a/website/docs/docs/dbt-cloud/using-dbt-cloud/cloud-metrics-layer.md b/website/docs/docs/dbt-cloud/using-dbt-cloud/cloud-metrics-layer.md new file mode 100644 index 00000000000..ca4d4e2f007 --- /dev/null +++ b/website/docs/docs/dbt-cloud/using-dbt-cloud/cloud-metrics-layer.md @@ -0,0 +1,18 @@ +--- +title: "What is the dbt metrics layer?" +id: "cloud-metrics-layer" +description: "The dbt metrics layer helps you standardize metrics within your organization." +keywords: + - dbt metrics layer +--- + +[dbt metrics](/docs/building-a-dbt-project/metrics) ensure metric consistency and provide a way to standardize metrics under version control in dbt projects. By abstracting metrics calculations out of pre-aggregated tables or specific business intelligence tools (BI tools), dbt metrics can be defined once and used everywhere. Defining metrics in one place ensures consistent reporting of key business metrics especially in an environment where metric definitions and dimensions are changing along with your business. + +The data models that power these metrics already exist in your dbt project. You can use dbt metrics in different ways: + +* High-level view of your most important key performance indicators (KPIs), such as weekly active users, revenue, or time-on-site. +* Drilled-down view of the core entities that comprise those metrics, such as users, orders, or pageviews. + +While dbt does not currently provide a BI experience for exploring these metrics, we’re working on a number of integrations with BI partners that will help unlock the full value of the metrics layer. + +If you’re interested in taking metrics for a spin or integrating your product with dbt metrics, you can [sign up for the beta!](https://docs.google.com/forms/d/1MjVfD3rLg2hpjEbOaaocnjGtUdNY-wNpoyy1aHL_x9o/viewform) diff --git a/website/docs/docs/dbt-cloud/using-dbt-cloud/cloud-model-timing-tab.md b/website/docs/docs/dbt-cloud/using-dbt-cloud/cloud-model-timing-tab.md new file mode 100644 index 00000000000..8f09d9dfb34 --- /dev/null +++ b/website/docs/docs/dbt-cloud/using-dbt-cloud/cloud-model-timing-tab.md @@ -0,0 +1,21 @@ +--- +title: "Model timing tab" +id: "cloud-model-timing-tab" +description: "Visually explore runs and identify long-running models with the model timing dashboard." +--- + +### Overview + +:::info Model timing +Model Timing is only available on the Team and Multi-tenant Enterprise plans +::: + +Accessed via the "run detail" page in dbt Cloud, the model timing dashboard displays the model composition, order, and run time for every job run in dbt Cloud. The top 1% of model durations are automatically highlighted for quick reference. This visualization is displayed after the run completes. + +This is a very visual way to explore your run and surface model bottlenecks. Longest running models *may* be ripe for further exploration -- which can lead to refactoring or reducing run cadence. + +Notes: +- The model timing dashboard is currently only available on multi-tenant Team and Enterprise accounts. +- The model timing dashboard can only be viewed for jobs that have successfully completed. + + diff --git a/website/docs/docs/dbt-cloud/using-dbt-cloud/cloud-notifications.md b/website/docs/docs/dbt-cloud/using-dbt-cloud/cloud-notifications.md new file mode 100644 index 00000000000..b243a0de260 --- /dev/null +++ b/website/docs/docs/dbt-cloud/using-dbt-cloud/cloud-notifications.md @@ -0,0 +1,25 @@ +--- +title: "Configuring notifications" +description: "Set up notifications in dbt Cloud to receive Email or Slack alerts for job run status." +--- + +### Overview + +Setting up notifications in dbt Cloud will allow you to receive alerts via Email or a chosen Slack channel when a job run succeeds, fails, or is cancelled. + +### Email + +There are two options for setting up email notifications. As a **user**, you can set up email notifications for yourself under your Profile. As an **admin**, you can set up notifications on behalf of your team members. + +1. Click the gear in the top right and select **Notification settings**. + +2. **As a user:** Select **Edit** and select the type of Notification (Succeeds, Fails, or Is Cancelled) for each Job for which you would like to be notified, or + + **As an admin:** Select one or more users you'd like to set notifications for. If you only see your own name, then you might not have admin privileges. Select **Edit** and select the type of Notification (Succeeds, Fails, or Is Cancelled) for each Job for which they will be notified. + +3. Click **Save**. + + +### Slack + + diff --git a/website/docs/docs/dbt-cloud/using-dbt-cloud/cloud-setting-a-custom-target-name.md b/website/docs/docs/dbt-cloud/using-dbt-cloud/cloud-setting-a-custom-target-name.md index 96091d53262..3944bfc3d58 100644 --- a/website/docs/docs/dbt-cloud/using-dbt-cloud/cloud-setting-a-custom-target-name.md +++ b/website/docs/docs/dbt-cloud/using-dbt-cloud/cloud-setting-a-custom-target-name.md @@ -1,6 +1,8 @@ --- title: "Setting a custom target name" id: "cloud-setting-a-custom-target-name" +description: "You can define a custom target name for any dbt Cloud job to correspond to settings in your dbt project." + --- ## dbt Cloud Scheduler @@ -17,11 +19,11 @@ where created_at > date_trunc('month', current_date) {% endif %} ``` -To set a custom target name for a job in dbt Cloud, configure the "Target Name" field for your job in the Job Settings page. +To set a custom target name for a job in dbt Cloud, configure the **Target Name** field for your job in the Job Settings page. - + ## dbt Cloud IDE -When developing in dbt Cloud, you can set a custom target name in your development credentials. Head to your account (via your profile image in the top right hand corner), select the project under "Credentials" and update the target name. +When developing in dbt Cloud, you can set a custom target name in your development credentials. Go to your account (from the gear menu in the top right hand corner), select the project under **Credentials**, and update the target name. diff --git a/website/docs/docs/dbt-cloud/using-dbt-cloud/cloud-slack-notifications.md b/website/docs/docs/dbt-cloud/using-dbt-cloud/cloud-slack-notifications.md index 6f1156f47a1..f2e9f63d4f2 100644 --- a/website/docs/docs/dbt-cloud/using-dbt-cloud/cloud-slack-notifications.md +++ b/website/docs/docs/dbt-cloud/using-dbt-cloud/cloud-slack-notifications.md @@ -1,15 +1,6 @@ --- -title: "Configuring Slack Notifications" +title: "Configuring Slack notifications" +description: "Report status alerts in a designated Slack channel every time you run a job." --- -Setting up Slack notifications in dbt Cloud will allow you to receive alerts in a chosen Slack channel when a job run succeeds, fails, or is cancelled. - -**Note**: Currently, Slack notifications can only be configured by one user to one Slack channel. Additionally, you must be an admin of the Slack workspace in order to configure Slack notifications. - -In general, there are two parts to setting up Slack notifications. The first involves setting up the dbt Cloud integration with Slack, while the second involves setting up the notifications themselves. - - - If you **haven't** set up the integration: Watch the entire video below! - - - If you **have** set up the integration: Feel free to skip ahead to 0:40 in the video. - - + diff --git a/website/docs/docs/dbt-cloud/using-dbt-cloud/cloud-snapshotting-source-freshness.md b/website/docs/docs/dbt-cloud/using-dbt-cloud/cloud-snapshotting-source-freshness.md index 7f7b407b436..d314b570d2b 100644 --- a/website/docs/docs/dbt-cloud/using-dbt-cloud/cloud-snapshotting-source-freshness.md +++ b/website/docs/docs/dbt-cloud/using-dbt-cloud/cloud-snapshotting-source-freshness.md @@ -1,13 +1,14 @@ --- title: "Source freshness" id: "cloud-snapshotting-source-freshness" +description: "Validate that data freshness meets expectations and alert if stale." --- ## Data Source Freshness dbt Cloud provides a helpful interface around dbt's [source data freshness](using-sources#snapshotting-source-data-freshness) calculations. When a dbt Cloud job is configured to snapshot source data freshness, dbt Cloud will render a user interface showing you the state of the most recent snapshot. This interface is intended to help you determine if your source data freshness is meeting the SLAs that you've defined for your organization. - + ### Enabling source freshness snapshots @@ -15,7 +16,8 @@ First, make sure to configure your sources to [snapshot freshness information](u - - **v0.21.0:** Renamed `dbt source snapshot-freshness` to `dbt source freshness`. If using an older version of dbt, the command is `snapshot-freshness`. + - **v0.21.0:** Renamed `dbt source snapshot-freshness` to `dbt source freshness`. If using an older version of dbt, the command is `snapshot-freshness`. + To have dbt Cloud display data source freshness as a rendered user interface, you will still need to use the pre-v0.21 syntax of `dbt source snapshot-freshness`. @@ -37,10 +39,14 @@ Remember that `dbt build` does _not_ include source freshness checks when it bui ### Source freshness snapshot frequency -It's important that your freshness jobs run frequently enough to snapshot data latency in accordance with your SLAs. You can imagine that if you have a 1 hour SLA on a particular dataset, snapshotting the freshness of that table once daily would not be appropriate. As a good rule of thumb, you should run your source freshness jobs with at least double the frequency of your lowest SLA. Here's an example table of some reasonable snapshot frequencies given typical SLAs: +It's important that your freshness jobs run frequently enough to snapshot data latency in accordance with your SLAs. You can imagine that if you have a 1 hour SLA on a particular dataset, snapshotting the freshness of that once daily would not be appropriate. As a good rule of thumb, you should run your source freshness jobs with at least double the frequency of your lowest SLA. Here's an example table of some reasonable snapshot frequencies given typical SLAs: | SLA | Snapshot Frequency | | --- | ------------------ | | 1 hour | 30 mins | | 1 day | 12 hours | | 1 week | About daily | + +## Further reading + +For more on exposing links to the latest documentation and sharing source freshness reports to your team, see [Building and configuring artifacts](artifacts). diff --git a/website/docs/docs/dbt-cloud/using-dbt-cloud/cloud-using-a-custom-cron-schedule.md b/website/docs/docs/dbt-cloud/using-dbt-cloud/cloud-using-a-custom-cron-schedule.md index e8d730ac751..a0883b5e8cf 100644 --- a/website/docs/docs/dbt-cloud/using-dbt-cloud/cloud-using-a-custom-cron-schedule.md +++ b/website/docs/docs/dbt-cloud/using-dbt-cloud/cloud-using-a-custom-cron-schedule.md @@ -1,12 +1,14 @@ --- -title: "Custom cron schedules" +title: "Setting custom cron schedules" id: "cloud-using-a-custom-cron-schedule" +description: "You can use cron syntax to specify when you want to run a job." --- ### Overview + In dbt Cloud, you can use "cron" syntax to specify when you'd like your job to run. Cron syntax is very expressive, and allows you to completely customize your run schedule. -If you need help coming up with the right cron syntax, we recommend using a tool like crontab.guru. There, you can enter cron snippets and see what they mean in plain english. You can also find some example snippets below. +If you need help coming up with the right cron syntax, we recommend using a tool like `crontab.guru`. There, you can enter cron snippets and see what they mean in plain English. You can also find some example snippets below. ### Examples @@ -17,6 +19,13 @@ If you need help coming up with the right cron syntax, we recommend using a tool - `0 0 */2 * *`: At midnight UTC every other day - `0 0 * * 1`: At midnight UTC every Monday. -A custom cron schedule can be specified in the Triggers section of the Job Settings page. +A custom cron schedule can be specified in the Job Settings page when you edit a job: + +1. Select a job. +2. Click **Settings**. +3. Click **Edit**. +4. In the Triggers section, activate the **Run on schedule** option. +5. Select **Enter custom cron schedule**. +6. Enter the custom cron syntax for the schedule you want. - + diff --git a/website/docs/docs/introduction.md b/website/docs/docs/introduction.md index cb3a9782a82..73d33aa8e20 100644 --- a/website/docs/docs/introduction.md +++ b/website/docs/docs/introduction.md @@ -3,9 +3,9 @@ title: "What is dbt?" id: "introduction" --- -dbt (data build tool) enables analytics engineers to transform data in their warehouses by simply writing select statements. dbt handles turning these select statements into tables and views. +dbt enables analytics engineers to transform data in their warehouses by simply writing select statements. dbt handles turning these select statements into tables and views. -dbt does the `T` in `ELT` (Extract, Load, Transform) processes – it doesn’t extract or load data, but it’s extremely good at transforming data that’s already loaded into your warehouse. +dbt does the `T` in (Extract, Load, Transform) processes – it doesn’t extract or load data, but it’s extremely good at transforming data that’s already loaded into your warehouse. The role of dbt within a modern data stack is discussed in more detail [here](https://blog.fishtownanalytics.com/what-exactly-is-dbt-47ba57309068). @@ -29,9 +29,9 @@ Want to check out a sample project? Have a look at our [Jaffle Shop](https://git ::: ### Database Connections -dbt connects to your data warehouse to run data transformation queries. As such, you’ll need a data warehouse with source data loaded in it to use dbt. dbt natively supports connections to Snowflake, BigQuery, Redshift and Postgres data warehouses, and there’s a number of community-supported adapters for other warehouses (see [docs](available-adapters)). +dbt connects to your to run data transformation queries. As such, you’ll need a data warehouse with source data loaded in it to use dbt. dbt natively supports connections to Snowflake, BigQuery, Redshift and Postgres data warehouses, and there’s a number of community-supported adapters for other warehouses (see [Supported Data Platforms](supported-data-platforms)). -When you define your connection, you’ll also be able to specify the target schema where dbt should create your models as tables and views. See [Managing environments](managing-environments) for more information on picking target schema names. +When you define your connection, you’ll also be able to specify the target schema where dbt should create your models as tables and views. See [Managing environments](managing-environments) for more information on picking target schema names. ### dbt Commands @@ -40,7 +40,7 @@ A command is an instruction to execute dbt which compiles and runs SQL against t When you issue a dbt command, such as `run`, dbt: 1. Determines the order to execute the models in your project in. -2. Generates the DDL required to build the model, as per the model's *materialization* +2. Generates the required to build the model, as per the model's ** 3. Executes the compiled queries against your data warehouse, using the credentials specified in the *target* defined in your *profile*. Executing these queries creates relations in the target schema in your data warehouse. These relations contain transformed data, ready for analysis. A list of commands can be found in the [Command reference](dbt-commands) section of these docs. @@ -76,7 +76,7 @@ A materialization represents a build strategy for your select query – the code dbt ships with the following built-in materializations: * `view` (default): The model is built as a view in the database. * `table`: The model is built as a table in the database. -* `ephemeral`: The model is not directly built in the database, but is instead pulled into dependent models as common table expressions. +* `ephemeral`: The model is not directly built in the database, but is instead pulled into dependent models as common expressions. * `incremental`: The model is initially built as a table, and in subsequent runs, dbt inserts new rows and updates changed rows in the table. Custom materializations can also be built if required. @@ -109,7 +109,7 @@ Importantly, dbt also uses the `ref` function to determine the sequence in which -dbt builds a directed acyclic graph (DAG) based on the interdepencies between models – each node of the graph represents a model, and edges between the nodes are defined by `ref` functions, where a model specified in a `ref` function is recognized as a predecessor of the current model. +dbt builds a directed acyclic graph (DAG) based on the interdependencies between models – each node of the graph represents a model, and edges between the nodes are defined by `ref` functions, where a model specified in a `ref` function is recognized as a predecessor of the current model. When dbt runs, models are executed in the order specified by the DAG – there’s no need to explicitly define the order of execution of your models. Building models in staged transformations also reduces the need to repeat SQL, as a single transformation (for example, renaming a column) can be shared as a predecessor for a number of downstream models. diff --git a/website/docs/docs/running-a-dbt-project/dbt-api.md b/website/docs/docs/running-a-dbt-project/dbt-api.md deleted file mode 100644 index 9c545f918ca..00000000000 --- a/website/docs/docs/running-a-dbt-project/dbt-api.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -title: "Using the Python API" -id: "dbt-api" ---- - -The primary interface into `dbt-core` is on the command line. It is designed to be invoked with commands, arguments, and flags. Starting in v1, this interface is contracted, with backwards compatibility guaranteed. - -It _is_ possible to import and invoke dbt as a Python module. This API is still not contracted or documented, and it is liable to change in future versions of `dbt-core` without warning. Please use caution when upgrading across versions of dbt if you choose to run dbt in this manner! - -We aim to contract and document an increasing number of Python interfaces within `dbt-core`. Today, those interfaces are: -- [Adapter plugin](building-a-new-adapter) classes and methods. These are liable to change in minor versions _only_, and we will aim for backwards compatibility whenever possible. -- [Events](events), Python objects that dbt emits as log messages. diff --git a/website/docs/docs/running-a-dbt-project/running-dbt-in-production.md b/website/docs/docs/running-a-dbt-project/running-dbt-in-production.md index 79156f824c1..9bcb57cdec7 100644 --- a/website/docs/docs/running-a-dbt-project/running-dbt-in-production.md +++ b/website/docs/docs/running-a-dbt-project/running-dbt-in-production.md @@ -1,10 +1,10 @@ --- -title: "Running dbt in Production" +title: "About running dbt in production" id: "running-dbt-in-production" --- -## What does running dbt in production mean? -Running dbt in production simply means **setting up a system to run a dbt job on a schedule**, rather than running dbt commands manually from the command line. These production dbt jobs should create the tables and views that your business intelligence tools and end users query. Before continuing, make sure you understand dbt's approach to [managing environments](managing-environments). + +Running dbt in production means **setting up a system to run a dbt job on a schedule**, rather than running dbt commands manually from the command line. These production dbt jobs should create the tables and views that your business intelligence tools and end users query. Before continuing, make sure you understand dbt's approach to [managing environments](managing-environments). :::info dbt commands in production @@ -12,41 +12,57 @@ We've written a guide for the dbt commands we run in production, over on [Discou ::: -As well as setting up a schedule, there are a number of other things you should consider when setting up dbt to run in production, such as: +In addition to setting up a schedule, there are other considerations when setting up dbt to run in production: + * The complexity involved in creating a new dbt job, or editing an existing one. * Setting up notifications if a step within your job returns an error code (e.g. a model cannot be built, or a test fails). * Accessing logs to help debug any issues. * Pulling the latest version of your git repo before running dbt (i.e. continuous deployment). * Running your dbt project before merging code into master (i.e. continuous integration). * Allowing access for team members that need to collaborate on your dbt project. - + ## Ways to run dbt in production -### Using dbt Cloud -We've built [dbt Cloud](https://www.getdbt.com/signup/) from the ground up to empower data teams to easily run dbt in production. With dbt Cloud, you can: + +If you don't want to run dbt commands manually on the command line, you can use dbt Cloud, Airflow, Prefect, Dagster, automation server, or Cron to run dbt jobs on a schedule. +### dbt Cloud + +We've built [dbt Cloud](https://www.getdbt.com/signup/) to empower data teams to easily run dbt in production. If you're interested in trying out dbt Cloud, you can [sign up for an account](https://cloud.getdbt.com/signup/). + +dbt Cloud enables you to: - run your jobs on a schedule - view logs for any historical invocation of dbt - configure error notifications - render your project's documentation -If you're interested in giving dbt Cloud a spin, you can sign up for a *forever free* account [here](https://cloud.getdbt.com/signup/). +### Airflow - - -### Using Airflow If your organization is using [Airflow](https://airflow.apache.org/), there are a number of ways you can run your dbt jobs, including: -* Invoking dbt through the [BashOperator](https://airflow.apache.org/howto/operator/bash.html). In this case, be sure to install dbt into a virtual environment to avoid issues with conflicting dependencies between Airflow and dbt. -* Installing the [airflow-dbt](https://pypi.org/project/airflow-dbt/) python package. This package uses Airflow's operator and hook concept — the source code can be found on [github](https://github.com/gocardless/airflow-dbt). -### Using Prefect +* Installing the [dbt Cloud Provider](https://registry.astronomer.io/providers/dbt-cloud) to orchestrate dbt Cloud jobs. This package contains multiple Hooks, Operators, and Sensors to complete various actions within dbt Cloud. See an [example airflow DAG](https://registry.astronomer.io/dags/example-dbt-cloud) to get started! + + + + +* Invoking dbt Core jobs through the [BashOperator](https://registry.astronomer.io/providers/apache-airflow/modules/bashoperator). In this case, be sure to install dbt into a virtual environment to avoid issues with conflicting dependencies between Airflow and dbt. + +For more details on both of these methods, including example implementations, check out [this guide](https://www.astronomer.io/guides/airflow-dbt). + +### Prefect + If your organization is using [Prefect](https://www.prefect.io), use the [DbtShellTask](https://docs.prefect.io/api/latest/tasks/dbt.html#dbtshelltask) to schedule, execute and monitor your dbt runs. Alternatively, you can use the supported [ShellTask](https://docs.prefect.io/api/latest/tasks/shell.html#shelltask) to execute dbt commands through the shell. -### Using Dagster -If your organization is using [Dagster](https://dagster.io/), you can use the [dagster_dbt](https://docs.dagster.io/_apidocs/libraries/dagster-dbt) library to integrate dbt commands into your pipelines. Execution through both the dbt CLI and the dbt RPC server is supported, and metadata from dbt runs is automatically aggregated. Check out the [example pipeline](https://dagster.io/blog/dagster-dbt) for details. +You can also trigger dbt Cloud jobs with the [DbtCloudRunJob](https://docs.prefect.io/api/latest/tasks/dbt.html#dbtcloudrunjob) task. Running this task will generate a markdown artifact viewable in the Prefect UI. The artifact will contain links to the dbt artifacts generate as a result of the job run. + +### Dagster + +If your organization is using [Dagster](https://dagster.io/), you can use the [dagster_dbt](https://docs.dagster.io/_apidocs/libraries/dagster-dbt) library to integrate dbt commands into your pipelines. This library supports the execution of dbt through dbt Cloud, dbt CLI and the dbt RPC server. Running dbt from Dagster automatically aggregates metadata about your dbt runs. Check out the [example pipeline](https://dagster.io/blog/dagster-dbt) for details. + +### Automation servers -### Using an automation server Automation servers, like CodeDeploy, GitLab CI/CD ([video](https://youtu.be/-XBIIY2pFpc?t=1301)), Bamboo and Jenkins, can be used to schedule bash commands for dbt. They also provide a UI to view logging to the command line, and integrate with your git repository. -### Using cron +### Cron + Cron is a decent way to schedule bash commands. However, while it may seem like an easy route to schedule a job, writing code to take care of all of the additional features associated with a production deployment often makes this route more complex compared to other options listed here. diff --git a/website/docs/docs/running-a-dbt-project/using-the-dbt-ide.md b/website/docs/docs/running-a-dbt-project/using-the-dbt-ide.md index d7f1caf6c97..493c3c8d383 100644 --- a/website/docs/docs/running-a-dbt-project/using-the-dbt-ide.md +++ b/website/docs/docs/running-a-dbt-project/using-the-dbt-ide.md @@ -3,24 +3,24 @@ title: "Using the dbt IDE" id: "using-the-dbt-ide" --- -The dbt Integrated Development Environment (IDE) is a single interface for building, testing, running, and version controlling dbt projects. We encourage you to use the IDE and share your feedback with the dbt Cloud team. +The dbt Integrated Development Environment (IDE) is a single interface for building, testing, running, and version controlling dbt projects. ### Requirements -- The dbt IDE is powered by the [dbt Server](rpc) which has been overhauled in dbt v0.15.0. In order to use the IDE, your dbt project must be compatible with dbt v0.15.0. +- The dbt IDE is powered by [dbt-rpc](rpc) which has been overhauled in dbt v0.15.0. In order to use the IDE, your dbt project must be compatible with dbt v0.15.0. - To use the IDE, you must have a [Developer License](cloud-seats-and-users). - Write access must be enabled for your dbt repository in dbt Cloud. See [Connecting your GitHub Account](cloud-installing-the-github-application) and [Importing a project by git URL](cloud-import-a-project-by-git-url) for detailed setup instructions. ### Creating a development environment New dbt Cloud accounts will automatically be created with a Development Environment for the project created during setup. If you have an existing dbt Cloud account, you may need to create a Development Environment manually to use the dbt IDE. -To create a Development Environment, navigate to the Environments page for your Project and click the "New Environment" button. +To create a development environment, choose **Deploy** > **Environments** from the top left. Then, click **Create Environment**. - + -To create a Development Environment, change the environment "type" to "development". Enter a name like "Dev" for the environment to help identify it amongst your other environments. Finally, click "Save" to finish creating your Development Environment. +Enter an environment **Name** that would help you identify it among your other environments (for example, `Nate's Development Environment`). Choose **Development** as the **Environment Type**. You can also select which **dbt Version** to use at this time. For compatibility reasons, we recommend that you select the same dbt version that you plan to use in your deployment environment. Finally, click **Save** to finish creating your development environment. - + ### Setting up developer credentials @@ -28,11 +28,11 @@ The IDE uses *developer credentials* to connect to your database. These develope New dbt Cloud accounts should have developer credentials created automatically as a part of Project creation in the initial application setup. - + -Existing accounts *may not* have development credentials configured already. To manage your development credentials, navigate to your [Profile](https://cloud.getdbt.com/#/profile/) in dbt Cloud and find the relevant Project under the **Credentials** header. After entering your developer credentials, you'll be able to access the dbt IDE. +New users on existing accounts *might not* have their development credentials already configured. To manage your development credentials, go to the [Credentials](https://cloud.getdbt.com/next/settings/profile#credentials) section. Select the relevant project in the list. After entering your developer credentials, you'll be able to access the dbt IDE. - + ### Compiling and running SQL @@ -49,6 +49,6 @@ This video explores running dbt projects in the dbt IDE. For a full list of the ### Version control -This videos explores version controlling changes to dbt projects with git in the dbt IDE. +This video explores version controlling changes to dbt projects with git in the dbt IDE. diff --git a/website/docs/docs/supported-data-platforms.md b/website/docs/docs/supported-data-platforms.md new file mode 100644 index 00000000000..6fc58e6a271 --- /dev/null +++ b/website/docs/docs/supported-data-platforms.md @@ -0,0 +1,81 @@ +--- +title: "Supported Data Platforms" +id: "supported-data-platforms" +--- + +dbt connects to and runs SQL against your database, warehouse, lake or query engine. To keep things simple, we group all of these SQL-speaking things into one bucket called "data platforms". dbt can be extended to any data platform by means of a dedicated _adapter plugin_. These plugins are built as separate Python modules that dbt Core will discover them if they are installed on your system. All the adapters listed below are open source and free to use, just like dbt Core. + +To learn more about adapters, check out [What Are Adapters](contributing/adapter-development/1-what-are-adapters). + +## Adapter Installation + +With a few exceptions [^1], all adapters listed below can be installed from PyPI using `pip install `. The installation will include `dbt-core` and any other required dependencies, which may include both other dependencies and even other adapter plugins. Read more about [installing dbt](dbt-cli/install/overview). + +## Adapter Taxonomy + +### Verified by dbt Labs + +In order to provide a more consistent and reliable experience, dbt Labs now has a rigorous process by which we verify adapter plugins. The process covers aspects of development, documentation, user experience and maintenance. These adapters earn a "Verified" designation so that users can have a certain level of trust and expectation when they use them. To learn more see [Verifying a new adapter](docs/contributing/adapter-development/7-verifying-a-new-adapter) + +We also welcome and encourage adapter plugins from the dbt community (see the below [Contributing to a pre-existing adapter](#contributing-to-a-pre-existing-adapter)). Please note that these community maintainers are intrepid volunteers who owe you nothing, but give anyway -- so be kind and understanding, and help out where you can! + +### Maintainers + +Who made and maintains and adapter is certainly relevant, but we recommend using an adapter's verification status to determine quality and health of an adapter. So far we have three categories of maintainers: + +| Supported by | Maintained By | +| ------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| dbt Labs | dbt Labs maintains a set of adapter plugins for some of the most common databases, warehouses, and platforms. As for why particular data platforms were chosen, see ["Why Verify an Adapter"](7-verifying-a-new-adapter#why-verify-an-adapter) | +| Partner | These adapter plugins are built and maintained by the same people who build and maintain the complementary data technology | +| Community | These adapter plugins are contributed and maintained by members of the community 🌱 | + +## Supported Data Platforms + +### Verified Adapters + +| Data Platform | latest verified version | +| ------------------------------------------ | ------------------------ | +| AlloyDB ([setup](alloydb-setup)) | (same as `dbt-postgres`) | +| BigQuery ([setup](bigquery-setup)) | 1.2.0 | +| Databricks ([setup](databricks-setup)) | 1.2.0 :construction: | +| Postgres ([setup](postgres-setup)) | 1.2.0 | +| Redshift ([setup](redshift-setup)) | 1.2.0 | +| Snowflake ([setup](snowflake-setup)) | 1.2.0 | +| Apache Spark ([setup](spark-setup)) | 1.2.0 | +| Starburst & Trino ([setup](trino-setup)) | 1.2.0 :construction: | + +### Community Adapters + +| Data Platforms (click to view setup guide) | | | +| ----------------------------------------------- | --------------------------------| ---------------------------------| +| [Athena](athena-setup) | [Hive](hive-setup) | [SingleStore](singlestore-setup) | +| [Clickhouse](clickhouse-setup) | [Impala](impala-setup) | [SQLite](sqlite-setup) | +| [IBM DB2](ibmdb2-setup) | [iomete](iomete-setup) | [SQL Server & Azure SQ](mssql-setup) | +| [DuckDB](duckdb-setup) | [Layer](layer-setup) | [AzureSynapse](azuresynapse-setup) | +| [Dremio](dremio-setup) | [Materialize](materialize-setup) | [Teradata](teradata-setup)| +| [Exasol Analytics](exasol-setup) | [MindsDB](mindsdb-setup) | [TiDB](tidb-setup)| +| [Firebold](firebolt-setup) | [MySQL](mysql-setup) | [Vertica](vertica-setup)| +| [AWS Glue](glue-setup) | [Oracle](oracle-setup) | +| [Greenplum](greenplum-setup) | [Rockset](rockset-setup) + +## Contributing to dbt-core adapters + +### Contributing to a pre-existing adapter + +Community-supported plugins are works in progress, and anyone is welcome to contribute by testing and writing code. If you're interested in contributing: + +- Join both the dedicated channel, [#adapter-ecosystem](https://getdbt.slack.com/archives/C030A0UF5LM), in [dbt Slack](https://community.getdbt.com/) and the channel for your adapter's data store (see **Slack Channel** column of above tables) +- Check out the open issues in the plugin's source repository (follow relevant link in **Adapter Repository** column of above tables) + +### Creating a new adapter + +If you see something missing from the lists above, and you're interested in developing an integration, read more about adapters and how they're developed in the [Adapter Development](/category/adapter-development) section. + +If you have a new adapter, please add it to this list using a pull request! See [Documenting your adapter](5-documenting-a-new-adapter) for more information. + +[^1]: Here are the two different adapters. Use the PyPI package name when installing with `pip` + + | Adapter repo name | PyPI package name | + | ----------------- | -------------------- | + | `dbt-athena` | `dbt-athena-adapter` | + | `dbt-layer` | `dbt-layer-bigquery` | diff --git a/website/docs/faqs/Accounts/change-billing.md b/website/docs/faqs/Accounts/change-billing.md new file mode 100644 index 00000000000..65e47cc9c4a --- /dev/null +++ b/website/docs/faqs/Accounts/change-billing.md @@ -0,0 +1,11 @@ +--- +title: How can I update my billing information? +description: "Instructions on how to update your billing info" +sidebar_label: 'How to update billing' +id: change-billing +--- + + +If you want to change your account's credit card details, select the gear menu in the upper right corner of dbt Cloud. Go to Account Settings → Billing → Payment Information. In the upper right corner of Payment Information, click **Edit** to enter the new credit card details. Only the _account owner_ can make this change. + +To change your billing name or location address, send our Support team a message at support@getdbt.com with the newly updated information, and we can make that change for you! diff --git a/website/docs/faqs/configurable-snapshot-path.md b/website/docs/faqs/Accounts/configurable-snapshot-path.md similarity index 76% rename from website/docs/faqs/configurable-snapshot-path.md rename to website/docs/faqs/Accounts/configurable-snapshot-path.md index 66f084ee775..45e51f20dbf 100644 --- a/website/docs/faqs/configurable-snapshot-path.md +++ b/website/docs/faqs/Accounts/configurable-snapshot-path.md @@ -1,5 +1,8 @@ --- title: Can I store my snapshots in a directory other than the `snapshot` directory in my project? +description: "You can see how to change snapshots directory in your project" +sidebar_label: 'Store snapshot in other directory' +id: configurable-snapshot-path --- By default, dbt expects your snapshot files to be located in the `snapshots` subdirectory of your project. diff --git a/website/docs/faqs/Accounts/dbt-specific-jinja.md b/website/docs/faqs/Accounts/dbt-specific-jinja.md new file mode 100644 index 00000000000..e2623491007 --- /dev/null +++ b/website/docs/faqs/Accounts/dbt-specific-jinja.md @@ -0,0 +1,8 @@ +--- +title: What parts of Jinja are dbt-specific? +description: "You can check which Jinja functions are dbt-specific" +sidebar_label: 'dbt-specific Jinja' +id: dbt-specific-jinja +--- + +There are certain expressions that are specific to dbt — these are documented in the [Jinja function reference](/reference/dbt-jinja-functions) section of these docs. Further, docs blocks, snapshots, and materializations are custom Jinja _blocks_ that exist only in dbt. diff --git a/website/docs/faqs/Accounts/git-account-in-use.md b/website/docs/faqs/Accounts/git-account-in-use.md new file mode 100644 index 00000000000..a84577e6ede --- /dev/null +++ b/website/docs/faqs/Accounts/git-account-in-use.md @@ -0,0 +1,15 @@ +--- +title: Why am I getting an "account in use" error? +description: "What to do when you receive a Git account in use error" +sidebar_label: 'Git account in use' +id: git-account-in-use +--- + +If you're receiving an 'Account in use' error when trying to integrate GitHub in your Profile page, this is because the Git integration is a 1-to-1 integration, so you can only have your Git account linked to one dbt Cloud user account. + +Here are some steps to take to get you unstuck: + +* Log in to the dbt Cloud account integrated with your Git account. Go to your user profile and click on Integrations to remove the link. + +If you don't remember which dbt Cloud account is integrated, please email dbt Support at support@getdbt.com and we'll do our best to disassociate the integration for you. + diff --git a/website/docs/faqs/Accounts/payment-accepted.md b/website/docs/faqs/Accounts/payment-accepted.md new file mode 100644 index 00000000000..2e26063c684 --- /dev/null +++ b/website/docs/faqs/Accounts/payment-accepted.md @@ -0,0 +1,10 @@ +--- +title: Can I pay via invoice? +description: "What payments types are accepted" +sidebar_label: 'Can I pay invoice' +id: payment-accepted +--- + +Presently for Team plans, self-service dbt Cloud payments must be made via credit card and by default, they will be billed monthly based on the number of active developer seats. + +We don't have any plans to do invoicing for self-service teams in the near future, but we *do* currently support invoices for companies on the **dbt Cloud Enterprise plan.** Feel free to [contact us](https://www.getdbt.com/contact) to build your Enterprise pricing. diff --git a/website/docs/faqs/Accounts/slack.md b/website/docs/faqs/Accounts/slack.md new file mode 100644 index 00000000000..01001141e2e --- /dev/null +++ b/website/docs/faqs/Accounts/slack.md @@ -0,0 +1,8 @@ +--- +title: How do I set up Slack notifications? +description: "Instructions on how to set up slack notifications" +sidebar_label: 'How to set up Slack' +id: slack +--- + + diff --git a/website/docs/faqs/install-pip-best-practices.md b/website/docs/faqs/Core/install-pip-best-practices.md similarity index 90% rename from website/docs/faqs/install-pip-best-practices.md rename to website/docs/faqs/Core/install-pip-best-practices.md index edfcdc54f53..6af983028e5 100644 --- a/website/docs/faqs/install-pip-best-practices.md +++ b/website/docs/faqs/Core/install-pip-best-practices.md @@ -1,6 +1,8 @@ --- title: "What are the best practices for installing dbt Core with pip?" -description: "" +description: "Instructions on how to install dbt Core with pip" +sidebar_label: 'Installing dbt Core with pip' +id: install-pip-best-practices.md --- Managing Python local environments can be challenging! You can use these best practices to improve the dbt Core installation with pip. diff --git a/website/docs/faqs/install-pip-os-prereqs.md b/website/docs/faqs/Core/install-pip-os-prereqs.md similarity index 82% rename from website/docs/faqs/install-pip-os-prereqs.md rename to website/docs/faqs/Core/install-pip-os-prereqs.md index 04a5be334a3..c0519a3e84a 100644 --- a/website/docs/faqs/install-pip-os-prereqs.md +++ b/website/docs/faqs/Core/install-pip-os-prereqs.md @@ -1,7 +1,8 @@ --- - title: "Does my operating system have prerequisites?" -Description: "You can check whether your operating system has prerequisites for installing dbt Core." +description: "You can check whether your operating system has prerequisites for installing dbt Core." +sidebar_label: 'dbt Core system prerequisites' +id: install-pip-os-prereqs.md --- @@ -54,4 +55,6 @@ pip install cryptography~=3.4 Windows requires Python and git to successfully install and run dbt Core. -Install [Git for Windows](https://git-scm.com/downloads) and [Python version 3.6 or higher for Windows](https://www.python.org/downloads/windows/). \ No newline at end of file +Install [Git for Windows](https://git-scm.com/downloads) and [Python version 3.7 or higher for Windows](https://www.python.org/downloads/windows/). + +For further questions, please see the [Python compatibility FAQ](/docs/faqs/Core/install-python-compatibility) diff --git a/website/docs/faqs/install-python-compatibility.md b/website/docs/faqs/Core/install-python-compatibility.md similarity index 58% rename from website/docs/faqs/install-python-compatibility.md rename to website/docs/faqs/Core/install-python-compatibility.md index 276becc9f35..9e20cbb0f85 100644 --- a/website/docs/faqs/install-python-compatibility.md +++ b/website/docs/faqs/Core/install-python-compatibility.md @@ -1,9 +1,21 @@ --- title: What version of Python can I use? -description: "Python versions 3.7, 3.8, and 3.9 can be used with dbt Core" +description: "Python versions 3.7 and newer can be used with dbt Core" +sidebar_label: 'Python version' +id: install-python-compatibility --- -As of v1.0.0, `dbt-core` is compatible with Python versions 3.7, 3.8, and 3.9. + + +The latest version of `dbt-core` is compatible with Python versions 3.7, 3.8, 3.9, and 3.10. + + + + + +As of v1.0, `dbt-core` is compatible with Python versions 3.7, 3.8, and 3.9. + + Adapter plugins and their dependencies are not always compatible with the latest version of Python. For example, dbt-snowflake v0.19 is not compatible with Python 3.9, but dbt-snowflake versions 0.20+ are. diff --git a/website/docs/faqs/document-all-columns.md b/website/docs/faqs/Docs/document-all-columns.md similarity index 71% rename from website/docs/faqs/document-all-columns.md rename to website/docs/faqs/Docs/document-all-columns.md index 19fd5c4f96a..0de7881bfdd 100644 --- a/website/docs/faqs/document-all-columns.md +++ b/website/docs/faqs/Docs/document-all-columns.md @@ -1,5 +1,8 @@ --- title: Do I need to add a yaml entry for column for it to appear in the docs site? +description: "All columns appear in your docs site" +sidebar_label: 'Types of columns included in doc site' +id: document-all-columns --- Fortunately, no! diff --git a/website/docs/faqs/document-other-resources.md b/website/docs/faqs/Docs/document-other-resources.md similarity index 65% rename from website/docs/faqs/document-other-resources.md rename to website/docs/faqs/Docs/document-other-resources.md index 58dda592d36..b5d612fbcfc 100644 --- a/website/docs/faqs/document-other-resources.md +++ b/website/docs/faqs/Docs/document-other-resources.md @@ -1,5 +1,8 @@ --- title: Can I document things other than models, like sources, seeds, and snapshots? +description: "Using the description key to document resources" +sidebar_label: 'Document other resources' +id: document-other-resources --- Yes! You can document almost everything in your project using the `description:` key. Check out the reference docs on [descriptions](description) for more info! diff --git a/website/docs/faqs/documenting-macros.md b/website/docs/faqs/Docs/documenting-macros.md similarity index 82% rename from website/docs/faqs/documenting-macros.md rename to website/docs/faqs/Docs/documenting-macros.md index 7db45b3ef74..71211f2c100 100644 --- a/website/docs/faqs/documenting-macros.md +++ b/website/docs/faqs/Docs/documenting-macros.md @@ -1,12 +1,15 @@ --- title: How do I document macros? +description: "You can use a schema file to document macros" +sidebar_label: 'Document macros' +id: documenting-macros --- The `macros:` key is new in 0.16.0. To document macros, use a [schema file](macro-properties) and nest the configurations under a `macros:` key -## Example: +## Example diff --git a/website/docs/faqs/Docs/long-descriptions.md b/website/docs/faqs/Docs/long-descriptions.md new file mode 100644 index 00000000000..f353050468e --- /dev/null +++ b/website/docs/faqs/Docs/long-descriptions.md @@ -0,0 +1,23 @@ +--- +title: How do I write long-form explanations in my descriptions? +description: "Write long descriptions in your documentation" +sidebar_label: 'Write long descriptions' +id: long-descriptions +--- +If you need more than a sentence to explain a model, you can: + +1. Split your description over multiple lines ([yaml docs](https://yaml-multiline.info/)), like so: + + ```yml + version: 2 + + models: + - name: customers + description: > + Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod + tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, + quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo + consequat. + ``` + +2. Use a [docs block](/documentation#using-docs-blocks) to write the description in a Markdown file. diff --git a/website/docs/faqs/Docs/sharing-documentation.md b/website/docs/faqs/Docs/sharing-documentation.md new file mode 100644 index 00000000000..4c6e0e84f77 --- /dev/null +++ b/website/docs/faqs/Docs/sharing-documentation.md @@ -0,0 +1,8 @@ +--- +title: How do I share my documentation with my team members? +description: "Use read-only seats to share documentation" +sidebar_label: 'Share documentation with teammates' +id: sharing-documentation +--- + +If you're using dbt Cloud to deploy your project, and have the [Team plan](https://www.getdbt.com/pricing/), you can have up to 5 read-only users, who will be able access the documentation for your project. diff --git a/website/docs/faqs/beta-release.md b/website/docs/faqs/Environments/beta-release.md similarity index 75% rename from website/docs/faqs/beta-release.md rename to website/docs/faqs/Environments/beta-release.md index 6cfea736780..5eef07d3510 100644 --- a/website/docs/faqs/beta-release.md +++ b/website/docs/faqs/Environments/beta-release.md @@ -1,4 +1,7 @@ --- title: What is a beta release? +description: "How to try out beta features" +sidebar_label: 'What is a beta release?' +id: beta-release --- This is a chance to try out brand-new functionality. You get to start planning for use cases that the next minor version will unlock. We get to hear from you about unexpected behavior and nasty bugs, so that the release candidate has more polish and fewer surprises. diff --git a/website/docs/faqs/Environments/diff-database-environment.md b/website/docs/faqs/Environments/diff-database-environment.md new file mode 100644 index 00000000000..49675540b80 --- /dev/null +++ b/website/docs/faqs/Environments/diff-database-environment.md @@ -0,0 +1,8 @@ +--- +title: Can I set a different connection at the environment level? +description: "Separate projects for different environments workaround" +sidebar_label: 'Set different database connections at environment level' +id: diff-database-environment +--- + +Although you're unable to set a different connection at the environment level, there is a workaround where you can have separate projects for their different environments and link them to different hostnames, while still connecting to the same repo. diff --git a/website/docs/faqs/profile-env-vars.md b/website/docs/faqs/Environments/profile-env-vars.md similarity index 56% rename from website/docs/faqs/profile-env-vars.md rename to website/docs/faqs/Environments/profile-env-vars.md index 32912361343..d9cea7946de 100644 --- a/website/docs/faqs/profile-env-vars.md +++ b/website/docs/faqs/Environments/profile-env-vars.md @@ -1,4 +1,7 @@ --- title: Can I use environment variables in my profile? +description: "Use env_var in your profile" +sidebar_label: 'Use env_var in your profile' +id: profile-env-vars --- Yes! Check out the docs on [environment variables](env_var) for more information. diff --git a/website/docs/faqs/profile-name.md b/website/docs/faqs/Environments/profile-name.md similarity index 71% rename from website/docs/faqs/profile-name.md rename to website/docs/faqs/Environments/profile-name.md index b72260baa11..c8ed61dc087 100644 --- a/website/docs/faqs/profile-name.md +++ b/website/docs/faqs/Environments/profile-name.md @@ -1,4 +1,7 @@ --- title: What should I name my profile? +description: "Use company name for profile name" +sidebar_label: 'Naming your profile' +id: profile-name --- We typically use a company name for a profile name, and then use targets to differentiate between `dev` and `prod`. Check out the docs on [managing environments](managing-environments) for more information. diff --git a/website/docs/faqs/target-names.md b/website/docs/faqs/Environments/target-names.md similarity index 68% rename from website/docs/faqs/target-names.md rename to website/docs/faqs/Environments/target-names.md index f01b0e4c399..f141a95fc1f 100644 --- a/website/docs/faqs/target-names.md +++ b/website/docs/faqs/Environments/target-names.md @@ -1,5 +1,8 @@ --- title: What should I name my target? +description: "Using targets to clarify development and production runs" +sidebar_label: 'Naming your target' +id: target-names --- We typically use targets to differentiate between development and production runs of dbt, naming the targets `dev` and `prod` respectively. Check out the docs on [managing environments](managing-environments) for more information. diff --git a/website/docs/faqs/Git/gitignore.md b/website/docs/faqs/Git/gitignore.md new file mode 100644 index 00000000000..fb097bb4043 --- /dev/null +++ b/website/docs/faqs/Git/gitignore.md @@ -0,0 +1,25 @@ +--- +title: Why can't I checkout a branch or create a new branch? +description: "Add or fill in gitignore file" +sidebar_label: 'Unable to checkout or create branch' +id: gitignore +--- + +If you're finding yourself unable to revert changes, check out a branch or click commit - this is usually do to your project missing a [.gitignore](https://github.com/dbt-labs/dbt-starter-project/blob/main/.gitignore) file OR your gitignore file doesn't contain the necessary content inside the folder. + +This is what causes that 'commit' git action button to display. No worries though - to fix this, you'll need to complete the following steps in order: + +1. In the Cloud IDE, add the missing .gitignore file or contents to your project. You'll want to make sure the .gitignore file includes the following: + + ```shell + target/ + dbt_modules/ + dbt_packages/ + logs/ + ``` + +2. Once you've added that, make sure to save and commit. + +3. Navigate to the same branch in your remote repository (which can be accessed directly through your git provider's web interface) and delete the logs, target, and dbt_modules/dbt_packages folders. + +4. Go back into the Cloud IDE and reclone your repository. This can be done by clicking on the green "ready" in the bottom right corner of the IDE (next to the command bar), and then clicking the orange "reclone repo" button in the pop up. diff --git a/website/docs/faqs/Git/gitlab-authentication.md b/website/docs/faqs/Git/gitlab-authentication.md new file mode 100644 index 00000000000..0debdf87873 --- /dev/null +++ b/website/docs/faqs/Git/gitlab-authentication.md @@ -0,0 +1,29 @@ +--- +title: I'm seeing a Gitlab authentication out of date error loop +description: "GitLab and dbt Cloud deploy key mismatch " +sidebar_label: 'GitLab authentication out of date' +id: gitlab-authentication +--- + +If you're seeing a 'GitLab Authentication is out of date' 500 server error page - this usually occurs when the deploy key in the repository settings in both dbt Cloud and GitLab do not match. + +No worries - this is a current issue the dbt Labs team is working on and we have a few workarounds for you to try: + +### 1st Workaround + +1. Disconnect repo from project in dbt Cloud. +2. Go to Gitlab and click on Settings > Repository. +3. Under Repository Settings, remove/revoke active dbt Cloud deploy tokens and deploy keys. +4. Attempt to reconnect your repository via dbt Cloud. +5. You would then need to check Gitlab to make sure that the new deploy key is added. +6. Once confirmed that it's added, refresh dbt Cloud and try developing once again. + +### 2nd Workaround + +1. Keep repo in project as is -- don't disconnect. +2. Copy the deploy key generated in dbt Cloud. +3. Go to Gitlab and click on Settings > Repository. +4. Under Repository Settings, manually add to your Gitlab project deploy key repo (with `Grant write permissions` box checked). +5. Go back to dbt Cloud, refresh your page and try developing again. + +If you've tried the workarounds above and are still experiencing this behavior - reach out to the Support team at support@getdbt.com and we'll be happy to help! diff --git a/website/docs/faqs/Git/gitlab-selfhosted.md b/website/docs/faqs/Git/gitlab-selfhosted.md new file mode 100644 index 00000000000..c02c363cf3a --- /dev/null +++ b/website/docs/faqs/Git/gitlab-selfhosted.md @@ -0,0 +1,10 @@ +--- +title: Can self-hosted GitLab instances only be connected via dbt Cloud Enterprise plans? +description: "Self hosted GitLab instances plan availability" +sidebar_label: 'Self-hosted GitLab instances available for dbt Cloud Enterprise' +id: gitlab-selfhosted +--- + +Presently yes, this is only available to Enterprise users. This is because of the way you have to set up the GitLab app redirect URL for auth, which can only be customized if you're a user on an Enterprise plan. + +Check out our [pricing page](https://www.getdbt.com/pricing/) for more information or feel free to [contact us](https://www.getdbt.com/contact) to build your Enterprise pricing. diff --git a/website/docs/faqs/Git/google-cloud-repo.md b/website/docs/faqs/Git/google-cloud-repo.md new file mode 100644 index 00000000000..1e88ac9a6ed --- /dev/null +++ b/website/docs/faqs/Git/google-cloud-repo.md @@ -0,0 +1,18 @@ +--- +title: How can I connect dbt to a Google Source repository? +description: "Use SSH URL method to connect to Google Source Repo" +sidebar_label: 'Connect dbt to a Google Source repository' +id: google-cloud-repo + +--- + +Although we don't officially support Google Cloud as a git repository, the below workaround using the SSH URL method should help you to connect: + +- First: "import" your Repository into dbt Cloud using the SSH URL provided to you by GCP. That will look something like: +`ssh://drew@fishtownanalytics.com@source.developers.google.com:2022/p/dbt-integration-tests/r/drew-debug` + +- After importing the repo, you should see a public key generated by dbt Cloud for the repository. You'll want to copy that public key into a new SSH Key for your user here: [https://source.cloud.google.com/user/ssh_keys](https://source.cloud.google.com/user/ssh_keys) + +- After saving this SSH key, dbt Cloud should be able to read and write to this repo. + +If you've tried the workaround above and are still having issues connecting - reach out to the Support team at support@getdbt.com and we'll be happy to help! diff --git a/website/docs/faqs/Git/managed-repo.md b/website/docs/faqs/Git/managed-repo.md new file mode 100644 index 00000000000..8d549daf76d --- /dev/null +++ b/website/docs/faqs/Git/managed-repo.md @@ -0,0 +1,10 @@ +--- +title: How can we move our project from a managed repository, to a self-hosted repository? +description: "Email Support to request your managed repository" +sidebar_label: 'How to request your managed repository zipfile' +id: managed-repo +--- + +dbt Labs can send your managed repository through a ZIP file in its current state for you to push up to a git provider. After that, you'd just need to switch over to the repo in your [Project](/docs/dbt-cloud/cloud-configuring-dbt-cloud/cloud-import-a-project-by-git-url) to point to the new repository. + +When you're ready to do this, [contact the dbt Labs Support team](mailto:support@getdbt.com) with your request and your managed repo URL, which you can find by navigating to your project setting. To find project settings, click the gear icon in the upper right, select **Account settings**, click **Projects**, and then select your project. Under **Repository** in the project details page, you can find your managed repo URL. diff --git a/website/docs/faqs/Git/run-on-pull.md b/website/docs/faqs/Git/run-on-pull.md new file mode 100644 index 00000000000..3536259bb79 --- /dev/null +++ b/website/docs/faqs/Git/run-on-pull.md @@ -0,0 +1,15 @@ +--- +title: Why is Run on Pull request grayed out? +description: "Use the GitHub auth method to enable Rull on Pull request" +sidebar_label: 'Run on Pull request grayed out' +id: run-on-pull +--- + +If you're unable to enable Run on Pull requests, you'll want to make sure your existing repo was not added via the Deploy Key auth method. + +If it was added via a deploy key method, you'll want to use the [GitHub auth method](https://docs.getdbt.com/docs/cloud-installing-the-github-application) to enable CI in dbt Cloud. + +To go ahead and enable 'Run on Pull requests', you'll want to remove dbt Cloud from the Apps & Integration on GitHub and re-integrate it again via the GitHub app method. + +If you've tried the workaround above and are still experiencing this behavior - reach out to the Support team at support@getdbt.com and we'll be happy to help! + diff --git a/website/docs/faqs/jinja-whitespace.md b/website/docs/faqs/Jinja/jinja-whitespace.md similarity index 82% rename from website/docs/faqs/jinja-whitespace.md rename to website/docs/faqs/Jinja/jinja-whitespace.md index cd26398a2b9..90a7dc5d2e1 100644 --- a/website/docs/faqs/jinja-whitespace.md +++ b/website/docs/faqs/Jinja/jinja-whitespace.md @@ -1,6 +1,10 @@ --- title: My compiled SQL has a lot of spaces and new lines, how can I get rid of it? +description: "Managing whitespace control" +sidebar_label: 'Compiled sql has a lot of white space' +id: jinja-whitespace --- + This is known as "whitespace control". Use a minus sign (`-`, e.g. `{{- ... -}}`, `{%- ... %}`, `{#- ... -#}`) at the start or end of a block to strip whitespace before or after the block (more docs [here](https://jinja.palletsprojects.com/page/templates/#whitespace-control)). Check out the [tutorial on using Jinja](using-jinja#use-whitespace-control-to-tidy-up-compiled-code) for an example. diff --git a/website/docs/faqs/quoting-column-names.md b/website/docs/faqs/Jinja/quoting-column-names.md similarity index 87% rename from website/docs/faqs/quoting-column-names.md rename to website/docs/faqs/Jinja/quoting-column-names.md index ccca7566dc4..aff4a36b886 100644 --- a/website/docs/faqs/quoting-column-names.md +++ b/website/docs/faqs/Jinja/quoting-column-names.md @@ -1,10 +1,16 @@ --- title: Why do I need to quote column names in Jinja? +description: "Use quotes to pass string" +sidebar_label: 'Why quote column names in Jinja' +id: quoting-column-names --- + In the [macro example](jinja-macros#macros) we passed the column name `amount` quotes: + ```sql {{ cents_to_dollars('amount') }} as amount_usd ``` + We have to use quotes to pass the _string_ `'amount'` to the macro. Without the quotes, the Jinja parser will look for a variable named `amount`. Since this doesn't exist, it will compile to nothing. diff --git a/website/docs/faqs/which-jinja-docs.md b/website/docs/faqs/Jinja/which-jinja-docs.md similarity index 60% rename from website/docs/faqs/which-jinja-docs.md rename to website/docs/faqs/Jinja/which-jinja-docs.md index 47995df9835..5272509e8b4 100644 --- a/website/docs/faqs/which-jinja-docs.md +++ b/website/docs/faqs/Jinja/which-jinja-docs.md @@ -1,9 +1,12 @@ --- title: Which docs should I use when writing Jinja or creating a macro? +description: "Useful Jinja docs" +sidebar_label: 'Useful Jinja docs' +id: which-jinja-docs --- If you are stuck with a Jinja issue, it can get confusing where to check for more information. We recommend you check (in order): 1. [Jinja's Template Designer Docs](https://jinja.palletsprojects.com/page/templates/): This is the best reference for most of the Jinja you'll use -2. [Our Jinja function reference](dbt-jinja-functions): This documents any additional functionality we've added to Jinja in dbt. -3. [Agate's table docs](https://agate.readthedocs.io/page/api/table.html): If you're operating on the result of a query, dbt will pass it back to you as an agate table. This means that the methods you call on the table belong to the Agate library rather than Jinja or dbt. +2. [Our Jinja function reference](/docs/building-a-dbt-project/jinja-macros#related-reference-docs): This documents any additional functionality we've added to Jinja in dbt. +3. [Agate's table docs](https://agate.readthedocs.io/page/api/table.html): If you're operating on the result of a query, dbt will pass it back to you as an agate table. This means that the methods you call on the belong to the Agate library rather than Jinja or dbt. diff --git a/website/docs/faqs/available-configurations.md b/website/docs/faqs/Models/available-configurations.md similarity index 63% rename from website/docs/faqs/available-configurations.md rename to website/docs/faqs/Models/available-configurations.md index 7efc18cc566..5d59dfd4246 100644 --- a/website/docs/faqs/available-configurations.md +++ b/website/docs/faqs/Models/available-configurations.md @@ -1,10 +1,14 @@ --- -title: What other model configurations are there? +title: What model configurations exist? +description: "Learning about model configurations" +sidebar_label: 'Model configurations' +id: available-configurations --- You can also configure: + * [tags](resource-configs/tags) to support easy categorization and graph selection * [custom schemas](resource-configs/schema) to split your models across multiple schemas -* [aliases](resource-configs/alias) if your view/table name should differ from the filename +* [aliases](resource-configs/alias) if your / name should differ from the filename * Snippets of SQL to run at the start or end of a model, known as [hooks](hooks-operations) * Warehouse-specific configurations for performance (e.g. `sort` and `dist` keys on Redshift, `partitions` on BigQuery) diff --git a/website/docs/faqs/Models/available-materializations.md b/website/docs/faqs/Models/available-materializations.md new file mode 100644 index 00000000000..f8b1530aca4 --- /dev/null +++ b/website/docs/faqs/Models/available-materializations.md @@ -0,0 +1,10 @@ +--- +title: What materializations are available in dbt? +description: "dbt uses 4 materializations" +sidebar_label: 'Materializations available' +id: available-materializations +--- + +dbt ships with four materializations: `view`, `table`, `incremental` and `ephemeral`. Check out the documentation on [materializations](materializations) for more information on each of these options. + +You can also create your own [custom materializations](creating-new-materializations), if required however this is an advanced feature of dbt. diff --git a/website/docs/faqs/configurable-model-path.md b/website/docs/faqs/Models/configurable-model-path.md similarity index 82% rename from website/docs/faqs/configurable-model-path.md rename to website/docs/faqs/Models/configurable-model-path.md index 39933c88dd2..9d16bb1f05f 100644 --- a/website/docs/faqs/configurable-model-path.md +++ b/website/docs/faqs/Models/configurable-model-path.md @@ -1,5 +1,9 @@ --- title: Can I store my models in a directory other than the `models` directory in my project? +description: "How to name models directory" +sidebar_label: 'How to name models directory' +id: configurable-model-path + --- diff --git a/website/docs/faqs/Models/create-a-schema.md b/website/docs/faqs/Models/create-a-schema.md new file mode 100644 index 00000000000..4bac0cfcd53 --- /dev/null +++ b/website/docs/faqs/Models/create-a-schema.md @@ -0,0 +1,8 @@ +--- +title: Do I need to create my target schema before running dbt? +description: "Target schema is checked or created for you before running dbt" +sidebar_label: 'Target schema before running dbt' +id: create-a-schema + +--- +Nope! dbt will check if the schema exists when it runs. If the schema does not exist, dbt will create it for you. diff --git a/website/docs/faqs/create-dependencies.md b/website/docs/faqs/Models/create-dependencies.md similarity index 84% rename from website/docs/faqs/create-dependencies.md rename to website/docs/faqs/Models/create-dependencies.md index d1b112d3695..6ca7d044fb6 100644 --- a/website/docs/faqs/create-dependencies.md +++ b/website/docs/faqs/Models/create-dependencies.md @@ -1,5 +1,9 @@ --- title: How do I create dependencies between models? +description: "Using ref function to create dependencies" +sidebar_label: 'Creating dependencies between models' +id: create-dependencies + --- When you use the `ref` [function](dbt-jinja-functions/ref), dbt automatically infers the dependencies between models. @@ -40,4 +44,4 @@ Found 2 models, 28 tests, 0 snapshots, 0 analyses, 130 macros, 0 operations, 0 s Done. PASS=2 WARN=0 ERROR=0 SKIP=0 TOTAL=2 ``` -To get some practice with this, we recommend you complete the [tutorial](tutorial/1-setting-up.md) to build your first dbt project +To learn more about building a dbt project, we recommend you complete the [Getting Started guide](/guides/getting-started). diff --git a/website/docs/faqs/Models/insert-records.md b/website/docs/faqs/Models/insert-records.md new file mode 100644 index 00000000000..83e69e1307c --- /dev/null +++ b/website/docs/faqs/Models/insert-records.md @@ -0,0 +1,12 @@ +--- +title: If models can only be `select` statements, how do I insert records? +description: "Incremental models to insert records" +sidebar_label: 'How to insert records' +id: insert-records + +--- + +For those coming from an (Extract Transform Load) paradigm, there's often a desire to write transformations as `insert` and `update` statements. In comparison, dbt will wrap your `select` query in a `create table as` statement, which can feel counter-productive. + +* If you wish to use `insert` statements for performance reasons (i.e. to reduce data that is processed), consider [incremental models](configuring-incremental-models) +* If you wish to use `insert` statements since your source data is constantly changing (e.g. to create "Type 2 Slowly Changing Dimensions"), consider [snapshotting your source data](snapshots), and building models on top of your snaphots. diff --git a/website/docs/faqs/model-custom-schemas.md b/website/docs/faqs/Models/model-custom-schemas.md similarity index 71% rename from website/docs/faqs/model-custom-schemas.md rename to website/docs/faqs/Models/model-custom-schemas.md index dbf3ec113ce..4a00ea9e7be 100644 --- a/website/docs/faqs/model-custom-schemas.md +++ b/website/docs/faqs/Models/model-custom-schemas.md @@ -1,7 +1,10 @@ --- -title: Can I build my models in a schema other than my target schema? +title: Can I build my models in a schema other than my target schema or split my models across multiple schemas? +description: "You can build models outside target schema" +sidebar_label: 'How to build models in schema(s) outside target schema' +id: model-custom-schemas + --- -## Or: Can I split my models across multiple schemas? Yes! Use the [schema](reference/resource-configs/schema.md) configuration in your `dbt_project.yml` file, or using a `config` block: @@ -20,7 +23,6 @@ models: - ```sql diff --git a/website/docs/faqs/reference-models-in-another-project.md b/website/docs/faqs/Models/reference-models-in-another-project.md similarity index 55% rename from website/docs/faqs/reference-models-in-another-project.md rename to website/docs/faqs/Models/reference-models-in-another-project.md index 02c1e21aa24..824145fbb79 100644 --- a/website/docs/faqs/reference-models-in-another-project.md +++ b/website/docs/faqs/Models/reference-models-in-another-project.md @@ -1,7 +1,11 @@ --- title: How can I reference models or macros in another project? +description: "Use packages to add another project to your dbt project" +sidebar_label: 'Reference models or macros in another project' +id: reference-models-in-another-project + --- You can use [packages](package-management) to add another project to your dbt project, including other projects you've created. Check out the [docs](package-management) -for more information! +for more information! diff --git a/website/docs/faqs/removing-deleted-models.md b/website/docs/faqs/Models/removing-deleted-models.md similarity index 59% rename from website/docs/faqs/removing-deleted-models.md rename to website/docs/faqs/Models/removing-deleted-models.md index 53081226084..05682465dc0 100644 --- a/website/docs/faqs/removing-deleted-models.md +++ b/website/docs/faqs/Models/removing-deleted-models.md @@ -1,9 +1,13 @@ --- title: How do I remove deleted models from my data warehouse? +description: "Remove deleted models directly in your data warehouse" +sidebar_label: 'Removing deleted models from your warehouse' +id: removing-deleted-models + --- If you delete a model from your dbt project, dbt does not automatically drop the relation from your schema. This means that you can end up with extra objects in schemas that dbt creates, which can be confusing to other users. -(This can also happen when you switch a model from being a view or table, to ephemeral) +(This can also happen when you switch a model from being a or , to ephemeral) When you remove models from your dbt project, you should manually drop the related relations from your schema. diff --git a/website/docs/faqs/run-downtime.md b/website/docs/faqs/Models/run-downtime.md similarity index 59% rename from website/docs/faqs/run-downtime.md rename to website/docs/faqs/Models/run-downtime.md index 5b976bde258..4c19511061b 100644 --- a/website/docs/faqs/run-downtime.md +++ b/website/docs/faqs/Models/run-downtime.md @@ -1,6 +1,10 @@ --- title: If I rerun dbt, will there be any downtime as models are rebuilt? +description: "No downtime when re-building models in dbt " +sidebar_label: 'Re-building models in dbt atomically' +id: run-downtime + --- Nope! The SQL that dbt generates behind the scenes ensures that any relations are replaced atomically (i.e. your business users won't experience any downtime). -The implementation of this varies on each warehouse, check out the [logs](faqs/checking-logs.md) to see the SQL dbt is executing. +The implementation of this varies on each warehouse, check out the [logs](/docs/faqs/Runs/checking-logs) to see the SQL dbt is executing. diff --git a/website/docs/faqs/source-quotes.md b/website/docs/faqs/Models/source-quotes.md similarity index 86% rename from website/docs/faqs/source-quotes.md rename to website/docs/faqs/Models/source-quotes.md index 5b010dc1e70..da5a278669b 100644 --- a/website/docs/faqs/source-quotes.md +++ b/website/docs/faqs/Models/source-quotes.md @@ -1,5 +1,9 @@ --- title: I need to use quotes to select from my source, what should I do? +description: "Use quoting property to quote values" +sidebar_label: 'How to quote values' +id: source-quotes + --- This is reasonably common on Snowflake in particular. diff --git a/website/docs/faqs/specifying-column-types.md b/website/docs/faqs/Models/specifying-column-types.md similarity index 84% rename from website/docs/faqs/specifying-column-types.md rename to website/docs/faqs/Models/specifying-column-types.md index c4a90afc0e8..f7cf439bc4b 100644 --- a/website/docs/faqs/specifying-column-types.md +++ b/website/docs/faqs/Models/specifying-column-types.md @@ -1,5 +1,9 @@ --- title: How do I specify column types? +description: "Specify column types in models" +sidebar_label: 'Specify column types in models' +id: specifying-column-types + --- Simply cast the column to the correct type in your model: @@ -22,7 +26,7 @@ insert into dbt_alice.my_table ( ) ``` -In comparison, dbt would build this table using a `create table as` statement: +In comparison, dbt would build this using a `create table as` statement: ```sql create table dbt_alice.my_table as ( @@ -33,6 +37,7 @@ create table dbt_alice.my_table as ( So long as your model queries return the correct column type, the table you create will also have the correct column type. To define additional column options: + * Rather than enforcing uniqueness and not-null constraints on your column, use dbt's [testing](building-a-dbt-project/tests) functionality to check that your assertions about your model hold true. * Rather than creating default values for a column, use SQL to express defaults (e.g. `coalesce(updated_at, current_timestamp()) as updated_at`) * In edge-cases where you _do_ need to alter a column (e.g. column-level encoding on Redshift), consider implementing this via a [post-hook](pre-hook-post-hook). diff --git a/website/docs/faqs/sql-dialect.md b/website/docs/faqs/Models/sql-dialect.md similarity index 72% rename from website/docs/faqs/sql-dialect.md rename to website/docs/faqs/Models/sql-dialect.md index 4f0978e0ac6..df7168a1b60 100644 --- a/website/docs/faqs/sql-dialect.md +++ b/website/docs/faqs/Models/sql-dialect.md @@ -1,14 +1,15 @@ --- -title: Which SQL dialect should I write my models in? +title: Which SQL dialect should I write my models in? Or which SQL dialect does dbt use? +description: "Use SQL dialect of your own database" +sidebar_label: 'Which SQL dialect to use?' +id: sql-dialect --- -Or: -### Which SQL dialect does dbt use? dbt can feel like magic, but it isn't actually magic. Under the hood, it's running SQL in your own warehouse — your data is not processed outside of your warehouse. -As such, your models should just use the **SQL dialect of your own database**. Then, when dbt wraps your `select` statements in the appropriate DDL or DML, it will use the correct DML for your warehouse — all of this logic is written in to dbt. +As such, your models should just use the **SQL dialect of your own database**. Then, when dbt wraps your `select` statements in the appropriate or , it will use the correct DML for your warehouse — all of this logic is written in to dbt. -You can find more information about the databases, platforms, and query engines that dbt supports in the [Supported Adapters](available-adapters) docs. +You can find more information about the databases, platforms, and query engines that dbt supports in the [Supported Data Platforms](supported-data-platforms) docs. Want to go a little deeper on how this works? Consider a snippet of SQL that works on each warehouse: @@ -21,7 +22,7 @@ select 1 as my_column -To replace an existing table, here's an _illustrative_ example of the SQL dbt will run on different warehouses (the actual SQL can get much more complicated than this!) +To replace an existing , here's an _illustrative_ example of the SQL dbt will run on different warehouses (the actual SQL can get much more complicated than this!) selected in the freshness snapshot. + +Additionally, dbt will write the freshness results to a file in the `target/` directory called `sources.json` by default. You can also override this destination, use the `-o` flag to the `dbt source freshness` command. + +After enabling source freshness within a job, configure [Artifacts](docs/dbt-cloud/using-dbt-cloud/artifacts) in your **Project Details** page, which you can find by clicking the gear icon and then selecting **Account settings**. You can see the current status for source freshness by clicking **View Sources** in the job page. diff --git a/website/docs/faqs/debugging-jinja.md b/website/docs/faqs/Project/debugging-jinja.md similarity index 72% rename from website/docs/faqs/debugging-jinja.md rename to website/docs/faqs/Project/debugging-jinja.md index 8eadf722976..bebc76b4f99 100644 --- a/website/docs/faqs/debugging-jinja.md +++ b/website/docs/faqs/Project/debugging-jinja.md @@ -1,5 +1,9 @@ --- title: How do I debug my Jinja? +description: "Using target folder or log function to debug Jinja" +sidebar_label: 'Debugging Jinja' +id: debugging-jinja + --- You should get familiar with checking the compiled SQL in `target/compiled//` and the logs in `logs/dbt.log` to see what dbt is running behind the scenes. diff --git a/website/docs/faqs/define-a-column-type.md b/website/docs/faqs/Project/define-a-column-type.md similarity index 87% rename from website/docs/faqs/define-a-column-type.md rename to website/docs/faqs/Project/define-a-column-type.md index 13f2844bc6c..0f15f9e6892 100644 --- a/website/docs/faqs/define-a-column-type.md +++ b/website/docs/faqs/Project/define-a-column-type.md @@ -1,5 +1,9 @@ --- title: How do I define a column type? +description: "Using cast function to define a column type" +sidebar_label: 'How to define a column type' +id: define-a-column-type + --- Your warehouse's SQL engine automatically assigns a [datatype](https://www.w3schools.com/sql/sql_datatypes.asp) to every column, whether it's found in a source or model. To force SQL to treat a columns a certain datatype, use `cast` functions: @@ -16,7 +20,7 @@ from {{ ref('stg_orders') }} -Many modern data warehouses now support `::` syntax as a shorthand for `cast( as )`. +Many modern s now support `::` syntax as a shorthand for `cast( as )`. diff --git a/website/docs/faqs/docs-for-multiple-projects.md b/website/docs/faqs/Project/docs-for-multiple-projects.md similarity index 80% rename from website/docs/faqs/docs-for-multiple-projects.md rename to website/docs/faqs/Project/docs-for-multiple-projects.md index 0966ec8d480..774eafb1e6e 100644 --- a/website/docs/faqs/docs-for-multiple-projects.md +++ b/website/docs/faqs/Project/docs-for-multiple-projects.md @@ -1,5 +1,9 @@ --- title: Can I render docs for multiple projects? +description: "Using packages to render docs for multiple projects" +sidebar_label: 'Render docs for multiple projects' +id: docs-for-multiple-projects + --- Yes! To do this, you'll need to create a "super project" that lists each project as a dependent [package](package-management) in a `packages.yml` file. Then run `dbt deps` to install the projects as packages, prior to running `dbt docs generate`. diff --git a/website/docs/faqs/example-projects.md b/website/docs/faqs/Project/example-projects.md similarity index 76% rename from website/docs/faqs/example-projects.md rename to website/docs/faqs/Project/example-projects.md index 26d5773867b..219397462d5 100644 --- a/website/docs/faqs/example-projects.md +++ b/website/docs/faqs/Project/example-projects.md @@ -1,12 +1,17 @@ --- title: Are there any example dbt projects? +description: "List of example dbt projects" +sidebar_label: 'dbt project examples' +id: example-projects + --- Yes! -* **Getting Started Tutorial:** You can build your own example dbt project in the [Getting Started Tutorial](tutorial/1-setting-up.md) + +* **Getting Started Tutorial:** You can build your own example dbt project in the [Getting Started Tutorial](/guides/getting-started) * **Jaffle Shop:** A demonstration project (closely related to the tutorial) for a fictional ecommerce store ([source code](https://github.com/dbt-labs/jaffle_shop)) * **MRR Playbook:** A demonstration project that models subscription revenue ([source code](https://github.com/dbt-labs/mrr-playbook), [docs](https://www.getdbt.com/mrr-playbook/#!/overview)) * **Attribution Playbook:** A demonstration project that models marketing attribution ([source code](https://github.com/dbt-labs/attribution-playbook), [docs](https://www.getdbt.com/attribution-playbook/#!/overview)) * **GitLab:** Gitlab's internal dbt project is open source and is a great example of how to use dbt at scale ([source code](https://gitlab.com/gitlab-data/analytics/-/tree/master/transform/snowflake-dbt), [docs](https://dbt.gitlabdata.com/)) -If you have an example project to add to this list, suggest an [edit](https://github.com/dbt-labs/docs.getdbt.com/edit/master/website/docs/faqs/example-projects.md). +If you have an example project to add to this list, suggest an edit by clicking **Edit this page** below. diff --git a/website/docs/faqs/exclude-table-from-freshness.md b/website/docs/faqs/Project/exclude-table-from-freshness.md similarity index 71% rename from website/docs/faqs/exclude-table-from-freshness.md rename to website/docs/faqs/Project/exclude-table-from-freshness.md index 8cd6e164ba7..c8aacce2de9 100644 --- a/website/docs/faqs/exclude-table-from-freshness.md +++ b/website/docs/faqs/Project/exclude-table-from-freshness.md @@ -1,8 +1,12 @@ --- title: How do I exclude a table from a freshness snapshot? +description: "Use null to exclude a table from a freshness snapshot" +sidebar_label: 'Exclude a table from freshness snapshot ' +id: exclude-table-from-freshness + --- -Some tables in a data source may be updated infrequently. If you've set a `freshness` property at the source level, this table is likely to fail checks. +Some tables in a data source may be updated infrequently. If you've set a `freshness` property at the source level, this is likely to fail checks. To work around this, you can set the table's freshness to null (`freshness: null`) to "unset" the freshness for a particular table: diff --git a/website/docs/faqs/multiple-resource-yml-files.md b/website/docs/faqs/Project/multiple-resource-yml-files.md similarity index 77% rename from website/docs/faqs/multiple-resource-yml-files.md rename to website/docs/faqs/Project/multiple-resource-yml-files.md index 3f736a97004..06738aeae65 100644 --- a/website/docs/faqs/multiple-resource-yml-files.md +++ b/website/docs/faqs/Project/multiple-resource-yml-files.md @@ -1,5 +1,9 @@ --- title: Should I use separate files to declare resource properties, or one large file? +description: "Structuring your files and project" +sidebar_label: 'Ways to structure your project/files' +id: multiple-resource-yml-files + --- It's up to you: - Some folks find it useful to have one file per model (or source / snapshot / seed etc) diff --git a/website/docs/faqs/project-name.md b/website/docs/faqs/Project/project-name.md similarity index 56% rename from website/docs/faqs/project-name.md rename to website/docs/faqs/Project/project-name.md index fa893d882db..ec4b393a50a 100644 --- a/website/docs/faqs/project-name.md +++ b/website/docs/faqs/Project/project-name.md @@ -1,4 +1,8 @@ --- title: What should I name my dbt project? +description: "Using snake_case to name your dbt project" +sidebar_label: 'How to format your dbt project name' +id: project-name + --- The name of your company (in `snake_case`) often makes for a good [project name](reference/project-configs/name.md). diff --git a/website/docs/faqs/properties-not-in-config.md b/website/docs/faqs/Project/properties-not-in-config.md similarity index 86% rename from website/docs/faqs/properties-not-in-config.md rename to website/docs/faqs/Project/properties-not-in-config.md index 9ef7ef86bf9..64d3376553f 100644 --- a/website/docs/faqs/properties-not-in-config.md +++ b/website/docs/faqs/Project/properties-not-in-config.md @@ -1,5 +1,9 @@ --- title: Can I add tests and descriptions in a config block? +description: "Types of properties defined in config blocks" +sidebar_label: 'Types of properties defined in config blocks' +id: properties-not-in-config + --- In v0.21, dbt added the ability to define node configs in `.yml` files, in addition to `config()` blocks and `dbt_project.yml`. But the reverse isn't always true: there are some things in `.yml` files that can _only_ be defined there. diff --git a/website/docs/faqs/resource-yml-name.md b/website/docs/faqs/Project/resource-yml-name.md similarity index 84% rename from website/docs/faqs/resource-yml-name.md rename to website/docs/faqs/Project/resource-yml-name.md index 79baf07b5ca..a528a6392e2 100644 --- a/website/docs/faqs/resource-yml-name.md +++ b/website/docs/faqs/Project/resource-yml-name.md @@ -1,5 +1,9 @@ --- title: If I can name these files whatever I'd like, what should I name them? +description: "Recommendations on how to name your files" +sidebar_label: 'How to name your files' +id: resource-yml-name + --- It's up to you! Here's a few options: - Default to the existing terminology: `schema.yml` (though this does make it hard to find the right file over time) diff --git a/website/docs/faqs/schema-yml-name.md b/website/docs/faqs/Project/schema-yml-name.md similarity index 78% rename from website/docs/faqs/schema-yml-name.md rename to website/docs/faqs/Project/schema-yml-name.md index e7563caaba2..9f8683647ca 100644 --- a/website/docs/faqs/schema-yml-name.md +++ b/website/docs/faqs/Project/schema-yml-name.md @@ -1,5 +1,9 @@ --- title: Does my `.yml` file containing tests and descriptions need to be named `schema.yml`? +description: "Naming your Tests and Descriptions files" +sidebar_label: 'How to name your tests and descriptions files' +id: schema-yml-name + --- No! You can name this file whatever you want (including `whatever_you_want.yml`), so long as: * The file is in your `models/` directory¹ diff --git a/website/docs/faqs/separate-profile.md b/website/docs/faqs/Project/separate-profile.md similarity index 68% rename from website/docs/faqs/separate-profile.md rename to website/docs/faqs/Project/separate-profile.md index 0cdda094f0a..b2a6f521dc3 100644 --- a/website/docs/faqs/separate-profile.md +++ b/website/docs/faqs/Project/separate-profile.md @@ -1,5 +1,9 @@ --- title: Why are profiles stored outside of my project? +description: "Profiles stored outside version control" +sidebar_label: 'Profiles stored outside project' +id: separate-profile + --- Profiles are stored separately to dbt projects to avoid checking credentials into version control. Database credentials are extremely sensitive information and should **never be checked into version control**. diff --git a/website/docs/faqs/source-has-bad-name.md b/website/docs/faqs/Project/source-has-bad-name.md similarity index 83% rename from website/docs/faqs/source-has-bad-name.md rename to website/docs/faqs/Project/source-has-bad-name.md index e091ee01421..10fb2f03d78 100644 --- a/website/docs/faqs/source-has-bad-name.md +++ b/website/docs/faqs/Project/source-has-bad-name.md @@ -1,5 +1,9 @@ --- title: What if my source is in a poorly named schema or table? +description: "Use schema and identifier properities to define names" +sidebar_label: 'Source is in a poorly-named scheme or table' +id: source-has-bad-name + --- By default, dbt will use the `name:` parameters to construct the source reference. diff --git a/website/docs/faqs/source-in-different-database.md b/website/docs/faqs/Project/source-in-different-database.md similarity index 67% rename from website/docs/faqs/source-in-different-database.md rename to website/docs/faqs/Project/source-in-different-database.md index 475aa41de2b..cdfa3c62b76 100644 --- a/website/docs/faqs/source-in-different-database.md +++ b/website/docs/faqs/Project/source-in-different-database.md @@ -1,5 +1,9 @@ --- title: What if my source is in a different database to my target database? +description: "Use database property to define source in a diff database" +sidebar_label: 'Source is in a different database to target database' +id: source-in-different-database + --- Use the [`database` property](resource-properties/database) to define the database that the source is in. diff --git a/website/docs/faqs/structure-a-project.md b/website/docs/faqs/Project/structure-a-project.md similarity index 69% rename from website/docs/faqs/structure-a-project.md rename to website/docs/faqs/Project/structure-a-project.md index d1e2c240cf7..e627c5e4793 100644 --- a/website/docs/faqs/structure-a-project.md +++ b/website/docs/faqs/Project/structure-a-project.md @@ -1,5 +1,9 @@ --- title: How should I structure my project? +description: "Recommendations on how to structure project" +sidebar_label: 'How to structure project' +id: structure-a-project + --- There's no one best way to structure a project! Every organization is unique. diff --git a/website/docs/faqs/Project/which-materialization.md b/website/docs/faqs/Project/which-materialization.md new file mode 100644 index 00000000000..32599a61746 --- /dev/null +++ b/website/docs/faqs/Project/which-materialization.md @@ -0,0 +1,10 @@ +--- +title: Which materialization should I use for my model? +description: "Recommendations on materializations to use for models" +sidebar_label: 'What materializations to use' +id: which-materialization + +--- +Start out with views, and then change models to tables when required for performance reasons (i.e. downstream queries have slowed). + +Check out the [docs on materializations](materializations) for advice on when to use each . diff --git a/website/docs/faqs/which-schema.md b/website/docs/faqs/Project/which-schema.md similarity index 78% rename from website/docs/faqs/which-schema.md rename to website/docs/faqs/Project/which-schema.md index 0378410b19f..56a2a87d844 100644 --- a/website/docs/faqs/which-schema.md +++ b/website/docs/faqs/Project/which-schema.md @@ -1,5 +1,9 @@ --- title: How did dbt choose which schema to build my models in? +description: "You can change your target schema in your Environment Settings." +sidebar_label: 'dbt builds models in your target schema' +id: which-schema + --- By default, dbt builds models in your target schema. To change your target schema: * If you're developing in **dbt Cloud**, these are set for each user when you first use a development environment. @@ -7,4 +11,4 @@ By default, dbt builds models in your target schema. To change your target schem If you wish to split your models across multiple schemas, check out the docs on [using custom schemas](using-custom-schemas). -Note: on BigQuery, `dataset` is used interchangeably with `schema`. \ No newline at end of file +Note: on BigQuery, `dataset` is used interchangeably with `schema`. diff --git a/website/docs/faqs/why-not-write-dml.md b/website/docs/faqs/Project/why-not-write-dml.md similarity index 63% rename from website/docs/faqs/why-not-write-dml.md rename to website/docs/faqs/Project/why-not-write-dml.md index 7e7ae1057b7..cf778c2086c 100644 --- a/website/docs/faqs/why-not-write-dml.md +++ b/website/docs/faqs/Project/why-not-write-dml.md @@ -1,15 +1,20 @@ --- -title: Why can't I just write DML in my transformations? +title: "Why can't I just write DML in my transformations?" +description: "Using SQL in your transformations instead of DML." +sidebar_label: 'Why not write in DML' +id: why-not-write-dml + --- -Or: -### I'm already familiar with DML, and can write these statements manually, why should I use dbt to do this? #### `select` statements make transformations accessible -More people know how to write `select` statements, than DML, making the transformation layer accessible to more people! -#### Writing good DML is hard. -If you write the DDL / DML yourself you can end up getting yourself tangled in problems like: -* What happens if the table already exists? Or this table already exists as a view, but now I want it to be a table? +More people know how to write `select` statements, than , making the transformation layer accessible to more people! + +#### Writing good DML is hard + +If you write the / DML yourself you can end up getting yourself tangled in problems like: + +* What happens if the already exists? Or this table already exists as a , but now I want it to be a table? * What if the schema already exists? Or, should I check if the schema already exists? * How do I replace a model atomically (such that there's no down-time for someone querying the table) * What if I want to parameterize my schema so I can run these transformations in a development environment? @@ -18,9 +23,11 @@ If you write the DDL / DML yourself you can end up getting yourself tangled in p Each of these problems _can_ be solved, but they are unlikely to be the best use of your time. #### dbt does more than generate SQL + You can test your models, generate documentation, create snapshots, and more! #### You reduce your vendor lock in + SQL dialects tend to diverge the most in DML and DDL (rather than in `select` statements) — check out the example [here](sql-dialect). By writing less SQL, it can make a migration to a new database technology easier. If you do need to write custom DML, there are ways to do this in dbt using [custom materializations](creating-new-materializations). diff --git a/website/docs/faqs/why-so-many-macros.md b/website/docs/faqs/Project/why-so-many-macros.md similarity index 77% rename from website/docs/faqs/why-so-many-macros.md rename to website/docs/faqs/Project/why-so-many-macros.md index 574c86a0899..5687d119cf8 100644 --- a/website/docs/faqs/why-so-many-macros.md +++ b/website/docs/faqs/Project/why-so-many-macros.md @@ -1,10 +1,14 @@ --- title: Why does my dbt output have so many macros in it? +description: "Your dbt project includes many macros." +sidebar_label: 'dbt project has a lot of macros' +id: why-so-many-macros + --- The output of a dbt run counts over 100 macros in your project! -``` +```shell $ dbt run Running with dbt=0.17.0 Found 1 model, 0 tests, 0 snapshots, 0 analyses, 138 macros, 0 operations, 0 seed files, 0 sources diff --git a/website/docs/faqs/why-version-2.md b/website/docs/faqs/Project/why-version-2.md similarity index 78% rename from website/docs/faqs/why-version-2.md rename to website/docs/faqs/Project/why-version-2.md index aec614f2c3c..c86aab37262 100644 --- a/website/docs/faqs/why-version-2.md +++ b/website/docs/faqs/Project/why-version-2.md @@ -1,5 +1,9 @@ --- title: "Why do model and source yml files always start with `version: 2`?" +description: ".yml file structure more extensible with version 2." +sidebar_label: 'Why does yml file start with version 2' +id: why-version-2 + --- Once upon a time, the structure of these `.yml` files was very different (s/o to anyone who was using dbt back then!). Adding `version: 2` allowed us to make this structure more extensible. diff --git a/website/docs/faqs/Project/yaml-file-extension.md b/website/docs/faqs/Project/yaml-file-extension.md new file mode 100644 index 00000000000..6ba113db52c --- /dev/null +++ b/website/docs/faqs/Project/yaml-file-extension.md @@ -0,0 +1,9 @@ +--- +title: Can I use a yaml file extension? +description: "dbt will only search for files with a `.yml` file extension" +sidebar_label: '.yml file extension search' +id: yaml-file-extension + +--- + +No. At present, dbt will only search for files with a `.yml` file extension. In a future release of dbt, dbt will also search for files with a `.yaml` file extension. diff --git a/website/docs/faqs/Runs/checking-logs.md b/website/docs/faqs/Runs/checking-logs.md new file mode 100644 index 00000000000..dbfdb6806a1 --- /dev/null +++ b/website/docs/faqs/Runs/checking-logs.md @@ -0,0 +1,16 @@ +--- +title: How can I see the SQL that dbt is running? +description: "Review logs to check the sql dbt is running" +sidebar_label: 'Reviewing sql that dbt runs' +id: checking-logs + +--- + +To check out the SQL that dbt is running, you can look in: + +* dbt Cloud: + * Within the run output, click on a model name, and then select "Details" +* dbt CLI: + * The `target/compiled/` directory for compiled `select` statements + * The `target/run/` directory for compiled `create` statements + * The `logs/dbt.log` file for verbose logging. diff --git a/website/docs/faqs/failed-prod-run.md b/website/docs/faqs/Runs/failed-prod-run.md similarity index 67% rename from website/docs/faqs/failed-prod-run.md rename to website/docs/faqs/Runs/failed-prod-run.md index 575419a20bd..23cabad7692 100644 --- a/website/docs/faqs/failed-prod-run.md +++ b/website/docs/faqs/Runs/failed-prod-run.md @@ -1,5 +1,9 @@ --- title: What happens if one of my runs fails? +description: "Set up notifications to debug failed runs" +sidebar_label: 'Notifications to debug failed runs' +id: failed-prod-run + --- If you're using dbt Cloud, we recommend setting up email and Slack notifications (`Account Settings > Notifications`) for any failed runs. Then, debug these runs the same way you would debug any runs in development. diff --git a/website/docs/faqs/Runs/failed-tests.md b/website/docs/faqs/Runs/failed-tests.md new file mode 100644 index 00000000000..bfee565ef61 --- /dev/null +++ b/website/docs/faqs/Runs/failed-tests.md @@ -0,0 +1,18 @@ +--- +title: One of my tests failed, how can I debug it? +description: "You can debug failed tests by finding the SQL" +sidebar_label: 'Debug failed tests' +id: failed-tests + +--- +To debug a failing test, find the SQL that dbt ran by: + +* dbt Cloud: + * Within the test output, click on the failed test, and then select "Details" + +* dbt CLI: + * Open the file path returned as part of the error message. + * Navigate to the `target/compiled/schema_tests` directory for all compiled test queries + +Copy the SQL into a query editor (in dbt Cloud, you can paste it into a new `Statement`), and run the query to find the records that failed. + diff --git a/website/docs/faqs/run-downstream-of-seed.md b/website/docs/faqs/Runs/run-downstream-of-seed.md similarity index 67% rename from website/docs/faqs/run-downstream-of-seed.md rename to website/docs/faqs/Runs/run-downstream-of-seed.md index f8b288aa2e2..bbf295f403d 100644 --- a/website/docs/faqs/run-downstream-of-seed.md +++ b/website/docs/faqs/Runs/run-downstream-of-seed.md @@ -1,11 +1,15 @@ --- title: How do I run models downstream of a seed? +description: "You run models downstread using model selection syntax" +sidebar_label: 'Run models downstream of a seed' +id: run-downstream-of-seed + --- You can run models downstream of a seed using the [model selection syntax](node-selection/syntax), and treating the seed like a model. For example, the following would run all models downstream of a seed named `country_codes`: -``` +```shell $ dbt run --select country_codes+ ``` diff --git a/website/docs/faqs/run-one-model.md b/website/docs/faqs/Runs/run-one-model.md similarity index 69% rename from website/docs/faqs/run-one-model.md rename to website/docs/faqs/Runs/run-one-model.md index 15747c60849..dfbb54f2087 100644 --- a/website/docs/faqs/run-one-model.md +++ b/website/docs/faqs/Runs/run-one-model.md @@ -1,11 +1,14 @@ --- title: How do I run one model at a time? +description: "Use select flags to run one model at a time" +sidebar_label: 'Run one model at a time' +id: run-one-model + --- To run one model, use the `--select` flag (or `-s` flag), followed by the name of the model: - -``` +```shell $ dbt run --select customers ``` diff --git a/website/docs/faqs/run-one-snapshot.md b/website/docs/faqs/Runs/run-one-snapshot.md similarity index 68% rename from website/docs/faqs/run-one-snapshot.md rename to website/docs/faqs/Runs/run-one-snapshot.md index 31c7d7e0e11..7029f3c02da 100644 --- a/website/docs/faqs/run-one-snapshot.md +++ b/website/docs/faqs/Runs/run-one-snapshot.md @@ -1,11 +1,14 @@ --- title: How do I run one snapshot at a time? +description: "Use select flags to run one snapshot at a time" +sidebar_label: 'Run one snapshot at a time' +id: run-one-snapshot + --- To run one snapshot, use the `--select` flag, followed by the name of the snapshot: - -``` +```shell $ dbt snapshot --select order_snapshot ``` diff --git a/website/docs/faqs/running-models-downstream-of-source.md b/website/docs/faqs/Runs/running-models-downstream-of-source.md similarity index 60% rename from website/docs/faqs/running-models-downstream-of-source.md rename to website/docs/faqs/Runs/running-models-downstream-of-source.md index 92fd0def5c3..9a56dd81294 100644 --- a/website/docs/faqs/running-models-downstream-of-source.md +++ b/website/docs/faqs/Runs/running-models-downstream-of-source.md @@ -1,16 +1,20 @@ --- title: How do I run models downstream of one source? +description: "Use source selector to run models downstream of a source" +sidebar_label: 'Run models downstream of one source' +id: running-model-downstream-of-source + --- To run models downstream of a source, use the `source:` selector: -``` +```shell $ dbt run --select source:jaffle_shop+ ``` (You can also use the `-s` shorthand here instead of `--select`) -To run models downstream of one source table: +To run models downstream of one source : -``` +```shell $ dbt run --select source:jaffle_shop.orders+ ``` diff --git a/website/docs/faqs/snapshot-frequency.md b/website/docs/faqs/Runs/snapshot-frequency.md similarity index 79% rename from website/docs/faqs/snapshot-frequency.md rename to website/docs/faqs/Runs/snapshot-frequency.md index 3f78584effc..9a964b94cc7 100644 --- a/website/docs/faqs/snapshot-frequency.md +++ b/website/docs/faqs/Runs/snapshot-frequency.md @@ -1,5 +1,9 @@ --- title: How often should I run the snapshot command? +description: "Snapshot command intended to run on hourly/daily schedule " +sidebar_label: 'Snapshot command schedule' +id: snapshot-frequency + --- Snapshots are a batch-based approach to [change data capture](https://en.wikipedia.org/wiki/Change_data_capture). The `dbt snapshot` command must be run on a schedule to ensure that changes to tables are actually recorded! While individual use-cases may vary, snapshots are intended to be run between hourly and daily. If you find yourself snapshotting more frequently than that, consider if there isn't a more appropriate way to capture changes in your source data tables. diff --git a/website/docs/faqs/build-one-seed.md b/website/docs/faqs/Seeds/build-one-seed.md similarity index 73% rename from website/docs/faqs/build-one-seed.md rename to website/docs/faqs/Seeds/build-one-seed.md index bdd80651a07..974258cbe19 100644 --- a/website/docs/faqs/build-one-seed.md +++ b/website/docs/faqs/Seeds/build-one-seed.md @@ -1,11 +1,18 @@ --- title: How do I build one seed at a time? +description: "Use select flag to build one seed at a time" +sidebar_label: "Build one seed at a time" +id: build-one-seed --- + As of v0.16.0, you can use a `--select` option with the `dbt seed` command, like so: -``` +```shell + $ dbt seed --select country_codes + ``` + There is also an `--exclude` option. Check out more in the [model selection syntax](node-selection/syntax) documentation. diff --git a/website/docs/faqs/full-refresh-seed.md b/website/docs/faqs/Seeds/full-refresh-seed.md similarity index 84% rename from website/docs/faqs/full-refresh-seed.md rename to website/docs/faqs/Seeds/full-refresh-seed.md index 4e0e5575337..b59f7a8f60d 100644 --- a/website/docs/faqs/full-refresh-seed.md +++ b/website/docs/faqs/Seeds/full-refresh-seed.md @@ -1,5 +1,9 @@ --- title: The columns of my seed changed, and now I get an error when running the `seed` command, what should I do? +description: "Rerun the command with a `--full-refresh` flag" +sidebar_label: 'debug error when columns of seed changes' +id: full-refresh-seed + --- If you changed the columns of your seed, you may get a `Database Error`: @@ -12,7 +16,7 @@ If you changed the columns of your seed, you may get a `Database Error`: }> -``` +```shell $ dbt seed Running with dbt=0.16.0-rc2 Found 0 models, 0 tests, 0 snapshots, 0 analyses, 130 macros, 0 operations, 1 seed file, 0 sources @@ -37,7 +41,7 @@ Done. PASS=0 WARN=0 ERROR=1 SKIP=0 TOTAL=1 -``` +```shell $ dbt seed Running with dbt=0.16.0-rc2 Found 0 models, 0 tests, 0 snapshots, 0 analyses, 149 macros, 0 operations, 1 seed file, 0 sources @@ -62,13 +66,14 @@ Done. PASS=0 WARN=0 ERROR=1 SKIP=0 TOTAL=1 In this case, you should rerun the command with a `--full-refresh` flag, like so: -``` + +```shell dbt seed --full-refresh ``` **Why is this the case?** -When you typically run dbt seed, dbt truncates the existing table and reinserts the data. This pattern avoids a `drop cascade` command, which may cause downstream objects (that your BI users might be querying!) to get dropped. +When you typically run dbt seed, dbt truncates the existing and reinserts the data. This pattern avoids a `drop cascade` command, which may cause downstream objects (that your BI users might be querying!) to get dropped. However, when column names are changed, or new columns are added, these statements will fail as the table structure has changed. diff --git a/website/docs/faqs/leading-zeros-in-seed.md b/website/docs/faqs/Seeds/leading-zeros-in-seed.md similarity index 75% rename from website/docs/faqs/leading-zeros-in-seed.md rename to website/docs/faqs/Seeds/leading-zeros-in-seed.md index c59e663c9cc..f2ffeb05f3f 100644 --- a/website/docs/faqs/leading-zeros-in-seed.md +++ b/website/docs/faqs/Seeds/leading-zeros-in-seed.md @@ -1,5 +1,9 @@ --- title: How do I preserve leading zeros in a seed? +description: "Use column types to include leading zeros in seed" +sidebar_label: 'Include leading zeroes in your seed file' +id: leading-zeros-in-seed + --- If you need to preserve leading zeros (for example in a zipcode or mobile number): diff --git a/website/docs/faqs/load-raw-data-with-seed.md b/website/docs/faqs/Seeds/load-raw-data-with-seed.md similarity index 72% rename from website/docs/faqs/load-raw-data-with-seed.md rename to website/docs/faqs/Seeds/load-raw-data-with-seed.md index 142ce37979e..e33780f5dcc 100644 --- a/website/docs/faqs/load-raw-data-with-seed.md +++ b/website/docs/faqs/Seeds/load-raw-data-with-seed.md @@ -1,9 +1,13 @@ --- title: Can I use seeds to load raw data? +description: "Use seeds to load business specific logic" +sidebar_label: 'Seed data files requirements' +id: load-raw-data-with-seed + --- Seeds should **not** be used to load raw data (for example, large CSV exports from a production database). Since seeds are version controlled, they are best suited to files that contain business-specific logic, for example a list of country codes or user IDs of employees. -Loading CSVs using dbt's seed functionality is not performant for large files. Consider using a different tool to load these CSVs into your data warehouse. +Loading CSVs using dbt's seed functionality is not performant for large files. Consider using a different tool to load these CSVs into your . diff --git a/website/docs/faqs/seed-custom-schemas.md b/website/docs/faqs/Seeds/seed-custom-schemas.md similarity index 70% rename from website/docs/faqs/seed-custom-schemas.md rename to website/docs/faqs/Seeds/seed-custom-schemas.md index 3031600029e..66b17807904 100644 --- a/website/docs/faqs/seed-custom-schemas.md +++ b/website/docs/faqs/Seeds/seed-custom-schemas.md @@ -1,7 +1,10 @@ --- -title: Can I build my seeds in a schema other than my target schema? +title: Can I build my seeds in a schema other than my target schema or can I split my seeds across multiple schemas? +description: "Use schema config in your dbt_project.yml file" +sidebar_label: 'Build seeds in a schema outside target schema' +id: seed-custom-schemas + --- -## Or: Can I split my seeds across multiple schemas? Yes! Use the [schema](reference/resource-configs/schema.md) configuration in your `dbt_project.yml` file. diff --git a/website/docs/faqs/seed-datatypes.md b/website/docs/faqs/Seeds/seed-datatypes.md similarity index 78% rename from website/docs/faqs/seed-datatypes.md rename to website/docs/faqs/Seeds/seed-datatypes.md index 75d1cb51291..cc4f7363b3c 100644 --- a/website/docs/faqs/seed-datatypes.md +++ b/website/docs/faqs/Seeds/seed-datatypes.md @@ -1,5 +1,9 @@ --- title: How do I set a datatype for a column in my seed? +description: "Use column_types to set a datatype" +sidebar_label: 'Set a datatype for a column in seed' +id: seed-datatypes + --- dbt will infer the datatype for each column based on the data in your CSV. diff --git a/website/docs/faqs/seed-hooks.md b/website/docs/faqs/Seeds/seed-hooks.md similarity index 68% rename from website/docs/faqs/seed-hooks.md rename to website/docs/faqs/Seeds/seed-hooks.md index 77daba1a558..9af3be74e13 100644 --- a/website/docs/faqs/seed-hooks.md +++ b/website/docs/faqs/Seeds/seed-hooks.md @@ -1,8 +1,13 @@ --- title: Do hooks run with seeds? +description: "Run hooks with seeds and configure them in project.yml file" +sidebar_label: "Use hooks to run with seeds" +id: seed-hooks + --- Yes! The following hooks are available: + - [pre-hooks & post-hooks](reference/resource-configs/pre-hook-post-hook.md) - [on-run-start & on-run-end hooks](reference/project-configs/on-run-start-on-run-end.md) diff --git a/website/docs/faqs/snapshot-hooks.md b/website/docs/faqs/Snapshots/snapshot-hooks.md similarity index 76% rename from website/docs/faqs/snapshot-hooks.md rename to website/docs/faqs/Snapshots/snapshot-hooks.md index df8b2429752..f60bd48e4c0 100644 --- a/website/docs/faqs/snapshot-hooks.md +++ b/website/docs/faqs/Snapshots/snapshot-hooks.md @@ -1,8 +1,13 @@ --- title: Do hooks run with snapshots? +description: "Run hooks with snapshots" +sidebar_label: 'Use hooks to run with snapshots' +id: snapshot-hooks + --- Yes! The following hooks are available for snapshots: + - [pre-hooks](/reference/resource-configs/pre-hook-post-hook/) - [post-hooks](/reference/resource-configs/pre-hook-post-hook/) - [on-run-start](/reference/resource-configs/pre-hook-post-hook/) diff --git a/website/docs/faqs/snapshot-schema-changes.md b/website/docs/faqs/Snapshots/snapshot-schema-changes.md similarity index 73% rename from website/docs/faqs/snapshot-schema-changes.md rename to website/docs/faqs/Snapshots/snapshot-schema-changes.md index 9d1e4e4378e..75a5babc748 100644 --- a/website/docs/faqs/snapshot-schema-changes.md +++ b/website/docs/faqs/Snapshots/snapshot-schema-changes.md @@ -1,7 +1,11 @@ --- title: What happens if I add new columns to my snapshot query? +description: "Reconcile changes when adding new columns in snapshot query" +sidebar_label: 'Snapshot column changes' +id: snapshot-schema-changes + --- -When the columns of your source query changes, dbt will attempt to reconcile this change in the destination snapshot table. dbt does this by: +When the columns of your source query changes, dbt will attempt to reconcile this change in the destination snapshot . dbt does this by: 1. Creating new columns from the source query in the destination table 2. Expanding the size of string types where necessary (eg. `varchar`s on Redshift) diff --git a/website/docs/faqs/snapshot-target-schema.md b/website/docs/faqs/Snapshots/snapshot-target-schema.md similarity index 89% rename from website/docs/faqs/snapshot-target-schema.md rename to website/docs/faqs/Snapshots/snapshot-target-schema.md index 9030b50009f..02cd8f4d639 100644 --- a/website/docs/faqs/snapshot-target-schema.md +++ b/website/docs/faqs/Snapshots/snapshot-target-schema.md @@ -1,5 +1,9 @@ --- title: Why is there only one `target_schema` for snapshots? +description: "Snapshots build into the same `target_schema`" +sidebar_label: 'Build snapshots into one `target_schema`' +id: snapshot-target-schema + --- Snapshots build into the same `target_schema`, no matter who is running them. diff --git a/website/docs/faqs/Snapshots/snapshotting-freshness-for-one-source.md b/website/docs/faqs/Snapshots/snapshotting-freshness-for-one-source.md new file mode 100644 index 00000000000..c1cc7687b11 --- /dev/null +++ b/website/docs/faqs/Snapshots/snapshotting-freshness-for-one-source.md @@ -0,0 +1,24 @@ +--- +title: How do I snapshot freshness for one source only? +description: "Use select flag to snapshot for specific sources" +sidebar_label: 'Snapshot freshness for specific sources.' +id: snapshotting-freshness-for-one-source + +--- + +:::info As of dbt Core v0.21, you need to prefix sources with the source: selection method. In previous versions of dbt, sources were specified by name only. ::: + +Use the `--select` flag to snapshot freshness for specific sources. Eg: + +```shell +# Snapshot freshness for all Jaffle Shop tables: +$ dbt source freshness --select source:jaffle_shop + +# Snapshot freshness for a particular source : +$ dbt source freshness --select source:jaffle_shop.orders + +# Snapshot freshness for multiple particular source tables: +$ dbt source freshness --select source:jaffle_shop.orders source:jaffle_shop.customers +``` + +See the [`source freshness` command reference](commands/source) for more information. diff --git a/website/docs/faqs/available-tests.md b/website/docs/faqs/Tests/available-tests.md similarity index 83% rename from website/docs/faqs/available-tests.md rename to website/docs/faqs/Tests/available-tests.md index 07fb08bafe1..206bb60b5bf 100644 --- a/website/docs/faqs/available-tests.md +++ b/website/docs/faqs/Tests/available-tests.md @@ -1,7 +1,12 @@ --- title: What tests are available for me to use in dbt? +description: "Types of tests to use in dbt" +sidebar_label: 'Available test to use in dbt' +id: available-tests + --- Out of the box, dbt ships with the following tests: + * `unique` * `not_null` * `accepted_values` diff --git a/website/docs/faqs/configurable-data-path.md b/website/docs/faqs/Tests/configurable-data-path.md similarity index 76% rename from website/docs/faqs/configurable-data-path.md rename to website/docs/faqs/Tests/configurable-data-path.md index 24f3f1800b7..bacc732433b 100644 --- a/website/docs/faqs/configurable-data-path.md +++ b/website/docs/faqs/Tests/configurable-data-path.md @@ -1,10 +1,14 @@ --- title: Can I store my seeds in a directory other than the `seeds` directory in my project? +description: "Where to store seeds in a directory" +sidebar_label: 'How to name seeds directory' +id: configurable-data-path + --- -- **v1.0.0:** The config 'data-paths' has been deprecated in favor of [`seed-paths`](seed-paths). +- **v1.0.0:** The config 'data-paths' has been deprecated in favor of [`seed-paths`](seed-paths). diff --git a/website/docs/faqs/configurable-data-test-path.md b/website/docs/faqs/Tests/configurable-data-test-path.md similarity index 82% rename from website/docs/faqs/configurable-data-test-path.md rename to website/docs/faqs/Tests/configurable-data-test-path.md index e4bda68b810..2c3e8d729ba 100644 --- a/website/docs/faqs/configurable-data-test-path.md +++ b/website/docs/faqs/Tests/configurable-data-test-path.md @@ -1,5 +1,9 @@ --- title: Can I store my tests in a directory other than the `tests` directory in my project? +description: "Where to store tests in a directory" +sidebar_label: 'How to name tests directory' +id: configurable-data-test-path + --- By default, dbt expects your singular test files to be located in the `tests` subdirectory of your project, and generic test definitions to be located in `tests/generic` or `macros`. diff --git a/website/docs/faqs/Tests/custom-test-thresholds.md b/website/docs/faqs/Tests/custom-test-thresholds.md new file mode 100644 index 00000000000..14dd36666c0 --- /dev/null +++ b/website/docs/faqs/Tests/custom-test-thresholds.md @@ -0,0 +1,14 @@ +--- +title: Can I set test failure thresholds? +description: "Use configs to set custom failure thresholds in tests" +sidebar_label: 'How to set failure thresholds in test' +id: custom-test-thresholds + +--- + +As of `v0.20.0`, you can use the `error_if` and `warn_if` configs to set custom failure thresholds in your tests. For more details, see [reference](reference/resource-configs/severity) for more information. + +For dbt `v0.19.0` and earlier, you could try these possible solutions: + +* Setting the [severity](resource-properties/tests#severity) to `warn`, or: +* Writing a [custom generic test](custom-generic-tests) that accepts a threshold argument ([example](https://discourse.getdbt.com/t/creating-an-error-threshold-for-schema-tests/966)) diff --git a/website/docs/faqs/multiple-test-files.md b/website/docs/faqs/Tests/multiple-test-files.m similarity index 60% rename from website/docs/faqs/multiple-test-files.md rename to website/docs/faqs/Tests/multiple-test-files.m index 04e62971400..2ae6f4f93d3 100644 --- a/website/docs/faqs/multiple-test-files.md +++ b/website/docs/faqs/Tests/multiple-test-files.m @@ -1,4 +1,8 @@ --- title: Do all my tests go in one file? +description: "Structuring files for tests" +sidebar_label: 'How to structure files for tests' +id: multiple-test-files + --- No! You can use as many files as you want! Some folks find it useful to have one file per model, we tend to have one per directory. diff --git a/website/docs/faqs/recommended-tests.md b/website/docs/faqs/Tests/recommended-tests.md similarity index 66% rename from website/docs/faqs/recommended-tests.md rename to website/docs/faqs/Tests/recommended-tests.md index ee1b65b01b2..b3f6e7f5c31 100644 --- a/website/docs/faqs/recommended-tests.md +++ b/website/docs/faqs/Tests/recommended-tests.md @@ -1,7 +1,11 @@ --- title: What tests should I add to my project? +description: "Recommended tests for project" +sidebar_label: 'Recommended tests for project' +id: recommended-tests + --- -We recommend that every model has a test on a primary key, that is, a column that is `unique` and `not_null`. +We recommend that every model has a test on a , that is, a column that is `unique` and `not_null`. We also recommend that you test any assumptions on your source data. For example, if you believe that your payments can only be one of three payment methods, you should test that assumption regularly — a new payment method may introduce logic errors in your SQL. diff --git a/website/docs/faqs/test-one-model.md b/website/docs/faqs/Tests/test-one-model.md similarity index 74% rename from website/docs/faqs/test-one-model.md rename to website/docs/faqs/Tests/test-one-model.md index 975c4cd5157..16f80e6934e 100644 --- a/website/docs/faqs/test-one-model.md +++ b/website/docs/faqs/Tests/test-one-model.md @@ -1,9 +1,14 @@ --- title: How do I test one model at a time? +description: "Use select flag to test one model at a time" +sidebar_label: 'Testing one model at a time' +id: test-one-model + --- Running tests on one model looks very similar to running a model: use the `--select` flag (or `-s` flag), followed by the name of the model: -``` + +```shell dbt test --select customers ``` diff --git a/website/docs/faqs/testing-seeds.md b/website/docs/faqs/Tests/testing-seeds.md similarity index 82% rename from website/docs/faqs/testing-seeds.md rename to website/docs/faqs/Tests/testing-seeds.md index 44b5a3cacc6..75c7fcf0ff1 100644 --- a/website/docs/faqs/testing-seeds.md +++ b/website/docs/faqs/Tests/testing-seeds.md @@ -1,12 +1,16 @@ --- title: How do I test and document seeds? +description: "Use a schema file to test and document seeds" +sidebar_label: 'Test and document seeds' +id: testing-seeds + --- The `seeds:` key is new in 0.16.0. Prior to this, use a `models:` key instead. To test and document seeds, use a [schema file](configs-and-properties) and nest the configurations under a `seeds:` key -## Example: +## Example diff --git a/website/docs/faqs/Tests/testing-sources.md b/website/docs/faqs/Tests/testing-sources.md new file mode 100644 index 00000000000..06051eae7e9 --- /dev/null +++ b/website/docs/faqs/Tests/testing-sources.md @@ -0,0 +1,37 @@ +--- +title: How do I run tests on just my sources? +description: "Use the select source command to test sources" +sidebar_label: 'Run tests on all sources' +id: testing-sources + +--- + +To run tests on all sources, use the following command: + +```shell +$ dbt test --select source:* +``` + +(You can also use the `-s` shorthand here instead of `--select`) + +To run tests on one source (and all of its tables): + +```shell +$ dbt test --select source:jaffle_shop +``` + +And, to run tests on one source only: + +```shell +$ dbt test --select source:jaffle_shop.orders +``` + +Yep, we know this syntax is a little less than ideal, so we're hoping to improve it in a future release. Check out the [model selection syntax](node-selection/syntax) for more examples! + + +:::info Node selection syntax +In dbt 0.21.0, the node selection syntax [was standardized](https://github.com/dbt-labs/dbt-core/pull/3791) to use `--select` everywhere. Before this, some commands like `dbt run` and `dbt test` used `--models` instead. + +Older versions still show an error because [argparse](https://docs.python.org/3/library/argparse.html#allow-abbrev) is expanding `--select` to `--selector`, which is a different flag. +To fix this issue, either upgrade to dbt 0.21.0 or higher, or use `--models` instead of `--select`. +::: diff --git a/website/docs/faqs/uniqueness-two-columns.md b/website/docs/faqs/Tests/uniqueness-two-columns.md similarity index 82% rename from website/docs/faqs/uniqueness-two-columns.md rename to website/docs/faqs/Tests/uniqueness-two-columns.md index 0e42c5ed09d..207be4372d3 100644 --- a/website/docs/faqs/uniqueness-two-columns.md +++ b/website/docs/faqs/Tests/uniqueness-two-columns.md @@ -1,11 +1,15 @@ --- title: Can I test the uniqueness of two columns? +description: "Options to test uniqueness of two columns" +sidebar_label: 'Test the uniqueness of two columns' +id: uniqueness-two-columns + --- Yes, There's a few different options. -Consider an orders table that contains records from multiple countries, and the combination of ID and country code is unique: +Consider an orders that contains records from multiple countries, and the combination of ID and country code is unique: | order_id | country_code | |----------|--------------| diff --git a/website/docs/faqs/when-to-test.md b/website/docs/faqs/Tests/when-to-test.md similarity index 72% rename from website/docs/faqs/when-to-test.md rename to website/docs/faqs/Tests/when-to-test.md index 63585a333e8..fc97f98000b 100644 --- a/website/docs/faqs/when-to-test.md +++ b/website/docs/faqs/Tests/when-to-test.md @@ -1,5 +1,9 @@ --- title: When should I run my tests? +description: "Run tests in production or when writing new code" +sidebar_label: 'When to run tests' +id: when-to-test + --- You should run your tests whenever you are writing new code (to ensure you haven't broken any existing models by changing SQL), and whenever you run your transformations in production (to ensure that your assumptions about your source data are still valid). diff --git a/website/docs/faqs/Troubleshooting/access-gdrive-credential.md b/website/docs/faqs/Troubleshooting/access-gdrive-credential.md new file mode 100644 index 00000000000..ca73c5c2631 --- /dev/null +++ b/website/docs/faqs/Troubleshooting/access-gdrive-credential.md @@ -0,0 +1,24 @@ +--- +title: I'm receiving a "Permission denied while getting Drive credential" error when trying to query from Google Drive? +description: "Grant BigQuery service account access" +sidebar_label: 'Error when trying to query from Google Drive' +id: access-gdrive-credential + +--- + +If you're seeing the below error when you try to query a dataset from a Google Drive document in the IDE, the IDE due to the below error message, we'll do our best to get you unstuck with the below steps! + +``` +Access denied: BigQuery BigQuery: Permission denied while getting Drive credentials +``` + +Usually this errors indicates that you haven't granted the BigQuery service account access to the specific Google Drive document. If you're seeing this error, try giving the service account (client email seen [here](https://docs.getdbt.com/docs/dbt-cloud/cloud-configuring-dbt-cloud/connecting-your-database#connecting-to-bigquery)) you are using for your BigQuery connection in dbt Cloud, permission to your Google Drive or Google Sheet. You'll want to do this directly in your Google Document and click the 'share' button and enter the client email there. + +If you are experiencing this error when using oAuth, and you have verified your access to the Google Sheet, you may need to grant permissions for gcloud to access Google Drive: + +``` +gcloud auth application-default login --scopes=openid,https://www.googleapis.com/auth/userinfo.email,https://www.googleapis.com/auth/cloud-platform,https://www.googleapis.com/auth/sqlservice.login,https://www.googleapis.com/auth/drive +``` +For more info see the [gcloud auth application-default documentation](https://cloud.google.com/sdk/gcloud/reference/auth/application-default/login) + +If you've tried the steps above and are still experiencing this behavior - reach out to the Support team at support@getdbt.com and we'll be happy to help! diff --git a/website/docs/faqs/Troubleshooting/access_token_error.md b/website/docs/faqs/Troubleshooting/access_token_error.md new file mode 100644 index 00000000000..85be1fcd9dc --- /dev/null +++ b/website/docs/faqs/Troubleshooting/access_token_error.md @@ -0,0 +1,21 @@ +--- +title: I'm receiving an `access_token` error when trying to run queries in the IDE. +description: "Reauthenticate warehouse when seeing `access_token` error" +sidebar_label: '`access_token` error in the IDE' +id: access_token_error + +--- + +If you're seeing the below error when you try to run queries in the IDE, have no fear - we'll do our best to get you unstuck with the following steps! + + `access_token` + +In order to resolve the issue, you'll want to: + +1. Go to you Profile (upper right corner of dbt Cloud) +2. Click on the correct warehouse connection under "Credentials" +3. Click "Connect Snowflake Account" green button in the "Development Credentials" section. This drives you through reauthentication through the SSO flow. + +If you've tried the step above and are still experiencing this behavior - reach out to the Support team at support@getdbt.com and we'll be happy to help! + + diff --git a/website/docs/faqs/dispatch-could-not-find-package.md b/website/docs/faqs/Troubleshooting/dispatch-could-not-find-package.md similarity index 60% rename from website/docs/faqs/dispatch-could-not-find-package.md rename to website/docs/faqs/Troubleshooting/dispatch-could-not-find-package.md index dea47e27f98..8b9f6c15367 100644 --- a/website/docs/faqs/dispatch-could-not-find-package.md +++ b/website/docs/faqs/Troubleshooting/dispatch-could-not-find-package.md @@ -1,10 +1,18 @@ --- -title: "[Error] Could not find package 'my_project'" +title: "[Error] Could not find my_project package" +description: "Macros missing from packages" +sidebar_label: 'Could not find package error' +id: dispatch-could-not-find-package + --- If a package name is included in the `search_order` of a project-level `dispatch` config, dbt expects that package to contain macros which are viable candidates for dispatching. If an included package does not contain _any_ macros, dbt will raise an error like: -``` + +```shell Compilation Error In dispatch: Could not find package 'my_project' ``` + This does not mean the package or root project is missing—it means that any macros from it are missing, and so it is missing from the search spaces available to `dispatch`. + +If you've tried the step above and are still experiencing this behavior - reach out to the Support team at support@getdbt.com and we'll be happy to help! diff --git a/website/docs/faqs/Troubleshooting/git-revlist-error.md b/website/docs/faqs/Troubleshooting/git-revlist-error.md new file mode 100644 index 00000000000..e90c2729ec5 --- /dev/null +++ b/website/docs/faqs/Troubleshooting/git-revlist-error.md @@ -0,0 +1,31 @@ +--- +title: I'm receiving a git rev-list master error in the IDE? +description: "Primary branch not recognized" +sidebar_label: 'git rev-list master error in the IDE' +id: git-revlist-error +--- + +If you're unable to access the IDE due to the below error message, we'll do our best to get you unstuck with the below steps! + +```shell +git rev-list master..origin/main --count +fatal: ambiguous argument 'master..origin/main': unknown revision or path not in the working tree. +Use '--' to separate paths from revisions, like this: +'git [...] -- [...]' +``` + +Usually this error indicates that the "main" branch name has changed or it is possible that dbt Cloud was unable to determine what your primary branch was. No worries, we have a few workarounds for you to try: + +**Workaround 1** +Take a look at your Environment Settings - If you **do not** have a custom branch filled in your Environment Settings: + +1. Disconnect and reconnect your repository [connection](https://docs.getdbt.com/docs/dbt-cloud/cloud-configuring-dbt-cloud/cloud-import-a-project-by-git-url) on your Project Settings page. This should then allow dbt Cloud to pick up that the "main" branch is now called `main` +2. In the Environment Settings, set the custom branch to 'master' and refresh the IDE + +**Workaround 2** +Take a look at your Environment Settings - If you **do** have a custom branch filled in your Environment Settings: + +1. Disconnecting and reconnecting your repository [connection](https://docs.getdbt.com/docs/dbt-cloud/cloud-configuring-dbt-cloud/cloud-import-a-project-by-git-url) on your Project Settings page. This should then allow dbt Cloud to pick up that the "main" branch is now called `main` +2. In the Environment Settings, remove the custom branch and refresh the IDE + +If you've tried the workarounds above and are still experiencing this behavior - reach out to the Support team at support@getdbt.com and we'll be happy to help! diff --git a/website/docs/faqs/Troubleshooting/gitignore.md b/website/docs/faqs/Troubleshooting/gitignore.md new file mode 100644 index 00000000000..47c7500e662 --- /dev/null +++ b/website/docs/faqs/Troubleshooting/gitignore.md @@ -0,0 +1,26 @@ +--- +title: Why can't I checkout a branch or create a new branch? +description: "Add or fill in gitignore file" +sidebar_label: 'Unable to checkout or create branch' +id: gitignore +--- + +If you're finding yourself unable to revert changes, check out a branch or click commit - this is usually do to your project missing a .[gitignore](https://github.com/dbt-labs/dbt-starter-project/blob/main/.gitignore) file OR your gitignore file doesn't contain the necessary content inside the folder. + +This is what causes that 'commit' git action button to display. No worries though - to fix this, you'll need to complete the following steps in order: + +1. In the Cloud IDE, add the missing .gitignore file or contents to your project. You'll want to make sure the .gitignore file includes the following: + + ```shell + target/ + dbt_modules/ + dbt_packages/ + logs/ + ``` + +2. Once you've added that, make sure to save and commit. + +3. Navigate to the same branch in your remote repository (which can be accessed directly through your git provider's web interface) and delete the logs, target, and dbt_modules/dbt_packages folders. + +4. Go back into the Cloud IDE and reclone your repository. This can be done by clicking on the green "ready" in the bottom right corner of the IDE (next to the command bar), and then clicking the orange "reclone repo" button in the pop up. + diff --git a/website/docs/faqs/Troubleshooting/gitlab-authentication.md b/website/docs/faqs/Troubleshooting/gitlab-authentication.md new file mode 100644 index 00000000000..7e7177b022a --- /dev/null +++ b/website/docs/faqs/Troubleshooting/gitlab-authentication.md @@ -0,0 +1,29 @@ +--- +title: I'm seeing a Gitlab authentication out of date error loop +description: "GitLab and dbt Cloud deploy key mismatch " +sidebar_label: 'GitLab authentication out of date' +id: gitlab-authentication +--- + +If you're seeing a 'GitLab Authentication is out of date' 500 server error page - this usually occurs when the deploy key in the repository settings in both dbt Cloud and GitLab do not match. + +No worries - this is a current issue the dbt Labs team is working on and we have a few workarounds for you to try: + +### 1st Workaround + +1. Disconnect repo from project in dbt Cloud. +2. Go to Gitlab and click on Settings > Repository. +3. Under Repository Settings, remove/revoke active dbt Cloud deploy tokens and deploy keys. +4. Attempt to reconnect your repository via dbt Cloud. +5. You would then need to check Gitlab to make sure that the new deploy key is added. +6. Once confirmed that it's added, refresh dbt Cloud and try developing once again. + +### 2nd Workaround + +1. Keep repo in project as is -- don't disconnect. +2. Copy the deploy key generated in dbt Cloud. +3. Go to Gitlab and click on Settings > Repository. +4. Under Repository Settings, manually add to your Gitlab project deploy key repo (with `Grant write permissions` box checked). +5. Go back to dbt Cloud, refresh your page and try developing again. + +If you've tried the workarounds above and are still experiencing this behavior - reach out to the Support team at support@getdbt.com and we'll be happy to help! diff --git a/website/docs/faqs/Troubleshooting/nonetype-ide-error.md b/website/docs/faqs/Troubleshooting/nonetype-ide-error.md new file mode 100644 index 00000000000..85e0c67ec6a --- /dev/null +++ b/website/docs/faqs/Troubleshooting/nonetype-ide-error.md @@ -0,0 +1,22 @@ +--- +title: I'm receiving a NoneType object has no attribute error in the IDE? +description: "Copy SSH key to your warehouse" +sidebar_label: 'NoneType error in the IDE' +id: nonetype-ide-error + +--- + +If you're unable to access the IDE due to the below error message, we'll do our best to get you unstuck with the below steps! + +```shell +NoneType object has no attribute +enumerate_fields' +``` + +Usually this errors indicates that you tried connecting your database via [SSH tunnel](https://docs.getdbt.com/docs/dbt-cloud/cloud-configuring-dbt-cloud/connecting-your-database#connecting-via-an-ssh-tunnel). If you're seeing this error, double-check you have supplied the following items: + +- the hostname +- username +- port of bastion server + +If you've tried the step above and are still experiencing this behavior - reach out to the Support team at support@getdbt.com and we'll be happy to help! diff --git a/website/docs/faqs/Troubleshooting/partial-parsing-error.md b/website/docs/faqs/Troubleshooting/partial-parsing-error.md new file mode 100644 index 00000000000..3f37928771f --- /dev/null +++ b/website/docs/faqs/Troubleshooting/partial-parsing-error.md @@ -0,0 +1,11 @@ +--- +title: "I'm getting a \"Partial parsing enabled: 1 files deleted, 0 files added, 2 files changed\" compilation error in dbt Cloud?" +description: "Delete partial_parse file" +sidebar_label: 'partial_parse error in the IDE' +id: partial-parsing-error + +--- + +If you're receiving this error, try deleting the `target/partial_parse.msgpack` file from your project and refresh your IDE. + +If you've tried the workaround above and are still experiencing this behavior - reach out to the Support team at support@getdbt.com and we'll be happy to help! diff --git a/website/docs/faqs/Troubleshooting/runtime-error-could-not-find-profile.md b/website/docs/faqs/Troubleshooting/runtime-error-could-not-find-profile.md new file mode 100644 index 00000000000..7d7ad21e4f6 --- /dev/null +++ b/website/docs/faqs/Troubleshooting/runtime-error-could-not-find-profile.md @@ -0,0 +1,28 @@ +--- +title: I'm receiving a Runtime Error Could not find profile named 'user' error? +description: "Re-authorize your credentials on Profile Settings" +sidebar_label: '"Could not find profile named user" error in the IDE' +id: runtime-error-could-not-find-profile + +--- + +If you're unable to access the IDE due to the below error message, we'll do our best to get you unstuck with the below steps! + +```shell +Running with dbt=0.21.0 +Encountered an error while reading the project: + ERROR: Runtime Error + Could not find profile named 'user' +Runtime Error + Could not run dbt' +``` + +Usually this errors indicates that there is an issue with missing/stale credentials/authentication. No worries, we have a few workarounds for you to try: + +**In the IDE:** +If this is happening in the IDE, you'll want to navigate to the Profile settings where your development credentials are configured. Once you're there, you'll need to either re-enter or re-authorize your credentials in order to get around this error message. + +**In a job:** +If this is happening in a job, it might be that you made some sort of change to the deployment environment in which the job is configured and did not re-enter your deployment credentials upon saving those changes. To fix this, you'll need to go back into the deployment environment settings, re-enter your credentials (either the private key/private key passphrase or the username and password), and kick off a new job run. + +If you've tried the step above and are still experiencing this behavior - reach out to the Support team at support@getdbt.com and we'll be happy to help! diff --git a/website/docs/faqs/Troubleshooting/runtime-packages.yml.md b/website/docs/faqs/Troubleshooting/runtime-packages.yml.md new file mode 100644 index 00000000000..14e87be41d9 --- /dev/null +++ b/website/docs/faqs/Troubleshooting/runtime-packages.yml.md @@ -0,0 +1,28 @@ +--- +title: Why am I receiving a Runtime Error in my packages? +description: "Update dbt_utils package in packages.yml file" +sidebar_label: 'Runtime error in packages.yml file' +id: runtime-packages.yml + +--- + +If you're receiving the runtime error below in your packages.yml folder, it may be due to an old version of your dbt_utils package that isn't compatible with your current dbt Cloud version. + +```shell +Running with dbt=xxx +Runtime Error + Failed to read package: Runtime Error + Invalid config version: 1, expected 2 + Error encountered in dbt_utils/dbt_project.yml + ``` + +Try updating the old version of the dbt_utils package in your packages.yml to the latest version found in the [dbt hub](https://hub.getdbt.com/dbt-labs/dbt_utils/latest/): + +```shell +packages: +- package: dbt-labs/dbt_utils + +version: xxx +``` + +If you've tried the workaround above and are still experiencing this behavior - reach out to the Support team at support@getdbt.com and we'll be happy to help! diff --git a/website/docs/faqs/sql-errors.md b/website/docs/faqs/Troubleshooting/sql-errors.md similarity index 69% rename from website/docs/faqs/sql-errors.md rename to website/docs/faqs/Troubleshooting/sql-errors.md index 3e6b84b5842..1208e5e8288 100644 --- a/website/docs/faqs/sql-errors.md +++ b/website/docs/faqs/Troubleshooting/sql-errors.md @@ -1,11 +1,15 @@ --- -title: What happens if the SQL in my query is bad? +title: What happens if the SQL in my query is bad or I get a database error? +description: "Use error message and logs to debug" +sidebar_label: 'How to debug SQL or database error' +id: sql-errors + --- -Or: -### I got a Database Error, what does that mean? + If there's a mistake in your SQL, dbt will return the error that your database returns. -```shell-session + +```shell $ dbt run --select customers Running with dbt=0.15.0 Found 3 models, 9 tests, 0 snapshots, 0 analyses, 133 macros, 0 operations, 0 seed files, 0 sources @@ -20,10 +24,10 @@ Found 3 models, 9 tests, 0 snapshots, 0 analyses, 133 macros, 0 operations, 0 se Completed with 1 error and 0 warnings: Database Error in model customers (models/customers.sql) - Syntax error: Expected ")" but got identifier `grand-highway-265418` at [13:15] + Syntax error: Expected ")" but got identifier `your-info-12345` at [13:15] compiled SQL at target/run/jaffle_shop/customers.sql Done. PASS=0 WARN=0 ERROR=1 SKIP=0 TOTAL=1 ``` -Any models downstream of this model will also be skipped. Use the error message and the [compiled SQL](faqs/checking-logs.md) to debug any errors. +Any models downstream of this model will also be skipped. Use the error message and the [compiled SQL](faqs/runs/checking-logs) to debug any errors. diff --git a/website/docs/faqs/Troubleshooting/unused-model-configurations.md b/website/docs/faqs/Troubleshooting/unused-model-configurations.md new file mode 100644 index 00000000000..ba5506c260f --- /dev/null +++ b/website/docs/faqs/Troubleshooting/unused-model-configurations.md @@ -0,0 +1,10 @@ +--- +title: I got an "unused model configurations" error message, what does this mean? +description: "Model configurations error message" +sidebar_label: 'unused model configurations error' +id: unused-model-configurations + +--- +You might have forgotten to nest your configurations under your project name, or you might be trying to apply configurations to a directory that doesn't exist. + +Check out this [article](https://discourse.getdbt.com/t/faq-i-got-an-unused-model-configurations-error-message-what-does-this-mean/112) to understand more. diff --git a/website/docs/faqs/bq-impersonate-service-account-setup.md b/website/docs/faqs/Warehouse/bq-impersonate-service-account-setup.md similarity index 84% rename from website/docs/faqs/bq-impersonate-service-account-setup.md rename to website/docs/faqs/Warehouse/bq-impersonate-service-account-setup.md index d57e23b32b5..60db41095e5 100644 --- a/website/docs/faqs/bq-impersonate-service-account-setup.md +++ b/website/docs/faqs/Warehouse/bq-impersonate-service-account-setup.md @@ -1,5 +1,9 @@ --- title: How can I set up the right permissions in BigQuery? +description: "Use service account to set up permissions in BigQuery" +sidebar_label: 'Setting up permissions in BigQuery"' +id: bq-impersonate-service-account-setup + --- To use this functionality, first create the service account you want to @@ -16,4 +20,4 @@ the [IAM Service Account Credentials API](https://console.cloud.google.com/apis/ Enabling the API and granting the role are eventually consistent operations, taking up to 7 minutes to fully complete, but usually fully propagating within 60 seconds. Give it a few minutes, then add the `impersonate_service_account` -option to your BigQuery profile configuration. \ No newline at end of file +option to your BigQuery profile configuration. diff --git a/website/docs/faqs/bq-impersonate-service-account-why.md b/website/docs/faqs/Warehouse/bq-impersonate-service-account-why.md similarity index 85% rename from website/docs/faqs/bq-impersonate-service-account-why.md rename to website/docs/faqs/Warehouse/bq-impersonate-service-account-why.md index ffde684fed4..e56485e18e7 100644 --- a/website/docs/faqs/bq-impersonate-service-account-why.md +++ b/website/docs/faqs/Warehouse/bq-impersonate-service-account-why.md @@ -1,5 +1,9 @@ --- title: Why would I want to impersonate a service account? +description: "Build models using dedicated service account" +sidebar_label: 'Why impersonate a service account' +id: bq-impersonate-service-account-why + --- You may want your models to be built using a dedicated service account that has @@ -15,4 +19,4 @@ This allows you to reap the advantages of using federated identity for developer directly, and without needing to create separate service account and keys for each user. It also allows you to completely eliminate the need for service account keys in CI as long as your CI is running on GCP (Cloud Build, Jenkins, -GitLab/Github Runners, etc). \ No newline at end of file +GitLab/Github Runners, etc). diff --git a/website/docs/faqs/connecting-to-two-dbs-not-allowed.md b/website/docs/faqs/Warehouse/connecting-to-two-dbs-not-allowed.md similarity index 64% rename from website/docs/faqs/connecting-to-two-dbs-not-allowed.md rename to website/docs/faqs/Warehouse/connecting-to-two-dbs-not-allowed.md index a29e85f72b4..f7c546b3648 100644 --- a/website/docs/faqs/connecting-to-two-dbs-not-allowed.md +++ b/website/docs/faqs/Warehouse/connecting-to-two-dbs-not-allowed.md @@ -1,14 +1,18 @@ --- title: Can I connect my dbt project to two databases? +description: "Prepare your warehouse for dbt transformations" +sidebar_label: 'Can you connect dbt project to two databases?' +id: connecting-to-two-dbs-not-allowed + --- The meaning of the term 'database' varies with each major warehouse manager. Hence, the answer to "can a dbt project connect to more than one database?" depends on the warehouse used in your tech stack. + * dbt projects connecting to warehouses like Snowflake or Bigquery—these empower one set of credentials to draw from all datasets or 'projects' available to an account—are _sometimes_ said to connect to more than one database. * dbt projects connecting to warehouses like Redshift and Postgres—these tie one set of credentials to one database—are said to connect to one database only. -Sidestep the 'one database problem' by relying on ELT thinking (i.e. extract -> load -> transform). Remember, dbt is not a loader--with few exceptions, it doesn't move data from sources to a warehouse. dbt is a transformer. It enters the picture after extractors and loaders have funneled sources into a warehouse. It moves and combines data inside the warehouse itself. +Sidestep the 'one database problem' by relying on thinking (i.e. extract -> load -> transform). Remember, dbt is not a loader--with few exceptions, it doesn't move data from sources to a warehouse. dbt is a transformer. It enters the picture after extractors and loaders have funneled sources into a warehouse. It moves and combines data inside the warehouse itself. Hence, instead of thinking "how do I connect my dbt project to two databases", ask "what loader services will best prepare our warehouse for dbt transformations." For more on the modern 'ELT-powered' data stack, see the "dbt and the modern BI stack" section of this [dbt blog post](https://blog.getdbt.com/what--exactly--is-dbt-/). - diff --git a/website/docs/faqs/database-privileges.md b/website/docs/faqs/Warehouse/database-privileges.md similarity index 71% rename from website/docs/faqs/database-privileges.md rename to website/docs/faqs/Warehouse/database-privileges.md index 0e5306918b3..73e0549f130 100644 --- a/website/docs/faqs/database-privileges.md +++ b/website/docs/faqs/Warehouse/database-privileges.md @@ -1,11 +1,15 @@ --- title: What privileges does my database user need to use dbt? +description: "Database privileges to use dbt" +sidebar_label: 'Database privileges to use dbt' +id: database-privileges + --- Your user will need to be able to: * `select` from raw data in your warehouse (i.e. data to be transformed) * `create` schemas, and therefore create tables/views within that schema¹ -* read system views to generate documentation (i.e. views in +* read system views to generate documentation (i.e. views in `information_schema`) On Postgres, Redshift, and Snowflake, use a series of `grants` to ensure that @@ -14,4 +18,4 @@ your user has the correct privileges. On BigQuery, use the "BigQuery User" role to assign these privileges. --- -¹Alternatively, a separate user can create a schema for the dbt user, and then grant the user privileges to create within this schema. We generally recommend granting your dbt user the ability to create schemas, as it is less complicated to implement. \ No newline at end of file +¹Alternatively, a separate user can create a schema for the dbt user, and then grant the user privileges to create within this schema. We generally recommend granting your dbt user the ability to create schemas, as it is less complicated to implement. diff --git a/website/docs/faqs/Warehouse/loading-data.md b/website/docs/faqs/Warehouse/loading-data.md new file mode 100644 index 00000000000..3fb13f139b0 --- /dev/null +++ b/website/docs/faqs/Warehouse/loading-data.md @@ -0,0 +1,12 @@ +--- +title: How do I load data into my warehouse? +description: "Recommendations on tools to load data to warehouse" +sidebar_label: 'Recommendations on tools to get data into your warehouse' +id: loading-data + +--- +dbt assumes that you already have a copy of your data, in your . We recommend you use an off-the-shelf tool like [Stitch](https://www.stitchdata.com/) or [Fivetran](https://fivetran.com/) to get data into your warehouse. + +**Can dbt be used to load data?** + +No, dbt does not extract or load data. It focuses on the transformation step only. diff --git a/website/docs/faqs/Warehouse/sample-profiles.md b/website/docs/faqs/Warehouse/sample-profiles.md new file mode 100644 index 00000000000..57287a7d97b --- /dev/null +++ b/website/docs/faqs/Warehouse/sample-profiles.md @@ -0,0 +1,9 @@ +--- +title: What should my profiles.yml file look like for my warehouse? +description: "Go to Profile Set up to see the structure of a profile" +sidebar_label: 'Structure of profile for each warehouse' +id: sample-profiles + +--- + +The structure of a profile looks different on each warehouse. Check out the [Supported Data Platforms](supported-data-platforms) page, and navigate to the `Profile Setup` section for your warehouse. diff --git a/website/docs/faqs/available-materializations.md b/website/docs/faqs/available-materializations.md deleted file mode 100644 index 5c5592fa736..00000000000 --- a/website/docs/faqs/available-materializations.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -title: What materializations are available in dbt? ---- - -dbt ships with four materializations: `view`, `table`, `incremental` and `ephemeral`. Check out the documentation on [materializations](materializations) for more information on each of these options. - -You can also create your own [custom materializations](creating-new-materializations), if required however this is an advanced feature of dbt. diff --git a/website/docs/faqs/checking-logs.md b/website/docs/faqs/checking-logs.md deleted file mode 100644 index edd84b9a2cb..00000000000 --- a/website/docs/faqs/checking-logs.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -title: How can I see the SQL that dbt is running? ---- -To check out the SQL that dbt is running, you can look in: -* dbt Cloud: - * Within the run output, click on a model name, and then select "Details" -* dbt CLI: - * The `target/compiled/` directory for compiled `select` statements - * The `target/run/` directory for compiled `create` statements - * The `logs/dbt.log` file for verbose logging. diff --git a/website/docs/faqs/cloud-vs-core.md b/website/docs/faqs/cloud-vs-core.md deleted file mode 100644 index 556264ae8f7..00000000000 --- a/website/docs/faqs/cloud-vs-core.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -title: What is the difference between dbt Core, the dbt CLI and dbt Cloud? ---- - -dbt Core is the software that takes a [dbt project](projects) (`.sql` and `.yml` files) and a command and then creates tables/views in your warehouse. dbt Core includes a command line interface (CLI) so that users can execute dbt commands using a terminal program. dbt Core is [open source](https://github.com/dbt-labs/dbt) and free to use. - -dbt Cloud is an application that helps teams use dbt. dbt Cloud provides a web-based IDE to develop dbt projects, a purpose-built scheduler, and a way to share dbt documentation with your team. dbt Cloud offers a number of features for free, as well as additional features in paid tiers (check out the pricing [here](https://www.getdbt.com/pricing/)). diff --git a/website/docs/faqs/create-a-schema.md b/website/docs/faqs/create-a-schema.md deleted file mode 100644 index 0ee9411cd87..00000000000 --- a/website/docs/faqs/create-a-schema.md +++ /dev/null @@ -1,4 +0,0 @@ ---- -title: Do I need to create my target schema before running dbt? ---- -Nope! dbt will check if the schema exists when it runs. If the schema does not exist, dbt will create it for you. \ No newline at end of file diff --git a/website/docs/faqs/custom-test-thresholds.md b/website/docs/faqs/custom-test-thresholds.md deleted file mode 100644 index 43dbad9d0e6..00000000000 --- a/website/docs/faqs/custom-test-thresholds.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -title: Can I set test failure thresholds? ---- - -This is not currently supported in dbt natively. - -Instead, consider: -* Setting the [severity](resource-properties/tests#severity) to `warn`, or: -* Writing a [custom generic test](custom-generic-tests) that accepts a threshold argument ([example](https://discourse.getdbt.com/t/creating-an-error-threshold-for-schema-tests/966)) diff --git a/website/docs/faqs/dbt-specific-jinja.md b/website/docs/faqs/dbt-specific-jinja.md deleted file mode 100644 index 30726c883ca..00000000000 --- a/website/docs/faqs/dbt-specific-jinja.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: What parts of Jinja are dbt-specific? ---- - -There are certain expressions that are specific to dbt — these are documented in the [Jinja function reference](dbt-jinja-functions) section of these docs. Further, docs blocks, snapshots, and materializations are custom Jinja _blocks_ that exist only in dbt. diff --git a/website/docs/faqs/failed-tests.md b/website/docs/faqs/failed-tests.md deleted file mode 100644 index 3b4a1751648..00000000000 --- a/website/docs/faqs/failed-tests.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -title: One of my tests failed, how can I debug it? ---- -To debug a failing test, find the SQL that dbt ran by: -* dbt Cloud: - * Within the test output, click on the failed test, and then select "Details" -* dbt CLI: - * Open the file path returned as part of the error message. - * Navigate to the `target/compiled/schema_tests` directory for all compiled test queries - -Copy the SQL into a query editor (in dbt Cloud, you can paste it into a new `Statement`), and run the query to find the records that failed. - diff --git a/website/docs/faqs/index.md b/website/docs/faqs/index.md deleted file mode 100644 index 738257a4ee8..00000000000 --- a/website/docs/faqs/index.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -id: all -title: List of FAQs ---- - - diff --git a/website/docs/faqs/insert-records.md b/website/docs/faqs/insert-records.md deleted file mode 100644 index 6d0c5c3c01f..00000000000 --- a/website/docs/faqs/insert-records.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -title: If models can only be `select` statements, how do I insert records? ---- - -For those coming from an ETL (Extract Transform Load) paradigm, there's often a desire to write transformations as `insert` and `update` statements. In comparison, dbt will wrap your `select` query in a `create table as` statement, which can feel counter-productive. - -* If you wish to use `insert` statements for perfomance reasons (i.e. to reduce data that is processed), consider [incremental models](configuring-incremental-models) -* If you wish to use `insert` statements since your source data is constantly changing (e.g. to create "Type 2 Slowly Changing Dimensions"), consider [snapshotting your source data](snapshots), and building models on top of your snaphots. diff --git a/website/docs/faqs/loading-data.md b/website/docs/faqs/loading-data.md deleted file mode 100644 index 28d53210cf5..00000000000 --- a/website/docs/faqs/loading-data.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -title: How do I load data into my warehouse? ---- -dbt assumes that you already have a copy of your data, in your data warehouse. We recommend you use an off-the-shelf tool like [Stitch](https://www.stitchdata.com/) or [Fivetran](https://fivetran.com/) to get data into your warehouse. - -**Can dbt be used to load data?** - -No, dbt does not extract or load data. It focuses on the transformation step only. diff --git a/website/docs/faqs/long-descriptions.md b/website/docs/faqs/long-descriptions.md deleted file mode 100644 index c59f1b6b726..00000000000 --- a/website/docs/faqs/long-descriptions.md +++ /dev/null @@ -1,18 +0,0 @@ ---- -title: How do I write long-form explanations in my descriptions? ---- -If you need more than a sentence to explain a model, you can: -1. Split your description over multiple lines ([yaml docs](https://yaml-multiline.info/)), like so: -```yml -version: 2 - -models: -- name: customers - description: > - Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod - tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, - quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo - consequat. -``` - -2. Use a [docs block](/documentation#using-docs-blocks) to write the description in a Markdown file. diff --git a/website/docs/faqs/prerelease-docs.md b/website/docs/faqs/prerelease-docs.md deleted file mode 100644 index 2cc029bb3da..00000000000 --- a/website/docs/faqs/prerelease-docs.md +++ /dev/null @@ -1,4 +0,0 @@ ---- -title: Why are there "prerelease" docs? ---- -We want to give beta testers the information they need to try out new features, without adding confusion to the current docs site. This is served from a long-lived `next` branch of the docs repo. Feedback on prerelease docs is also welcome—use the "Edit this page" feature at the bottom. diff --git a/website/docs/faqs/sample-profiles.md b/website/docs/faqs/sample-profiles.md deleted file mode 100644 index 8c058512291..00000000000 --- a/website/docs/faqs/sample-profiles.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: What should my profiles.yml file look like for my warehouse? ---- - -The structure of a profile looks different on each warehouse. Check out the [supported databases](available-adapters) page, and navigate to the `Profile Setup` section for your warehouse. diff --git a/website/docs/faqs/sharing-documentation.md b/website/docs/faqs/sharing-documentation.md deleted file mode 100644 index dafe8c95f76..00000000000 --- a/website/docs/faqs/sharing-documentation.md +++ /dev/null @@ -1,4 +0,0 @@ ---- -title: How do I share my documentation with my team members? ---- -If you're using dbt Cloud to deploy your project, and have the [Team Plan](https://www.getdbt.com/pricing/), you can have up to 50 read only users, who will be able access the documentation for your project. diff --git a/website/docs/faqs/snapshot-freshness-output.md b/website/docs/faqs/snapshot-freshness-output.md deleted file mode 100644 index fe41877a3f3..00000000000 --- a/website/docs/faqs/snapshot-freshness-output.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -title: Are the results of freshness stored anywhere? ---- -Yes! - -The `snapshot-freshness` command will output a pass/warning/error status for each table selected in the freshness snapshot. - -Additionally, dbt will write the freshness results to a file in the `target/` directory called `sources.json` by default. You can also override this destination, use the `-o` flag to the `snapshot-freshness` command. diff --git a/website/docs/faqs/snapshotting-freshness-for-one-source.md b/website/docs/faqs/snapshotting-freshness-for-one-source.md deleted file mode 100644 index 405ad9a97be..00000000000 --- a/website/docs/faqs/snapshotting-freshness-for-one-source.md +++ /dev/null @@ -1,19 +0,0 @@ ---- -title: How do I snapshot freshness for one source only? ---- - - -Use the `--select` flag to snapshot freshness for specific sources. Eg: - -``` -# Snapshot freshness for all Snowplow tables: -$ dbt source freshness --select jaffle_shop - -# Snapshot freshness for a particular source table: -$ dbt source freshness --select jaffle_shop.orders - -# Snapshot freshness for multiple particular source tables: -$ dbt source freshness --select jaffle_shop.orders jaffle_shop.customers -``` - -See the [`source freshness` command reference](commands/source) for more information. diff --git a/website/docs/faqs/test-sources.md b/website/docs/faqs/test-sources.md deleted file mode 100644 index bf37fbf05d4..00000000000 --- a/website/docs/faqs/test-sources.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -title: How do I run tests on sources only? ---- - -It is possible! You need to use the `source:` selection method: - -``` -$ dbt test --select source:* -``` - -Check out the [model selection syntax documentation](node-selection/test-selection-examples) for more operators and examples. diff --git a/website/docs/faqs/testing-sources.md b/website/docs/faqs/testing-sources.md deleted file mode 100644 index a8edbca23e1..00000000000 --- a/website/docs/faqs/testing-sources.md +++ /dev/null @@ -1,24 +0,0 @@ ---- -title: How do I run tests on just my sources? ---- - -To run tests on all sources, use the following command: - -``` -$ dbt test --select source:* -``` -(You can also use the `-s` shorthand here instead of `--select`) - -To run tests on one source (and all of its tables): - -``` -$ dbt test --select source:jaffle_shop -``` - -And, to run tests on one source table only: - -``` -$ dbt test --select source:jaffle_shop.orders -``` - -Yep, we know this syntax is a little less than ideal, so we're hoping to improve it in a future release. Check out the [model selection syntax](node-selection/syntax) for more examples! diff --git a/website/docs/faqs/unused-model-configurations.md b/website/docs/faqs/unused-model-configurations.md deleted file mode 100644 index d4d968bada1..00000000000 --- a/website/docs/faqs/unused-model-configurations.md +++ /dev/null @@ -1,4 +0,0 @@ ---- -title: I got an "unused model configurations" error message, what does this mean? ---- -You might have forgotten to nest your configurations under your project name, or you might be trying to apply configurations to a directory that doesn't exist. Check out this [article](https://discourse.getdbt.com/t/faq-i-got-an-unused-model-configurations-error-message-what-does-this-mean/112) to understand more. diff --git a/website/docs/faqs/which-materialization.md b/website/docs/faqs/which-materialization.md deleted file mode 100644 index be5b78af3fb..00000000000 --- a/website/docs/faqs/which-materialization.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -title: Which materialization should I use for my model? ---- -Start out with views, and then change models to tables when required for performance reasons (i.e. downstream queries have slowed). - -Check out the [docs on materializations](materializations) for advice on when to use each materialization. diff --git a/website/docs/faqs/yaml-file-extension.md b/website/docs/faqs/yaml-file-extension.md deleted file mode 100644 index 1fc6a6f7dd0..00000000000 --- a/website/docs/faqs/yaml-file-extension.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Can I use a yaml file extension? ---- - -No. At present, dbt will only search for files with a `.yml` file extension. In a future release of dbt, dbt will also search for files with a `.yaml` file extension. diff --git a/website/docs/guides/best-practices/how-we-structure/1-guide-overview.md b/website/docs/guides/best-practices/how-we-structure/1-guide-overview.md new file mode 100644 index 00000000000..8a5aaa998be --- /dev/null +++ b/website/docs/guides/best-practices/how-we-structure/1-guide-overview.md @@ -0,0 +1,98 @@ +--- +title: How we structure our dbt projects +id: 1-guide-overview +--- + +## Why does structure matter? + +Analytics engineering, at its core, is about helping groups of human beings collaborate on better decisions at scale. We have [limited bandwidth for making decisions](https://en.wikipedia.org/wiki/Decision_fatigue). We also, as a cooperative social species, rely on [systems and patterns to optimize collaboration](https://en.wikipedia.org/wiki/Pattern_language) with others. This combination of traits means that for collaborative projects it's crucial to establish consistent and comprehensible norms such that your team’s limited bandwidth for decision making can be spent on unique and difficult problems, not deciding where folders should go or how to name files. + +Building a great dbt project is an inherently collaborative endeavor, bringing together domain knowledge from every department to map the goals and narratives of the entire company. As such, it's especially important to establish a deep and broad set of patterns to ensure as many people as possible are empowered to leverage their particular expertise in a positive way, and to ensure that the project remains approachable and maintainable as your organization scales. + +Famously, Steve Jobs [wore the same outfit everyday](https://images.squarespace-cdn.com/content/v1/5453c539e4b02ab5398ffc8f/1580381503218-E56FQDNFL1P4OBLQWHWW/ke17ZwdGBToddI8pDm48kJKedFpub2aPqa33K4gNUDwUqsxRUqqbr1mOJYKfIPR7LoDQ9mXPOjoJoqy81S2I8N_N4V1vUb5AoIIIbLZhVYxCRW4BPu10St3TBAUQYVKcxb5ZTIyC_D49_DDQq2Sj8YVGtM7O1i4h5tvKa2lazN4nGUQWMS_WcPM-ztWbVr-c/steve_jobs_outfit.jpg) to reduce decision fatigue. You can think of this guide similarly, as a black turtleneck and New Balance sneakers for your company’s dbt project. A dbt project’s power outfit, or more accurately its structure, is composed not of fabric but of files, folders, naming conventions, and programming patterns. How you label things, group them, split them up, or bring them together — the system you use to organize the data transformations encoded in your dbt project — this is your project’s structure. + +This guide is just a starting point. You may decide that you prefer Birkenstocks or a purple hoodie for your project over Jobs-ian minimalism. That's fine. What's important is that you think through the reasoning for those changes in your organization, explicitly declare them in a thorough, accessible way for all contributors, and above all *stay consistent*. + +One foundational principle that applies to all dbt projects though, is the need to establish a cohesive arc moving data from *source-conformed* to *business-conformed*. Source-conformed data is shaped by external systems out of our control, while business-conformed data is shaped by the needs, concepts, and definitions we create. No matter what patterns or conventions you define within your project, this process remains the essential purpose of the transformation layer, and dbt as your tool within it. This guide is an update to a seminal analytics engineering [post of the same name](https://discourse.getdbt.com/t/how-we-structure-our-dbt-projects/355) by the great Claire Carroll, and while some of the details have changed over time (as anticipated in that post) this fundamental trajectory holds true. Moving forward, this guide will be iteratively updated as new tools expand our viewpoints, new experiences sharpen our vision, and new voices strengthen our perspectives, but always in service of that aim. + +### Learning goals + +This guide has three main goals: + +- Thoroughly cover our most up-to-date recommendations on how to structure typical dbt projects +- Illustrate these recommendations with comprehensive examples +- At each stage, explain *why* we recommend the approach that we do, so that you're equipped to decide when and where to deviate from these recommendations to better fit your organization’s unique needs + +You should walk away from this guide with a deeper mental model of how the components of a dbt project fit together, such that purpose and principles of analytics engineering feel more clear and intuitive. + +By approaching our structure intentionally, we’ll gain a better understanding of foundational ideals like moving our data from the wide array of narrower source-conformed models that our systems give us to a narrower set of wider, richer business-conformed designs we create. As we move along that arc, we’ll understand how stacking our transformations in optimized, modular layers means we can apply each transformation in only one place. With a disciplined approach to the files, folders, and materializations that comprise our structure, we’ll find that we can create clear stories not only through our data, but also our codebase and the artifacts it generates in our warehouse. + +Our hope is that by deepening your sense of the connections between these patterns and the principles they flow from, you'll be able to translate them to fit your specific needs and craft customized documentation for your team to act on. + +:::info Example project. +This guide walks through our recommendations using a very simple dbt project — similar to the one used for the Getting Started guide and many other demos — from a fictional company called the Jaffle Shop. You can read more about [jaffles](https://en.wiktionary.org/wiki/jaffle) if you want (they *are* a real thing), but that context isn’t important to understand the structure. We encourage you to follow along, try things out, make changes, and take notes on what works or doesn't work for you along the way. +::: + +We'll get a deeper sense of our project as we move through the guide, but for now we just need to know that the Jaffle Shop is a restaurant selling jaffles that has two main data sources: + +- A replica of our transactional database, called `jaffle_shop`, with core entities like orders and customers. +- Synced data from [Stripe](https://stripe.com/), which we use for processing payments. + +### Guide structure overview + +We'll walk through our topics in the same order that our data would move through transformation: + +1. Dig into how we structure the files, folders, and models for our three primary layers in the `models` directory, which build on each other: + 1. **Staging** — creating our atoms, our initial modular building blocks, from source data + 2. **Intermediate** — stacking layers of logic with clear and specific purposes to prepare our staging models to join into the entities we want + 3. **Marts** — bringing together our modular pieces into a wide, rich vision of the entities our organization cares about +2. Explore how these layers fit into the rest of the project: + 1. Review the overall structure comprehensively + 2. Expand on YAML configuration in-depth + 3. Discuss how to use the other folders in a dbt project: `tests`, `seeds`, and `analysis` + +Below is the complete file tree of the project we’ll be working through. Don’t worry if this looks like a lot of information to take in at once - this is just to give you the full vision of what we’re building towards. We’ll focus in on each of the sections one by one as we break down the project’s structure. + +```markdown +jaffle_shop +├── README.md +├── analysis +├── data +│ └── employees.csv +├── dbt_project.yml +├── macros +│ └── cents_to_dollars.sql +├── models +│ ├── intermediate +│ │ └── finance +│ │ ├── _int_finance__models.yml +│ │ └── int_payments_pivoted_to_orders.sql +│ ├── marts +│ │ ├── finance +│ │ │ ├── _finance__models.yml +│ │ │ ├── orders.sql +│ │ │ └── payments.sql +│ │ └── marketing +│ │ ├── _marketing__models.yml +│ │ └── customers.sql +│ ├── staging +│ │ ├── jaffle_shop +│ │ │ ├── _jaffle_shop__docs.md +│ │ │ ├── _jaffle_shop__models.yml +│ │ │ ├── _jaffle_shop__sources.yml +│ │ │ ├── base +│ │ │ │ ├── base_jaffle_shop__customers.sql +│ │ │ │ └── base_jaffle_shop__deleted_customers.sql +│ │ │ ├── stg_jaffle_shop__customers.sql +│ │ │ └── stg_jaffle_shop__orders.sql +│ │ └── stripe +│ │ ├── _stripe__models.yml +│ │ ├── _stripe__sources.yml +│ │ └── stg_stripe__payments.sql +│ └── utilities +│ └── all_dates.sql +├── packages.yml +├── snapshots +└── tests + └── assert_positive_value_for_total_amount.sql +``` diff --git a/website/docs/guides/best-practices/how-we-structure/2-staging.md b/website/docs/guides/best-practices/how-we-structure/2-staging.md new file mode 100644 index 00000000000..15b076e1d41 --- /dev/null +++ b/website/docs/guides/best-practices/how-we-structure/2-staging.md @@ -0,0 +1,220 @@ +--- +title: "Staging: Preparing our atomic building blocks" +id: 2-staging +--- + +The staging layer is where our journey begins. This is the foundation of our project, where we bring all the individual components we're going to use to build our more complex and useful models into the project. + +We'll use an analogy for working with dbt throughout this guide: thinking modularly in terms of atoms, molecules, and more complex outputs like proteins or cells (we apologize in advance to any chemists or biologists for our inevitable overstretching of this metaphor). Within that framework, if our source system data is a soup of raw energy and quarks, then you can think of the staging layer as condensing and refining this material into the individual atoms we’ll later build more intricate and useful structures with. + +### Staging: Files and folders + +Let's zoom into the staging directory from our `models` file tree [in the overview](/guides/best-practices/how-we-structure/1-guide-overview) and walk through what's going on here. + +```markdown +models/staging +├── jaffle_shop +│ ├── _jaffle_shop__docs.md +│ ├── _jaffle_shop__models.yml +│ ├── _jaffle_shop__sources.yml +│ ├── base +│ │ ├── base_jaffle_shop__customers.sql +│ │ └── base_jaffle_shop__deleted_customers.sql +│ ├── stg_jaffle_shop__customers.sql +│ └── stg_jaffle_shop__orders.sql +└── stripe + ├── _stripe__models.yml + ├── _stripe__sources.yml + └── stg_stripe__payments.sql +``` + +- **Folders.** Folder structure is extremely important in dbt. Not only do we need a consistent structure to find our way around the codebase, as with any software project, but our folder structure is also one of the key interfaces into understanding the knowledge graph encoded in our project (alongside the DAG and the data output into our warehouse). It should reflect how the data flows, step-by-step, from a wide variety of source-conformed models into fewer, richer business-conformed models. Moreover, we can use our folder structure as a means of selection in dbt [selector syntax](https://docs.getdbt.com/reference/node-selection/syntax). For example, with the above structure, if we got fresh Stripe data loaded and wanted to run all the models that build on our Stripe data, we can easily run `dbt build --select staging.stripe+` and we’re all set building more up-to-date reports on payments. + - ✅ **Subdirectories based on the source system**. Our internal transactional database is one system, the data we get from Stripe's API is another, and lastly the events from our Snowplow instrumentation. We've found this to be the best grouping for most companies, as source systems tend to share similar loading methods and properties between tables, and this allows us to operate on those similar sets easily. + - ❌ **Subdirectories based on loader.** Some people attempt to group by how the data is loaded (Fivetran, Stitch, custom syncs), but this is too broad to be useful on a project of any real size. + - ❌ **Subdirectories based on business grouping.** Another approach we recommend against is splitting up by business groupings in the staging layer, and creating subdirectories like 'marketing', 'finance', etc. A key goal of any great dbt project should be establishing a single source of truth. By breaking things up too early, we open ourselves up to create overlap and conflicting definitions (think marketing and financing having different fundamental tables for orders). We want everybody to be building with the same set of atoms, so in our experience, starting our transformations with our staging structure reflecting the source system structures is the best level of grouping for this step. +- **File names.** Creating a consistent pattern of file naming is [crucial in dbt](https://docs.getdbt.com/blog/on-the-importance-of-naming). File names must be unique and correspond the name of the model when selected and created in the warehouse. We recommend putting as much clear information into the file name as possible, including a prefix for the layer the model exists in, important grouping information, and specific information about the entity or transformation in the model. + - ✅ `stg_[source]__[entity]s.sql` - the double underscore between source system and entity helps visually distinguish the separate parts in the case of a source name having multiple words. For instance, `google_analytics__campaigns` is always understandable, whereas to somebody unfamiliar `google_analytics_campaigns` could be `analytics_campaigns` from the `google` source system as easily as `campaigns` from the `google_analytics` source system. Think of it like an [oxford comma](https://www.youtube.com/watch?v=P_i1xk07o4g), the extra clarity is very much worth the extra punctuation. + - ❌ `stg_[entity].sql` - might be specific enough at first, but will break down in time. Adding the source system into the file name aids in discoverability, and allows understanding where a component model came from even if you aren't looking at the file tree. + - ✅ **Plural.** SQL, and particularly SQL in dbt, should read as much like prose as we can achieve. We want to lean into the broad clarity and declarative nature of SQL when possible. As such, unless there’s a single order in your `orders` table, plural is the correct way to describe what is in a table with multiple rows. + +### Staging: Models + +Now that we’ve got a feel for how the files and folders fit together, let’s look inside one of these files and dig into what makes for a well-structured staging model. + +Below, is an example of a standard staging model (from our `stg_stripe__payments` model) that illustrates the common patterns within the staging layer. We’ve organized our model into two CTEs: one pulling in a source table via the [source macro](https://docs.getdbt.com/docs/building-a-dbt-project/using-sources#selecting-from-a-source) and the other applying our transformations. + +While our later layers of transformation will vary greatly from model to model, every one of our staging models will follow this exact same pattern. As such, we need to make sure the pattern we’ve established is rock solid and consistent. + +```sql +-- stg_stripe__payments.sql + +with + +source as ( + + select * from {{ source('stripe','payment') }} + +), + +renamed as ( + + select + -- ids + id as payment_id, + orderid as order_id, + + -- strings + paymentmethod as payment_method, + case + when payment_method in ('stripe', 'paypal', 'credit_card', 'gift_card') then 'credit' + else 'cash' + end as payment_type, + status, + + -- numerics + amount as amount_cents, + amount / 100.0 as amount, + + -- booleans + case + when status = 'successful' then true + else false + end as is_completed_payment, + + -- dates + date_trunc('day', created) as created_date, + + -- timestamps + created::timestamp_ltz as created_at + + from source + +) + +select * from renamed +``` + +- Based on the above, the most standard types of staging model transformations are: + - ✅ **Renaming** + - ✅ **Type casting** + - ✅ **Basic computations** (e.g. cents to dollars) + - ✅ **Categorizing** (using conditional logic to group values into buckets or booleans, such as in the `case when` statements above) + - ❌ **Joins** — the goal of staging models is to clean and prepare individual source conformed concepts for downstream usage. We're creating the most useful version of a source system table, which we can use as a new modular component for our project. In our experience, joins are almost always a bad idea here — they create immediate duplicated computation and confusing relationships that ripple downstream — there are occasionally exceptions though (see [base models](guides/best-practices/how-we-structure/2-staging#staging-other-considerations) below). + - ❌ **Aggregations** — aggregations entail grouping, and we're not doing that at this stage. Remember - staging models are your place to create the building blocks you’ll use all throughout the rest of your project — if we start changing the grain of our tables by grouping in this layer, we’ll lose access to source data that we’ll likely need at some point. We just want to get our individual concepts cleaned and ready for use, and will handle aggregating values downstream. +- ✅ **Materialized as views.** Looking at a partial view of our `dbt_project.yml` below, we can see that we’ve configured the entire staging directory to be materialized as views. As they’re not intended to be final artifacts themselves, but rather building blocks for later models, staging models should typically be materialized as views for two key reasons: + - Any downstream model (discussed more in [marts](/guides/best-practices/how-we-structure/4-marts)) referencing our staging models will always get the freshest data possible from all of the component views it’s pulling together and materializing + - It avoids wasting space in the warehouse on models that are not intended to be queried by data consumers, and thus do not need to perform as quickly or efficiently + + ```yaml + # dbt_project.yml + + models: + jaffle_shop: + staging: + +materialized: view + ``` + +- Staging models are the only place we'll use the [`source` macro](/docs/building-a-dbt-project/using-sources), and our staging models should have a 1-to-1 relationship to our source tables. That means for each source system table we’ll have a single staging model referencing it, acting as its entry point — *staging* it — for use downstream. + +:::tip Don’t Repeat Yourself. +Staging models help us keep our code DRY. dbt's modular, reusable structure means we can, and should, push any transformations that we’ll always want to use for a given component model as far upstream as possible. This saves us from potentially wasting code, complexity, and compute doing the same transformation more than once. For instance, if we know we always want our monetary values as floats in dollars, but the source system is integers and cents, we want to do the division and type casting as early as possible so that we can reference it rather than redo it repeatedly downstream. +::: + +This is a welcome change for many of us who have become used to applying the same sets of SQL transformations in many places out of necessity! For us, the earliest point for these 'always-want' transformations is the staging layer, the initial entry point in our transformation process. The DRY principle is ultimately the litmus test for whether transformations should happen in the staging layer. If we'll want them in every downstream model and they help us eliminate repeated code, they're probably okay. + +### Staging: Other considerations + +- **Base models when joins are necessary to stage concepts.** Sometimes, in order to maintain a clean and DRY staging layer we do need to implement some joins to create a solid concept for our building blocks. In these cases, we recommend creating a sub-directory in the staging directory for the source system in question and building `base` models. These have all the same properties that would normally be in the staging layer, they will directly source the raw data and do the non-joining transformations, then in the staging models we’ll join the requisite base models. The most common use cases for building a base layer under a staging folder are: + - ✅ **Joining in separate delete tables**. Sometime a source system might store deletes in a separate table. Typically we’ll want to make sure we can mark or filter out deleted records for all our component models, so we’ll need to join these delete records up to any of our entities that follow this pattern. This is the example shown below to illustrate. + + ```sql + -- base_jaffle_shop__customers.sql + + with + + source as ( + + select * from {{ source('jaffle_shop','customers') }} + + ), + + customers as ( + + select + id as customer_id, + first_name, + last_name + + from source + + ) + + select * from customers + ``` + + ```sql + -- base_jaffle_shop__deleted_customers.sql + + with + + source as ( + + select * from {{ source('jaffle_shop','customer_deletes') }} + + ), + + deleted_customers as ( + + select + id as customer_id, + deleted as deleted_at + + from source + + ) + + select * from deleted_customers + ``` + + ```sql + -- stg_jaffle_shop__customers.sql + + with + + customers as ( + + select * from {{ ref('base_jaffle_shop__customers') }} + + ), + + deleted_customers as ( + + select * from {{ ref('base_jaffle_shop__deleted_customers') }} + + ), + + join_and_mark_deleted_customers as ( + + select + customers.*, + case + when deleted_customers.deleted_at is not null then true + else false + end as is_deleted + + from customers + + left join deleted_customers on customers.customer_id = deleted_customers.customer_id + + ) + + select * from join_and_mark_deleted_customers + ``` + + - ✅ **Unioning disparate but symmetrical sources**. A typical example here would be if you operate multiple ecommerce platforms in various territories via a SaaS platform like Shopify. You would have perfectly identical schemas, but all loaded separately into your warehouse. In this case, it’s easier to reason about our orders if *all* of our shops are unioned together, so we’d want to handle the unioning in a base model before we carry on with our usual staging model transformations on the (now complete) set — you can dig into [more detail on this use case here](https://discourse.getdbt.com/t/unioning-identically-structured-data-sources/921). +- **[Codegen](https://github.com/dbt-labs/dbt-codegen) to automate staging table generation.** It’s very good practice to learn to write staging models by hand, they’re straightforward and numerous, so they can be an excellent way to absorb the dbt style of writing SQL. Also, we’ll invariably find ourselves needing to add special elements to specific models at times — for instance, in one of the situations above that require base models — so it’s helpful to deeply understand how they work. Once that understanding is established though, because staging models are built largely following the same rote patterns and need to be built 1-to-1 for each source table in a source system, it’s preferable to start automating their creation. For this, we have the [codegen](https://github.com/dbt-labs/dbt-codegen) package. This will let you automatically generate all the source YAML and staging model boilerplate to speed up this step, and we recommend using it in every project. +- **Utilities folder.** While this is not in the `staging` folder, it’s useful to consider as part of our fundamental building blocks. The `models/utilities` directory is where we can keep any general purpose models that we generate from macros or based on seeds that provide tools to help us do our modeling, rather than data to model itself. The most common use case is a [date spine](https://github.com/dbt-labs/dbt-utils#date_spine-source) generated with [the dbt utils package](https://hub.getdbt.com/dbt-labs/dbt_utils/latest/). + +:::info Development flow versus DAG order. +This guide follows the order of the DAG, so we can get a holistic picture of how these three primary layers build on each other towards fueling impactful data products. It’s important to note though that developing models does not typically move linearly through the DAG. Most commonly, we should start by mocking out a design in a spreadsheet so we know we’re aligned with our stakeholders on output goals. Then, we’ll want to write the SQL to generate that output, and identify what tables are involved. Once we have our logic and dependencies, we’ll make sure we’ve staged all the necessary atomic pieces into the project, then bring them together based on the logic we wrote to generate our mart. Finally, with a functioning model flowing in dbt, we can start refactoring and optimizing that mart. By splitting the logic up and moving parts back upstream into intermediate models, we ensure all of our models are clean and readable, the story of our DAG is clear, and we have more surface area to apply thorough testing. +:::info diff --git a/website/docs/guides/best-practices/how-we-structure/3-intermediate.md b/website/docs/guides/best-practices/how-we-structure/3-intermediate.md new file mode 100644 index 00000000000..9fc71b326a4 --- /dev/null +++ b/website/docs/guides/best-practices/how-we-structure/3-intermediate.md @@ -0,0 +1,99 @@ +--- +title: "Intermediate: Purpose-built transformation steps" +id: 3-intermediate +--- + +Once we’ve got our atoms ready to work with, we’ll set about bringing them together into more intricate, connected molecular shapes. The intermediate layer is where these molecules live, creating varied forms with specific purposes on the way towards the more complex proteins and cells we’ll use to breathe life into our data products. + +### Intermediate: Files and folders + +Let’s take a look at the intermediate layer of our project to understand the purpose of this stage more concretely. + +```markdown +models/intermediate +└── finance + ├── _int_finance__models.yml + └── int_payments_pivoted_to_orders.sql +``` + +- **Folders** + - ✅ **Subdirectories based on business groupings.** Much like the staging layer, we’ll house this layer of models inside their own `intermediate` subfolder. Unlike the staging layer, here we shift towards being business-conformed, splitting our models up into subdirectories not by their source system, but their area of business concern. +- **File names** + - `✅ int_[entity]s_[verb]s.sql` - the variety of transformations that can happen inside of the intermediate layer make it harder to dictate strictly how to name them. The best guiding principle is to think about *verbs* (e.g. `pivoted`, `aggregated_to_user`, `joined`, `fanned_out_by_quantity`, `funnel_created`, etc.) in the intermediate layer. In our example project, we use an intermediate model to pivot payments out to the order grain, so we name our model `int_payments_pivoted_to_orders`. It’s easy for anybody to quickly understand what’s happening in that model, even if they don’t know SQL. That clarity is worth the long file name. It’s important to note that we’ve dropped the double underscores at this layer. In moving towards business conformed concepts, we no longer need to separate a system and an entity and simply reference the unified entity if possible. In cases where you need intermediate models to operate at the source system level (e.g. `int_shopify__orders_summed`, `int_core__orders_summed` which you would later union), you’d preserve the double underscores. Some people like to separate the entity and verbs with double underscores as well. That’s a matter of preference, but in our experience there are often intrinsic connection between entities and verbs in this layer that make that difficult to maintain. + +:::tip Don’t over-optimize too early! +The example project is very simple for illustrative purposes. This level of division in our post-staging layers is probably unnecessary when dealing with this few models. Remember, our goal is a *single* *source of truth.* We don’t want finance and marketing operating on separate `orders` models, we want to use our dbt project as a means to bring those definitions together! As such, don’t split and optimize too early. If you have less than 10 marts models and aren’t having problems developing and using them, feel free to forego subdirectories completely (except in the staging layer, where you should always implement them as you add new source systems to your project) until the project has grown to really need them. Using dbt is always about bringing simplicity to complexity. +::: + +### Intermediate: Models + +Below is the lone intermediate model from our small example project. This represents an excellent use case per our principles above, serving a clear single purpose: grouping and pivoting a staging model to different grain. It utilizes a bit of Jinja to make the model DRY-er (striving to be DRY applies to the code we write inside a single model in addition to transformations across the codebase), but don’t be intimidated if you’re not quite comfortable with [Jinja](https://docs.getdbt.com/docs/building-a-dbt-project/jinja-macros) yet. Looking at the name of the CTE, `pivot_and_aggregate_payments_to_order_grain` we get a very clear idea of what’s happening inside this block. By descriptively labeling the transformations happening inside our CTEs within model, just as we do with our files and folders, even a stakeholder who doesn’t know SQL would be able to grasp the purpose of this section, if not the code. As you begin to write more complex transformations moving out of the staging layer, keep this idea in mind. In the same way our models connect into a DAG and tell the story of our transformations on a macro scale, CTEs can do this on a smaller scale inside our model files. + +```sql +-- int_payments_pivoted_to_orders.sql + +{%- set payment_methods = ['bank_transfer','credit_card','coupon','gift_card'] -%} + +with + +payments as ( + + select * from {{ ref('stg_stripe__payments') }} + +), + +pivot_and_aggregate_payments_to_order_grain as ( + + select + order_id, + {% for payment_method in payment_methods -%} + + sum( + case + when payment_method = '{{ payment_method }}' and + status = 'success' + then amount + else 0 + end + ) as {{ payment_method }}_amount, + + {%- endfor %} + sum(case when status = 'success' then amount end) as total_amount + + from payments + + group by 1 + +) + +select * from pivot_and_aggregate_payments_to_order_grain +``` + +- ❌ **Exposed to end users.** Intermediate models should generally not be exposed in the main production schema. They are not intended for output to final targets like dashboards or applications, so it’s best to keep them separated from models that are so you can more easily control data governance and discoverability. +- ✅ **Materialized ephemerally.** Considering the above, one popular option is to default to intermediate models being materialized [ephemerally](/docs/building-a-dbt-project/building-models/materializations/#ephemeral). This is generally the best place to start for simplicity. It will keep unnecessary models out of your warehouse with minimum configuration. Keep in mind though that the simplicity of ephemerals does translate a bit more difficulty in troubleshooting, as they’re interpolated into the models that `ref` them, rather than existing on their own in a way that you can view the output of. +- ✅ **Materialized as views in a custom schema with special permissions.** A more robust option is to materialize your intermediate models as views in a specific [custom schema](https://docs.getdbt.com/docs/building-a-dbt-project/building-models/using-custom-schemas), outside of your main production schema. This gives you added insight into development and easier troubleshooting as the number and complexity of your models grows, while remaining easy to implement and taking up negligible space. + +:::tip Keep your warehouse tidy! +There are three interfaces to the organizational knowledge graph we’re encoding into dbt: the DAG, the files and folder structure of our codebase, and the output into the warehouse. As such, it’s really important that we consider that output intentionally! Think of the schemas, tables, and views we’re creating in the warehouse as *part of the UX,* in addition to the dashboards, ML, apps, and other use cases you may be targeting for the data. Ensuring that our output is named and grouped well, and that models not intended for broad use are either not materialized or built into special areas with specific permissions is crucial to achieve this. +::: + +- Intermediate models’ purposes, as these serve to break up complexity from our marts models, can take as many forms as data transformation might require. Some of the most common use cases of intermediate models include: + + - ✅ **Structural simplification.** Bringing together a reasonable number (typically 4 to 6) of entities or concepts (staging models, or perhaps other intermediate models) that will be joined with another similarly purposed intermediate model to generate a mart — rather than have 10 joins in our mart, we can join two intermediate models that each house a piece of the complexity, giving us increased readability, flexibility, testing surface area, and insight into our components. + - ✅ **Re-graining.** Intermediate models are often used to fan out or collapse models to the right composite grain — if we’re building a mart for `order_items` that requires us to fan out our `orders` based on the `quantity` column, creating a new single row for each item, this would be ideal to do in a specific intermediate model to maintain clarity in our mart and more easily view that our grain is correct before we mix it with other components + - ✅ **Isolating complex operations.** It’s helpful to move any particularly complex or difficult to understand pieces of logic into their own intermediate models. This not only makes them easier to refine and troubleshoot, but simplifies later models that can reference this concept in a more clearly readable way. For example, in the `quantity` fan out example above, we benefit by isolating this complex piece of logic so we can quickly debug and thoroughly test that transformation, and downstream models can reference `order_items` in a way that’s intuitively easy to grasp. + - ❌ **Used repeatedly in multiple models.** If we’re referencing the same intermediate model in several places, it probably should be a macro, or we should reconsider how and where we’re bringing our models together. Remember our DRY principle: while it’s good that we’ve modularized our logic, bringing the same intermediate model into several downstream models usually indicates that we’re creating duplication in our output too early and recomputing the same transformations. Ideally, it’s in the *marts* layer that we’ll start bringing concepts together repeatedly to form a variety of outputs that often have similar data. Be wary of doing this in the intermediate layer, as it can lead to your DAG becoming confusing — generally an indicator that the mental models of our project flow are getting muddied. Additionally, it’s usually more efficient to join marts as they have been materialized into the warehouse, meaning we don’t have to recompute the entire chain of transformations in addition to the computing the joins. + + ![Multiple *outputs* from an intermediate model, bringing the same model into several different marts, is typically a red flag in our DAG that we’re computing the same transformations multiple times.](/img/guides/best-practices/how-we-structure/widening-dag.png) + + Multiple *outputs* from an intermediate model, bringing the same model into several different marts, is typically a red flag in our DAG that we’re computing the same transformations multiple times. + + - ✅ **Used in one model.** Bringing our intermediate models, staging models, and other marts together thoughtfully so our models can build on each other efficiently. + + ![Multiple *inputs* to a model is generally preferable. Several inputs and one output at each node indicates we’re bringing our concepts together into richer, wider entities; forming a healthy DAG shaped like an arrowhead pointing to the right.](/img/guides/best-practices/how-we-structure/narrowing-dag.png) + + Multiple *inputs* to a model is generally preferable. Several inputs and one output at each node indicates we’re bringing our concepts together into richer, wider entities; forming a healthy DAG shaped like an arrowhead pointing to the right. + +:::tip Narrow the DAG, widen the tables. +Until we get to the marts layer and start building our various outputs, we ideally want our DAG to look like an arrowhead pointed right. As we move from source-conformed to business-conformed, we’re also moving from numerous, narrow, isolated concepts to fewer, wider, joined concepts. We’re bringing our components together into wider, richer concepts, and that creates this shape in our DAG. This way when we get to the marts layer we have a robust set of components that can quickly and easily be put into any configuration to answer a variety of questions and serve specific needs. One rule of thumb to ensure you’re following this pattern on an individual model level is allowing multiple *inputs* to a model, but **not** multiple *outputs*. Several arrows going *into* our post-staging models is great and expected, several arrows coming *out* is a red flag. There are absolutely situations where you need to break this rule, but it’s something to be aware of, careful about, and avoid when possible. +::: diff --git a/website/docs/guides/best-practices/how-we-structure/4-marts.md b/website/docs/guides/best-practices/how-we-structure/4-marts.md new file mode 100644 index 00000000000..201956ddbf7 --- /dev/null +++ b/website/docs/guides/best-practices/how-we-structure/4-marts.md @@ -0,0 +1,137 @@ +--- +title: "Marts: Business-defined entities" +id: 4-marts +--- + +This is the layer where everything comes together and we start to arrange all of our atoms (staging models) and molecules (intermediate models) into full-fledged cells that have identity and purpose. We sometimes like to call this the *entity* *layer* or *concept layer*, to emphasize that all our marts are meant to represent a specific entity or concept at its unique grain. For instance, an order, a customer, a territory, a click event, a payment — each of these would be represented with a distinct mart, and each row would represent a discrete instance of these concepts. Unlike in a traditional Kimball star schema though, in modern data warehousing — where storage is cheap and compute is expensive — we’ll happily borrow and add any and all data from other concepts that are relevant to answering questions about the mart’s core entity. Building the same data in multiple places, as we do with `orders` in our `customers` mart example below, is more efficient in this paradigm than repeatedly rejoining these concepts (this is a basic definition of denormalization in this context). Let’s take a look at how we approach this first layer intended expressly for exposure to end users. + +### Marts: Files and folders + +The last layer of our core transformations is below, providing models for both `finance` and `marketing` departments. + +```markdown +models/marts +├── finance +│ ├── _finance__models.yml +│ ├── orders.sql +│ └── payments.sql +└── marketing + ├── _marketing__models.yml + └── customers.sql +``` + +✅ **Group by department or area of concern.** If you have fewer than 10 or so marts you may not have much need for subfolders, so as with the intermediate layer, don’t over-optimize too early. If you do find yourself needing to insert more structure and grouping though, use useful business concepts here. In our marts layer, we’re no longer worried about source-conformed data, so grouping by departments (marketing, finance, etc.) is the most common structure at this stage. + +✅ **Name by entity.** Use plain English to name the file based on the concept that forms the grain of the mart `customers`, `orders`. Note that for pure marts, there should not be a time dimension (`orders_per_day`) here, that is typically best captured via metrics. + +❌ **Build the same concept differently for different teams.** `finance_orders` and `marketing_orders` is typically considered an anti-pattern. There are, as always, exceptions — a common pattern we see is that, finance may have specific needs, for example reporting revenue to the government in a way that diverges from how the company as a whole measures revenue day-to-day. Just make sure that these are clearly designed and understandable as *separate* concepts, not departmental views on the same concept: `tax_revenue` and `revenue` not `finance_revenue` and `marketing_revenue`. + +### Marts: Models + +Finally we’ll take a look at the best practices for models within the marts directory by examining two of our marts models. These are the business-conformed — that is, crafted to our vision and needs — entities we’ve been bringing these transformed components together to create. + +```sql +-- orders.sql + +with + +orders as ( + + select * from {{ ref('stg_jaffle_shop__orders' )}} + +), + +order_payments as ( + + select * from {{ ref('int_payments_pivoted_to_orders') }} + +), + +orders_and_order_payments_joined as ( + + select + orders.order_id, + orders.customer_id, + orders.order_date, + coalesce(order_payments.total_amount, 0) as amount, + coalesce(order_payments.gift_card_amount, 0) as gift_card_amount + + from orders + + left join order_payments on orders.order_id = order_payments.order_id + +) + +select * from orders_and_payments_joined +``` + +```sql +-- customers.sql + +with + +customers as ( + + select * from {{ ref('stg_jaffle_shop__customers')}} + +), + +orders as ( + + select * from {{ ref('orders')}} + +), + +customer_orders as ( + + select + customer_id, + min(order_date) as first_order_date, + max(order_date) as most_recent_order_date, + count(order_id) as number_of_orders, + sum(amount) as lifetime_value + + from orders + + group by 1 + +), + +customers_and_customer_orders_joined as ( + + select + customers.customer_id, + customers.first_name, + customers.last_name, + customer_orders.first_order_date, + customer_orders.most_recent_order_date, + coalesce(customer_orders.number_of_orders, 0) as number_of_orders, + customer_orders.lifetime_value + + from customers + + left join customer_orders on customers.customer_id = customer_orders.customer_id + +) + +select * from customers_and_customer_orders_joined +``` + +- ✅ **Materialized as tables or incremental models.** Once we reach the marts layer, it’s time to start building not just our logic into the warehouse, but the data itself. This gives end users much faster performance for these later models that are actually designed for their use, and saves us costs recomputing these entire chains of models every time somebody refreshes a dashboard or runs a regression in python. A good general rule of thumb regarding materialization is to always start with a view (as it takes up essentially no storage and always gives you up-to-date results), once that view takes too long to practically *query*, build it into a table, and finally once that table takes too long to *build* and is slowing down your runs, [configure it as an incremental model](https://docs.getdbt.com/docs/building-a-dbt-project/building-models/configuring-incremental-models/). As always, start simple and only add complexity as necessary. The models with the most data and compute-intensive transformations should absolutely take advantage of dbt’s excellent incremental materialization options, but rushing to make all your marts models incremental by default will introduce superfluous difficulty. We recommend reading this [classic post from Tristan on the limits of incremental modeling](https://discourse.getdbt.com/t/on-the-limits-of-incrementality/303). +- ✅ **Wide and denormalized.** Unlike old school warehousing, in the modern data stack storage is cheap and it’s compute that is expensive and must be prioritized as such, packing these into very wide denormalized concepts that can provide everything somebody needs about a concept as a goal. +- ❌ **Too many joins in one mart.** One good rule of thumb when building dbt transformations is to avoid bringing together too many concepts in a single mart. What constitutes ‘too many’ can vary. If you need to bring 8 staging models together with nothing but simple joins, that might be fine. Conversely, if you have 4 concepts you’re weaving together with some complex and computationally heavy window functions, that could be too much. You need to weigh the number of models you’re joining against the complexity of the logic within the mart, and if it’s too much to read through and build a clear mental model of then look to modularize. While this isn’t a hard rule, if you’re bringing together more than 4 or 5 concepts to create your mart, you may benefit from adding some intermediate models for added clarity. Two intermediate models that bring together three concepts each, and a mart that brings together those two intermediate models, will typically result in a much more readable chain of logic than a single mart with six joins. +- ✅ **Build on separate marts thoughtfully.** While we strive to preserve a narrowing DAG up to the marts layer, once here things may start to get a little less strict. A common example is passing information between marts at different grains, as we saw above, where we bring our `orders` mart into our `customers` marts to aggregate critical order data into a `customer` grain. Now that we’re really ‘spending’ compute and storage by actually building the data in our outputs, it’s sensible to leverage previously built resources to speed up and save costs on outputs that require similar data, versus recomputing the same views and CTEs from scratch. The right approach here is heavily dependent on your unique DAG, models, and goals — it’s just important to note that using a mart in building another, later mart is okay, but requires careful consideration to avoid wasted resources or circular dependencies. + +:::tip Marts are entity-grained. +The most important aspect of marts is that they contain all of the useful data about a *particular entity* at a granular level. That doesn’t mean we don’t bring in lots of other entities and concepts, like tons of `user` data into our `orders` mart, we do! It just means that individual `orders` remain the core grain of our table. If we start grouping `users` and `orders` along a [date spine](https://github.com/dbt-labs/dbt-utils#date_spine-source), into something like `user_orders_per_day`, we’re moving past marts into *metrics*. +::: + +### Marts: Other considerations + +- **Troubleshoot via tables.** While stacking views and ephemeral models up until our marts — only building data into the warehouse at the end of a chain when we have the models we really want end users to work with — is ideal in production, it can present some difficulties in development. Particularly, certain errors may seem to be surfacing in our later models that actually stem from much earlier dependencies in our model chain (ancestor models in our DAG that are built before the model throwing the errors). If you’re having trouble pinning down where or what a database error is telling you, it can be helpful to temporarily build a specific chain of models as tables so that the warehouse will throw the error where it’s actually occurring. +- **After marts: the activation layer.** In the same way that our staging models are building blocks for our marts, that also offer us direct views into specific source data, our marts are building blocks for our final outputs that also offer direct views into specific ideas. You can use marts directly, but they are equally important as components for building models in the *activation layer* after marts. This is a deep and fast-evolving topic, so we’ll cover this in a separate forthcoming guide that dives into: + - Metrics + - Reverse ETL + - Reporting and dashboards + - Data science and ML + - [Exposures](https://docs.getdbt.com/docs/building-a-dbt-project/exposures) (how we tie our dbt DAG into all of the above) diff --git a/website/docs/guides/best-practices/how-we-structure/5-the-rest-of-the-project.md b/website/docs/guides/best-practices/how-we-structure/5-the-rest-of-the-project.md new file mode 100644 index 00000000000..ea54462dabb --- /dev/null +++ b/website/docs/guides/best-practices/how-we-structure/5-the-rest-of-the-project.md @@ -0,0 +1,113 @@ +--- +title: "The rest of the project" +id: 5-the-rest-of-the-project +--- + +### Project structure review + +So far we’ve focused on the `models` folder, the primary directory of our dbt project. Next, we’ll zoom out and look at how the rest of our project files and folders fit in with this structure, starting with how we approach YAML configuration files. + +```markdown +models +├── intermediate +│ └── finance +│ ├── _int_finance__models.yml +│ └── int_payments_pivoted_to_orders.sql +├── marts +│ ├── finance +│ │ ├── _finance__models.yml +│ │ ├── orders.sql +│ │ └── payments.sql +│ └── marketing +│ ├── _marketing__models.yml +│ └── customers.sql +├── staging +│ ├── jaffle_shop +│ │ ├── _jaffle_shop__docs.md +│ │ ├── _jaffle_shop__models.yml +│ │ ├── _jaffle_shop__sources.yml +│ │ ├── base +│ │ │ ├── base_jaffle_shop__customers.sql +│ │ │ └── base_jaffle_shop__deleted_customers.sql +│ │ ├── stg_jaffle_shop__customers.sql +│ │ └── stg_jaffle_shop__orders.sql +│ └── stripe +│ ├── _stripe__models.yml +│ ├── _stripe__sources.yml +│ └── stg_stripe__payments.sql +└── utilities + └── all_dates.sql +``` + +### YAML in-depth + +When structuring your YAML configuration files in a dbt project, you want to balance centralization and file size to make specific configs as easy to find as possible. It’s important to note that while the top-level YAML files (`dbt_project.yml`, `packages.yml`) need to be specifically named and in specific locations, the files containing your `sources` and `models` dictionaries can be named, located, and organized however you want. It’s the internal contents that matter here. As such, we’ll lay out our primary recommendation, as well as the pros and cons of a popular alternative. Like many other aspects of structuring your dbt project, what’s most important here is consistency, clear intention, and thorough documentation on how and why you do what you do. + +- ✅ **Config per folder.** As in the example above, create a `_[directory]__models.yml` per directory in your models folder that configures all the models in that directory. for staging folders, also include a `_[directory]__sources.yml` per directory. + - The leading underscore ensure your YAML files will be sorted to the top of every folder to make them easy to separate from your models. + - YAML files don’t need unique names in the way that SQL model files do, but including the directory (instead of simply `_sources.yml` in each folder), means you can fuzzy find for the right file more quickly. + - We’ve recommended several different naming conventions over the years, most recently calling these `schema.yml` files. We’ve simplified to recommend that these simply be labelled based on the YAML dictionary that they contain. + - If you utilize [doc blocks](https://docs.getdbt.com/docs/building-a-dbt-project/documentation#using-docs-blocks) in your project, we recommend following the same pattern, and creating a `_[directory]__docs.md` markdown file per directory containing all your doc blocks for that folder of models. +- ❌ **Config per project.** Some people put *all* of their source and model YAML into one file. While you can technically do this, and while it certainly simplifies knowing what file the config you’re looking for will be in (as there is only one file), it makes it much harder to find specific configurations within that file. We recommend balancing those two concerns. +- ⚠️ **Config per model.** On the other end of the spectrum, some people prefer to create one YAML file per model. This presents less of an issue than a single monolith file, as you can quickly search for files, know exactly where specific configurations exist, spot models without configs (and thus without tests) by looking at the file tree, and various other advantages. In our opinion, the extra files, tabs, and windows this requires creating, copying from, pasting to, closing, opening, and managing creates a somewhat slower development experience that outweighs the benefits. Defining config per directory is the most balanced approach for most projects, but if you have compelling reasons to use config per model, there are definitely some great projects that follow this paradigm. +- ✅ **Cascade configs.** Leverage your `dbt_project.yml` to set default configurations at the directory level. Use the well-organized folder structure we’ve created thus far to define the baseline schemas and materializations, and use dbt’s cascading scope priority to define variations to this. For example, as below, define your marts to be materialized as tables by default, define separate schemas for our separate subfolders, and any models that need to use incremental materialization can be defined at the model level. + +```yaml +-- dbt_project.yml + +models: + jaffle_shop: + staging: + +materialized: view + intermediate: + +materialized: ephemeral + marts: + +materialized: table + finance: + +schema: finance + marketing: + +schema: marketing +``` + +:::tip Define your defaults. +One of the many benefits this consistent approach to project structure confers to us is this ability to cascade default behavior. Carefully organizing our folders and defining configuration at that level whenever possible frees us from configuring things like schema and materialization in every single model (not very DRY!) — we only need to configure exceptions to our general rules. Tagging is another area this principle comes into play. Many people new to dbt will rely on tags rather than a rigorous folder structure, and quickly find themselves in a place where every model *requires* a tag. This creates unnecessary complexity. We want to lean on our folders as our primary selectors and grouping mechanism, and use tags to define groups that are *exceptions.* A folder-based selection like **`dbt build --select marts.marketing` is much simpler than trying to tag every marketing-related model, hoping all developers remember to add that tag for new models, and using `dbt build --select tag:marketing`. +::: + +### How we use the other folders + +```yaml +jaffle_shop +├── analysis +├── data +│ └── employees.csv +├── macros +│ ├── _macros.yml +│ └── cents_to_dollars.sql +├── snapshots +└── tests + └── assert_positive_value_for_total_amount.sql +``` + +We’ve focused heavily thus far on the primary area of action in our dbt project, the `models` folder. As you’ve probably observed though, there are several other folders in our project. While these are, by design, very flexible to your needs, we’ll discuss the most common use cases for these other folders to help get you started. + +- ✅ `seeds` for lookup tables. The most common use case for seeds is loading lookup tables that are helpful for modeling but don’t exist in any source systems — think mapping zip codes to states, or UTM parameters to marketing campaigns. In this example project we have a small seed that maps our employees to their `customer_id`s, so that we can handle their purchases with special logic. +- ❌ `seeds` for loading source data. Do not use seeds to load data from a source system into your warehouse. If it exists in a system you have access to, you should be loading it with a proper EL tool into the raw data area of your warehouse. dbt is designed to operate on data in the warehouse, not as a data-loading tool. +- ✅ `analysis` for storing auditing queries. The `analysis` folder lets you store any queries you want to use Jinja with and version control, but not build into models in your warehouse. There are limitless possibilities here, but the most common use case when we set up projects at dbt Labs is to keep queries that leverage the [audit helper](https://github.com/dbt-labs/dbt-audit-helper) package. This package is incredibly useful for finding discrepancies in output when migrating logic from another system into dbt. +- ✅ `tests` for testing multiple specific tables simultaneously. As dbt tests have evolved, writing singular tests has become less and less necessary. It's extremely useful for work-shopping test logic, but more often than not you'll find yourself either migrating that logic into your own custom generic tests or discovering a pre-built test that meets your needs from the ever-expanding universe of dbt packages (between the extra tests in [`dbt-utils`](https://github.com/dbt-labs/dbt-utils) and [`dbt-expectations`](https://github.com/calogica/dbt-expectations) almost any situation is covered). One area where singular tests still shine though is flexibly testing things that require a variety of specific models. If you're familiar with the difference between [unit tests](https://en.wikipedia.org/wiki/Unit_testing) [and](https://www.testim.io/blog/unit-test-vs-integration-test/) [integration](https://www.codecademy.com/resources/blog/what-is-integration-testing/) [tests](https://en.wikipedia.org/wiki/Integration_testing) in software engineering, you can think of generic and singular tests in a similar way. If you need to test the results of how several specific models interact or relate to each other, a singular test will likely be the quickest way to nail down your logic. +- ✅ `snapshots` for creating [Type 2 slowly changing dimension](https://en.wikipedia.org/wiki/Slowly_changing_dimension#Type_2:_add_new_row) records from [Type 1](https://en.wikipedia.org/wiki/Slowly_changing_dimension#Type_1:_overwrite) (destructively updated) source data. This is [covered thoroughly in the dbt Docs](https://docs.getdbt.com/docs/building-a-dbt-project/snapshots), unlike these other folders has a more defined purpose, and is out-of-scope for this guide, but mentioned for completion. +- ✅ `macros` for DRY-ing up transformations you find yourself doing repeatedly. Like snapshots, a full dive into macros is out-of-scope for this guide and well [covered elsewhere](https://docs.getdbt.com/docs/building-a-dbt-project/jinja-macros/), but one important structure-related recommendation is to [write documentation for your macros](https://docs.getdbt.com/faqs/docs/documenting-macros). We recommend creating a `_macros.yml` and documenting the purpose and arguments for your macros once they’re ready for use. + +### Project splitting + +One important, growing consideration in the analytics engineering ecosystem is how and when to split a codebase into multiple dbt projects. Our present stance on this for most projects, particularly for teams starting out, is straightforward: you should avoid it unless you have no other option or it saves you from an even more complex workaround. If you do have the need to split up your project, it’s completely possible through the use of private packages, but the added complexity and separation is, for most organizations, a hindrance not a help, at present. That said, this is very likely subject to change! [We want to create a world where it’s easy to bring lots of dbt projects together into a cohesive lineage](https://github.com/dbt-labs/dbt-core/discussions/5244). In a world where it’s simple to break up monolithic dbt projects into multiple connected projects, perhaps inside of a modern monorepo, the calculus will be different, and the below situations we recommend against may become totally viable. So watch this space! + +- ❌ **Business groups or departments.** Conceptual separations within the project are not a good reason to split up your project. Splitting up, for instance, marketing and finance modeling into separate projects will not only add unnecessary complexity, but destroy the unifying effect of collaborating across your organization on cohesive definitions and business logic. +- ❌ **ML vs Reporting use cases.** Similarly to the point above, splitting a project up based on different use cases, particularly more standard BI versus ML features, is a common idea. We tend to discourage it for the time being. As with the previous point, a foundational goal of implementing dbt is to create a single source of truth in your organization. The features you’re providing to your data science teams should be coming from the same marts and metrics that serve reports on executive dashboards. There are a growing number of tools like [fal](https://blog.fal.ai/introducing-fal-dbt/) and [Continual.ai](http://Continual.ai) that make excellent use of this unified viewpoint. +- ✅ **Data governance.** Structural, organizational needs — such as data governance and security — are one of the few worthwhile reasons to split up a project. If, for instance, you work at a healthcare company with only a small team cleared to access raw data with PII in it, you may need to split out your staging models into their own project to preserve those policies. In that case, you would import your staging project into the project that builds on those staging models as a [private package](https://docs.getdbt.com/docs/building-a-dbt-project/package-management/#private-packages). +- ✅ **Project size.** At a certain point, your project may grow to have simply too many models to present a viable development experiment. If you have 1000s of models, it absolutely makes sense to find a way to split up your project. + +## Final considerations + +Overall, consistency is more important than any of these specific conventions. As your project grows and your experience with dbt deepens, you will undoubtedly find aspects of the above structure you want to change. While we recommend this approach for the majority of projects, every organization is unique! The only dogmatic advice we’ll put forward here is that when you find aspects of the above structure you wish to change, think intently about your reasoning and document for your team *how* and *why* you are deviating from these conventions. To that end, we highly encourage you to fork this guide and add it to your project’s README, wiki, or docs so you can quickly create and customize those artifacts. + +Finally, we emphasize that this guide is a living document! It will certainly change and grow as dbt and dbt Labs evolve. We invite you to join in — discuss, comment, and contribute regarding suggested changes or new elements to cover. diff --git a/website/docs/tutorial/add-a-seed.md b/website/docs/guides/getting-started/add-a-seed.md similarity index 86% rename from website/docs/tutorial/add-a-seed.md rename to website/docs/guides/getting-started/add-a-seed.md index 7561508d2a8..85080109cd4 100644 --- a/website/docs/tutorial/add-a-seed.md +++ b/website/docs/guides/getting-started/add-a-seed.md @@ -4,7 +4,7 @@ id: add-a-seed description: Learn how to add a seed file to your project --- :::caution Heads up! -You'll need to have completed the Getting Started part of this tutorial to +You'll need to have completed the earlier parts of this guide to complete this lesson ::: diff --git a/website/docs/guides/getting-started/building-your-first-project.md b/website/docs/guides/getting-started/building-your-first-project.md new file mode 100644 index 00000000000..1bbab1a1273 --- /dev/null +++ b/website/docs/guides/getting-started/building-your-first-project.md @@ -0,0 +1,14 @@ +--- +title: "Building your first project" +id: building-your-first-project +description: "" +sidebar_label: "Building your first project" +--- + +Once you set up your warehouse and connect to dbt Cloud, you are ready to build your first dbt project. + +In this guide, you will: + +* Build your first models +* Test and document your project +* Schedule a job to be run in your production environment diff --git a/website/docs/guides/getting-started/building-your-first-project/build-your-first-models.md b/website/docs/guides/getting-started/building-your-first-project/build-your-first-models.md new file mode 100644 index 00000000000..9ccda2e6b3c --- /dev/null +++ b/website/docs/guides/getting-started/building-your-first-project/build-your-first-models.md @@ -0,0 +1,58 @@ +--- +title: Build your first models +id: build-your-first-models +description: "Now that you've set up the starter project, you can get to the fun part — building models!" +--- + +Now that you set up your sample project and had a successful run, you can get to the fun part — [building models](building-models)! You will take a sample query and turn it into a model in your dbt project. A model in dbt is a select statement. + +## Checkout a new git branch + +1. Click **Develop** from the upper left of dbt Cloud. You need to create a new branch since the main branch is now set to read-only mode. + +2. Click **Create branch**, and name your branch `add-customers-model`. +
+ +
+ +## Build your first model + +1. Click **Develop** from the upper left of dbt Cloud. +2. Click the **...** next to the Models directory, then select **Create file**. +3. Name the file `models/customers.sql`, then click **Create**. +4. Copy the following query into the file and click **Save File**. + + + +5. Enter `dbt run` in the command prompt at the bottom of the screen. You should get a successful run and see three models under DETAILS: +
+ +
+ +In the future, you would connect your business intelligence (BI) tools to these views and tables so they only read cleaned up data rather than raw data in your BI tool. + +#### FAQs + + + + + + + +## Change the way your model is materialized + + + +## Delete the example models + + + +## Build models on top of other models + + + +## Next steps + +Once you build your first model, you're ready to [test and document your project](guides/getting-started/building-your-first-project/test-and-document-your-project). + + diff --git a/website/docs/guides/getting-started/building-your-first-project/schedule-a-job.md b/website/docs/guides/getting-started/building-your-first-project/schedule-a-job.md new file mode 100644 index 00000000000..e9b172565c1 --- /dev/null +++ b/website/docs/guides/getting-started/building-your-first-project/schedule-a-job.md @@ -0,0 +1,65 @@ +--- +title: Schedule a job +id: schedule-a-job +description: In this part of the guide, we'll go through how you can schedule a job in dbt Cloud. +--- + +In this part of the guide, you will learn how to schedule a job to be run in your production environment. Scheduling a job is sometimes called _deploying a project_. + +As the `jaffle_shop` business gains more customers, and those customers create more orders, you will see more records added to your source data. Because you materialized the `customers` model as a table, you'll need to periodically rebuild your table to ensure that the data stays up-to-date. This update will happen when you run a job. + +## Commit your changes + +Now that you've built your customer model, you need to commit the changes you made to the project so that the repository has your latest code. + +1. Click **Commit** and add a message. For example, "Add customers model, tests, docs." +2. Click **merge to main** To add these changes to the main branch on your repo. + +## Create a deployment environment + +1. In the upper left, select **Deploy**, then click **Environments**. +2. Click **Create Environment**. +3. Name your deployment environment. For example, "Production." +4. Add a target dataset, for example, "Analytics." dbt will build into this dataset. For some warehouses this will be named "schema." +5. Click **Save**. + +## Create and run a job + +Jobs are a set of dbt commands that you want to run on a schedule. For example, `dbt run` and `dbt test`. + +1. After creating your deployment environment, you should be directed to the page for new environment. If not, select **Deploy** in the upper left, then click **Jobs**. +2. Click **Create one** and provide a name, for example "Production run", and link to the Environment you just created. +3. Scroll down to "Execution Settings" and select **Generate docs on run**. +4. Under "Commands," add these commands as part of your job if you don't see them: + * `dbt run` + * `dbt test` +5. For this exercise, **do NOT** set a schedule for your project to run -- while your organization's project **should** run regularly, there's no need to run this project on a schedule. +6. Select **Save**, then click **Run now** to run your job. +7. Click the run and watch its progress under "Run history." +8. Once the run is complete, click **View Documentation** to see the docs for your project. + +:::tip +Congratulations 🎉! You've just deployed your first dbt project! +::: + +### FAQs + + + +## Next steps + +Congratulations! Now that you've got a working dbt project, you can read about dbt [best practices](/guides/best-practices). + +You can improve your dbt skills with these fun exercises: + +* Turn your raw data references (for example, turn `` `dbt-tutorial`.jaffle_shop.orders``) into [sources](/docs/building-a-dbt-project/using-sources). +* Build a new models for `orders`, that uses the `payments` table to calculate the total order amount. +* Reorganize your project into [how we structure dbt projects](/blog/how-we-structure-our-dbt-projects). +* If you want a more in-depth learning experience, we recommend taking the [dbt Fundamentals on our dbt Learn online courses site](https://courses.getdbt.com/courses/fundamentals). + + +Here are some ways to [learn more](learning-more) essential dbt skills: + +* Learn how to use Jinja in your project by reading the [Jinja tutorial](using-jinja). +* Learn how to [connect to dbt Core using the CLI](getting-started-dbt-core). +* Refactor [legacy SQL to dbt SQL](refactoring-legacy-sql). diff --git a/website/docs/guides/getting-started/building-your-first-project/test-and-document-your-project.md b/website/docs/guides/getting-started/building-your-first-project/test-and-document-your-project.md new file mode 100644 index 00000000000..016880e1601 --- /dev/null +++ b/website/docs/guides/getting-started/building-your-first-project/test-and-document-your-project.md @@ -0,0 +1,26 @@ +--- +title: Test and document your project +id: test-and-document-your-project +description: Let's test and document our models to build trust in our data. +--- + +## Add tests to your models + + + +## Document your models + + + +3. Click the link above the file tree in the Develop interface to launch documentation in a new tab. + +#### FAQs + + + + +## Next steps + +Once you test and document your project, you're ready to [Schedule a job](guides/getting-started/building-your-first-project/schedule-a-job). + + diff --git a/website/docs/guides/getting-started/create-a-project.md b/website/docs/guides/getting-started/create-a-project.md new file mode 100644 index 00000000000..57df4d90b15 --- /dev/null +++ b/website/docs/guides/getting-started/create-a-project.md @@ -0,0 +1,18 @@ +--- +title: Create a project +id: create-a-project +description: "When you are ready to create projects in dbt, you can use either dbt Cloud or the dbt CLI." +--- + +Once you set up your data platform, you can create a project in dbt. When you're ready to create a project, you need to decide which interface best suits your needs for working with dbt. + +## Choose how to work with dbt + +You can work with dbt in two ways: + +* **dbt Cloud**: Edit files and run projects using the web-based Integrated Development Environment (IDE). +* **dbt CLI**: Edit files locally using a code editor, and run projects using the command line interface (CLI). + +To use the CLI, it's important that you know some basics of your terminal. In particular, you should understand `cd`, `ls` and `pwd` to navigate through the directory structure of your computer easily. As such, if you are new to programming, we recommend using **dbt Cloud** for this guide. + +If you wish to use the CLI, please follow the [installation instructions](/dbt-cli/install/overview) for your operating system. diff --git a/website/docs/guides/getting-started/getting-set-up.md b/website/docs/guides/getting-started/getting-set-up.md new file mode 100644 index 00000000000..56bbcb13ff8 --- /dev/null +++ b/website/docs/guides/getting-started/getting-set-up.md @@ -0,0 +1,10 @@ +--- +title: Getting set up in dbt Cloud +id: getting-set-up +description: "Set up a sample project to get you started using dbt Cloud." +sidebar_label: "Getting set up" +--- + +In this guide, you will learn how to set up dbt Cloud using a sample project and one of the most common data platforms. You can select from [BigQuery](/guides/getting-started/getting-set-up/setting-up-bigquery), [Databricks](/guides/getting-started/getting-set-up/setting-up-databricks), [Redshift](/guides/getting-started/getting-set-up/setting-up-redshift), or [Snowflake](/guides/getting-started/getting-set-up/setting-up-snowflake). If you're not sure, then try [BigQuery](/guides/getting-started/getting-set-up/setting-up-bigquery). + +If you'd rather edit and run files locally using the dbt command line interface (dbt CLI) to connect to dbt Core, then you can refer to [Getting started using dbt Core](/guides/getting-started/learning-more/getting-started-dbt-core). diff --git a/website/docs/guides/getting-started/getting-set-up/setting-up-bigquery.md b/website/docs/guides/getting-started/getting-set-up/setting-up-bigquery.md new file mode 100644 index 00000000000..01d2d1aa5b7 --- /dev/null +++ b/website/docs/guides/getting-started/getting-set-up/setting-up-bigquery.md @@ -0,0 +1,141 @@ +--- +title: "Set up and connect BigQuery" +id: setting-up-bigquery +description: "Set up BigQuery with sample data and connect to dbt Cloud." +sidebar_label: "Set up and connect BigQuery" +pagination_next: guides/getting-started/building-your-first-project/build-your-first-models +--- + +## Introduction + +For the BigQuery project in the getting started guide, you'll learn how to set up BigQuery and connect it to dbt Cloud. + +This guide will walk you through: + +- Setting up a new BigQuery instance +- Accessing sample data in a public data set +- Connecting dbt Cloud to BigQuery + +## Prerequisites + +Before beginning this guide, make sure that you have access to **new or existing Google account**. You can use a personal or work account to set up BigQuery through Google Cloud Platform (GCP). + +## Setting up + + + +Before jumping into the steps below, login to your Google account. + +1. Navigate to the [BigQuery Console](https://console.cloud.google.com/bigquery). + - If you don't have a Google Cloud Platform account you will be asked to create one. + - If you do have one (or multiple) it will likely log you into your oldest account. Click your profile picture to the right and verify your are using the correct email account. + +2. Create a new project for this tutorial: + - If you've just created a BigQuery account, you'll be prompted to create a new project straight away. + - If you already have an existing organization, you can select the project drop down in the header bar, and create a new project from there. +
+ +
+ +3. Select **NEW PROJECT**. You should see a project name automatically populate. You can change the name to something more relevant, for example "dbt Learn - Bigquery Setup." + +
+ +
+ +4. Click **Create**. + +## Loading data + +BigQuery supports public data sets that can be directly queried, so we will show you how to access those datasets via select statements. Additionally, we will show you how to populate your own database objects with that data. + +1. Navigate to the [BigQuery Console](https://console.cloud.google.com/bigquery) again. Make sure your new project is selected in the header. If you do not see your account or project, click your profile picture to the right and verify your are using the correct email account. + +2. Copy and paste the below queries into the Query Editor to validate that you are able to run them successfully. + + ```sql + select * from `dbt-tutorial.jaffle_shop.customers`; + select * from `dbt-tutorial.jaffle_shop.orders`; + select * from `dbt-tutorial.stripe.payment`; + ``` + +3. Verify you can see an output: +
+ +
+4. Create datasets. Datasets in BigQuery are equivalent to schemas in a traditional database. + + 1. Find your project in the picker. Click the three dots to expose options. + 2. Click **Create dataset**. +
+ +
+ 3. Fill in `Dataset ID` as required. This will be used like schema in fully qualified references to your database objects, i.e. database.schema.table, so choose a name that fits the purpose, in this case we will be creating one now for `jaffle_shop` and one for `stripe` later. +
+ +
+ 4. Leave the default values in the rest of the fields: + - `Data location` can be left blank -- if selected, this determines the GCP location where your data is stored. The current default location is the US multi-region. All tables within this dataset will share this location. + - Even though it is unchecked, billing table expiration will be set automatically to 60 days, because billing has not been enabled for this project, so GCP defaults to deprecating tables. + - Allow Google to manage encryption. + - Click `CREATE DATASET`. + - Repeat steps i through iv for the second dataset, `stripe`. + +## Connecting to dbt Cloud + +You will learn how to connect dbt Cloud to Google BigQuery so that you can leverage the power of dbt to transform data in BigQuery. + +### Generate BigQuery credentials + + + +In order to let dbt connect to your warehouse, you'll need to generate a keyfile. This is analogous to using a database user name and password with most other data warehouses. + +1. Go to the [BigQuery credential wizard](https://console.cloud.google.com/apis/credentials/wizard). Make sure your new project is selected in the header. If you do not see your account or project, click your profile picture to the right and verify your are using the correct email account. +2. Select **+ Create Credentials** then select **Service account**. +3. Type `dbt-user` in the Service account name field, then click **Create and Continue**. +4. Type and select **BigQuery Admin** in the Role field. +5. Click **Continue**. +6. Leave fields blank in the "Grant users access to this service account" section and click **Done**. +7. Click the service account that you just created. +8. Select **Keys**. +9. Click **Add Key** then select **Create new key**. +10. Select **JSON** as the key type then click **Create**. +11. You should be prompted to download the file. Save it locally to an easy-to-remember spot, with a clear filename. For example, `dbt-user-creds.json`. + +### Create a dbt Cloud account + + + + + +### Connect dbt Cloud to BigQuery + +Now let's set up the connection between dbt Cloud and BigQuery. + +1. Click **BigQuery** to set up your connection. +2. Click **Upload a Service Account JSON File** in BigQuery settings. +3. Select the JSON file you downloaded in [Generate BigQuery Credentials](#generate-bigquery-credentials). dbt Cloud will fill in all the necessary fields. +4. Click **Test** at the top. This verifies that dbt Cloud can access your BigQuery account. +5. If you see "Connection test Succeeded!" then click **Continue**. If it fails, you might need to go back and regenerate your BigQuery credentials. + +## Initialize your repository and start development + +### Setting up a managed repository + + + +### Initialize your dbt project + + + + +Congratulations! You have successfully completed the following: + +- Set up a new BigQuery instance +- Accessing sample data in a public data set +- Connected dbt Cloud to BigQuery + +## Next steps + + diff --git a/website/docs/guides/getting-started/getting-set-up/setting-up-databricks.md b/website/docs/guides/getting-started/getting-set-up/setting-up-databricks.md new file mode 100644 index 00000000000..05253abecbc --- /dev/null +++ b/website/docs/guides/getting-started/getting-set-up/setting-up-databricks.md @@ -0,0 +1,262 @@ +--- +title: "Set up and connect Databricks" +id: setting-up-databricks +description: "Set up Databricks with sample data and connect to dbt Cloud." +sidebar_label: "Set up and connect Databricks" +pagination_prev: guides/getting-started/getting-set-up +pagination_next: guides/getting-started/building-your-first-project/build-your-first-models +--- + +## Introduction + +For the Databricks project in the getting started guide, you'll learn how to set up Databricks and connect it to dbt Cloud. + +This project will walk you through: + +- Setting up a Databricks account +- Loading training data into your Databricks account +- Configuring a SQL endpoint in Databricks +- Connecting dbt Cloud and Databricks + +## Prerequisites + +Before starting this tutorial, you will need the following: + +- Existing Cloud Provider account (AWS, GCP, Azure). +- Permissions to create an S3 bucket in said account. + +## Setting up + +1. Use your existing account or sign up for a Databricks account at [Try Databricks](https://databricks.com/). Complete the form with your user information. + +
+ +
+ +2. For the purpose of this tutorial, you will be selecting AWS as our cloud provider but if you use Azure or GCP internally, please choose one of them. The setup process will be similar. +3. Check your email to complete the verification process. +4. After setting up your password, you will be guided to choose a subscription plan. You will need to select either the `Premium` or `Enterprise` plan to access the SQL Compute functionality, required for using the SQL Endpoint for dbt. We have chosen `Premium` for this tutorial. Click `Continue` after selecting your plan. + +
+ +
+ +5. Click on `Get Started` when you come to this below page and then `Confirm` after you validate that you have everything needed. + +
+ +
+
+ +
+ +6. Now it's time to create your first workspace. A Databricks workspace is an environment for accessing all of your Databricks assets. The workspace organizes objects like notebooks, SQL Endpoints, clusters, etc into one place. Provide the name of your workspace and choose the appropriate AWS region and click **Start Quickstart**. You might get the checkbox of `I have data in S3 that I want to query with Databricks`. You do not need to check this off for the purpose of this tutorial. + +
+ +
+ +7. By clicking on `Start Quickstart`, you will be redirected to AWS and asked to log in if you haven’t already. After logging in, you should see a page similar to this. + +
+ +
+ +:::tip +If you get a session error and don’t get redirected to this page, do not worry, go back to the Databricks UI and create a workspace from the interface. All you have to do is click **create workspaces**, choose the quickstart, fill out the form and click **Start Quickstart**. +::: + +8. There is no need to change any of the pre-filled out fields in the Parameters. Just add in your Databricks password under **Databricks Account Credentials**. Check off the Acknowledgement and click **Create stack**. +
+ +
+ +
+ +
+9. Afterwards, you should land on the CloudFormation > Stacks page. Once the status becomes `CREATE_COMPLETE`, you will be ready to start. This process can take about 5 minutes so feel free to click refresh to refresh the status updates. +
+ +
+10. Go back to the Databricks tab. You should see that your workspace is ready to use. +
+ +
+11. Now let’s jump into the workspace. Click on `Open` and log into the workspace using the same login as you used to log into the account. + +Congrats! You are now ready to start working in the workspace. +
+ +
+ +## Loading data + +Our next step is to load some data to transform. Luckily for us, Databricks makes it really easy for us to upload data. + +1. First we need a SQL endpoint. Find the drop down menu and toggle into the SQL space. +
+ +
+2. We will be setting up a SQL endpoint now. Select `SQL Endpoints` from the left hand side console. You will see that a default SQL Endpoint exists. +
+ +
+3. Click **Start** on the Starter Endpoint. This will take a few minutes to get the necessary resources spun up. + +4. While you're waiting, download the three CSV files locally that you will need for this tutorial. You can find them here: + - [jaffle_shop_customers.csv](https://dbt-tutorial-public.s3-us-west-2.amazonaws.com/jaffle_shop_customers.csv) + - [jaffle_shop_orders.csv](https://dbt-tutorial-public.s3-us-west-2.amazonaws.com/jaffle_shop_orders.csv) + - [stripe_payments.csv](https://dbt-tutorial-public.s3-us-west-2.amazonaws.com/stripe_payments.csv) + +5. Once the SQL Endpoint is up, click on the `Create` and then `Table` on the drop down menu. +
+ +
+ +6. Let's load the Jaffle Shop Customers data first. Drop in the `jaffle_shop_customers.csv` file into the UI. +
+ +
+ +7. Update the Table Attributes at the top: + + - data_catalog = hive_metastore + - database = default + - table = jaffle_shop_customers + - Make sure that the column data types are correct. The way you can do this is by hovering over the datatype icon next to the column name. + - ID = bigint + - FIRST_NAME = string + - LAST_NAME = string + +
+ +
+ +8. Click `Create` on the bottom once you’re done. + +9. Now let’s do the same for `Jaffle Shop Orders` and `Stripe Payments`. + +
+ +
+ +
+ +
+ +10. Once that's done, make sure you can query the training data. Navigate to the `SQL Editor` through the left hand menu. This will bring you to a query editor. +11. Ensure that you can run a `select *` from each of the tables with the following code snippets. + + ```sql + select * from default.jaffle_shop_customers + select * from default.jaffle_shop_orders + select * from default.stripe_payments + ``` + +
+ +
+ +12. To ensure any users who might be working on your dbt project has access to your object, run this command. + + ```sql + grant all privileges on schema default to users; + ``` + +Congratulations! At this point, you have created a Databricks account, loaded training data, and successfully set up a SQL end point to query the data. + +## Connecting to dbt Cloud + + There are two ways to connect dbt Cloud and Databricks. The first option is Partner Connect, which provides a streamlined setup to create your dbt Cloud account from within your new Databricks trial account. The second option is to create your dbt Cloud account separately and build the Databricks connection yourself. If you are looking to get started quickly, we recommend option 1. If you are looking to customize your setup from the very beginning and gain familiarity with the dbt Cloud setup flow, we recommend option 2. + +### Option 1: Connect dbt Cloud and Databricks with partner connect + +1. In the Databricks workspace, on the left-side console: click on `Partner Connect`. + +
+ +
+ +2. Select the dbt tile under `Data preparation and transformation`. +3. Click on `Next` when prompted to `Connect to partner`. This action will create a service principal, PAT token for that service principle, and SQL Endpoint for the dbt Cloud account to use. This does mean that you will have two SQL Endpoints at your disposal from the previous step and from using Partner Connect. + +
+ +
+ + +4. Click on `Connect to dbt Cloud`. +
+ +
+5. After the new tab loads, you will see a form. If you already created a dbt Cloud account, you will be asked to provide an account name. If you haven't created account, you will be asked to provide an account name and password. + +
+ +
+ +6. After you have filled out the form and clicked on `Complete Registration`, you will be logged into dbt Cloud automatically. + + +### Option 2: Connect dbt Cloud and Databricks manually + +#### Get endpoint and token information + +To manually setup dbt Cloud, you will need the SQL Endpoint connection information and to generate a user token. You can find your SQL endpoint connection information by going to the `Databricks UI > SQL > SQL Endpoints > Starter Endpoint > Connection details`. Save this information because you will need it later. + + + +To generate a user token for your development credentials in dbt Cloud, click on `Settings` on the left side console (while still in the SQL part of the workspace). Click on `Personal Access Token` and provide a comment like `dbt Cloud development`. Save the token information somewhere because you will need it for the next part. +
+ +
+ +#### Create a dbt Cloud account + + + +#### Connect dbt Cloud to Databricks + +1. Choose **Databricks** to setup your connection. + + +2. For the name, write `Databricks` or another simple title. +3. For Databricks settings, reference your SQL endpoint connection details from step 6 of the previous section for each of the following fields: + + - Method will be ODBC + - Hostname comes from Server hostname + - Endpoint comes from the last part of HTTP path after `/endpoints` +
+ +
+ +4. For your Development Credentials, type: + + - `User` and `token` that you saved in a previous step. + - You’ll notice that the schema name has been auto created for you. By convention, this is `dbt_`. This is the schema connected directly to your development environment, and it's where your models will be built when running dbt within the Cloud IDE. + +5. Click **Test Connection** at the bottom. This verifies that dbt Cloud can access your Databricks workspace. +6. If the connection test succeeds, click **Next**. If it fails, you may need to check your Databricks settings and credentials. + +## Initialize your repository and start development + +If you used Partner Connect, you can skip to [initializing your dbt project](/setting-up-databricks#initialize-your-dbt-project) as the Partner Connect provides you with a managed repository. Otherwise, you will need to create your managed repository connection. + +### Setting up a managed repository + + + +### Initialize your dbt project + + + +Congratulations! You have successfully completed the following: + +- Set up a Databricks account +- Loaded training data into your Databricks account +- Configured a SQL endpoint in Databricks +- Connected dbt Cloud and Databricks + +## Next steps + + diff --git a/website/docs/guides/getting-started/getting-set-up/setting-up-redshift.md b/website/docs/guides/getting-started/getting-set-up/setting-up-redshift.md new file mode 100644 index 00000000000..78c5f499cf0 --- /dev/null +++ b/website/docs/guides/getting-started/getting-set-up/setting-up-redshift.md @@ -0,0 +1,215 @@ +--- +title: "Set up and connect Redshift" +id: setting-up-redshift +description: "Set up Redshift with sample data and connect to dbt Cloud." +sidebar_label: "Set up and connect Redshift" +pagination_prev: guides/getting-started/getting-set-up +pagination_next: guides/getting-started/building-your-first-project/build-your-first-models +--- + +## Introduction + +For the Redshift project in the getting started guide, you'll learn how to set up Redshift and connect it to dbt Cloud. + +This guide will walk you through: + +- Setting up a Redshift cluster +- Loading training data into your Redshift account +- Connecting dbt Cloud and Redshift + +## Prerequisites + +Before beginning this tutorial you will need access to an **existing AWS account** with permissions to execute a CloudFormation template to create appropriate roles and a Redshift cluster. If you do not have an AWS account, head over to [Sign up for AWS](https://portal.aws.amazon.com/billing/signup#/start/email). + +## Setting up + +Let’s get started by accessing your AWS account and setting up Redshift. + +1. Sign into your AWS account on the [AWS sign in page](https://signin.aws.amazon.com/console) as a root user or IAM user depending on your level of access. +2. We will be using a CloudFormation template to quickly set up a Redshift instance. A CloudFormation template is a configuration file that will automatically spin up the necessary resources in AWS. Use the link below to start this process. (source: [cloudformation json file](https://github.com/aws-samples/aws-modernization-with-dbtlabs/blob/main/resources/cloudformation/create-dbtworkshop-infr)) + +**[Start CloudFormation Stack](https://console.aws.amazon.com/cloudformation/home?region=us-east-1#/stacks/new?stackName=dbt-workshop&templateURL=https://tpch-sample-data.s3.amazonaws.com/create-dbtworkshop-infr)** + +3. Choose next for each page until you reach the `Select acknowledgement checkbox`. Check the box for "I acknowledge that AWS CloudFormation might create IAM resources with custom names" and click `Create Stack`. You should land on the stack page with a `CREATE_IN_PROGRESS` status. + + + +4. When the stack status changes to “CREATE_COMPLETE”, click on the `Outputs` tab on the top to view information that you will use throughout the rest of this guide. Save those credentials for later by keeping this open in a tab. + +5. Type in `Redshift` to the search bar on the top and click on `Amazon Redshift` + + + +6. Confirm that your new Redshift Cluster is listed under Cluster overview. Click on the cluster name. + + + +7. Click on `Query Data`. You can choose the classic query editor or v2. We will be using the v2 version for the purpose of this guide. + +8. You may be asked to Configure account. For the purpose of this sandbox environment, we recommend selecting “Configure account”. + +9. Click on your cluster name in the list and fill out the credentials from the output of the stack. +- Database: `dbtworkshop` +- User Name: `dbtadmin` +- Password: *choose your own password and save it for later* + + + + + +10. Click on `Create Connection`. + +Congrats! You have your Redshift cluster. + +## Loading data + +Now we are going to load our sample data into the S3 bucket that our Cloudformation template created. S3 buckets are a cheap and simple way to store data outside of Redshift. + +1. The data used in this course is stored as CSVs in a public S3 bucket. You can use the following URLs to download these files. Download these to your computer to use in the following steps. +- [jaffle_shop_customers.csv](https://dbt-tutorial-public.s3-us-west-2.amazonaws.com/jaffle_shop_customers.csv) +- [jaffle_shop_orders.csv](https://dbt-tutorial-public.s3-us-west-2.amazonaws.com/jaffle_shop_orders.csv) +- [stripe_payments.csv](https://dbt-tutorial-public.s3-us-west-2.amazonaws.com/stripe_payments.csv) + +2. Now we are going to use the S3 bucket that you created via CloudFormation and upload the files. Go to the search bar at the top and type in `S3` and click on S3. There will be sample data in the file already, feel free to ignore it or use it for other modeling exploration. + + + + +3. Click on the `name of the bucket` S3 bucket. If you have multiple S3 buckets, this will be the bucket that was listed under “Workshopbucket” on the Outputs page. The bucket will be prefixed with `dbt-data-lake`. + + + +4. Click on `Upload`, drag the three files into the UI, and click on `Upload` on the button. + + + +5. Save the name of the S3 bucket. It should look like this: `s3://dbt-data-lake-xxxx`. You will need it for the next section. +6. Now let’s go back to the Redshift query editor. Search for Redshift in the search bar, choose your cluster, and select Query data. +7. In your query editor, execute this query below to create the schemas that we will be placing your raw data into. You can highlight the statement and then click on Run to run them individually. If you are on the Classic Query Editor, you might need to input them separately into the UI. You should see these schemas listed under `dbtworkshop`. + +```sql +create schema if not exists jaffle_shop; +create schema if not exists stripe; +``` + +8. Now create the tables in your schema with these queries using the statements below. These will be populated as tables in the respective schemas. + +```sql +create table jaffle_shop.customers( + id integer, + first_name varchar(50), + last_name varchar(50) +); + +create table jaffle_shop.orders( + id integer, + user_id integer, + order_date date, + status varchar(50), + _etl_loaded_at timestamp default current_timestamp +); + +create table stripe.payment( + id integer, + orderid integer, + paymentmethod varchar(50), + status varchar(50), + amount integer, + created date, + _batched_at timestamp default current_timestamp +); +``` + +9. Now we need to copy the data from S3. **Be sure to update the S3 location, iam role, and region.** You can find the S3 and iam role in your outputs from the Cloudformation stack. + +```sql +copy jaffle_shop.customers( id, first_name, last_name) +from 's3://dbt-data-lake-xxxx/jaffle_shop_customers.csv' +iam_role 'arn:aws:iam::XXXXXXXXXX:role/RoleName' +region 'us-east-1' +delimiter ',' +ignoreheader 1 +acceptinvchars; + +copy jaffle_shop.orders(id, user_id, order_date, status) +from 's3://dbt-data-lake-xxxx/jaffle_shop_orders.csv' +iam_role 'arn:aws:iam::XXXXXXXXXX:role/RoleName' +region 'us-east-1' +delimiter ',' +ignoreheader 1 +acceptinvchars; + +copy stripe.payment(id, orderid, paymentmethod, status, amount, created) +from 's3://dbt-data-lake-xxxx/stripe_payments.csv' +iam_role 'arn:aws:iam::XXXXXXXXXX:role/RoleName' +region 'us-east-1' +delimiter ',' +ignoreheader 1 +Acceptinvchars; +``` + +Ensure that you can run a select * from each of the tables with the following code snippets. + +```sql +select * from jaffle_shop.customers; +select * from jaffle_shop.orders; +select * from stripe.payment; +``` + +Congratulations! At this point, you have created a Redshift instance and loaded training data. In the next section, we will walk through the next steps to connect dbt Cloud and Redshift. + +## Connecting to dbt Cloud + +#### Create a dbt Cloud account + + + +#### Connect dbt Cloud to Redshift + +Now let's set up the connection between dbt Cloud and Redshift + +1. Click **Redshift** to set up your connection. +
+ +
+ +2. For the name, write `Redshift` or another simple title. + +3. Enter your Redshift settings. Reference your credentials you saved from the CloudFormation template. + - Your hostname is the entire hostname. Make sure to drop the http:// at the beginning and any trailing slashes at the end. + - The port is `5439` + - The database is `dbtworkshop`. +
+ +
+ +4. Set your development credentials. These credentials will be used by dbt Cloud to connect to Redshift. Those credentials (as provided in your cloudformation output) will be: + - Username: `dbtadmin` + - password: *this was the password that you set earlier in the guide* + - Schema: You’ll notice that the schema name has been auto created for you. By convention, this is `dbt_`. This is the schema connected directly to your development environment, and it's where your models will be built when running dbt within the Cloud IDE. +
+ +
+ +4. Click **Test Connection** at the bottom. This verifies that dbt Cloud can access your Redshift cluster. +5. If the connection test succeeds, click **Next**. If it fails, you may need to check your Redshift settings and credentials. + +## Initialize your repository and start development + +### Setting up a managed repository + + + +### Initialize your dbt project + + + +Congratulations! You have successfully completed the following: + +- Set up a Redshift cluster +- Loaded training data into your Redshift account +- Connected dbt Cloud and Redshift + +## Next steps + + diff --git a/website/docs/guides/getting-started/getting-set-up/setting-up-snowflake.md b/website/docs/guides/getting-started/getting-set-up/setting-up-snowflake.md new file mode 100644 index 00000000000..de11ac74ab7 --- /dev/null +++ b/website/docs/guides/getting-started/getting-set-up/setting-up-snowflake.md @@ -0,0 +1,293 @@ +--- +title: "Set up and connect Snowflake" +id: setting-up-snowflake +description: "Set up Snowflake with sample data and connect to dbt Cloud." +sidebar_label: "Set up and connect Snowflake" +pagination_prev: guides/getting-started/getting-set-up +pagination_next: guides/getting-started/building-your-first-project/build-your-first-models +--- + +## Introduction + +For the Snowflake project in the getting started guide, you'll learn how to set up Snowflake and connect it to dbt Cloud. + +This guide will walk you through: + +* Setting up a Snowflake trial account +* Loading training data into your Snowflake account +* Creating a dbt Cloud account, either through Partner Connect or through the account flow +* Connecting dbt Cloud and Snowflake +* Setting up the dbt Cloud IDE, querying data, and doing your first dbt run + +## Prerequisites + +The only prerequisites for this guide are to have access to an email account for signing up for Snowflake and dbt Cloud. + +## Setting up + +You can start by signing up for a free trial on Snowflake: + +1. Sign up for a free trial by following [this link](https://signup.snowflake.com/) and completing the sign-up form. +2. Select the Enterprise edition, choose a cloud provider and region, and agree to the terms of service. + + You should consider organizational questions when choosing a cloud provider for a full implementation. For more information, see [Introduction to Cloud Platforms](https://docs.snowflake.com/en/user-guide/intro-cloud-platforms.html) in the Snowflake docs. For the purposes of this setup, all cloud providers and regions will work so choose whichever you’d like. +3. Click **GET STARTED**. +
+ +
+ +4. After submitting the sign-up form, you should receive an email asking you to activate your account. Click the link in the email and a new tab will open up where you’ll create your username and password. Complete the form and click **Get started**. +
+ +
+ +5. Congrats! Your workspace is ready for some data. Feel free to check out any of the getting started tooltips that Snowflake provides in the UI to familiarize yourself before moving on to the next section. +
+ +
+ +## Loading data + +Now we’re ready for some sample data. The data used here is stored as CSV files in a public S3 bucket and the following steps will guide you through how to prepare your Snowflake account for that data and upload it. + +1. If using the new Snowflake UI, create a new worksheet by clicking the "+ Worksheet" button in the upper right hand corner of the screen. + +

+ +

+ +2. Run the following commands to create a new virtual warehouse, two new databases (one for raw data, the other for future dbt development), and two new schemas (one for `jaffle_shop` data, the other for 'stripe' data). If you're curious to learn more about the naming conventions used, check out [this article](https://blog.getdbt.com/how-we-configure-snowflake/). Feel free to copy/paste from below: + +```sql +create warehouse transforming; +create database raw; +create database analytics; +create schema raw.jaffle_shop; +create schema raw.stripe; +``` + +

+ +

+ +3. Our next step will focus on creating **three** raw tables in the `raw` database and `jaffle_shop` and `stripe` schemas. Execute the tabbed code snippets below to create the customers, orders, and payment table and load the respective data. + + + + + + ```sql + ​​create table raw.jaffle_shop.customers + ( id integer, + first_name varchar, + last_name varchar + ); + + copy into raw.jaffle_shop.customers (id, first_name, last_name) + from 's3://dbt-tutorial-public/jaffle_shop_customers.csv' + file_format = ( + type = 'CSV' + field_delimiter = ',' + skip_header = 1 + ); + ``` + + + + + + ```sql + create table raw.jaffle_shop.orders + ( id integer, + user_id integer, + order_date date, + status varchar, + _etl_loaded_at timestamp default current_timestamp + ); + + copy into raw.jaffle_shop.orders (id, user_id, order_date, status) + from 's3://dbt-tutorial-public/jaffle_shop_orders.csv' + file_format = ( + type = 'CSV' + field_delimiter = ',' + skip_header = 1 + ); + ``` + + + + + + ```sql + create table raw.stripe.payment + ( id integer, + orderid integer, + paymentmethod varchar, + status varchar, + amount integer, + created date, + _batched_at timestamp default current_timestamp + ); + + copy into raw.stripe.payment (id, orderid, paymentmethod, status, amount, created) + from 's3://dbt-tutorial-public/stripe_payments.csv' + file_format = ( + type = 'CSV' + field_delimiter = ',' + skip_header = 1 + ); + ``` + + + + +

+ +

+ +

+ +

+ +

+ +

+ +6. Great! Your data is loaded and ready to go. Just to make sure, run the following commands to query your data and confirm that you see an output for each one. + +```sql +select * from raw.jaffle_shop.customers; +select * from raw.jaffle_shop.orders; +select * from raw.stripe.payment; +``` + +Now we’re ready to set up dbt Cloud! + +## Connecting to dbt Cloud + +There are two ways to connect dbt Cloud and Snowflake. The first option is Partner Connect, which provides a streamlined setup to create your dbt Cloud account from within your new Snowflake trial account. The second option is to create your dbt Cloud account separately and build the Snowflake connection yourself. If you are looking to get started quickly, we recommend **option 1**. If you are looking to customize your setup from the very beginning and gain familiarity with the dbt Cloud setup flow, we recommend **option 2**. + +### Option 1: Connect dbt Cloud and Snowflake with partner connect + +1. With your Snowflake account up and running with data, we’re ready to connect it with dbt Cloud. We’re going to use [Snowflake Partner Connect](https://docs.snowflake.com/en/user-guide/ecosystem-partner-connect.html) to set up your dbt Cloud account and project. Using Partner Connect will allow you to create a complete dbt account with your [Snowflake connection](https://docs.getdbt.com/docs/dbt-cloud/cloud-configuring-dbt-cloud/connecting-your-database#connecting-to-snowflake), [a managed repository](https://docs.getdbt.com/docs/dbt-cloud/cloud-configuring-dbt-cloud/cloud-using-a-managed-repository), [environments](https://docs.getdbt.com/docs/guides/managing-environments), and credentials. +2. There’s a couple of ways you can access the Partner Connect page depending on if you’re navigating in the classic Snowflake UI or the new UI. + + * **Snowflake Classic UI:** If you’re using the classic version of the Snowflake UI, you can click the Partner Connect button in the top bar of your account. From there, click on the dbt tile to open up the connect box. + +

+ +

+ + * **Snowflake New UI:** If you’re using the new web interface, you’ll want to click on your name in the upper left hand corner and then click on Partner Connect in the drop down menu. You can scroll down to find the dbt tile, or search for dbt in the search bar and it will float to the top. Click on the tile to open up the connect box. + +

+ +

+ +

+ +

+ +3. Once you’ve clicked on the tile, a connection box will appear that will look slightly different depending on the route you took above, but will contain the same Optional Grant box towards the bottom. In both cases, you’ll want to type in or select the `RAW` and `ANALYTICS` databases. This will grant access for your new dbt user role to each database. + +

+ +

+ +

+ +

+ +4. After you’ve entered the database names using either option above, click "Connect". You should see a pop up window similar to the one of the options below. Click Activate. + +

+ +

+ +

+ +

+ +5. A new tab will be created that will take you to the dbt Cloud website. Here you’ll be asked to create an account name with password, as well as agree to the Terms of Service. Once that’s done, click Complete Registration. + +

+ +

+ +6. We have one slight tweak to make to the dbt Cloud interface to account for the `analytics` database and `transforming` warehouse created earlier. Click the gear icon in the upper right and select **Account Settings**. Choose the "Partner Connection Trial" project and select `snowflake` in the overview table. Select edit and update the fields `database` and `warehouse` to be `analytics` and `transforming`, respectively. + +

+ +

+ +

+ +

+ +7. Great! Your dbt Cloud account is now completely setup and connected to your Snowflake trial account with a [managed repository](https://docs.getdbt.com/docs/dbt-cloud/cloud-configuring-dbt-cloud/cloud-using-a-managed-repository). You can skip to the **[Initialize your repo and start development](#initialize-your-repository-and-start-development)** section to get started in the IDE. + +### Option 2: Connect dbt Cloud and Snowflake manually + +#### Create a dbt Cloud account + + + +#### Connect dbt Cloud to Snowflake + +Now let's formally set up the connection between dbt Cloud and Snowflake. + +1. Choose **Snowflake** to setup your connection. +
+ +
+2. For the name, write `Snowflake` or another simple title. +2. Enter the following information under Snowflake settings. + * **Account:** Find your account by using the Snowflake trial account URL and removing `snowflakecomputing.com`. The order of your account information will vary by Snowflake version. For example, Snowflake's Classic console URL might look like: `oq65696.west-us-2.azure.snowflakecomputing.com`. The AppUI or Snowsight URL might look more like: `snowflakecomputing.com/west-us-2.azure/oq65696`. In both examples, your account will be: `oq65696.west-us-2.azure`. For more information, see "[Account Identifiers](https://docs.snowflake.com/en/user-guide/admin-account-identifier.html)" in the Snowflake documentation. +
+ * **Role:** Leave blank for now. You can update this to a default Snowflake role in the future. + * **Database:** `analytics`. This tells dbt to create new models in the analytics database. + * **Warehouse:** `transforming`. This tells dbt to use the transforming warehouse we created earlier. +
+ +
+ +3. Enter the following information under Development credentials. + * **Username:** The username you created for Snowflake. Note: The username is not your email address and is usually your first and last name together in one word. + * **Password:** The password you set when creating your Snowflake account + * **Schema:** You’ll notice that the schema name has been auto created for you. By convention, this is `dbt_`. This is the schema connected directly to your development environment, and it's where your models will be built when running dbt within the Cloud IDE. + * **Target name:** leave as default + * **Threads:** Leave as 4. This is the number of simultaneous connects that dbt Cloud will make to build models concurrently. +
+ +
+ +4. Click **Test Connection** at the bottom. This verifies that dbt Cloud can access your Snowflake account. +5. If the connection test succeeds, click **Next**. If it fails, you may need to check your Snowflake settings and credentials. + +## Initialize your repository and start development + +If you used Partner Connect, you can skip over to [initializing your dbt project](/setting-up-snowflake#initialize-your-dbt-project) as the Partner Connect sets you up with an managed repostiory already. If not, you will need to create your managed repository connection. + +### Setting up a managed repository + + + +### Initialize your dbt project + + + +Congratulations! You have successfully completed the following: + +- Set up a new Snowflake instance +- Loaded training data into your Snowflake account +- Connected dbt Cloud and Snowflake + +## Next steps + + diff --git a/website/docs/guides/getting-started/getting-started.md b/website/docs/guides/getting-started/getting-started.md new file mode 100644 index 00000000000..0cd06fe699e --- /dev/null +++ b/website/docs/guides/getting-started/getting-started.md @@ -0,0 +1,29 @@ +--- +title: Getting started with dbt Cloud +id: getting-started +description: "Create your first dbt project using a SQL query." +--- + +dbt centralizes your analytics code and enables software engineering-style guardrails for data teams. dbt enables you to collaborate on SQL, version it through Git, and test and document your queries before safely deploying them to production and monitoring them. + +dbt takes your analytics code and helps you modularize it before you compile and run against your database. This enables you and your team to collaborate on a single source of truth for metrics and insights. A single source of truth, combined with the ability to define tests for your data, reduces errors when your analytics code is updated due to changes in your business and alerts you when a job fails + +This guide will show you how to set up dbt Cloud and perform some key tasks. These tasks will illustrate how dbt establishes standard practices for your work. + +In this guide, you will: + +* Set up a warehouse with sample data +* Connect the warehouse to dbt Cloud +* Add a Git repository to dbt Cloud +* Execute a dbt transformation using `dbt run` +* Schedule a job or transformation + +If you want a more in-depth learning experience, we recommend taking the dbt Fundamentals on our [dbt Learn online courses site](https://courses.getdbt.com/). + +## Before you begin + +Before you begin, you will need: + +* Warehouse with sample data. If you don't have this, you can use the [Big Query project](guides/getting-started/getting-set-up/setting-up-bigquery), which leverages public data sets. +* Basic understanding of Git. +* Basic understanding of SQL. diff --git a/website/docs/guides/getting-started/learning-more.md b/website/docs/guides/getting-started/learning-more.md new file mode 100644 index 00000000000..0ee54c5e8c7 --- /dev/null +++ b/website/docs/guides/getting-started/learning-more.md @@ -0,0 +1,14 @@ +--- +title: "Learning more" +id: learning-more +description: "Learn more dbt skills and make more impact using dbt." +sidebar_label: "Learning more" +--- + +After building your first models, testing and documenting your project, and scheduling a job, you can explore different ways to enhance your dbt skills. + +To learn more: + +* Connect to dbt Core using the command line interface +* Refactor legacy SQL +* Learn how to use Jinja diff --git a/website/docs/guides/getting-started/learning-more/getting-started-dbt-core.md b/website/docs/guides/getting-started/learning-more/getting-started-dbt-core.md new file mode 100644 index 00000000000..32213e2c9b2 --- /dev/null +++ b/website/docs/guides/getting-started/learning-more/getting-started-dbt-core.md @@ -0,0 +1,261 @@ +--- +title: "Getting started with dbt Core" +id: getting-started-dbt-core +description: "Connecting your warehouse to dbt Core using the CLI." +sidebar_label: "Getting started with dbt Core" +--- + +When you use dbt Core to work with dbt, you will be editing files locally using a code editor, and running projects using the dbt command line interface (dbt CLI). If you'd rather edit files and run projects using the web-based Integrated Development Environment (IDE), you should refer to [Getting set up in dbt Cloud](/guides/getting-started/getting-set-up). + +## Prerequisites + +* To use the dbt CLI, it's important that you know some basics of the Terminal. In particular, you should understand `cd`, `ls` and `pwd` to navigate through the directory structure of your computer easily. +* Install dbt Core using the [installation instructions](/dbt-cli/install/overview) for your operating system. +* Complete [Setting up (in BigQuery)](/guides/getting-started/getting-set-up/setting-up-bigquery#setting-up) and [Loading data (BigQuery)](/guides/getting-started/getting-set-up/setting-up-bigquery#loading-data). +* [Create a GitHub account](https://github.com/join) if you don't already have one. + +## Create a starter project + +After setting up BigQuery to work with dbt, you are ready to create a starter project with example models, before building your own models. + +### Create a repository + +The following steps use [GitHub](https://github.com/) as the Git provider for this guide, but you can use any Git provider. You should have already [created a GitHub account](https://github.com/join). + +1. [Create a new GitHub repository](https://github.com/new) named `dbt-tutorial`. +2. Select **Public** so the repository can be shared with others. You can always make it private later. +3. Leave the default values for all other settings. +4. Click **Create repository**. +5. Save the commands from "…or create a new repository on the command line" to use later in [Commit your changes](#commit-your-changes). + +### Create a project + +Learn how to use a series of commands using the command line of the Terminal to create your project. dbt Core includes an `init` command that helps scaffold a dbt project. + +To create your dbt project: + +1. Make sure you have dbt Core installed and check the version using the `dbt --version` command: + + ```terminal + dbt --version + ``` + +2. Initiate the `jaffle_shop` project using the `init` command: + + ```terminal + dbt init jaffle_shop + ``` + +3. Navigate into your project's directory: + + ```terminal + cd jaffle_shop + ``` + +4. Use `pwd` to confirm that you are in the right spot: + + ```terminal + $ pwd + > Users/BBaggins/dbt-projects/jaffle_shop + ``` + +5. Use a code editor like Atom or VSCode to open the project directory you created in the previous steps, which we named jaffle_shop. The content includes folders and `.sql` and `.yml` files generated by the `init` command. + +
+ +
+ +6. Update the following values in the `dbt_project.yml` file: + + + + ```yaml + name: jaffle_shop # Change from the default, `my_new_project` + + ... + + profile: jaffle_shop # Change from the default profile name, `default` + + ... + + models: + jaffle_shop: # Change from `my_new_project` to match the previous value for `name:` + ... + ``` + + + +### Connect to BigQuery + +When developing locally, dbt connects to your using a [profile](/dbt-cli/configure-your-profile), which is a yaml file with all the connection details to your warehouse. + +1. Create a file in the `~/.dbt/` directory named `profiles.yml`. +2. Move your BigQuery keyfile into this directory. +3. Copy the following and paste into the new profiles.yml file. Make sure you update the values where noted. + + + + ```yaml + jaffle_shop: # this needs to match the profile in your dbt_project.yml file + target: dev + outputs: + dev: + type: bigquery + method: service-account + keyfile: /Users/BBaggins/.dbt/dbt-tutorial-project-331118.json # replace this with the full path to your keyfile + project: grand-highway-265418 # Replace this with your project id + dataset: dbt_bbagins # Replace this with dbt_your_name, e.g. dbt_bilbo + threads: 1 + timeout_seconds: 300 + location: US + priority: interactive + ``` + + + +4. Run the `debug` command from your project to confirm that you can successfully connect: + + ```terminal + $ dbt debug + > Connection test: OK connection ok + ``` + +
+ +
+ +#### FAQs + + + + + + + +### Perform your first dbt run + +Our sample project has some example models in it. We're going to check that we can run them to confirm everything is in order. + +1. Enter the `run` command to build example models: + + ```terminal + dbt run + ``` + +You should have an output that looks like this: +
+ +
+ +### Commit your changes + +Commit your changes so that the repository contains the latest code. + +1. Link the GitHub repository you created to your dbt project by running the following commands in Terminal. Make sure you use the correct git URL for your repository, which you should have saved from step 5 in [Create a repository](#create-a-repository). + + ```terminal + git init + git branch -M main + git add . + git commit -m "Create a dbt project" + git remote add origin https://github.com/USERNAME/dbt-tutorial.git + git push -u origin main + ``` + +2. Return to your GitHub repository to verify your new files have been added. + +## Build your first models + +Now that you set up your sample project, you can get to the fun part — [building models](building-models)! You will take a sample query and turn it into a model in your dbt project. + +### Checkout a new git branch + +Check out a new git branch to work on new code: + +1. Create a new branch by using the `checkout` command and passing the `-b` flag: + + ```terminal + $ git checkout -b add-customers-model + > Switched to a new branch `add-customer-model` + ``` + +### Build your first model + +1. Open your project in your favorite code editor. +2. Create a new SQL file in the `models` directory, named `models/customers.sql`. +3. Paste the following query into the `models/customers.sql` file. + + + +4. From the command line, enter `dbt run`. +
+ +
+ +When you return to the BigQuery console, you can `select` from this model. + +#### FAQs + + + + + + + +### Change the way your model is materialized + + + + + +### Delete the example models + + + +### Build models on top of other models + + + +### Next steps + + + +You can also explore: + +* The `target` directory to see all of the compiled SQL. The `run` directory shows the create or replace table statements that are running, which are the select statements wrapped in the correct DDL. +* The `logs` file to see how dbt Core logs all of the action happening within your project. It shows the selects statements that are running and the python logging happening when dbt runs. + +## Test and document your project + +### Add tests to your models + + + +### Document your models + + + +3. Run `dbt docs serve` command to launch the documentation in a local website. + +#### FAQs + + + + + +#### Next steps + + + +### Commit updated changes + +You need to commit the changes you made to the project so that the repository has your latest code. + +1. Add all your changes to git: `git add -A` +2. Commit your changes: `git commit -m "Add customers model, tests, docs"` +3. Push your changes to your repository: `git push` +4. Navigate to your repository, and open a pull request to merge the code into your master branch. + +## Schedule a job + +We recommend using dbt Cloud to schedule a job. For more information about using dbt Core to schedule a job, see [dbt airflow](/blog/dbt-airflow-spiritual-alignment) blog post or [Running a dbt project](/docs/running-a-dbt-project/running-dbt-in-production). diff --git a/website/docs/tutorial/refactoring-legacy-sql.md b/website/docs/guides/getting-started/learning-more/refactoring-legacy-sql.md similarity index 86% rename from website/docs/tutorial/refactoring-legacy-sql.md rename to website/docs/guides/getting-started/learning-more/refactoring-legacy-sql.md index 04dafcd4cab..b6a79aed5e8 100644 --- a/website/docs/tutorial/refactoring-legacy-sql.md +++ b/website/docs/guides/getting-started/learning-more/refactoring-legacy-sql.md @@ -1,28 +1,29 @@ --- -title: Refactoring legacy SQL to dbt SQL +title: Refactoring legacy SQL to dbt id: refactoring-legacy-sql -description: This tutorial walks through refactoring a long SQL query (perhaps from a stored procedure) into modular dbt data models. +description: This guide walks through refactoring a long SQL query (perhaps from a stored procedure) into modular dbt data models. --- -You may have already learned how to build dbt models from scratch. +You may have already learned how to build dbt models from scratch. -But in reality, you probably already have some queries or stored procedures that power analyses and dashboards, and now you’re wondering how to port those into dbt. +But in reality, you probably already have some queries or stored procedures that power analyses and dashboards, and now you’re wondering how to port those into dbt. -There are two parts to accomplish this: migration and refactoring. In this tutorial we’re going to learn a process to help us turn legacy SQL code into modular dbt models. +There are two parts to accomplish this: migration and refactoring. In this guide we’re going to learn a process to help us turn legacy SQL code into modular dbt models. When migrating and refactoring code, it’s of course important to stay organized. We'll do this is by following several steps (jump directly from the right sidebar): 1. Migrate your code 1:1 into dbt 2. Implement dbt sources rather than referencing raw database tables 3. Choose a refactoring strategy -4. Implement CTE groupings and cosmetic cleanup +4. Implement CTE groupings and cosmetic cleanup 5. Separate data transformations into standardized layers 6. Audit the output of dbt models vs legacy SQL Let's get into it! -> Note: this tutorial is excerpted from the new dbt Learn On-demand Course, "Refactoring from Procedural SQL to dbt" - if you're curious, pick up the [free refactoring course here](https://courses.getdbt.com/courses/refactoring), which includes example and practice refactoring projects. - +:::info More resources. +This guide is excerpted from the new dbt Learn On-demand Course, "Refactoring SQL for Modularity" - if you're curious, pick up the [free refactoring course here](https://courses.getdbt.com/courses/refactoring-sql-for-modularity), which includes example and practice refactoring projects. Or for a more in-depth look at migrating DDL and DML from stored procedures check out [this guide](/guides/migration/tools/migrating-from-stored-procedures/1-migrating-from-stored-procedures). +::: ## Migrate your existing SQL code @@ -35,13 +36,13 @@ To get going, you'll copy your legacy SQL query into your dbt project, by saving -Once you've copied it over, you'll want to `dbt run` to execute the query and populate the table in your warehouse. +Once you've copied it over, you'll want to `dbt run` to execute the query and populate the in your warehouse. -> If this is your first time running dbt, you may want to start with the [Introduction to dbt](/docs/introduction) and the [Getting Started tutorial](/tutorial/setting-up) before diving into refactoring. +> If this is your first time running dbt, you may want to start with the [Introduction to dbt](/docs/introduction) and the earlier sections of the [Getting Started guide](/guides/getting-started/) before diving into refactoring. This step may sound simple, but if you're porting over an existing set of SQL transformations to a new SQL dialect, you will need to consider how your legacy SQL dialect differs from your new SQL flavor, and you may need to modify your legacy code to get it to run at all. -This will commonly happen if you're migrating from a [stored procedure workflow on a legacy database](https://getdbt.com/analytics-engineering/case-for-elt-workflow/) into dbt + a cloud data warehouse. +This will commonly happen if you're migrating from a [stored procedure workflow on a legacy database](https://getdbt.com/analytics-engineering/case-for-elt-workflow/) into dbt + a cloud . Functions that you were using previously may not exist, or their syntax may shift slightly between SQL dialects. @@ -92,7 +93,7 @@ Means that you will work directly on the SQL script that you ported over in the You'll move it into a `/marts` subfolder within your project's `/models` folder and go to town. -**Pros**: +**Pros**: - You won't have any old models to delete once refactoring is done. **Cons**: @@ -116,7 +117,6 @@ Means that you will copy your model to a `/marts` folder, and work on changes on We generally recommend the **alongside** approach, which we'll follow in this tutorial. - ## Implement CTE groupings Once you choose your refactoring strategy, you'll want to do some cosmetic cleanups according to your data modeling best practices and start moving code into CTE groupings. This will give you a head start on porting SQL snippets from CTEs into modular [dbt data models](https://docs.getdbt.com/docs/building-a-dbt-project/building-models). @@ -185,7 +185,7 @@ We'll cover that later - for now, just use `select * from {{ source('schema', 't Logical CTEs contain unique transformations used to generate the final product, and we want to separate these into logical blocks. To identify our logical CTEs, we will follow subqueries in order. -If a subquery has nested subqueries, we will want to continue moving down until we get to the first layer, then pull out the subqueries in order as CTEs, making our way back to the final select statement. +If a has nested subqueries, we will want to continue moving down until we get to the first layer, then pull out the subqueries in order as CTEs, making our way back to the final select statement. Name these CTEs as the alias that the subquery was given - you can rename it later, but for now it is best to make as few changes as possible. @@ -201,7 +201,7 @@ After you have moved everything into CTEs, you'll want to write a `select * from This allows anyone after us to easily step through the CTEs when troubleshooting, rather than having to untangle nested queries. -> For more background on CTEs, check out the [dbt Labs style guide](https://github.com/dbt-labs/corp/blob/master/dbt_style_guide.md#ctes). +> For more background on CTEs, check out the [dbt Labs style guide](https://github.com/dbt-labs/corp/blob/main/dbt_style_guide.md#ctes). ## Port CTEs to individual data models Rather than keep our SQL code confined to one long SQL file, we'll now start splitting it into modular + reusable [dbt data models](https://docs.getdbt.com/docs/building-a-dbt-project/building-models). @@ -237,13 +237,13 @@ Our final model accomplishes the result set we want, and it uses the components -We'll want to audit our results using the dbt [audit_helper package](https://hub.getdbt.com/fishtown-analytics/audit_helper/latest/). +We'll want to audit our results using the dbt [audit_helper package](https://hub.getdbt.com/dbt-labs/audit_helper/latest/). Under the hood, it generates comparison queries between our before and after states, so that we can compare our original query results to our refactored results to identify differences. Sure, we could write our own query manually to audit these models, but using the dbt `audit_helper` package gives us a head start and allows us to identify variances more quickly. ## Ready for refactoring practice? -Head to the free on-demand course, [Refactoring from Procedural SQL to dbt](https://courses.getdbt.com/courses/refactoring) for a more in-depth refactoring example + a practice refactoring problem to test your skills. +Head to the free on-demand course, [Refactoring from Procedural SQL to dbt](https://courses.getdbt.com/courses/refactoring-sql-for-modularity) for a more in-depth refactoring example + a practice refactoring problem to test your skills. -Questions on this tutorial or the course? Drop a note in #learn-on-demand in [dbt Community Slack](https://getdbt.com/community). +Questions on this guide or the course? Drop a note in #learn-on-demand in [dbt Community Slack](https://getdbt.com/community). diff --git a/website/docs/tutorial/using-jinja.md b/website/docs/guides/getting-started/learning-more/using-jinja.md similarity index 99% rename from website/docs/tutorial/using-jinja.md rename to website/docs/guides/getting-started/learning-more/using-jinja.md index 3acf0e10b4c..43cf95059a4 100644 --- a/website/docs/tutorial/using-jinja.md +++ b/website/docs/guides/getting-started/learning-more/using-jinja.md @@ -3,7 +3,7 @@ title: "Using Jinja" id: "using-jinja" --- -In this tutorial, we're going to take a common pattern used in SQL, and then use Jinja to improve our code. +In this guide, we're going to take a common pattern used in SQL, and then use Jinja to improve our code. If you'd like to work through this query, add [this CSV](https://github.com/dbt-labs/jaffle_shop/blob/core-v1.0.0/seeds/raw_payments.csv) to the `seeds/` folder of your dbt project, and then execute `dbt seed`. @@ -16,7 +16,6 @@ Consider a data model in which an `order` can have many `payments`. Each `paymen From an analytics perspective, it's important to know how much of each `order` was paid for with each `payment_method`. In your dbt project, you can create a model, named `order_payment_method_amounts`, with the following SQL: - ```sql diff --git a/website/docs/docs/guides/best-practices.md b/website/docs/guides/legacy/best-practices.md similarity index 81% rename from website/docs/docs/guides/best-practices.md rename to website/docs/guides/legacy/best-practices.md index 21b67769f58..969886da238 100644 --- a/website/docs/docs/guides/best-practices.md +++ b/website/docs/guides/legacy/best-practices.md @@ -11,7 +11,7 @@ All dbt projects should be managed in version control. Git branches should be cr :::info Git guide -We've codified our best practices in Git, in our [Git guide](https://github.com/dbt-labs/corp/blob/master/git-guide.md). +We've codified our best practices in Git, in our [Git guide](https://github.com/dbt-labs/corp/blob/main/git-guide.md). ::: @@ -23,14 +23,14 @@ SQL styles, field naming conventions, and other rules for your dbt project shoul :::info Our style guide -We've made our [style guide](https://github.com/dbt-labs/corp/blob/master/dbt_style_guide.md) public – these can act as a good starting point for your own style guide. +We've made our [style guide](https://github.com/dbt-labs/corp/blob/main/dbt_style_guide.md) public – these can act as a good starting point for your own style guide. ::: ## Best practices in dbt projects ### Use the ref function -The [ref](ref) function is what makes dbt so powerful! Using the `ref` function allows dbt to infer dependencies, ensuring that models are built in the correct order. It also ensures that your current model selects from upstream tables and views in the same environment that you're working in. +The [ref](ref) function is what makes dbt so powerful! Using the `ref` function allows dbt to infer dependencies, ensuring that models are built in the correct order. It also ensures that your current model selects from upstream tables and views in the same environment that you're working in. Always use the `ref` function when selecting from another model, rather than using the direct relation reference (e.g. `my_schema.my_table`). ### Limit references to raw data @@ -62,9 +62,9 @@ You can instead find our opinions on how we structure our dbt projects in [this ::: ### Break complex models up into smaller pieces -Complex models often include multiple Common Table Expressions (CTEs). In dbt, you can instead separate these CTEs into separate models that build on top of each other. It is often a good idea to break up complex models when: +Complex models often include multiple Common Table Expressions (CTEs). In dbt, you can instead separate these CTEs into separate models that build on top of each other. It is often a good idea to break up complex models when: * A CTE is duplicated across two models. Breaking the CTE into a separate model allows you to reference the model from any number of downstream models, reducing duplicated code. -* A CTE changes the grain of a the data it selects from. It's often useful to test any transformations that change the grain (as in, what one record represents) of your data. Breaking a CTE into a separate model allows you to test this transformation independently of a larger model. +* A CTE changes the of a the data it selects from. It's often useful to test any transformations that change the grain (as in, what one record represents) of your data. Breaking a CTE into a separate model allows you to test this transformation independently of a larger model. * The SQL in a query contains many lines. Breaking CTEs into separate models can reduce the cognitive load when another dbt user (or your future self) is looking at the code. ### Group your models in directories @@ -81,19 +81,19 @@ dbt provides a framework to test assumptions about the results generated by a mo :::info Recommended tests -Our [coding conventions](https://github.com/dbt-labs/corp/blob/master/dbt_coding_conventions.md) recommend that at a minimum, every model should have a primary key that is tested to ensure it is unique, and not null. +Our [style guide](https://github.com/dbt-labs/corp/blob/main/dbt_style_guide.md) recommends that at a minimum, every model should have a that is tested to ensure it is unique, and not null. ::: ### Consider the information architecture of your data warehouse -When a user connects to a data warehouse via a SQL client, they often rely on the names of schemas, relations, and columns, to understand the data they are presented with. To improve the information architecture of a data warehouse, we: +When a user connects to a via a SQL client, they often rely on the names of schemas, relations, and columns, to understand the data they are presented with. To improve the information architecture of a data warehouse, we: * Use [custom schemas](using-custom-schemas) to separate relations into logical groupings, or hide intermediate models in a separate schema. Generally, these custom schemas align with the directories we use to group our models, and are configured from the `dbt_project.yml` file. -* Use prefixes in table names (for example, `stg_`, `fct_` and `dim_`) to indicate which relations should be queried by end users. +* Use prefixes in names (for example, `stg_`, `fct_` and `dim_`) to indicate which relations should be queried by end users. ### Choose your materializations wisely -[Materializations](materializations) determine the way models are built through configuration. As a general rule: +[](materializations) determine the way models are built through configuration. As a general rule: * Views are faster to build, but slower to query compared to tables. -* Incremental models provide the same query performance as tables, are faster to build compared to the table materialization, however they introduce complexity into a project. +* Incremental models provide the same query performance as tables, are faster to build compared to the table , however they introduce complexity into a project. We often: * Use views by default @@ -158,6 +158,37 @@ dbt test --select result:fail --exclude --defer --state path/to/p > Note: If you're using the `--state target/` flag, `result:error` and `result:fail` flags can only be selected concurrently(in the same command) if using the `dbt build` command. `dbt test` will overwrite the `run_results.json` from `dbt run` in a previous command invocation. +:::caution Experimental functionality +The `source_status` selection method is experimental and subject to change. During this time, ongoing improvements may limit this feature’s availability and cause breaking changes to its functionality. +::: + + + +Only supported by v1.1 or newer. + + + + + +Only supported by v1.1 or newer. + +By comparing to a `sources.json` artifact from a previous production run to a current `sources.json` artifact, dbt can determine which sources are fresher and run downstream models based on them. + +```bash +# job 1 +dbt source freshness # must be run to get previous state +``` + +Test all my sources that are fresher than the previous run, and run and test all models downstream of them: + +```bash +# job 2 +dbt source freshness # must be run again to compare current to previous state +dbt build --select source_status:fresher+ --state path/to/prod/artifacts +``` + + + To learn more, read the docs on [state](understanding-state). ## Pro-tips for dbt Projects diff --git a/website/docs/docs/guides/building-packages.md b/website/docs/guides/legacy/building-packages.md similarity index 89% rename from website/docs/docs/guides/building-packages.md rename to website/docs/guides/legacy/building-packages.md index df7d4ef5e7e..bf29a0b0479 100644 --- a/website/docs/docs/guides/building-packages.md +++ b/website/docs/guides/legacy/building-packages.md @@ -41,7 +41,7 @@ When working on your package, we often find it useful to install a local copy of ### Follow our best practices _Modeling packages only_ -Use our [dbt coding conventions](https://github.com/dbt-labs/corp/blob/master/dbt_style_guide.md), our article on [how we structure our dbt projects](https://discourse.getdbt.com/t/how-we-structure-our-dbt-projects/355), and our [best practices](best-practices) for all of our advice on how to build your dbt project. +Use our [dbt coding conventions](https://github.com/dbt-labs/corp/blob/main/dbt_style_guide.md), our article on [how we structure our dbt projects](https://discourse.getdbt.com/t/how-we-structure-our-dbt-projects/355), and our [best practices](best-practices) for all of our advice on how to build your dbt project. This is where it comes in especially handy to have worked on your own dbt project previously. @@ -50,7 +50,7 @@ _Modeling packages only_ Not every user of your package is going to store their Mailchimp data in a schema named `mailchimp`. As such, you'll need to make the location of raw data configurable. -We recommend using [sources](using-sources) and [variables](using-variables) to achieve this. Check out [this package](https://github.com/fivetran/dbt_facebook_ads_source/blob/master/models/src_facebook_ads.yml#L5-L6) for an example — notably, the README [includes instructions](https://github.com/fivetran/dbt_facebook_ads_source#configuration) on how to override the default schema from a `dbt_project.yml` file. +We recommend using [sources](using-sources) and [variables](using-variables) to achieve this. Check out [this package](https://github.com/fivetran/dbt_facebook_ads_source/blob/main/models/src_facebook_ads.yml#L5-L6) for an example — notably, the README [includes instructions](https://github.com/fivetran/dbt_facebook_ads_source#configuration) on how to override the default schema from a `dbt_project.yml` file. ### Install upstream packages from hub.getdbt.com @@ -75,10 +75,10 @@ Many SQL functions are specific to a particular database. For example, the funct If you wish to support multiple warehouses, we have a number of tricks up our sleeve: - We've written a number of macros that compile to valid SQL snippets on each of the original four adapters. Where possible, leverage these macros. - If you need to implement cross-database compatibility for one of your macros, use the [`adapter.dispatch` macro](dispatch) to achieve this. Check out the cross-database macros in dbt-utils for examples. -- If you're working on a modeling package, you may notice that you need write different models for each warehouse (for example, if the EL tool you are working with stores data differently on each warehouse). In this case, you can write different versions of each model, and use the [`enabled` config](enabled), in combination with [`target.type`](dbt-jinja-functions/target) to enable the correct models — check out [this package](https://github.com/fivetran/dbt_facebook_ads_creative_history/blob/master/dbt_project.yml#L11-L16) as an example. +- If you're working on a modeling package, you may notice that you need write different models for each warehouse (for example, if the EL tool you are working with stores data differently on each warehouse). In this case, you can write different versions of each model, and use the [`enabled` config](enabled), in combination with [`target.type`](/reference/dbt-jinja-functions/target) to enable the correct models — check out [this package](https://github.com/fivetran/dbt_facebook_ads_creative_history/blob/main/dbt_project.yml#L11-L16) as an example. -If your package has only been written to work for one data warehouse, make sure you document this in your package README. +If your package has only been written to work for one , make sure you document this in your package README. ### Use specific model names _Modeling packages only_ @@ -88,7 +88,7 @@ Many datasets have a concept of a "user" or "account" or "session". To make sure ### Default to views _Modeling packages only_ -dbt makes it possible for users of your package to override your model materialization settings. In general, default to materializing models as `view`s instead of `table`s. +dbt makes it possible for users of your package to override your model settings. In general, default to materializing models as `view`s instead of `table`s. The major exception to this is when working with data sources that benefit from incremental modeling (for example, web page views). Implementing incremental logic on behalf of your end users is likely to be helpful in this case. ### Test and document your package @@ -132,7 +132,7 @@ packages: 5. Confirm that you can run `dbt run` and `dbt test` from your command line successfully. -5. (Optional) Use a CI tool, like CircleCI or GitHub Actions, to automate running your dbt project when you open a new Pull Request. For inspiration, check out one of our [CircleCI configs](https://github.com/dbt-labs/snowplow/blob/master/.circleci/config.yml), which runs tests against our four main warehouses. Note: this is an advanced step — if you are going down this path, you may find it useful to say hi on [dbt Slack](https://community.getdbt.com/). +5. (Optional) Use a CI tool, like CircleCI or GitHub Actions, to automate running your dbt project when you open a new Pull Request. For inspiration, check out one of our [CircleCI configs](https://github.com/dbt-labs/snowplow/blob/main/.circleci/config.yml), which runs tests against our four main warehouses. Note: this is an advanced step — if you are going down this path, you may find it useful to say hi on [dbt Slack](https://community.getdbt.com/). ## 5. Deploy the docs for your package _Optional_ diff --git a/website/docs/docs/guides/database-specific-guides/creating-date-partitioned-tables.md b/website/docs/guides/legacy/creating-date-partitioned-tables.md similarity index 89% rename from website/docs/docs/guides/database-specific-guides/creating-date-partitioned-tables.md rename to website/docs/guides/legacy/creating-date-partitioned-tables.md index 3ee7ccaeb32..9d22025761d 100644 --- a/website/docs/docs/guides/database-specific-guides/creating-date-partitioned-tables.md +++ b/website/docs/guides/legacy/creating-date-partitioned-tables.md @@ -12,7 +12,7 @@ The functionality described below was introduced in dbt Core v0.10 (March 2018). dbt supports the creation of [date partitioned tables](https://cloud.google.com/bigquery/docs/partitioned-tables) in BigQuery. -To configure a dbt model as a date partitioned table, use the `materialized='table'` model configuration in conjunction with a list of `partitions`. dbt will execute your model query once for each specified partition. For example: +To configure a dbt model as a date partitioned , use the `materialized='table'` model configuration in conjunction with a list of `partitions`. dbt will execute your model query once for each specified partition. For example: @@ -46,7 +46,7 @@ from `snowplow`.`events_[DBT__PARTITION_DATE]` -To make this model more dynamic, we can use the `dbt.partition_range` macro to generate a list of 8-digit dates in a specified range. Further, dbt provides a handy macro, `date_sharded_table`, for getting a date-sharded table by its prefix for a given date. Together, this looks like: +To make this model more dynamic, we can use the `dbt.partition_range` macro to generate a list of 8-digit dates in a specified range. Further, dbt provides a handy macro, `date_sharded_table`, for getting a date-sharded by its prefix for a given date. Together, this looks like: @@ -114,4 +114,4 @@ Here's an example of running this model for the first 3 days of 2018 as a part o ``` dbt run --select partitioned_yesterday --vars 'dates: "20180101, 20180103"' -``` \ No newline at end of file +``` diff --git a/website/docs/docs/guides/creating-new-materializations.md b/website/docs/guides/legacy/creating-new-materializations.md similarity index 80% rename from website/docs/docs/guides/creating-new-materializations.md rename to website/docs/guides/legacy/creating-new-materializations.md index 5826a04e1e1..9dec21fbec6 100644 --- a/website/docs/docs/guides/creating-new-materializations.md +++ b/website/docs/guides/legacy/creating-new-materializations.md @@ -5,7 +5,7 @@ id: "creating-new-materializations" ## Overview -The model materializations you're familiar with, `table`, `view`, and `incremental` are implemented as macros in a package that's distributed along with dbt. You can check out the source for these materializations [here](https://github.com/dbt-labs/dbt-core/tree/dev/louisa-may-alcott/core/dbt/include/global_project/macros/materializations). If you need to create your own materializations, reading these files is a good place to start. Continue reading below for a deep-dive into dbt materializations. +The model materializations you're familiar with, `table`, `view`, and `incremental` are implemented as macros in a package that's distributed along with dbt. You can check out the source for these materializations [here](https://github.com/dbt-labs/dbt-core/tree/dev/louisa-may-alcott/core/dbt/include/global_project/macros/materializations). If you need to create your own materializations, reading these files is a good place to start. Continue reading below for a deep-dive into dbt materializations. :::caution @@ -63,7 +63,7 @@ Each of these tasks are explained in sections below. ### Prepare the database -Materializations are responsible for creating new tables or views in the database, or inserting/updating/deleting data from existing tables. As such, materializations need to know about the state of the database to determine exactly what sql they should run. Here is some pseudocode for the "setup" phase of the **table** materialization: +Materializations are responsible for creating new tables or views in the database, or inserting/updating/deleting data from existing tables. As such, materializations need to know about the state of the database to determine exactly what sql they should run. Here is some pseudocode for the "setup" phase of the **** materialization: ```sql -- Refer to the table materialization (linked above) for an example of real syntax @@ -89,7 +89,7 @@ Pre- and post-hooks can be specified for any model -- be sure that your material ``` ### Executing SQL -Construct your materialization DML to account for the different permutations of table existence, materialization flags, etc. There are a number of [adapter functions](dbt-jinja-functions/adapter) and context variables that can help you here. Be sure to consult the Reference section of this site for a full list of variables and functions at your disposal. +Construct your materialization to account for the different permutations of existence, materialization flags, etc. There are a number of [adapter functions](/reference/dbt-jinja-functions/adapter) and context variables that can help you here. Be sure to consult the Reference section of this site for a full list of variables and functions at your disposal. ### Run post-hooks @@ -148,7 +148,7 @@ Materializations should [return](return) the list of Relations that they have cr If a materialization solely creates a single relation, then returning that relation at the end of the materialization is sufficient to synchronize the dbt Relation cache. If the materialization *renames* or *drops* Relations other than the relation returned by the materialization, then additional work is required to keep the cache in sync with the database. -To explicitly remove a relation from the cache, use [adapter.drop_relation](dbt-jinja-functions/adapter). To explicitly rename a relation in the cache, use [adapter.rename_relation](dbt-jinja-functions/adapter). Calling these methods is preferable to executing the corresponding SQL directly, as they will mutate the cache as required. If you do need to execute the SQL to drop or rename relations directly, use the `adapter.cache_dropped` and `adapter.cache_renamed` methods to synchronize the cache. +To explicitly remove a relation from the cache, use [adapter.drop_relation](/reference/dbt-jinja-functions/adapter). To explicitly rename a relation in the cache, use [adapter.rename_relation](/reference/dbt-jinja-functions/adapter). Calling these methods is preferable to executing the corresponding SQL directly, as they will mutate the cache as required. If you do need to execute the SQL to drop or rename relations directly, use the `adapter.cache_dropped` and `adapter.cache_renamed` methods to synchronize the cache. ## Materialization Configuration @@ -165,7 +165,7 @@ config.get('optional_config_name', default="the default") config.require('required_conifg_name') ``` -For more information on the `config` dbt Jinja function, see the [config](dbt-jinja-functions/config) reference. +For more information on the `config` dbt Jinja function, see the [config](/reference/dbt-jinja-functions/config) reference. ## Materialization precedence diff --git a/website/docs/docs/guides/custom-generic-tests.md b/website/docs/guides/legacy/custom-generic-tests.md similarity index 95% rename from website/docs/docs/guides/custom-generic-tests.md rename to website/docs/guides/legacy/custom-generic-tests.md index 4809669bf9b..7ece5f08496 100644 --- a/website/docs/docs/guides/custom-generic-tests.md +++ b/website/docs/guides/legacy/custom-generic-tests.md @@ -20,7 +20,7 @@ There are tons of generic tests defined in open source packages, such as [dbt-ut Generic tests are defined in SQL files. Those files can live in two places: - `tests/generic/`: that is, a special subfolder named `generic` within your [test paths](test-paths) (`tests/` by default) -- `macros/`: Why? Generic tests work work a lot like macros, and historically, this was the only place they could be defined. If your generic test depends on complex macro logic, you may find it more convenient to define the macros and the generic test in the same file. +- `macros/`: Why? Generic tests work a lot like macros, and historically, this was the only place they could be defined. If your generic test depends on complex macro logic, you may find it more convenient to define the macros and the generic test in the same file. To define your own generic tests, simply create a `test` block called ``. All generic tests should accept one or both of the standard arguments: - `model`: The resource on which the test is defined, templated out to its relation name. (Note that the argument is always named `model`, even when the resource is a source, seed, or snapshot.) @@ -143,7 +143,7 @@ models: It is possible to include a `config()` block in a generic test definition. Values set there will set defaults for all specific instances of that generic test, unless overridden within the specific instance's `.yml` properties. - + ```sql {% test warn_if_odd(model, column_name) %} diff --git a/website/docs/docs/guides/debugging-errors.md b/website/docs/guides/legacy/debugging-errors.md similarity index 96% rename from website/docs/docs/guides/debugging-errors.md rename to website/docs/guides/legacy/debugging-errors.md index 3fef4e47f8d..72529da3f85 100644 --- a/website/docs/docs/guides/debugging-errors.md +++ b/website/docs/guides/legacy/debugging-errors.md @@ -11,7 +11,7 @@ Learning how to debug is a skill, and one that will make you great at your role! - The `target/run` directory contains the SQL dbt executes to build your models. - The `logs/dbt.log` file contains all the queries that dbt runs, and additional logging. Recent errors will be at the bottom of the file. - **dbt Cloud users**: Use the above, or the `Details` tab in the command output. - - **dbt CLI users**: Note that your code editor _may_ be hiding these files from the tree view ([Atom help](https://discuss.atom.io/t/all-gitignored-files-are-hidden-now-atom-1-15/39238), [VSCode help](https://stackoverflow.com/questions/42891463/how-can-i-show-ignored-files-in-visual-studio-code)). + - **dbt CLI users**: Note that your code editor _may_ be hiding these files from the tree ([Atom help](https://discuss.atom.io/t/all-gitignored-files-are-hidden-now-atom-1-15/39238), [VSCode help](https://stackoverflow.com/questions/42891463/how-can-i-show-ignored-files-in-visual-studio-code)). 5. If you are really stuck, try [asking for help](getting-help). Before doing so, take the time to write your question well so that others can diagnose the problem quickly. @@ -315,11 +315,11 @@ Found a cycle: model.jaffle_shop.customers --> model.jaffle_shop.stg_customers - Your dbt DAG is not acyclic, and needs to be fixed! - Update the `ref` functions to break the cycle. -- If you need to reference the current model, use the [`{{ this }}` variable](dbt-jinja-functions/this) instead. +- If you need to reference the current model, use the [`{{ this }}` variable](/reference/dbt-jinja-functions/this) instead. ## Database Errors -The thorniest errors of all! These errors come from your data warehouse, and dbt passes the message on. You may need to use your warehouse docs (i.e. the Snowflake docs, or BigQuery docs) to debug these. +The thorniest errors of all! These errors come from your , and dbt passes the message on. You may need to use your warehouse docs (i.e. the Snowflake docs, or BigQuery docs) to debug these. ``` $ dbt run diff --git a/website/docs/docs/guides/debugging-schema-names.md b/website/docs/guides/legacy/debugging-schema-names.md similarity index 100% rename from website/docs/docs/guides/debugging-schema-names.md rename to website/docs/guides/legacy/debugging-schema-names.md diff --git a/website/docs/docs/guides/getting-help.md b/website/docs/guides/legacy/getting-help.md similarity index 85% rename from website/docs/docs/guides/getting-help.md rename to website/docs/guides/legacy/getting-help.md index 7adfc835ce7..436444a6206 100644 --- a/website/docs/docs/guides/getting-help.md +++ b/website/docs/guides/legacy/getting-help.md @@ -6,9 +6,8 @@ dbt is open source, and has a generous community behind it. Asking questions wel ### 1. Try to solve your problem first before asking for help -#### Check out the existing documentation -We invest heavily in our docs, so this should be the first place you turn! If you're a new dbt user, spend some time completing the [Getting Started tutorial](/tutorial/setting-up) to get familiar with dbt. - +#### Search the existing documentation +The docs site you're on is highly searchable, make sure to explore for the answer here as a first step. If you're new to dbt, try working through the [Getting Started guide](/guides/getting-started/) first to get a firm foundation on the essential concepts. #### Try to debug the issue yourself We have a handy guide on [debugging errors](debugging-errors) to help out! This guide also helps explain why errors occur, and which docs you might need to search for help. @@ -43,9 +42,10 @@ We use a number of different mediums to share information - If your question is roughly "I've hit this error and am stuck", please ask it on [Stack Overflow](https://stackoverflow.com/questions/ask?tags=dbt). - If you think you've found a bug, please report it on the relevant GitHub repo (e.g. [dbt repo](https://github.com/dbt-labs/dbt), [dbt-utils repo](https://github.com/dbt-labs/dbt-utils)) - If you are looking for an opinionated answer (e.g. "What's the best approach to X?", "Why is Y done this way?"), then, feel free to join our [Slack community](https://community.getdbt.com/) and ask it in the correct channel: - * **#beginners:** A great channel if you're getting started with dbt and want to understand how it works. - * **#modeling:** This channel is most useful when wanting to ask questions about data model design, SQL patterns, and testing. - * **#suggestions:** Got an idea for dbt? This is the place! + * **#advice-dbt-for-beginners:** A great channel if you're getting started with dbt and want to understand how it works. + * **#advice-dbt-for-power-users:** If you’re hitting an error in dbt that you don’t understand, let us know here. + * **#advice-data-modeling:** This channel is most useful when wanting to ask questions about data model design, SQL patterns, and testing. + * **#dbt-suggestions:** Got an idea for dbt? This is the place! * Other channels: We're adding new channels all the time — please take a moment to browse the channels to see if there is a better fit ## Receiving dedicated support diff --git a/website/docs/docs/guides/navigating-the-docs.md b/website/docs/guides/legacy/navigating-the-docs.md similarity index 97% rename from website/docs/docs/guides/navigating-the-docs.md rename to website/docs/guides/legacy/navigating-the-docs.md index e65a439b7b3..4a289ef50e6 100644 --- a/website/docs/docs/guides/navigating-the-docs.md +++ b/website/docs/guides/legacy/navigating-the-docs.md @@ -46,7 +46,7 @@ How analytics engineers use dbt to solve their tactical problems, e.g.: * Version controlling UDFs * Writing a custom schema test for not null * Snowflake shares + dbt -* Permission schemes in a data warehouse +* Permission schemes in a Usually these are write-ups where there is no one perfect answer (unlike the “I’m stuck” questions on Stack Overflow), instead, you might need to dig into the “why” or discuss tradeoffs of your approach in these articles. diff --git a/website/docs/docs/guides/understanding-state.md b/website/docs/guides/legacy/understanding-state.md similarity index 64% rename from website/docs/docs/guides/understanding-state.md rename to website/docs/guides/legacy/understanding-state.md index bfb0390be02..9573452e376 100644 --- a/website/docs/docs/guides/understanding-state.md +++ b/website/docs/guides/legacy/understanding-state.md @@ -9,9 +9,9 @@ title: "Understanding state" -One of the greatest underlying assumptions about dbt is that its operations should be **stateless** and **idempotent**. That is, it doesn't matter how many times a model has been run before, or if it has ever been run before. It doesn't matter if you run it once or a thousand times. Given the same raw data, you can expect the same transformed result. A given run of dbt doesn't need to "know" about _any other_ run; it just needs to know about the code in the project and the objects in your database as they exist _right now_. +One of the greatest underlying assumptions about dbt is that its operations should be **stateless** and ****. That is, it doesn't matter how many times a model has been run before, or if it has ever been run before. It doesn't matter if you run it once or a thousand times. Given the same raw data, you can expect the same transformed result. A given run of dbt doesn't need to "know" about _any other_ run; it just needs to know about the code in the project and the objects in your database as they exist _right now_. -That said, dbt does store "state"—a detailed, point-in-time view of project resources, database objects, and invocation results—in the form of its [artifacts](dbt-artifacts). If you choose, dbt can use these artifacts to inform certain operations. Crucially, the operations themselves are still stateless and idempotent: given the same manifest and the same raw data, dbt will produce the same transformed result. +That said, dbt does store "state"—a detailed, point-in-time view of project resources, database objects, and invocation results—in the form of its [artifacts](dbt-artifacts). If you choose, dbt can use these artifacts to inform certain operations. Crucially, the operations themselves are still stateless and : given the same manifest and the same raw data, dbt will produce the same transformed result. dbt can leverage artifacts from a prior invocation as long as their file path is passed to the `--state` flag. This is a prerequsite for: - [The `state:` selector](methods#the-state-method), whereby dbt can identify resources that are new or modified @@ -69,3 +69,33 @@ The state and result selectors can also be combined in a single invocation of db ```bash $ dbt run --select result:+ state:modified+ --defer --state ./ ``` + +### The "source_status" status + + +Only supported by v1.1 or newer. + + + + + +Only supported by v1.1 or newer. + +:::caution Experimental functionality +The `source_status` selection method is experimental and subject to change. During this time, ongoing improvements may limit this feature’s availability and cause breaking changes to its functionality. +::: + + +Another element of job state is the `source_status` of a prior dbt invocation. After executing `dbt source freshness`, for example, dbt creates the `sources.json` artifact which contains execution times and `max_loaded_at` dates for dbt sources. You can read more about `sources.json` on the ['sources'](/docs/reference/artifacts/sources-json) page. + +The following dbt commands produce `sources.json` artifacts whose results can be referenced in subsequent dbt invocations: +- `dbt source freshness` + +After issuing one of the above commands, you can reference the source freshness results by adding a selector to a subsequent command as follows: + +```bash +# You can also set the DBT_ARTIFACT_STATE_PATH environment variable instead of the --state flag. +$ dbt source freshness # must be run again to compare current to previous state +$ dbt build --select source_status:fresher+ --state path/to/prod/artifacts +``` + \ No newline at end of file diff --git a/website/docs/docs/guides/videos.md b/website/docs/guides/legacy/videos.md similarity index 100% rename from website/docs/docs/guides/videos.md rename to website/docs/guides/legacy/videos.md diff --git a/website/docs/guides/migration/tools/migrating-from-stored-procedures/1-migrating-from-stored-procedures.md b/website/docs/guides/migration/tools/migrating-from-stored-procedures/1-migrating-from-stored-procedures.md new file mode 100644 index 00000000000..aae8b373b2c --- /dev/null +++ b/website/docs/guides/migration/tools/migrating-from-stored-procedures/1-migrating-from-stored-procedures.md @@ -0,0 +1,27 @@ +--- +title: Migrating from DDL, DML, and stored procedures +id: 1-migrating-from-stored-procedures +--- + +One of the more common situations that new dbt adopters encounter is a historical codebase of transformations written as a hodgepodge of DDL and DML statements, or stored procedures. Going from DML statements to dbt models is often a challenging hump for new users to get over, because the process involves a significant paradigm shift between a procedural flow of building a dataset (e.g. a series of DDL and DML statements) to a declarative approach to defining a dataset (e.g. how dbt uses SELECT statements to express data models). This guide aims to provide tips, tricks, and common patterns for converting DML statements to dbt models. + +## Preparing to migrate + +Before getting into the meat of conversion, it’s worth noting that DML statements will not always illustrate a comprehensive set of columns and column types that an original table might contain. Without knowing the DDL to create the table, it’s impossible to know precisely if your conversion effort is apples-to-apples, but you can generally get close. + +If your supports `SHOW CREATE TABLE`, that can be a quick way to get a comprehensive set of columns you’ll want to recreate. If you don’t have the DDL, but are working on a substantial stored procedure, one approach that can work is to pull column lists out of any DML statements that modify the table, and build up a full set of the columns that appear. + +As for ensuring that you have the right column types, since models materialized by dbt generally use `CREATE TABLE AS SELECT` or `CREATE VIEW AS SELECT` as the driver for object creation, tables can end up with unintended column types if the queries aren’t explicit. For example, if you care about `INT` versus `DECIMAL` versus `NUMERIC`, it’s generally going to be best to be explicit. The good news is that this is easy with dbt: you just cast the column to the type you intend. + +We also generally recommend that column renaming and type casting happen as close to the source tables as possible, typically in a layer of staging transformations, which helps ensure that future dbt modelers will know where to look for those transformations! See [How we structure our dbt projects](/guides/best-practices/how-we-structure/1-guide-overview) for more guidance on overall project structure. + +### Operations we need to map + +There are four primary DML statements that you are likely to have to convert to dbt operations while migrating a procedure: + +- `INSERT` +- `UPDATE` +- `DELETE` +- `MERGE` + +Each of these can be addressed using various techniques in dbt. Handling `MERGE`s is a bit more involved than the rest, but can be handled effectively via dbt. The first three, however, are fairly simple to convert. diff --git a/website/docs/guides/migration/tools/migrating-from-stored-procedures/2-mapping-inserts.md b/website/docs/guides/migration/tools/migrating-from-stored-procedures/2-mapping-inserts.md new file mode 100644 index 00000000000..8453160c4db --- /dev/null +++ b/website/docs/guides/migration/tools/migrating-from-stored-procedures/2-mapping-inserts.md @@ -0,0 +1,57 @@ +--- +title: Inserts +id: 2-inserts +--- + +An `INSERT` statement is functionally the same as using dbt to `SELECT` from an existing source or other dbt model. If you are faced with an `INSERT`-`SELECT` statement, the easiest way to convert the statement is to just create a new dbt model, and pull the `SELECT` portion of the `INSERT` statement out of the procedure and into the model. That’s basically it! + +To really break it down, let’s consider a simple example: + +```sql +INSERT INTO returned_orders (order_id, order_date, total_return) + +SELECT order_id, order_date, total FROM orders WHERE type = 'return' +``` + +Converting this with a first pass to a [dbt model](docs/building-a-dbt-project/building-models) (in a file called returned_orders.sql) might look something like: + +```sql +SELECT + order_id as order_id, + order_date as order_date, + total as total_return + +FROM {{ ref('orders') }} + +WHERE type = 'return' +``` + +Functionally, this would create a model (which could be materialized as a table or view depending on needs) called `returned_orders` that contains three columns: `order_id`, `order_date`, `total_return`) predicated on the type column. It achieves the same end as the `INSERT`, just in a declarative fashion, using dbt. + +## **A note on `FROM` clauses** + +In dbt, using a hard-coded table or view name in a `FROM` clause is one of the most serious mistakes new users make. dbt uses the ref and source macros to discover the ordering that transformations need to execute in, and if you don’t use them, you’ll be unable to benefit from dbt’s built-in lineage generation and pipeline execution. In the sample code throughout the remainder of this article, we’ll use ref statements in the dbt-converted versions of SQL statements, but it is an exercise for the reader to ensure that those models exist in their dbt projects. + +## **Sequential `INSERT`s to an existing table can be `UNION ALL`’ed together** + +Since dbt models effectively perform a single `CREATE TABLE AS SELECT` (or if you break it down into steps, `CREATE`, then an `INSERT`), you may run into complexities if there are multiple `INSERT` statements in your transformation that all insert data into the same table. Fortunately, this is a simple thing to handle in dbt. Effectively, the logic is performing a `UNION ALL` between the `INSERT` queries. If I have a transformation flow that looks something like (ignore the contrived nature of the scenario): + +```sql +CREATE TABLE all_customers + +INSERT INTO all_customers SELECT * FROM us_customers + +INSERT INTO all_customers SELECT * FROM eu_customers +``` + +The dbt-ified version of this would end up looking something like: + +```sql +SELECT * FROM {{ ref('us_customers') }} + +UNION ALL + +SELECT * FROM {{ ref('eu_customers') }} +``` + +The logic is functionally equivalent. So if there’s another statement that `INSERT`s into a model that I’ve already created, I can just add that logic into a second `SELECT` statement that is just `UNION ALL`'ed with the first. Easy! diff --git a/website/docs/guides/migration/tools/migrating-from-stored-procedures/3-mapping-updates.md b/website/docs/guides/migration/tools/migrating-from-stored-procedures/3-mapping-updates.md new file mode 100644 index 00000000000..b6f0874fb6b --- /dev/null +++ b/website/docs/guides/migration/tools/migrating-from-stored-procedures/3-mapping-updates.md @@ -0,0 +1,55 @@ +--- +title: Updates +id: 3-updates +--- + +`UPDATE`s start to increase the complexity of your transformations, but fortunately, they’re pretty darn simple to migrate, as well. The thought process that you go through when translating an `UPDATE` is quite similar to how an `INSERT` works, but the logic for the `SELECT` list in the dbt model is primarily sourced from the content in the `SET` section of the `UPDATE` statement. Let’s look at a simple example: + +```sql +UPDATE orders + +SET type = 'return' + +WHERE total < 0 +``` + +The way to look at this is similar to an `INSERT`-`SELECT` statement. The table being updated is the model you want to modify, and since this is an `UPDATE`, that model has likely already been created, and you can either: + +- add to it with subsequent transformations +- create an intermediate model that builds off of the original model – perhaps naming it something like `int_[entity]_[verb].sql`. + +The `SELECT` list should contain all of the columns for the table, but for the specific columns being updated by the DML, you’ll use the computation on the right side of the equals sign as the `SELECT`ed value. Then, you can use the target column name on the left of the equals sign as the column alias. + +If I were building an intermediate transformation from the above query would translate to something along the lines of: + +```sql +SELECT + CASE + WHEN total < 0 THEN 'return' + ELSE type + END AS type, + + order_id, + order_date + +FROM {{ ref('stg_orders') }} +``` + +Since the `UPDATE` statement doesn’t modify every value of the type column, we use a `CASE` statement to apply the contents’ `WHERE` clause. We still want to select all of the columns that should end up in the target table. If we left one of the columns out, it wouldn’t be passed through to the target table at all due to dbt’s declarative approach. + +Sometimes, you may not be sure what all the columns are in a table, or in the situation as above, you’re only modifying a small number of columns relative to the total number of columns in the table. It can be cumbersome to list out every column in the table, but fortunately dbt contains some useful utility macros that can help list out the full column list of a table. + +Another way I could have written the model a bit more dynamically might be: + +```sql +SELECT + {{ dbt_utils.star(from=ref('stg_orders'), except=['type']) }}, + CASE + WHEN total < 0 THEN 'return' + ELSE type + END AS type, + +FROM {{ ref('stg_orders') }} +``` + +The `dbt_utils.star()` macro will print out the full list of columns in the table, but skip the ones I’ve listed in the except list, which allows me to perform the same logic while writing fewer lines of code. This is a simple example of using dbt macros to simplify and shorten your code, and dbt can get a lot more sophisticated as you learn more techniques. Read more about the [dbt_utils package](https://hub.getdbt.com/dbt-labs/dbt_utils/latest/) and the [star macro](https://github.com/dbt-labs/dbt-utils/tree/0.8.6/#star-source). diff --git a/website/docs/guides/migration/tools/migrating-from-stored-procedures/4-mapping-deletes.md b/website/docs/guides/migration/tools/migrating-from-stored-procedures/4-mapping-deletes.md new file mode 100644 index 00000000000..f7a6542acc7 --- /dev/null +++ b/website/docs/guides/migration/tools/migrating-from-stored-procedures/4-mapping-deletes.md @@ -0,0 +1,45 @@ +--- +title: Deletes +id: 4-deletes +--- + +One of the biggest differences between a procedural transformation and how dbt models data is that dbt, in general, will never destroy data. While there are ways to execute hard `DELETE`s in dbt that are outside of the scope of this article, the general best practice for handling deleted data is to just use soft deletes, and filter out soft-deleted data in a final transformation. + +Let’s consider a simple example query: + +```sql +DELETE FROM stg_orders WHERE order_status IS NULL +``` + +In a dbt model, you’ll need to first identify the records that should be deleted and then filter them out. There are really two primary ways you might translate this query: + +```sql +SELECT * FROM {{ ref('stg_orders') }} WHERE order_status IS NOT NULL +``` + +This first approach just inverts the logic of the DELETE to describe the set of records that should remain, instead of the set of records that should be removed. This ties back to the way dbt declaratively describes datasets. You reference the data that should be in a dataset, and the table or view gets created with that set of data. + +Another way you could achieve this is by marking the deleted records, and then filtering them out. For example: + +```sql +WITH + +soft_deletes AS ( + + SELECT + *, + CASE + WHEN order_status IS NULL THEN true + ELSE false + END AS to_delete + + FROM {{ ref('stg_orders') }} + +) + +SELECT * FROM soft_deletes WHERE to_delete = false +``` + +This approach flags all of the deleted records, and the final `SELECT` filters out any deleted data, so the resulting table contains only the remaining records. It’s a lot more verbose than just inverting the `DELETE` logic, but for complex `DELETE` logic, this ends up being a very effective way of performing the `DELETE` that retains historical context. + +It’s worth calling out that while this doesn’t enable a hard delete, hard deletes can be executed a number of ways, the most common being to execute a dbt [macros](https://docs.getdbt.com/docs/building-a-dbt-project/jinja-macros/#macros) via as a [run-operation](https://docs.getdbt.com/reference/commands/run-operation), or by using a [post-hook](https://docs.getdbt.com/reference/resource-configs/pre-hook-post-hook/) to perform a `DELETE` statement after the records to-be-deleted have been marked. These are advanced approaches outside the scope of this guide. diff --git a/website/docs/guides/migration/tools/migrating-from-stored-procedures/5-mapping-merges.md b/website/docs/guides/migration/tools/migrating-from-stored-procedures/5-mapping-merges.md new file mode 100644 index 00000000000..4e773e40875 --- /dev/null +++ b/website/docs/guides/migration/tools/migrating-from-stored-procedures/5-mapping-merges.md @@ -0,0 +1,184 @@ +--- +title: Merges +id: 5-merges +--- + +dbt has a concept called [materialization](/docs/building-a-dbt-project/building-models/materializations), which determines how a model is physically or logically represented in the warehouse. `INSERT`s, `UPDATE`s, and `DELETE`s will typically be accomplished using table or view materializations. For incremental workloads accomplished via commands like `MERGE` or `UPSERT`, dbt has a particular materialization called [incremental](/docs/building-a-dbt-project/building-models/configuring-incremental-models). The incremental materialization is specifically used to handle incremental loads and updates to a table without recreating the entire table from scratch on every run. + +## Step 1: Map the MERGE like an INSERT/UPDATE to start + +Before we get into the exact details of how to implement an incremental materialization, let’s talk about logic conversion. Extracting the logic of the `MERGE` and handling it as you would an `INSERT` or an `UPDATE` is the easiest way to get started migrating a `MERGE` command. . + +To see how the logic conversion works, we’ll start with an example `MERGE`. In this scenario, imagine a ride sharing app where rides are loaded into an details table daily, and tips may be updated at some later date, and need to be kept up-to-date: + +```sql +MERGE INTO ride_details USING ( + SELECT + ride_id, + subtotal, + tip + + FROM rides_to_load AS rtl + + ON ride_details.ride_id = rtl.ride_id + + WHEN MATCHED THEN UPDATE + + SET ride_details.tip = rtl.tip + + WHEN NOT MATCHED THEN INSERT (ride_id, subtotal, tip) + VALUES (rtl.ride_id, rtl.subtotal, NVL(rtl.tip, 0, rtl.tip) +); +``` + +The content of the `USING` clause is a useful piece of code because that can easily be placed in a CTE as a starting point for handling the match statement. I find that the easiest way to break this apart is to treat each match statement as a separate CTE that builds on the previous match statements. + +We can ignore the `ON` clause for now, as that will only come into play once we get to a point where we’re ready to turn this into an incremental. + +As with `UPDATE`s and `INSERT`s, you can use the `SELECT` list and aliases to name columns appropriately for the target table, and `UNION` together `INSERT` statements (taking care to use `UNION`, rather than `UNION ALL` to avoid duplicates). + +The `MERGE` would end up translating to something like this: + +```sql +WITH + +using_clause AS ( + + SELECT + ride_id, + subtotal, + tip + + FROM {{ ref('rides_to_load') }} + +), + +updates AS ( + + SELECT + ride_id, + subtotal, + tip + + FROM using_clause + +), + +inserts AS ( + + SELECT + ride_id, + subtotal, + NVL(rtl.tip, 0, rtl.tip) + + FROM using_clause + +) + +SELECT * + +FROM updates + +UNION inserts +``` + +To be clear, this transformation isn’t complete. The logic here is similar to the `MERGE`, but will not actually do the same thing, since the updates and inserts CTEs are both selecting from the same source query. We’ll need to ensure we grab the separate sets of data as we transition to the incremental materialization. + +One important caveat is that dbt does not natively support `DELETE` as a `MATCH` action. If you have a line in your `MERGE` statement that uses `WHEN MATCHED THEN DELETE`, you’ll want to treat it like an update and add a soft-delete flag, which is then filtered out in a follow-on transformation. + +### Step 2: Convert to incremental materialization + +As mentioned above, incremental materializations are a little special in that when the target table does not exist, the materialization functions in nearly the same way as a standard table materialization, and executes a `CREATE TABLE AS SELECT` statement. If the target table does exist, however, the materialization instead executes a `MERGE` statement. + +Since a `MERGE` requires a `JOIN` condition between the `USING` clause and the target table, we need a way to specify how dbt determines whether or not a record triggers a match or not. That particular piece of information is specified in the dbt model configuration. + +We can add the following `config()` block to the top of our model to specify how it should build incrementally: + +```sql +{{ + config( + materialized='incremental', + unique_key='ride_id', + incremental_strategy='merge' + ) +}} +``` + +The three configuration fields in this example are the most important ones. + +- Setting `materialized='incremental'` tells dbt to apply UPSERT logic to the target table. +- The `unique_key` should be a primary key of the target table. This is used to match records with the existing table. +- `incremental_strategy` here is set to MERGE any existing rows in the target table with a value for the `unique_key` which matches the incoming batch of data. There are [various incremental strategies](docs/building-a-dbt-project/building-models/configuring-incremental-models#about-incremental_strategy) for different situations and warehouses. + +The bulk of the work in converting a model to an incremental materialization comes in determining how the logic should change for incremental loads versus full backfills or initial loads. dbt offers a special macro, `is_incremental()`, which evaluates false for initial loads or for backfills (called full refreshes in dbt parlance), but true for incremental loads. + +This macro can be used to augment the model code to adjust how data is loaded for subsequent loads. How that logic should be added will depend a little bit on how data is received. Some common ways might be: + +1. The source table is truncated ahead of incremental loads, and only contains the data to be loaded in that increment. +2. The source table contains all historical data, and there is a load timestamp column that identifies new data to be loaded. + +In the first case, the work is essentially done already. Since the source table always contains only the new data to be loaded, the query doesn’t have to change for incremental loads. The second case, however, requires the use of the `is_incremental()` macro to correctly handle the logic. + +Taking the converted `MERGE` statement that we’d put together previously, we’d augment it to add this additional logic: + +```sql +WITH + +using_clause AS ( + + SELECT + ride_id, + subtotal, + tip, + max(load_timestamp) as load_timestamp + + FROM {{ ref('rides_to_load') }} + + + {% if is_incremental() %} + + WHERE load_timestamp > (SELECT max(load_timestamp) FROM {{ this }}) + + {% endif %} + +), + +updates AS ( + + SELECT + ride_id, + subtotal, + tip, + load_timestamp + + FROM using_clause + + {% if is_incremental() %} + + WHERE ride_id IN (SELECT ride_id FROM {{ this }}) + + {% endif %} + +), + +inserts AS ( + + SELECT + ride_id, + subtotal, + NVL(tip, 0, tip), + load_timestamp + + FROM using_clause + + WHERE ride_id NOT IN (SELECT ride_id FROM updates) + +) + +SELECT * FROM updates UNION inserts +``` + +There are a couple important concepts to understand here: + +1. The code in the `is_incremental()` conditional block only executes for incremental executions of this model code. If the target table doesn’t exist, or if the `--full-refresh` option is used, that code will not execute. +2. `{{ this }}` is a special keyword in dbt that when used in a Jinja block, self-refers to the model for which the code is executing. So if you have a model in a file called `my_incremental_model.sql`, `{{ this }}` will refer to `my_incremental_model` (fully qualified with database and schema name if necessary). By using that keyword, we can leverage the current state of the target table to inform the source query. diff --git a/website/docs/guides/migration/tools/migrating-from-stored-procedures/6-migrating-from-stored-procedures-conclusion.md b/website/docs/guides/migration/tools/migrating-from-stored-procedures/6-migrating-from-stored-procedures-conclusion.md new file mode 100644 index 00000000000..6fddf15c163 --- /dev/null +++ b/website/docs/guides/migration/tools/migrating-from-stored-procedures/6-migrating-from-stored-procedures-conclusion.md @@ -0,0 +1,6 @@ +--- +title: Putting it all together +id: 6-migrating-from-stored-procedures-conclusion +--- + +The techniques shared above are useful ways to get started converting the individual DML statements that are often found in stored procedures. Using these types of patterns, legacy procedural code can be rapidly transitioned to dbt models that are much more readable, maintainable, and benefit from software engineering best practices like DRY principles. Additionally, once transformations are rewritten as dbt models, it becomes much easier to test the transformations to ensure that the data being used downstream is high-quality and trustworthy. diff --git a/website/docs/guides/migration/versions/05-upgrading-to-v1.3.md b/website/docs/guides/migration/versions/05-upgrading-to-v1.3.md new file mode 100644 index 00000000000..2cf669390c1 --- /dev/null +++ b/website/docs/guides/migration/versions/05-upgrading-to-v1.3.md @@ -0,0 +1,50 @@ +--- +title: "Trying out v1.3 (prerelease)" +--- +### Resources + +- [Changelog](https://github.com/dbt-labs/dbt-core/blob/main/CHANGELOG.md) +- [CLI Installation guide](/dbt-cli/install/overview) +- [Cloud upgrade guide](/docs/dbt-cloud/cloud-configuring-dbt-cloud/cloud-choosing-a-dbt-version) + +## Breaking changes + +There are no breaking changes for code in dbt projects and packages. We are committed to providing backward compatibility for all versions 1.x. If you encounter an error upon upgrading, please let us know by [opening an issue](https://github.com/dbt-labs/dbt-core/issues/new). + +### For users of dbt Metrics + +The names of metric properties have changed, with backward compatibility. Those changes are: +- Renamed `type` to `calculation_method` +- Renamed `sql` to `expression` +- Renamed `expression` calculation method metrics to `derived` calculation method metrics + +We plan to keep backward compatibility for a full minor version. Defining metrics with the old names will raise an error in dbt Core v1.4. + +### For consumers of dbt artifacts (metadata) + +We have updated the manifest schema version to `v7`. This includes the changes to metrics described above and a few other changes related to the addition of Python models: +- Renamed `raw_sql` to `raw_code` +- Renamed `compiled_sql` to `compiled_code` +- A new top-level node property, `language` (`'sql'` or `'python'`) + +For users of [state-based selection](understanding-state): This release includes logic providing backward and forward compatibility for older manifest versions. While running dbt Core v1.3, it should be possible to use `state:modified --state ...` selection against a manifest produced by dbt Core v1.0 and higher. + +### For maintainers of adapter plugins + +_GitHub discussion forthcoming_ + +**Notes:** +- The `statement` and `create_table_as` macros accept a new argument, `language`, with a default value of `'sql'` + +## New and changed documentation + +- **[Python models](building-models/python-models)** are natively supported in `dbt-core` for the first time, on data warehouses that support Python runtimes. +- Updates made to **[Metrics](building-a-dbt-project/metrics)** reflect their new syntax for definition, as well as additional properties that are now available. +- Plus, a few related updates to **[exposure properties](exposure-properties)**: `config`, `label`, and `name` validation. +- **[Custom `node_color`](/docs/reference/resource-configs/docs.md)** in `dbt-docs`. For the first time, you can control the colors displayed in dbt's DAG. Want bronze, silver, and gold layers? It's at your fingertips. +- Search for **[`Profiles.yml`](/docs/dbt-cli/configure-your-profile#advanced-customizing-a-profile-directory)** in the current working directory before `~/.dbt` + +### Quick hits +- **["Full refresh"](full_refresh)** flag supports a short name, `-f`. +- **[The "config" selection method](methods#the-config-method)** supports boolean and list config values, in addition to strings. +- Two new dbt-Jinja context variables for accessing invocation metadata: [`invocation_args_dict`](flags#invocation_args_dict) and [`dbt_metadata_envs`](env_var#custom-metadata). diff --git a/website/docs/guides/migration/versions/06-upgrading-to-v1.2.md b/website/docs/guides/migration/versions/06-upgrading-to-v1.2.md new file mode 100644 index 00000000000..f4ecb1e3e1e --- /dev/null +++ b/website/docs/guides/migration/versions/06-upgrading-to-v1.2.md @@ -0,0 +1,36 @@ +--- +title: "Upgrading to v1.2 (latest)" +--- +### Resources + +- [Changelog](https://github.com/dbt-labs/dbt-core/blob/1.2.latest/CHANGELOG.md) +- [CLI Installation guide](/dbt-cli/install/overview) +- [Cloud upgrade guide](/docs/dbt-cloud/cloud-configuring-dbt-cloud/cloud-choosing-a-dbt-version) + +## Breaking changes + +There are no breaking changes for code in dbt projects and packages. We are committed to providing backwards compatibility for all versions 1.x. If you encounter an error upon upgrading, please let us know by [opening an issue](https://github.com/dbt-labs/dbt-core/issues/new). + +### For consumers of dbt artifacts (metadata) + +The manifest schema version has been updated to `v6`. The relevant changes are: +- Change to `config` default, which includes a new `grants` property with default value `{}` +- Addition of a `metrics` property, to any node which could reference metrics using the `metric()` function + +For users of [state-based selection](understanding-state): This release also includes new logic declaring forwards compatibility for older manifest versions. While running dbt Core v1.2, it should be possible to use `state:modified --state ...` selection against a manifest produced by dbt Core v1.0 or v1.1. + +## For maintainers of adapter plugins + +See GitHub discussion [dbt-labs/dbt-core#5468](https://github.com/dbt-labs/dbt-core/discussions/5468) for detailed information + +## New and changed functionality + +- **[Grants](resource-configs/grants)** are natively supported in `dbt-core` for the first time. That support extends to all standard materializations, and the most popular adapters. If you already use hooks to apply simple grants, we encourage you to use built-in `grants` to configure your models, seeds, and snapshots instead. This will enable you to [DRY](https://en.wikipedia.org/wiki/Don%27t_repeat_yourself) up your duplicated or boilerplate code. +- **[Metrics](building-a-dbt-project/metrics)** now support an `expression` type (metrics-on-metrics), as well as a `metric()` function to use when referencing metrics from within models, macros, or `expression`-type metrics. For more information on how to use expression metrics, check out the [**`dbt_metrics` package**](https://github.com/dbt-labs/dbt_metrics) +- **[dbt-Jinja functions](/reference/dbt-jinja-functions)** now include the [`itertools` Python module](dbt-jinja-functions/modules#itertools), as well as the [set](dbt-jinja-functions/set) and [zip](dbt-jinja-functions/zip) functions. +- **[Node selection](node-selection/syntax)** includes a [file selection method](node-selection/methods#the-file-method) (`-s model.sql`), and [yaml selector](node-selection/yaml-selectors) inheritance. +- **[Global configs](global-configs)** now include CLI flag and environment variable settings for [`target-path`](target-path) and [`log-path`](log-path), which can be used to override the values set in `dbt_project.yml` + +### Specific adapters + +- [Postgres](postgres-profile) and [Redshift](redshift-profile) profiles support a `retries` config, if dbt encounters an operational error or timeout when opening a connection. The default is 1 retry. diff --git a/website/docs/guides/migration/versions/07-upgrading-to-v1.1.md b/website/docs/guides/migration/versions/07-upgrading-to-v1.1.md new file mode 100644 index 00000000000..4ed1844cfdb --- /dev/null +++ b/website/docs/guides/migration/versions/07-upgrading-to-v1.1.md @@ -0,0 +1,64 @@ +--- +title: "Upgrading to v1.1" +--- +### Resources + +- [Changelog](https://github.com/dbt-labs/dbt-core/blob/1.1.latest/CHANGELOG.md) +- [CLI Installation guide](/dbt-cli/install/overview) +- [Cloud upgrade guide](/docs/dbt-cloud/cloud-configuring-dbt-cloud/cloud-choosing-a-dbt-version) + +## Breaking changes + +There are no breaking changes for code in dbt projects and packages. We are committed to providing backwards compatibility for all versions 1.x. If you encounter an error upon upgrading, please let us know by [opening an issue](https://github.com/dbt-labs/dbt-core/issues/new). + +### For maintainers of adapter plugins + +We have reworked the testing suite for adapter plugin functionality. For details on the new testing suite, see: ["Testing a new adapter"](testing-a-new-adapter) + +The abstract methods `get_response` and `execute` now only return `connection.AdapterReponse` in type hints. Previously, they could return a string. We encourage you to update your methods to return an object of class `AdapterResponse`, or implement a subclass specific to your adapter. This also gives you the opportunity to add fields specific to your adapter's query execution, such as `rows_affected` or `bytes_processed`. + +### For consumers of dbt artifacts (metadata) + +The manifest schema version will be updated to v5. The only change is to the default value of `config` for parsed nodes. + +For users of [state-based functionality](understanding-state), such as the `state:modified` selector, recall that: + +> The `--state` artifacts must be of schema versions that are compatible with the currently running dbt version. + +If you have two jobs, whereby one job compares or defers to artifacts produced by the other, you'll need to upgrade both at the same time. If there's a mismatch, dbt will alert you with this error message: + +``` +Expected a schema version of "https://schemas.getdbt.com/dbt/manifest/v5.json" in /manifest.json, but found "https://schemas.getdbt.com/dbt/manifest/v4.json". Are you running with a different version of dbt? +``` + +## New and changed documentation + +[**Incremental models**](configuring-incremental-models) can now accept a list of multiple columns as their `unique_key`, for models that need a combination of columns to uniquely identify each row. This is supported by the most common data warehouses, for incremental strategies that make use of the `unique_key` config (`merge` and `delete+insert`). + +[**Generic tests**](resource-properties/tests) can define custom names. This is useful to "prettify" the synthetic name that dbt applies automatically. It's needed to disambiguate the case when the same generic test is defined multiple times with different configurations. + +[**Sources**](source-properties) can define configuration inline with other `.yml` properties, just like other resource types. The only supported config is `enabled`; you can use this to dynamically enable/disable sources based on environment or package variables. + +### Advanced and experimental functionality + +**Fresh Rebuilds.** There's a new _experimental_ selection method in town: [`source_status:fresher`](node-selection/methods#the-source_status-method). Much like the `state:` and `result` methods, the goal is to use dbt metadata to run your DAG more efficiently. If dbt has access to previous and current results of `dbt source freshness` (the `sources.json` artifact), dbt can compare them to determine which sources have loaded new data, and select only resources downstream of "fresher" sources. Read more in ["Understanding State"](understanding-state) and ["CI/CD in dbt Cloud"](cloud-enabling-continuous-integration-with-github). + + +[**dbt-Jinja functions**](/reference/dbt-jinja-functions) have a new landing page, and two new members: +- [`print`](/reference/dbt-jinja-functions/print) exposes the Python `print()` function. It can be used as an alternative to `log()`, and together with the `QUIET` config, for advanced macro-driven workflows. +- [`selected_resources`](/reference/dbt-jinja-functions/selected_resources) exposes, at runtime, the list of DAG nodes selected by the current task. + +[**Global configs**](global-configs) include some new additions: + +- `QUIET` and `NO_PRINT`, to control which log messages dbt prints to terminal output. For use in advanced macro-driven workflows, such as [codegen](https://hub.getdbt.com/dbt-labs/codegen/latest/). +- `CACHE_SELECTED_ONLY` is an _experimental_ config that can significantly speed up dbt's start-of-run preparations, in cases where you're running only a few models from a large project that manages many schemas. + +### For users of specific adapters + +**dbt-bigquery** added Support for finer-grained configuration of query timeout and retry when defining your [connection profile](bigquery-profile). + +**dbt-spark** added support for a [`session` connection method](spark-profile#session), for use with a pySpark session, to support rapid iteration when developing advanced or experimental functionality. This connection method is not recommended for new users, and it is not supported in dbt Cloud. + +### Dependencies + +[Python compatibility](install-python-compatibility): dbt Core officially supports Python 3.10 diff --git a/website/docs/docs/guides/migration-guide/upgrading-to-1-0-0.md b/website/docs/guides/migration/versions/08-upgrading-to-v1.0.md similarity index 95% rename from website/docs/docs/guides/migration-guide/upgrading-to-1-0-0.md rename to website/docs/guides/migration/versions/08-upgrading-to-v1.0.md index 0d91c23f54c..c7d94354fa2 100644 --- a/website/docs/docs/guides/migration-guide/upgrading-to-1-0-0.md +++ b/website/docs/guides/migration/versions/08-upgrading-to-v1.0.md @@ -1,12 +1,12 @@ --- -title: "Upgrading to 1.0.0" - +title: "Upgrading to v1.0" --- - ### Resources - [Discourse](https://discourse.getdbt.com/t/3180) - [Changelog](https://github.com/dbt-labs/dbt-core/blob/1.0.latest/CHANGELOG.md) +- [CLI Installation guide](/dbt-cli/install/overview) +- [Cloud upgrade guide](/docs/dbt-cloud/cloud-configuring-dbt-cloud/cloud-choosing-a-dbt-version) ## Breaking changes @@ -67,5 +67,5 @@ Several under-the-hood changes from past minor versions, tagged with deprecation - [Parsing](parsing): partial parsing and static parsing have been turned on by default. - [Global configs](global-configs) have been standardized. Related updates to [global CLI flags](global-cli-flags) and [`profiles.yml`](profiles.yml). - [The `init` command](init) has a whole new look and feel. It's no longer just for first-time users. -- Add `result:` subselectors for smarter reruns when dbt models have errors and tests fail. See examples: [Pro-tips for Workflows](/docs/guides/best-practices.md#pro-tips-for-workflows) +- Add `result:` subselectors for smarter reruns when dbt models have errors and tests fail. See examples: [Pro-tips for Workflows](/guides/legacy/best-practices#pro-tips-for-workflows) - Secret-prefixed [env vars](env_var) are now allowed only in `profiles.yml` + `packages.yml` diff --git a/website/docs/docs/guides/migration-guide/upgrading-to-0-21-0.md b/website/docs/guides/migration/versions/09-upgrading-to-v0.21.md similarity index 74% rename from website/docs/docs/guides/migration-guide/upgrading-to-0-21-0.md rename to website/docs/guides/migration/versions/09-upgrading-to-v0.21.md index eea1dd56915..1d1ed61d949 100644 --- a/website/docs/docs/guides/migration-guide/upgrading-to-0-21-0.md +++ b/website/docs/guides/migration/versions/09-upgrading-to-v0.21.md @@ -1,18 +1,22 @@ --- -title: "Upgrading to 0.21.0" +title: "Upgrading to v0.21" --- +:::caution Unsupported version +dbt Core v0.21 has reached the end of critical support. No new patch versions will be released, and it will stop running in dbt Cloud on June 30, 2022. Read ["About dbt Core versions"](core-versions) for more details. +::: + ### Resources - [Discourse](https://discourse.getdbt.com/t/3077) - [Release notes](https://github.com/dbt-labs/dbt-core/releases/tag/v0.21.0) -- [Full changelog](https://github.com/fishtown-analytics/dbt/blob/0.21.latest/CHANGELOG.md) +- [Full changelog](https://github.com/dbt-labs/dbt-core/blob/0.21.latest/CHANGELOG.md) ## Breaking changes - `dbt source snapshot-freshness` has been renamed to `dbt source freshness`. Its node selection logic is now consistent with other tasks. In order to check freshness for a specific source, you must prefix it with `source:`. -- **Snowflake:** Turn off transactions and turn on autocommit by default. Explicitly specify `begin` and `commit` for DML statements in incremental and snapshot materializations. Note that this may affect user-space code that depends on transactions. +- **Snowflake:** Turn off transactions and turn on `autocommit` by default. Within dbt materializations, wrap [DML statements](https://stackoverflow.com/a/44796508) in explicit `begin` and `commit`. Note that it is not recommended to run statements outside of dbt logic. If you do this, despite our recommendation, you will need to wrap those statements in explicit `begin` and `commit`. Note also that this may affect user-space code that depends on transactions, such as pre-hooks and post-hooks that specify `transaction: true` or `transaction: false`. We recommend removing those references to transactions. - **Artifacts:** - [`manifest.json`](manifest-json) uses a `v3` schema that includes additional node properties (no changes to existing properties) - [`run_results.json`](run-results-json) uses a `v3` schema that has added `skipped` as a potential `TestResult` @@ -42,5 +46,5 @@ title: "Upgrading to 0.21.0" ### Plugins - **Postgres** [profile](postgres-profile) property `connect_timeout` now configurable. Also applicable to child plugins (e.g. `dbt-redshift`) -- **Redshift**: [profile](redshift-profile) property `ra3: true` to support cross-database source definitions and read-only querying +- **Redshift**: [profile](redshift-profile) property `ra3_node: true` to support cross-database source definitions and read-only querying - **BigQuery**: [profile](bigquery-profile) property `execution_project` now configurable. [Snapshots](snapshots) support `target_project` and `target_dataset` config aliases. diff --git a/website/docs/docs/guides/migration-guide/upgrading-to-0-20-0.md b/website/docs/guides/migration/versions/10-upgrading-to-v0.20.md similarity index 88% rename from website/docs/docs/guides/migration-guide/upgrading-to-0-20-0.md rename to website/docs/guides/migration/versions/10-upgrading-to-v0.20.md index 9d7ca2b883b..6dcd5c0fa47 100644 --- a/website/docs/docs/guides/migration-guide/upgrading-to-0-20-0.md +++ b/website/docs/guides/migration/versions/10-upgrading-to-v0.20.md @@ -1,13 +1,17 @@ --- -title: "Upgrading to 0.20.0" +title: "Upgrading to v0.20" --- +:::caution Unsupported version +dbt Core v0.20 has reached the end of critical support. No new patch versions will be released, and it will stop running in dbt Cloud on June 30, 2022. Read ["About dbt Core versions"](core-versions) for more details. +::: + ### Resources - [Discourse](https://discourse.getdbt.com/t/2621) - [Release notes](https://github.com/dbt-labs/dbt-core/releases/tag/v0.20.0) -- [Full changelog](https://github.com/fishtown-analytics/dbt/blob/0.20.latest/CHANGELOG.md) +- [Full changelog](https://github.com/dbt-labs/dbt-core/blob/0.20.latest/CHANGELOG.md) ## Breaking changes diff --git a/website/docs/docs/guides/migration-guide/upgrading-to-0-11-0.md b/website/docs/guides/migration/versions/11-Older versions/upgrading-to-0-11-0.md similarity index 100% rename from website/docs/docs/guides/migration-guide/upgrading-to-0-11-0.md rename to website/docs/guides/migration/versions/11-Older versions/upgrading-to-0-11-0.md diff --git a/website/docs/docs/guides/migration-guide/upgrading-to-0-12-0.md b/website/docs/guides/migration/versions/11-Older versions/upgrading-to-0-12-0.md similarity index 100% rename from website/docs/docs/guides/migration-guide/upgrading-to-0-12-0.md rename to website/docs/guides/migration/versions/11-Older versions/upgrading-to-0-12-0.md diff --git a/website/docs/docs/guides/migration-guide/upgrading-to-0-13-0.md b/website/docs/guides/migration/versions/11-Older versions/upgrading-to-0-13-0.md similarity index 85% rename from website/docs/docs/guides/migration-guide/upgrading-to-0-13-0.md rename to website/docs/guides/migration/versions/11-Older versions/upgrading-to-0-13-0.md index 0d67a6ce103..7834c330b5c 100644 --- a/website/docs/docs/guides/migration-guide/upgrading-to-0-13-0.md +++ b/website/docs/guides/migration/versions/11-Older versions/upgrading-to-0-13-0.md @@ -13,7 +13,7 @@ Use a variable from the [`{{ target }}` context](target) or [`on-run-end` contex ### Adapter methods -A number of materialization-specific adapter methods have changed in breaking ways. If you use these adapter methods in your macros or materializations, you may need to update your code accordingly. +A number of materialization-specific adapter methods have changed in breaking ways. If you use these adapter methods in your macros or materializations, you may need to update your code accordingly. - query_for_existing - **removed**, use [get_relation](adapter#get_relation) instead. - [get_missing_columns](adapter#get_missing_columns) - changed to take `Relation`s instead of schemas and identifiers - [expand_target_column_types](adapter#expand_target_column_types) - changed to take a `Relation` instead of schema, identifier @@ -25,4 +25,4 @@ A number of materialization-specific adapter methods have changed in breaking wa Version 1 schema.yml specs (deprecated in 0.11.0) are no longer supported. Please use the version 2 spec instead. -See the [0.11.0 migration guide](upgrading-to-0-11-0#schemayml-v2-syntax) for details. +See the [0.11.0 migration guide](upgrading-to-0-11-0.md#schemayml-v2-syntax) for details. diff --git a/website/docs/docs/guides/migration-guide/upgrading-to-0-14-0.md b/website/docs/guides/migration/versions/11-Older versions/upgrading-to-0-14-0.md similarity index 90% rename from website/docs/docs/guides/migration-guide/upgrading-to-0-14-0.md rename to website/docs/guides/migration/versions/11-Older versions/upgrading-to-0-14-0.md index 4caa2d06dde..8a1a5faa458 100644 --- a/website/docs/docs/guides/migration-guide/upgrading-to-0-14-0.md +++ b/website/docs/guides/migration/versions/11-Older versions/upgrading-to-0-14-0.md @@ -19,7 +19,7 @@ There are a handful of changes to be aware of as you migrate from archives to sn - snapshots are specified in .sql files, whereas archives were specified in the `dbt_project.yml` file ### Snapshot column name changes -This table shows the differences between the column names produced by `dbt archive` and `dbt snapshot`. **Note:** These new snapshot meta-column names are _unquoted_. If you're using Snowflake, this means that your snapshot column names will be rendered in upper-case, rather than lower-case. +This shows the differences between the column names produced by `dbt archive` and `dbt snapshot`. **Note:** These new snapshot meta-column names are _unquoted_. If you're using Snowflake, this means that your snapshot column names will be rendered in upper-case, rather than lower-case. | Archive Column (quoted) | Snapshot Column (unquoted) | | ----------------------- | -------------------------- | @@ -45,7 +45,7 @@ The provided migration script should be run _once_ by a single dbt user. This da :::caution Custom Materializations -This guide assumes that you are using the built-in archive materialization. If you are using a custom archive materialization, see the section on "Migrating archives manually" below. +This guide assumes that you are using the built-in archive . If you are using a custom archive materialization, see the section on "Migrating archives manually" below. ::: @@ -145,7 +145,7 @@ To upgrade this macro (and suppress this warning), add a second argument, `node` ## Non-Destructive runs -The `--non-destructive` flag was removed from dbt in v0.14.0. This flag existed as a workaround for the lack of late-binding views in Amazon Redshift. With the introduction of the [with no schema binding](https://docs.aws.amazon.com/redshift/latest/dg/r_CREATE_VIEW.html) clause for Redshift views, non-destructive runs are no longer necessary. +The `--non-destructive` flag was removed from dbt in v0.14.0. This flag existed as a workaround for the lack of late-binding views in Amazon Redshift. With the introduction of the [with no schema binding](https://docs.aws.amazon.com/redshift/latest/dg/r_CREATE_VIEW.html) clause for Redshift views, non-destructive runs are no longer necessary. The `--non-destructive` flag was problematic for a few reasons: @@ -162,7 +162,7 @@ Postgres users should ensure that they use table or incremental models for relat ## Snowflake Incremental Model Changes -In dbt v0.14.0, the implementation of `incremental` models on Snowflake has changed. By default, dbt will use a [merge](https://docs.snowflake.net/manuals/sql-reference/sql/merge.html) statement to atomically upsert records into a table incrementally. Previous versions of dbt used a two-step `delete+insert` approach to upsert data. +In dbt v0.14.0, the implementation of `incremental` models on Snowflake has changed. By default, dbt will use a [merge](https://docs.snowflake.net/manuals/sql-reference/sql/merge.html) statement to atomically upsert records into a incrementally. Previous versions of dbt used a two-step `delete+insert` approach to upsert data. The `merge` statement requires that records participating in the upsert are unique. If these records are not unique, then the statement will fail with a "nondeterministic merge" error. If you see this error after upgrading to 0.14.0, you can resolve it in one of two ways: diff --git a/website/docs/docs/guides/migration-guide/upgrading-to-0-14-1.md b/website/docs/guides/migration/versions/11-Older versions/upgrading-to-0-14-1.md similarity index 91% rename from website/docs/docs/guides/migration-guide/upgrading-to-0-14-1.md rename to website/docs/guides/migration/versions/11-Older versions/upgrading-to-0-14-1.md index a40da7e9839..a411b079292 100644 --- a/website/docs/docs/guides/migration-guide/upgrading-to-0-14-1.md +++ b/website/docs/guides/migration/versions/11-Older versions/upgrading-to-0-14-1.md @@ -15,11 +15,11 @@ The following section only applies to Snapshots running against Snowflake or Big When a [Snapshot](snapshots) is configured to use the `check` strategy, dbt will compare the specified `check_cols` between the source dataset and the snapshotted dataset to determine if a row in the Snapshot has changed. A logic error in the v0.14.0 release of dbt caused this strategy to fail if the values of the specified `check_cols` for a given row cycled back into a previously known state. Importantly, this issue only affects Snowflake and BigQuery due to their respective uses of the `merge` statement in Snapshots. -In this failure mode, dbt would "finalize" existing records by setting a `dbt_valid_to` date for a changed record without correspondingly inserting a new record for the change. **In this state, the finalized records will no longer be tracked in the Snapshot table**. +In this failure mode, dbt would "finalize" existing records by setting a `dbt_valid_to` date for a changed record without correspondingly inserting a new record for the change. **In this state, the finalized records will no longer be tracked in the Snapshot **. ### Resolution -To determine if your Snapshot table is affected by this issue, you can run a query to find "stuck" records. These "stuck" records: +To determine if your Snapshot is affected by this issue, you can run a query to find "stuck" records. These "stuck" records: - Are the most recent records for a given `unique_key` in the snapshot - Have a value for both `dbt_valid_from` and `dbt_valid_to` @@ -79,7 +79,7 @@ This migration is only required for users of the `check` snapshot strategy on Sn ::: -The query shown above will generate a set of rows which are in a "stuck" state. You can use the output of this query to update the records in your snapshot table to become "unstuck". To do this, use an `update` statement that sets the `dbt_valid_to` column to `null` for records identified in the query above. **Use caution when running DML directly against a snapshot table. It is a good idea to make a backup of this table before applying running this migration manually!** A sample query has been provided below: please test this query _thoroughly_ before running it in production. +The query shown above will generate a set of rows which are in a "stuck" state. You can use the output of this query to update the records in your snapshot table to become "unstuck". To do this, use an `update` statement that sets the `dbt_valid_to` column to `null` for records identified in the query above. **Use caution when running directly against a snapshot table. It is a good idea to make a backup of this table before applying running this migration manually!** A sample query has been provided below: please test this query _thoroughly_ before running it in production. diff --git a/website/docs/docs/guides/migration-guide/upgrading-to-0-15-0.md b/website/docs/guides/migration/versions/11-Older versions/upgrading-to-0-15-0.md similarity index 89% rename from website/docs/docs/guides/migration-guide/upgrading-to-0-15-0.md rename to website/docs/guides/migration/versions/11-Older versions/upgrading-to-0-15-0.md index d309740802c..ca54e6c8abb 100644 --- a/website/docs/docs/guides/migration-guide/upgrading-to-0-15-0.md +++ b/website/docs/guides/migration/versions/11-Older versions/upgrading-to-0-15-0.md @@ -20,7 +20,7 @@ expect this field will now return errors. See the latest ### Custom materializations -All materializations must now [manage dbt's Relation cache](creating-new-materializations#update-the-relation-cache). +All materializations must now [manage dbt's Relation cache](creating-new-materializations#update-the-relation-cache). ### dbt Server diff --git a/website/docs/docs/guides/migration-guide/upgrading-to-0-16-0.md b/website/docs/guides/migration/versions/11-Older versions/upgrading-to-0-16-0.md similarity index 98% rename from website/docs/docs/guides/migration-guide/upgrading-to-0-16-0.md rename to website/docs/guides/migration/versions/11-Older versions/upgrading-to-0-16-0.md index 4eef260bd2c..9590eca0379 100644 --- a/website/docs/docs/guides/migration-guide/upgrading-to-0-16-0.md +++ b/website/docs/guides/migration/versions/11-Older versions/upgrading-to-0-16-0.md @@ -35,7 +35,7 @@ for an example of how to use the two-argument variant of `generate_schema_name`. The `partition_by` config for BigQuery models now accepts a dictionary containing the following keys: -- `field`: The field name in the table to partition by +- `field`: The field name in the to partition by - `data_type`: The data type for the partitioning field (`date`, `timestamp`, `datetime`, `int64`) - `range`: Only required if the `data_type` is `int64` (for range bucket partitioning) diff --git a/website/docs/docs/guides/migration-guide/upgrading-to-0-17-0.md b/website/docs/guides/migration/versions/11-Older versions/upgrading-to-0-17-0.md similarity index 93% rename from website/docs/docs/guides/migration-guide/upgrading-to-0-17-0.md rename to website/docs/guides/migration/versions/11-Older versions/upgrading-to-0-17-0.md index fedf3362bdc..9075a974571 100644 --- a/website/docs/docs/guides/migration-guide/upgrading-to-0-17-0.md +++ b/website/docs/guides/migration/versions/11-Older versions/upgrading-to-0-17-0.md @@ -196,7 +196,7 @@ models: ### Accessing sources in the `graph` object -In previous versions of dbt, the `sources` in a dbt project could be accessed in the compilation context using the [graph.nodes](dbt-jinja-functions/graph) context variable. In dbt v0.17.0, these sources have been moved out of the `graph.nodes` dictionary and into a new `graph.sources` dictionary. This change is also reflected in the `manifest.json` artifact produced by dbt. If you are accessing these sources programmatically, please update any references from `graph.nodes` to `graph.sources` instead. +In previous versions of dbt, the `sources` in a dbt project could be accessed in the compilation context using the [graph.nodes](/reference/dbt-jinja-functions/graph) context variable. In dbt v0.17.0, these sources have been moved out of the `graph.nodes` dictionary and into a new `graph.sources` dictionary. This change is also reflected in the `manifest.json` artifact produced by dbt. If you are accessing these sources programmatically, please update any references from `graph.nodes` to `graph.sources` instead. ### BigQuery `locations` removed from Catalog @@ -248,8 +248,8 @@ BigQuery: **Core** - [`path:` selectors](node-selection/methods#the-path-method) - [`--fail-fast`](commands/run#failing-fast) -- [as_text Jinja filter](dbt-jinja-functions/as_text) -- [accessing nodes in the `graph` object](dbt-jinja-functions/graph) +- [as_text Jinja filter](/reference/dbt-jinja-functions/as_text) +- [accessing nodes in the `graph` object](/reference/dbt-jinja-functions/graph) - [persist_docs](resource-configs/persist_docs) - [source properties](reference/source-properties) - [source overrides](resource-properties/overrides) diff --git a/website/docs/docs/guides/migration-guide/upgrading-to-0-18-0.md b/website/docs/guides/migration/versions/11-Older versions/upgrading-to-0-18-0.md similarity index 93% rename from website/docs/docs/guides/migration-guide/upgrading-to-0-18-0.md rename to website/docs/guides/migration/versions/11-Older versions/upgrading-to-0-18-0.md index 955ccf6d911..efdc2162a7e 100644 --- a/website/docs/docs/guides/migration-guide/upgrading-to-0-18-0.md +++ b/website/docs/guides/migration/versions/11-Older versions/upgrading-to-0-18-0.md @@ -19,7 +19,7 @@ Please be aware of the following changes in v0.18.0. While breaking, we do not e ### Data tests -- Data tests are written as CTEs instead of subqueries. Adapter plugins for databases that don't support CTEs may need to override this behavior. +- Data tests are written as CTEs instead of subqueries. Adapter plugins for databases that don't support CTEs may need to override this behavior. ### Python requirements - Upgraded `snowflake-connector-python` dependency to 2.2.10 and enabled the SSO token cache diff --git a/website/docs/docs/guides/migration-guide/upgrading-to-0-19-0.md b/website/docs/guides/migration/versions/11-Older versions/upgrading-to-0-19-0.md similarity index 93% rename from website/docs/docs/guides/migration-guide/upgrading-to-0-19-0.md rename to website/docs/guides/migration/versions/11-Older versions/upgrading-to-0-19-0.md index 0473e309d86..dee59fa7815 100644 --- a/website/docs/docs/guides/migration-guide/upgrading-to-0-19-0.md +++ b/website/docs/guides/migration/versions/11-Older versions/upgrading-to-0-19-0.md @@ -7,7 +7,7 @@ title: "Upgrading to 0.19.0" - [Discourse](https://discourse.getdbt.com/t/1951) - [Release notes](https://github.com/dbt-labs/dbt-core/releases/tag/v0.19.0) -- [Full changelog](https://github.com/fishtown-analytics/dbt/blob/0.19.latest/CHANGELOG.md) +- [Full changelog](https://github.com/dbt-labs/dbt-core/blob/0.19.latest/CHANGELOG.md) ## Breaking changes @@ -23,7 +23,7 @@ See the docs below for more details. We don't expect these to require action in #### Deprecations -Removed support for `config-version: 1` of dbt_project.yml, which was deprecated in v0.17.0. Use `config-version: 2` in all projects and installed packages. Otherwise, dbt will raise an error. See docs on [config-version](config-version) and the [v0.17.0 Migration Guide](upgrading-to-0-17-0) for details. +Removed support for `config-version: 1` of dbt_project.yml, which was deprecated in v0.17.0. Use `config-version: 2` in all projects and installed packages. Otherwise, dbt will raise an error. See docs on [config-version](config-version) and the [v0.17.0 Migration Guide](/guides/migration/versions) for details. ### For dbt plugin maintainers @@ -42,7 +42,7 @@ See [dbt#2961](https://github.com/dbt-labs/dbt-core/pull/2961) for full implemen ## New and changed documentation ### Core -- [dbt Artifacts](dbt-artifacts): The JSON artifacts produced by dbt—manifest, catalog, run results, and sources—are simpler to consume and more clearly documented. +- [dbt Artifacts](dbt-artifacts): The artifacts produced by dbt—manifest, catalog, run results, and sources—are simpler to consume and more clearly documented. - [dbt Classes](dbt-classes#result-objects), [on-run-end Context](on-run-end-context#results): The `Result` object has a new schema, in line with changes to `run_results.json`. - [Statement blocks](statement-blocks): The `call statement` result `status` string is now a structured object named `response`. - [Snapshots](snapshots#invalidate_hard_deletes): If the config `invalidate_hard_deletes` is enabled, `dbt snapshot` will update records whose unique key no longer exist in the snapshot query. Should those uniquely identified records "revive," `dbt snapshot` will re-add them. diff --git a/website/docs/guides/orchestration/airflow-and-dbt-cloud/1-airflow-and-dbt-cloud.md b/website/docs/guides/orchestration/airflow-and-dbt-cloud/1-airflow-and-dbt-cloud.md new file mode 100644 index 00000000000..ee9650fae7d --- /dev/null +++ b/website/docs/guides/orchestration/airflow-and-dbt-cloud/1-airflow-and-dbt-cloud.md @@ -0,0 +1,55 @@ +--- +title: Airflow and dbt Cloud +id: 1-airflow-and-dbt-cloud +--- + +In some cases, [Airflow](https://airflow.apache.org/) may be the preferred orchestrator for your organization over working fully within dbt Cloud. There are a few reasons your team might be considering using Airflow to orchestrate your dbt jobs: + +- Your team is already using Airflow to orchestrate other processes +- Your team needs to ensure that a [dbt job](https://docs.getdbt.com/docs/dbt-cloud/cloud-overview#schedule-and-run-dbt-jobs-in-production) kicks off before or after another process outside of dbt Cloud +- Your team needs flexibility to manage more complex scheduling, such as kicking off one dbt job only after another has completed +- Your team wants to own their own orchestration solution +- You need code to work right now without starting from scratch + +## How are people using Airflow + dbt today? + +### Airflow + dbt Core + +There are so many great examples from Gitlab through their open source data engineering work. Example: [here](https://gitlab.com/gitlab-data/analytics/-/blob/master/dags/transformation/dbt_snowplow_backfill.py). This is especially appropriate if you are well-versed in Kubernetes, CI/CD, and docker task management when building your airflow pipelines. If this is you and your team, you’re in good hands reading through more details: [here](https://about.gitlab.com/handbook/business-technology/data-team/platform/infrastructure/#airflow) and [here](https://about.gitlab.com/handbook/business-technology/data-team/platform/dbt-guide/) + +### Airflow + dbt Cloud API w/Custom Scripts + +This has served as a bridge until the fabled Astronomer + dbt Labs-built dbt Cloud provider became generally available: [here](https://registry.astronomer.io/providers/dbt-cloud?type=Sensors&utm_campaign=Monthly%20Product%20Updates&utm_medium=email&_hsmi=208603877&utm_content=208603877&utm_source=hs_email) + +There are many different permutations of this over time: + +- [Custom Python Scripts](https://github.com/sungchun12/airflow-dbt-cloud/blob/main/archive/dbt_cloud_example.py): This is an airflow DAG based on custom python API utilities [here](https://github.com/sungchun12/airflow-dbt-cloud/blob/main/archive/dbt_cloud_utils.py) +- [Make API requests directly through the BashOperator based on the docs](https://docs.getdbt.com/dbt-cloud/api-v2#operation/triggerRun): You can make cURL requests to invoke dbt Cloud to do what you want +- [Other ways to run dbt in airflow](https://docs.getdbt.com/docs/running-a-dbt-project/running-dbt-in-production/#using-airflow): Official dbt Docs on how teams are running dbt in airflow + +## This guide's process + +These solutions are great, but can be difficult to trust as your team grows and management for things like: testing, job definitions, secrets, and pipelines increase past your team’s capacity. Roles become blurry (or were never clearly defined at the start!). Both data and analytics engineers start digging through custom logging within each other’s workflows to make heads or tails of where and what the issue really is. Not to mention that when the issue is found, it can be even harder to decide on the best path forward for safely implementing fixes. This complex workflow and unclear delineation on process management results in a lot of misunderstandings and wasted time just trying to get the process to work smoothly! + +### A better way + +After today’s walkthrough, you’ll get hands-on experience: + +1. Creating a working local Airflow environment +2. Invoking a dbt Cloud job with Airflow (with proof!) +3. Reusing tested and trusted Airflow code for your specific use cases + +While you’re learning the ropes, you’ll also gain a better understanding of how this helps to: + +- Reduce the cognitive load when building and maintaining pipelines +- Avoid dependency hell (think: `pip install` conflicts) +- Implement better recoveries from failures +- Define clearer workflows so that data and analytics engineers work better, together ♥️ + +### Prerequisites + +- [dbt Cloud Teams or Enterprise account](https://www.getdbt.com/pricing/) (with [admin access](https://docs.getdbt.com/docs/dbt-cloud/access-control/enterprise-permissions)) in order to create a service token. Permissions for service tokens can be found [here](https://docs.getdbt.com/docs/dbt-cloud/dbt-cloud-api/service-tokens#permissions-for-service-account-tokens). +- A [free Docker account](https://hub.docker.com/signup) in order to sign in to Docker Desktop, which will be installed in the initial setup. +- A local digital scratchpad for temporarily copy-pasting API keys and URLs + +🙌 Let’s get started! 🙌 diff --git a/website/docs/guides/orchestration/airflow-and-dbt-cloud/2-setting-up-airflow-and-dbt-cloud.md b/website/docs/guides/orchestration/airflow-and-dbt-cloud/2-setting-up-airflow-and-dbt-cloud.md new file mode 100644 index 00000000000..cb5895e80f4 --- /dev/null +++ b/website/docs/guides/orchestration/airflow-and-dbt-cloud/2-setting-up-airflow-and-dbt-cloud.md @@ -0,0 +1,87 @@ +--- +title: Setting up Airflow and dbt Cloud +id: 2-setting-up-airflow-and-dbt-cloud +--- + +## 1. Install the Astro CLI + +Astro is a managed software service that includes key features for teams working with Airflow. In order to use Astro, we’ll install the Astro CLI, which will give us access to useful commands for working with Airflow locally. You can read more about Astro [here](https://docs.astronomer.io/astro/). + +In this example, we’re using Homebrew to install Astro CLI. Follow the instructions to install the Astro CLI for your own operating system [here](https://docs.astronomer.io/astro/install-cli). + +```bash +brew install astronomer/cloud/astrocloud +``` + + + +## 2. Install and start Docker Desktop + +Docker allows us to spin up an environment with all the apps and dependencies we need for the example. + +Follow the instructions [here](https://docs.docker.com/desktop/) to install Docker desktop for your own operating system. Once Docker is installed, ensure you have it up and running for the next steps. + + + +## 3. Clone the airflow-dbt-cloud repository + +Open your terminal and clone the [airflow-dbt-cloud repository](https://github.com/sungchun12/airflow-dbt-cloud.git). This contains example Airflow DAGs that you’ll use to orchestrate your dbt Cloud job. Once cloned, navigate into the `airflow-dbt-cloud` project. + +```bash +git clone https://github.com/sungchun12/airflow-dbt-cloud.git +cd airflow-dbt-cloud +``` + + + +## 4. Start the Docker container + +1. Run the following command to spin up the Docker container and start your local Airflow deployment: + + ```bash + astrocloud dev start + ``` + + When this finishes, you should see a message similar to the following: + + ```bash + Airflow is starting up! This might take a few minutes… + + Project is running! All components are now available. + + Airflow Webserver: http://localhost:8080 + Postgres Database: localhost:5432/postgres + The default Airflow UI credentials are: admin:admin + The default Postrgres DB credentials are: postgres:postgres + ``` + +2. Open the Airflow interface. Launch your web browser and navigate to the address for the **Airflow Webserver** from your output in Step 1. + + This will take you to your local instance of Airflow. You’ll need to log in with the **default credentials**: + + - Username: admin + - Password: admin + + ![Airflow login screen](/img/guides/orchestration/airflow-and-dbt-cloud/airflow-login.png) + + + +## 5. Create a dbt Cloud service token + +Create a service token from within dbt Cloud using the instructions [found here](https://docs.getdbt.com/docs/dbt-cloud/dbt-cloud-api/service-tokens). Ensure that you save a copy of the token, as you won’t be able to access this later. In this example we use `Account Admin`, but you can also use `Job Admin` instead for token permissions. + + + +## 6. Create a dbt Cloud job + +In your dbt Cloud account create a job, paying special attention to the information in the bullets below. Additional information for creating a dbt Cloud job can be found [here](https://docs.getdbt.com/docs/dbt-cloud/cloud-quickstart/#create-a-new-job). + +- Configure the job with the commands that you want to include when this job kicks off, as Airflow will be referring to the job’s configurations for this rather than being explicitly coded in the Airflow DAG. This job will run a set of commands rather than a single command. +- Ensure that the schedule is turned **off** since we’ll be using Airflow to kick things off. +- Once you hit `save` on the job, make sure you copy the URL and save it for referencing later. The url will look similar to this: + +```html +https://cloud.getdbt.com/#/accounts/{account_id}/projects/{project_id}/jobs/{job_id}/ +``` + + diff --git a/website/docs/guides/orchestration/airflow-and-dbt-cloud/3-running-airflow-and-dbt-cloud.md b/website/docs/guides/orchestration/airflow-and-dbt-cloud/3-running-airflow-and-dbt-cloud.md new file mode 100644 index 00000000000..d6fd32bdba9 --- /dev/null +++ b/website/docs/guides/orchestration/airflow-and-dbt-cloud/3-running-airflow-and-dbt-cloud.md @@ -0,0 +1,104 @@ +--- +title: Running Airflow and dbt Cloud +id: 3-running-airflow-and-dbt-cloud +--- + + + +Now you have all the working pieces to get up and running with Airflow + dbt Cloud. Let’s dive into make this all work together. We will **set up a connection** and **run a DAG in Airflow** that kicks off a dbt Cloud job. + +## 1. Add your dbt Cloud API token as a secure connection + +1. Navigate to Admin and click on **Connections** + + ![Airflow connections menu](/img/guides/orchestration/airflow-and-dbt-cloud/airflow-connections-menu.png) + +2. Click on the `+` sign to add a new connection, then click on the drop down to search for the dbt Cloud Connection Type + + ![Create connection](/img/guides/orchestration/airflow-and-dbt-cloud/create-connection.png) + + ![Connection type](/img/guides/orchestration/airflow-and-dbt-cloud/connection-type.png) + +3. Add in your connection details and your default dbt Cloud account id. This is found in your dbt Cloud URL after the accounts route section (`/accounts/{YOUR_ACCOUNT_ID}`), for example the account with id 16173 would see this in their URL: `https://cloud.getdbt.com/#/accounts/16173/projects/36467/jobs/65767/` + +![https://lh3.googleusercontent.com/sRxe5xbv_LYhIKblc7eiY7AmByr1OibOac2_fIe54rpU3TBGwjMpdi_j0EPEFzM1_gNQXry7Jsm8aVw9wQBSNs1I6Cyzpvijaj0VGwSnmVf3OEV8Hv5EPOQHrwQgK2RhNBdyBxN2](https://lh3.googleusercontent.com/sRxe5xbv_LYhIKblc7eiY7AmByr1OibOac2_fIe54rpU3TBGwjMpdi_j0EPEFzM1_gNQXry7Jsm8aVw9wQBSNs1I6Cyzpvijaj0VGwSnmVf3OEV8Hv5EPOQHrwQgK2RhNBdyBxN2) + +## 2. Add your `job_id` and `account_id` config details to the python file: [dbt_cloud_provider_eltml.py](https://github.com/sungchun12/airflow-dbt-cloud/blob/main/dags/dbt_cloud_provider_eltml.py) + +1. You’ll find these details within the dbt Cloud job URL, see the comments in the code snippet below for an example. + + ```python + # dbt Cloud Job URL: https://cloud.getdbt.com/#/accounts/16173/projects/36467/jobs/65767/ + # account_id: 16173 + #job_id: 65767 + + # line 28 + default_args={"dbt_cloud_conn_id": "dbt_cloud", "account_id": 16173}, + + trigger_dbt_cloud_job_run = DbtCloudRunJobOperator( + task_id="trigger_dbt_cloud_job_run", + job_id=65767, # line 39 + check_interval=10, + timeout=300, + ) + ``` + +2. Turn on the DAG and verify the job succeeded after running. Note: screenshots taken from different job runs, but the user experience is consistent. + + ![https://lh6.googleusercontent.com/p8AqQRy0UGVLjDGPmcuGYmQ_BRodyL0Zis-eQgSmp69EHbKW51o4S-bCl1fXHlOmwpYEBxD0A-O1Q1hwt-VDVMO1wWH-AIeaoelBx06JXRJ0m1OcHaPpFKH0xDiduIhNlQhhbLiy](https://lh6.googleusercontent.com/p8AqQRy0UGVLjDGPmcuGYmQ_BRodyL0Zis-eQgSmp69EHbKW51o4S-bCl1fXHlOmwpYEBxD0A-O1Q1hwt-VDVMO1wWH-AIeaoelBx06JXRJ0m1OcHaPpFKH0xDiduIhNlQhhbLiy) + + ![Airflow DAG](/img/guides/orchestration/airflow-and-dbt-cloud/airflow-dag.png) + + ![Task run instance](/img/guides/orchestration/airflow-and-dbt-cloud/task-run-instance.png) + + ![https://lh6.googleusercontent.com/S9QdGhLAdioZ3x634CChugsJRiSVtTTd5CTXbRL8ADA6nSbAlNn4zV0jb3aC946c8SGi9FRTfyTFXqjcM-EBrJNK5hQ0HHAsR5Fj7NbdGoUfBI7xFmgeoPqnoYpjyZzRZlXkjtxS](https://lh6.googleusercontent.com/S9QdGhLAdioZ3x634CChugsJRiSVtTTd5CTXbRL8ADA6nSbAlNn4zV0jb3aC946c8SGi9FRTfyTFXqjcM-EBrJNK5hQ0HHAsR5Fj7NbdGoUfBI7xFmgeoPqnoYpjyZzRZlXkjtxS) + +## How do I rerun the dbt Cloud job and downstream tasks in my pipeline? + +If you have worked with dbt Cloud before, you have likely encountered cases where a job fails. In those cases, you have likely logged into dbt Cloud, investigated the error, and then manually restarted the job. + +This section of the guide will show you how to restart the job directly from Airflow. This will specifically run *just* the `trigger_dbt_cloud_job_run` and downstream tasks of the Airflow DAG and not the entire DAG. If only the transformation step fails, you don’t need to re-run the extract and load processes. Let’s jump into how to do that in Airflow. + +1. Click on the task + + ![Task DAG view](/img/guides/orchestration/airflow-and-dbt-cloud/task-dag-view.png) + +2. Clear the task instance + + ![Clear task instance](/img/guides/orchestration/airflow-and-dbt-cloud/clear-task-instance.png) + + ![Approve clearing](/img/guides/orchestration/airflow-and-dbt-cloud/approve-clearing.png) + +3. Watch it rerun in real time + + ![Re-run](/img/guides/orchestration/airflow-and-dbt-cloud/re-run.png) + +## Cleaning up + +At the end of this guide, make sure you shut down your docker container. When you’re done using Airflow, use the following command to stop the container: + +```bash +$ astrocloud dev stop + +[+] Running 3/3 + ⠿ Container airflow-dbt-cloud_e3fe3c-webserver-1 Stopped 7.5s + ⠿ Container airflow-dbt-cloud_e3fe3c-scheduler-1 Stopped 3.3s + ⠿ Container airflow-dbt-cloud_e3fe3c-postgres-1 Stopped 0.3s +``` + +To verify that the deployment has stopped, use the following command: + +```bash +astrocloud dev ps +``` + +This should give you an output like this: + +```bash +Name State Ports +airflow-dbt-cloud_e3fe3c-webserver-1 exited +airflow-dbt-cloud_e3fe3c-scheduler-1 exited +airflow-dbt-cloud_e3fe3c-postgres-1 exited +``` + + diff --git a/website/docs/guides/orchestration/airflow-and-dbt-cloud/4-airflow-and-dbt-cloud-faqs.md b/website/docs/guides/orchestration/airflow-and-dbt-cloud/4-airflow-and-dbt-cloud-faqs.md new file mode 100644 index 00000000000..818896ae87a --- /dev/null +++ b/website/docs/guides/orchestration/airflow-and-dbt-cloud/4-airflow-and-dbt-cloud-faqs.md @@ -0,0 +1,50 @@ +--- +title: Airflow and dbt Cloud FAQs +id: 4-airflow-and-dbt-cloud-faqs +--- +## 1. How can we run specific subsections of the dbt DAG in Airflow? + +Because of the way we configured the dbt Cloud job to run in Airflow, you can leave this job to your analytics engineers to define in the job configurations from dbt Cloud. If, for example, we need to run hourly-tagged models every hour and daily-tagged models daily, we can create jobs like `Hourly Run` or `Daily Run` and utilize the commands `dbt run -s tag:hourly` and `dbt run -s tag:daily` within each, respectively. We only need to grab our dbt Cloud `account` and `job id`, configure it in an Airflow DAG with the code provided, and then we can be on your way. See more node selection options: [here](/reference/node-selection/syntax) + +## 2. How can I re-run models from the point of failure? + +You may want to parse the dbt DAG in Airflow to get the benefit of re-running from the point of failure. However, when you have hundreds of models in your DAG expanded out, it becomes useless for diagnosis and rerunning due to the overhead that comes along with creating an expansive Airflow DAG. + +You can’t re-run from failure natively in dbt Cloud today (feature coming!), but you can use a custom rerun parser. + +Using a simple python script coupled with the dbt Cloud provider, you can: + +- Avoid managing artifacts in a separate storage bucket(dbt Cloud does this for you) +- Avoid building your own parsing logic +- Get clear logs on what models you're rerunning in dbt Cloud (without hard coding step override commands) + +Watch the video below to see how it works! + + + +## 3. Should Airflow run one big dbt job or many dbt jobs? + +Overall we recommend being as purposeful and minimalistic as you can. This is because dbt manages all of the dependencies between models and the orchestration of running those dependencies in order, which in turn has benefits in terms of warehouse processing efforts. + +## 4. We want to kick off our dbt jobs after our ingestion tool (such as Fivetran) / data pipelines are done loading data. Any best practices around that? + +Our friends at Astronomer answer this question with this example: [here](https://registry.astronomer.io/dags/fivetran-dbt-cloud-census) + +## 5. How do you set up a CI/CD workflow with Airflow? + +Check out these two resources for accomplishing your own CI/CD pipeline: + +- [Continuous Integration with dbt Cloud](/docs/dbt-cloud/using-dbt-cloud/cloud-enabling-continuous-integration#overview) +- [Astronomer's CI/CD Example](https://docs.astronomer.io/software/ci-cd/#example-cicd-workflow) + +## 6. Can dbt dynamically create tasks in the DAG like Airflow can? + +We prefer to keep models bundled vs. unbundled. You can go this route, but if you have hundreds of dbt models, it’s more effective to let the dbt Cloud job handle the models and dependencies. Bundling provides the solution to clear observability when things go wrong - we've seen more success in having the ability to clearly see issues in a bundled dbt Cloud job than combing through the nodes of an expansive Airflow DAG. If you still have a use case for this level of control though, our friends at Astronomer answer this question [here](https://www.astronomer.io/blog/airflow-dbt-1/)! + +## 7. Can you trigger notifications if a dbt job fails with Airflow? Is there any way to access the status of the dbt Job to do that? + +Yes, either through [Airflow's email/slack](https://www.astronomer.io/guides/error-notifications-in-airflow/) functionality by itself or combined with [dbt Cloud's notifications](/docs/dbt-cloud/using-dbt-cloud/cloud-notifications), which support email and slack notifications. + +## 8. Are there decision criteria for how to best work with dbt Cloud and airflow? + +Check out this deep dive into planning your dbt Cloud + Airflow implementation [here](https://www.youtube.com/watch?v=n7IIThR8hGk)! diff --git a/website/docs/guides/orchestration/custom-cicd-pipelines/1-cicd-background.md b/website/docs/guides/orchestration/custom-cicd-pipelines/1-cicd-background.md new file mode 100644 index 00000000000..4dbcbb6c6c7 --- /dev/null +++ b/website/docs/guides/orchestration/custom-cicd-pipelines/1-cicd-background.md @@ -0,0 +1,43 @@ +--- +title: Customizing CI/CD +id: 1-cicd-background +--- + +# Creating Custom CI/CD Pipelines + +One of the core tenets of dbt is that analytic code should be version controlled. This provides a ton of benefit to your organization in terms of collaboration, code consistency, stability, and the ability to roll back to a prior version. There’s an additional benefit that is provided with your code hosting platform that is often overlooked or underutilized. Some of you may have experience using dbt Cloud’s [webhook functionality](https://docs.getdbt.com/docs/dbt-cloud/using-dbt-cloud/cloud-enabling-continuous-integration) to run a job when a PR is created. This is a fantastic capability, and meets most use cases for testing your code before merging to production. However, there are circumstances when an organization needs additional functionality, like running workflows on every commit (linting), or running workflows after a merge is complete. In this article, we will show you how to setup custom pipelines to lint your project and trigger a dbt Cloud job via the API. + +A note on parlance in this article since each code hosting platform uses different terms for similar concepts. The terms `pull request` (PR) and `merge request` (MR) are used interchangeably to mean the process of merging one branch into another branch. + + +## What are pipelines? + +Pipelines (which are known by many names, such as workflows, actions, or build steps) are a series of pre-defined jobs that are triggered by specific events in your repository (PR created, commit pushed, branch merged, etc). Those jobs can do pretty much anything your heart desires assuming you have the proper security access and coding chops. + +Jobs are executed on [runners](https://docs.github.com/en/actions/learn-github-actions/understanding-github-actions#runners), which are virtual servers. The runners come pre-configured with Ubuntu Linux, macOS, or Windows. That means the commands you execute are determined by the operating system of your runner. You’ll see how this comes into play later in the setup, but for now just remember that your code is executed on virtual servers that are, typically, hosted by the code hosting platform. + +![Diagram of how pipelines work](/img/guides/orchestration/custom-cicd-pipelines/pipeline-diagram.png) + +Please note, runners hosted by your code hosting platform provide a certain amount of free time. After that, billing charges may apply depending on how your account is setup. You also have the ability to host your own runners. That is beyond the scope of this article, but checkout the links below for more information if you’re interested in setting that up: + +- Repo-hosted runner billing information: + - [GitHub](https://docs.github.com/en/billing/managing-billing-for-github-actions/about-billing-for-github-actions) + - [GitLab](https://docs.gitlab.com/ee/ci/pipelines/cicd_minutes.html) +- Self-hosted runner information: + - [GitHub](https://docs.github.com/en/actions/hosting-your-own-runners/about-self-hosted-runners) + - [GitLab](https://docs.gitlab.com/runner/) + +Additionally, if you’re using the free tier of GitLab you can still follow this guide, but it may ask you to provide a credit card to verify your account. You’ll see something like this the first time you try to run a pipeline: + +![Warning from GitLab showing payment information is required](/img/guides/orchestration/custom-cicd-pipelines/gitlab-cicd-payment-warning.png) + + +## How to setup pipelines + +This guide provides details for multiple code hosting platforms. Where steps are unique, they are presented without a selection option. If code is specific to a platform (i.e. GitHub, GitLab) you will see a selection option for each. + +Pipelines can be triggered by various events. The [dbt Cloud webhook](https://docs.getdbt.com/docs/dbt-cloud/using-dbt-cloud/cloud-enabling-continuous-integration) process already triggers a run if you want to run your jobs on a merge request, so this guide focuses on running pipelines for every push and when PRs are merged. Since pushes happen frequently in a project, we’ll keep this job super simple and fast by linting with SQLFluff. The pipeline that runs on merge requests will run less frequently, and can be used to call the dbt Cloud API to trigger a specific job. This can be helpful if you have specific requirements that need to happen when code is updated in production, like running a `--full-refresh` on all impacted incremental models. + +Here’s a quick look at what this pipeline will accomplish: + +![Diagram showing the pipelines to be created and the programs involved](/img/guides/orchestration/custom-cicd-pipelines/pipeline-programs-diagram.png) diff --git a/website/docs/guides/orchestration/custom-cicd-pipelines/2-lint-on-push.md b/website/docs/guides/orchestration/custom-cicd-pipelines/2-lint-on-push.md new file mode 100644 index 00000000000..5031ea50844 --- /dev/null +++ b/website/docs/guides/orchestration/custom-cicd-pipelines/2-lint-on-push.md @@ -0,0 +1,142 @@ +--- +title: Lint code on push +id: 2-lint-on-push +--- + +This section shows a very basic example of linting a project every time a commit is pushed to the repo. While it is simple, it shows the power of CI and can be expanded on to meet the needs of your organization. + +The steps below use [SQLFluff](https://docs.sqlfluff.com/en/stable/) to scan your code and look for linting errors. In the example, it's set to use the `snowflake` dialect, and specfically runs the rules L019, L020, L021, and L022. This is purley for demonstration purposes. You should update this to reflect your code base's [dialect](https://docs.sqlfluff.com/en/stable/dialects.html) and the [rules](https://docs.sqlfluff.com/en/stable/rules.html) you've established for your repo. + +### 1. Create a yaml file to define your pipeline + +The yaml files defined below are what tell your code hosting platform the steps to run. In this setup, you’re telling the platform to run a SQLFluff lint job every time a commit is pushed. + + + + +In order for GitHub to know that you want to run an action, you need to have a few specific folders in your project. Add a new folder named `.github`, and within that folder add a new one named `workflows`. Your final folder structure will look like this: + +```sql +my_awesome_project +├── .github +│ ├── workflows +│ │ └── lint_on_push.yml +``` + +To define the job for our action, let’s add a new file named `lint_on_push.yml` under the `workflows` folder. This file is how we tell the GitHub runner what to execute when the job is triggered. + +Below I touch on the important pieces for running a dbt Cloud job, but if you want a full run-down of all the components of this yaml file checkout [this GitHub article](https://docs.github.com/en/actions/learn-github-actions/understanding-github-actions#understanding-the-workflow-file) on actions. + +**Key pieces:** + +- `on:` - this is used to filter when the pipeline is run. In this example we’re running it on every push except for pushes to branches named `main`. For more filters, checkout [GitHub’s docs](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows). +- `runs-on: ubuntu-latest` - this defines the operating system we’re using to run the job +- `uses:` - remember the virtual servers we coved in the background section? They’re just empty operating systems, so there are two pieces of setup that are needed in order to access the code in your repo, and setup Python correctly on the virtual server. These two actions are called from other repos in GitHub to provide those services. For more information on them, checkout their repos: [actions/checkout](https://github.com/actions/checkout#checkout-v3) and [actions/setup-python](https://github.com/actions/setup-python#setup-python-v3). +- `run:` - this is how we’re telling the GitHub runner to execute the Python script we defined above. + +```yaml +name: lint dbt project on push + +on: + push: + branches-ignore: + - 'main' + +jobs: +# this job runs SQLFluff with a specific set of rules + # note the dialect is set to Snowflake, so make that specific to your setup + # details on linter rules: https://docs.sqlfluff.com/en/stable/rules.html + lint_project: + name: Run SQLFluff linter + runs-on: ubuntu-latest + + steps: + - uses: "actions/checkout@v3" + - uses: "actions/setup-python@v2" + with: + python-version: "3.9" + - name: Install SQLFluff + run: "pip install sqlfluff==0.13.1" + - name: Lint project + run: "sqlfluff lint models --dialect snowflake --rules L019,L020,L021,L022" + +``` + + + + +Create a `.gitlab-ci.yml` file in your **root directory** to define the triggers for when to execute the script above. You’ll put the code below into this file. + +```sql +my_awesome_project +├── dbt_project.yml +├── .gitlab-ci.yml +``` + +**Key pieces:** + +- `image: python:3.9` - this defines the virtual image we’re using to run the job +- `rules:` - this is used to filter when the pipeline runs. In this case we’re telling it to run on every push event except when the branch is named `main`. Filters are very powerful to run commands on specific events, and you can find a full list in [GitLab’s documentation](https://docs.gitlab.com/ee/ci/yaml/#rules). +- `script:` - this is how we’re telling the GitLab runner to execute the Python script we defined above. + +```yaml +image: python:3.9 + +stages: + - pre-build + +# this job runs SQLFluff with a specific set of rules +# note the dialect is set to Snowflake, so make that specific to your setup +# details on linter rules: https://docs.sqlfluff.com/en/stable/rules.html +lint-project: + stage: pre-build + rules: + - if: $CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH != 'main' + script: + - pip install sqlfluff==0.13.1 + - sqlfluff lint models --dialect snowflake --rules L019,L020,L021,L022 +``` + + + + +### 2. Commit and push your changes to make sure everything works + +After you finish creating the yaml files, commit and push your code. Doing this will trigger your pipeline for the first time! If everything goes well, you should see the pipeline in your code platform. When you click into the job you’ll get a log showing that SQLFluff was run. If your code failed linting you’ll get an error in the job with a description of what needs to be fixed. If everything passed the lint check, you’ll see a successful job run. + + + + +In your repository, click the *Actions* tab + +![Image showing the GitHub action for lint on push](/img/guides/orchestration/custom-cicd-pipelines/lint-on-push-github.png) + +Sample output from SQLFluff in the `Run SQLFluff linter` job: + +![Image showing the logs in GitHub for the SQLFluff run](/img/guides/orchestration/custom-cicd-pipelines/lint-on-push-logs-github.png) + + + + +In the menu option got to *CI/CD > Pipelines* + +![Image showing the GitLab action for lint on push](/img/guides/orchestration/custom-cicd-pipelines/lint-on-push-gitlab.png) + +Sample output from SQLFluff in the `Run SQLFluff linter` job: + +![Image showing the logs in GitLab for the SQLFluff run](/img/guides/orchestration/custom-cicd-pipelines/lint-on-push-logs-gitlab.png) + + + diff --git a/website/docs/guides/orchestration/custom-cicd-pipelines/3-dbt-cloud-job-on-merge.md b/website/docs/guides/orchestration/custom-cicd-pipelines/3-dbt-cloud-job-on-merge.md new file mode 100644 index 00000000000..3e3447ec403 --- /dev/null +++ b/website/docs/guides/orchestration/custom-cicd-pipelines/3-dbt-cloud-job-on-merge.md @@ -0,0 +1,295 @@ +--- +title: Run a dbt Cloud job on merge +id: 3-dbt-cloud-job-on-merge +--- + +This job will take a bit more to setup, but is a good example of how to call the dbt Cloud API from a CI/CD pipeline. The concepts persented here can be generalized and used in whatever way best suits your use case. + +The setup below shows how to call the dbt Cloud API to run a job every time there is a push to your main branch (i.e. a PR is merged). + + +### 1. Get your dbt Cloud API key + +When running a CI/CD pipeline you’ll want to use a service token instead of any individual’s API key. There are [detailed docs](https://docs.getdbt.com/docs/dbt-cloud/dbt-cloud-api/service-tokens) available on this, but below is a quick rundown (this must be performed by an Account Admin): + +- Login to your dbt Cloud account +- In the upper left, click the menu button, then *Account Settings* +- Click *Service Tokens* on the left +- Click *New Token* to create a new token specifically for CI/CD API calls +- Name your token something like “CICD Token” +- Click the *+Add* button under *Access,* and grant this token the *Job Admin* permission +- Click *Save* and you’ll see a grey box appear with your token. Copy that and save it somewhere safe (this is a password, and should be treated as such). + +![View of the dbt Cloud page where service tokens are created](/img/guides/orchestration/custom-cicd-pipelines/dbt-service-token-page.png) + +Here’s a video showing the steps as well: + + + +### 2. Put your dbt Cloud API key into your repo + +This next part will happen in you code hosting platform. We need to save your API key from above into a repository secret so the job we create can access it. It is **not** recommended to ever save passwords or API keys in your code, so this step ensures that your key stays secure, but is still usable for your pipelines. + + + + +In GitHub: + +- Open up your repository where you want to run the pipeline (the same one that houses your dbt project) +- Click *Settings* to open up the repository options +- On the left click the *Security* dropdown +- From that list, click on *Actions* +- Towards the middle of the screen, click the *New repository secret* button +- It will ask you for a name, so let’s call ours `DBT_API_KEY` + - **It’s very important that you copy/paste this name exactly because it’s used in the scripts below.** +- In the *Value* section, paste in the key you copied from dbt Cloud +- Click *Add secret* and you’re all set! + +** A quick note on security: while using a repository secret is the most straightforward way to setup this secret, there are other options available to you in GitHub. They’re beyond the scope of this guide, but could be helpful if you need to create a more secure environment for running actions. Checkout GitHub’s documentation on secrets [here](https://docs.github.com/en/actions/security-guides/encrypted-secrets).* + +Here’s a video showing these steps: + + + + + +In GitLab: + +- Open up your repository where you want to run the pipeline (the same one that houses your dbt project) +- Click *Settings* > *CI/CD* +- Under the *Variables* section, click *Expand,* then click *Add variable* +- It will ask you for a name, so let’s call ours `DBT_API_KEY` + - **It’s very important that you copy/paste this name exactly because it’s used in the scripts below.** +- In the *Value* section, paste in the key you copied from dbt Cloud +- Make sure the check box next to *Protect variable* is unchecked, and the box next to *Mask variable* is selected (see below) + - “Protected” means that the variable is only available in pipelines that run on protected branches or protected tags - that won’t work for us because we want to run this pipeline on multiple branches. “Masked” means that it will be available to your pipeline runner, but will be masked in the logs. + + ![View of the GitLab window for entering DBT_API_KEY](/img/guides/orchestration/custom-cicd-pipelines/dbt-api-key-gitlab.png) + + Here’s a video showing these steps: + + + + + + +### 3. Create script to trigger dbt Cloud job via an API call + +In your dbt Cloud project, create a new folder at the root level named `python`. In that folder, create a file named `run_and_monitor_dbt_job.py`. You’ll copy/paste the contents from this [gist](https://gist.github.com/b-per/f4942acb8584638e3be363cb87769b48) into that file. + +```yaml +my_awesome_project +├── python +│ └── run_and_monitor_dbt_job.py +``` + +This Python file has everything you need to call the dbt Cloud API, but requires a few inputs (see snip below). Those inputs are fed to this script through environment variables that will be defined in the next step. + +```python +#------------------------------------------------------------------------------ +# get environment variables +#------------------------------------------------------------------------------ +api_base = os.getenv('DBT_URL', 'https://cloud.getdbt.com/') # default to multitenant url +job_cause = os.getenv('DBT_JOB_CAUSE', 'API-triggered job') # default to generic message +git_branch = os.getenv('DBT_JOB_BRANCH', None) # default to None +schema_override = os.getenv('DBT_JOB_SCHEMA_OVERRIDE', None) # default to None +api_key = os.environ['DBT_API_KEY'] # no default here, just throw an error here if key not provided +account_id = os.environ['DBT_ACCOUNT_ID'] # no default here, just throw an error here if id not provided +project_id = os.environ['DBT_PROJECT_ID'] # no default here, just throw an error here if id not provided +job_id = os.environ['DBT_PR_JOB_ID'] # no default here, just throw an error here if id not provided +``` + +**Required input:** + +In order to call the dbt Cloud API, there are a few pieces of info the script needs. The easiest way to get these values is to open up the job you want to run in dbt Cloud. The URL when you’re inside the job has all the values you need: + +- `DBT_ACCOUNT_ID` - this is the number just after `accounts/` in the URL +- `DBT_PROJECT_ID` - this is the number just after `projects/` in the URL +- `DBT_PR_JOB_ID` - this is the number just after `jobs/` in the URL + +![Image of a dbt Cloud job URL with the pieces for account, project, and job highlighted](/img/guides/orchestration/custom-cicd-pipelines/dbt-cloud-job-url.png) + +### 4. Update your project to include the new API call + + + + +For this new job, we’ll add a file for the dbt Cloud API call named `dbt_run_on_merge.yml`. + +```yaml +my_awesome_project +├── python +│ └── run_and_monitor_dbt_job.py +├── .github +│ ├── workflows +│ │ └── dbt_run_on_merge.yml +│ │ └── lint_on_push.yml +``` + +The yaml file will look pretty similar to our earlier job, but there is a new section called `env` that we’ll use to pass in the required variables. Update the variables below to match your setup based on the comments in the file. + +It’s worth noting that we changed the `on:` section to now run **only** when there are pushes to a branch named `main` (i.e. a PR is merge). Have a look through [GitHub’s docs](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows) on these filters for additional use cases. + +```yaml + +name: run dbt Cloud job on push + +# This filter says only run this job when there is a push to the main branch +# This works off the assumption that you've restrictred this branch to only all PRs to push to the deafult branch +# Update the name to match the name of your default branch +on: + push: + branches: + - 'main' + +jobs: + + # the job calls the dbt Cloud API to run a job + run_dbt_cloud_job: + name: Run dbt Cloud Job + runs-on: ubuntu-latest + + # Set the environment variables needed for the run + env: + DBT_ACCOUNT_ID: 00000 # enter your account id + DBT_PROJECT_ID: 00000 # enter your project id + DBT_PR_JOB_ID: 00000 # enter your job id + DBT_API_KEY: ${{ secrets.DBT_API_KEY }} + DBT_JOB_CAUSE: 'GitHub Pipeline CI Job' + DBT_JOB_BRANCH: ${{ github.ref_name }} + + steps: + - uses: "actions/checkout@v3" + - uses: "actions/setup-python@v2" + with: + python-version: "3.9" + - name: Run dbt Cloud job + run: "python python/run_and_monitor_dbt_job.py" +``` + + + + +For this job, we'll set it up using the `gitlab-ci.yml` file as in the prior step (see Step 1 of the linting setup for more info). The yaml file will look pretty similar to our earlier job, but there is a new section called `variables` that we’ll use to pass in the required variables to the Python script. Update this section to match your setup based on the comments in the file. + +Please note that the `rules:` section now says to run **only** when there are pushes to a branch named `main` (i.e. a PR is merge). Have a look through [GitLab’s docs](https://docs.gitlab.com/ee/ci/yaml/#rules) on these filters for additional use cases. + + + + +```yaml +image: python:3.9 + +variables: + DBT_ACCOUNT_ID: 00000 # enter your account id + DBT_PROJECT_ID: 00000 # enter your project id + DBT_PR_JOB_ID: 00000 # enter your job id + DBT_API_KEY: $DBT_API_KEY # secret variable in gitlab account + DBT_URL: https://cloud.getdbt.com + DBT_JOB_CAUSE: 'GitLab Pipeline CI Job' + DBT_JOB_BRANCH: $CI_COMMIT_BRANCH + +stages: + - build + +# this job calls the dbt Cloud API to run a job +run-dbt-cloud-job: + stage: build + rules: + - if: $CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH == 'main' + script: + - python python/run_and_monitor_dbt_job.py +``` + + + + +```yaml +image: python:3.9 + +variables: + DBT_ACCOUNT_ID: 00000 # enter your account id + DBT_PROJECT_ID: 00000 # enter your project id + DBT_PR_JOB_ID: 00000 # enter your job id + DBT_API_KEY: $DBT_API_KEY # secret variable in gitlab account + DBT_URL: https://cloud.getdbt.com + DBT_JOB_CAUSE: 'GitLab Pipeline CI Job' + DBT_JOB_BRANCH: $CI_COMMIT_BRANCH + +stages: + - pre-build + - build + +# this job runs SQLFluff with a specific set of rules +# note the dialect is set to Snowflake, so make that specific to your setup +# details on linter rules: https://docs.sqlfluff.com/en/stable/rules.html +lint-project: + stage: pre-build + rules: + - if: $CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH != 'main' + script: + - pip install sqlfluff==0.13.1 + - sqlfluff lint models --dialect snowflake --rules L019,L020,L021,L022 + +# this job calls the dbt Cloud API to run a job +run-dbt-cloud-job: + stage: build + rules: + - if: $CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH == 'main' + script: + - python python/run_and_monitor_dbt_job.py +``` + + + + + + + + +### 5. Test your new action + +Now that you have a shiny new action, it’s time to test it out! Since this change is setup to only run on merges to your default branch, you’ll need to create and merge this change into your main branch. Once you do that, you’ll see a new pipeline job has been triggered to run the dbt Cloud job you assigned in the variables section. + +Additionally, you’ll see the job in the run history of dbt Cloud. It should be fairly easy to spot because it will say it was triggered by the API, and the *INFO* section will have the branch you used for this guide. + + + + +![dbt run on merge job in GitHub](/img/guides/orchestration/custom-cicd-pipelines/dbt-run-on-merge-github.png) + +![dbt Cloud job showing it was triggered by GitHub](/img/guides/orchestration/custom-cicd-pipelines/dbt-cloud-job-github-triggered.png) + + + + +![dbt run on merge job in GitLub](/img/guides/orchestration/custom-cicd-pipelines/dbt-run-on-merge-gitlab.png) + +![dbt Cloud job showing it was triggered by GitLub](/img/guides/orchestration/custom-cicd-pipelines/dbt-cloud-job-gitlab-triggered.png) + + + diff --git a/website/docs/guides/orchestration/custom-cicd-pipelines/4-something-to-consider.md b/website/docs/guides/orchestration/custom-cicd-pipelines/4-something-to-consider.md new file mode 100644 index 00000000000..180ab35d44f --- /dev/null +++ b/website/docs/guides/orchestration/custom-cicd-pipelines/4-something-to-consider.md @@ -0,0 +1,8 @@ +--- +title: Something to Consider +id: 4-something-to-consider +--- + +Running dbt Cloud jobs through a CI/CD pipeline is a form of job orchestration. If you also run jobs using dbt Cloud’s built in scheduler, you now have 2 orchestration tools running jobs. The risk with this is that you could run into conflicts - you can imagine a case where you are triggering a pipeline on certain actions and running scheduled jobs in dbt Cloud, you would probably run into job clashes. The more tools you have, the more you have to make sure everything talks to each other. + +That being said, if **the only reason you want to use pipelines is for adding a lint check or run on merge**, you might decide the pros outweigh the cons, and as such you want to go with a hybrid approach. Just keep in mind that if two processes try and run the same job at the same time, dbt Cloud will queue the jobs and run one after the other. It’s a balancing act but can be accomplished with diligence to ensure you’re orchestrating jobs in a manner that does not conflict. \ No newline at end of file diff --git a/website/docs/learn/1-setting-up.md b/website/docs/learn/1-setting-up.md deleted file mode 100644 index 439a994d751..00000000000 --- a/website/docs/learn/1-setting-up.md +++ /dev/null @@ -1,120 +0,0 @@ ---- -title: Setting up -id: setting-up -description: This tutorial is the required pre-work for dbt Learn. ---- - - -This tutorial is the required pre-work for dbt Learn. Before beginning this tutorial, please ensure that you been received your Snowflake credentials and dbt Cloud invitation by email from a Learn instructor. - -If you are **new to dbt**, we recommend you take some time to read through the FAQs, and come armed with any questions you have along the way. If you get completely stuck in this tutorial, please ask questions in the dedicated Slack channel, as detailed in the welcome email. - -If you are already **experienced with dbt**, you still need to complete this tutorial as we'll be building on this project in our lessons. - -:::info -Please note that this tutorial is adapted from the main Getting Started tutorial — there may be some references to BigQuery in various videos, however the same concepts should apply on Snowflake. -::: - -In this tutorial, we will be turning the below query into a dbt project that is tested, documented, and deployed — you can check out the generated documentation docs for the project we're building [here](https://www.getdbt.com/getting-started-tutorial/#!/overview?g_v=1). - - - - -This tutorial is based on a fictional business named `jaffle_shop`, so you'll see this name used throughout the project. At this organization, the following query is used to build a `customers` table. - -```sql -with customers as ( - - select - id as customer_id, - first_name, - last_name - - from raw.jaffle_shop.customers - -), - -orders as ( - - select - id as order_id, - user_id as customer_id, - order_date, - status - - from raw.jaffle_shop.orders - -), - -customer_orders as ( - - select - customer_id, - - min(order_date) as first_order_date, - max(order_date) as most_recent_order_date, - count(order_id) as number_of_orders - - from orders - - group by 1 - -), - - -final as ( - - select - customers.customer_id, - customers.first_name, - customers.last_name, - customer_orders.first_order_date, - customer_orders.most_recent_order_date, - coalesce(customer_orders.number_of_orders, 0) as number_of_orders - - from customers - - left join customer_orders using (customer_id) - -) - -select * from final -``` - -## Connect to Snowflake -For dbt Learn, we've created a Snowflake account that you will be added to, but dbt works with [many data warehouses](available-adapters). - -1. Go to the Snowflake Console (link provided in email) and login with your supplied credentials. -2. Reset your password: all students will be asked to update their password — please use a password manager to store this securely. -3. Copy and paste the above query into a worksheet to validate that you are able to run it successfully. - - - -### FAQs - - - - -## Create a repository -We're going to use [GitHub](https://github.com/) as our git provider for this tutorial, but you can use any git provider. If you don't yet have a GitHub account, [create one now](https://github.com/join). - - -1. Create a new GitHub repository [here](https://github.com/new) named `dbt-learn-[initialsurname]` (e.g. `dbt-learn-ccarroll`). -2. Click **Create repository** (without `.gitignore` and without a license). - - - - -## Choose the way you want to develop -There’s two main ways of working with dbt: - -1. Edit files and run projects using the web-based Integrated Development Environment (IDE) in **dbt Cloud**. -2. Edit files locally using a code editor, and run projects using the Command Line Interface (**dbt CLI**). - -To use the CLI, it's important that you know some basics of your terminal. In particular, you should understand `cd`, `ls` and `pwd` to navigate through the directory structure of your computer easily. As such, if you are new to programming, we recommend using **dbt Cloud** for this tutorial. - -:::info -During dbt Learn, we try our best to demonstrate using both workflows. However, we tend to default to using dbt Cloud for some of the shorter demonstrations. -::: - -If you wish to use the CLI, please follow the [installation instructions](/dbt-cli/install/overview) for your operating system. diff --git a/website/docs/learn/2a-create-a-project-dbt-cloud.md b/website/docs/learn/2a-create-a-project-dbt-cloud.md deleted file mode 100644 index a9d530602c6..00000000000 --- a/website/docs/learn/2a-create-a-project-dbt-cloud.md +++ /dev/null @@ -1,78 +0,0 @@ ---- -title: 'dbt Cloud: Create a project' -sidebar_label: dbt Cloud -id: create-a-project-dbt-cloud -description: Now that we're set up, let's create a starter project with example models in dbt Cloud. ---- - -Now that we've successfully run our sample query in Snowflake, and chosen the way we want to develop, we can create a dbt project! In this step, we'll create a starter project with example models, before we build our own models. - -:::info - -These are the instructions for developing a project in dbt Cloud. If you're -using the dbt CLI, follow the instructions [here](/learn/create-a-project-dbt-cli). - -::: - -:::caution -Learn students: please make sure you name your project "dbt Learn - [initialsurname]" -::: - - - -## Create the starter project -:::info -You should have received an invitation to dbt Cloud. Please accept the invitation and create an account. -::: - -1. Login to [dbt Cloud](https://cloud.getdbt.com/login/). If you are also part of another organization's account, ensure you select "dbt Learn" as your account in the header bar. -2. Create a new project in dbt Cloud: - * Click the hamburger menu, then `Account Settings`, then `Projects`. - * **Name your project "dbt Learn - [initialsurname]"** (e.g "dbt Learn - ccarroll"), and click `Save`. There's no need to fill in the other details. - * Click the hamburger menu, and then `Home`. - * Switch the project in the header bar to your new "dbt Learn - [initialsurname]" project. **Do not use another student's project** -3. Complete the project setup flow: - * Connect to Snowflake using your provided credentials (also see below image) - * Add a repository — choose the Github integration, and link to the repository you set up in the [Setting Up](/learn/setting-up) instructions. - - - - - - - -:::caution -For the `[account id]` for Snowflake, this should be the account ID, not the entire URL. For example, use `abc12345` instead of `abc12345.snowflakecomputing.com` -::: - -4. Go to the `Develop` interface by either: - * Selecting `Start Developing`, or - * Selecting the hamburger menu, and then `Develop`. -5. Select `Initialize a project` to create your project. You should see a directory structure with `.sql` and `.yml` files that were generated by the `init` command. - - -6. Update the following values in the `dbt_project.yml` file: - - - -```yaml -name: jaffle_shop # this normally says my_new_package -config-version: 2 # you must be using dbt v0.17.0 for this to work -... - -models: - jaffle_shop: #this normally says my_new_package. It should match the value for `name:` - ... -``` - - - -## Perform your first dbt run -Our sample project has some example models in it. We're going to check that we can run them to confirm everything is in order. In the terminal bar at the bottom of the screen, type in `dbt run` and hit enter. - - - -## Commit your changes -We need to commit our changes so that our repository has up-to-date code. Click the `commit` button, with a message like "Create a starter project" - - diff --git a/website/docs/learn/2b-create-a-project-dbt-cli.md b/website/docs/learn/2b-create-a-project-dbt-cli.md deleted file mode 100644 index 9de2ee8d838..00000000000 --- a/website/docs/learn/2b-create-a-project-dbt-cli.md +++ /dev/null @@ -1,139 +0,0 @@ ---- -title: 'dbt CLI: Create a project' -sidebar_label: dbt CLI -id: create-a-project-dbt-cli -description: Now that we're set up, let's create a starter project with example models using the dbt CLI. ---- - -Now that we've successfully run our sample query in Snowflake, and chosen the way we want to develop, we can create a dbt project! In this step, we'll create a starter project with example models, before we build our own models. - -:::info - -These are the instructions for developing a project using the dbt CLI. If you're developing in dbt Cloud, follow the instructions [here](/learn/create-a-project-dbt-cloud). - -::: - - -## Create a project - - -The dbt CLI comes with a command to help you scaffold a dbt project. To create your dbt project: -1. Ensure dbt is installed by running `dbt --version`: -```shell-session -$ dbt --version -``` - -:::info - -dbt should have been installed as part of the [Setting Up](/learn/setting-up) part of the tutorial. If it was not installed, please follow the [installation instructions](dbt-cli/install/overview). - -::: - -2. Run the `init` command: -```shell-session -$ dbt init jaffle-shop -``` -3. `cd` into your project: -```shell-session -$ cd jaffle-shop -``` -You can use `pwd` to confirm that you are in the right spot. - -3. Open your project (i.e. the directory you just created) in a code editor like Atom or VSCode. You should see a directory structure with `.sql` and `.yml` files that were generated by the `init` command. - - - - -4. Update the following values in the `dbt_project.yml` file: - - - -```yaml -name: jaffle_shop # this normally says my_new_package -config-version: 2 # you must be using dbt v0.17.0 for this to work - -... - -profile: jaffle_shop # this normally says default - -... - -models: - jaffle_shop: #this normally says my_new_package. It should match the value for `name:` - ... -``` - - - -## Connect to Snowflake -When developing locally, dbt connects to your data warehouse using a [profile](/dbt-cli/configure-your-profile) — a yaml file with all the connection details to your warehouse. - -1. Create a file in the `~/.dbt/` directory named `profiles.yml`. -2. Copy the following into the file — make sure you update the values where indicated. - - - -```yaml -jaffle_shop: # this needs to match the profile: in your dbt_project.yml file - target: dev - outputs: - dev: - type: snowflake - threads: 4 - account: # supplied to you, eg. pa19123 (do not include the `snowflakecomputing.com` part) - user: # supplied to you - password: # supplied to you, you should have been asked to reset it when you opened the Snowflake console - role: transformer - database: analytics - warehouse: transforming - schema: dev_ # e.g. dev_ccarroll - client_session_keep_alive: False -``` - - - -4. Execute the debug command from your project to confirm that you can successfully connect -```shell-session -$ dbt debug -``` -Confirm that the last line of the output is `Connection test: OK connection ok`. - - - -### FAQs - - - - - - - -## Perform your first dbt run -Our sample project has some example models in it. We're going to check that we can run them to confirm everything is in order. - -1. Execute the `run` command to build the example models: -```shell-session -$ dbt run -``` -You should have an ouput that looks like this: - - - -## Commit your changes -We need to commit our changes so that our repository has up-to-date code. - - -1. Link the GitHub repository you created in the [Setting Up](/learn/setting-up) instructions to your dbt project by running the following commands. Make sure you use the correct git URL for your repository. -```shell-session -$ git init -$ git add -A -$ git commit -m "Create a dbt project" -$ git remote add origin https://github.com/USERNAME/dbt-learn-[initialsurname].git -$ git push -u origin master -``` - -:::info - -If this is your first time using git, it's worth taking some time to understand the basics. - -::: diff --git a/website/docs/learn/3-build-your-first-models.md b/website/docs/learn/3-build-your-first-models.md deleted file mode 100644 index dea0e49bb93..00000000000 --- a/website/docs/learn/3-build-your-first-models.md +++ /dev/null @@ -1,282 +0,0 @@ ---- -title: Build your first models -id: build-your-first-models -description: With our starter project setup, it's time to get to the fun part — building models! ---- - -With our starter project setup, it's time to get to the fun part — building [models](/docs/building-a-dbt-project/building-models)! We're going to take the query from the [Setting up](/learn/setting-up) instructions, and turn it into a model in our dbt project. - -## Checkout a new git branch -### dbt Cloud -1. Ensure you're in the Develop interface. If you're not, click the hamburger menu, and then `Develop`. The master branch should now be set to "read only" mode, so you'll need to create a new branch. This is generally good practice anyway. -2. Click the "create new branch" button, and name your branch `add-customers-model`. - - - - -### dbt CLI -It's a good idea to check out a new git branch when working on new code. - -1. Run `git checkout -b add-customers-model` to create a new branch/ - - - -## Build your first model -### dbt Cloud - - -1. Ensure you're in the Develop interface. If you're not, click the hamburger menu, and then `Develop`. -2. Create a new file in the `models` directory named `models/customers.sql`. -3. Paste the query from the [Setting up](/learn/setting-up) instructions into the file. -4. Execute `dbt run` in the command prompt at the bottom of the screen. You should get a successful run, like so: - - - -If you switch back to the Snowflake console you'll be able to `select` from this model. - - -### dbt CLI - - - -1. Open your project in a code editor -2. Create a new SQL file in the `models` directory, named `models/customers.sql`. -3. Paste the query from the [Setting up](/learn/setting-up) instructions into the file. -4. From the command line, execute `dbt run`. Your output should look like this: - - - -If you switch back to the Snowflake console you'll be able to `select` from this model. - -### FAQs - - - - - - - -## Change the way your model is materialized -One of the most powerful features of dbt is that you can change the way a model is materialized in your warehouse, simply by changing a configuration value. Let's see this in action. - -:::info Using the `+` sign in your `dbt_project.yml` -These videos were recorded with a slightly older version of dbt (dbt v0.15.0), which did not use the `+` sign in the `dbt_project.yml` file (this was introduced in dbt v0.17.0). - -We'll try to update the videos soon, but for now, take extra note of the `+` signs in the code samples below, under the `models:` key. - -::: - - - - - - -1. Edit the following in your `dbt_project.yml` file: - - - -```yml -models: - jaffle_shop: - +materialized: table - example: - +materialized: view - -``` - - - -2. Execute `dbt run`. Your model, `customers` should now be built as a table! - -:::info -To do this, dbt had to first run a `drop view` statement, then a `create table as` statement. -::: - - -3. Edit `models/customers.sql` to have the following snippet at the top: - - - -```sql -{{ - config( - materialized='view' - ) -}} - -with customers as ( - - select - id as customer_id - ... - -) - -``` - - - -4. Execute `dbt run`. Your model, `customers` should be built as a view. - -### FAQs - - - - -## Delete the example models - -We don't need the sample files that dbt created for us anymore! Let's delete them. - - - - - - -1. Delete the `models/example/` directory -2. Delete the `example:` key from your `dbt_project.yml` file, and any configurations that are listed under it - - - -```yaml -# before -models: - jaffle_shop: - +materialized: table - example: - +materialized: view -``` - - - - -```yaml -# after -models: - jaffle_shop: - +materialized: table -``` - - - -### FAQs - - - - -## Build models on top of other models -Often, it's a good idea to clean your data in one place, before doing additional transformations downstream. Our query already uses CTEs to this effect, but now we're going to experiment with using the [ref](ref) function to separate this clean-up into upstream models, like so: - - - - - - - - - -1. Create a new SQL file, `models/stg_customers.sql`, with the SQL from the `customers` CTE in our original query: - - - -```sql -select - id as customer_id, - first_name, - last_name - -from raw.jaffle_shop.customers -``` - - - -2. Create a second new SQL file, `models/stg_orders.sql`, with the SQL from the `orders` CTE in our original query: - - - -```sql -select - id as order_id, - user_id as customer_id, - order_date, - status - -from raw.jaffle_shop.orders -``` - - - -3. Edit the SQL in your `models/customers.sql` file as follows: - - - -```sql -with customers as ( - - select * from {{ ref('stg_customers') }} - -), - -orders as ( - - select * from {{ ref('stg_orders') }} - -), - -customer_orders as ( - - select - customer_id, - - min(order_date) as first_order_date, - max(order_date) as most_recent_order_date, - count(order_id) as number_of_orders - - from orders - - group by 1 - -), - - -final as ( - - select - customers.customer_id, - customers.first_name, - customers.last_name, - customer_orders.first_order_date, - customer_orders.most_recent_order_date, - coalesce(customer_orders.number_of_orders, 0) as number_of_orders - - from customers - - left join customer_orders using (customer_id) - -) - -select * from final -``` - - - -4. Execute `dbt run` - -This time when dbt ran, separate views/tables were created for `stg_customers`, `stg_orders` and `customers`. dbt was able to infer the order in which to run these models in — `customers` depends on `stg_customers` and `stg_orders`, so gets built last. There's no need to explicitly define these dependencies. - - -### FAQs - - - - -## Extra exercises -* Write some bad SQL to cause an error — can you debug this error? -* Run only a single model at a time ([docs](node-selection/syntax)) -* Group your models with a `stg_` prefix into a `staging` subdirectory (i.e. `models/staging/stg_customers.sql`) - * Configure your `staging` models to be views - * Run only the `staging` models - - - - - diff --git a/website/docs/learn/4-test-and-document-your-project.md b/website/docs/learn/4-test-and-document-your-project.md deleted file mode 100644 index 91fe716a1ab..00000000000 --- a/website/docs/learn/4-test-and-document-your-project.md +++ /dev/null @@ -1,177 +0,0 @@ ---- -title: Test and document your project -id: test-and-document-your-project -description: Let's test and document our models to build trust in our data. ---- - -## Add tests to your models -Adding [tests](/docs/building-a-dbt-project/tests) to a project helps validate that your models are working correctly. So let's add some tests to our project! - - - - - - -1. Create a new YAML file in the `models` directory, named `models/schema.yml` -2. Add the following contents to the file: - - - -```yaml -version: 2 - -models: - - name: customers - columns: - - name: customer_id - tests: - - unique - - not_null - - - name: stg_customers - columns: - - name: customer_id - tests: - - unique - - not_null - - - name: stg_orders - columns: - - name: order_id - tests: - - unique - - not_null - - name: status - tests: - - accepted_values: - values: ['placed', 'shipped', 'completed', 'return_pending', 'returned'] - - name: customer_id - tests: - - not_null - - relationships: - to: ref('stg_customers') - field: customer_id - -``` - - - -3. Execute `dbt test`, and confirm that all your tests passed. - - - - - - -:::info -When you run `dbt test`, dbt iterates through your YAML files, and constructs a query for each test. Each query will return the number of records that fail the test. If this number is 0, then the test is successful. -::: - -### FAQs - - - - - - - - - -## Document your models -Adding [documentation](/docs/building-a-dbt-project/documentation) to your project allows you to describe your models in rich detail, and share that information with your team. Here, we're going to add some basic documentation to our project. - - - - - - -1. Update your `models/schema.yml` file to include some descriptions, such as those below. - - - -```yaml -version: 2 - -models: - - name: customers - description: One record per customer - columns: - - name: customer_id - description: Primary key - tests: - - unique - - not_null - - name: first_order_date - description: NULL when a customer has not yet placed an order. - - - name: stg_customers - description: This model cleans up customer data - columns: - - name: customer_id - description: Primary key - tests: - - unique - - not_null - - - name: stg_orders - description: This model cleans up order data - columns: - - name: order_id - description: Primary key - tests: - - unique - - not_null - - name: status - tests: - - accepted_values: - values: ['placed', 'shipped', 'completed', 'return_pending', 'returned'] - -``` - - - -2. Execute `dbt docs generate` to generate the documentation for your project. dbt introspects your project and your warehouse to generate a json file with rich documentation about your project. -3. [CLI] Execute `dbt docs serve` to launch the documentation in a local website. [Cloud] Click the link above the file tree in the develop interface to launch documentation in a new tab. - - -:::tip -Great work ⭐️! You've just built your first dbt project that's tested and documented! -::: - - -### FAQs - - - - -## Extra exercises - - - - - - -* Write a test that fails, for example, omit one of the order statuses in the `accepted_values` list. What does a failing test look like? Can you debug the failure? -* Run the tests for one model only. If you grouped your `stg_` models into a directory, try running the tests for all the models in that directory. -* Use a [docs block](/docs/building-a-dbt-project/documentation#using-docs-blocks) to add a Markdown description to a model. - -## Commit your changes -First off, we need to commit the changes we made to our project so that our repository has our latest code. - -### dbt Cloud - - -Click the `commit` button, with a message like "Add customers model, tests, docs" - -### dbt CLI - - -1. Add all your changes to git: `git add -A` -2. Commit your changes: `git commit -m "Add customers model, tests, docs"` -3. Push your changes to your repository: `git push` - -## Next steps - -:::tip -Congratulations 🎉! You've just deployed your first dbt project! Please reply to the email you received with your credentials with a link to your GitHub repository. -::: diff --git a/website/docs/learn/load_data.sql b/website/docs/learn/load_data.sql deleted file mode 100644 index ed9bf36cae7..00000000000 --- a/website/docs/learn/load_data.sql +++ /dev/null @@ -1,53 +0,0 @@ -create schema raw.jaffle_shop; - -create table raw.jaffle_shop.customers -( - id integer, - first_name varchar, - last_name varchar -); - -create table raw.jaffle_shop.orders -( - id integer, - user_id integer, - order_date date, - status varchar -); - -copy into raw.jaffle_shop.customers from 's3://dbt-tutorial-test/customers.csv' - file_format = ( - type = 'CSV' - field_delimiter = ',' - skip_header = 1 - ) -; - -copy into raw.jaffle_shop.orders from 's3://dbt-tutorial-test/orders.csv' - file_format = ( - type = 'CSV' - field_delimiter = ',' - skip_header = 1 - ) -; - - -create schema raw.stripe; - - -create or replace table raw.stripe.payment -( - id integer, - "orderID" integer, - "paymentMethod" varchar, - amount integer, - created date -); - -copy into raw.stripe.payment from 's3://dbt-tutorial-test/stripe_payments.csv' - file_format = ( - type = 'CSV' - field_delimiter = ',' - skip_header = 1 - ) -; diff --git a/website/docs/reference/artifacts/catalog-json.md b/website/docs/reference/artifacts/catalog-json.md index 46dc0311816..d5788f6f250 100644 --- a/website/docs/reference/artifacts/catalog-json.md +++ b/website/docs/reference/artifacts/catalog-json.md @@ -6,7 +6,7 @@ _Current schema_: [`v1`](https://schemas.getdbt.com/dbt/catalog/v1.json) _Produced by:_ `dbt docs generate` -This file contains information from your data warehouse about the tables and views produced and defined by the resources in your project. Today, dbt uses this file to populate metadata, such as column types and table statistics, in the [docs site](documentation). +This file contains information from your about the tables and views produced and defined by the resources in your project. Today, dbt uses this file to populate metadata, such as column types and statistics, in the [docs site](documentation). ### Top-level keys diff --git a/website/docs/reference/artifacts/dbt-artifacts.md b/website/docs/reference/artifacts/dbt-artifacts.md index bd1282b92eb..6ac9f5d004d 100644 --- a/website/docs/reference/artifacts/dbt-artifacts.md +++ b/website/docs/reference/artifacts/dbt-artifacts.md @@ -2,7 +2,7 @@ title: Overview --- -With every invocation, dbt generates and saves one or more *artifacts*. Several of these are JSON files (`manifest.json`, `catalog.json`, `run_results.json`, and `sources.json`) that are used to power: +With every invocation, dbt generates and saves one or more *artifacts*. Several of these are files (`manifest.json`, `catalog.json`, `run_results.json`, and `sources.json`) that are used to power: - [documentation](documentation) - [state](understanding-state) - [visualizing source freshness](cloud-snapshotting-source-freshness) @@ -10,7 +10,7 @@ With every invocation, dbt generates and saves one or more *artifacts*. Several They could also be used to: - calculate project-level test coverage - perform longitudinal analysis of run timing -- identify historical changes in table structure +- identify historical changes in structure - do much, much more dbt has produced artifacts since the release of dbt-docs in v0.11.0. Starting in dbt v0.19.0, we are committing to a stable and sustainable way of versioning, documenting, and validating dbt artifacts. @@ -18,8 +18,8 @@ dbt has produced artifacts since the release of dbt-docs in v0.11.0. Starting in ## When are artifacts produced? Most dbt commands (and corresponding RPC methods) produce artifacts: -- [manifest](manifest-json): produced by `compile`, `run`, `test`, `docs generate`, `ls` -- [run results](run-results-json): produced by `run`, `test`, `seed`, `snapshot`, `docs generate` +- [manifest](manifest-json): produced by `build`, `compile`, `run`, `test`, `docs generate`, `ls` +- [run results](run-results-json): produced by `build`, `run`, `test`, `seed`, `snapshot`, `docs generate` - [catalog](catalog-json): produced by `docs generate` - [sources](sources-json): produced by `source freshness` @@ -43,9 +43,4 @@ In the manifest, the `metadata` may also include: #### Notes: - The structure of dbt artifacts is canonized by [JSON schemas](https://json-schema.org/), which are hosted at **schemas.getdbt.com**. -- As of v0.20.0, the current schema for each artifact is: - - https://schemas.getdbt.com/dbt/manifest/v4.json - - https://schemas.getdbt.com/dbt/run-results/v4.json - - https://schemas.getdbt.com/dbt/catalog/v1.json - - https://schemas.getdbt.com/dbt/sources/v3.json -- Artifact versions may change in any minor version of dbt (`v0.x.0`). Each artifact is versioned independently. +- Artifact versions may change in any minor version of dbt (`v1.x.0`). Each artifact is versioned independently. diff --git a/website/docs/reference/artifacts/manifest-json.md b/website/docs/reference/artifacts/manifest-json.md index f54125c901e..99834266318 100644 --- a/website/docs/reference/artifacts/manifest-json.md +++ b/website/docs/reference/artifacts/manifest-json.md @@ -2,7 +2,7 @@ title: Manifest --- -_Current schema_: [`v4`](https://schemas.getdbt.com/dbt/manifest/v4/index.html) +_Current schema_: [`v6`](https://schemas.getdbt.com/dbt/manifest/v6/index.html) _Produced by:_ - `dbt compile` diff --git a/website/docs/reference/artifacts/run-results-json.md b/website/docs/reference/artifacts/run-results-json.md index 9e0d27f0da5..f2ded4f23dc 100644 --- a/website/docs/reference/artifacts/run-results-json.md +++ b/website/docs/reference/artifacts/run-results-json.md @@ -22,7 +22,7 @@ Note: `dbt source freshness` produces a different artifact, [`sources.json`](sou ### Top-level keys - [`metadata`](dbt-artifacts#common-metadata) -- `args`: Dictionary of arguments passed to the CLI command or RPC method that produced this artifact. Most useful is `which` (command) or `rpc_method`. This dict excludes null values, and includes default values if they are not null. +- `args`: Dictionary of arguments passed to the CLI command or RPC method that produced this artifact. Most useful is `which` (command) or `rpc_method`. This dict excludes null values, and includes default values if they are not null. Equivalent to [`invocation_args_dict`](flags#invocation_args_dict) in the dbt-Jinja context. - `elapsed_time`: Total invocation time in seconds. - `results`: Array of node execution details. diff --git a/website/docs/reference/artifacts/sources-json.md b/website/docs/reference/artifacts/sources-json.md index 39d318f940e..678fc19aa9c 100644 --- a/website/docs/reference/artifacts/sources-json.md +++ b/website/docs/reference/artifacts/sources-json.md @@ -17,7 +17,7 @@ This file contains information about [sources with freshness checks](using-sourc Each entry in `results` is a dictionary with the following keys: - `unique_id`: Unique source node identifier, which map results to `sources` in the [manifest](manifest-json) -- `max_loaded_at`: Max value of `loaded_at_field` timestamp in the source table when queried. +- `max_loaded_at`: Max value of `loaded_at_field` timestamp in the source when queried. - `snapshotted_at`: Current timestamp when querying. - `max_loaded_at_time_ago_in_s`: Interval between `max_loaded_at` and `snapshotted_at`, calculated in python to handle timezone complexity. - `criteria`: The freshness threshold(s) for this source, defined in the project. diff --git a/website/docs/reference/commands/clean.md b/website/docs/reference/commands/clean.md index d973400378b..e65b4ac671c 100644 --- a/website/docs/reference/commands/clean.md +++ b/website/docs/reference/commands/clean.md @@ -9,4 +9,6 @@ id: "clean" -`dbt clean` is a utility function that deletes all folders specified in the `clean-targets` list specified in `dbt_project.yml`. You can use this to delete the `dbt_packages` and `target` directories. \ No newline at end of file +`dbt clean` is a utility function that deletes all folders specified in the `clean-targets` list specified in `dbt_project.yml`. You can use this to delete the `dbt_packages` and `target` directories. + +To avoid complex permissions issues and potentially deleting crucial aspects of the remote file system without access to fix them, this command does not work when interfacing with the RPC server that powers the dbt Cloud IDE. Instead, when working in dbt Cloud, the `dbt deps` command cleans before it installs pacakges automatically. The `target` folder can be manually deleted from the sidbear file tree if needed. diff --git a/website/docs/reference/commands/cmd-docs.md b/website/docs/reference/commands/cmd-docs.md index be70d0ae026..d9032c29b91 100644 --- a/website/docs/reference/commands/cmd-docs.md +++ b/website/docs/reference/commands/cmd-docs.md @@ -11,7 +11,7 @@ The command is responsible for generating your project's documentation website b 1. copying the website `index.html` file into the `target/` directory 2. compiling the project to `target/manifest.json` -3. producing the `target/catalog.json` file, which contains metadata about the tables and views produced by the models in your project. +3. producing the `target/catalog.json` file, which contains metadata about the tables and views produced by the models in your project. **Example**: ``` @@ -26,7 +26,7 @@ dbt docs generate --no-compile ``` ### dbt docs serve -This command starts a webserver on port 8000 to serve your documentation locally. The webserver is rooted in your `target/` directory. +This command starts a webserver on port 8000 to serve your documentation locally. The webserver is rooted in your `target/` directory. Be sure to run `dbt docs generate` before `dbt docs serve` because the `generate` command produces a [catalog metadata artifact](/reference/artifacts/catalog-json) that the `serve` command depends upon. You will see an error message if the catalog is missing. **Usage:** ``` diff --git a/website/docs/reference/commands/deps.md b/website/docs/reference/commands/deps.md index 4966044d648..7a60c8c074b 100644 --- a/website/docs/reference/commands/deps.md +++ b/website/docs/reference/commands/deps.md @@ -19,8 +19,8 @@ Where relevant, dbt will display up to date and/or latest versions of packages t packages: - package: dbt-labs/dbt_utils version: 0.7.1 - - package: tailsdotcom/dbt_artifacts - version: 0.5.0-a1 + - package: brooklyn-data/dbt_artifacts + version: 1.2.0 install-prerelease: true - package: dbt-labs/codegen version: 0.4.0 @@ -39,9 +39,8 @@ packages: Installing dbt-labs/dbt_utils@0.7.1 Installed from version 0.7.1 Up to date! -Installing tailsdotcom/dbt_artifacts@0.5.0a1 - Installed from version 0.5.0a1 - Updated version available: 0.5.0 +Installing brooklyn-data/dbt_artifacts@1.2.0 + Installed from version 1.2.0 Installing dbt-labs/codegen@0.4.0 Installed from version 0.4.0 Up to date! diff --git a/website/docs/reference/commands/init.md b/website/docs/reference/commands/init.md index 95eb6d3fff7..3b163268178 100644 --- a/website/docs/reference/commands/init.md +++ b/website/docs/reference/commands/init.md @@ -13,7 +13,7 @@ The `init` command is interactive and responsive like never before. If this is your first time ever using the tool, it will: - ask you to name your project -- ask you which database adapter you're using (or to [install the one you need](available-adapters)) +- ask you which database adapter you're using (or to [Supported Data Platforms](supported-data-platforms)) - prompt you for each piece of information that dbt needs to connect to that database: things like `account`, `user`, `password`, etc Then, it will: diff --git a/website/docs/reference/commands/list.md b/website/docs/reference/commands/list.md index e1efd5a5420..a4639944a74 100644 --- a/website/docs/reference/commands/list.md +++ b/website/docs/reference/commands/list.md @@ -5,7 +5,7 @@ id: "list" ## Overview -The `dbt ls` command lists resources in your dbt project. It accepts selector arguments that are similar to those provided in [dbt run](run). `dbt list` is an alias for `dbt ls`. +The `dbt ls` command lists resources in your dbt project. It accepts selector arguments that are similar to those provided in [dbt run](run). `dbt list` is an alias for `dbt ls`. While `dbt ls` will read your [connection profile](dbt-cli/configure-your-profile) to resolve [`target`](dbt-jinja-functions/target)-specific logic, this command will not connect to your database or run any queries. ### Usage ``` @@ -85,4 +85,4 @@ models/base/snowplow_base_events.sql models/base/snowplow_base_web_page_context.sql models/identification/snowplow_id_map.sql ... -``` \ No newline at end of file +``` diff --git a/website/docs/reference/commands/run.md b/website/docs/reference/commands/run.md index 4ca35f079e0..0b775a157f0 100644 --- a/website/docs/reference/commands/run.md +++ b/website/docs/reference/commands/run.md @@ -7,7 +7,7 @@ id: "run" `dbt run` executes compiled sql model files against the current `target` database. dbt connects to the target database and runs the relevant SQL required -to materialize all data models using the specified materialization strategies. +to materialize all data models using the specified strategies. Models are run in the order defined by the dependency graph generated during compilation. Intelligent multi-threading is used to minimize execution time without violating dependencies. @@ -21,7 +21,7 @@ support transactions. ## Refresh incremental models -If you provide the `--full-refresh` argument to `dbt run`, dbt will treat incremental models as table models. This is useful when +If you provide the `--full-refresh` flag to `dbt run`, dbt will treat incremental models as models. This is useful when 1. The schema of an incremental model changes and you need to recreate it. 2. You want to reprocess the entirety of the incremental model because of new logic in the model code. @@ -34,6 +34,12 @@ dbt run --full-refresh + + +You can also supply the flag by its short name: `dbt run -f`. + + + In the dbt compilation context, this flag will be available as [flags.FULL_REFRESH](flags). Further, the `is_incremental()` macro will return `false` for *all* models in response when the `--full-refresh` flag is specified. diff --git a/website/docs/reference/commands/seed.md b/website/docs/reference/commands/seed.md index 3a0227d8cbd..e60ceced0d3 100644 --- a/website/docs/reference/commands/seed.md +++ b/website/docs/reference/commands/seed.md @@ -10,7 +10,7 @@ id: "seed" -The `dbt seed` command will load `csv` files located in the `seed-paths` directory of your dbt project into your data warehouse. +The `dbt seed` command will load `csv` files located in the `seed-paths` directory of your dbt project into your . ### Selecting seeds to run diff --git a/website/docs/reference/commands/source.md b/website/docs/reference/commands/source.md index 27f07f6dd37..415cff2d3e2 100644 --- a/website/docs/reference/commands/source.md +++ b/website/docs/reference/commands/source.md @@ -17,7 +17,7 @@ If you're using an older version of dbt Core (before v0.21), the old name of the -If your dbt project is [configured with sources](using-sources), then the `dbt source freshness` command will query all of your defined source tables, determining the "freshness" of these tables. If the tables are stale (based on the `freshness` config specified for your sources) then dbt will report a warning or error accordingly. If a source table is in a stale state, then dbt will exit with a nonzero exit code. +If your dbt project is [configured with sources](using-sources), then the `dbt source freshness` command will query all of your defined source tables, determining the "freshness" of these tables. If the tables are stale (based on the `freshness` config specified for your sources) then dbt will report a warning or error accordingly. If a source is in a stale state, then dbt will exit with a nonzero exit code. ### Specifying sources to snapshot @@ -39,7 +39,7 @@ $ dbt source freshness --select source:snowplow.event ### Configuring source freshness output -When `dbt source freshness` completes, a JSON file containing information about the freshness of your sources will be saved to `target/sources.json`. An example `sources.json` will look like: +When `dbt source freshness` completes, a file containing information about the freshness of your sources will be saved to `target/sources.json`. An example `sources.json` will look like: diff --git a/website/docs/reference/configs-and-properties.md b/website/docs/reference/configs-and-properties.md index 09b3ac51220..eec119badb9 100644 --- a/website/docs/reference/configs-and-properties.md +++ b/website/docs/reference/configs-and-properties.md @@ -20,7 +20,7 @@ For example, you can use resource **properties** to: * Define official downstream uses of your data models, in the form of [exposures](exposures) Whereas you can use **configurations** to: -* Change how a model will be materialized (table, view, incremental, etc) +* Change how a model will be materialized (, , incremental, etc) * Declare where a seed will be created in the database (`..`) * Declare whether a resource should persist its descriptions as comments in the database * Apply tags and "meta" properties @@ -29,13 +29,15 @@ Whereas you can use **configurations** to: Depending on the resource type, configurations can be defined: -1. Using a [`config()` Jinja macro](dbt-jinja-functions/config) within a `model`, `snapshot`, or `test` SQL file +1. Using a [`config()` Jinja macro](/reference/dbt-jinja-functions/config) within a `model`, `snapshot`, or `test` SQL file 2. Using a [`config` property](resource-properties/config) in a `.yml` file 3. From the [`dbt_project.yml` file](dbt_project.yml), under the corresponding resource key (`models:`, `snapshots:`, `tests:`, etc) ### Config inheritance -Configurations are prioritized in order of specificity, which is generally the order above: an in-file `config()` block takes precedence over properties defied in a `.yml` file, which takes precedence over a config defined in the project file. (Note that generic tests work a little differently when it comes to specificity. See [test configs](test-configs).) +dbt prioritizes configurations in order of specificity, from most specificity to least specificity. This generally follows the order above: an in-file `config()` block --> properties defined in a `.yml` file --> config defined in the project file. + +Note - Generic tests work a little differently when it comes to specificity. See [test configs](test-configs). Within the project file, configurations are also applied hierarchically. The most-specific config always "wins": In the project file, configurations applied to a `marketing` subdirectory will take precedence over configurations applied to the entire `jaffle_shop` project. To apply a configuration to a model, or directory of models, define the resource path as nested dictionary keys. @@ -163,12 +165,12 @@ You can find an exhaustive list of each supported property and config, broken do * Exposure [properties](exposure-properties) ## FAQs - - - - - - + + + + + + ## Troubleshooting common errors diff --git a/website/docs/reference/dbt-classes.md b/website/docs/reference/dbt-classes.md index 47a60a4b121..20e7637ba7a 100644 --- a/website/docs/reference/dbt-classes.md +++ b/website/docs/reference/dbt-classes.md @@ -2,13 +2,13 @@ title: "dbt Classes" --- -dbt has a number of classes it uses to represent objects in a data warehouse, parts of a dbt project, and the results of a command. +dbt has a number of classes it uses to represent objects in a , parts of a dbt project, and the results of a command. These classes are often useful when building advanced dbt models and macros. ## Relation -The `Relation` object is used to interpolate schema and table names into SQL code with appropriate quoting. This object should _always_ be used instead of interpolating values with `{{ schema }}.{{ table }}` directly. Quoting of the Relation object can be configured using the [`quoting` config][quoting]. +The `Relation` object is used to interpolate schema and names into SQL code with appropriate quoting. This object should _always_ be used instead of interpolating values with `{{ schema }}.{{ table }}` directly. Quoting of the Relation object can be configured using the [`quoting` config][quoting]. ### Creating Relations @@ -52,7 +52,7 @@ class Relation: -- Return true if the relation is a table {{ relation.is_table }} --- Return true if the relation is a view +-- Return true if the relation is a {{ relation.is_view }} -- Return true if the relation is a cte @@ -120,8 +120,8 @@ col.string_type() # character varying (255) The `Column` type is overridden as a `BigQueryColumn` in BigQuery dbt projects. This object works the same as the `Column` type described above, with the exception of extra properties and methods: ### Properties -**fields**: Returns the list of subfields contained within a field (if the column is a STRUCT) -**mode**: Returns the "mode" of the column, eg. `REPEATED` +- **fields**: Returns the list of subfields contained within a field (if the column is a STRUCT) +- **mode**: Returns the "mode" of the column, eg. `REPEATED` ### Instance methods **flatten()**: Return a flattened list of `BigQueryColumns` in which subfields are expanded into their own columns. For example, this nested field: diff --git a/website/docs/reference/dbt-jinja-functions.md b/website/docs/reference/dbt-jinja-functions.md deleted file mode 100644 index 8131da669fd..00000000000 --- a/website/docs/reference/dbt-jinja-functions.md +++ /dev/null @@ -1,42 +0,0 @@ ---- -title: "dbt Jinja Functions" ---- - -In addition to the standard Jinja library ([docs](https://jinja.palletsprojects.com/page/templates/)), we've added additional functions and variables to the Jinja context that are useful when working with a dbt project: -* [adapter](adapter) -* [as_bool](as_bool) -* [as_native](as_native) -* [as_number](as_number) -* [as_text](as_text) -* [builtins](builtins) -* [config](dbt-jinja-functions/config) -* [dbt_version](dbt_version) -* [dbt-project-yml-context](dbt-project-yml-context) -* [debug-method](debug-method) -* [doc](doc) -* [env_var](env_var) -* [exceptions](exceptions) -* [execute](execute) -* [flags](flags) -* [fromjson](fromjson) -* [fromyaml](fromyaml) -* [graph](graph) -* [invocation_id](invocation_id) -* [log](log) -* [modules](modules) -* [on-run-end-context](on-run-end-context) -* [profiles-yml-context](profiles-yml-context) -* [project_name](project_name) -* [ref](ref) -* [return](return) -* [run_query](run_query) -* [run_started_at](run_started_at) -* [schema](dbt-jinja-functions/schema) -* [schemas](schemas) -* [source](dbt-jinja-functions/source) -* [statement-blocks](statement-blocks) -* [target](target) -* [this](this) -* [tojson](tojson) -* [toyaml](toyaml) -* [var](var) diff --git a/website/docs/reference/dbt-jinja-functions/adapter.md b/website/docs/reference/dbt-jinja-functions/adapter.md index 9d996833538..1c11d1c8ff7 100644 --- a/website/docs/reference/dbt-jinja-functions/adapter.md +++ b/website/docs/reference/dbt-jinja-functions/adapter.md @@ -12,12 +12,13 @@ The following functions are available: - [adapter.dispatch](dispatch) - [adapter.get_missing_columns](#get_missing_columns) - [adapter.expand_target_column_types](#expand_target_column_types) -- [adapter.get_relation](#get_relation) +- [adapter.get_relation](#get_relation) or [load_relation](#load_relation) - [adapter.get_columns_in_relation](#get_columns_in_relation) - [adapter.create_schema](#create_schema) - [adapter.drop_schema](#drop_schema) - [adapter.drop_relation](#drop_relation) - [adapter.rename_relation](#rename_relation) +- [adapter.quote](#quote) ### Deprecated adapter functions @@ -38,7 +39,7 @@ __Args__: Returns a list of [Columns](dbt-classes#column) that is the difference of the columns in the `from_table` and the columns in the `to_table`, i.e. (`set(from_relation.columns) - set(to_table.columns)`). -Useful for detecting new columns in a source table. +Useful for detecting new columns in a source . **Usage**: @@ -52,7 +53,7 @@ Useful for detecting new columns in a source table. {% for col in adapter.get_missing_columns(target_relation, this) %} - alter table {{this}} add column "{{col.name}}" {{col.data_type}}; + alter {{this}} add column "{{col.name}}" {{col.data_type}}; {% endfor %} ``` @@ -64,7 +65,7 @@ __Args__: * `from_relation`: The source [Relation](dbt-classes#relation) to use as a template * `to_relation`: The [Relation](dbt-classes#relation) to mutate -Expand the `to_relation` table's column types to match the schema of `from_relation`. Column expansion is constrained to string and numeric types on supported databases. Typical usage involves expanding column types (from eg. `varchar(16)` to `varchar(32)`) to support insert statements. +Expand the `to_relation` 's column types to match the schema of `from_relation`. Column expansion is constrained to string and numeric types on supported databases. Typical usage involves expanding column types (from eg. `varchar(16)` to `varchar(32)`) to support insert statements. **Usage**: @@ -74,7 +75,7 @@ Expand the `to_relation` table's column types to match the schema of `from_relat {% set tmp_relation = adapter.get_relation(...) %} {% set target_relation = adapter.get_relation(...) %} -{% do adapter.expand_target_column_types(tmp_realtion, target_relation) %} +{% do adapter.expand_target_column_types(tmp_relation, target_relation) %} ``` @@ -87,7 +88,7 @@ __Args__: * `schema`: The schema of the relation to fetch * `identifier`: The identifier of the relation to fetch -Returns a [Relation](dbt-classes#relation) object identified by the `database.schema.identifier` provided to the method, or `None` if the relation does not exist. +Returns a cached [Relation](dbt-classes#relation) object identified by the `database.schema.identifier` provided to the method, or `None` if the relation does not exist. **Usage**: @@ -106,13 +107,37 @@ Returns a [Relation](dbt-classes#relation) object identified by the `database.sc +## load_relation +__Args__: + + * `relation`: The [Relation](dbt-classes#relation) to try to load + +A convenience wrapper for [get_relation](#get_relation). Returns the cached version of the [Relation](dbt-classes#relation) object, or `None` if the relation does not exist. + +**Usage**: + + + +```sql + +{% set relation_exists = (load_relation(ref('my_model')) is not none %} +{% if relation_exists %} + {{ log("my_model has already been built", info=true) }} +{% else %} + {{ log("my_model doesn't exist in the warehouse. Maybe it was dropped?", info=true) }} +{% endif %} + +``` + + + ## get_columns_in_relation __Args__: * `relation`: The [Relation](dbt-classes#relation) to find the columns for -Returns a list of [Columns](dbt-classes#column) in a table. +Returns a list of [Columns](dbt-classes#column) in a . **Usage**: @@ -171,7 +196,7 @@ __Args__: * `relation`: The Relation to drop -Drops a Relation in the database. If the target relation does not exist, then this method is a no-op. The specific implementation is adapter-dependent, but adapters should implement a cascading drop, such that bound views downstream of the dropped relation are also dropped. **Note**: this adapter method is destructive, so please use it with care! +Drops a Relation in the database. If the target relation does not exist, then this method is a no-op. The specific implementation is adapter-dependent, but adapters should implement a cascading drop, such that bound views downstream of the dropped relation are also dropped. **Note**: this adapter method is destructive, so please use it with care! The `drop_relation` method will remove the specified relation from dbt's relation cache. @@ -215,6 +240,26 @@ Renames a Relation the database. The `rename_relation` method will rename the s + +## quote +__Args__: + + * `identifier`: A string to quote + +Encloses `identifier` in the correct quotes for the adapter when escaping reserved column names etc. + +**Usage:** + + + +```sql +select + 'abc' as {{ adapter.quote('table_name') }}, + 'def' as {{ adapter.quote('group by') }} +``` + + + ## get_columns_in_table :::danger Deprecated @@ -226,9 +271,9 @@ This method is deprecated and will be removed in a future release. Please use [g __Args__: * `schema_name`: The schema to test - * `table_name`: The table (or view) from which to select columns + * `table_name`: The (or view) from which to select columns -Returns a list of [Columns](dbt-classes#column) in a table. +Returns a list of [Columns](dbt-classes#column) in a . @@ -255,9 +300,9 @@ This method is deprecated and will be removed in a future release. Please use [g __Args__: * `schema`: The schema to test - * `table`: The relation to look for + * ``: The relation to look for -Returns true if a relation named like `table` exists in schema `schema`, false otherwise. +Returns true if a relation named like `` exists in schema `schema`, false otherwise. diff --git a/website/docs/reference/dbt-jinja-functions/builtins.md b/website/docs/reference/dbt-jinja-functions/builtins.md index 57d6750cec1..f3ee4313f2c 100644 --- a/website/docs/reference/dbt-jinja-functions/builtins.md +++ b/website/docs/reference/dbt-jinja-functions/builtins.md @@ -10,10 +10,11 @@ The `builtins` variable exists to provide references to builtin dbt context meth The `builtins` variable is a dictionary containing the following keys: - [ref](ref) -- [source](dbt-jinja-functions/source) -- [config](dbt-jinja-functions/config) +- [source](/reference/dbt-jinja-functions/source) +- [config](/reference/dbt-jinja-functions/config) ## Usage + The following macro overrides the `ref` method available in the model compilation context to return a [Relation](dbt-classes#relation) with the database name overriden to `dev`. ``` diff --git a/website/docs/reference/dbt-jinja-functions/config.md b/website/docs/reference/dbt-jinja-functions/config.md index 2625b826658..3bc0d1c7f3f 100644 --- a/website/docs/reference/dbt-jinja-functions/config.md +++ b/website/docs/reference/dbt-jinja-functions/config.md @@ -5,7 +5,7 @@ id: "config" ## Overview -The `config` variable exists to handle end-user configuration for custom materializations. Configs like `unique_key` can be implemented using the `config` variable in your own materializations. +The `config` variable exists to handle end-user configuration for custom materializations. Configs like `unique_key` can be implemented using the `config` variable in your own materializations. For example, code in the `incremental` materialization like this: ``` @@ -55,4 +55,4 @@ Example usage: {% materialization incremental, default -%} {%- set unique_key = config.require('unique_key') -%} ... -``` \ No newline at end of file +``` diff --git a/website/docs/reference/dbt-jinja-functions/cross-database-macros.md b/website/docs/reference/dbt-jinja-functions/cross-database-macros.md new file mode 100644 index 00000000000..a7d8f2bc54b --- /dev/null +++ b/website/docs/reference/dbt-jinja-functions/cross-database-macros.md @@ -0,0 +1,953 @@ +--- +title: "cross-database macros" +id: "cross-database-macros" +--- + +# Cross-database macros + +## Overview + +These macros benefit three different user groups: +- If you maintain a package, your package is more likely to work on other adapters by using these macros (rather than a specific database's SQL syntax) +- If you maintain an adapter, your adapter is more likely to support more packages by implementing (and testing) these macros. +- If you're an end user, more packages and adapters are likely to "just work" for you (without you having to do anything). + +:::note Note +Please make sure to take a look at the [SQL expressions section](#sql-expressions) to understand quoting syntax for string values and date literals. +::: + +## All functions (alphabetical) + + + +- [any_value](#any_value) +- [bool_or](#bool_or) +- [cast_bool_to_text](#cast_bool_to_text) +- [concat](#concat) +- [dateadd](#dateadd) +- [datediff](#datediff) +- [date_trunc](#date_trunc) +- [escape_single_quotes](#escape_single_quotes) +- [except](#except) +- [hash](#hash) +- [intersect](#intersect) +- [last_day](#last_day) +- [length](#length) +- [listagg](#listagg) +- [position](#position) +- [replace](#replace) +- [right](#right) +- [safe_cast](#safe_cast) +- [split_part](#split_part) +- [string_literal](#string_literal) +- [type_bigint](#type_bigint) +- [type_float](#type_float) +- [type_int](#type_int) +- [type_numeric](#type_numeric) +- [type_string](#type_string) +- [type_timestamp](#type_timestamp) + + + + +- [any_value](#any_value) +- [array_append](#array_append) +- [array_concat](#array_concat) +- [array_construct](#array_construct) +- [bool_or](#bool_or) +- [cast_bool_to_text](#cast_bool_to_text) +- [concat](#concat) +- [dateadd](#dateadd) +- [datediff](#datediff) +- [date_trunc](#date_trunc) +- [escape_single_quotes](#escape_single_quotes) +- [except](#except) +- [hash](#hash) +- [intersect](#intersect) +- [last_day](#last_day) +- [length](#length) +- [listagg](#listagg) +- [position](#position) +- [replace](#replace) +- [right](#right) +- [safe_cast](#safe_cast) +- [split_part](#split_part) +- [string_literal](#string_literal) +- [type_bigint](#type_bigint) +- [type_boolean](#type_boolean) +- [type_float](#type_float) +- [type_int](#type_int) +- [type_numeric](#type_numeric) +- [type_string](#type_string) +- [type_timestamp](#type_timestamp) + + + + + +[**Data type functions**](#data-type-functions) +- [type_bigint](#type_bigint) +- [type_float](#type_float) +- [type_int](#type_int) +- [type_numeric](#type_numeric) +- [type_string](#type_string) +- [type_timestamp](#type_timestamp) + + + + +[**Data type functions**](#data-type-functions) +- [type_bigint](#type_bigint) +- [type_boolean](#type_boolean) +- [type_float](#type_float) +- [type_int](#type_int) +- [type_numeric](#type_numeric) +- [type_string](#type_string) +- [type_timestamp](#type_timestamp) + + + +[**Set functions**](#set-functions) +- [except](#except) +- [intersect](#intersect) + + + +[**Array functions**](#array-functions) +- [array_append](#array_append) +- [array_concat](#array_concat) +- [array_construct](#array_construct) + + + +[**String functions**](#string-functions) +- [concat](#concat) +- [hash](#hash) +- [length](#length) +- [position](#position) +- [replace](#replace) +- [right](#right) +- [split_part](#split_part) + +[**String literal functions**](#string-literal-functions) +- [escape_single_quotes](#escape_single_quotes) +- [string_literal](#string_literal) + +[**Aggregate and window functions**](#aggregate-and-window-functions) +- [any_value](#any_value) +- [bool_or](#bool_or) +- [listagg](#listagg) + +[**Cast functions**](#cast-functions) +- [cast_bool_to_text](#cast_bool_to_text) +- [safe_cast](#safe_cast) + +[**Date and time functions**](#date-and-time-functions) +- [dateadd](#dateadd) +- [datediff](#datediff) +- [date_trunc](#date_trunc) +- [last_day](#last_day) + +## Data type functions + +### type_bigint +__Args__: + + * None + +This macro yields the database-specific data type for a `BIGINT`. + +**Usage**: + +```sql +{{ dbt.type_bigint() }} +``` + +**Sample Output (PostgreSQL)**: + +```sql +bigint +``` + + + +### type_boolean +__Args__: + + * None + +This macro yields the database-specific data type for a `BOOLEAN`. + +**Usage**: + +```sql +{{ dbt.type_boolean() }} +``` + +**Sample Output (PostgreSQL)**: + +```sql +BOOLEAN +``` + + + +### type_float +__Args__: + + * None + +This macro yields the database-specific data type for a `FLOAT`. + +**Usage**: + +```sql +{{ dbt.type_float() }} +``` + +**Sample Output (PostgreSQL)**: + +```sql +FLOAT +``` + +### type_int +__Args__: + + * None + +This macro yields the database-specific data type for an `INT`. + +**Usage**: + +```sql +{{ dbt.type_int() }} +``` + +**Sample Output (PostgreSQL)**: + +```sql +INT +``` + +### type_numeric + +__Args__: + + * None + +This macro yields the database-specific data type for a `NUMERIC`. + +**Usage**: + +```sql +{{ dbt.type_numeric() }} +``` + +**Sample Output (PostgreSQL)**: + +```sql +numeric(28,6) +``` + +### type_string +__Args__: + + * None + +This macro yields the database-specific data type for `TEXT`. + +**Usage**: + +```sql +{{ dbt.type_string() }} +``` + +**Sample Output (PostgreSQL)**: + +```sql +TEXT +``` + +### type_timestamp +__Args__: + + * None + +This macro yields the database-specific data type for a `TIMESTAMP` (which may or may not match the behavior of `TIMESTAMP WITHOUT TIMEZONE` from ANSI SQL-92). + +**Usage**: + +```sql +{{ dbt.type_timestamp() }} +``` + +**Sample Output (PostgreSQL)**: + +```sql +TIMESTAMP +``` + +## Set functions + +### except +__Args__: + + * None + +`except` is one of the set operators specified ANSI SQL-92 (along with `union` and `intersect`) and is akin to [set difference](https://en.wikipedia.org/wiki/Complement_(set_theory)#Relative_complement). + +**Usage**: + +```sql +{{ dbt.except() }} +``` + +**Sample Output (PostgreSQL)**: + +```sql +except +``` + +### intersect +__Args__: + + * None + +`intersect` is one of the set operators specified ANSI SQL-92 (along with `union` and `except`) and is akin to [set intersection](https://en.wikipedia.org/wiki/Intersection_(set_theory)). + +**Usage**: + +```sql +{{ dbt.intersect() }} +``` + +**Sample Output (PostgreSQL)**: + +```sql +intersect +``` + + + +## Array functions + +### array_append +__Args__: + + * `array` (required): The array to append to. + * `new_element` (required): The element to be appended. This element must *match the data type of the existing elements* in the array in order to match PostgreSQL functionality and *not null* to match BigQuery functionality. + +This macro appends an element to the end of an array and returns the appended array. + +**Usage**: + +```sql +{{ dbt.array_append("array_column", "element_column") }} +{{ dbt.array_append("array_column", "5") }} +{{ dbt.array_append("array_column", "'blue'") }} +``` + +**Sample Output (PostgreSQL)**: + +```sql +array_append(array_column, element_column) +array_append(array_column, 5) +array_append(array_column, 'blue') +``` + +### array_concat +__Args__: + + * `array_1` (required): The array to append to. + * `array_2` (required): The array to be appended to `array_1`. This array must match the data type of `array_1` in order to match PostgreSQL functionality. + +This macro returns the concatenation of two arrays. + +**Usage**: + +```sql +{{ dbt.array_concat("array_column_1", "array_column_2") }} +``` + +**Sample Output (PostgreSQL)**: + +```sql +array_cat(array_column_1, array_column_2) +``` + +### array_construct +__Args__: + + * `inputs` (optional): The list of array contents. If not provided, this macro will create an empty array. All inputs must be the *same data type* in order to match PostgreSQL functionality and *not null* to match BigQuery functionality. + * `data_type` (optional): Specifies the data type of the constructed array. This is only relevant when creating an empty array (will otherwise use the data type of the inputs). If `inputs` are `data_type` are both not provided, this macro will create an empty array of type integer. + +This macro returns an array constructed from a set of inputs. + +**Usage**: + +```sql +{{ dbt.array_construct(["column_1", "column_2", "column_3"]) }} +{{ dbt.array_construct([], "integer") }} +{{ dbt.array_construct([1, 2, 3, 4]) }} +{{ dbt.array_construct(["'blue'", "'green'"]) }} +``` + +**Sample Output (PostgreSQL)**: + +```sql +array[ column_1 , column_2 , column_3 ] +array[]::integer[] +array[ 1 , 2 , 3 , 4 ] +array[ 'blue' , 'green' ] +``` + + + +## String functions + +### concat +__Args__: + + * `fields`: Jinja array of [attribute names or expressions](#sql-expressions). + +This macro combines a list of strings together. + +**Usage**: + +```sql +{{ dbt.concat(["column_1", "column_2"]) }} +{{ dbt.concat(["year_column", "'-'" , "month_column", "'-'" , "day_column"]) }} +{{ dbt.concat(["first_part_column", "'.'" , "second_part_column"]) }} +{{ dbt.concat(["first_part_column", "','" , "second_part_column"]) }} +``` + +**Sample Output (PostgreSQL)**: + +```sql +column_1 || column_2 +year_column || '-' || month_column || '-' || day_column +first_part_column || '.' || second_part_column +first_part_column || ',' || second_part_column +``` + +### hash +__Args__: + + * `field`: [attribute name or expression](#sql-expressions). + +This macro provides a hash (such as [MD5](https://en.wikipedia.org/wiki/MD5)) of an [expression](#sql-expressions) cast as a string. + +**Usage**: + +```sql +{{ dbt.hash("column") }} +{{ dbt.hash("'Pennsylvania'") }} +``` + +**Sample Output (PostgreSQL)**: + +```sql +md5(cast(column as + varchar +)) +md5(cast('Pennsylvania' as + varchar +)) +``` + +### length +__Args__: + + * `expression`: string [expression](#sql-expressions). + + +This macro calculates the number of characters in a string. + +**Usage**: + +```sql +{{ dbt.length("column") }} +``` + +**Sample Output (PostgreSQL)**: + +```sql + length( + column + ) +``` + +### position +__Args__: + + * `substring_text`: [attribute name or expression](#sql-expressions). + * `string_text`: [attribute name or expression](#sql-expressions). + +This macro searches for the first occurrence of `substring_text` within `string_text` and returns the 1-based position if found. + +**Usage**: + +```sql +{{ dbt.position("substring_column", "text_column") }} +{{ dbt.position("'-'", "text_column") }} +``` + +**Sample Output (PostgreSQL)**: + +```sql + position( + substring_column in text_column + ) + + position( + '-' in text_column + ) +``` + +### replace +__Args__: + + * `field`: [attribute name or expression](#sql-expressions). + * `old_chars`: [attribute name or expression](#sql-expressions). + * `new_chars`: [attribute name or expression](#sql-expressions). + +This macro updates a string and replaces all occurrences of one substring with another. The precise behavior may vary slightly from one adapter to another. + +**Usage**: + +```sql +{{ dbt.replace("string_text_column", "old_chars_column", "new_chars_column") }} +{{ dbt.replace("string_text_column", "'-'", "'_'") }} +``` + +**Sample Output (PostgreSQL)**: + +```sql + replace( + string_text_column, + old_chars_column, + new_chars_column + ) + + replace( + string_text_column, + '-', + '_' + ) +``` + +### right +__Args__: + + * `string_text`: [attribute name or expression](#sql-expressions). + * `length_expression`: numeric [expression](#sql-expressions). + +This macro returns the N rightmost characters from a string. + +**Usage**: + +```sql +{{ dbt.right("string_text_column", "length_column") }} +{{ dbt.right("string_text_column", "3") }} +``` + +**Sample Output (PostgreSQL)**: + +```sql + right( + string_text_column, + length_column + ) + + right( + string_text_column, + 3 + ) +``` + +### split_part +__Args__: + +* `string_text` (required): Text to be split into parts. +* `delimiter_text` (required): Text representing the delimiter to split by. +* `part_number` (required): Requested part of the split (1-based). If the value is negative, the parts are counted backward from the end of the string. + +This macro splits a string of text using the supplied delimiter and returns the supplied part number (1-indexed). + +**Usage**: + +When referencing a column, use one pair of quotes. When referencing a string, use single quotes enclosed in double quotes. + +```sql +{{ dbt.split_part(string_text='column_to_split', delimiter_text='delimiter_column', part_number=1) }} +{{ dbt.split_part(string_text="'1|2|3'", delimiter_text="'|'", part_number=1) }} +``` + +**Sample Output (PostgreSQL)**: + +```sql + split_part( + column_to_split, + delimiter_column, + 1 + ) + + split_part( + '1|2|3', + '|', + 1 + ) +``` + +## String literal functions + +### escape_single_quotes +__Args__: + + * `value`: Jinja string literal value + +This macro adds escape characters for any single quotes within the provided string literal. Note: if given a column, it will only operate on the column _name_, not the values within the column. + +To escape quotes for column values, consider a macro like [replace](#replace) or a regular expression replace. + +**Usage**: + +```sql +{{ dbt.escape_single_quotes("they're") }} +{{ dbt.escape_single_quotes("ain't ain't a word") }} +``` + +**Sample Output (PostgreSQL)**: + +```sql +they''re +ain''t ain''t a word +``` + +### string_literal +__Args__: + + * `value`: Jinja string value + +This macro converts a Jinja string into a SQL string literal. + +To cast column values to a string, consider a macro like [safe_cast](#safe_cast) or an ordinary cast. + +**Usage**: + +```sql +select {{ dbt.string_literal("Pennsylvania") }} +``` + +**Sample Output (PostgreSQL)**: + +```sql +select 'Pennsylvania' +``` + +## Aggregate and window functions + +### any_value +__Args__: + + * `expression`: an [expression](#sql-expressions). + +This macro returns some value of the expression from the group. The selected value is non-deterministic (rather than random). + +**Usage**: + +```sql +{{ dbt.any_value("column_name") }} +``` + +**Sample Output (PostgreSQL)**: + +```sql +any(column_name) +``` + +### bool_or +__Args__: + + * `expression`: [attribute name or expression](#sql-expressions). + +This macro returns the logical `OR` of all non-`NULL` expressions -- `true` if at least one record in the group evaluates to `true`. + +**Usage**: + +```sql +{{ dbt.bool_or("boolean_column") }} +{{ dbt.bool_or("integer_column = 3") }} +{{ dbt.bool_or("string_column = 'Pennsylvania'") }} +{{ dbt.bool_or("column1 = column2") }} +``` + +**Sample Output (PostgreSQL)**: + +```sql +bool_or(boolean_column) +bool_or(integer_column = 3) +bool_or(string_column = 'Pennsylvania') +bool_or(column1 = column2) +``` + +### listagg +__Args__: + + * `measure` (required): The [attribute name or expression](#sql-expressions) that determines the values to be concatenated. To only include distinct values add keyword `DISTINCT` to beginning of expression (example: 'DISTINCT column_to_agg'). + * `delimiter_text` (required): Text representing the delimiter to separate concatenated values by. + * `order_by_clause` (optional): An expression (typically one or more column names separated by commas) that determines the order of the concatenated values. + * `limit_num` (optional): Specifies the maximum number of values to be concatenated. + +This macro returns the concatenated input values from a group of rows separated by a specified delimiter. + +**Usage**: + +Note: If there are instances of `delimiter_text` within your `measure`, you cannot include a `limit_num`. + +```sql +{{ dbt.listagg(measure="column_to_agg", delimiter_text="','", order_by_clause="order by order_by_column", limit_num=10) }} +``` + +**Sample Output (PostgreSQL)**: + +```sql +array_to_string( + (array_agg( + column_to_agg + order by order_by_column + ))[1:10], + ',' + ) +``` + +## Cast functions + +### cast_bool_to_text +__Args__: + + * `field`: boolean [attribute name or expression](#sql-expressions). + +This macro casts a boolean value to a string. + +**Usage**: + +```sql +{{ dbt.cast_bool_to_text("boolean_column_name") }} +{{ dbt.cast_bool_to_text("false") }} +{{ dbt.cast_bool_to_text("true") }} +{{ dbt.cast_bool_to_text("0 = 1") }} +{{ dbt.cast_bool_to_text("1 = 1") }} +{{ dbt.cast_bool_to_text("null") }} +``` + +**Sample Output (PostgreSQL)**: + +```sql + cast(boolean_column_name as + varchar +) + + cast(false as + varchar +) + + cast(true as + varchar +) + + cast(0 = 1 as + varchar +) + + cast(1 = 1 as + varchar +) + + cast(null as + varchar +) +``` + +### safe_cast +__Args__: + + * `field`: [attribute name or expression](#sql-expressions). + * `type`: data type to convert to + +For databases that support it, this macro will return `NULL` when the cast fails (instead of raising an error). + +**Usage**: + +```sql +{{ dbt.safe_cast("column_1", api.Column.translate_type("string")) }} +{{ dbt.safe_cast("column_2", api.Column.translate_type("integer")) }} +{{ dbt.safe_cast("'2016-03-09'", api.Column.translate_type("date")) }} +``` + +**Sample Output (PostgreSQL)**: + +```sql + cast(column_1 as TEXT) + cast(column_2 as INT) + cast('2016-03-09' as date) +``` + +## Date and time functions + +### dateadd +__Args__: + + * `datepart`: [date or time part](#date-and-time-parts). + * `interval`: integer count of the `datepart` to add (can be positive or negative) + * `from_date_or_timestamp`: date/time [expression](#sql-expressions). + +This macro adds a time/day interval to the supplied date/timestamp. Note: The `datepart` argument is database-specific. + +**Usage**: + +```sql +{{ dbt.dateadd(datepart="day", interval=1, from_date_or_timestamp="'2016-03-09'") }} +{{ dbt.dateadd(datepart="month", interval=-2, from_date_or_timestamp="'2016-03-09'") }} +``` + +**Sample Output (PostgreSQL)**: + +```sql + '2016-03-09' + ((interval '10 day') * (1)) + '2016-03-09' + ((interval '10 month') * (-2)) +``` + +### datediff +__Args__: + + * `first_date`: date/time [expression](#sql-expressions). + * `second_date`: date/time [expression](#sql-expressions). + * `datepart`: [date or time part](#date-and-time-parts). + +This macro calculates the difference between two dates. + +**Usage**: + +```sql +{{ dbt.datediff("column_1", "column_2", "day") }} +{{ dbt.datediff("column", "'2016-03-09'", "month") }} +{{ dbt.datediff("'2016-03-09'", "column", "year") }} +``` + +**Sample Output (PostgreSQL)**: + +```sql + ((column_2)::date - (column_1)::date) + + ((date_part('year', ('2016-03-09')::date) - date_part('year', (column)::date)) + * 12 + date_part('month', ('2016-03-09')::date) - date_part('month', (column)::date)) + + (date_part('year', (column)::date) - date_part('year', ('2016-03-09')::date)) +``` + +### date_trunc +__Args__: + + * `datepart`: [date or time part](#date-and-time-parts). + * `date`: date/time [expression](#sql-expressions). + +This macro truncates / rounds a timestamp to the first instant for the given [date or time part](#date-and-time-parts). + +**Usage**: + +```sql +{{ dbt.date_trunc("day", "updated_at") }} +{{ dbt.date_trunc("month", "updated_at") }} +{{ dbt.date_trunc("year", "'2016-03-09'") }} +``` + +**Sample Output (PostgreSQL)**: + +```sql +date_trunc('day', updated_at) +date_trunc('month', updated_at) +date_trunc('year', '2016-03-09') +``` + +### last_day +__Args__: + + * `date`: date/time [expression](#sql-expressions). + * `datepart`: [date or time part](#date-and-time-parts). + +This macro gets the last day for a given date and datepart. + +**Usage**: +- The `datepart` argument is database-specific. +- This macro currently only supports dateparts of `month` and `quarter`. + +```sql +{{ dbt.last_day("created_at", "month") }} +{{ dbt.last_day("'2016-03-09'", "year") }} +``` + +**Sample Output (PostgreSQL)**: + +```sql +cast( + date_trunc('month', created_at) + ((interval '10 month') * (1)) + + ((interval '10 day') * (-1)) + as date) + +cast( + date_trunc('year', '2016-03-09') + ((interval '10 year') * (1)) + + ((interval '10 day') * (-1)) + as date) +``` + +## Date and time parts + +Often supported date and time parts (case insensitive): +* `year` +* `quarter` +* `month` +* `week` +* `day` +* `hour` +* `minute` +* `second` +* `millisecond` +* `microsecond` +* `nanosecond` + +This listing is not meant to be exhaustive, and some of these date and time parts may not be supported for particular adapters. +Some macros may not support all date and time parts. Some adapters may support more or less precision. + +## SQL expressions + +A SQL expression may take forms like the following: +- function +- column name +- date literal +- string literal +- <other data type> literal (number, etc) +- `NULL` + +Example: +Suppose there is an `orders` table with a column named `order_date`. The following shows 3 different types of expressions: +```sql +select + date_trunc(month, order_date) as expression_function, + order_date as expression_column_name, + '2016-03-09' as expression_date_literal, + 'Pennsylvania' as expression_string_literal, + 3 as expression_number_literal, + NULL as expression_null, +from orders +``` + +Note that the string literal example includes single quotes. (Note: the string literal character may vary per database. For this example, we suppose a single quote.) To refer to a SQL string literal in Jinja, surrounding double quotes are required. + +So within Jinja, the string values would be: +- `"date_trunc(month, order_date)"` +- `"order_date"` +- `"'2016-03-09'"` +- `"'Pennsylvania'"` +- `"NULL"` diff --git a/website/docs/reference/dbt-jinja-functions/dbt-project-yml-context.md b/website/docs/reference/dbt-jinja-functions/dbt-project-yml-context.md index 2050d137ce8..71d0ce67628 100644 --- a/website/docs/reference/dbt-jinja-functions/dbt-project-yml-context.md +++ b/website/docs/reference/dbt-jinja-functions/dbt-project-yml-context.md @@ -17,7 +17,7 @@ and `snapshots:` keys in the `dbt_project.yml` file. **Available context variables:** - [target](target) - [env_var](env_var) -- [vars](var) (_Note: only variables defined with `--vars` are availabe_) +- [vars](var) (_Note: only variables defined with `--vars` are available_) - [builtins](builtins) - [dbt_version](dbt_version) diff --git a/website/docs/reference/dbt-jinja-functions/dispatch.md b/website/docs/reference/dbt-jinja-functions/dispatch.md index 2a382f4beb3..f6fde6d7a64 100644 --- a/website/docs/reference/dbt-jinja-functions/dispatch.md +++ b/website/docs/reference/dbt-jinja-functions/dispatch.md @@ -12,7 +12,7 @@ title: "dispatch" -dbt can extend functionality across [its many supported adapters](available-adapters) through a system of [multiple dispatch](https://en.wikipedia.org/wiki/Multiple_dispatch). Because SQL syntax, data types, and DDL/DML support vary across adapters, dbt can define and call generic functional macros, and then "dispatch" that macro to the appropriate implementation for the current adapter. +dbt can extend functionality across [Supported Data Platforms](supported-data-platforms) through a system of [multiple dispatch](https://en.wikipedia.org/wiki/Multiple_dispatch). Because SQL syntax, data types, and / support vary across adapters, dbt can define and call generic functional macros, and then "dispatch" that macro to the appropriate implementation for the current adapter. ## Syntax @@ -83,7 +83,7 @@ Below that macro, I've defined three possible implementations of the `concat` ma ### A more complex example -I found an existing implementation of the `concat` macro in the dbt-utils package. However, I want to override its implementation of the `concat` macro on Redshift in particular. In all other cases—including the default implementation—I'm perfectly happy falling back to the implementations defined in [`dbt_utils.concat`](https://github.com/dbt-labs/dbt-utils/blob/master/macros/cross_db_utils/concat.sql). +I found an existing implementation of the `concat` macro in the dbt-utils package. However, I want to override its implementation of the `concat` macro on Redshift in particular. In all other cases—including the default implementation—I'm perfectly happy falling back to the implementations defined in [`dbt_utils.concat`](https://github.com/dbt-labs/dbt-utils/blob/main/macros/cross_db_utils/concat.sql). @@ -154,7 +154,7 @@ As a package maintainer, this functionality enables users of my package to exten I maintain an internal utility package at my organization, named `my_org_dbt_helpers`. I use this package to reimplement built-in dbt macros on behalf of all my dbt-using colleagues, who work across a number of dbt projects. -My package can define custom versions of any dispatched global macro I choose, from `generate_schema_name` to `test_unique`. I can define a new default version of that macro (e.g. `default__generate_schema_name`), or custom versions for specific data warehouse adapters (e.g. `spark__generate_schema_name`). +My package can define custom versions of any dispatched global macro I choose, from `generate_schema_name` to `test_unique`. I can define a new default version of that macro (e.g. `default__generate_schema_name`), or custom versions for specific adapters (e.g. `spark__generate_schema_name`). Each root project installing my package simply needs to include the [project-level `dispatch` config](project-configs/dispatch-config) that searches my package ahead of `dbt` for the `dbt` global namespace: @@ -249,4 +249,4 @@ In rare cases, the child adapter may prefer the default implementation to its pa ## FAQs - + diff --git a/website/docs/reference/dbt-jinja-functions/env_var.md b/website/docs/reference/dbt-jinja-functions/env_var.md index b72936d115a..a105ecb2e22 100644 --- a/website/docs/reference/dbt-jinja-functions/env_var.md +++ b/website/docs/reference/dbt-jinja-functions/env_var.md @@ -59,11 +59,13 @@ models: For certain configurations, you can use "secret" env vars. Any env var named with the prefix `DBT_ENV_SECRET_` will be: - Available for use in `profiles.yml` + `packages.yml`, via the same `env_var()` function -- Disallowed everywhere else, including `dbt_project.yml` and model SQL, to prevent accidentally writing these secret values to the data warehouse or metadata artifacts +- Disallowed everywhere else, including `dbt_project.yml` and model SQL, to prevent accidentally writing these secret values to the or metadata artifacts - Scrubbed from dbt logs and replaced with `*****`, any time its value appears in those logs (even if the env var was not called directly) The primary use case of secret env vars is git access tokens for [private packages](package-management#private-packages). +**Note:** When dbt is loading profile credentials and package configuration, secret env vars will be replaced with the string value of the environment variable. You cannot modify secrets using Jinja filters, including type-casting filters such as [`as_number`](as_number) or [`as_bool`](as_bool), or pass them as arguments into other Jinja macros. + ### Custom metadata @@ -74,6 +76,26 @@ The primary use case of secret env vars is git access tokens for [private packag Any env var named with the prefix `DBT_ENV_CUSTOM_ENV_` will be included in [dbt artifacts](dbt-artifacts#common-metadata), in a `metadata.env` dictionary, with its prefix-stripped name as its key. + + +A dictionary of these prefixed env vars will also be available in a `dbt_metadata_envs` context variable: +```sql +-- {{ dbt_metadata_envs }} + +select 1 as id +``` +```shell +$ DBT_ENV_CUSTOM_ENV_MY_FAVORITE_COLOR=indigo DBT_ENV_CUSTOM_ENV_MY_FAVORITE_NUMBER=6 dbt compile +``` +Compiles to: +```sql +-- {'MY_FAVORITE_COLOR': 'indigo', 'DBT_ENV_CUSTOM_ENV_MY_FAVORITE_NUMBER': '6'} + +select 1 as id +``` + + + :::info dbt Cloud Usage If you are using dbt Cloud, you must adhere to the naming conventions for environment variables. Environment variables in dbt Cloud must be prefixed with `DBT_` (including `DBT_ENV_CUSTOM_ENV_` or `DBT_ENV_SECRET_`). Environment variables keys are uppercased and case sensitive. When referencing `{{env_var('DBT_KEY')}}` in your project's code, the key must match exactly the variable defined in dbt Cloud's UI. ::: diff --git a/website/docs/reference/dbt-jinja-functions/exceptions.md b/website/docs/reference/dbt-jinja-functions/exceptions.md index cc649e08ccf..77cfacb8309 100644 --- a/website/docs/reference/dbt-jinja-functions/exceptions.md +++ b/website/docs/reference/dbt-jinja-functions/exceptions.md @@ -7,7 +7,7 @@ The `exceptions` namespace can be used to raise warnings and errors in dbt users ## raise_compiler_error -The `exceptions.raise_compiler_error` method will raise a compiler error with the provided message. This is typically only useful in macros or materializations when invalid arguments are provided by the calling model. Note that throwing an exception will cause a model to fail, so please use this variable with care! +The `exceptions.raise_compiler_error` method will raise a compiler error with the provided message. This is typically only useful in macros or materializations when invalid arguments are provided by the calling model. Note that throwing an exception will cause a model to fail, so please use this variable with care! __Example usage__: diff --git a/website/docs/reference/dbt-jinja-functions/execute.md b/website/docs/reference/dbt-jinja-functions/execute.md index b6e4a510429..e3febefad3a 100644 --- a/website/docs/reference/dbt-jinja-functions/execute.md +++ b/website/docs/reference/dbt-jinja-functions/execute.md @@ -38,7 +38,7 @@ Compilation Error in model order_payment_methods (models/order_payment_methods.s 'None' has no attribute 'table' ``` -This is because Line #11 assumes that a table has been returned, when, during the parse phase, this query hasn't been run. +This is because Line #11 assumes that a has been returned, when, during the parse phase, this query hasn't been run. To work around this, wrap any problematic Jinja in an `{% if execute %}` statement: diff --git a/website/docs/reference/dbt-jinja-functions/flags.md b/website/docs/reference/dbt-jinja-functions/flags.md index 79a911d4068..ba393378269 100644 --- a/website/docs/reference/dbt-jinja-functions/flags.md +++ b/website/docs/reference/dbt-jinja-functions/flags.md @@ -22,7 +22,29 @@ drop table ... The list of available flags is defined in the [`flags` module](https://github.com/dbt-labs/dbt-core/blob/HEAD/core/dbt/flags.py) within `dbt-core`. Recommended use cases include: -- different materialization logic based on "run modes," such as `flags.FULL_REFRESH` and `flags.STORE_FAILURES` +- different logic based on "run modes," such as `flags.FULL_REFRESH` and `flags.STORE_FAILURES` - running hooks conditionally based on the current command / task type, via `flags.WHICH` **Note:** It is _not_ recommended to use flags as an input to parse-time configurations, properties, or dependencies (`ref` + `source`). Flags are likely to change in every invocation of dbt, and their parsed values will become stale (and yield incorrect results) in subsequent invocations that have partial parsing enabled. For more details, see [the docs on parsing](parsing). + + + +### invocation_args_dict + +For the full set of information passed from the CLI—subcommand, flags, arguments—you can use `invocation_args_dict`. This is equivalent to the `args` dictionary in [`run_results.json`](run-results-json). + +```sql +-- models/my_model.sql +-- {{ invocation_args_dict }} +-- {{ dbt_metadata_envs }} + +select 1 as id +``` +Compiles to: +```sql +-- {'write_json': True, 'use_colors': True, 'printer_width': 80, 'version_check': True, 'partial_parse': True, 'static_parser': True, 'profiles_dir': '/Users/.../.dbt', 'send_anonymous_usage_stats': False, 'event_buffer_size': 100000, 'quiet': False, 'no_print': False, 'parse_only': False, 'which': 'compile', 'rpc_method': 'compile', 'indirect_selection': 'eager'} + +select 1 as id +``` + + diff --git a/website/docs/reference/dbt-jinja-functions/modules.md b/website/docs/reference/dbt-jinja-functions/modules.md index 6a188ff3008..baa8da80f13 100644 --- a/website/docs/reference/dbt-jinja-functions/modules.md +++ b/website/docs/reference/dbt-jinja-functions/modules.md @@ -48,3 +48,46 @@ This variable is a pointer to the Python [re](https://docs.python.org/3/library/ ) -%} {% endif %} ``` + + + +## itertools +This variable is a pointer to the Python [itertools](https://docs.python.org/3/library/itertools.html) module, which includes useful functions for working with iterators (loops, lists, and the like). + +The supported functions are: +- `count` +- `cycle` +- `repeat` +- `accumulate` +- `chain` +- `compress` +- `islice` +- `starmap` +- `tee` +- `zip_longest` +- `product` +- `permutations` +- `combinations` +- `combinations_with_replacement` + +**Usage** + +``` +{%- set A = [1, 2] -%} +{%- set B = ['x', 'y', 'z'] -%} +{%- set AB_cartesian = modules.itertools.product(A, B) -%} + +{%- for item in AB_cartesian %} + {{ item }} +{%- endfor -%} +``` +``` + (1, 'x') + (1, 'y') + (1, 'z') + (2, 'x') + (2, 'y') + (2, 'z') +``` + + diff --git a/website/docs/reference/dbt-jinja-functions/print.md b/website/docs/reference/dbt-jinja-functions/print.md new file mode 100644 index 00000000000..25ced86da62 --- /dev/null +++ b/website/docs/reference/dbt-jinja-functions/print.md @@ -0,0 +1,18 @@ +--- +title: "print" +id: "print" +--- + +## About print + +Use the `print()` function when you want to print messages to both the log file and standard output (stdout). + +When used in conjunction with the `QUIET` global config, which suppresses non-error logs, you will only see error logs and the print messages in stdout. For more information, see [Global configs](/reference/global-configs). + +## Example + +```sql + {% macro some_macro(arg1, arg2) %} + {{ print("Running some_macro: " ~ arg1 ~ ", " ~ arg2) }} + {% endmacro %}" +``` diff --git a/website/docs/reference/dbt-jinja-functions/ref.md b/website/docs/reference/dbt-jinja-functions/ref.md index d540fc37742..9be20d0a226 100644 --- a/website/docs/reference/dbt-jinja-functions/ref.md +++ b/website/docs/reference/dbt-jinja-functions/ref.md @@ -45,6 +45,8 @@ There is also a two-argument variant of the `ref` function. With this variant, y select * from {{ ref('package_name', 'model_name') }} ``` +**Note:** The `package_name` should only include the name of the package, not the maintainer. For example, if you use the [`fivetran/stripe`](https://hub.getdbt.com/fivetran/stripe/latest/) package, type `stripe` in that argument, and not `fivetran/stripe`. + ### Forcing Dependencies In normal usage, dbt knows the proper order to run all models based on the usage of the `ref` function. There are cases though where dbt doesn't know when a model should be run. An example of this is when a model only references a macro. In that case, dbt thinks the model can run first because no explicit references are made at compilation time. To address this, you can use a SQL comment along with the `ref` function — dbt will understand the dependency, and the compiled query will still be valid: diff --git a/website/docs/reference/dbt-jinja-functions/run_query.md b/website/docs/reference/dbt-jinja-functions/run_query.md index ca27fc3bb74..e23a836fe1f 100644 --- a/website/docs/reference/dbt-jinja-functions/run_query.md +++ b/website/docs/reference/dbt-jinja-functions/run_query.md @@ -8,18 +8,14 @@ The `run_query` macro provides a convenient way to run queries and fetch their r __Args__: * `sql`: The SQL query to execute -Returns a [Table](https://agate.readthedocs.io/page/api/table.html) object with the result of the query. If the specified query does not return results (eg. a DDL, DML, or maintenance query), then the return value will be `none`. +Returns a [Table](https://agate.readthedocs.io/page/api/table.html) object with the result of the query. If the specified query does not return results (eg. a , , or maintenance query), then the return value will be `none`. **Note:** The `run_query` macro will not begin a transaction automatically - if you wish to run your query inside of a transaction, please use `begin` and `commit ` statements as appropriate. - :::info Using run_query for the first time? - -Check out the tutorial on [using Jinja](using-jinja#dynamically-retrieve-the-list-of-payment-methods) for an example of working with the results of the `run_query` macro! - +Check out the section of the Getting Started guide on [using Jinja](/guides/getting-started/learning-more/using-jinja#dynamically-retrieve-the-list-of-payment-methods) for an example of working with the results of the `run_query` macro! ::: - **Example Usage:** diff --git a/website/docs/reference/dbt-jinja-functions/schema.md b/website/docs/reference/dbt-jinja-functions/schema.md index 17b7c72cc02..c49e5616798 100644 --- a/website/docs/reference/dbt-jinja-functions/schema.md +++ b/website/docs/reference/dbt-jinja-functions/schema.md @@ -3,4 +3,4 @@ title: "schema" id: "schema" --- -The schema that the model is configured to be materialized in. This is typically the same as `model['schema']`. \ No newline at end of file +The schema that the model is configured to be materialized in. This is typically the same as `model['schema']`. diff --git a/website/docs/reference/dbt-jinja-functions/selected_resources.md b/website/docs/reference/dbt-jinja-functions/selected_resources.md new file mode 100644 index 00000000000..f359a88553c --- /dev/null +++ b/website/docs/reference/dbt-jinja-functions/selected_resources.md @@ -0,0 +1,69 @@ +--- +title: "selected_resources" +id: "selected_resources" +--- + +The `selected_resources` context variable contains a list of all the _nodes_ +selected by the current dbt command. + +Currently, this variable is not accessible when using the command `run-operation`. + +:::danger Warning! + +dbt actively builds the graph during the [parsing phase](execute) of +running dbt projects, so the `selected_resources` context variable will be +empty during parsing. Please read the information on this page to effectively use this variable. + +::: + +### Usage + +The `selected_resources` context variable is a list of all the resources selected by +the current dbt command selector. Its value depends on the usage of parameters like +`--select`, `--exclude` and `--selector`. + +For a given run it will look like: + +```json +["model.my_project.model1", "model.my_project.model2", "snapshot.my_project.my_snapshot"] +``` + +It can be used in macros in a `pre-hook`, `post-hook`, `on-run-start` or `on-run-end` +to evaluate what nodes are selected and trigger different logic whether a particular node +is selected or not. + + + +```sql + +/* + Check if a given model is selected and trigger a different action, depending on the result +*/ + +{% if execute %} + {% if 'model.my_project.model1' in selected_resources %} + + {% do log("model1 is included based on the current selection", info=true) %} + + {% else %} + + {% do log("model1 is not included based on the current selection", info=true) %} + + {% endfor %} +{% endif %} + +/* + Example output when running the code in on-run-start + when doing `dbt build`, including all nodels +--------------------------------------------------------------- + model1 is included based on the current selection + + + Example output when running the code in on-run-start + when doing `dbt run --select model2` +--------------------------------------------------------------- + model1 is not included based on the current selection +*/ +``` + + \ No newline at end of file diff --git a/website/docs/reference/dbt-jinja-functions/set.md b/website/docs/reference/dbt-jinja-functions/set.md new file mode 100644 index 00000000000..d78f5777828 --- /dev/null +++ b/website/docs/reference/dbt-jinja-functions/set.md @@ -0,0 +1,50 @@ +--- +title: "set" +id: "set" +--- + +### set + +_Not to be confused with the `{% set foo = "bar" ... %}` expression in Jinja!_ + +The `set` context method can be used to convert any iterable to a sequence of iterable elements that are unique (a set). + +__Args__: +- `value`: The iterable to convert (e.g. a list) +- `default`: A default value to return if the `value` argument is not a valid iterable + +### Usage + +``` +{% set my_list = [1, 2, 2, 3] %} +{% set my_set = set(my_list) %} +{% do log(my_set) %} {# {1, 2, 3} #} +``` + +``` +{% set my_invalid_iterable = 1234 %} +{% set my_set = set(my_invalid_iterable) %} +{% do log(my_set) %} {# None #} +``` + +### set_strict + +The `set_strict` context method can be used to convert any iterable to a sequence of iterable elements that are unique (a set). The difference to the `set` context method is that the `set_strict` method will raise an exception on a `TypeError`, if the provided value is not a valid iterable and cannot be converted to a set. + +__Args__: +- `value`: The iterable to convert (e.g. a list) + +``` +{% set my_list = [1, 2, 2, 3] %} +{% set my_set = set(my_list) %} +{% do log(my_set) %} {# {1, 2, 3} #} +``` + +``` +{% set my_invalid_iterable = 1234 %} +{% set my_set = set_strict(my_invalid_iterable) %} +{% do log(my_set) %} + +Compilation Error in ... (...) + 'int' object is not iterable +``` diff --git a/website/docs/reference/dbt-jinja-functions/statement-blocks.md b/website/docs/reference/dbt-jinja-functions/statement-blocks.md index e2eade2fa3a..c6de74a0225 100644 --- a/website/docs/reference/dbt-jinja-functions/statement-blocks.md +++ b/website/docs/reference/dbt-jinja-functions/statement-blocks.md @@ -3,7 +3,7 @@ title: "statement blocks" id: "statement-blocks" --- -`statement`s are sql queries that hit the database and return results to your Jinja context. Here’s an example of a `statement` which gets all of the states from a users table. +`statement`s are sql queries that hit the database and return results to your Jinja context. Here’s an example of a `statement` which gets all of the states from a users . diff --git a/website/docs/reference/dbt-jinja-functions/target.md b/website/docs/reference/dbt-jinja-functions/target.md index 8c3ce3422f8..dd8d567c8b0 100644 --- a/website/docs/reference/dbt-jinja-functions/target.md +++ b/website/docs/reference/dbt-jinja-functions/target.md @@ -8,7 +8,7 @@ id: "target" * **dbt CLI:** These values are based on the target defined in your [`profiles.yml` file](reference/profiles.yml.md) * **dbt Cloud Scheduler:** * `target.name` is defined per job as described [here](cloud-setting-a-custom-target-name). - * For all other attributes, the values are defined by the deployment connection. To check any of these values, head to `Environments` (via the hamburger menu), select the relevant deployment environment, and select settings. + * For all other attributes, the values are defined by the deployment connection. To check these values, click **Deploy** from the upper left and select **Environments**. Then, select the relevant deployment environment, and click **Settings**. * **dbt Cloud IDE:** The values are defined by your connection and credentials. To check any of these values, head to your account (via your profile image in the top right hand corner), and select the project under "Credentials". @@ -20,7 +20,7 @@ Some configs are shared between all adapters, while others are adapter-specific. | `target.profile_name` | jaffle_shop | The name of the active profile | | `target.name` | dev | Name of the active target | | `target.schema` | dbt_alice | Name of the dbt schema (or, dataset on BigQuery) | -| `target.type` | postgres | The active adapter being used. One of "postgres", "snowflake", "bigquery", "redshift" | +| `target.type` | postgres | The active adapter being used. One of "postgres", "snowflake", "bigquery", "redshift", "databricks" | | `target.threads` | 4 | The number of threads in use by dbt | diff --git a/website/docs/reference/dbt-jinja-functions/this.md b/website/docs/reference/dbt-jinja-functions/this.md index a7f07f631be..04ee45673c0 100644 --- a/website/docs/reference/dbt-jinja-functions/this.md +++ b/website/docs/reference/dbt-jinja-functions/this.md @@ -13,6 +13,10 @@ id: "this" ## Examples + + + + ### Grant permissions on a model in a post-hook @@ -26,6 +30,8 @@ models: + + ### Configuring incremental models diff --git a/website/docs/reference/dbt-jinja-functions/tojson.md b/website/docs/reference/dbt-jinja-functions/tojson.md index de6f34a8028..7cf44f870dd 100644 --- a/website/docs/reference/dbt-jinja-functions/tojson.md +++ b/website/docs/reference/dbt-jinja-functions/tojson.md @@ -3,7 +3,7 @@ title: "tojson" id: "tojson" --- -The `tojson` context method can be used to serialize a Python object primitive, eg. a `dict` or `list` to a json string. +The `tojson` context method can be used to serialize a Python object primitive, eg. a `dict` or `list` to a JSON string. __Args__: * `value`: The value serialize to json (required) @@ -15,4 +15,4 @@ __Args__: {% set my_json_string = tojson(my_dict) %} {% do log(my_json_string) %} -``` \ No newline at end of file +``` diff --git a/website/docs/reference/dbt-jinja-functions/zip.md b/website/docs/reference/dbt-jinja-functions/zip.md new file mode 100644 index 00000000000..78c92e18925 --- /dev/null +++ b/website/docs/reference/dbt-jinja-functions/zip.md @@ -0,0 +1,53 @@ +--- +title: "zip" +id: "zip" +--- + +### zip + +The `zip` context method can be used to used to return an iterator of tuples, where the i-th tuple contains the i-th element from each of the argument iterables. ([Python docs](https://docs.python.org/3/library/functions.html#zip)) + :param + :param + +__Args__: +- `*args`: Any number of iterables +- `default`: A default value to return if `*args` is not iterable + +### Usage + +``` +{% set my_list_a = [1, 2] %} +{% set my_list_b = ['alice', 'bob'] %} +{% set my_zip = zip(my_list_a, my_list_b) | list %} +{% do log(my_zip) %} {# [(1, 'alice'), (2, 'bob')] #} +``` + +``` +{% set my_list_a = 12 %} +{% set my_list_b = ['alice', 'bob'] %} +{% set my_zip = zip(my_list_a, my_list_b, default = []) | list %} +{% do log(my_zip) %} {# [] #} +``` + +### zip_strict + +The `zip_strict` context method can be used to used to return an iterator of tuples, just like `zip`. The difference to the `zip` context method is that the `zip_strict` method will raise an exception on a `TypeError`, if one of the provided values is not a valid iterable. + +__Args__: +- `value`: The iterable to convert (e.g. a list) + +``` +{% set my_list_a = [1, 2] %} +{% set my_list_b = ['alice', 'bob'] %} +{% set my_zip = zip_strict(my_list_a, my_list_b) | list %} +{% do log(my_zip) %} {# [(1, 'alice'), (2, 'bob')] #} +``` + +``` +{% set my_list_a = 12 %} +{% set my_list_b = ['alice', 'bob'] %} +{% set my_zip = zip_strict(my_list_a, my_list_b) %} + +Compilation Error in ... (...) + 'int' object is not iterable +``` diff --git a/website/docs/reference/events-logging.md b/website/docs/reference/events-logging.md index 26c008539f6..679d3a8f9cc 100644 --- a/website/docs/reference/events-logging.md +++ b/website/docs/reference/events-logging.md @@ -34,19 +34,19 @@ With every task that dbt performs, it generates events. It records those events When `json` [log formatting](global-configs#log-formatting) is enabled, dbt will output produce rich, structured log information which can be piped into monitoring tools for analysis, or to power applications with dbt metadata in real time. -Each log line will have the following JSON properties: +Each log line will have the following properties: | Field | Description | |-------------|---------------| | `code` | A unique identifier for each event type | -| `data` | A dictionary containing programmatically accessible information about the log line. The contents of this ctionary vary based on the event type which generated this log message. | +| `data` | A dictionary containing programmatically accessible information about the log line. The contents of this dictionary vary based on the event type which generated this log message. | | [`invocation_id`](invocation_id) | A unique identifier for this invocation of dbt | | `level` | A string representation of the log level (`debug`, `info`, `warn`, `error`) | | `log_version` | Integer indicating version | -| `msg` | The human-friendly log message. **Note**: This message is not intended for machine consumption. Log messages are bject to change in future versions of dbt, and those changes may or may not coincide with a change in `log_version`. | +| `msg` | The human-friendly log message. **Note**: This message is not intended for machine consumption. Log messages are subject to change in future versions of dbt, and those changes may or may not coincide with a change in `log_version`. | | `node_info` | If applicable, a dictionary of human- and machine-friendly information about a currently running resource | | `pid` | The process ID for the running dbt invocation which produced this log message | -| `thread_name` | The thread in which the log message was produced, helpful for tracking queries when dbt is run with ltiple threads | +| `thread_name` | The thread in which the log message was produced, helpful for tracking queries when dbt is run with multiple threads | | `ts` | When the log line was printed | | `type` | Always `log_line` | diff --git a/website/docs/reference/exit-codes.md b/website/docs/reference/exit-codes.md index 5ae643cf3e1..8e2667b56c1 100644 --- a/website/docs/reference/exit-codes.md +++ b/website/docs/reference/exit-codes.md @@ -11,4 +11,4 @@ When dbt exits, it will return an exit code of either 0, 1, or 2. | 1 | The dbt invocation completed with at least one handled error (eg. model syntax error, bad permissions, etc). The run was completed, but some models may have been skipped. | | 2 | The dbt invocation completed with an unhandled error (eg. ctrl-c, network interruption, etc). | -While these exit codes may change in the future, a zero exit code will always imply success whereas a nonzero exit code will always imply failure. \ No newline at end of file +While these exit codes may change in the future, a zero exit code will always imply success whereas a nonzero exit code will always imply failure. diff --git a/website/docs/reference/exposure-properties.md b/website/docs/reference/exposure-properties.md index 6593caf3b9e..cee5271ac26 100644 --- a/website/docs/reference/exposure-properties.md +++ b/website/docs/reference/exposure-properties.md @@ -17,13 +17,19 @@ Exposures are defined in `.yml` files nested under an `exposures:` key. You may You can name these files `whatever_you_want.yml`, and nest them arbitrarily deeply in subfolders within the `models/` directory. + + +Exposure names must contain only letters, numbers, and underscores (no spaces or special characters). For a short human-friendly name with title casing, spaces, and special characters, use the `label` property. + + + ```yml version: 2 exposures: - - name: + - name: [description](description): type: {dashboard, notebook, analysis, ml, application} url: @@ -38,6 +44,11 @@ exposures: - ref('model') - ref('seed') - source('name', 'table') + + # added in dbt Core v1.3 + label: "Human-Friendly Name for this Exposure!" + [config](resource-properties/config): + enabled: true | false - name: ... # declare properties of additional exposures ``` @@ -52,6 +63,7 @@ exposures: exposures: - name: weekly_jaffle_metrics + label: Jaffles by the Week # optional, new in dbt Core v1.3 type: dashboard # required maturity: high # optional url: https://bi.tool/dashboards/1 # optional diff --git a/website/docs/reference/global-configs.md b/website/docs/reference/global-configs.md index 4c15d0b54a2..eaf2ef1785d 100644 --- a/website/docs/reference/global-configs.md +++ b/website/docs/reference/global-configs.md @@ -3,17 +3,15 @@ title: "Global Configs" id: "global-configs" --- -### About Global Configs +## About Global Configs -Global configs enable you to fine-tune how dbt runs projects on your machine—whether your personal laptop, an orchestration tool running remotely, or (in some cases) dbt Cloud. They differ from [project configs](reference/dbt_project.yml) and [resource configs](reference/configs-and-properties), which tell dbt _what_ to run. +Global configs enable you to fine-tune _how_ dbt runs projects on your machine—whether your personal laptop, an orchestration tool running remotely, or (in some cases) dbt Cloud. In general, they differ from most [project configs](reference/dbt_project.yml) and [resource configs](reference/configs-and-properties), which tell dbt _what_ to run. -Global configs control things like the visual output of logs, the manner in which dbt parses your project, and what to do when dbt finds a version mismatch or a failing model. +Global configs control things like the visual output of logs, the manner in which dbt parses your project, and what to do when dbt finds a version mismatch or a failing model. These configs are "global" because they are available for all dbt commands, and because they can be set for all projects running on the same machine or in the same environment. -These configs are "global" because they are available for all dbt commands, and because they apply across all projects run on the same machine. +Starting in v1.0, you can set global configs in three places. When all three are set, command line flags take precedence, then environment variables, and last yaml configs (usually `profiles.yml`). -Starting in v1.0, you can set global configs in three places. When all three are set, command line flags take precedence, then environment variables, and last profile configs. - -#### Command line flags +## Command line flags Command line (CLI) flags immediately follow `dbt` and precede your subcommand. When set, CLI flags override environment variables and profile configs. @@ -73,7 +71,7 @@ $ dbt --no-version-check run -#### Environment variables +## Environment variables Environment variables contain a `DBT_` prefix @@ -88,9 +86,9 @@ $ dbt run -#### Profile (or user) configurations +## Yaml configurations -You can set profile (or user) configurations in the `config:` block of `profiles.yml`. You would use the profile config to set defaults for all projects running on your local machine. +For most global configurations, you can set "user profile" configurations in the `config:` block of `profiles.yml`. This style of configuration sets default values for all projects using this profile directory—usually, all projects running on your local machine. @@ -103,46 +101,60 @@ config: -## Failing fast + -Supply the `-x` or `--fail-fast` flag to `dbt run` to make dbt exit immediately if a single resource fails to build. If other models are in-progress when the first model fails, then dbt will terminate the connections for these still-running models. +The exception: Some global configurations are actually set in `dbt_project.yml`, instead of `profiles.yml`, because they control where dbt places logs and artifacts. Those file paths are always relative to the location of `dbt_project.yml`. For more details, see ["Log and target paths"](#log-and-target-paths) below. -For example, you can select four models to run, but if a failure occurs in the first model, the failure will prevent other models from running: + + + + +### Cache database objects for selected resource + +:::caution Experimental config flag +This should be considered an _unstable_ config flag because it is experimental and subject to change. We reserve the right to make breaking changes to this config flag. +::: + +At the start of runs, dbt caches metadata about all the objects in all the schemas where it might materialize resources (such as models). By default, dbt caches all schemas related to the project. When this config is enabled, dbt will only cache schemas related to selected resources for the current run. This can offer significant speed improvements when running a small subset of a large project. + +For example, to improve speed and performance while focused on developing Salesforce models, which are materialized into their own dedicated schema, you would select those models and pass the `cache-selected-only` flag: ```text -$ dbt -x run --threads 1 -Running with dbt=1.0.0 -Found 4 models, 1 test, 1 snapshot, 2 analyses, 143 macros, 0 operations, 1 seed file, 0 sources -14:47:39 | Concurrency: 1 threads (target='dev') -14:47:39 | -14:47:39 | 1 of 4 START table model test_schema.model_1........... [RUN] -14:47:40 | 1 of 4 ERROR creating table model test_schema.model_1.. [ERROR in 0.06s] -14:47:40 | 2 of 4 START view model test_schema.model_2............ [RUN] -14:47:40 | CANCEL query model.debug.model_2....................... [CANCEL] -14:47:40 | 2 of 4 ERROR creating view model test_schema.model_2... [ERROR in 0.05s] +$ dbt --cache-selected-only run --select salesforce -Database Error in model model_1 (models/model_1.sql) - division by zero - compiled SQL at target/run/debug/models/model_1.sql +``` + +The previous example enables you to start working with your salesforce models, and dbt will only cache those models instead of the entire project. + +To set the config in your `profile.yml`: + + +```yaml + +config: + cache_selected_only: true -Encountered an error: -FailFast Error in model model_1 (models/model_1.sql) - Failing early due to test failure or runtime error ``` -## Checking version compatibility + + + + +### Checking version compatibility Projects are recommended to set [dbt version requirements](require-dbt-version), especially if they use features that are newer, or which may break in future versions of dbt Core. By default, if you run a project with an incompatible dbt version, dbt will raise an error. You can use the `VERSION_CHECK` config to disable this check and suppress the error message: + ``` $ dbt --no-version-check run Running with dbt=1.0.0 Found 13 models, 2 tests, 1 archives, 0 analyses, 204 macros, 2 operations.... ``` -## Debug-level logging +### Debug-level logging + The `DEBUG` config redirects dbt's debug logs to standard out. The has the effect of showing debug-level log information in the terminal in addition to the `logs/dbt.log` file. This output is verbose. The `--debug` flag is also available via shorthand as `-d`. @@ -155,11 +167,54 @@ $ dbt --debug run ``` + + +### Experimental parser + +With the `USE_EXPERIMENTAL_PARSER` config, you can opt into the latest and greatest experimental version of the static parser, which is still being sampled for 100% correctness. See [the docs on parsing](parsing#experimental-parser) for more details. + + + +```yaml + +config: + use_experimental_parser: true + +``` + -## Log Formatting +### Failing fast + +Supply the `-x` or `--fail-fast` flag to `dbt run` to make dbt exit immediately if a single resource fails to build. If other models are in-progress when the first model fails, then dbt will terminate the connections for these still-running models. + +For example, you can select four models to run, but if a failure occurs in the first model, the failure will prevent other models from running: + +```text +$ dbt -x run --threads 1 +Running with dbt=1.0.0 +Found 4 models, 1 test, 1 snapshot, 2 analyses, 143 macros, 0 operations, 1 seed file, 0 sources + +14:47:39 | Concurrency: 1 threads (target='dev') +14:47:39 | +14:47:39 | 1 of 4 START table model test_schema.model_1........... [RUN] +14:47:40 | 1 of 4 ERROR creating table model test_schema.model_1.. [ERROR in 0.06s] +14:47:40 | 2 of 4 START view model test_schema.model_2............ [RUN] +14:47:40 | CANCEL query model.debug.model_2....................... [CANCEL] +14:47:40 | 2 of 4 ERROR creating view model test_schema.model_2... [ERROR in 0.05s] + +Database Error in model model_1 (models/model_1.sql) + division by zero + compiled SQL at target/run/debug/models/model_1.sql + +Encountered an error: +FailFast Error in model model_1 (models/model_1.sql) + Failing early due to test failure or runtime error +``` + +### Log Formatting -The `LOG_FORMAT` config specifies how dbt's logs should be formatted. If the value of this config is `json`, dbt will output fully structured logs in JSON format; otherwise, it will output text-formatted logs that are sparser for the CLI and more detailed in `logs/dbt.log`. +The `LOG_FORMAT` config specifies how dbt's logs should be formatted. If the value of this config is `json`, dbt will output fully structured logs in format; otherwise, it will output text-formatted logs that are sparser for the CLI and more detailed in `logs/dbt.log`. @@ -171,6 +226,7 @@ $ dbt --log-format json run :::tip Tip: verbose structured logs Use `json` formatting value in conjunction with the `DEBUG` config to produce rich log information which can be piped into monitoring tools for analysis: + ```text $ dbt --debug --log-format json run ``` @@ -179,61 +235,85 @@ See [structured logging](events-logging#structured-logging) for more details. ::: - -## Writing JSON artifacts - -The `WRITE_JSON` config determines whether dbt writes JSON artifacts (eg. `manifest.json`, `run_results.json`) to the `target/` directory. JSON serialization can be slow, and turning this flag off _might_ make invocations of dbt faster. Alternatively, you might disable this config if you want to perform a dbt operation and avoid overwriting artifacts from a previous run step. - - +### Partial Parsing -```text -$ dbt --no-write-json run -``` +The `PARTIAL_PARSE` config can turn partial parsing on or off in your project. See [the docs on parsing](parsing#partial-parsing) for more details. - + -## Strict +```yaml -As of v1.0, the `-S` or `--strict` flag has been deprecated. +config: + partial_parse: true -## Warnings as Errors +``` -Turning on the `WARN_ERROR` config will convert dbt warnings into errors. Any time dbt would normally warn, it will instead raise an error. Examples include `--select` criteria that selects no resources, deprecations, configurations with no associated models, invalid test configurations, or tests and freshness checks that are configured to return warnings. + ```text -$ dbt --warn-error run -... +dbt --no-partial-parse run ``` -## Partial Parsing -The `PARTIAL_PARSE` config can turn partial parsing on or off in your project. See [the docs on parsing](parsing#partial-parsing) for more details. +### Printer width + +By default, dbt will print out lines padded to 80 characters wide. You can change this setting by adding the following to your `profiles.yml` file: ```yaml - config: - partial_parse: true - + printer_width: 120 ``` - + -```text -$ dbt --no-partial-parse run +### Log and target paths + +By default, dbt will write logs to a directory named `logs/`, and all other artifacts to a directory named `target/`. Both of those directories are located relative to `dbt_project.yml` of the active project—that is, the root directory from which dbt is run. + +Just like other global configs, it is possible to override these values for your environment or invocation by using CLI flags (`--target-path`, `--log-path`) or environment variables (`DBT_TARGET_PATH`, `DBT_LOG_PATH`). + +Unlike the other global configs documented on this page, which can be set in `profiles.yml`, the project paths are configured in `dbt_project.yml`. This is because `profiles.yml` and `dbt_project.yml` are most often located in separate file systems on your machine, and the log and artifact paths are always defined relative to the location of `dbt_project.yml`. + + + +```yaml +[target-path](target-path): "other-target" +[log-path](log-path): "other-logs" ``` -## Static parser + + +### Send anonymous usage stats + +We want to build the best version of dbt possible, and a crucial part of that is understanding how users work with dbt. To this end, we've added some simple event tracking to dbt (using Snowplow). We do not track credentials, raw model contents or model names (we consider these private, and frankly none of our business). + +Usage statistics are fired when dbt is invoked and when models are run. These events contain basic platform information (OS + python version) and metadata such as whether the invocation succeeded, how long it took, an anonymized hash key representing the raw model content, and number of nodes that were run. You can see all the event definitions in [`tracking.py`](https://github.com/dbt-labs/dbt-core/blob/HEAD/core/dbt/tracking.py). + +By default this is turned on – you can opt out of event tracking at any time by adding the following to your `profiles.yml` file: + +```yaml +config: + send_anonymous_usage_stats: False +``` + +You can also use the DO_NOT_TRACK environmental variable to enable or disable sending anonymous data. For more information, see [Environmental variables](/dbt-cloud/using-dbt-cloud/cloud-environment-variables). + +`DO_NOT_TRACK=1` is the same as `DBT_SEND_ANONYMOUS_USAGE_STATS=False` +`DO_NOT_TRACK=0` is the same as `DBT_SEND_ANONYMOUS_USAGE_STATS=True` + +### Static parser + The `STATIC_PARSER` config can enable or disable use of the static parser. See [the docs on parsing](parsing#static-parser) for more details. @@ -247,21 +327,57 @@ config: -## Experimental parser -With the `USE_EXPERIMENTAL_PARSER` config, you can opt into the latest and greatest experimental version of the static parser, which is still being sampled for 100% correctness. See [the docs on parsing](parsing#experimental-parser) for more details. +### Strict + +As of v1.0, the `-S` or `--strict` flag has been deprecated. + + + +### Suppress non-error logs in output + +By default, dbt shows all logs in standard out (stdout). You can use the `QUIET` config to show only error logs in stdout. Logs will still include the output of anything passed to the `print()` macro. For example, you might suppress all but error logs to more easily find and debug a jinja error. ```yaml - config: - use_experimental_parser: true + quiet: true +``` + + + +Supply the `-q` or `--quiet` flag to `dbt run` to show only error logs and suppress non-error logs. + +```text +$ dbt --quiet run +... + +``` + +### Suppress `print()` messages in stdout +By default, dbt includes `print()` messages in standard out (stdout). You can use the `NO_PRINT` config to prevent these messages from showing up in stdout. + + + +```yaml +config: + no_print: true ``` -## Use colors +Supply `--no-print` flag to `dbt run` to suppress `print()` messages from showing in stdout. + +```text +$ dbt --no-print run +... + +``` + + + +### Use colors By default, dbt will colorize the output it prints in your terminal. You can turn this off by adding the following to your `profiles.yml` file: @@ -272,36 +388,34 @@ config: use_colors: False ``` -``` +```text $ dbt --use-colors run $ dbt --no-use-colors run ``` +### Warnings as Errors -## Printer width - -By default, dbt will print out lines padded to 80 characters wide. You can change this setting by adding the following to your `profiles.yml` file: +Turning on the `WARN_ERROR` config will convert dbt warnings into errors. Any time dbt would normally warn, it will instead raise an error. Examples include `--select` criteria that selects no resources, deprecations, configurations with no associated models, invalid test configurations, or tests and freshness checks that are configured to return warnings. - + -```yaml -config: - printer_width: 120 +```text +$ dbt --warn-error run +... ``` -## Send anonymous usage stats +### Writing JSON artifacts -We want to build the best version of dbt possible, and a crucial part of that is understanding how users work with dbt. To this end, we've added some simple event tracking to dbt (using Snowplow). We do not track credentials, model contents or model names (we consider these private, and frankly none of our business). +The `WRITE_JSON` config determines whether dbt writes JSON artifacts (eg. `manifest.json`, `run_results.json`) to the `target/` directory. JSON serialization can be slow, and turning this flag off _might_ make invocations of dbt faster. Alternatively, you might disable this config if you want to perform a dbt operation and avoid overwriting artifacts from a previous run step. -Usage statistics are fired when dbt is invoked and when models are run. These events contain basic platform information (OS + python version). You can see all the event definitions in [`tracking.py`](https://github.com/dbt-labs/dbt-core/blob/HEAD/core/dbt/tracking.py). + -By default this is turned on – you can opt out of event tracking at any time by adding the following to your `profiles.yml` file: -```yaml -config: - send_anonymous_usage_stats: False +```text +dbt --no-write-json run ``` + diff --git a/website/docs/reference/model-configs.md b/website/docs/reference/model-configs.md index a38e43cd0c1..bd3d238e83b 100644 --- a/website/docs/reference/model-configs.md +++ b/website/docs/reference/model-configs.md @@ -108,6 +108,7 @@ models: [+](plus-prefix)[persist_docs](persist_docs): [+](plus-prefix)[full_refresh](full_refresh): [+](plus-prefix)[meta](meta): {} + [+](plus-prefix)[grants](grants): {} ``` @@ -136,7 +137,7 @@ models: [persist_docs](persist_docs): [full_refresh](full_refresh): [meta](meta): {} - + [grants](grants): {} ``` @@ -161,6 +162,7 @@ models: [alias](resource-configs/alias)="", [persist_docs](persist_docs)={}, [meta](meta)={} + [grants](grants)={} ) }} ``` diff --git a/website/docs/reference/node-selection/defer.md b/website/docs/reference/node-selection/defer.md index 68d72cec836..23b7be6ab00 100644 --- a/website/docs/reference/node-selection/defer.md +++ b/website/docs/reference/node-selection/defer.md @@ -9,40 +9,30 @@ title: "Defer" -**N.B.** Deferral is a powerful, complex feature that enables compelling workflows. We reserve the right to change the name and syntax in a future version of dbt to make the behavior clearer and more intuitive. For details, see [dbt#2968](https://github.com/fishtown-analytics/dbt/issues/2968). +**N.B.** Deferral is a powerful, complex feature that enables compelling workflows. We reserve the right to change the name and syntax in a future version of dbt to make the behavior clearer and more intuitive. For details, see [dbt#2968](https://github.com/dbt-labs/dbt-core/issues/2968). Defer is a powerful feature that makes it possible to run a subset of models or tests in a [sandbox environment](managing-environments), without having to first build their upstream parents. This can save time and computational resources when you want to test a small number of models in a large project. Defer requires that a manifest from a previous dbt invocation be passed to the `--state` flag or env var. Together with the `state:` selection method, these features enable "Slim CI". Read more about [state](understanding-state). - ### Usage - - - - ```shell - $ dbt run --select [...] --defer --state path/to/artifacts - $ dbt test --select [...] --defer --state path/to/artifacts - ``` + - - +```shell +$ dbt run --select [...] --defer --state path/to/artifacts +$ dbt test --select [...] --defer --state path/to/artifacts +``` - ```shell - $ dbt run --models [...] --defer --state path/to/artifacts - $ dbt test --models [...] --defer --state path/to/artifacts - ``` + - - + +```shell +$ dbt run --models [...] --defer --state path/to/artifacts +$ dbt test --models [...] --defer --state path/to/artifacts +``` + When the `--defer` flag is provided, dbt will resolve `ref` calls differently depending on two criteria: 1. Is the referenced node included in the model selection criteria of the current run? diff --git a/website/docs/reference/node-selection/exclude.md b/website/docs/reference/node-selection/exclude.md index 1ef1907a1e6..4fbc1a6e79e 100644 --- a/website/docs/reference/node-selection/exclude.md +++ b/website/docs/reference/node-selection/exclude.md @@ -5,29 +5,20 @@ title: "Exclude" ### Excluding models dbt provides an `--exclude` flag with the same semantics as `--select`. Models specified with the `--exclude` flag will be removed from the set of models selected with `--select`. - - + - ```bash - $ dbt run --select my_package.*+ --exclude my_package.a_big_model+ - ``` - - - +```bash +$ dbt run --select my_package.*+ --exclude my_package.a_big_model+ +``` - ```bash - $ dbt run --models my_package.*+ --exclude my_package.a_big_model+ - ``` + + - - +```bash +$ dbt run --models my_package.*+ --exclude my_package.a_big_model+ +``` + Exclude a specific resource by its name or lineage: diff --git a/website/docs/reference/node-selection/graph-operators.md b/website/docs/reference/node-selection/graph-operators.md index bac95aa1c0b..31318b1379a 100644 --- a/website/docs/reference/node-selection/graph-operators.md +++ b/website/docs/reference/node-selection/graph-operators.md @@ -5,23 +5,16 @@ title: "Graph operators" ### The "plus" operator If placed at the front of the model selector, `+` will select all parents of the selected model. If placed at the end of the string, `+` will select all children of the selected model. - - + - ```bash + ```bash $ dbt run --select my_model+ # select my_model and all children $ dbt run --select +my_model # select my_model and all parents $ dbt run --select +my_model+ # select my_model, and all of its parents and children ``` - - + + ```bash $ dbt run --models my_model+ # select my_model and all children @@ -29,9 +22,7 @@ If placed at the front of the model selector, `+` will select all parents of the $ dbt run --models +my_model+ # select my_model, and all of its parents and children ``` - - - + ### The "n-plus" operator New in v0.18.0 @@ -39,14 +30,7 @@ If placed at the front of the model selector, `+` will select all parents of the You can adjust the behavior of the `+` operator by quantifying the number of edges to step through. - - + ```bash $ dbt run --select my_model+1 # select my_model and its first-degree children @@ -54,8 +38,8 @@ to step through. $ dbt run --select 3+my_model+4 # select my_model, its parents up to the 3rd degree, and its children down to the 4th degree ``` - - + + ```bash $ dbt run --models my_model+1 # select my_model and its first-degree children @@ -63,39 +47,33 @@ to step through. $ dbt run --models 3+my_model+4 # select my_model, its parents up to the 3rd degree, and its children down to the 4th degree ``` - - - + ### The "at" operator The `@` operator is similar to `+`, but will also include _the parents of the children of the selected model_. This is useful in continuous integration environments where you want to build a model and all of its children, but the _parents_ of those children might not exist in the database yet. The selector `@snowplow_web_page_context` will build all three models shown in the diagram below. +```bash +$ dbt run --models @my_model # select my_model, its children, and the parents of its children +``` + ### The "star" operator The `*` operator matches all models within a package or directory. - - + ```bash $ dbt run --select snowplow.* # run all of the models in the snowplow package $ dbt run --select finance.base.* # run all of the models in models/finance/base ``` - - + + ```bash $ dbt run --models snowplow.* # run all of the models in the snowplow package $ dbt run --models finance.base.* # run all of the models in models/finance/base ``` - - + diff --git a/website/docs/reference/node-selection/methods.md b/website/docs/reference/node-selection/methods.md index 00450de075e..90ea7455466 100644 --- a/website/docs/reference/node-selection/methods.md +++ b/website/docs/reference/node-selection/methods.md @@ -8,95 +8,83 @@ syntax `method:value`. ### The "tag" method The `tag:` method is used to select models that match a specified [tag](resource-configs/tags). - - + ```bash $ dbt run --select tag:nightly # run all models with the `nightly` tag ``` - - + + ```bash $ dbt run --models tag:nightly # run all models with the `nightly` tag ``` - - + ### The "source" method The `source` method is used to select models that select from a specified [source](using-sources). Use in conjunction with the `+` operator. - - + ```bash $ dbt run --select source:snowplow+ # run all models that select from Snowplow sources ``` - - + + ```bash $ dbt run --models source:snowplow+ # run all models that select from Snowplow sources ``` - - + ### The "path" method The `path` method is used to select models located at or under a specific path. While the `path` prefix is not explicitly required, it may be used to make selectors unambiguous. - - + + ```bash + # These two selectors are equivalent + dbt run --select path:models/staging/github + dbt run --select models/staging/github -```bash -# These two selectors are equivalent -dbt run --select path:models/staging/github -dbt run --select models/staging/github + # These two selectors are equivalent + dbt run --select path:models/staging/github/stg_issues.sql + dbt run --select models/staging/github/stg_issues.sql + ``` -# These two selectors are equivalent -dbt run --select path:models/staging/github/stg_issues.sql -dbt run --select models/staging/github/stg_issues.sql -``` + + - - + ```bash + # These two selectors are equivalent + dbt run --models path:models/staging/github + dbt run --models models/staging/github + # These two selectors are equivalent + dbt run --models path:models/staging/github/stg_issues.sql + dbt run --models models/staging/github/stg_issues.sql + ``` -```bash -# These two selectors are equivalent -dbt run --models path:models/staging/github -dbt run --models models/staging/github + + + + +### The "file" method +The `file` method can be used to select a model by its filename, including the file extension (`.sql`). -# These two selectors are equivalent -dbt run --models path:models/staging/github/stg_issues.sql -dbt run --models models/staging/github/stg_issues.sql +```bash +# These are equivalent +dbt run --select some_model.sql +dbt run --select some_model ``` - - + + ### The "package" method New in v0.18.0 @@ -105,14 +93,7 @@ The `package` method is used to select models defined within the root project or an installed dbt package. While the `package:` prefix is not explicitly required, it may be used to make selectors unambiguous. - - + ```bash # These three selectors are equivalent @@ -121,9 +102,8 @@ selectors unambiguous. dbt run --select snowplow.* ``` - - - + + ```bash # These three selectors are equivalent @@ -132,22 +112,14 @@ selectors unambiguous. dbt run --models snowplow.* ``` - - + ### The "config" method New in v0.18.0 The `config` method is used to select models that match a specified [node config](configs-and-properties). - - + ```bash $ dbt run --select config.materialized:incremental # run all models that are materialized incrementally @@ -155,8 +127,8 @@ The `config` method is used to select models that match a specified [node config $ dbt run --select config.cluster_by:geo_country # run all models clustered by `geo_country` ``` - - + + ```bash $ dbt run --models config.materialized:incremental # run all models that are materialized incrementally @@ -164,8 +136,33 @@ The `config` method is used to select models that match a specified [node config $ dbt run --models config.cluster_by:geo_country # run all models clustered by `geo_country` ``` - - + + + + +While most config values are strings, you can also use the `config` method to match boolean configs, dictionary keys, and values in lists. + +For example, given a model with the following configurations: +``` +{{ config( + materialized = 'incremental', + unique_key = ['column_a', 'column_b'], + grants = {'select': ['reporter', 'analysts']}, + transient = true +) }} + +select ... +``` + + You can select using any of the following: +```bash +$ dbt ls -s config.materialized:incremental +$ dbt ls -s config.unique_key:column_a +$ dbt ls -s config.grants.select:reporter +$ dbt ls -s config.transient:true +``` + + ### The "test_type" method @@ -177,30 +174,22 @@ The `config` method is used to select models that match a specified [node config The `test_type` method is used to select tests based on their type, `singular` or `generic`: - - + ```bash $ dbt test --select test_type:generic # run all generic tests $ dbt test --select test_type:singular # run all singular tests ``` - - + + ```bash $ dbt test --models test_type:schema # run all schema tests $ dbt test --models test_type:data # run all data tests ``` - - + ### The "test_name" method New in v0.18.0 @@ -209,14 +198,7 @@ The `test_name` method is used to select tests based on the name of the generic that defines it. For more information about how generic tests are defined, read about [tests](building-a-dbt-project/tests). - - + ```bash $ dbt test --select test_name:unique # run all instances of the `unique` test @@ -224,9 +206,8 @@ that defines it. For more information about how generic tests are defined, read $ dbt test --select test_name:range_min_max # run all instances of a custom schema test defined in the local project, `range_min_max` ``` - - - + + ```bash $ dbt test --models test_name:unique # run all instances of the `unique` test @@ -234,8 +215,7 @@ that defines it. For more information about how generic tests are defined, read $ dbt test --models test_name:range_min_max # run all instances of a custom schema test defined in the local project, `range_min_max` ``` - - + ### The "state" method @@ -251,14 +231,7 @@ The `state` method is used to select nodes by comparing them against a previous `state:modified`: All new nodes, plus any changes to existing nodes. - - + ```bash $ dbt test --select state:new # run all tests on new models + and new tests on old models @@ -266,8 +239,8 @@ The `state` method is used to select nodes by comparing them against a previous $ dbt ls --select state:modified # list all modified nodes (not just models) ``` - - + + ```bash $ dbt test --models state:new # run all tests on new models + and new tests on old models @@ -275,8 +248,7 @@ The `state` method is used to select nodes by comparing them against a previous $ dbt ls --select state:modified # This really is still --select! list all modified nodes (not just models) ``` - - + Because state comparison is complex, and everyone's project is different, dbt supports subselectors that include a subset of the full `modified` criteria: - `state:modified.body`: Changes to node body (e.g. model SQL, seed values) @@ -285,21 +257,14 @@ Because state comparison is complex, and everyone's project is different, dbt su - `state:modified.persisted_descriptions`: Changes to relation- or column-level `description`, _if and only if_ `persist_docs` is enabled at each level - `state:modified.macros`: Changes to upstream macros (whether called directly or indirectly by another macro) -Remember that `state:modified` includes _all_ of the criteria above, as well as some extra resource-specific criteria, such as changes to a source's `freshness` property or an exposure's `maturity` property. (View the source code for the full set of checks used when comparing [sources](https://github.com/dbt-labs/dbt-core/blob/9e796671dd55d4781284d36c035d1db19641cd80/core/dbt/contracts/graph/parsed.py#L660-L681), [exposures](https://github.com/dbt-labs/dbt-core/blob/9e796671dd55d4781284d36c035d1db19641cd80/core/dbt/contracts/graph/parsed.py#L768-L783), and [executable nodes](https://github.com/dbt-labs/dbt-core/blob/9e796671dd55d4781284d36c035d1db19641cd80/core/dbt/contracts/graph/parsed.py#L319-L330).) +Remember that `state:modified` includes _all_ of the criteria above, as well as some extra resource-specific criteria, such as modifying a source's `freshness` or `quoting` rules or an exposure's `maturity` property. (View the source code for the full set of checks used when comparing [sources](https://github.com/dbt-labs/dbt-core/blob/9e796671dd55d4781284d36c035d1db19641cd80/core/dbt/contracts/graph/parsed.py#L660-L681), [exposures](https://github.com/dbt-labs/dbt-core/blob/9e796671dd55d4781284d36c035d1db19641cd80/core/dbt/contracts/graph/parsed.py#L768-L783), and [executable nodes](https://github.com/dbt-labs/dbt-core/blob/9e796671dd55d4781284d36c035d1db19641cd80/core/dbt/contracts/graph/parsed.py#L319-L330).) ### The "exposure" method New in v0.18.1 The `exposure` method is used to select parent resources of a specified [exposure](exposures). Use in conjunction with the `+` operator. - - + ```bash $ dbt run --select +exposure:weekly_kpis # run all models that feed into the weekly_kpis exposure @@ -307,8 +272,8 @@ The `exposure` method is used to select parent resources of a specified [exposur $ dbt ls --select +exposure:* --resource-type source # list all sources upstream of all exposures ``` - - + + ```bash $ dbt run --models +exposure:weekly_kpis # run all models that feed into the weekly_kpis exposure @@ -316,8 +281,7 @@ The `exposure` method is used to select parent resources of a specified [exposur $ dbt ls --select +exposure:* --resource-type source # This really is still --select! list all sources upstream of all exposures ``` - - + ### The "metric" method New in v1.0.0 @@ -340,3 +304,32 @@ $ dbt test --select result:fail # run all tests that failed on the prior invocat $ dbt build --select 1+result:fail # run all the models associated with failed tests from the prior invocation of dbt build $ dbt seed --select result:error # run all seeds that generated errors on the prior invocation of dbt seed. ``` + +### The "source_status" method + + +Only supported by v1.1 or newer. + + + + + +Only supported by v1.1 or newer. + +:::caution Experimental functionality +The `source_status` selection method is experimental and subject to change. During this time, ongoing improvements may limit this feature’s availability and cause breaking changes to its functionality. +::: + +Another element of job state is the `source_status` of a prior dbt invocation. After executing `dbt source freshness`, for example, dbt creates the `sources.json` artifact which contains execution times and `max_loaded_at` dates for dbt sources. You can read more about `sources.json` on the ['sources'](/docs/reference/artifacts/sources-json) page. + +The following dbt commands produce `sources.json` artifacts whose results can be referenced in subsequent dbt invocations: +- `dbt source freshness` + +After issuing one of the above commands, you can reference the source freshness results by adding a selector to a subsequent command as follows: + +```bash +# You can also set the DBT_ARTIFACT_STATE_PATH environment variable instead of the --state flag. +$ dbt source freshness # must be run again to compare current to previous state +$ dbt build --select source_status:fresher+ --state path/to/prod/artifacts +``` + \ No newline at end of file diff --git a/website/docs/reference/node-selection/putting-it-together.md b/website/docs/reference/node-selection/putting-it-together.md index d7c658d5387..c8be96142d0 100644 --- a/website/docs/reference/node-selection/putting-it-together.md +++ b/website/docs/reference/node-selection/putting-it-together.md @@ -2,14 +2,7 @@ title: "Putting it together" --- - - + ```bash $ dbt run --select my_package.*+ # select all models in my_package and their children @@ -23,8 +16,8 @@ title: "Putting it together" $ dbt test --select config.incremental_strategy:insert_overwrite,test_name:unique # execute all `unique` tests that select from models using the `insert_overwrite` incremental strategy ``` - - + + ```bash $ dbt run --models my_package.*+ # select all models in my_package and their children @@ -38,35 +31,25 @@ title: "Putting it together" $ dbt test --models config.incremental_strategy:insert_overwrite,test_name:unique # execute all `unique` tests that select from models using the `insert_overwrite` incremental strategy ``` - - + This can get complex! Let's say I want a nightly run of models that build off snowplow data and feed exports, while _excluding_ the biggest incremental models (and one other model, to boot). - - - + ```bash $ dbt run --select @source:snowplow,tag:nightly models/export --exclude package:snowplow,config.materialized:incremental export_performance_timing ``` - - + + ```bash $ dbt run --models @source:snowplow,tag:nightly models/export --exclude package:snowplow,config.materialized:incremental export_performance_timing ``` - - + This command selects all models that: * Select from snowplow sources, plus their parents, _and_ are tagged "nightly" diff --git a/website/docs/reference/node-selection/set-operators.md b/website/docs/reference/node-selection/set-operators.md index b5cf29ef4be..605558c0b92 100644 --- a/website/docs/reference/node-selection/set-operators.md +++ b/website/docs/reference/node-selection/set-operators.md @@ -9,28 +9,20 @@ included in the final set. Run snowplow_sessions, all ancestors of snowplow_sessions, fct_orders, and all ancestors of fct_orders: - - + ```bash $ dbt run --select +snowplow_sessions +fct_orders ``` - - + + ```bash $ dbt run --models +snowplow_sessions +fct_orders ``` - - + ### Intersections New in v0.18.0 @@ -40,76 +32,51 @@ dbt will select only resources which satisfy _all_ arguments. Run all the common ancestors of snowplow_sessions and fct_orders: - - + ```bash $ dbt run --select +snowplow_sessions,+fct_orders ``` - - + + ```bash $ dbt run --models +snowplow_sessions,+fct_orders ``` - - - + Run all the common descendents of stg_invoices and stg_accounts: - - + ```bash $ dbt run --select stg_invoices+,stg_accounts+ ``` - - + + ```bash $ dbt run --models stg_invoices+,stg_accounts+ ``` - - + Run models that are in the marts/finance subdirectory *and* tagged nightly: - - + ```bash $ dbt run --select marts.finance,tag:nightly ``` - - + + ```bash $ dbt run --models marts.finance,tag:nightly ``` - - + diff --git a/website/docs/reference/node-selection/syntax.md b/website/docs/reference/node-selection/syntax.md index a1f46a4a903..b95dfdaacfa 100644 --- a/website/docs/reference/node-selection/syntax.md +++ b/website/docs/reference/node-selection/syntax.md @@ -53,14 +53,7 @@ The `--select` flag accepts one or more arguments. Each argument can be one of: Examples: - - + ```bash $ dbt run --select my_dbt_project_name # runs all models in your project @@ -72,9 +65,8 @@ Examples: $ dbt run --select path/to/my_model.sql # run a specific model by its path ``` - - - + + ```bash $ dbt run --models my_dbt_project_name # runs all models in your project @@ -86,21 +78,11 @@ Examples: $ dbt run --models path/to/my_model.sql # run a specific model by its path ``` - - - + dbt supports a shorthand language for defining subsets of nodes. This language uses the characters `+`, `@`, `*`, and `,`. - - - + ```bash # multiple arguments can be provided to --select @@ -112,9 +94,9 @@ dbt supports a shorthand language for defining subsets of nodes. This language u # use methods and intersections for more complex selectors $ dbt run --select path:marts/finance,tag:nightly,config.materialized:table ``` - - + + ```bash # multiple arguments can be provided to --select @@ -126,9 +108,8 @@ dbt supports a shorthand language for defining subsets of nodes. This language u # use methods and intersections for more complex selectors $ dbt run --models path:marts/finance,tag:nightly,config.materialized:table ``` - - + As your selection logic gets more complex, and becomes unwieldly to type out as command-line arguments, consider using a [yaml selector](yaml-selectors). You can use a predefined definition with the `--selector` flag. diff --git a/website/docs/reference/node-selection/test-selection-examples.md b/website/docs/reference/node-selection/test-selection-examples.md index b723a69651b..fcb4ecd8ccc 100644 --- a/website/docs/reference/node-selection/test-selection-examples.md +++ b/website/docs/reference/node-selection/test-selection-examples.md @@ -32,83 +32,58 @@ Test selection is powerful, and we know it can be tricky. To that end, we've inc Run generic tests only: - - + ```bash $ dbt test --select test_type:generic ``` - - + + ```bash $ dbt test --models test_type:data ``` - - + Run singular tests only: - - + ```bash $ dbt test --select test_type:singular ``` - - + + ```bash $ dbt test --models test_type:data ``` - - + In both cases, `test_type` checks a property of the test itself. These are forms of "direct" test selection. ### Indirect selection - - - + ```bash $ dbt test --select customers $ dbt test --select orders ``` - - + + ```bash $ dbt test --models customers $ dbt test --models orders ``` - - + These are examples of "indirect" selection: `customers` and `orders` select models (whether by name or path). Any tests defined on either `customers` or `orders` will be selected indirectly, and thereby included. @@ -124,41 +99,26 @@ Imagine a `relationships` test between `customers` and `orders`. By default, the $ dbt test --select customers orders --indirect-selection=cautious ``` - - + ```bash $ dbt test --select customers orders ``` - - + + ```bash $ dbt test --models customers orders ``` - - + ### Syntax examples The following examples should feel somewhat familiar if you're used to executing `dbt run` with the `--select` option to build parts of your DAG: - - + ```bash # Run tests on a model (indirect selection) @@ -181,8 +141,8 @@ The following examples should feel somewhat familiar if you're used to executing ``` - - + + ```bash # Run tests on a model (indirect selection) @@ -205,66 +165,50 @@ The following examples should feel somewhat familiar if you're used to executing ``` - - + The same principle can be extended to tests defined on other resource types. In these cases, we will execute all tests defined on certain sources via the `source:` selection method: - - + - ```bash - # tests on all sources - $ dbt test --select source:* + ```bash + # tests on all sources + $ dbt test --select source:* - # tests on one source - $ dbt test --select source:jaffle_shop + # tests on one source + $ dbt test --select source:jaffle_shop - # tests on one source table - $ dbt test --select source:jaffle_shop.customers + # tests on one source table + $ dbt test --select source:jaffle_shop.customers - # tests on everything _except_ sources - $ dbt test --exclude source:* - ``` + # tests on everything _except_ sources + $ dbt test --exclude source:* + ``` - - + + - ```bash - # tests on all sources - $ dbt test --models source:* + ```bash + # tests on all sources + $ dbt test --models source:* - # tests on one source - $ dbt test --models source:jaffle_shop + # tests on one source + $ dbt test --models source:jaffle_shop - # tests on one source table - $ dbt test --models source:jaffle_shop.customers + # tests on one source table + $ dbt test --models source:jaffle_shop.customers - # tests on everything _except_ sources - $ dbt test --exclude source:* - ``` + # tests on everything _except_ sources + $ dbt test --exclude source:* + ``` - - + ### More complex selection Through the combination of direct and indirect selection, there are many ways to accomplish the same outcome. Let's say we have a data test named `assert_total_payment_amount_is_positive` that depends on a model named `payments`. All of the following would manage to select and execute that test specifically: - - + ```bash $ dbt test --select assert_total_payment_amount_is_positive # directly select the test by name @@ -272,8 +216,8 @@ Through the combination of direct and indirect selection, there are many ways to $ dbt test --select payments --data # indirect selection, earlier versions ``` - - + + ```bash $ dbt test --models assert_total_payment_amount_is_positive # directly select the test by name @@ -281,48 +225,38 @@ Through the combination of direct and indirect selection, there are many ways to $ dbt test --models payments --data # indirect selection, earlier versions ``` - - + As long as you can select a common property of a group of resources, indirect selection allows you to execute all the tests on those resources, too. In the example above, we saw it was possible to test all table-materialized models. This principle can be extended to other resource types, too: + - - - - ```bash - # Run tests on all models with a particular materialization - $ dbt test --select config.materialized:table + ```bash + # Run tests on all models with a particular materialization + $ dbt test --select config.materialized:table - # Run tests on all seeds, which use the 'seed' materialization - $ dbt test --select config.materialized:seed + # Run tests on all seeds, which use the 'seed' materialization + $ dbt test --select config.materialized:seed - # Run tests on all snapshots, which use the 'snapshot' materialization - $ dbt test --select config.materialized:snapshot - ``` + # Run tests on all snapshots, which use the 'snapshot' materialization + $ dbt test --select config.materialized:snapshot + ``` - - + + - ```bash - # Run tests on all models with a particular materialization - $ dbt test --models config.materialized:table + ```bash + # Run tests on all models with a particular materialization + $ dbt test --models config.materialized:table - # Run tests on all seeds, which use the 'seed' materialization - $ dbt test --models config.materialized:seed + # Run tests on all seeds, which use the 'seed' materialization + $ dbt test --models config.materialized:seed - # Run tests on all snapshots, which use the 'snapshot' materialization - $ dbt test --models config.materialized:snapshot - ``` + # Run tests on all snapshots, which use the 'snapshot' materialization + $ dbt test --models config.materialized:snapshot + ``` -
- + Note that this functionality may change in future versions of dbt. @@ -347,29 +281,20 @@ models: - - + ```bash $ dbt test --select tag:my_column_tag ``` - - + + ```bash $ dbt test --models tag:my_column_tag ``` - - - + Currently, tests "inherit" tags applied to columns, sources, and source tables. They do _not_ inherit tags applied to models, seeds, or snapshots. In all likelihood, those tests would still be selected indirectly, because the tag selects its parent. This is a subtle distinction, and it may change in future versions of dbt. @@ -394,27 +319,17 @@ models: - - - - + ```bash $ dbt test --select tag:my_test_tag ``` - - + + ```bash $ dbt test --models tag:my_test_tag ``` - - + diff --git a/website/docs/reference/node-selection/yaml-selectors.md b/website/docs/reference/node-selection/yaml-selectors.md index 53c9430daa7..70d6f318c6b 100644 --- a/website/docs/reference/node-selection/yaml-selectors.md +++ b/website/docs/reference/node-selection/yaml-selectors.md @@ -124,10 +124,10 @@ As a general rule, dbt will indirectly select _all_ tests if they touch _any_ re - union: - method: fqn value: model_a - greedy: eager # default: will include all tests that touch model_a + indirect_selection: eager # default: will include all tests that touch model_a - method: fqn value: model_b - greedy: cautious # will not include tests touching model_b + indirect_selection: cautious # will not include tests touching model_b # if they have other unselected parents ``` @@ -139,28 +139,20 @@ See [test selection examples](test-selection-examples) for more details about in Here are two ways to represent: - - + ```bash $ dbt run --select @source:snowplow,tag:nightly models/export --exclude package:snowplow,config.materialized:incremental export_performance_timing ``` - - + + ```bash $ dbt run --models @source:snowplow,tag:nightly models/export --exclude package:snowplow,config.materialized:incremental export_performance_timing ``` - - + ``` @@ -269,3 +261,31 @@ selectors: default: "{{ target.name == 'prod' | as_bool }}" definition: ... ``` + + + +### Selector inheritance + +Selectors can reuse and extend definitions from other selectors, via the `selector` method. + +```yml +selectors: + - name: foo_and_bar + definition: + intersection: + - tag: foo + - tag: bar + + - name: foo_bar_less_buzz + definition: + intersection: + # reuse the definition from above + - method: selector + value: foo_and_bar + # with a modification! + - exclude: + - method: tag + value: buzz +``` + + diff --git a/website/docs/reference/parsing.md b/website/docs/reference/parsing.md index f6b3f72461d..256c01dd094 100644 --- a/website/docs/reference/parsing.md +++ b/website/docs/reference/parsing.md @@ -30,7 +30,7 @@ python -c "from yaml import CLoader" ## Partial parsing -After parsing your project, dbt stores an internal project manifest in a file called `partial_parse.msgpack`. When partial parsing is enabled, dbt will use that internal manifest to determine which files have been changed (if any) since it last parsed the project. Then, it will _only_ parse the changed files, or files related those changes. +After parsing your project, dbt stores an internal project manifest in a file called `partial_parse.msgpack`. When partial parsing is enabled, dbt will use that internal manifest to determine which files have been changed (if any) since it last parsed the project. Then, it will _only_ parse the changed files, or files related to those changes. Starting in v1.0, partial parsing is **on** by default. In development, partial parsing can significantly reduce the time spent waiting at the start of a run, which translates to faster dev cycles and iteration. @@ -56,7 +56,7 @@ If you ever get into a bad state, you can disable partial parsing and trigger a ## Static parser -At parse time, dbt needs to extract the contents of `ref()`, `source()`, and `config()` from all models in the project. Traditionally, dbt has extracted those values by rendering the Jinja in every model file, which can be slow. In v0.20, we introduced a new way to statically analyze model files, leveraging [`tree-sitter`](https://github.com/tree-sitter/tree-sitter), which we're calling an "experimental parser". You can see the code for an initial Jinja2 grammar [here](https://github.com/fishtown-analytics/tree-sitter-jinja2). +At parse time, dbt needs to extract the contents of `ref()`, `source()`, and `config()` from all models in the project. Traditionally, dbt has extracted those values by rendering the Jinja in every model file, which can be slow. In v0.20, we introduced a new way to statically analyze model files, leveraging [`tree-sitter`](https://github.com/tree-sitter/tree-sitter), which we're calling an "experimental parser". You can see the code for an initial Jinja2 grammar [here](https://github.com/dbt-labs/tree-sitter-jinja2). Starting in v1.0, the experimental parser is **on** by default. We believe it can offer *some* speedup to 95% of projects. You may optionally turn it off using the [`STATIC_PARSER` global config](global-configs#static-parser). diff --git a/website/docs/reference/profiles.yml.md b/website/docs/reference/profiles.yml.md index e1b6d544dd8..90023836358 100644 --- a/website/docs/reference/profiles.yml.md +++ b/website/docs/reference/profiles.yml.md @@ -12,21 +12,21 @@ This article lists the parts of your `profiles.yml` which are _not_ database spe ```yml [config](global-configs): - [send_anonymous_usage_stats](global-configs#send_anonymous_usage_stats): - [use_colors](global-configs#use_colors): - [partial_parse](global-configs#partial_parse): - [printer_width](global-configs#printer_width): - [write_json](global-configs#write_json): - [warn_error](global-configs#warn_error): - [log_format](global-configs#log_format): - [debug](global-configs#debug): - [version_check](global-configs#version_check): - [fail_fast](global-configs#fail_fast): - [use_experimental_parser](global-configs#use_experimental_parser): - [static_parser](global-configs#static_parser): + [send_anonymous_usage_stats](global-configs#send-anonymous-usage-stats): + [use_colors](global-configs#use-colors): + [partial_parse](global-configs#partial-parsing): + [printer_width](global-configs#printer-width): + [write_json](global-configs#writing-json-artifacts): + [warn_error](global-configs#warnings-as-errors): + [log_format](global-configs#log-formatting): + [debug](global-configs#debug-level-logging): + [version_check](global-configs#checking-version-compatibility): + [fail_fast](global-configs#failing-fast): + [use_experimental_parser](global-configs#experimental-parser): + [static_parser](global-configs#static-parser): : - target: + target: # this is the default target outputs: : type: diff --git a/website/docs/reference/project-configs/asset-paths.md b/website/docs/reference/project-configs/asset-paths.md index 3621cc133d6..401a88d86c7 100644 --- a/website/docs/reference/project-configs/asset-paths.md +++ b/website/docs/reference/project-configs/asset-paths.md @@ -16,7 +16,7 @@ Optionally specify a custom list of directories to copy to the `target` director -* `v0.18.0`: This configuration was introduced — see the [migration guide for 0.18.0](upgrading-to-0-18-0) for more details. +* `v0.18.0`: This configuration was introduced — see the [migration guide](/guides/migration/versions) for more details. diff --git a/website/docs/reference/project-configs/config-version.md b/website/docs/reference/project-configs/config-version.md index b3ee4f51590..60e787513a5 100644 --- a/website/docs/reference/project-configs/config-version.md +++ b/website/docs/reference/project-configs/config-version.md @@ -15,7 +15,7 @@ Specify your `dbt_project.yml` as using the v2 structure. -* `v0.17.0`: This configuration was introduced — see the [migration guide for 0.17.0](upgrading-to-0-17-0) for more details. +* `v0.17.0`: This configuration was introduced — see the [migration guide](/guides/migration/versions) for more details. diff --git a/website/docs/reference/project-configs/dispatch-config.md b/website/docs/reference/project-configs/dispatch-config.md index 303b5f6b820..6cb8060949c 100644 --- a/website/docs/reference/project-configs/dispatch-config.md +++ b/website/docs/reference/project-configs/dispatch-config.md @@ -18,34 +18,33 @@ dispatch: ## Definition -Optionally override the [dispatch](dispatch) search locations for macros in certain namespaces. +Optionally override the [dispatch](dispatch) search locations for macros in certain namespaces. If not specified, `dispatch` will look in your root project _first_, by default, and then look for implementations in the package named by `macro_namespace`. ## Examples -I've reimplemented certain macros from the `dbt_utils` package, and I want my versions to take precedence. Otherwise, fall back to the versions in `dbt_utils`. + +I want to "shim" the `dbt_utils` package with the `spark_utils` compatibility package. ```yml dispatch: - macro_namespace: dbt_utils - search_order: - - macro_namespace: packagename - search_order: [packagename] + search_order: ['spark_utils', 'dbt_utils'] ``` -I want to "shim" the `dbt_utils` package with the `spark_utils` compatibility package. +I've reimplemented certain macros from the `dbt_utils` package in my root project (`'my_root_project'`), and I want my versions to take precedence. Otherwise, fall back to the versions in `dbt_utils`. + +_Note: As of v0.21.1, this is the default behavior. You may optionally choose to express that search order explicitly as:_ ```yml dispatch: - - macro_namespace: packagename - search_order: [packagename] - - macro_namespace: packagename - search_order: [packagename] + - macro_namespace: dbt_utils + search_order: ['my_root_project', 'dbt_utils'] ``` diff --git a/website/docs/reference/project-configs/log-path.md b/website/docs/reference/project-configs/log-path.md index 5dc1bf69806..64b5d73ce85 100644 --- a/website/docs/reference/project-configs/log-path.md +++ b/website/docs/reference/project-configs/log-path.md @@ -16,6 +16,18 @@ Optionally specify a custom directory where dbt will write logs. ## Default By default, dbt will write to the `logs` directory, i.e. `log-path: logs` + +## Configuration + +In the manner of a ["global" config](global-configs), the log path can be set in three places: +1. `--log-path` CLI flag +2. `DBT_LOG_PATH` environment variable +3. `log-path` in `dbt_project.yml` + +The precedence order is: CLI flag > env var > `dbt_project.yml` + + + ## Examples ### Write logs to a subdirectory named `dbt_logs` instead of `logs` diff --git a/website/docs/reference/project-configs/on-run-start-on-run-end.md b/website/docs/reference/project-configs/on-run-start-on-run-end.md index 011fe5b117c..091122baa88 100644 --- a/website/docs/reference/project-configs/on-run-start-on-run-end.md +++ b/website/docs/reference/project-configs/on-run-start-on-run-end.md @@ -20,6 +20,8 @@ A SQL statement (or list of SQL statements) to be run at the start, or end, of t - `dbt seed` - `dbt snapshot` - `dbt build` +- `dbt compile` +- `dbt docs generate` `on-run-start` and `on-run-end` hooks can also call macros that return SQL statements @@ -27,6 +29,11 @@ A SQL statement (or list of SQL statements) to be run at the start, or end, of t * The `on-run-end` hook has additional jinja variables available in the context — check out the [docs](on-run-end-context). ## Examples + + + + + ### Grant privileges at the end of a run @@ -51,6 +58,8 @@ on-run-end: + + ### Grant privileges on all schemas that dbt uses at the end of a run This leverages the [schemas](schemas) variable that is only available in an `on-run-end` hook. diff --git a/website/docs/reference/project-configs/profile.md b/website/docs/reference/project-configs/profile.md index 52d544279f5..0a468040f0a 100644 --- a/website/docs/reference/project-configs/profile.md +++ b/website/docs/reference/project-configs/profile.md @@ -10,7 +10,7 @@ profile: string ## Definition -The profile your dbt project should use to connect to your data warehouse. +The profile your dbt project should use to connect to your . * If you are developing in dbt Cloud: This configuration is optional * If you are developing locally: This configuration is required, unless a command-line option (i.e. `--profile`) is supplied. @@ -18,14 +18,11 @@ The profile your dbt project should use to connect to your data warehouse. * [Connecting to your warehouse](dbt-cli/configure-your-profile) ## Recommendation -Often an organization has only one data warehouse, so it is sensible to use your organization's name as a profile name, in `snake_case`. For example: +Often an organization has only one , so it is sensible to use your organization's name as a profile name, in `snake_case`. For example: * `profile: acme` * `profile: jaffle_shop` -* `profile: evilcorp` -It is also reasonable to include the name of your warehouse technology in your profile name. For example: +It is also reasonable to include the name of your warehouse technology in your profile name, partiuclarly if you have multiple warehouses. For example: * `profile: acme_snowflake` * `profile: jaffle_shop_bigquery` -* `profile: evilcorp_redshift` - -If you are working on more than one project, do not use `profile: default` as your profile name (as set by the `dbt init` [command](init)), as it will become hard to manage multiple profiles. +* `profile: jaffle_shop_redshift` diff --git a/website/docs/reference/project-configs/query-comment.md b/website/docs/reference/project-configs/query-comment.md index 8d1b12c68e5..3ce4a4df870 100644 --- a/website/docs/reference/project-configs/query-comment.md +++ b/website/docs/reference/project-configs/query-comment.md @@ -39,7 +39,7 @@ The `query-comment` configuration can also call a macro that returns a string. ## Default -By default, dbt will insert a JSON comment at the top of your query containing the information including the dbt version, profile and target names, and node ids for the resources it runs. For example: +By default, dbt will insert a comment at the top of your query containing the information including the dbt version, profile and target names, and node ids for the resources it runs. For example: ```sql /* {"app": "dbt", "dbt_version": "0.15.0rc2", "profile_name": "debug", @@ -56,7 +56,7 @@ create view analytics.analytics.orders as ( ## Using the dictionary syntax The dictionary syntax includes two keys: * `comment` (optional, see above for default): The string to be injected to a query as a comment. - * `append` (optional, default=`false`): Whether a comment should be appended (added to the bottom of a query) or not (i.e. added to the top of a comment). By default, comments are added to the top of queries (i.e. `append: false`). + * `append` (optional, default=`false`): Whether a comment should be appended (added to the bottom of a query) or not (i.e. added to the top of a query). By default, comments are added to the top of queries (i.e. `append: false`). This syntax is useful on databases like Snowflake which [remove leading SQL comments](https://docs.snowflake.com/en/release-notes/2017-04.html#queries-leading-comments-removed-during-execution). diff --git a/website/docs/reference/project-configs/quoting.md b/website/docs/reference/project-configs/quoting.md index 0b2ff778cfa..5c89183ddc8 100644 --- a/website/docs/reference/project-configs/quoting.md +++ b/website/docs/reference/project-configs/quoting.md @@ -46,8 +46,9 @@ The default values vary by database. For most adapters, quoting is set to `true` by default. -This is because creating relations with quoted identifiers does not inhibit the ability to select from them, and quoting allows you to use reserved words as object names (though that should probably be avoided) - +Why? It's equally easy to select from relations with quoted or unquoted identifiers. Quoting allows you to use reserved words and special characters in those identifiers, though we recommend avoiding this whenever possible. + + ```yml quoting: @@ -63,7 +64,7 @@ quoting: On Snowflake, quoting is set to `false` by default. -This is because creating relations with quoted identifiers inhibits your ability to select from the them. +Creating relations with quoted identifiers also makes those identifiers case sensitive. It's much more difficult to select from them. You can re-enable quoting for relations identifiers that are case sensitive, reserved words, or contain special characters, but we recommend you avoid this as much as possible. diff --git a/website/docs/reference/project-configs/require-dbt-version.md b/website/docs/reference/project-configs/require-dbt-version.md index d52ffe15c70..ccea51f833a 100644 --- a/website/docs/reference/project-configs/require-dbt-version.md +++ b/website/docs/reference/project-configs/require-dbt-version.md @@ -12,9 +12,9 @@ require-dbt-version: version-range | [version-range] ## Definition -Optionally specify a range of dbt versions that a project is compatible with. +You can use `require-dbt-version` to restrict your project to only work with a range of dbt versions. -By using this configuration, dbt will throw a helpful error message if a user tries to run your project with an unsupported version of dbt. This is especially useful for packages (like [dbt-utils](https://github.com/dbt-labs/dbt-utils)). Additionally, this can help ensure that your whole team is synchronized on the same version of dbt for local development. +When you set this configuration, dbt sends a helpful error message for any user who attempts to run the project with an unsupported version of dbt. This can be useful for package maintainers (such as [dbt-utils](https://github.com/dbt-labs/dbt-utils)) to ensure that users' dbt version is compatible with the package. Setting this configuration might also help your whole team remain synchronized on the same version of dbt for local development, to avoid compatibility issues from changed behaviour. If this configuration is not specified, no version check will occur. @@ -26,15 +26,15 @@ If this configuration is not specified, no version check will occur. :::info YAML Quoting -This configuration needs to be interpolated by the yaml parser as a string. As such, you should quote the value of the configuration. For example. Also take care to get the spacing correct. +This configuration needs to be interpolated by the yaml parser as a string. As such, you should quote the value of the configuration, taking care to avoid whitespace. For example: ```yml # ✅ These will work -require-dbt-version: ">=0.16.0" -require-dbt-version: '>=0.16.0' +require-dbt-version: ">=1.0.0" # Double quotes are OK +require-dbt-version: '>=1.0.0' # So are single quotes # ❌ These will not work -require-dbt-version: >=0.16.0 -require-dbt-version: ">= 0.16.0" +require-dbt-version: >=1.0.0 # No quotes? No good +require-dbt-version: ">= 1.0.0" # Don't put whitespace after the equality signs ``` ::: @@ -42,67 +42,69 @@ require-dbt-version: ">= 0.16.0" ## Examples -### Require a specific dbt version -Use an exact version number. In this example, this project will only run with dbt v0.16.0 supported. +### Specify a minimum dbt version +Use a `>=` operator for a minimum boundary. In the following example, this project will run with any version of dbt greater than or equal to 1.0.0. + ```yml -require-dbt-version: 0.16.0 - +require-dbt-version: ">=1.0.0" ``` -### Specify a minimum dbt version -Use a `>=` operator for a minimum boundary. In this example, this project will run with any version of dbt greater than or equal to 0.16.0. +### Pin to a range +Use a comma separated list for an upper and lower bound. In the following example, this project will run with dbt 1.x.x. ```yml -require-dbt-version: ">=0.16.0" - +require-dbt-version: [">=1.0.0", "<2.0.0"] ``` - -### Pin to a minor dbt version using a range -Use a comma separated list for an upper and lower bound. In this example, this project will run with dbt 0.16.x. +OR ```yml -require-dbt-version: ">=0.16.0,<0.17.0" - +require-dbt-version: ">=1.0.0,<2.0.0" ``` -OR + +### Require a specific dbt version +:::caution Not recommended +With the release of major version 1.0 of dbt Core, pinning to a specific patch is discouraged. +::: + +While you can restrict your project to run only with an exact version of dbt Core, we do not recommend this for dbt Core v1.0.0 and higher. + +In the following example, the project will only run with dbt v0.21.1. ```yml -require-dbt-version: [">=0.16.0", "<0.17.0"] - +require-dbt-version: 0.21.1 ``` - ## Invalid dbt versions If the version of dbt used to invoke a project disagrees with the specified `require-dbt-version` in the project or _any_ of the included packages, then dbt will fail immediately with the following error: ``` $ dbt compile -Running with dbt=0.17.0 +Running with dbt=0.21.0 Encountered an error while reading the project: Runtime Error This version of dbt is not supported with the 'my_project' package. - Installed version of dbt: =0.16.0 - Required version of dbt for 'my_project': ['>=0.16.0', '<0.17.0'] + Installed version of dbt: =0.21.0 + Required version of dbt for 'my_project': ['>=1.0.0', '<2.0.0'] Check the requirements for the 'my_project' package, or run dbt again with --no-version-check ``` @@ -111,7 +113,7 @@ Runtime Error To suppress failures to to incompatible dbt versions, supply the `--no-version-check` flag to `dbt run`. ``` $ dbt run --no-version-check -Running with dbt=0.17.0 +Running with dbt=0.21.0 Found 13 models, 2 tests, 1 archives, 0 analyses, 204 macros, 2 operations.... ``` @@ -119,4 +121,4 @@ See [global configs](global-configs#checking-version-compatibility) for usage de ## Recommendation * This is a recommended configuration -* You should pin your required dbt version to a minor release (see above [example](#pin-to-a-minor-dbt-version-using-a-range)) +* Before v1, you should pin your required dbt version to a minor release. After v1, you should pin to a major release (see above [example](#pin-to-a-range)) diff --git a/website/docs/reference/project-configs/target-path.md b/website/docs/reference/project-configs/target-path.md index 9bbd2c19de0..82956d9688d 100644 --- a/website/docs/reference/project-configs/target-path.md +++ b/website/docs/reference/project-configs/target-path.md @@ -17,6 +17,18 @@ Optionally specify a custom directory where compiled files (e.g. compiled models ## Default By default, dbt will write compiled files to the `target` directory, i.e. `target-path: target` + +## Configuration + +In the manner of a ["global" config](global-configs), the target path can be set in three places: +1. `--target-path` CLI flag +2. `DBT_TARGET_PATH` environment variable +3. `target-path` in `dbt_project.yml` + +The precedence order is: CLI flag > env var > `dbt_project.yml` + + + ## Examples ### Use a subdirectory named `compiled` for compiled files diff --git a/website/docs/reference/project-configs/version.md b/website/docs/reference/project-configs/version.md index 4cc811c378c..31d91ad9c82 100644 --- a/website/docs/reference/project-configs/version.md +++ b/website/docs/reference/project-configs/version.md @@ -2,6 +2,12 @@ datatype: version required: True --- + +dbt projects have two distinct types of the `version` tags. This field has a different meaning depending on its location. + +## `dbt_project.yml` versions + +The version tag in a `dbt_project` file represents the version of your dbt project. Although **this is a required parameter**, it is not currently meaningfully used by dbt. The version must be in a [semantic version](https://semver.org/) format, e.g. `1.0.0`. For more on Core versions, see "[About dbt Core versions](/docs/core-versions)." ```yml @@ -10,7 +16,20 @@ version: version -## Definition -The version of a dbt project. Note that while **this is a required parameter**, it is not currently meaningfully used by dbt. The version must be in a [semantic version](https://semver.org/) format, e.g. `1.0.0` + +## `.yml` property file versions + +A version tag in a `.yml` property file provides the control tag, which informs how dbt processes property files. For more on why we require this tag, see property file [FAQs](reference/configs-and-properties#faqs). + +For more on property files, see their general [documentation](reference/configs-and-properties#where-can-i-define-properties) on the same page. + + +```yml +version: 2 # Only 2 is accepted by current and recent versions of dbt. +``` + + + + diff --git a/website/docs/reference/resource-configs/alias.md b/website/docs/reference/resource-configs/alias.md index 006de4674f4..0ba3482ea97 100644 --- a/website/docs/reference/resource-configs/alias.md +++ b/website/docs/reference/resource-configs/alias.md @@ -1,5 +1,5 @@ --- -resource_types: [models, seeds] +resource_types: [models, seeds, snapshots, tests] datatype: string --- @@ -12,7 +12,7 @@ This is a work in progress document. While this configuration applies to multipl Optionally specify a custom alias for a [model](docs/building-a-dbt-project/building-models) or [seed](docs/building-a-dbt-project/seeds). -When dbt creates a relation (table/view) in a database, it creates it as: `{{ database }}.{{ schema }}.{{ identifier }}`, e.g. `analytics.finance.payments` +When dbt creates a relation (/) in a database, it creates it as: `{{ database }}.{{ schema }}.{{ identifier }}`, e.g. `analytics.finance.payments` The standard behavior of dbt is: * If a custom alias is _not_ specified, the identifier of the relation is the resource name (i.e. the filename). @@ -26,7 +26,7 @@ To learn more about changing the way that dbt generates a relation's `identifier ### Seeds Configure a seed's alias in your `dbt_project.yml` file. -The seed at `seeds/country_codes.csv` will be built as a table named `country_mappings`. +The seed at `seeds/country_codes.csv` will be built as a named `country_mappings`. diff --git a/website/docs/reference/resource-configs/azuresynapse-configs.md b/website/docs/reference/resource-configs/azuresynapse-configs.md new file mode 100644 index 00000000000..3281fd9627c --- /dev/null +++ b/website/docs/reference/resource-configs/azuresynapse-configs.md @@ -0,0 +1,72 @@ +--- +title: "Microsoft Azure Synapse DWH configurations" +id: "azuresynapse-configs" +--- + +All [configuration options for the Microsoft SQL Server adapter](mssql-configs) also apply to this adapter. + +Additionally, the configuration options below are available. + +### Indices and distributions + +The main index and the distribution type can be set for models that are materialized to tables. + + + + + + + +```sql +{{ + config( + index='HEAP', + dist='ROUND_ROBIN' + ) +}} + +select * +from ... +``` + + + + + + + + + +```yaml +models: + your_project_name: + materialized: view + staging: + materialized: table + index: HEAP +``` + + + + + + + +The following are the supported index types: + +* `CLUSTERED COLUMNSTORE INDEX` (default) +* `HEAP` +* `CLUSTERED INDEX (COLUMN_NAME)` +* `CLUSTERED COLUMNSTORE INDEX ORDER(COLUMN_NAME)` + +The following are the supported distribution types: + +* `ROUND_ROBIN` (default) +* `HASH(COLUMN_NAME)` +* `REPLICATE` diff --git a/website/docs/reference/resource-configs/bigquery-configs.md b/website/docs/reference/resource-configs/bigquery-configs.md index 35c18606162..f57fba0fa05 100644 --- a/website/docs/reference/resource-configs/bigquery-configs.md +++ b/website/docs/reference/resource-configs/bigquery-configs.md @@ -40,15 +40,15 @@ Example usage for versions of dbt < 0.16.0: -BigQuery supports the use of a [partition by](https://cloud.google.com/bigquery/docs/data-definition-language#specifying_table_partitioning_options) clause to easily partition a table by a column or expression. This option can help decrease latency and cost when querying large tables. Note that partition pruning [only works](https://cloud.google.com/bigquery/docs/querying-partitioned-tables#pruning_limiting_partitions) when partitions are filtered using literal values (so selecting partitions using a subquery won't improve performance). +BigQuery supports the use of a [partition by](https://cloud.google.com/bigquery/docs/data-definition-language#specifying_table_partitioning_options) clause to easily partition a by a column or expression. This option can help decrease latency and cost when querying large tables. Note that partition pruning [only works](https://cloud.google.com/bigquery/docs/querying-partitioned-tables#pruning_limiting_partitions) when partitions are filtered using literal values (so selecting partitions using a won't improve performance). The `partition_by` config can be supplied as a dictionary with the following format: ```python { - "field": "", - "granularity": "< hour | day | month | year >" + "field": "", + "data_type": "", + "granularity": "" # Only required if data_type is "int64" "range": { @@ -291,9 +291,13 @@ models: ### Specifying labels -dbt supports the specification of BigQuery labels for the tables and views that it creates. These labels can be specified using the `labels` model config. +dbt supports the specification of BigQuery labels for the tables and views that it creates. These labels can be specified using the `labels` model config. The `labels` config can be provided in a model config, or in the `dbt_project.yml` file, as shown below. + +:::info Note +BigQuery requires that both key-value pair entries for labels have a maximum length of 63 characters. +::: **Configuring labels in a model file** @@ -376,7 +380,7 @@ Please note that in order for policy tags to take effect, [column-level `persist ## Merge behavior (incremental models) -The [`incremental_strategy` config](configuring-incremental-models#what-is-an-incremental_strategy) controls how dbt builds incremental models. dbt uses a [merge statement](https://cloud.google.com/bigquery/docs/reference/standard-sql/dml-syntax) on BigQuery to refresh incremental tables. +The [`incremental_strategy` config](configuring-incremental-models#about-incremental_strategy) controls how dbt builds incremental models. dbt uses a [merge statement](https://cloud.google.com/bigquery/docs/reference/standard-sql/dml-syntax) on BigQuery to refresh incremental tables. The `incremental_strategy` config can be set to one of two values: - `merge` (default) @@ -442,7 +446,7 @@ declare dbt_partitions_for_replacement array; set (dbt_partitions_for_replacement) = ( select as struct array_agg(distinct date(max_tstamp)) - from `my_project`.`my_dataset`.`sessions` + from `my_project`.`my_dataset`.{{ model_name }}__dbt_tmp ); /* @@ -594,6 +598,7 @@ select ... ## Authorized Views + New in v0.18.0 If the `grant_access_to` config is specified for a model materialized as a @@ -601,6 +606,8 @@ view, dbt will grant the view model access to select from the list of datasets provided. See [BQ docs on authorized views](https://cloud.google.com/bigquery/docs/share-access-views) for more details. + + ```yml @@ -629,10 +636,8 @@ models: -Views with this configuration will be able to select from objects in -`project_1.dataset_1` and `project_2.dataset_2`, even when they are located -elsewhere and queried by users who do not otherwise have -access to `project_1.dataset_1` and `project_2.dataset_2`. +Views with this configuration will be able to select from objects in `project_1.dataset_1` and `project_2.dataset_2`, even when they are located elsewhere and queried by users who do not otherwise have access to `project_1.dataset_1` and `project_2.dataset_2`. #### Limitations + The `grant_access_to` config is not thread-safe when multiple views need to be authorized for the same dataset. The initial `dbt run` operation after a new `grant_access_to` config is added should therefore be executed in a single thread. Subsequent runs using the same configuration will not attempt to re-apply existing access grants, and can make use of multiple threads. diff --git a/website/docs/reference/resource-configs/clickhouse-configs.md b/website/docs/reference/resource-configs/clickhouse-configs.md new file mode 100644 index 00000000000..9057b6cc228 --- /dev/null +++ b/website/docs/reference/resource-configs/clickhouse-configs.md @@ -0,0 +1,223 @@ +--- +title: "ClickHouse configurations" +id: "clickhouse-configs" +--- + +## Models + +| Type | Supported? | Details | +|-----------------------------|------------|----------------------------------------------------------------------------------------------------------------------------------| +| view materialization | YES | Creates a [view](https://clickhouse.com/docs/en/sql-reference/table-functions/view/). | +| table materialization | YES | Creates a [table](https://clickhouse.com/docs/en/operations/system-tables/tables/). See below for the list of supported engines. | +| incremental materialization | YES | Creates a table if it doesn't exist, and then writes only updates to it. | + +### View Materialization + +A dbt model can be created as a [ClickHouse view](https://clickhouse.com/docs/en/sql-reference/table-functions/view/) and configured using the following syntax: + + + + + + +```yaml +models: + : + +materialized: view +``` + + + + + + + +```jinja +{{ config(materialized = "view") }} +``` + + + + + +### Table Materialization + +A dbt model can be created as a [ClickHouse table](https://clickhouse.com/docs/en/operations/system-tables/tables/) and configured using the following syntax: + + + + + + +```yaml +models: + : + +materialized: table + +order_by: [ , ... ] + +engine: + +partition_by: [ , ... ] +``` + + + + + + + +```jinja +{{ config( + materialized = "table", + engine = "", + order_by = [ "", ... ], + partition_by = [ "", ... ], + ... + ] +) }} +``` + + + + + +#### Table Configuration + +| Option | Description | Required? | +|----------------|------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------| +| `materialized` | How the model will be materialized into ClickHouse. Must be `table` to create a table model. | Required | +| `engine` | The table engine to use when creating tables. See list of supported engines below. | Optional (default: `MergeTree()`) | +| `order_by` | A tuple of column names or arbitrary expressions. This allows you to create a small sparse index that helps find data faster. | Optional (default: `tuple()`) | +| `partition_by` | A partition is a logical combination of records in a table by a specified criterion. The partition key can be any expression from the table columns. | Optional | + +### Incremental Materialization + +Table model will be reconstructed for each dbt execution. This may be infeasible and extremely costly for larger result sets or complex transformations. To address this challenge and reduce the build time, a dbt model can be created as an incremental ClickHouse table and is configured using the following syntax: + + + + + + +```yaml +models: + : + +materialized: incremental + +order_by: [ , ... ] + +engine: + +partition_by: [ , ... ] + +unique_key: [ , ... ] + +inserts_only: [ True|False ] +``` + + + + + + + +```jinja +{{ config( + materialized = "incremental", + engine = "", + order_by = [ "", ... ], + partition_by = [ "", ... ], + unique_key = [ "", ... ], + inserts_only = [ True|False ], + ... + ] +) }} +``` + + + + + +#### Incremental Table Configuration + +| Option | Description | Required? | +|----------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------| +| `materialized` | How the model will be materialized into ClickHouse. Must be `table` to create a table model. | Required | +| `unique_key` | A tuple of column names that uniquely identify rows. For more details on uniqueness constraints, see [here](https://docs.getdbt.com/docs/building-a-dbt-project/building-models/configuring-incremental-models#defining-a-uniqueness-constraint-optional). | Required. If not provided altered rows will be added twice to the incremental table. | +| `engine` | The table engine to use when creating tables. See list of supported engines below. | Optional (default: `MergeTree()`) | +| `order_by` | A tuple of column names or arbitrary expressions. This allows you to create a small sparse index that helps find data faster. | Optional (default: `tuple()`) | +| `partition_by` | A partition is a logical combination of records in a table by a specified criterion. The partition key can be any expression from the table columns. | Optional | +| `inserts_only` | If set to True, incremental updates will be inserted directly to the target incremental table without creating intermediate table. Read more about this configuration in our [doc](https://clickhouse.com/docs/en/integrations/dbt/dbt-incremental-model#inserts-only-mode) | Optional (default: `False`) | + +## Snapshot + +dbt snapshots allow a record to be made of changes to a mutable model over time. This in turn allows point-in-time queries on models, where analysts can “look back in time” at the previous state of a model. This functionality is supported by the ClickHouse connector and is configured using the following syntax: + + + +```jinja +{{ + config( + target_schema = "", + unique_key = "", + strategy = "", + updated_at = "", + ) +}} +``` + + + +#### Snapshot Configuration + +| Option | Description | Required? | +|-----------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------| +| `target_schema` | A ClickHouse's database name where the snapshot table will be created. | Required | +| `unique_key` | A tuple of column names that uniquely identify rows. | Required. If not provided altered rows will be added twice to the incremental table. | +| `strategy` | Defines how dbt knows if a row has changed. More about dbt startegies [here](https://docs.getdbt.com/docs/building-a-dbt-project/snapshots#detecting-row-changes) | Required | +| `updated_at` | If using the timestamp strategy, the timestamp column to compare. | Only if using the timestamp strategy | + +## Supported Table Engines + +| Type | Details | +|------------------------|-------------------------------------------------------------------------------------------| +| MergeTree (default) | https://clickhouse.com/docs/en/engines/table-engines/mergetree-family/mergetree/. | +| HDFS | https://clickhouse.com/docs/en/engines/table-engines/integrations/hdfs | +| MaterializedPostgreSQL | https://clickhouse.com/docs/en/engines/table-engines/integrations/materialized-postgresql | +| S3 | https://clickhouse.com/docs/en/engines/table-engines/integrations/s3 | +| EmbeddedRocksDB | https://clickhouse.com/docs/en/engines/table-engines/integrations/embedded-rocksdb | +| Hive | https://clickhouse.com/docs/en/engines/table-engines/integrations/hive | + +If you encounter issues connecting to ClickHouse from dbt with one of the above engines, please report an issue [here](https://github.com/ClickHouse/dbt-clickhouse/issues). + +## Cross Database Macro Support + +dbt-clickhouse supports most of the cross database macros now included in dbt-core, with the following exceptions: +* The `listagg` SQL function (and therefore the corresponding dbt macro) is not supported by ClickHouse. You can achieve similar results with the ClickHouse `groupArray` function but in some cases subqueries may be required to achieve the desired ordering. +* The `split_part` SQL function is implemented in ClickHouse using the splitByChar function. This function requires using a constant string for the "split" delimiter, so the `delimeter` parameter used for this macro will be interpreted as a string, not a column name +* Similarly, the `replace` SQL function in ClickHouse requires constant strings for the `old_chars` and `new_chars` parameters, so those parameters will be interpreted as strings rather than column names when invoking this macro. + +## Setting `quote_columns` + +To prevent a warning, make sure to explicitly set a value for `quote_columns` in your `dbt_project.yml`. See the [doc on quote_columns](https://docs.getdbt.com/reference/resource-configs/quote_columns) for more information. + +```yaml +seeds: + +quote_columns: false #or `true` if you have csv column headers with spaces +``` + + diff --git a/website/docs/reference/resource-configs/column_types.md b/website/docs/reference/resource-configs/column_types.md index b902e0cd9f5..8834718b91a 100644 --- a/website/docs/reference/resource-configs/column_types.md +++ b/website/docs/reference/resource-configs/column_types.md @@ -20,22 +20,25 @@ seeds: +column_types: country_code: varchar(2) country_name: varchar(32) - ``` - + Or (as of v0.21): + + + ```yml version: 2 seeds: - name: country_codes config: - country_code: varchar(2) - country_name: varchar(32) + column_types: + country_code: varchar(2) + country_name: varchar(32) ``` diff --git a/website/docs/reference/resource-configs/database.md b/website/docs/reference/resource-configs/database.md index 9cedb290163..4cb31d6f899 100644 --- a/website/docs/reference/resource-configs/database.md +++ b/website/docs/reference/resource-configs/database.md @@ -1,5 +1,5 @@ --- -resource_types: [models, seeds] +resource_types: [models, seeds, tests] datatype: string --- @@ -12,7 +12,7 @@ This is a work in progress document. While this configuration applies to multipl Optionally specify a custom database for a [model](docs/building-a-dbt-project/building-models) or [seed](docs/building-a-dbt-project/seeds). (To specify a database for a [snapshot](snapshots), use the [`target_database` config](target_database)). -When dbt creates a relation (table/view) in a database, it creates it as: `{{ database }}.{{ schema }}.{{ identifier }}`, e.g. `analytics.finance.payments` +When dbt creates a relation (/) in a database, it creates it as: `{{ database }}.{{ schema }}.{{ identifier }}`, e.g. `analytics.finance.payments` The standard behavior of dbt is: * If a custom database is _not_ specified, the database of the relation is the target database (`{{ target.database }}`). diff --git a/website/docs/reference/resource-configs/docs.md b/website/docs/reference/resource-configs/docs.md new file mode 100644 index 00000000000..c35890e0bf7 --- /dev/null +++ b/website/docs/reference/resource-configs/docs.md @@ -0,0 +1,308 @@ +--- +resource_types: models +datatype: "{dictionary}" +default_value: {show: true} +--- + + + + + + +```yml +version: 2 + +models: + - name: model_name + docs: + show: true | false + +``` + + + + + + + +This property is not implemented for sources. + + + + + + + +```yml +version: 2 + +seeds: + - name: seed_name + docs: + show: true | false + +``` + + + + + + + + + +```yml +version: 2 + +snapshots: + - name: snapshot_name + docs: + show: true | false + +``` + + + + + + + + + +```yml +version: 2 + +analyses: + - name: analysis_name + docs: + show: true | false +``` + + + + + + + + + + + +```yml +version: 2 + +macros: + - name: macro_name + docs: + show: true | false + +``` + + + + + + + +## Definition +The docs field can be used to provide documentation-specific configuration to models. The only currently supported docs attribute is shown, which controls whether or not models are shown in the auto-generated documentation website. + +**Note:** hidden models will still appear in the dbt DAG visualization but will be identified as "hidden.” + + + +* `v0.16.0`: This property was added + + + +## Default +The default value for `show` is `true`. + +## Examples +### Mark a model as hidden + +```yml +models: + - name: sessions__tmp + docs: + show: false +``` + + + +### Mark a subfolder of models as hidden + +**Note:** This can also hide dbt packages. + + + +```yml +models: + # hiding models within the staging subfolder + tpch: + staging: + +materialized: view + +docs: + show: false + + # hiding a dbt package + dbt_artifacts: + +docs: + show: false +``` + + + + + + + +## Custom node colors + +The `docs` attribute now supports `node_color` to customize the node color in the DAG within dbt docs. You can define node colors in the files below and apply overrides where needed. + +`node_color` hiearchy: + +`` overrides `schema.yml` overrides `dbt_project.yml` + + +## Examples + +Add custom node colors to models within subdirectories based on hex codes or a plain color name. + +![Example](../../../../website/static/img/node_color_example.png) + +`marts/core/fct_orders.sql` with `node_color: red` overrides `dbt_project.yml` with `node_color: gold` + +`marts/core/schema.yml` with `node_color: #000000` overrides `dbt_project.yml` with `node_color: gold` + + +```yml +models: + tpch: + staging: + +materialized: view + +docs: + node_color: "#cd7f32" + + marts: + core: + materialized: table + +docs: + node_color: "gold" +``` + + + + + +```yml +models: + - name: dim_customers + description: Customer dimensions table + docs: + node_color: '#000000' +``` + + + + + +```sql +{{ + config( + materialized = 'view', + tags=['finance'], + docs={'node_color': 'red'} + ) +}} + +with orders as ( + + select * from {{ ref('stg_tpch_orders') }} + +), +order_item as ( + + select * from {{ ref('order_items') }} + +), +order_item_summary as ( + + select + order_key, + sum(gross_item_sales_amount) as gross_item_sales_amount, + sum(item_discount_amount) as item_discount_amount, + sum(item_tax_amount) as item_tax_amount, + sum(net_item_sales_amount) as net_item_sales_amount + from order_item + group by + 1 +), +final as ( + + select + + orders.order_key, + orders.order_date, + orders.customer_key, + orders.status_code, + orders.priority_code, + orders.clerk_name, + orders.ship_priority, + + 1 as order_count, + order_item_summary.gross_item_sales_amount, + order_item_summary.item_discount_amount, + order_item_summary.item_tax_amount, + order_item_summary.net_item_sales_amount + from + orders + inner join order_item_summary + on orders.order_key = order_item_summary.order_key +) +select + * +from + final + +order by + order_date + +``` + + + +If a `node_color` is incompatible with dbt docs, you will see a compile error, as in the example below. + +```shell +Invalid color name for docs.node_color: aweioohafio23f. It is neither a valid HTML color name nor a valid HEX code. +``` + + + +```yml +models: + tpch: + marts: + core: + materialized: table + +docs: + node_color: "aweioohafio23f" +``` + + + + diff --git a/website/docs/reference/resource-configs/enabled.md b/website/docs/reference/resource-configs/enabled.md index 7f63a3bd0be..b2f1a71360a 100644 --- a/website/docs/reference/resource-configs/enabled.md +++ b/website/docs/reference/resource-configs/enabled.md @@ -11,6 +11,9 @@ default_value: true { label: 'Seeds', value: 'seeds', }, { label: 'Snapshots', value: 'snapshots', }, { label: 'Tests', value: 'tests', }, + { label: 'Sources', value: 'sources', }, + { label: 'Metrics', value: 'metrics', }, + { label: 'Exposures', value: 'exposures', }, ] }> @@ -133,6 +136,121 @@ tests: + + + + +```yaml +sources: + [](resource-path): + [+](plus-prefix)enabled: true | false + +``` + + + + + + + +```yaml +version: 2 + +sources: + - name: [] + [config](resource-properties/config): + enabled: true | false + tables: + - name: [] + [config](resource-properties/config): + enabled: true | false + +``` + + + + + + + + + + + +Support for disabling metrics was added in dbt Core v1.3 + + + + + + + +```yaml +metrics: + [](resource-path): + [+](plus-prefix)enabled: true | false + +``` + + + + + +```yaml +version: 2 + +metrics: + - name: [] + [config](resource-properties/config): + enabled: true | false + +``` + + + + + + + + + + + +Support for disabling exposures was added in dbt Core v1.3 + + + + + + + +```yaml +exposures: + [](resource-path): + [+](plus-prefix)enabled: true | false + +``` + + + + + +```yaml +version: 2 + +exposures: + - name: [] + [config](resource-properties/config): + enabled: true | false + +``` + + + + + + + ## Definition @@ -148,7 +266,7 @@ If you are disabling models because they are no longer being used, but you want ## Examples ### Disable a model in a package in order to use your own version of the model. -This could be useful if you want to change the logic of a model in a package. For example, if you need to change the logic in the `segment_web_page_views` from the `segment` package ([original model](https://github.com/dbt-labs/segment/blob/master/models/base/segment_web_page_views.sql)): +This could be useful if you want to change the logic of a model in a package. For example, if you need to change the logic in the `segment_web_page_views` from the `segment` package ([original model](https://github.com/dbt-labs/segment/blob/main/models/base/segment_web_page_views.sql)): 1. Add a model named `segment_web_page_views` the same name to your own project. 2. To avoid a compilation error due to duplicate models, disable the segment package's version of the model like so: diff --git a/website/docs/reference/resource-configs/firebolt-configs.md b/website/docs/reference/resource-configs/firebolt-configs.md new file mode 100644 index 00000000000..9974be6818a --- /dev/null +++ b/website/docs/reference/resource-configs/firebolt-configs.md @@ -0,0 +1,357 @@ +--- +title: "Firebolt configurations" +id: "firebolt-configs" +--- + + +## Setting `quote_columns` + +To prevent a warning, make sure to explicitly set a value for `quote_columns` in your `dbt_project.yml`. See the [doc on quote_columns](https://docs.getdbt.com/reference/resource-configs/quote_columns) for more information. + +```yaml +seeds: + +quote_columns: false #or `true` if you have csv column headers with spaces +``` + + +## Model Configuration for Fact Tables + +A dbt model can be created as a Firebolt fact and configured using the following syntax: + + + + + + +```yaml +models: + : + +materialized: table + +table_type: fact + +primary_index: [ , ... ] + +indexes: + - type: aggregating + key_column: [ , ... ] + aggregation: [ , ... ] + ... +``` + + + + + + + +```yaml +models: + - name: + config: + materialized: table + table_type: fact + primary_index: [ , ... ] + indexes: + - type: aggregating | join + key_column: [ , ... ] + aggregation: [ , ... ] + ... +``` + + + + + + + +```jinja +{{ config( + materialized = "table" + table_type = "fact" + primary_index = [ "", ... ], + indexes = [ + { + type = "aggregating" + key_column = [ "", ... ], + aggregation = [ "", ... ], + }, + ... + ] +) }} +``` + + + + + + +#### Fact Table Configurations + +| Configuration | Description | +|-------------------|-------------------------------------------------------------------------------------------| +| `materialized` | How the model will be materialized into Firebolt. Must be `table` to create a fact table. | +| `table_type` | Whether the materialized table will be a [fact or dimension](https://docs.firebolt.io/concepts/working-with-tables#fact-and-dimension-tables) table. | +| `primary_index` | Sets the primary index for the fact table using the inputted list of column names from the model. Required for fact tables. | +| `indexes` | A list of aggregating indexes to create on the fact table. | +| `type` | Specifies whether the index is an aggregating index or join index. Join indexes only apply to dimension tables, so for fact tables set to `aggregating`. | +| `key_column` | Sets the grouping of the aggregating index using the inputted list of column names from the model. | +| `aggregation` | Sets the aggregations on the aggregating index using the inputted list of SQL agg expressions. | + + +#### Example of a Fact Table With an Aggregating Index + +``` +{{ config( + materialized = "table", + table_type = "fact", + primary_index = "id", + indexes = [ + { + type: "aggregating", + key_column: "order_id", + aggregation: ["COUNT(DISTINCT status)", "AVG(customer_id)"] + } + ] +) }} +``` + + +## Model Configuration for Dimension Tables + +A dbt model can be materialized as a Firebolt dimension table and configured using the following syntax: + + + + + + +```yaml +models: + : + +materialized: table + +table_type: dimension + +indexes: + - type: join + join_column: + dimension_column: [ , ... ] + ... +``` + + + + + + + +```yaml +models: + - name: + config: + materialized: table + table_type: dimension + indexes: + - type: join + join_column: + dimension_column: [ , ... ], + ... +``` + + + + + + + +```jinja +{{ config( + materialized = "table", + table_type = "dimension", + indexes = [ + { + type = "join", + join_column = "", + dimension_column: [ "", ... ] + }, + ... + ], +) }} +``` + + + + + + +#### Dimension Table Configurations + +| Configuration | Description | +|--------------------|-------------------------------------------------------------------------------------------| +| `materialized` | How the model will be materialized into Firebolt. Must be `table` to create a dimension table. | +| `table_type` | Whether the materialized table will be a [fact or dimension](https://docs.firebolt.io/concepts/working-with-tables#fact-and-dimension-tables) table. | +| `indexes` | A list of join indexes to create on the dimension table. | +| `type` | Specifies whether the index is an aggregating index or join index. Aggregating indexes only apply to fact tables, so for dimension tables set to `join`. | +| `join_column` | Sets the join key of the join index using the inputted column name from the model. | +| `dimension_column` | Sets the columns to be loaded into memory on the join index using the inputted list of column names from the mode. | + + +#### Example of a Dimension Table With a Join Index + +``` +{{ config( + materialized = "table", + table_type = "dimension", + indexes = [ + { + type: "join", + join_column: "order_id", + dimension_column: ["customer_id", "status"] + } + ] +) }} +``` + + +## How Aggregating Indexes and Join Indexes Are Named + +In dbt-firebolt, you do not provide names for aggregating indexes and join indexes; they are named programmatically. dbt will generate index names using the following convention: + +``` +_____ +``` + +For example, a join index could be named `my_users__id__join_1633504263` and an aggregating index could be named `my_orders__order_date__aggregating_1633504263`. + + +## Managing Ingestion via External Tables + +`dbt-firebolt` supports dbt's [external tables feature](https://docs.getdbt.com/reference/resource-properties/external), which allows dbt to manage the table ingestion process from S3 into Firebolt. This is an optional feature but can be highly convenient depending on your use case. + +More information on using external tables including properly configuring IAM can be found in the Firebolt [documentation](https://docs.firebolt.io/sql-reference/commands/ddl-commands#create-external-table). + + +#### Installation of External Tables Package + +To install and use `dbt-external-tables` with Firebolt, you must: + +1. Add this package to your packages.yml: + + ```yaml + packages: + - package: dbt-labs/dbt_external_tables + version: + ``` + +2. Add these fields to your `dbt_project.yml`: + + ```yaml + dispatch: + - macro_namespace: dbt_external_tables + search_order: ['dbt', 'dbt_external_tables'] + ``` + +3. Pull in the `packages.yml` dependencies by calling `dbt deps`. + + +#### Using External Tables + +To use external tables, you must define a table as `external` in your `dbt_project.yml` file. Every external table must contain the fields `url`, `type`, and `object_pattern`. Note that the Firebolt external table specification requires fewer fields than what is specified in the dbt documentation. + +In addition to specifying the columns, an external table may specify partitions. Partitions are not columns and they cannot have the same name as columns. To avoid yaml parsing errors, remember to encase string literals (such as the `url` and `object_pattern` values) in single quotation marks. + + +#### dbt_project.yml Syntax For an External Table + +```yml +sources: + - name: firebolt_external + schema: "{{ target.schema }}" + loader: S3 + + tables: + - name: + external: + url: 's3:///' + object_pattern: '' + type: '' + credentials: + internal_role_arn: arn:aws:iam::id:/ + external_role_id: + object_pattern: '' + compression: '' + partitions: + - name: + data_type: + regex: '' + columns: + - name: + data_type: +``` + +#### Running External tables + +The `stage_external_sources` macro is inherited from the [dbt-external-tables package](https://github.com/dbt-labs/dbt-external-tables#syntax) and is the primary point of entry when using thes package. It has two operational modes: standard and "full refresh." + +```bash +# iterate through all source nodes, create if missing, refresh metadata +$ dbt run-operation stage_external_sources + +# iterate through all source nodes, create or replace (no refresh command is required as data is fetched live from remote) +$ dbt run-operation stage_external_sources --vars "ext_full_refresh: true" +``` + +## Incremental models + +The [`incremental_strategy` configuration](https://docs.getdbt.com/docs/building-a-dbt-project/building-models/configuring-incremental-models#about-incremental_strategy) controls how dbt builds incremental models. Firebolt currently supports the `append` configuration. You can specify `incremental_strategy` in `dbt_project.yml` or within a model file's `config()` block. The `append` configuration is the default. Specifying this configuration is optional. + +The `append` strategy performs an `INSERT INTO` statement with all the new data based on the model definition. This strategy doesn't update or delete existing rows, so if you do not filter the data to the most recent records only, it is likely that duplicate records will be inserted. + +Example source code: + +``` +{{ config( + materialized = 'incremental', + incremental_strategy='append' +) }} + +/* All rows returned by this query will be appended to the existing model */ + + +select * from {{ ref('raw_orders') }} +{% if is_incremental() %} + where order_date > (select max(order_date) from {{ this }}) +{% endif %} +``` + +Example run code: + +```sql +CREATE DIMENSION TABLE IF NOT EXISTS orders__dbt_tmp AS +SELECT * FROM raw_orders +WHERE order_date > (SELECT MAX(order_date) FROM orders); + +INSERT INTO orders VALUES ([columns]) +SELECT ([columns]) +FROM orders__dbt_tmp; +``` + +## Seeds behavior + +When running the ```dbt seed``` command we perform a `DROP CASCADE` operation instead of `TRUNCATE`. + +## Practice + +You can look at our modified version of the jaffle_shop, [jaffle_shop_firebolt](https://github.com/firebolt-db/jaffle_shop_firebolt), to see how indexes, as well as external tables, can be set or clone and execute the commands listed in the README.md diff --git a/website/docs/reference/resource-configs/full_refresh.md b/website/docs/reference/resource-configs/full_refresh.md index d78766e9e6d..69c30a4de77 100644 --- a/website/docs/reference/resource-configs/full_refresh.md +++ b/website/docs/reference/resource-configs/full_refresh.md @@ -67,7 +67,13 @@ Optionally set a resource to always or never full-refresh. `full_refresh` config will take precedence over the presence or absence of the `--full-refresh` flag. - If the `full_refresh` config is `none` or omitted, the resource will use the value of the `--full-refresh` flag. -This logic is encoded in the [`should_full_refresh()`](https://github.com/dbt-labs/dbt-core/blob/HEAD/core/dbt/include/global_project/macros/materializations/helpers.sql#L68) macro. + + +**Note:** The `--full-refresh` flag also supports a short name, `-f`. + + + +This logic is encoded in the [`should_full_refresh()`](https://github.com/dbt-labs/dbt-core/blob/main/core/dbt/include/global_project/macros/materializations/configs.sql#L6) macro. ## Usage @@ -78,7 +84,7 @@ This logic is encoded in the [`should_full_refresh()`](https://github.com/dbt-la ### Seeds - + ## Recommendation Set `full_refresh: false` for models of especially large datasets, which you would _never_ want dbt to fully drop and recreate. diff --git a/website/docs/reference/resource-configs/glue-configs.md b/website/docs/reference/resource-configs/glue-configs.md new file mode 100644 index 00000000000..62ec39bcbf7 --- /dev/null +++ b/website/docs/reference/resource-configs/glue-configs.md @@ -0,0 +1,240 @@ +--- +title: "AWS Glue configurations" +id: "glue-configs" +--- + + + +## Configuring tables + +When materializing a model as `table`, you may include several optional configs that are specific to the dbt-glue plugin, in addition to the [Apache Spark model configuration](spark-configs#configuring-tables). + +| Option | Description | Required? | Example | +|---------|----------------------------------------------------|-------------------------|--------------------------| +| custom_location | By default, the adapter will store your data in the following path: `location path`/`database`/`table`. If you don't want to follow that default behaviour, you can use this parameter to set your own custom location on S3 | No | `s3://mycustombucket/mycustompath` | + +## Incremental models + +dbt seeks to offer useful, intuitive modeling abstractions by means of its built-in configurations and materializations. + +For that reason, the dbt-glue plugin leans heavily on the [`incremental_strategy` config](configuring-incremental-models#about-incremental_strategy). This config tells the incremental materialization how to build models in runs beyond their first. It can be set to one of three values: + - **`append`** (default): Insert new records without updating or overwriting any existing data. + - **`insert_overwrite`**: If `partition_by` is specified, overwrite partitions in the table with new data. If no `partition_by` is specified, overwrite the entire table with new data. + - **`merge`** (Apache Hudi only): Match records based on a `unique_key`; update old records, insert new ones. (If no `unique_key` is specified, all new data is inserted, similar to `append`.) + +Each of these strategies has its pros and cons, which we'll discuss below. As with any model config, `incremental_strategy` may be specified in `dbt_project.yml` or within a model file's `config()` block. + +**Notes:** +The default strategie is **`insert_overwrite`** + +### The `append` strategy + +Following the `append` strategy, dbt will perform an `insert into` statement with all new data. The appeal of this strategy is that it is straightforward and functional across all platforms, file types, connection methods, and Apache Spark versions. However, this strategy _cannot_ update, overwrite, or delete existing data, so it is likely to insert duplicate records for many data sources. + + + + + + + +```sql +{{ config( + materialized='incremental', + incremental_strategy='append', +) }} + +-- All rows returned by this query will be appended to the existing table + +select * from {{ ref('events') }} +{% if is_incremental() %} + where event_ts > (select max(event_ts) from {{ this }}) +{% endif %} +``` + + + + + + +```sql +create view spark_incremental__dbt_tmp as + + select * from analytics.events + + where event_ts >= (select max(event_ts) from {{ this }}) + +; + +insert into table analytics.spark_incremental + select `date_day`, `users` from spark_incremental__dbt_tmp +``` + +; + +drop view spark_incremental__dbt_tmp + + + + + +### The `insert_overwrite` strategy + +This strategy is most effective when specified alongside a `partition_by` clause in your model config. dbt will run an [atomic `insert overwrite` statement](https://spark.apache.org/docs/latest/sql-ref-syntax-dml-insert-overwrite-table.html) that dynamically replaces all partitions included in your query. Be sure to re-select _all_ of the relevant data for a partition when using this incremental strategy. + +If no `partition_by` is specified, then the `insert_overwrite` strategy will atomically replace all contents of the table, overriding all existing data with only the new records. The column schema of the table remains the same, however. This can be desirable in some limited circumstances, since it minimizes downtime while the table contents are overwritten. The operation is comparable to running `truncate` + `insert` on other databases. For atomic replacement of Delta-formatted tables, use the `table` materialization (which runs `create or replace`) instead. + + + + + + +```sql +{{ config( + materialized='incremental', + partition_by=['date_day'], + file_format='parquet' +) }} + +/* + Every partition returned by this query will be overwritten + when this model runs +*/ + +with new_events as ( + + select * from {{ ref('events') }} + + {% if is_incremental() %} + where date_day >= date_add(current_date, -1) + {% endif %} + +) + +select + date_day, + count(*) as users + +from events +group by 1 +``` + + + + + + + +```sql +create view spark_incremental__dbt_tmp as + + with new_events as ( + + select * from analytics.events + + + where date_day >= date_add(current_date, -1) + + + ) + + select + date_day, + count(*) as users + + from events + group by 1 + +; + +insert overwrite table analytics.spark_incremental + partition (date_day) + select `date_day`, `users` from spark_incremental__dbt_tmp + +; + +drop view spark_incremental__dbt_tmp +``` + + + + + +Specifying `insert_overwrite` as the incremental strategy is optional, since it's the default strategy used when none is specified. + +### The `merge` strategy + +**Usage notes:** The `merge` incremental strategy requires: +- `file_format: hudi` +- AWS Glue runtime 2 with hudi libraries as extra jars + +You can add hudi libraries as extra jars in the classpath using extra_jars options in your profiles.yml. +Here is an example: +```yml +extra_jars: "s3://dbt-glue-hudi/Dependencies/hudi-spark.jar,s3://dbt-glue-hudi/Dependencies/spark-avro_2.11-2.4.4.jar" +``` + +dbt will run an [atomic `merge` statement](https://hudi.apache.org/docs/writing_data#spark-datasource-writer) which looks nearly identical to the default merge behavior on Snowflake and BigQuery. If a `unique_key` is specified (recommended), dbt will update old records with values from new records that match on the key column. If a `unique_key` is not specified, dbt will forgo match criteria and simply insert all new records (similar to `append` strategy). + + + + + + +```sql +{{ config( + materialized='incremental', + incremental_strategy='merge', + unique_key='user_id', + file_format='hudi' +) }} + +with new_events as ( + + select * from {{ ref('events') }} + + {% if is_incremental() %} + where date_day >= date_add(current_date, -1) + {% endif %} + +) + +select + user_id, + max(date_day) as last_seen + +from events +group by 1 +``` + + + + + + +## Persisting model descriptions + +Relation-level docs persistence is inherited from dbt-spark, for more details, check [Apache Spark model configuration](spark-configs#persisting-model-descriptions). + +## Always `schema`, never `database` + +This section is also inherited from dbt-spark, for more details, check [Apache Spark model configuration](spark-configs#always-schema-never-database). diff --git a/website/docs/reference/resource-configs/grants.md b/website/docs/reference/resource-configs/grants.md new file mode 100644 index 00000000000..197bd76aad8 --- /dev/null +++ b/website/docs/reference/resource-configs/grants.md @@ -0,0 +1,261 @@ +--- +resource_types: [models,seeds,snapshots] +datatype: "{}" +default_value: {} +id: "grants" +--- + +You can manage access to the datasets you're producing with dbt by using grants. To implement these permissions, define grants as resource configs on each model, seed, or snapshot. Define the default grants that apply to the entire project in your `dbt_project.yml`, and define model-specific grants within each model's SQL or YAML file. + +The grant resource configs enable you to apply permissions at build time to a specific set of recipients and model, seed, or snapshot. When your model, seed, or snapshot finishes building, dbt ensures that the grants on its view or table match exactly the grants you have configured. + +dbt aims to use the most efficient approach when updating grants, which varies based on the adapter you're using, and whether dbt is replacing or updating an object that already exists. You can always check the debug logs for the full set of grant and revoke statements that dbt runs. + +dbt encourages you to use grants as resource configs whenever possible in Core v1.2 and higher. In versions prior to Core v1.2, you were limited to using hooks for grants. Occasionally, you still might need to write grants statements manually and run them using hooks. For example, hooks may be appropriate if you want to: + +* Apply grants in a more complex or custom manner, beyond what the built-in grants capability can provide. +* Apply grants on other database objects besides views and tables. +* Take advantage of more-advanced permission capabilities offered by your data platform, for which dbt does not (yet!) offer out-of-the-box support using resource configuration. +* Create more granular row- and column-level access, use masking policies, or apply future grants. + +For more information on hooks, see [Hooks & operations](/building-a-dbt-project/hooks-operations). + +## Definition + +You can use the `grants` field to set permissions or grants for a resource. When you run a model, seed or seed, or snapshot a snapshot, dbt will run `grant` and/or `revoke` statements to ensure that the permissions on the database object match the `grants` you have configured on the resource. + +Like all configurations, `grants` will be included in dbt project metadata, including [the manifest artifact](dbt-artifacts/manifest-json). + +### Common syntax + +Grants have two key components: + +* **Privilege:** A right to perform a specific action or set of actions on an object in the database, such as selecting data from a table. +* **Grantees:** One or more recipients of granted privileges. Some platforms also call these "principals." For example, a grantee could be a user, a group of users, a role held by one or more users (Snowflake), or a service account (BigQuery/GCP). + +## Configuring grants + +You can configure `grants` in `dbt_project.yml` to apply grants to many resources at once—all models in your project, a package, or a subfolder—and you can also configure `grants` one-by-one for specific resources, in yaml `config:` blocks or right within their `.sql` files. + + + + + + + +```yml +models: + - name: specific_model + config: + grants: + select: ['reporter', 'bi'] +``` + + + +The `grants` config can also be defined: + +- under the `models` config block in `dbt_project.yml` +- in a `config()` Jinja macro within a model's SQL file + +See [configs and properties](configs-and-properties) for details. + + + + + + + +```yml +seeds: + - name: seed_name + config: + grants: + select: ['reporter', 'bi'] +``` + + + +The `grants` config can also be defined under the `seeds` config block in `dbt_project.yml`. See [configs and properties](configs-and-properties) for details. + + + + + + + +```yml +snapshots: + - name: snapshot_name + config: + grants: + select: ['reporter', 'bi'] +``` + + + +The `grants` config can also be defined: + +- under the `snapshots` config block in `dbt_project.yml` +- in a `config()` Jinja macro within a snapshot's SQL block + +See [configs and properties](configs-and-properties) for details. + + + + +### Grant config inheritance + +When you set `grants` for the same model in multiple places, such as in `dbt_project.yml` and in a more-specific `.sql` or `.yml` file, dbt's default behavior replaces the less-specific set of grantees with the more-specific set of grantees. This "merge and clobber" behavior updates each privilege when dbt parses your project. + +For example: + + + +```yml +models: + +grants: + select: ['user_a', 'user_b'] +``` + + + + + +```sql +{{ config(grants = {'select': ['user_c']}) }} +``` + + + +As a result of this configuration, `specific_model` will be configured to grant the `select` privilege to `user_c` _only_. After you run `specific_model`, that is the only granted privilege you would see in the database, and the only `grant` statement you would find in dbt's logs. + +Let's say we wanted to _add_ `user_c` to the existing list of grantees receiving the `select` privilege on `specific_model`, rather than _replacing_ that list entirely. To accomplish that, we can use the `+` ("addition") symbol, prefixing the name of the privilege: + + + +```sql +{{ config(grants = {'+select': ['user_c']}) }} +``` + + + +Now, the model will grant select to `user_a`, `user_b`, AND `user_c`! + +**Notes:** +- This will only take effect for privileges which include the `+` prefix. Each privilege controls that behavior separately. If we were granting other privileges, in addition to `select`, and those privilege names lacked the `+` prefix, they would continue to "clobber" rather than "add" new grantees. +- This use of `+`, controlling clobber vs. add merge behavior, is distinct from the use of `+` in `dbt_project.yml` (shown in the example above) for defining configs with dictionary values. For more information, see [the plus prefix](https://docs.getdbt.com/reference/resource-configs/plus-prefix). +- `grants` is the first config to support a `+` prefix for controlling config merge behavior. Currently, it's the only one. If it proves useful, we may extend this capability to new and existing configs in the future. + +## General examples + +You can grant each permission to a single grantee, or a set of multiple grantees. In this example, we're granting `select` on this model to just `bi_user`, so that it can be queried in our Business Intelligence (BI) tool. + + + +```sql +{{ config(materialized = 'table', grants = { + 'select': 'bi_user' +}) }} +``` + + + +When dbt runs this model for the first time, it will create the table, and then run code like: +```sql +grant select on schema_name.table_model to bi_user; +``` + +In this case, we're creating an incremental model, and granting the `select` privilege to two recipients: `bi_user` and `reporter`. + + + +```sql +{{ config(materialized = 'incremental', grants = { + 'select': ['bi_user', 'reporter'] +}) }} +``` + + + +When dbt runs this model for the first time, it will create the table, and then run code like: +```sql +grant select on schema_name.incremental_model to bi_user, reporter; +``` + +In subsequent runs, dbt will use database-specific SQL to show the grants already on `incremental_model`, and then determine if any `revoke` or `grant` statements are needed. + + +## Database-specific requirements and notes + +While we try to standardize the terms we use to describe different features, you will always find nuances in different databases. This section outlines some of those database-specific requirements and notes. + +In our examples above and below, you will find us referring to a privilege named `select`, and a grantee named `another_user`. Many databases use these or similar terms. Be aware that your database may require different syntax for privileges and grantees; you must configure `grants` in dbt with the appropriate names for both. + + + +
+ +On BigQuery, "privileges" are called "roles," and they take the form `roles/service.roleName`. For instance, instead of granting `select` on a model, you would grant `roles/bigquery.dataViewer`. + +Grantees can be users, groups, service accounts, domains—and each needs to be clearly demarcated as such with a prefix. For instance, to grant access on a model to `someone@yourcompany.com`, you need to specify them as `user:someone@yourcompany.com`. + +We encourage you to read Google's documentation for more context: +- [Understanding GCP roles](https://cloud.google.com/iam/docs/understanding-roles) +- [How to format grantees](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-control-language#user_list) + + + +### BigQuery examples + +Granting permission using SQL and BigQuery: + +```sql +{{ config(grants = {'roles/bigquery.dataViewer': ['user:someone@yourcompany.com']}) }} +``` + +Granting permission in a model schema using BigQuery: + + + +```yml +models: + - name: specific_model + config: + grants: + roles/bigquery.dataViewer: ['user:someone@yourcompany.com'] +``` + + + +
+ +
+ +- OSS Apache Spark / Delta Lake do not support `grants`. +- Databricks automatically enables `grants` on SQL endpoints. For interactive clusters, admins should enable grant functionality using these two setup steps in the Databricks documentation: + - [Enable table access control for your workspace](https://docs.databricks.com/administration-guide/access-control/table-acl.html) + - [Enable table access control for a cluster](https://docs.databricks.com/security/access-control/table-acls/table-acl.html) + +
+ +
+ +* No special requirements at this time. + +
+ +
+ +* dbt accounts for the [`copy_grants` configuration](/reference/resource-configs/snowflake-configs#copying-grants) when calculating which grants need to be added or removed. + +
+ +
diff --git a/website/docs/reference/resource-configs/greenplum-configs.md b/website/docs/reference/resource-configs/greenplum-configs.md new file mode 100644 index 00000000000..b9115553542 --- /dev/null +++ b/website/docs/reference/resource-configs/greenplum-configs.md @@ -0,0 +1,133 @@ +--- +title: "Greenplum configurations" +id: "greenplum-configs" +--- + +## Performance Optimizations + +Tables in Greenplum have powerful optimization configurations to improve query performance: + + - distribution + - column orientation + - compression + - `appendonly` toggle + - partitions + +Supplying these values as model-level configurations apply the corresponding settings in the generated `CREATE TABLE`(except partitions). Note that these settings will have no effect for models set to `view`. + +### Distribution + +In Greenplum, you can choose a [distribution key](https://gpdb.docs.pivotal.io/6-4/admin_guide/distribution.html), that will be used to sort data by segments. Joining on the partition will become more performant after specifying distribution. + +By default dbt-greenplum distributes data `RANDOMLY`. To implement a distribution key you need to specify the `distributed_by` parameter in model's config: + +```sql +{{ + config( + ... + distributed_by='' + ... + ) +}} + + +select ... +``` + +Also you can choose `DISTRIBUTED REPLICATED` option: + +```sql +{{ + config( + ... + distributed_replicated=true + ... + ) +}} + + +select ... +``` + +### Column orientation + +Greenpum supports two type of [orientation](https://gpdb.docs.pivotal.io/6-6/admin_guide/ddl/ddl-storage.html#topic39) row and column: + +```sql +{{ + config( + ... + orientation='column' + ... + ) +}} + + +select ... +``` + +### Compression + +Compression allows reducing read-write time. Greenplum suggest several [algorithms](https://gpdb.docs.pivotal.io/6-6/admin_guide/ddl/ddl-storage.html#topic40) algotihms to compress append-optimized tables: + - RLE_TYPE(only for column oriented table) + - ZLIB + - ZSTD + - QUICKLZ + +```sql +{{ + config( + ... + appendonly='true', + compresstype='ZLIB', + compresslevel=3, + blocksize=32768 + ... + ) +}} + + +select ... +``` + +As you can see, you can also specify `compresslevel` and `blocksize`. + +### Partition + +Greenplum does not support partitions with `create table as` [construction](https://gpdb.docs.pivotal.io/6-9/ref_guide/sql_commands/CREATE_TABLE_AS.html), so you need to build model in two steps + +1. create table schema +2. insert data + +To implement partitions into your dbt-model you need to specify the following config parameters: + - `fields_string` - definition of columns name, type and constraints + - `raw_partition` - partition specification + +```sql +{% set fields_string %} + some_filed int4 null, + date_field timestamp NULL +{% endset %} + + +{% set raw_partition %} + PARTITION BY RANGE (date_field) + ( + START ('2021-01-01'::timestamp) INCLUSIVE + END ('2023-01-01'::timestamp) EXCLUSIVE + EVERY (INTERVAL '1 day'), + DEFAULT PARTITION default_part + ); +{% endset %} + +{{ + config( + ... + fields_string=fields_string, + raw_partition=raw_partition, + ... + ) +}} + +select * +``` \ No newline at end of file diff --git a/website/docs/reference/resource-configs/hive-configs.md b/website/docs/reference/resource-configs/hive-configs.md new file mode 100644 index 00000000000..1fb498ec8ce --- /dev/null +++ b/website/docs/reference/resource-configs/hive-configs.md @@ -0,0 +1,52 @@ +--- +title: "Apache Hive configurations" +id: "hive-configs" +--- + +## Configuring tables + +When materializing a model as `table`, you may include several optional configs that are specific to the dbt-hive plugin, in addition to the standard [model configs](model-configs). + +| Option | Description | Required? | Example | +|---------|----------------------------------------------------|-------------------------|--------------------------| +| partition_by | partition by a column, typically a directory per partition is created | No | partition_by=['name'] | +| clustered_by | second level division of a partitioned column | No | clustered_by=['age'] | +| file_format | underlying storage format of the table, see https://cwiki.apache.org/confluence/display/Hive/FileFormats for supported formats | No | file_format='PARQUET' | +| location | storage location, typically an hdfs path | No | LOCATION='/user/etl/destination' | +| comment | comment for the table | No | comment='this is the cleanest model' | + +## Incremental models + +Supported modes for incremental model: + - **`append`** (default): Insert new records without updating or overwriting any existing data. + - **`insert_overwrite`**: For new records, insert data. When used along with partition clause, update data for changed record and insert data for new records. + +## Example: Using partition_by config option + + + +```sql +{{ + config( + materialized='table', + unique_key='id', + partition_by=['city'], + ) +}} + +with source_data as ( + select 1 as id, "Name 1" as name, "City 1" as city, + union all + select 2 as id, "Name 2" as name, "City 2" as city, + union all + select 3 as id, "Name 3" as name, "City 2" as city, + union all + select 4 as id, "Name 4" as name, "City 1" as city, +) + +select * from source_data +``` + + + +In the above example, a sample table is created with partition_by and other config options. One thing to note when using partition_by option is that the select query should always have the column name used in partition_by option as the last one, as can be seen for the ```city``` column name used in the above query. If the partition_by clause is not the same as the last column in select statement, Hive will flag an error when trying to create the model. diff --git a/website/docs/reference/resource-configs/impala-configs.md b/website/docs/reference/resource-configs/impala-configs.md new file mode 100644 index 00000000000..5564df115e7 --- /dev/null +++ b/website/docs/reference/resource-configs/impala-configs.md @@ -0,0 +1,66 @@ +--- +title: "Apache Impala configurations" +id: "impala-configs" +--- + +## Configuring tables + +When materializing a model as `table`, you may include several optional configs that are specific to the dbt-impala plugin, in addition to the standard [model configs](model-configs). + +| Option | Description | Required? | Example | +|---------|----------------------------------------------------|-------------------------|--------------------------| +| partition_by | partition by a column, typically a directory per partition is created | No | partition_by=['name'] | +| sort_by | sort by a column | No | sort_by=['age'] | +| row_format | format to be used when storing individual arows | No | row_format='delimited' | +| stored_as | underlying storage format of the table | No | stored_as='PARQUET' | +| location | storage location, typically an hdfs path | No | LOCATION='/user/etl/destination' | +| comment | comment for the table | No | comment='this is the cleanest model' | +| serde_properties | SerDes ([de-]serialization) prperties of table | No | serde_properties="('quoteChar'='\'', 'escapeChar'='\\')" | +| tbl_properties | any metadata can be stored as key/value pair with the table | No | tbl_properties="('dbt_test'='1')" | +| is_cached | true or false - if this table is cached | No | is_cached=false (default) | +| cache_pool | cache pool name to use if is_cached is set to true | No | | +| replication_factor | cache replication factor to use if is_cached is set to true | No | | +| external | is this an external table - true / false | No | external=true | + +For Cloudera specific options for above parameters see documentation of CREATE TABLE (https://docs.cloudera.com/documentation/enterprise/6/6.3/topics/impala_create_table.html) + +## Incremental models + +Supported modes for incremental model: + - **`append`** (default): Insert new records without updating or overwriting any existing data. + - **`insert_overwrite`**: For new records, insert data. When used along with partition clause, update data for changed record and insert data for new records. + + +Unsupported modes: + - **`unique_key`** This is not suppored option for incremental models in dbt-impala + - **`merge`**: Merge is not supported by the underlying warehouse, and hence not supported by dbt-impala + +## Example: Using partition_by config option + + + +```sql +{{ + config( + materialized='table', + unique_key='id', + partition_by=['city'], + ) +}} + +with source_data as ( + select 1 as id, "Name 1" as name, "City 1" as city, + union all + select 2 as id, "Name 2" as name, "City 2" as city, + union all + select 3 as id, "Name 3" as name, "City 2" as city, + union all + select 4 as id, "Name 4" as name, "City 1" as city, +) + +select * from source_data +``` + + + +In the above example, a sample table is created with partition_by and other config options. One thing to note when using partition_by option is that the select query should always have the column name used in partition_by option as the last one, as can be seen for the ```city``` column name used in the above query. If the partition_by clause is not the same as the last column in select statement, Impala will flag an error when trying to create the model. diff --git a/website/docs/reference/resource-configs/materialize-configs.md b/website/docs/reference/resource-configs/materialize-configs.md new file mode 100644 index 00000000000..2f0180de865 --- /dev/null +++ b/website/docs/reference/resource-configs/materialize-configs.md @@ -0,0 +1,72 @@ +--- +title: "Materialize configurations" +id: "materialize-configs" +--- + +## Performance optimizations + +### Incremental models +Materialize, at its core, is a real-time database that delivers incremental view updates without ever compromising on latency or correctness. +Materialized views are incremental models, defined once. + +### Indexes + +Materialized views (`materializedview`), views (`view`) and sources (`source`) may have a list of `indexes` defined. Each [Materialize index](https://materialize.com/docs/sql/create-index/) can have the following components: + +- `columns` (list, required): one or more columns on which the index is defined +- `type` (string, optional): a supported index type. The only supported type is [`arrangement`](https://materialize.com/docs/overview/arrangements/). + + + +```sql +{{ config(materialized='view', + indexes=[{'columns': ['symbol']}]) }} + +select ... +``` + + + +If one or more indexes are configured on a resource, dbt will run `create index` statement(s) as part of that resource's , within the same transaction as its main `create` statement. For the index's name, dbt uses a hash of its properties and the current timestamp, in order to guarantee uniqueness and avoid namespace conflict with other indexes. + +```sql +create index if not exists +"3695050e025a7173586579da5b27d275" +on "my_target_database"."my_target_schema"."view_model" +(symbol); +``` + +You can also configure indexes for a number of resources at once: + + + +```yaml +models: + project_name: + subdirectory: + +indexes: + - columns: ['symbol'] +``` + + + +### Tests + + + +- **v1.1.1:** Provide support for storing the results of a test query in a materialized view, using the `store_failures` config. + + + +If you set the optional `--store-failures` flag or [`store_failures` config](resource-configs/store_failures), dbt will create a materialized view using the test query. This view is a continuously updating representation of failures. + + + +```yaml +tests: + project_name: + +store_failures: true + +schema: test +``` + + \ No newline at end of file diff --git a/website/docs/reference/resource-configs/meta.md b/website/docs/reference/resource-configs/meta.md index 73823f81f3f..948982925b0 100644 --- a/website/docs/reference/resource-configs/meta.md +++ b/website/docs/reference/resource-configs/meta.md @@ -242,7 +242,7 @@ seeds: ### Override one meta attribute for a single model - + ```sql {{ config(meta = { diff --git a/website/docs/reference/resource-configs/mindsdb-configs.md b/website/docs/reference/resource-configs/mindsdb-configs.md new file mode 100644 index 00000000000..c100887138c --- /dev/null +++ b/website/docs/reference/resource-configs/mindsdb-configs.md @@ -0,0 +1,61 @@ +--- +title: "MindsDB configurations" +id: "mindsdb-configs" +--- + +## Authentication + +To succesfully connect dbt to MinsDB you will need to provide the following configuration from the MindsDB instance. + +| Key | Required| Description | Self-hosted | MindsDB Cloud | +|---------|-------------------------|---------------------------|-------------------------|--------------------------| +| type | ✔️ | The specific adapter to use | `mindsdb` | `mindsdb` | +| host | ✔️ | The MindsDB (hostname) to connect to | Default to `172.0.0.1` | Default to `cloud.mindsdb.com`| +| port | ✔️ | The port to use | Default to `47335` | Default to `3306`| +| schema | ✔️ | Specify the schema (database) to build models into | The MindsDB [integration name](https://docs.mindsdb.com/sql/create/databases/)|The MindsDB [integration name](https://docs.mindsdb.com/sql/create/databases/) +| username | ✔️ | The username to use to connect to the server | Default to `mindsdb` | Your mindsdb cloud username| +| password | ✔️ | The password to use for authenticating to the server | No password by default| Your mindsdb cloud password| + +## Usage + +Create dbt project, choose mindsdb as the database and set up the connection. Verify your connection works `dbt debug` + +`dbt init ` + +To create a predictor, create a dbt model with a "predictor" materialization. The name of the model will be the name of predictor. + +#### Parameters: +- `integration` - name of used integration to get data from and save result to. Must be created in mindsdb beforehand using the [`CREATE DATABASE` syntax](https://docs.mindsdb.com/sql/create/databases/). +- `predict` - field for prediction +- `predict_alias` [optional] - alias for predicted field +- `using` [optional] - options for configure trained model + +```sql +-- my_first_model.sql + {{ + config( + materialized='predictor', + integration='photorep', + predict='name', + predict_alias='name', + using={ + 'encoders.location.module': 'CategoricalAutoEncoder', + 'encoders.rental_price.module': 'NumericEncoder' + } + ) + }} + select * from stores +``` + +To apply predictor add dbt model with "table" materialization. It creates or replaces table in selected integration with results of predictor. +Name of the model is used as name of the table to store prediction results. +If you need to specify schema you can do it with dot separator: schema_name.table_name.sql + +#### Parameters +- `predictor_name` - name of the predictor. It has to be created in mindsdb. +- `integration` - name of used integration to get data from and save result to. Must be created in mindsdb beforehand using the [`CREATE DATABASE` syntax](https://docs.mindsdb.com/sql/create/databases/). + +``` + {{ config(materialized='table', predictor_name='TEST_PREDICTOR_NAME', integration='photorep') }} + select a, bc from ddd where name > latest +``` diff --git a/website/docs/reference/resource-configs/mssql-configs.md b/website/docs/reference/resource-configs/mssql-configs.md new file mode 100644 index 00000000000..502dd0d574b --- /dev/null +++ b/website/docs/reference/resource-configs/mssql-configs.md @@ -0,0 +1,150 @@ +--- +title: "Microsoft SQL Server configurations" +id: "mssql-configs" +--- + +## Materializations + +Ephemeral materialization is not supported due to T-SQL not supporting nested CTEs. It may work in some cases when you're working with very simple ephemeral models. + +### Tables + +Tables will, by default, be materialized as a columnstore tables. +This requires SQL Server 2017 or newer for on-premise instances or service tier S2 or higher for Azure. + +This behaviour can be disabled by setting the `as_columnstore` configuration option to `False`. + + + + + + + +```sql +{{ + config( + as_columnstore='False' + ) +}} + +select * +from ... +``` + + + + + + + + + +```yaml +models: + your_project_name: + materialized: view + staging: + materialized: table + as_columnstore: False +``` + + + + + + + +## Seeds + +By default, `dbt-sqlserver` will attempt to insert seed files in batches of 400 rows. +If this exceeds SQL Server's 2100 parameter limit, the adapter will automatically limit to the highest safe value possible. + +To set a different default seed value, you can set the variable `max_batch_size` in your project configuration. + + + +```yaml +vars: + max_batch_size: 200 # Any integer less than or equal to 2100 will do. +``` + + + +## Snapshots + +Columns in source tables can not have any constraints. +If, for example, any column has a `NOT NULL` constraint, an error will be thrown. + +## Indices + +You can specify indices to be created for your table by specifying post-hooks calling purpose-built macros. + +The following macros are available: + +* `create_clustered_index(columns, unique=False)`: columns is a list of columns, unique is an optional boolean (defaults to False). +* `create_nonclustered_index(columns, includes=columns)`: columns is a list of columns, includes is an optional list of columns to include in the index. +* `drop_all_indexes_on_table()`: drops current indices on a table. Only meaningful if the model is incremental.` + +Some examples: + + + +```sql +{{ + config({ + "as_columnstore": false, + "materialized": 'table', + "post-hook": [ + "{{ create_clustered_index(columns = ['row_id', 'row_id_complement'], unique=True) }}", + "{{ create_nonclustered_index(columns = ['modified_date']) }}", + "{{ create_nonclustered_index(columns = ['row_id'], includes = ['modified_date']) }}", + ] + }) + +}} + +select * +from ... +``` + + + +## Grants with auto provisioning + +dbt 1.2 introduced the capability to grant/revoke access using the `grants` [configuration option](grants). +In dbt-sqlserver, you can additionally set `auto_provision_aad_principals` to `true` in your model configuration if you are using Azure Active Directory authentication with an Azure SQL Database or Azure Synapse Dedicated SQL Pool. + +This will automatically create the Azure Active Directory principal inside your database if it does not exist yet. +Note that the principals need to exist in your Azure Active Directory, this just makes them available to use in your database. + +Principals are not removed again when they are removed from the grants configuration. + + + +```yaml +models: + your_project_name: + auto_provision_aad_principals: true +``` + + + +## cross-database macros + +The following macros are currently not supported: + +* `bool_or` +* `array_construct` +* `array_concat` +* `array_append` + +## dbt-utils + +Many [`dbt-utils`](https://hub.getdbt.com/dbt-labs/dbt_utils/latest/) are supported, +but require the installation of the [`tsql_utils`](https://hub.getdbt.com/dbt-msft/tsql_utils/latest/) dbt package. diff --git a/website/docs/reference/resource-configs/no-configs.md b/website/docs/reference/resource-configs/no-configs.md new file mode 100644 index 00000000000..a9fe4ec8752 --- /dev/null +++ b/website/docs/reference/resource-configs/no-configs.md @@ -0,0 +1,11 @@ +--- +title: "No specifc configurations for this Adapter" +id: "no-configs" +--- + +If you were guided to this page from a data platform setup article, it most likely means: + +- Setting up the profile is the only action the end-user needs to take on the data platform, or +- The subsequent actions the end-user needs to take are not currently documented + +If you'd like to contribute to data platform-specifc configuration information, refer to [Documenting a new adapter](5-documenting-a-new-adapter) \ No newline at end of file diff --git a/website/docs/reference/resource-configs/persist_docs.md b/website/docs/reference/resource-configs/persist_docs.md index 740613538ec..9dec5b6cefe 100644 --- a/website/docs/reference/resource-configs/persist_docs.md +++ b/website/docs/reference/resource-configs/persist_docs.md @@ -120,11 +120,49 @@ resources as needed. ## Support -The `persist_docs` config is supported on all core dbt plugins: BigQuery, -Redshift, Snowflake, and Postgres. Some databases impose limitations on the -types of descriptions that can be added to database objects. At present, the -`persist_docs` flag has the following known limitations: - - Column-level comments are not supported on Snowflake views +The `persist_docs` config is supported on the most widely used dbt adapters: +- Postgres +- Redshift +- Snowflake +- BigQuery +- Apache Spark & Databricks + +However, some databases limit where and how descriptions can be added to database objects. Those database adapters might not support `persist_docs`, or might offer only partial support. + +Some known issues and limitations: + + + +
+ +- Column-level comments require `file_format: delta` (or another "v2 file format") +- Column-level comments aren't supported for models materialized as views ([issue](https://github.com/dbt-labs/dbt-spark/issues/372)) + +
+ +
+ + + +- No known issues + + + + + +- Column names that must be quoted, such as column names containing special characters, will cause runtime errors if column-level `persist_docs` is enabled. This is fixed in v1.2. + + + + + +- Column-level comments aren't supported for models materialized as views + + + +
+ +
## Usage diff --git a/website/docs/reference/resource-configs/plus-prefix.md b/website/docs/reference/resource-configs/plus-prefix.md index 42501f1197d..c054ed5a81b 100644 --- a/website/docs/reference/resource-configs/plus-prefix.md +++ b/website/docs/reference/resource-configs/plus-prefix.md @@ -61,4 +61,10 @@ models:
-Since it doesn't hurt to use the `+` prefix, we recommend you use it whenever adding configs to your `dbt_project.yml` file. +When adding configs in `dbt_project.yml`, it doesn't hurt to use the `+` prefix, so we recommend you use it always. + + + +**Note:** This use of the `+` prefix, in `dbt_project.yml`, is distinct from the use of `+` to control config merge behavior (clobber vs. add) in other config settings (specific resource `.yml` and `.sql` files). Currently, the only config which supports `+` for controlling config merge behavior is [`grants`](grants#grant-config-inheritance). + + diff --git a/website/docs/reference/resource-configs/postgres-configs.md b/website/docs/reference/resource-configs/postgres-configs.md index adbd22f86dc..d28c073b065 100644 --- a/website/docs/reference/resource-configs/postgres-configs.md +++ b/website/docs/reference/resource-configs/postgres-configs.md @@ -3,6 +3,7 @@ title: "Postgres configurations" id: "postgres-configs" --- + ## Performance Optimizations ### Unlogged @@ -36,6 +37,8 @@ models: ### Indexes +While Postgres works reasonably well for datasets smaller than about 10mm rows, database tuning is sometimes required. It's important to create indexes for columns that are commonly used in joins or where clauses. + - **v0.20.0:** Introduced native support for `indexes` config @@ -63,7 +66,7 @@ select ...
-If one or more indexes are configured on a resource, dbt will run `create index` DDL statement(s) as part of that resource's materialization, within the same transaction as its main `create` statement. For the index's name, dbt uses a hash of its properties and the current timestamp, in order to guarantee uniqueness and avoid namespace conflict with other indexes. +If one or more indexes are configured on a resource, dbt will run `create index` statement(s) as part of that resource's , within the same transaction as its main `create` statement. For the index's name, dbt uses a hash of its properties and the current timestamp, in order to guarantee uniqueness and avoid namespace conflict with other indexes. ```sql create index if not exists diff --git a/website/docs/reference/resource-configs/pre-hook-post-hook.md b/website/docs/reference/resource-configs/pre-hook-post-hook.md index b353aaf9e2a..d3fb6c9c3e7 100644 --- a/website/docs/reference/resource-configs/pre-hook-post-hook.md +++ b/website/docs/reference/resource-configs/pre-hook-post-hook.md @@ -100,9 +100,13 @@ select ... ## Definition -A SQL statement (or list of SQL statements) to be run before or after a model, seed or snapshot is built. +A SQL statement (or list of SQL statements) to be run before or after a model, seed, or snapshot is built. -Pre- and post-hooks can also call macros that return SQL statements. +Pre- and post-hooks can also call macros that return SQL statements. If your macro depends on values available only at execution time, such as using model configurations or `ref()` calls to other resources as inputs, you will need to [wrap your macro call in an extra set of curly braces](dont-nest-your-curlies#an-exception). + +### Why would I use hooks? + +dbt aims to provide all the boilerplate SQL you need (DDL, DML, and DCL) via out-of-the-box functionality, which you can configure quickly and concisely. In some cases, there may be SQL that you want or need to run, specific to functionality in your data platform, which dbt does not (yet) offer as a built-in feature. In those cases, you can write the exact SQL you need, using dbt's compilation context, and pass it into a `pre-` or `post-` hook to run before or after your model, seed, or snapshot. @@ -112,6 +116,52 @@ Pre- and post-hooks can also call macros that return SQL statements. ## Examples + + + + + +### [Redshift] Unload one model to S3 + + + +```sql +{{ config( + post_hook = "unload ('select from {{ this }}') to 's3:/bucket_name/{{ this }}" +) }} + +select ... +``` + + + +See: [Redshift docs on `UNLOAD`](https://docs.aws.amazon.com/redshift/latest/dg/r_UNLOAD.html) + +### [Apache Spark] Analyze tables after creation + + + +```yml + +model: + jaffle_shop: # this is the project name + marts: + finance: + +post-hook: + # this can be a list + - "analyze table {{ this }} compute statistics for all columns" + # or call a macro instead + - "{{ analyze_table() }}" +``` + +See: [Apache Spark docs on `ANALYZE TABLE`](https://spark.apache.org/docs/latest/sql-ref-syntax-aux-analyze-table.html) + + + + + + + ### Grant privileges on a model @@ -171,6 +221,8 @@ model: + + ### Additional examples We've compiled some more in-depth examples [here](hooks-operations#additional-examples). @@ -190,9 +242,9 @@ If you're using an adapter that makes use of transactions (namely Postgres or Re There may be occasions where you need to run these hooks _outside_ of a transaction, for example: * You want to run a `VACUUM` in a `post-hook`, however this cannot be executed within a transaction ([Redshift docs](https://docs.aws.amazon.com/redshift/latest/dg/r_VACUUM_command.html#r_VACUUM_usage_notes)) -* You want to insert a record into an audit table at the start of a run, and do not want that statement rolled back if the model creation fails. +* You want to insert a record into an audit at the start of a run, and do not want that statement rolled back if the model creation fails. -To achieve this, you can use one of the following syntaxes: +To achieve this, you can use one of the following syntaxes. (Note: You should NOT use this syntax if using a database where dbt does not use transactions by default, including Snowflake, BigQuery, and Spark/Databricks.) #### Config block: use the `before_begin` and `after_commit` helper macros diff --git a/website/docs/reference/resource-configs/quote_columns.md b/website/docs/reference/resource-configs/quote_columns.md index 5ffbedc7a4e..5701fe0f11f 100644 --- a/website/docs/reference/resource-configs/quote_columns.md +++ b/website/docs/reference/resource-configs/quote_columns.md @@ -5,7 +5,7 @@ default_value: false --- ## Definition -An optional seed configuration, used to determine whether column names in the seed file should be quoted when the table is created. +An optional seed configuration, used to determine whether column names in the seed file should be quoted when the is created. * When `True`, dbt will quote the column names defined in the seed file when building a table for the seed, preserving casing. * (Default) When `False`, dbt will not quote the column names defined in the seed file. @@ -46,9 +46,10 @@ seeds: +Or (as of v0.21): + -Or (as of v0.21): ```yml version: 2 diff --git a/website/docs/reference/resource-configs/redshift-configs.md b/website/docs/reference/resource-configs/redshift-configs.md index 6d41f6e95bb..2fa6439d4fd 100644 --- a/website/docs/reference/resource-configs/redshift-configs.md +++ b/website/docs/reference/resource-configs/redshift-configs.md @@ -13,7 +13,7 @@ To-do: ### Using sortkey and distkey -Tables in Amazon Redshift have two powerful optimizations to improve query performance: distkeys and sortkeys. Supplying these values as model-level configurations apply the corresponding settings in the generated `CREATE TABLE` DDL. Note that these settings will have no effect for models set to `view` or `ephemeral` models. +Tables in Amazon Redshift have two powerful optimizations to improve query performance: distkeys and sortkeys. Supplying these values as model-level configurations apply the corresponding settings in the generated `CREATE TABLE` . Note that these settings will have no effect for models set to `view` or `ephemeral` models. - `dist` can have a setting of `all`, `even`, `auto`, or the name of a key. - `sort` accepts a list of sort keys, for example: `['timestamp', 'userid']`. dbt will build the sort key in the same order the fields are supplied. @@ -55,7 +55,7 @@ For more information on distkeys and sortkeys, view Amazon's docs: ## Late Binding Views -Redshift supports views unbound from their dependencies, or [late binding views](https://docs.aws.amazon.com/redshift/latest/dg/r_CREATE_VIEW.html#late-binding-views). This DDL option "unbinds" a view from the data it selects from. In practice, this means that if upstream views or tables are dropped with a cascade qualifier, the late-binding view does not get dropped as well. +Redshift supports views unbound from their dependencies, or [late binding views](https://docs.aws.amazon.com/redshift/latest/dg/r_CREATE_VIEW.html#late-binding-views). This DDL option "unbinds" a view from the data it selects from. In practice, this means that if upstream views or tables are dropped with a cascade qualifier, the late-binding view does not get dropped as well. Using late-binding views in a production deployment of dbt can vastly improve the availability of data in the warehouse, especially for models that are materialized as late-binding views and are queried by end-users, since they won’t be dropped when upstream models are updated. Additionally, late binding views can be used with [external tables](https://docs.aws.amazon.com/redshift/latest/dg/r_CREATE_EXTERNAL_TABLE.html) via Redshift Spectrum. diff --git a/website/docs/reference/resource-configs/schema.md b/website/docs/reference/resource-configs/schema.md index a3b22ce8291..ce055c9a038 100644 --- a/website/docs/reference/resource-configs/schema.md +++ b/website/docs/reference/resource-configs/schema.md @@ -1,5 +1,5 @@ --- -resource_types: [models, seeds] +resource_types: [models, seeds, tests] datatype: string --- @@ -11,7 +11,7 @@ This is a work in progress document. While this configuration applies to multipl ## Definition Optionally specify a custom schema for a [model](docs/building-a-dbt-project/building-models) or [seed](docs/building-a-dbt-project/seeds). (To specify a schema for a [snapshot](snapshots), use the [`target_schema` config](target_schema)). -When dbt creates a relation (table/view) in a database, it creates it as: `{{ database }}.{{ schema }}.{{ identifier }}`, e.g. `analytics.finance.payments` +When dbt creates a relation (/) in a database, it creates it as: `{{ database }}.{{ schema }}.{{ identifier }}`, e.g. `analytics.finance.payments` The standard behavior of dbt is: * If a custom schema is _not_ specified, the schema of the relation is the target schema (`{{ target.schema }}`). @@ -58,5 +58,19 @@ seeds: +### Tests + +Customize the name of the schema in which tests [configured to store failures](resource-configs/store_failures) will save their results: + + + +```yml +tests: + +store_failures: true + +schema: the_island_of_misfit_tests +``` + + + ## Warehouse specific information * BigQuery: `dataset` and `schema` are interchangeable diff --git a/website/docs/reference/resource-configs/severity.md b/website/docs/reference/resource-configs/severity.md index 2c333304644..436bfda9460 100644 --- a/website/docs/reference/resource-configs/severity.md +++ b/website/docs/reference/resource-configs/severity.md @@ -1,4 +1,7 @@ --- +title: "Configuring test `severity`" +id: "severity" +description: "You can use error thresholds to configure the severity of test results and set when to produce an error or warning based on the number of failed tests." resource_types: [tests] datatype: string --- @@ -29,18 +32,18 @@ Here's how those play in practice: Note that test warn statuses will return errors instead if the [`--warn-error`](global-cli-flags#warnings-as-errors) flag is passed. Unless dbt is told to treat warnings as errors, a test with `warn` severity will never return an error. - + -Configure a specific instance of a generic (schema) test: +Configure a specific instance of a out-of-the-box generic test: @@ -63,9 +66,9 @@ models: - + -Configure a one-off (data) test: +Configure a singular test: @@ -79,9 +82,9 @@ select ... - + -Set the default for all instances of a generic (schema) test, by setting the config inside its test block (definition): +Set the default for all instances of a custom generic test, by setting the config inside its test block (definition): @@ -108,7 +111,7 @@ Set the default for all tests in a package or project: ```yaml tests: +severity: warn # all tests - + : +warn_if: >10 # tests in ``` diff --git a/website/docs/reference/resource-configs/singlestore-configs.md b/website/docs/reference/resource-configs/singlestore-configs.md new file mode 100644 index 00000000000..f503779f0fc --- /dev/null +++ b/website/docs/reference/resource-configs/singlestore-configs.md @@ -0,0 +1,111 @@ +--- +title: "SingleStore configurations" +id: "singlestore-configs" +--- + + + + + - **v1.1.2:** Added support for for `storage_type`, `indexes`, `primary_key`, `sort_key`, `shard_key`, `unique_table_key`, `charset`, `collation` options for creating SingleStore tables. + + + +## Performance Optimizations +[SingleStore Physical Database Schema Design documentation](https://docs.singlestore.com/managed-service/en/create-a-database/physical-database-schema-design/concepts-of-physical-database-schema-design.html) is helpful if you want to use specific options (that are described below) in your dbt project. + + +### Storage type +SingleStore supports two storage types: **In-Memory Rowstore** and **Disk-based Columnstore** (the latter is default). See [the docs](https://docs.singlestore.com/managed-service/en/create-a-database/physical-database-schema-design/concepts-of-physical-database-schema-design/choosing-a-table-storage-type.html) for details. The dbt-singlestore adapter allows you to specify which storage type your table materialization would rely on using `storage_type` config parameter. + + + +```sql +{{ config(materialized='table', storage_type='rowstore') }} + +select ... +``` + + + +### Keys + +SingleStore tables are [sharded](https://docs.singlestore.com/managed-service/en/getting-started-with-managed-service/about-managed-service/sharding.html) and can be created with various column definitions. The following options are supported by the dbt-singlestore adapter, each of them accepts `column_list` (a list of column names) as an option value. Please refer to [Creating a Columnstore Table](https://docs.singlestore.com/managed-service/en/create-a-database/physical-database-schema-design/procedures-for-physical-database-schema-design/creating-a-columnstore-table.html) for more informartion on various key types in SingleStore. +- `primary_key` (translated to `PRIMARY KEY (column_list)`) +- `sort_key` (translated to `KEY (column_list) USING CLUSTERED COLUMNSTORE`) +- `shard_key` (translated to `SHARD KEY (column_list)`) +- `unique_table_key` (translated to `UNIQUE KEY (column_list)`) + + + +```sql +{{ + config( + primary_key=['id', 'user_id'], + shard_key=['id'] + ) +}} + +select ... +``` + + + + + +```sql +{{ + config( + materialized='table', + unique_table_key=['id'], + sort_key=['status'], + ) +}} + +select ... +``` + + + +### Indexes +Similarly to the Postgres adapter, table models, incremental models, seeds, and snapshots may have a list of `indexes` defined. Each index can have the following components: +- `columns` (list, required): one or more columns on which the index is defined +- `unique` (boolean, optional): whether the index should be declared unique +- `type` (string, optional): a supported [index type](https://docs.singlestore.com/managed-service/en/reference/sql-reference/data-definition-language-ddl/create-index.html), `hash` or `btree` + +As SingleStore tables are sharded, there are certain limitations to indexes creation, see the [docs](https://docs.singlestore.com/managed-service/en/create-a-database/physical-database-schema-design/concepts-of-physical-database-schema-design/understanding-keys-and-indexes-in-singlestore.html) for more details. + + + +```sql +{{ + config( + materialized='table', + shard_key=['id'], + indexes=[{'columns': ['order_date', 'id']}, {'columns': ['status'], 'type': 'hash'}] + ) +}} + +select ... +``` + + + + +### Other options + +You can specify the character set and collation for the table using `charset` and/or `collation` options. Supported values for `charset` are `binary`, `utf8`, and `utf8mb4`. Supported values for `collation` can be viewed as the output of `SHOW COLLATION` SQL query. Default collations for the corresponding charcter sets are `binary`, `utf8_general_ci`, and `utf8mb4_general_ci`. + + + +```sql +{{ + config( + charset='utf8mb4', + collation='utf8mb4_general_ci' + ) +}} + +select ... +``` + + \ No newline at end of file diff --git a/website/docs/reference/resource-configs/snowflake-configs.md b/website/docs/reference/resource-configs/snowflake-configs.md index 3729a9fcf76..44a8d4e5653 100644 --- a/website/docs/reference/resource-configs/snowflake-configs.md +++ b/website/docs/reference/resource-configs/snowflake-configs.md @@ -10,7 +10,7 @@ To-do: ## Transient tables -Snowflake supports the creation of [transient tables](https://docs.snowflake.net/manuals/user-guide/tables-temp-transient.html). Snowflake does not preserve a history for these tables, which can result in a measurable reduction of your Snowflake storage costs. Note however that transient tables do not participate in Time Travel. Weigh these tradeoffs when deciding whether or not to configure your dbt models as `transient`. **By default, all Snowflake tables created by dbt are `transient`.** +Snowflake supports the creation of [transient tables](https://docs.snowflake.net/manuals/user-guide/tables-temp-transient.html). Snowflake does not preserve a history for these tables, which can result in a measurable reduction of your Snowflake storage costs. Transient tables participate in time travel to a limited degree with a retention period of 1 day by default with no fail-safe period. Weigh these tradeoffs when deciding whether or not to configure your dbt models as `transient`. **By default, all Snowflake tables created by dbt are `transient`.** ### Configuring transient tables in dbt_project.yml @@ -93,24 +93,19 @@ In this example, you can set up a query tag to be applied to every query with th ``` -**Note:** query tags are set at the _session_ level. At the start of each model -materialization, if the model has a custom `query_tag` -configured, dbt will run `alter session set query_tag` to set the new value. -At the end of the materialization, dbt will run another `alter` statement to reset -the tag to its default value. As such, build failures midway through a materialization may result in subsequent -queries running with an incorrect tag. +**Note:** query tags are set at the _session_ level. At the start of each model , if the model has a custom `query_tag` configured, dbt will run `alter session set query_tag` to set the new value. At the end of the materialization, dbt will run another `alter` statement to reset the tag to its default value. As such, build failures midway through a materialization may result in subsequent queries running with an incorrect tag. ## Merge behavior (incremental models) -The [`incremental_strategy` config](configuring-incremental-models#what-is-an-incremental_strategy) controls how dbt builds incremental models. By default, dbt will use a [merge statement](https://docs.snowflake.net/manuals/sql-reference/sql/merge.html) on Snowflake to refresh incremental tables. +The [`incremental_strategy` config](configuring-incremental-models#about-incremental_strategy) controls how dbt builds incremental models. By default, dbt will use a [merge statement](https://docs.snowflake.net/manuals/sql-reference/sql/merge.html) on Snowflake to refresh incremental tables. Snowflake's `merge` statement fails with a "nondeterministic merge" error if the `unique_key` specified in your model config is not actually unique. If you encounter this error, you can instruct dbt to use a two-step incremental approach by setting the `incremental_strategy` config for your model to `delete+insert`. ## Configuring table clustering -dbt supports [table clustering](https://docs.snowflake.net/manuals/user-guide/tables-clustering-keys.html) on Snowflake. To control clustering for a table or incremental model, use the `cluster_by` config. When this configuration is applied, dbt will do two things: +dbt supports [table clustering](https://docs.snowflake.net/manuals/user-guide/tables-clustering-keys.html) on Snowflake. To control clustering for a or incremental model, use the `cluster_by` config. When this configuration is applied, dbt will do two things: 1. It will implicitly order the table results by the specified `cluster_by` fields 2. It will add the specified clustering keys to the target table @@ -213,7 +208,7 @@ snapshots: ## Copying grants -When the `copy_grants` config is set to `true`, dbt will add the `copy grants` DDL qualifier when rebuilding tables and views. The default value is `false`. +When the `copy_grants` config is set to `true`, dbt will add the `copy grants` qualifier when rebuilding tables and views. The default value is `false`. diff --git a/website/docs/reference/resource-configs/spark-configs.md b/website/docs/reference/resource-configs/spark-configs.md index 2971fc8e188..06b90e73531 100644 --- a/website/docs/reference/resource-configs/spark-configs.md +++ b/website/docs/reference/resource-configs/spark-configs.md @@ -12,13 +12,13 @@ To-do: When materializing a model as `table`, you may include several optional configs that are specific to the dbt-spark plugin, in addition to the standard [model configs](model-configs). -| Option | Description | Required? | Example | -|---------|----------------------------------------------------|-------------------------|--------------------------| -| file_format | The file format to use when creating tables (`parquet`, `delta`, `csv`, `json`, `text`, `jdbc`, `orc`, `hive` or `libsvm`). | Optional | `parquet`| -| location_root | The created table uses the specified directory to store its data. The table alias is appended to it. | Optional | `/mnt/root` | -| partition_by | Partition the created table by the specified columns. A directory is created for each partition. | Optional | `date_day` | -| clustered_by | Each partition in the created table will be split into a fixed number of buckets by the specified columns. | Optional | `country_code` | -| buckets | The number of buckets to create while clustering | Required if `clustered_by` is specified | `8` | +| Option | Description | Required? | Example | +|---------|------------------------------------------------------------------------------------------------------------------------------------|-------------------------|--------------------------| +| file_format | The file format to use when creating tables (`parquet`, `delta`, `hudi`, `csv`, `json`, `text`, `jdbc`, `orc`, `hive` or `libsvm`). | Optional | `parquet`| +| location_root | The created table uses the specified directory to store its data. The table alias is appended to it. | Optional | `/mnt/root` | +| partition_by | Partition the created table by the specified columns. A directory is created for each partition. | Optional | `date_day` | +| clustered_by | Each partition in the created table will be split into a fixed number of buckets by the specified columns. | Optional | `country_code` | +| buckets | The number of buckets to create while clustering | Required if `clustered_by` is specified | `8` | ## Incremental models @@ -28,12 +28,14 @@ When materializing a model as `table`, you may include several optional configs -dbt seeks to offer useful, intuitive modeling abstractions by means of its built-in configurations and materializations. Because there is so much variance between Apache Spark clusters out in the world—not to mention the powerful features offered to Databricks users by the Delta file format and custom runtime—making sense of all the available options is an undertaking in its own right. +dbt seeks to offer useful, intuitive modeling abstractions by means of its built-in configurations and materializations. Because there is so much variance between Apache Spark clusters out in the world—not to mention the powerful features offered to Databricks users by the Delta file format and custom runtime—making sense of all the available options is an undertaking in its own right. -For that reason, the dbt-spark plugin leans heavily on the [`incremental_strategy` config](configuring-incremental-models#what-is-an-incremental_strategy). This config tells the incremental materialization how to build models in runs beyond their first. It can be set to one of three values: +Alternatively, you can use Apache Hudi file format with Apache Spark runtime for building incremental models. + +For that reason, the dbt-spark plugin leans heavily on the [`incremental_strategy` config](configuring-incremental-models#about-incremental_strategy). This config tells the incremental materialization how to build models in runs beyond their first. It can be set to one of three values: - **`append`** (default): Insert new records without updating or overwriting any existing data. - - **`insert_overwrite`**: If `partition_by` is specified, overwrite partitions in the table with new data. If no `partition_by` is specified, overwrite the entire table with new data. - - **`merge`** (Delta Lake only): Match records based on a `unique_key`; update old records, insert new ones. (If no `unique_key` is specified, all new data is inserted, similar to `append`.) + - **`insert_overwrite`**: If `partition_by` is specified, overwrite partitions in the with new data. If no `partition_by` is specified, overwrite the entire table with new data. + - **`merge`** (Delta and Hudi file format only): Match records based on a `unique_key`; update old records, insert new ones. (If no `unique_key` is specified, all new data is inserted, similar to `append`.) Each of these strategies has its pros and cons, which we'll discuss below. As with any model config, `incremental_strategy` may be specified in `dbt_project.yml` or within a model file's `config()` block. @@ -191,8 +193,9 @@ insert overwrite table analytics.spark_incremental **Usage notes:** The `merge` incremental strategy requires: -- `file_format: delta` -- Databricks Runtime 5.1 and above +- `file_format: delta or hudi` +- Databricks Runtime 5.1 and above for delta file format +- Apache Spark for hudi file format dbt will run an [atomic `merge` statement](https://docs.databricks.com/spark/latest/spark-sql/language-manual/merge-into.html) which looks nearly identical to the default merge behavior on Snowflake and BigQuery. If a `unique_key` is specified (recommended), dbt will update old records with values from new records that match on the key column. If a `unique_key` is not specified, dbt will forgo match criteria and simply insert all new records (similar to `append` strategy). @@ -201,16 +204,16 @@ dbt will run an [atomic `merge` statement](https://docs.databricks.com/spark/lat values={[ { label: 'Source code', value: 'source', }, { label: 'Run code', value: 'run', }, - ] +] }> - + ```sql {{ config( materialized='incremental', - file_format='delta', + file_format='delta', # or 'hudi' unique_key='user_id', incremental_strategy='merge' ) }} @@ -237,10 +240,10 @@ group by 1 - + ```sql -create temporary view delta_incremental__dbt_tmp as +create temporary view merge_incremental__dbt_tmp as with new_events as ( @@ -261,8 +264,8 @@ create temporary view delta_incremental__dbt_tmp as ; -merge into analytics.delta_incremental as DBT_INTERNAL_DEST - using delta_incremental__dbt_tmp as DBT_INTERNAL_SOURCE +merge into analytics.merge_incremental as DBT_INTERNAL_DEST + using merge_incremental__dbt_tmp as DBT_INTERNAL_SOURCE on DBT_INTERNAL_SOURCE.user_id = DBT_INTERNAL_DEST.user_id when matched then update set * when not matched then insert * @@ -297,11 +300,11 @@ use or set `database` as a node config or in the target profile when running dbt If you want to control the schema/database in which dbt will materialize models, use the `schema` config and `generate_schema_name` macro _only_. -## Databricks configurations +## Default file format configurations -To access features exclusive to Databricks runtimes, such as +To access advanced incremental strategies features, such as [snapshots](snapshots) and the `merge` incremental strategy, you will want to -use the Delta file format when materializing models as tables. +use the Delta or Hudi file format as the default file format when materializing models as tables. It's quite convenient to do this by setting a top-level configuration in your project file: @@ -310,13 +313,13 @@ project file: ```yml models: - +file_format: delta + +file_format: delta # or hudi seeds: - +file_format: delta + +file_format: delta # or hudi snapshots: - +file_format: delta + +file_format: delta # or hudi ``` diff --git a/website/docs/reference/resource-configs/sql_header.md b/website/docs/reference/resource-configs/sql_header.md index 90c14d318fa..e56fd4c0f96 100644 --- a/website/docs/reference/resource-configs/sql_header.md +++ b/website/docs/reference/resource-configs/sql_header.md @@ -102,7 +102,7 @@ This uses the config block syntax: ```sql {{ config( - sql_header="alter session set timezone = 'Australia/Sydney'" + sql_header="alter session set timezone = 'Australia/Sydney';" ) }} select * from {{ ref('other_model') }} diff --git a/website/docs/reference/resource-configs/store_failures.md b/website/docs/reference/resource-configs/store_failures.md index 2e1c5608ccf..9207e333546 100644 --- a/website/docs/reference/resource-configs/store_failures.md +++ b/website/docs/reference/resource-configs/store_failures.md @@ -10,7 +10,7 @@ datatype: boolean -The configured test(s) will never store their failures when `dbt test --store-failures` is invoked. +The configured test(s) will store their failures when `dbt test --store-failures` is invoked. ## Description Optionally set a test to always or never store its failures in the database. @@ -18,13 +18,13 @@ Optionally set a test to always or never store its failures in the database. `store_failures` config will take precedence over the presence or absence of the `--store-failures` flag. - If the `store_failures` config is `none` or omitted, the resource will use the value of the `--store-failures` flag. -This logic is encoded in the [`should_store_failures()`](https://github.com/fishtown-analytics/dbt/blob/98c015b7754779793e44e056905614296c6e4527/core/dbt/include/global_project/macros/materializations/helpers.sql#L77) macro. +This logic is encoded in the [`should_store_failures()`](https://github.com/dbt-labs/dbt-core/blob/98c015b7754779793e44e056905614296c6e4527/core/dbt/include/global_project/macros/materializations/helpers.sql#L77) macro. - + -Configure a one-off (data) test: +Configure a singular (data) test: diff --git a/website/docs/reference/resource-configs/strategy.md b/website/docs/reference/resource-configs/strategy.md index 672bce39f0d..0d64963a635 100644 --- a/website/docs/reference/resource-configs/strategy.md +++ b/website/docs/reference/resource-configs/strategy.md @@ -131,8 +131,8 @@ This is a **required configuration**. There is no default value. ### Advanced: define and use custom snapshot strategy Behind the scenes, snapshot strategies are implemented as macros, named `snapshot__strategy` -* [Source code](https://github.com/dbt-labs/dbt-core/blob/HEAD/core/dbt/include/global_project/macros/materializations/snapshot/strategies.sql#L66) for the timestamp strategy -* [Source code](https://github.com/dbt-labs/dbt-core/blob/HEAD/core/dbt/include/global_project/macros/materializations/snapshot/strategies.sql#L133) for the check strategy +* [Source code](https://github.com/dbt-labs/dbt-core/blob/HEAD/core/dbt/include/global_project/macros/materializations/snapshots/strategies.sql#L65) for the timestamp strategy +* [Source code](https://github.com/dbt-labs/dbt-core/blob/HEAD/core/dbt/include/global_project/macros/materializations/snapshots/strategies.sql#L131) for the check strategy It's possible to implement your own snapshot strategy by adding a macro with the same naming pattern to your project. For example, you might choose to create a strategy which records hard deletes, named `timestamp_with_deletes`. diff --git a/website/docs/reference/resource-configs/tags.md b/website/docs/reference/resource-configs/tags.md index b0efa7290e3..48b0842a06d 100644 --- a/website/docs/reference/resource-configs/tags.md +++ b/website/docs/reference/resource-configs/tags.md @@ -8,7 +8,7 @@ datatype: string | [string] ## Description -The database that dbt should build a [snapshot](snapshots) table into. +The database that dbt should build a [snapshot](snapshots) into. Notes: - The specified database must already exist diff --git a/website/docs/reference/resource-configs/target_schema.md b/website/docs/reference/resource-configs/target_schema.md index c6c10e8e3b8..3fbb1510d78 100644 --- a/website/docs/reference/resource-configs/target_schema.md +++ b/website/docs/reference/resource-configs/target_schema.md @@ -26,7 +26,7 @@ snapshots: ## Description -The schema that dbt should build a [snapshot](snapshots) table into. Snapshots build into the same `target_schema`, no matter who is running them. +The schema that dbt should build a [snapshot](snapshots) into. Snapshots build into the same `target_schema`, no matter who is running them. On **BigQuery**, this is analogous to a `dataset`. @@ -34,7 +34,7 @@ On **BigQuery**, this is analogous to a `dataset`. This is a **required** parameter, no default is provided. ## FAQs - + ## Examples ### Build all snapshots in a schema named `snapshots` @@ -50,7 +50,7 @@ snapshots: ### Use a target-aware schema -Use the [`{{ target }}` variable](target) to change which schema a snapshot table is built in. +Use the [`{{ target }}` variable](target) to change which schema a snapshot is built in. Note: consider whether this use-case is right for you, as downstream `refs` will select from the `dev` version of a snapshot, which can make it hard to validate models that depend on snapshots (see above [FAQ](#faqs)) diff --git a/website/docs/reference/resource-configs/teradata-configs.md b/website/docs/reference/resource-configs/teradata-configs.md new file mode 100644 index 00000000000..033dec1d94a --- /dev/null +++ b/website/docs/reference/resource-configs/teradata-configs.md @@ -0,0 +1,233 @@ +--- +title: "Teradata configurations" +id: "teradata-configs" +--- + +## General + +* *Set `quote_columns`* - to prevent a warning, make sure to explicitly set a value for `quote_columns` in your `dbt_project.yml`. See the [doc on quote_columns](https://docs.getdbt.com/reference/resource-configs/quote_columns) for more information. + + ```yaml + seeds: + +quote_columns: false #or `true` if you have csv column headers with spaces + ``` + +* *Enable view column types in docs* - Teradata Vantage has a dbscontrol configuration flag called `DisableQVCI`. This flag instructs the database to create `DBC.ColumnsJQV` with view column type definitions. To enable this functionality you need to: + 1. Enable QVCI mode in Vantage. Use `dbscontrol` utility and then restart Teradata. Run these commands as a privileged user on a Teradata node: + ```bash + # option 551 is DisableQVCI. Setting it to false enables QVCI. + dbscontrol << EOF + M internal 551=false + W + EOF + + # restart Teradata + tpareset -y Enable QVCI + ``` + 2. Instruct `dbt` to use `QVCI` mode. Include the following variable in your `dbt_project.yml`: + ```yaml + vars: + use_qvci: true + ``` + For example configuration, see [dbt_project.yml](https://github.com/Teradata/dbt-teradata/blob/main/test/catalog/with_qvci/dbt_project.yml) in `dbt-teradata` QVCI tests. + +## Models + +### +* `table_kind` - define the table kind. Legal values are `MULTISET` (default for ANSI transaction mode required by `dbt-teradata`) and `SET`, e.g.: + ```yaml + {{ + config( + materialized="table", + table_kind="SET" + ) + }} + ``` + For details, see [CREATE TABLE documentation](https://docs.teradata.com/r/76g1CuvvQlYBjb2WPIuk3g/B6Js16DRQVwPDjgJ8rz7hg). +* `table_option` - defines table options. The config supports multiple statements. The definition below uses the Teradata syntax definition to explain what statements are allowed. Square brackets `[]` denote optional parameters. The pipe symbol `|` separates statements. Use commas to combine multiple statements as shown in the examples below: + ``` + { MAP = map_name [COLOCATE USING colocation_name] | + [NO] FALLBACK [PROTECTION] | + WITH JOURNAL TABLE = table_specification | + [NO] LOG | + [ NO | DUAL ] [BEFORE] JOURNAL | + [ NO | DUAL | LOCAL | NOT LOCAL ] AFTER JOURNAL | + CHECKSUM = { DEFAULT | ON | OFF } | + FREESPACE = integer [PERCENT] | + mergeblockratio | + datablocksize | + blockcompression | + isolated_loading + } + ``` + where: + * mergeblockratio: + ``` + { DEFAULT MERGEBLOCKRATIO | + MERGEBLOCKRATIO = integer [PERCENT] | + NO MERGEBLOCKRATIO + } + ``` + * datablocksize: + ``` + DATABLOCKSIZE = { + data_block_size [ BYTES | KBYTES | KILOBYTES ] | + { MINIMUM | MAXIMUM | DEFAULT } DATABLOCKSIZE + } + ``` + * blockcompression: + ``` + BLOCKCOMPRESSION = { AUTOTEMP | MANUAL | ALWAYS | NEVER | DEFAULT } + [, BLOCKCOMPRESSIONALGORITHM = { ZLIB | ELZS_H | DEFAULT } ] + [, BLOCKCOMPRESSIONLEVEL = { value | DEFAULT } ] + ``` + * isolated_loading: + ``` + WITH [NO] [CONCURRENT] ISOLATED LOADING [ FOR { ALL | INSERT | NONE } ] + ``` + + Examples: + + :::info Separators between statements + Note the commas that separate statements in `table_option` config. + ::: + + ```yaml + {{ + config( + materialized="table", + table_option="NO FALLBACK" + ) + }} + ``` + ```yaml + {{ + config( + materialized="table", + table_option="NO FALLBACK, NO JOURNAL" + ) + }} + ``` + ```yaml + {{ + config( + materialized="table", + table_option="NO FALLBACK, NO JOURNAL, CHECKSUM = ON, + NO MERGEBLOCKRATIO, + WITH CONCURRENT ISOLATED LOADING FOR ALL" + ) + }} + ``` + + For details, see [CREATE TABLE documentation](https://docs.teradata.com/r/76g1CuvvQlYBjb2WPIuk3g/B6Js16DRQVwPDjgJ8rz7hg). + +* `with_statistics` - should statistics be copied from the base table, e.g.: + ```yaml + {{ + config( + materialized="table", + with_statistics="true" + ) + }} + ``` + For details, see [CREATE TABLE documentation](https://docs.teradata.com/r/76g1CuvvQlYBjb2WPIuk3g/B6Js16DRQVwPDjgJ8rz7hg). + +* `index` - defines table indices: + ``` + [UNIQUE] PRIMARY INDEX [index_name] ( index_column_name [,...] ) | + NO PRIMARY INDEX | + PRIMARY AMP [INDEX] [index_name] ( index_column_name [,...] ) | + PARTITION BY { partitioning_level | ( partitioning_level [,...] ) } | + UNIQUE INDEX [ index_name ] [ ( index_column_name [,...] ) ] [loading] | + INDEX [index_name] [ALL] ( index_column_name [,...] ) [ordering] [loading] + [,...] + ``` + where: + * partitioning_level: + ``` + { partitioning_expression | + COLUMN [ [NO] AUTO COMPRESS | + COLUMN [ [NO] AUTO COMPRESS ] [ ALL BUT ] column_partition ] + } [ ADD constant ] + ``` + * ordering: + ``` + ORDER BY [ VALUES | HASH ] [ ( order_column_name ) ] + ``` + * loading: + ``` + WITH [NO] LOAD IDENTITY + ``` + + Examples: + + :::info Separators between statements + Note, unlike with `table_option` statements, there are no commas between statements in `index` config. + ::: + + ```yaml + {{ + config( + materialized="table", + index="UNIQUE PRIMARY INDEX ( GlobalID )" + ) + }} + ``` + + ```yaml + {{ + config( + materialized="table", + index="PRIMARY INDEX(id) + PARTITION BY RANGE_N(create_date + BETWEEN DATE '2020-01-01' + AND DATE '2021-01-01' + EACH INTERVAL '1' MONTH)" + ) + }} + ``` + + ```yaml + {{ + config( + materialized="table", + index="PRIMARY INDEX(id) + PARTITION BY RANGE_N(create_date + BETWEEN DATE '2020-01-01' + AND DATE '2021-01-01' + EACH INTERVAL '1' MONTH) + INDEX index_attrA (attrA) WITH LOAD IDENTITY" + ) + }} + ``` +## Seeds + +:::info Using seeds to load raw data + +As explained in [dbt seeds documentation](https://docs.getdbt.com/docs/building-a-dbt-project/seeds), seeds should not be used to load raw data (for example, large CSV exports from a production database). + +Since seeds are version controlled, they are best suited to files that contain business-specific logic, for example a list of country codes or user IDs of employees. + +Loading CSVs using dbt's seed functionality is not performant for large files. Consider using a different tool to load these CSVs into your . + +::: + +* `use_fastload` - use [fastload](https://github.com/Teradata/python-driver#FastLoad) when handling `dbt seed` command. The option will likely speed up loading when your seed files have hundreds of thousands of rows. You can set this seed configuration option in your `project.yml` file, e.g.: + + ```yaml + seeds: + : + +use_fastload: true + ``` + +## Common Teradata-specific tasks +* *collect statistics* - when a table is created or modified significantly, there might be a need to tell Teradata to collect statistics for the optimizer. It can be done using `COLLECT STATISTICS` command. You can perform this step using dbt's `post-hooks`, e.g.: + + ```yaml + {{ config( + post_hook=[ + "COLLECT STATISTICS ON {{ this }} COLUMN (column_1, column_2 ...);" + ] + )}} + ``` + See [Collecting Statistics documentation](https://docs.teradata.com/r/76g1CuvvQlYBjb2WPIuk3g/RAyUdGfvREwbO9J0DMNpLw) for more information. diff --git a/website/docs/reference/resource-configs/where.md b/website/docs/reference/resource-configs/where.md index 1bffee6d798..679fcd83751 100644 --- a/website/docs/reference/resource-configs/where.md +++ b/website/docs/reference/resource-configs/where.md @@ -14,7 +14,7 @@ datatype: string Filter the resource being tested (model, source, seed, or snapshot). -The `where` condition is templated into the test query by replacing the resource reference with a subquery. For instance, a `not_null` test may look like: +The `where` condition is templated into the test query by replacing the resource reference with a . For instance, a `not_null` test may look like: ```sql select * from my_model @@ -123,7 +123,7 @@ tests: ### Custom logic -As of v0.21, dbt defines a [`get_where_subquery` macro](https://github.com/dbt-labs/dbt-core/blob/develop/core/dbt/include/global_project/macros/etc/where_subquery.sql). +As of v0.21, dbt defines a [`get_where_subquery` macro](https://github.com/dbt-labs/dbt-core/blob/main/core/dbt/include/global_project/macros/materializations/tests/where_subquery.sql). dbt replaces `{{ model }}` in generic test definitions with `{{ get_where_subquery(relation) }}`, where `relation` is a `ref()` or `source()` for the resource being tested. The default implementation of this macro returns: - `{{ relation }}` when the `where` config is not defined (`ref()` or `source()`) diff --git a/website/docs/reference/resource-properties/config.md b/website/docs/reference/resource-properties/config.md index 7d251329a0c..636651c45b4 100644 --- a/website/docs/reference/resource-properties/config.md +++ b/website/docs/reference/resource-properties/config.md @@ -1,5 +1,5 @@ --- -resource_types: [models, seeds, snapshots, tests] +resource_types: [models, seeds, snapshots, tests, sources, metrics, exposures] datatype: "{dictionary}" --- @@ -14,6 +14,9 @@ datatype: "{dictionary}" { label: 'Seeds', value: 'seeds', }, { label: 'Snapshots', value: 'snapshots', }, { label: 'Tests', value: 'tests', }, + { label: 'Sources', value: 'sources', }, + { label: 'Metrics', value: 'metrics', }, + { label: 'Exposures', value: 'exposures', }, ] }> @@ -104,6 +107,91 @@ version: 2 + + + + +We have added support for the `config` property on sources in dbt Core v1.1 + + + + + + + +```yml +version: 2 + +sources: + - name: + config: + [](source-configs): + tables: + - name: + config: + [](source-configs): +``` + + + + + + + + + + + +We have added support for the `config` property on sources in dbt Core v1.3 + + + + + + + +```yml +version: 2 + +metrics: + - name: + config: + enabled: true | false +``` + + + + + + + + + + + +Support for the `config` property on `metrics` was added in dbt Core v1.3 + + + + + + + +```yml +version: 2 + +exposures: + - name: + config: + enabled: true | false +``` + + + + + + + The `config` property allows you to configure resources at the same time you're defining properties in yaml files. diff --git a/website/docs/reference/resource-properties/database.md b/website/docs/reference/resource-properties/database.md index 28ce2d654f7..c738eade322 100644 --- a/website/docs/reference/resource-properties/database.md +++ b/website/docs/reference/resource-properties/database.md @@ -32,7 +32,7 @@ If you're using BigQuery, use the _project_ name as the `database:` property. ::: ## Default -By default, dbt will search in your target database (i.e. the database that you are creating tables and views). +By default, dbt will search in your target database (i.e. the database that you are creating tables and views). ## Examples ### Define a source that is stored in the `raw` database diff --git a/website/docs/reference/resource-properties/description.md b/website/docs/reference/resource-properties/description.md index 44e39fed624..9a5342473d7 100644 --- a/website/docs/reference/resource-properties/description.md +++ b/website/docs/reference/resource-properties/description.md @@ -201,7 +201,7 @@ models: - name: dim_customers description: > One record per customer. Note that a customer must have made a purchase to - be included in this table — customer accounts that were created but never + be included in this — customer accounts that were created but never used have been filtered out. columns: @@ -306,7 +306,7 @@ models: ### Include an image from your repo in your descriptions To include an image from your repository in your descriptions: -1. Add the file in a subdirectory, e.g. `assets/dbt-logo.png` +1. Add the file in a subdirectory, e.g. `assets/dbt-logo.svg` 2. Set the [`asset-paths` config](project-configs/asset-paths) in your `dbt_project.yml` file so that this directory gets copied to the `target/` directory as part of `dbt docs generate` @@ -326,7 +326,7 @@ version: 2 models: - name: customers - description: "!\[dbt Logo](assets/dbt-logo.png)" + description: "!\[dbt Logo](assets/dbt-logo.svg)" columns: - name: customer_id @@ -342,7 +342,7 @@ _[CLI users only]_ 4. Run `dbt docs serve` — the image will be rendered as part of your project documentation: - + If mixing images and text together, also consider using a docs block. @@ -357,7 +357,7 @@ version: 2 models: - name: customers - description: "!\[dbt Logo](https://raw.githubusercontent.com/dbt-labs/dbt/develop/etc/dbt-logo-full.svg)" + description: "!\[dbt Logo](https://github.com/dbt-labs/dbt-core/blob/main/etc/dbt-core.svg)" columns: - name: customer_id @@ -369,25 +369,3 @@ models: If mixing images and text together, also consider using a docs block. - - -### Use html in a description - -You can use html in the description to do fancier things than you can in just markdown. Embedding iframes work too! It is recomended you do this in a docs block for ease of maintenance. - - - - -``` - -{% docs orders_status %} - -Here is an image documenting the ERD for this table: - -
- -{% enddocs %} - -``` - -
diff --git a/website/docs/reference/resource-properties/docs.md b/website/docs/reference/resource-properties/docs.md deleted file mode 100644 index feee1081324..00000000000 --- a/website/docs/reference/resource-properties/docs.md +++ /dev/null @@ -1,141 +0,0 @@ ---- -resource_types: models -datatype: "{dictionary}" -default_value: {show: true} ---- - - - - - - -```yml -version: 2 - -models: - - name: model_name - docs: - show: true | false - -``` - - - - - - - -This property is not implemented for sources. - - - - - - - -```yml -version: 2 - -seeds: - - name: seed_name - docs: - show: true | false - -``` - - - - - - - - - -```yml -version: 2 - -snapshots: - - name: snapshot_name - docs: - show: true | false - -``` - - - - - - - - - -```yml -version: 2 - -analyses: - - name: analysis_name - docs: - show: true | false -``` - - - - - - - - - - - -```yml -version: 2 - -macros: - - name: macro_name - docs: - show: true | false - -``` - - - - - - - -## Definition -The `docs` field can be used to provide documentation-specific configuration to models. The only currently supported `docs` attribute is `show`, which controls whether or not models are shown in the auto-generated documentation website. - -**Note:** hidden models will still appear in the dbt DAG visualization, but will be identified as "hidden". - - - -* `v0.16.0`: This property was added - - - -## Default -The default value for `show` is `true`. - -## Examples -### Mark a model as hidden - -```yml -models: - - name: sessions__tmp - docs: - show: false -``` diff --git a/website/docs/reference/resource-properties/external.md b/website/docs/reference/resource-properties/external.md index b167001be2a..a058d4dc685 100644 --- a/website/docs/reference/resource-properties/external.md +++ b/website/docs/reference/resource-properties/external.md @@ -31,11 +31,11 @@ sources: ## Definition An extensible dictionary of metadata properties specific to sources that point to external tables. -There are optional built-in properties, with simple type validation, that roughy correspond to -the Hive external table spec. You may define and use as many additional properties as you'd like. +There are optional built-in properties, with simple type validation, that roughly correspond to +the Hive external spec. You may define and use as many additional properties as you'd like. You may wish to define the `external` property in order to: -- Power macros that introspect [`graph.sources`](dbt-jinja-functions/graph) +- Power macros that introspect [`graph.sources`](/reference/dbt-jinja-functions/graph) - Define metadata that you can later extract from the [manifest](manifest-json) For an example of how this property can be used to power custom workflows, see the [`dbt-external-tables`](https://github.com/dbt-labs/dbt-external-tables) package. diff --git a/website/docs/reference/resource-properties/freshness.md b/website/docs/reference/resource-properties/freshness.md index af7ea642d04..d5f803419dd 100644 --- a/website/docs/reference/resource-properties/freshness.md +++ b/website/docs/reference/resource-properties/freshness.md @@ -33,7 +33,7 @@ sources:
## Definition -A freshness block is used to define the acceptable amount of time between the most recent record, and now, for a table to be considered "fresh". +A freshness block is used to define the acceptable amount of time between the most recent record, and now, for a to be considered "fresh". In the `freshness` block, one or both of `warn_after` and `error_after` can be provided. If neither is provided, then dbt will not calculate freshness snapshots for the tables in this source. diff --git a/website/docs/reference/resource-properties/identifier.md b/website/docs/reference/resource-properties/identifier.md index e3153dd7b9f..c15f7f18438 100644 --- a/website/docs/reference/resource-properties/identifier.md +++ b/website/docs/reference/resource-properties/identifier.md @@ -20,7 +20,7 @@ sources: ## Definition -The table name as stored in the database. +The name as stored in the database. This parameter is useful if you want to use a source table name that differs from the table name in the database. diff --git a/website/docs/reference/resource-properties/overrides.md b/website/docs/reference/resource-properties/overrides.md index e59832c3b63..e36e42d9753 100644 --- a/website/docs/reference/resource-properties/overrides.md +++ b/website/docs/reference/resource-properties/overrides.md @@ -59,7 +59,7 @@ sources: ### Configure your own source freshness for a source table in a package -You can override configurations at both the source and the table level +You can override configurations at both the source and the level diff --git a/website/docs/reference/resource-properties/quote.md b/website/docs/reference/resource-properties/quote.md index 2fd0e65274b..653e9b75343 100644 --- a/website/docs/reference/resource-properties/quote.md +++ b/website/docs/reference/resource-properties/quote.md @@ -128,7 +128,7 @@ The default quoting value is `false` This is particularly relevant to those using Snowflake, where quoting can be particularly fickle. This property is useful when: -- A source table has a column that needs to be quoted to be selected, for example, to preserve column casing +- A source has a column that needs to be quoted to be selected, for example, to preserve column casing - A seed was created with `quote_columns: true` ([docs](quote_columns)) on Snowflake - A model uses quotes in the SQL, potentially to work around the use of reserved words ```sql diff --git a/website/docs/reference/resource-properties/quoting.md b/website/docs/reference/resource-properties/quoting.md index 2c8f7dda869..5cb84f53789 100644 --- a/website/docs/reference/resource-properties/quoting.md +++ b/website/docs/reference/resource-properties/quoting.md @@ -27,7 +27,7 @@ sources: ## Definition Optionally configure whether dbt should quote databases, schemas, and identifiers when resolving a `{{ source() }}` function to a direct relation reference. -This config can be specified for all tables in a source, or for a specific source table. Quoting configs defined for a specific source table override the quoting configs specified for the top-level source. +This config can be specified for all tables in a source, or for a specific source . Quoting configs defined for a specific source table override the quoting configs specified for the top-level source. :::info BigQuery Terminology @@ -37,8 +37,15 @@ Note that for BigQuery quoting configuration, `database` and `schema` should be ## Default +The default values vary by database. -By default, dbt will _not_ quote the database, schema, or identifier. +For most adapters, quoting is set to _true_ by default. + +Why? It's equally easy to select from relations with quoted or unquoted identifiers. Quoting allows you to use reserved words and special characters in those identifiers, though we recommend avoiding this whenever possible. + +On Snowflake, quoting is set to _false_ by default. + +Creating relations with quoted identifiers also makes those identifiers case sensitive. It's much more difficult to select from them. You can re-enable quoting for relations identifiers that are case sensitive, reserved words, or contain special characters, but we recommend you avoid this as much as possible. ## Example diff --git a/website/docs/reference/resource-properties/tests.md b/website/docs/reference/resource-properties/tests.md index 0be881d80c8..a77e18c096c 100644 --- a/website/docs/reference/resource-properties/tests.md +++ b/website/docs/reference/resource-properties/tests.md @@ -152,11 +152,13 @@ This feature is not implemented for analyses. ## Description -The `tests` property defines assertions about a column, table, or view. The property contains a list of generic tests (referenced by name), which can include the four built-in generic tests available in dbt. It can also include any arguments or [configurations](test-configs) passed to those tests. +The `tests` property defines assertions about a column, , or . The property contains a list of [generic tests](building-a-dbt-project/tests#generic-tests), referenced by name, which can include the four built-in generic tests available in dbt. For example, you can add tests that ensure a column contains no duplicates and zero null values. Any arguments or [configurations](test-configs) passed to those tests should be nested below the test name. Once these tests are defined, you can validate their correctness by running `dbt test`. -## test_name +## Out-of-the-box tests + +There are four generic tests that are available out of the box, for everyone using dbt. ### `not_null` @@ -226,7 +228,7 @@ models: ### `relationships` -This test validates that all of the records in a child table have a corresponding record in a parent table. This property is referred to as "referential integrity". +This test validates that all of the records in a child have a corresponding record in a parent table. This property is referred to as "referential integrity". The following example tests that every order's `customer_id` maps back to a valid `customer`. @@ -270,7 +272,7 @@ models: ### Define and use a custom generic test -If you define your own custom generic ("schema") test, you can use that as the `test_name`: +If you've defined your own custom generic test, you can use that as the `test_name`: @@ -282,10 +284,183 @@ models: columns: - name: order_id tests: - - primary_key + - primary_key # name of my custom generic test ``` Check out the guide on writing a [custom generic test](custom-generic-tests) for more information. + + + +### Define a custom name for one test + +By default, dbt will synthesize a name for your generic test by concatenating: +- test name (`not_null`, `unique`, etc) +- model name (or source/seed/snapshot) +- column name (if relevant) +- arguments (if relevant, e.g. `values` for `accepted_values`) + +It does not include any configurations for the test. If the concatenated name is too long, dbt will use a truncated and hashed version instead. The goal is to preserve unique identifiers for all resources in your project, including tests. + +You may also define your own name for a specific test, via the `name` property. + +**When might you want this?** dbt's default approach can result in some wonky (and ugly) test names. By defining a custom name, you get full control over how the test will appear in log messages and metadata artifacts. You'll also be able to select the test by that name. + + + +```yaml +version: 2 + +models: + - name: orders + columns: + - name: status + tests: + - accepted_values: + name: unexpected_order_status_today + values: ['placed', 'shipped', 'completed', 'returned'] + config: + where: "order_date = current_date" +``` + + + +```sh +$ dbt test --select unexpected_order_status_today +12:43:41 Running with dbt=1.1.0 +12:43:41 Found 1 model, 1 test, 0 snapshots, 0 analyses, 167 macros, 0 operations, 1 seed file, 0 sources, 0 exposures, 0 metrics +12:43:41 +12:43:41 Concurrency: 5 threads (target='dev') +12:43:41 +12:43:41 1 of 1 START test unexpected_order_status_today ................................ [RUN] +12:43:41 1 of 1 PASS unexpected_order_status_today ...................................... [PASS in 0.03s] +12:43:41 +12:43:41 Finished running 1 test in 0.13s. +12:43:41 +12:43:41 Completed successfully +12:43:41 +12:43:41 Done. PASS=1 WARN=0 ERROR=0 SKIP=0 TOTAL=1 +``` + +A test's name must be unique for all tests defined on a given model-column combination. If you give the same name to tests defined on several different columns, or across several different models, then `dbt test --select ` will select them all. + +**When might you need this?** In cases where you have defined the same test twice, with only a difference in configuration, dbt will consider these tests to be duplicates: + + + +```yaml +version: 2 + +models: + - name: orders + columns: + - name: status + tests: + - accepted_values: + values: ['placed', 'shipped', 'completed', 'returned'] + config: + where: "order_date = current_date" + - accepted_values: + values: ['placed', 'shipped', 'completed', 'returned'] + config: + # only difference is in the 'where' config + where: "order_date = (current_date - interval '1 day')" # PostgreSQL syntax +``` + + + +```sh +Compilation Error + dbt found two tests with the name "accepted_values_orders_status__placed__shipped__completed__returned" defined on column "status" in "models.orders". + + Since these resources have the same name, dbt will be unable to find the correct resource + when running tests. + + To fix this, change the name of one of these resources: + - test.testy.accepted_values_orders_status__placed__shipped__completed__returned.69dce9e5d5 (models/one_file.yml) + - test.testy.accepted_values_orders_status__placed__shipped__completed__returned.69dce9e5d5 (models/one_file.yml) +``` + +By providing a custom name, you enable dbt to disambiguate them: + + + +```yaml +version: 2 + +models: + - name: orders + columns: + - name: status + tests: + - accepted_values: + name: unexpected_order_status_today + values: ['placed', 'shipped', 'completed', 'returned'] + config: + where: "order_date = current_date" + - accepted_values: + name: unexpected_order_status_yesterday + values: ['placed', 'shipped', 'completed', 'returned'] + config: + where: "order_date = (current_date - interval '1 day')" # PostgreSQL +``` + + + +```sh +$ dbt test +12:48:03 Running with dbt=1.1.0-b1 +12:48:04 Found 1 model, 2 tests, 0 snapshots, 0 analyses, 167 macros, 0 operations, 1 seed file, 0 sources, 0 exposures, 0 metrics +12:48:04 +12:48:04 Concurrency: 5 threads (target='dev') +12:48:04 +12:48:04 1 of 2 START test unexpected_order_status_today ................................ [RUN] +12:48:04 2 of 2 START test unexpected_order_status_yesterday ............................ [RUN] +12:48:04 1 of 2 PASS unexpected_order_status_today ...................................... [PASS in 0.04s] +12:48:04 2 of 2 PASS unexpected_order_status_yesterday .................................. [PASS in 0.04s] +12:48:04 +12:48:04 Finished running 2 tests in 0.21s. +12:48:04 +12:48:04 Completed successfully +12:48:04 +12:48:04 Done. PASS=2 WARN=0 ERROR=0 SKIP=0 TOTAL=2 +``` + +**If using [`store_failures`](resource-configs/store_failures):** dbt uses each test's name as the name of the table in which to store any failing records. If you have defined a custom name for one test, that custom name will also be used for its table of failures. You may optionally configure an [`alias`](resource-configs/alias) for the test, in order to separately control both the name of the test (for metadata) and the name of its database table (for storing failures). + + + + + +### Alternative format for defining tests + +When defining a generic test with a number of arguments and configurations, the YAML can look and feel unwieldy. If you find it easier, you can define the same test properties as top-level keys of a single dictionary, by providing the test name as `test_name` instead. It's totally up to you. + +This example is identical to the one above: + + + +```yaml +version: 2 + +models: + - name: orders + columns: + - name: status + tests: + - name: unexpected_order_status_today + test_name: accepted_values # name of the generic test to apply + values: + - placed + - shipped + - completed + - returned + config: + where: "order_date = current_date" +``` + + + + diff --git a/website/docs/reference/seed-configs.md b/website/docs/reference/seed-configs.md index aa5e95ecff9..f37944c29a6 100644 --- a/website/docs/reference/seed-configs.md +++ b/website/docs/reference/seed-configs.md @@ -58,15 +58,12 @@ seeds: ### General configurations -### General configurations - @@ -87,6 +84,7 @@ seeds: [+](plus-prefix)[persist_docs](persist_docs): [+](plus-prefix)[full_refresh](full_refresh): [+](plus-prefix)[meta](meta): {} + [+](plus-prefix)[grants](grants): {} ``` @@ -115,6 +113,7 @@ seeds: [persist_docs](persist_docs): [full_refresh](full_refresh): [meta](meta): {} + [grants](grants): {} ``` diff --git a/website/docs/reference/snapshot-configs.md b/website/docs/reference/snapshot-configs.md index 12eb9cbf2c2..34297b87ac6 100644 --- a/website/docs/reference/snapshot-configs.md +++ b/website/docs/reference/snapshot-configs.md @@ -113,7 +113,7 @@ snapshots: [+](plus-prefix)[pre-hook](pre-hook-post-hook): | [] [+](plus-prefix)[post-hook](pre-hook-post-hook): | [] [+](plus-prefix)[persist_docs](persist_docs): {} - + [+](plus-prefix)[grants](grants): {} ``` @@ -134,6 +134,7 @@ snapshots: [pre-hook](pre-hook-post-hook): | [] [post-hook](pre-hook-post-hook): | [] [persist_docs](persist_docs): {} + [grants](grants): {} ``` @@ -151,6 +152,7 @@ snapshots: [pre_hook](pre-hook-post-hook)="" | [""], [post_hook](pre-hook-post-hook)="" | [""] [persist_docs](persist_docs)={} + [grants](grants)={} ) }} ``` @@ -250,7 +252,7 @@ You can also define some common configs in a snapshot's `config` block. We don't version: 2 snapshots: - - name: orders_snapshot: + - name: orders_snapshot config: persist_docs: relation: true diff --git a/website/docs/reference/snowflake-permissions.md b/website/docs/reference/snowflake-permissions.md new file mode 100644 index 00000000000..80dbec25cc8 --- /dev/null +++ b/website/docs/reference/snowflake-permissions.md @@ -0,0 +1,23 @@ +--- +title: "Snowflake Permissions" +--- + +## Example Snowflake permissions + +``` +-- NOTE: warehouse_name, database_name, and role_name are placeholders! +-- Replace as-needed for your organization's naming convention! + +grant all on warehouse warehouse_name to role role_name; +grant usage on database database_name to role role_name; +grant create schema on database database_name to role role_name; +grant usage on schema database.an_existing_schema to role role_name; +grant create table on schema database.an_existing_schema to role role_name; +grant create view on schema database.an_existing_schema to role role_name; +grant usage on future schemas in database database_name to role role_name; +grant select on future tables in database database_name to role role_name; +grant select on future views in database database_name to role role_name; +grant usage on all schemas in database database_name to role role_name; +grant select on all tables in database database_name to role role_name; +grant select on all views in database database_name to role role_name; +``` diff --git a/website/docs/reference/source-configs.md b/website/docs/reference/source-configs.md index 32f9b83ca67..ef6937d6237 100644 --- a/website/docs/reference/source-configs.md +++ b/website/docs/reference/source-configs.md @@ -4,22 +4,79 @@ id: source-configs --- ## Available configurations -### Source-specific configurations -* None + +Sources only support one configuration, [`enabled`](enabled). ### General configurations -* [enabled](resource-configs/enabled.md): true | false + + + + + + + +```yaml +sources: + [](resource-path): + [+](plus-prefix)[enabled](enabled): true | false + +``` + + + + + + + + + + + + +```yaml +version: 2 + +sources: + - name: [] + [config](resource-properties/config): + [enabled](enabled): true | false + tables: + - name: [] + [config](resource-properties/config): + [enabled](enabled): true | false + +``` + + + + + + + + ## Configuring sources -Sources can be configured from the `dbt_project.yml` file under the `sources:` -key. This configuration is most useful for configuring sources imported from -[a package](package-management). You can disable sources imported from a package -to prevent them from rendering in the documentation, or to prevent -[source freshness checks](using-sources#snapshotting-source-data-freshness) -from running on source tables imported from packages. -Unlike other resource types, sources do not yet support a `config` property. It -is not possible to (re)define source configs hierarchically across multiple yaml files. + + +Sources can be configured via a `config:` block within their `.yml` definitions, or from the `dbt_project.yml` file under the `sources:` key. This configuration is most useful for configuring sources imported from [a package](package-management). You can disable sources imported from a package to prevent them from rendering in the documentation, or to prevent [source freshness checks](using-sources#snapshotting-source-data-freshness) from running on source tables imported from packages. + + + + + +Sources can be configured from the `dbt_project.yml` file under the `sources:` key. This configuration is most useful for configuring sources imported from [a package](package-management). You can disable sources imported from a package to prevent them from rendering in the documentation, or to prevent [source freshness checks](using-sources#snapshotting-source-data-freshness) from running on source tables imported from packages. + +Unlike other resource types, sources do not yet support a `config` property. It is not possible to (re)define source configs hierarchically across multiple yaml files. + + ### Examples #### Disable all sources imported from a package @@ -31,7 +88,6 @@ state your configuration under the [project name](project-configs/name.md) in th ```yml - sources: events: +enabled: false @@ -40,16 +96,56 @@ sources: -#### Disable a specific source + -To disable a specific source, qualify the resource path for your configuration -with both a package name and a source name. +#### Conditionally enable a single source +When defining a source, you can disable the entire source, or specific source tables, using the inline `config` property: - + + +```yml +version: 2 + +sources: + - name: my_source + config: + enabled: true + tables: + - name: my_source_table # enabled + - name: ignore_this_one # not enabled + config: + enabled: false +``` + + + +You can configure specific source tables, and use [variables](/reference/dbt-jinja-functions/var) as the input to that configuration: + + ```yml +version: 2 + +sources: + - name: my_source + tables: + - name: my_source_table + config: + enabled: "{{ var('my_source_table_enabled', false) }}" +``` + + + + +#### Disable a single source from a package + +To disable a specific source from another package, qualify the resource path for your configuration with both a package name and a source name. In this case, we're disabling the `clickstream` source from the `events` package. + + + +```yml sources: events: clickstream: @@ -58,8 +154,7 @@ sources: -Similarly, you can disable a specific table from a source by qualifying the -resource path with a package name, source name, and table name: +Similarly, you can disable a specific table from a source by qualifying the resource path with a package name, source name, and table name: diff --git a/website/docs/reference/source-properties.md b/website/docs/reference/source-properties.md index 118964809e4..375eca12fc7 100644 --- a/website/docs/reference/source-properties.md +++ b/website/docs/reference/source-properties.md @@ -25,6 +25,10 @@ sources: [loaded_at_field](resource-properties/freshness#loaded_at_field): [meta](meta): {} [tags](resource-configs/tags): [] + + # requires v1.1+ + [config](resource-properties/config): + [](source-configs): [overrides](resource-properties/overrides): diff --git a/website/docs/reference/test-configs.md b/website/docs/reference/test-configs.md index 3e05137769a..885718c2ebb 100644 --- a/website/docs/reference/test-configs.md +++ b/website/docs/reference/test-configs.md @@ -140,6 +140,10 @@ tests: [+](plus-prefix)[enabled](enabled): true | false [+](plus-prefix)[tags](resource-configs/tags): | [] [+](plus-prefix)[meta](resource-configs/meta): {dictionary} + # relevant for [store_failures](resource-configs/store_failures) only + [+](plus-prefix)[database](resource-configs/database): + [+](plus-prefix)[schema](resource-configs/schema): + [+](plus-prefix)[alias](resource-configs/alias): ``` @@ -153,7 +157,10 @@ tests: {{ config( [enabled](enabled)=true | false, [tags](resource-configs/tags)="" | [""] - [meta](resource-configs/meta)={dictionary} + [meta](resource-configs/meta)={dictionary}, + [database](resource-configs/database)="", + [schema](resource-configs/schema)="", + [alias](resource-configs/alias)="", ) }} ``` @@ -174,6 +181,10 @@ version: 2 [enabled](enabled): true | false [tags](resource-configs/tags): | [] [meta](resource-configs/meta): {dictionary} + # relevant for [store_failures](resource-configs/store_failures) only + [database](resource-configs/database): + [schema](resource-configs/schema): + [alias](resource-configs/alias): [columns](columns): - name: @@ -184,6 +195,10 @@ version: 2 [enabled](enabled): true | false [tags](resource-configs/tags): | [] [meta](resource-configs/meta): {dictionary} + # relevant for [store_failures](resource-configs/store_failures) only + [database](resource-configs/database): + [schema](resource-configs/schema): + [alias](resource-configs/alias): ``` This configuration mechanism is supported for specific instances of generic tests only. To configure a specific singular test, you should use the `config()` macro in its SQL definition. diff --git a/website/docs/reference/warehouse-profiles/azuresynapse-profile.md b/website/docs/reference/warehouse-profiles/azuresynapse-profile.md index f6bb119298d..977a1475bbf 100644 --- a/website/docs/reference/warehouse-profiles/azuresynapse-profile.md +++ b/website/docs/reference/warehouse-profiles/azuresynapse-profile.md @@ -1,8 +1,7 @@ --- -title: "Microsoft Azure Synapse DW Profile" +title: "Microsoft Azure Synapse DWH Profile" --- - :::info Community plugin Some core functionality may be limited. If you're interested in contributing, check out the source code for each repository listed below. @@ -12,167 +11,70 @@ Some core functionality may be limited. If you're interested in contributing, ch ## Overview of dbt-synapse **Maintained by:** Community -**Author:** Nandan Hegde and Anders Swanson -**Source:** [Github](https://github.com/dbt-msft/dbt-synapse) +**Author:** [dbt-msft community](https://github.com/dbt-msft) +**Source:** [GitHub](https://github.com/dbt-msft/dbt-synapse) **Core version:** v0.18.0 and newer -**dbt Cloud:** Not Supported -**dbt Slack channel** [Link to channel](https://getdbt.slack.com/archives/C01DRQ178LQ) +**dbt Cloud:** Not Supported +**dbt Slack channel:** [Link to channel](https://getdbt.slack.com/archives/C01DRQ178LQ) ![dbt-synapse stars](https://img.shields.io/github/stars/dbt-msft/dbt-synapse?style=for-the-badge) +![latest version on PyPI](https://img.shields.io/pypi/v/dbt-synapse?style=for-the-badge) The package can be installed from PyPI with: ```python pip install dbt-synapse ``` -For further (and more likely up-to-date) info, see the [README](https://github.com/swanderz/dbt-synapse/blob/master/README.md) - -### Connecting to Azure Synapse with **`dbt-synapse`** - -First download and install the [MSFT ODBC Driver 17 for SQL Server](https://docs.microsoft.com/en-us/sql/connect/odbc/download-odbc-driver-for-sql-server?view=sql-server-ver15) - -#### standard SQL Server authentication -SQL Server credentials are supported for on-prem as well as cloud, and it is the default authentication method for `dbt-sqlsever` - - - -```yml -type: synapse -driver: 'ODBC Driver 17 for SQL Server' (The ODBC Driver installed on your system) -server: server-host-name or ip -port: 1433 -schema: schemaname -user: username -password: password -``` - - - -#### Active Directory Authentication - -The following [`pyodbc`-supported ActiveDirectory methods](https://docs.microsoft.com/en-us/sql/connect/odbc/using-azure-active-directory?view=sql-server-ver15#new-andor-modified-dsn-and-connection-string-keywords) are available to authenticate to Azure SQL products: -- ActiveDirectory Password -- Azure CLI -- ActiveDirectory Interactive (*Windows only*) -- ActiveDirectory Integrated (*Windows only*) -- Service Principal (a.k.a. AAD Application) -- ~~ActiveDirectory MSI~~ (not implemented) - - - - - -Definitely not ideal, but available - - - -```yml -type: synapse -driver: 'ODBC Driver 17 for SQL Server' (The ODBC Driver installed on your system) -server: server-host-name or ip -port: 1433 -schema: schemaname -authentication: ActiveDirectoryPassword -user: bill.gates@microsoft.com -password: iheartopensource -``` - - - - - +:::info Dedicated SQL only -First, install the [Azure CLI](https://docs.microsoft.com/en-us/cli/azure/install-azure-cli), then, log in: +Azure Synapse offers both Dedicated SQL Pools and Serverless SQL Pools. +**Only Dedicated SQL Pools are supported by this adapter. If you really insist on using serverless pools, check out the neglected, experimental project: [dbt-synapse-serverless](https://github.com/dbt-msft/dbt-synapse-serverless)** -`az login` - - - -```yml -type: synapse -driver: 'ODBC Driver 17 for SQL Server' (The ODBC Driver installed on your system) -server: server-host-name or ip -port: 1433 -schema: schemaname -authentication: CLI -``` -This is also the preferred route for using a service principal: - -`az login --service-principal --username $CLIENTID --password $SECRET --tenant $TENANTID` - - - - - - +::: -*Windows Only* brings up the Azure AD prompt so you can MFA if need be. +### Prerequisites - +On Debian/Ubuntu make sure you have the ODBC header files before installing -```yml -type: synapse -driver: 'ODBC Driver 17 for SQL Server' (The ODBC Driver installed on your system) -server: server-host-name or ip -port: 1433 -schema: schemaname -authentication: ActiveDirectoryInteractive -user: bill.gates@microsoft.com +```bash +sudo apt install unixodbc-dev ``` - - - - - - -*Windows Only* uses your machine's credentials (might be disabled by your AAD admins) - - +Download and install the [Microsoft ODBC Driver 18 for SQL Server](https://docs.microsoft.com/en-us/sql/connect/odbc/download-odbc-driver-for-sql-server?view=sql-server-ver15). +If you already have ODBC Driver 17 installed, then that one will work as well. -```yml -type: synapse -driver: 'ODBC Driver 17 for SQL Server' (The ODBC Driver installed on your system) -server: server-host-name or ip -port: 1433 -schema: schemaname -authentication: ActiveDirectoryIntegrated -``` +:::tip Default settings change in dbt-synapse v1.2 / ODBC Driver 18 +Microsoft made several changes related to connection encryption. Read more about the changes [here](mssql-profile#connection-encryption). +::: - +### Authentication methods - +This adapter is based on the adapter for Microsoft SQL Server. +Therefor, the same authentication methods are supported. - +The configuration is the same except for 1 major difference: +instead of specifying `type: sqlserver`, you specify `type: synapse`. -`client_*` and `app_*` can be used interchangeably +Example: -```yml -type: synapse -driver: 'ODBC Driver 17 for SQL Server' (The ODBC Driver installed on your system) -server: server-host-name or ip -port: 1433 -schema: schemaname -authentication: ServicePrincipal -tenant_id: tenant_id -client_id: clientid -client_secret: clientsecret +```yaml +your_profile_name: + target: dev + outputs: + dev: + type: synapse + driver: 'ODBC Driver 17 for SQL Server' # (The ODBC Driver installed on your system) + server: workspacename.sql.azuresynapse.net # (Dedicated SQL endpoint of your workspace here) + port: 1433 + database: exampledb + schema: schema_name + user: username + password: password ``` - - - +You can find all the available options and the documentation and how to configure them on [the documentation page for the dbt-sqlserver adapter](mssql-profile). diff --git a/website/docs/reference/warehouse-profiles/clickhouse-profile.md b/website/docs/reference/warehouse-profiles/clickhouse-profile.md deleted file mode 100644 index 200837e595a..00000000000 --- a/website/docs/reference/warehouse-profiles/clickhouse-profile.md +++ /dev/null @@ -1,46 +0,0 @@ ---- -title: "ClickHouse Profile" ---- - -:::info Community plugin - -Some core functionality may be limited. If you're interested in contributing, check out the source code for each repository listed below. - -::: - -## Overview of dbt-clickhouse -**Maintained by:** Community -**Author:** Dmitriy Sokolov -**Source:** https://github.com/silentsokolov/dbt-clickhouse -**Core version:** v0.19.0 and newer -**dbt Cloud:** Not Supported - -![dbt-clickhouse stars](https://img.shields.io/github/stars/silentsokolov/dbt-clickhouse?style=for-the-badge) - -The easiest way to install it is to use pip: - - pip install dbt-clickhouse - -## Connecting to ClickHouse with **dbt-clickhouse** - -#### User / password authentication - -Configure your dbt profile for using ClickHouse: - -##### ClickHouse connection information - - -```yaml -dbt-clickhouse: - target: dev - outputs: - dev: - type: clickhouse - schema: [database name] - host: [db.clickhouse.com] - port: 9000 - user: [user] - password: [abc123] -``` - - diff --git a/website/docs/reference/warehouse-profiles/dremio-profile.md b/website/docs/reference/warehouse-profiles/dremio-profile.md deleted file mode 100644 index d156f815117..00000000000 --- a/website/docs/reference/warehouse-profiles/dremio-profile.md +++ /dev/null @@ -1,48 +0,0 @@ ---- -title: "Dremio Profile" ---- - -:::info Community plugin - -Some core functionality may be limited. If you're interested in contributing, check out the source code for each repository listed below. - -::: - -## Overview of dbt-dremio -**Maintained by:** Community -**Author:** Fabrice Etanchaud (Maif-vie) -**Source:** https://github.com/fabrice-etanchaud/dbt-dremio -**Core version:** v0.18.0 and newer -**dbt Cloud:** Not Supported - -![dbt-dremio stars](https://img.shields.io/github/stars/fabrice-etanchaud/dbt-dremio?style=for-the-badge) - -The easiest way to install it is to use pip: - - pip install dbt-dremio - -Follow the repository's link for os dependencies. - -## Connecting to Dremio with **dbt-dremio** - -### Connecting with ZooKeeper - -I have no means to test [connection with ZooKeeper](https://docs.dremio.com/drivers/dremio-connector.html#connecting-to-zookeeper). -If you do need this, contact me and I will provide you with a branch you can test. - -### Direct connection to a coordinator - -```yaml -my_profile: - outputs: - my_target: - type: dremio - threads: 2 -# please replace driver below with the one you gave to your dremio odbc driver installation - driver: Dremio ODBC Driver 64-bit - host: [coordinator host] - port: 31010 - schema: [schema] - user: [user] - password: [password] - target: my_target diff --git a/website/docs/reference/warehouse-profiles/exasol-profile.md b/website/docs/reference/warehouse-profiles/exasol-profile.md deleted file mode 100644 index 5155ece4007..00000000000 --- a/website/docs/reference/warehouse-profiles/exasol-profile.md +++ /dev/null @@ -1,47 +0,0 @@ ---- -title: "Exasol Profile" ---- - -:::info Community plugin - -Some core functionality may be limited. If you're interested in contributing, check out the source code for each repository listed below. - -::: - -## Overview of dbt-exasol -**Maintained by:** Community -**Author:** Torsten Glunde, Ilija Kutle -**Source:** https://github.com/tglunde/dbt-exasol -**Core version:** v0.14.0 and newer -**dbt Cloud:** Not Supported - -![dbt-exasol stars](https://img.shields.io/github/stars/tglunde/dbt-exasol?style=for-the-badge) - -Easiest install is to use pip: - - pip install dbt-exasol - -### Connecting to Exasol with **dbt-exasol** - -#### User / password authentication - -Configure your dbt profile for using Exasol: - -##### Exasol connection information - - -```yaml -dbt-exasol: - target: dev - outputs: - dev: - type: exasol - threads: 1 - dsn: HOST:PORT - user: USERNAME - password: PASSWORD - dbname: db - schema: SCHEMA -``` - - diff --git a/website/docs/reference/warehouse-profiles/materialize-profile.md b/website/docs/reference/warehouse-profiles/materialize-profile.md deleted file mode 100644 index de08a040b7b..00000000000 --- a/website/docs/reference/warehouse-profiles/materialize-profile.md +++ /dev/null @@ -1,68 +0,0 @@ ---- -title: "Materialize Profile" ---- - -:::info Vendor-supported plugin - -Certain core functionality may vary. If you would like to report a bug, request a feature, or contribute, you can check out the linked repository and open an issue. - -::: - -## Overview of dbt-materialize - -**Maintained by:** Materialize, Inc. -**Source:** [Github](https://github.com/MaterializeInc/materialize/blob/main/misc/dbt-materialize) -**Core version:** v0.18.1 and newer -**dbt Cloud:** Not Supported -**dbt Slack channel** [Link to channel](https://getdbt.slack.com/archives/C01PWAH41A5) - -The easiest way to install is to use pip: - - pip install dbt-materialize - -## Connecting to Materialize with **dbt-materialize** - -The dbt profile for Materialize is nearly identical to the [profile configuration for Postgres](postgres-profile): - - - -```yaml -dbt-materialize: - target: dev - outputs: - dev: - type: materialize - threads: 1 - host: [host] - port: [port] - user: [user] - pass: [password] - dbname: [database] - schema: [name of your dbt schema] -``` - - - -## Supported Features - -### Materializations - -Type | Supported? | Details ------|------------|---------------- -source | YES | Creates a [source](https://materialize.com/docs/sql/create-source/). -view | YES | Creates a [view](https://materialize.com/docs/sql/create-view/#main). -materializedview | YES | Creates a [materialized view](https://materialize.com/docs/sql/create-materialized-view/#main). -table | YES | Creates a [materialized view](https://materialize.com/docs/sql/create-materialized-view/#main). (Actual table support pending [#5266](https://github.com/MaterializeInc/materialize/issues/5266)) -index | YES | Creates an [index](https://materialize.com/docs/sql/create-index/#main). -sink | YES | Creates a [sink](https://materialize.com/docs/sql/create-sink/#main). -ephemeral | YES | Executes queries using CTEs. -incremental | NO | Use the `materializedview` materialization instead. Materialized views will always return up-to-date results without manual or configured refreshes. For more information, check out [Materialize documentation](https://materialize.com/docs/). - -### Seeds - -Running [`dbt seed`](commands/seed) will create a static materialized view from a CSV file. You will not be able to add to or update this view after it has been created. If you want to rerun `dbt seed`, you must first drop existing views manually with `drop view`. - -## Resources - -- [dbt and Materialize guide](https://materialize.com/docs/guides/dbt/) -- [Get started](https://github.com/MaterializeInc/materialize/blob/main/play/wikirecent-dbt/README.md) using dbt and Materialize together diff --git a/website/docs/reference/warehouse-profiles/mssql-profile.md b/website/docs/reference/warehouse-profiles/mssql-profile.md deleted file mode 100644 index 7c5ed9865f8..00000000000 --- a/website/docs/reference/warehouse-profiles/mssql-profile.md +++ /dev/null @@ -1,178 +0,0 @@ ---- -title: "Microsoft SQL Server Profile" ---- - -:::info Community plugin - -Some core functionality may be limited. If you're interested in contributing, check out the source code for each repository listed below. - -::: - -## Overview of dbt-sqlserver - -**Maintained by:** Community -**Author:** Mikael Ene -**Source:** [Github](https://github.com/dbt-msft/dbt-sqlserver) -**Core version:** v0.14.0 and newer -**dbt Cloud:** Not Supported -**dbt Slack channel** [Link to channel](https://getdbt.slack.com/archives/CMRMDDQ9W) - -![dbt-sqlserver stars](https://img.shields.io/github/stars/mikaelene/dbt-sqlserver?style=for-the-badge) - -The package can be installed from PyPI with: - -```python -pip install dbt-sqlserver -``` -On Ubuntu make sure you have the ODBC header files before installing - - sudo apt install unixodbc-dev - -### Connecting to SQL Server with **dbt-sqlserver** - -#### standard SQL Server authentication -SQL Server credentials are supported for on-prem as well as cloud, and it is the default authentication method for `dbt-sqlsever` - - - -```yml -type: sqlserver -driver: 'ODBC Driver 17 for SQL Server' (The ODBC Driver installed on your system) -server: server-host-name or ip -port: 1433 -schema: schemaname -user: username -password: password -``` - - - -#### Active Directory Authentication - -The following [`pyodbc`-supported ActiveDirectory methods](https://docs.microsoft.com/en-us/sql/connect/odbc/using-azure-active-directory?view=sql-server-ver15#new-andor-modified-dsn-and-connection-string-keywords) are available to authenticate to Azure SQL products: -- ActiveDirectory Password -- Azure CLI -- ActiveDirectory Interactive (*Windows only*) -- ActiveDirectory Integrated (*Windows only*) -- Service Principal (a.k.a. AAD Application) -- ~~ActiveDirectory MSI~~ (not implemented) - - - - - -Definitely not ideal, but available - - - -```yml -type: sqlserver -driver: 'ODBC Driver 17 for SQL Server' (The ODBC Driver installed on your system) -server: server-host-name or ip -port: 1433 -schema: schemaname -authentication: ActiveDirectoryPassword -user: bill.gates@microsoft.com -password: iheartopensource -``` - - - - - - - -First, install the [Azure CLI](https://docs.microsoft.com/en-us/cli/azure/install-azure-cli), then, log in: - -`az login` - - - -```yml -type: sqlserver -driver: 'ODBC Driver 17 for SQL Server' (The ODBC Driver installed on your system) -server: server-host-name or ip -port: 1433 -schema: schemaname -authentication: CLI -``` -This is also the preferred route for using a service principal: - -`az login --service-principal --username $CLIENTID --password $SECRET --tenant $TENANTID` - - - - - - - -*Windows Only* brings up the Azure AD prompt so you can MFA if need be. - - - -```yml -type: sqlserver -driver: 'ODBC Driver 17 for SQL Server' (The ODBC Driver installed on your system) -server: server-host-name or ip -port: 1433 -schema: schemaname -authentication: ActiveDirectoryInteractive -user: bill.gates@microsoft.com -``` - - - - - - - -*Windows Only* uses your machine's credentials (might be disabled by your AAD admins) - - - -```yml -type: sqlserver -driver: 'ODBC Driver 17 for SQL Server' (The ODBC Driver installed on your system) -server: server-host-name or ip -port: 1433 -schema: schemaname -authentication: ActiveDirectoryIntegrated -``` - - - - - - - -`client_*` and `app_*` can be used interchangeably - - - -```yml -type: sqlserver -driver: 'ODBC Driver 17 for SQL Server' (The ODBC Driver installed on your system) -server: server-host-name or ip -port: 1433 -schema: schemaname -authentication: ServicePrincipal -tenant_id: tenant_id -client_id: clientid -client_secret: clientsecret -``` - - - - - - - diff --git a/website/docs/reference/warehouse-profiles/oracle-profile.md b/website/docs/reference/warehouse-profiles/oracle-profile.md deleted file mode 100644 index b44e4eb8c32..00000000000 --- a/website/docs/reference/warehouse-profiles/oracle-profile.md +++ /dev/null @@ -1,51 +0,0 @@ ---- -title: "Oracle Profile" ---- - -:::info Community plugin - -Some core functionality may be limited. If you're interested in contributing, check out the source code for each repository listed below. - -::: - -## Overview of dbt-oracle - -**Maintained by:** Community -**Author:** Vitor Avancini -**Source:** [Github](https://github.com/techindicium/dbt-oracle) -**Core version:** v0.16.0 and newer -**dbt Cloud:** Not Supported -**dbt Slack channel** [Link to channel](https://getdbt.slack.com/archives/C01PWH4TXLY) - -![dbt-oracle stars](https://img.shields.io/github/stars/techindicium/dbt-oracle?style=for-the-badge) - -Easiest install is to use pip: - - pip install dbt-oracle - -You will need Oracle client driver installed. Check this [link](https://cx-oracle.readthedocs.io/en/latest/user_guide/installation.html) for the installation guide for your operating system - -### Connecting to Oracle with **dbt-oracle** - -#### User / password authentication - -Configure your dbt profile for using Oracle Authentication: - -##### Oracle Authentication - - -```yaml -dbt_oracle: - target: dev - outputs: - dev: - type: oracle - host: localhost - user: system - password: oracle - port: 1521 - dbname: [dbname] - schema: [schema] - threads: 4 -``` - diff --git a/website/docs/reference/warehouse-profiles/postgres-profile.md b/website/docs/reference/warehouse-profiles/postgres-profile.md deleted file mode 100644 index 981c5678a98..00000000000 --- a/website/docs/reference/warehouse-profiles/postgres-profile.md +++ /dev/null @@ -1,60 +0,0 @@ ---- -title: "Postgres Profile" ---- - -## Overview of dbt-postgres -**Maintained by:** core dbt maintainers -**Author:** dbt Labs -**dbt Cloud:** Supported -**dbt Slack channel** [Link to channel](https://getdbt.slack.com/archives/C0172G2E273) - -## Profile Configuration - -Postgres targets should be set up using the following configuration in your `profiles.yml` file. - - - -```yaml -company-name: - target: dev - outputs: - dev: - type: postgres - host: [hostname] - user: [username] - password: [password] - port: [port] - dbname: [database name] - schema: [dbt schema] - threads: [1 or more] - keepalives_idle: 0 # default 0, indicating the system default - connect_timeout: 10 # default 10 seconds - search_path: [optional, override the default postgres search_path] - role: [optional, set the role dbt assumes when executing queries] - sslmode: [optional, set the sslmode used to connect to the database] - -``` - - - -### Configurations - -#### search_path - -The `search_path` config controls the Postgres "search path" that dbt configures when opening new connections to the database. By default, the Postgres search path is `"$user, public"`, meaning that unqualified table names will be searched for in the `public` schema, or a schema with the same name as the logged-in user. **Note:** Setting the `search_path` to a custom value is not necessary or recommended for typical usage of dbt. - -#### role - - Added in v0.16.0 - -The `role` config controls the Postgres role that dbt assumes when opening new connections to the database. - -#### sslmode - - Added in v0.16.0 - -The `sslmode` config controls how dbt connectes to Postgres databases using SSL. See [the Postgres docs](https://www.postgresql.org/docs/9.1/libpq-ssl.html) on `sslmode` for usage information. When unset, dbt will connect to databases using the Postgres default, `prefer`, as the `sslmode`. - -### Postgres notes - -While Postgres works reasonably well for datasets smaller than about 10mm rows, database tuning is sometimes required. Make sure to create indexes for columns that are commonly used in joins or where clauses. diff --git a/website/docs/reference/warehouse-profiles/presto-profile.md b/website/docs/reference/warehouse-profiles/presto-profile.md deleted file mode 100644 index 389f3db3b9d..00000000000 --- a/website/docs/reference/warehouse-profiles/presto-profile.md +++ /dev/null @@ -1,77 +0,0 @@ ---- -title: "Presto Profile" ---- - -:::info Community plugin - -Some core functionality may be limited. If you're interested in contributing, check out the source code for each repository listed below. - -::: - -## Overview of dbt-presto -**Maintained by:** core dbt maintainers -**Author:** dbt Labs -**Source:** [Github](https://github.com/dbt-labs/dbt-presto) -**Core version:** v0.13.0 and newer -**dbt Cloud:** Not Supported -**dbt Slack channel** [Link to channel](https://getdbt.slack.com/archives/CNNPBQ24R) - -![dbt-presto stars](https://img.shields.io/github/stars/dbt-labs/dbt-presto?style=for-the-badge) - -## Set up a Presto Target - -Presto targets should be set up using the following configuration in your `profiles.yml` file. - - - -```yaml -my-presto-db: - target: dev - outputs: - dev: - type: presto - method: none # optional, one of {none | ldap | kerberos} - user: [user] - password: [password] # required if method is ldap or kerberos - database: [database name] - host: [hostname] - port: [port number] - schema: [your dbt schema] - threads: [1 or more] - -``` - - - -## Installation and Distribution - -dbt's Presto adapter is managed in its own repository, [dbt-presto](https://github.com/dbt-labs/dbt-presto). To use the Presto adapter, you must install the `dbt-presto` plugin: - -### Using pip -The following command will install the latest version of `dbt-presto` as well as the requisite version of `dbt-core`: - -``` -pip install dbt-presto -``` - -## Caveats - -### Unsupported Functionality - -Due to the nature of Presto, not all core dbt functionality is supported. The following features of dbt are not implemented on Presto: - -1. [Snapshots](snapshots) -2. [Incremental models](configuring-incremental-models) - -If you are interested in helping to add support for this functionality in dbt on Presto, please [open an issue](https://github.com/dbt-labs/dbt-presto/issues/new). - -### Required configuration - -dbt fundamentally works by dropping and creating tables and views in databases. As such, the following Presto configs must be set for dbt to work properly on Presto: - -``` -hive.metastore-cache-ttl=0s -hive.metastore-refresh-interval = 5s -hive.allow-drop-table=true -hive.allow-rename-table=true -``` diff --git a/website/docs/reference/warehouse-profiles/redshift-profile.md b/website/docs/reference/warehouse-profiles/redshift-profile.md deleted file mode 100644 index 1605dae7a32..00000000000 --- a/website/docs/reference/warehouse-profiles/redshift-profile.md +++ /dev/null @@ -1,96 +0,0 @@ ---- -title: "Redshift Profile" ---- - -## Overview of dbt-redshift -**Maintained by:** core dbt maintainers -**Author:** dbt Labs -**Source:** [Github](https://github.com/dbt-labs/dbt-redshift) -**dbt Cloud:** Supported -**dbt Slack channel** [Link to channel](https://getdbt.slack.com/archives/CJARVS0RY) - - -## Authentication Methods - -### Password-based authentication - - - -```yaml -company-name: - target: dev - outputs: - dev: - type: redshift - host: hostname.region.redshift.amazonaws.com - user: username - password: password1 - port: 5439 - dbname: analytics - schema: analytics - threads: 4 - keepalives_idle: 0 # default 0, indicating the system default - connect_timeout: 10 # default 10 seconds - # search_path: public # optional, not recommended - sslmode: [optional, set the sslmode used to connect to the database (in case this parameter is set, will look for ca in ~/.postgresql/root.crt)] - ra3: true # enables cross-database sources -``` - - - -### IAM Authentication - -To set up a Redshift profile using IAM Authentication, set the `method` -parameter to `iam` as shown below. Note that a password is not required when -using IAM Authentication. For more information on this type of authentication, -consult the [Redshift Documentation](https://docs.aws.amazon.com/redshift/latest/mgmt/generating-user-credentials.html) -and [boto3 -docs](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/redshift.html#Redshift.Client.get_cluster_credentials) -on generating user credentials with IAM Auth. - -If you receive the "You must specify a region" error when using IAM -Authentication, then your aws credentials are likely misconfigured. Try running -`aws configure` to set up AWS access keys, and pick a default region. If you have any questions, -please refer to the official AWS documentation on [Configuration and credential file settings](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-files.html). - - - -```yaml -my-redshift-db: - target: dev - outputs: - dev: - type: redshift - method: iam - cluster_id: [cluster_id] - host: hostname.region.redshift.amazonaws.com - user: alice - iam_profile: data_engineer # optional - iam_duration_seconds: 900 # optional - autocreate: true # optional - db_groups: ['analysts'] # optional - - # Other Redshift configs: - port: 5439 - dbname: analytics - schema: analytics - threads: 4 - keepalives_idle: 0 # default 0, indicating the system default - # search_path: public # optional, but not recommended - sslmode: [optional, set the sslmode used to connect to the database (in case this parameter is set, will look for ca in ~/.postgresql/root.crt)] - ra3: true # enables cross-database sources - -``` - - - -### Specifying an IAM Profile - -:::info New in dbt v0.18.0 -The `iam_profile` config option for Redshift profiles is new in dbt v0.18.0 -::: - -When the `iam_profile` configuration is set, dbt will use the specified profile from your `~/.aws/config` file instead of using the profile name `default` -## Redshift notes - -Where possible, dbt enables the use of `sort` and `dist` keys. See the section on [Redshift specific configurations](redshift-configs). diff --git a/website/docs/reference/warehouse-profiles/rockset-profile.md b/website/docs/reference/warehouse-profiles/rockset-profile.md deleted file mode 100644 index bf3f639fd55..00000000000 --- a/website/docs/reference/warehouse-profiles/rockset-profile.md +++ /dev/null @@ -1,54 +0,0 @@ ---- -title: "Rockset Profile" ---- - -:::info Vendor-supported plugin - -Certain core functionality may vary. If you would like to report a bug, request a feature, or contribute, you can check out the linked repository and open an issue. - -::: - -## Overview of dbt-rockset - -**Maintained by:** Rockset, Inc. -**Source:** [Github](https://github.com/rockset/dbt-rockset) -**Core version:** v0.19.2 and newer -**dbt Cloud:** Not Supported -**dbt Slack channel:** [Slack](https://getdbt.slack.com/archives/C02J7AZUAMN) - -The easiest way to install is to use pip: - - pip install dbt-rockset - -## Connecting to Rockset with **dbt-rockset** - -The dbt profile for Rockset is very simple and contains the following fields: - - - -```yaml -rockset: - target: dev - outputs: - dev: - type: rockset - workspace: [schema] - api_key: [api_key] - api_server: [api_server] # (Default is api.rs2.usw2.rockset.com) -``` - - - -### Materializations - -Type | Supported? | Details ------|------------|---------------- -view | YES | Creates a [view](https://rockset.com/docs/views/#gatsby-focus-wrapper). -table | YES | Creates a [collection](https://rockset.com/docs/collections/#gatsby-focus-wrapper). -ephemeral | YES | Executes queries using CTEs. -incremental | YES | Creates a [collection](https://rockset.com/docs/collections/#gatsby-focus-wrapper) if it doesn't exist, and then writes results to it. - -## Caveats -1. `unique_key` is not supported with incremental, unless it is set to [_id](https://rockset.com/docs/special-fields/#the-_id-field), which acts as a natural `unique_key` in Rockset anyway. -2. The `table` materialization is slower in Rockset than most due to Rockset's architecture as a low-latency, real-time database. Creating new collections requires provisioning hot storage to index and serve fresh data, which takes about a minute. -3. Rockset queries have a two-minute timeout. Any model which runs a query that takes longer to execute than two minutes will fail. diff --git a/website/docs/reference/warehouse-profiles/spark-profile.md b/website/docs/reference/warehouse-profiles/spark-profile.md deleted file mode 100644 index 450c3532e3d..00000000000 --- a/website/docs/reference/warehouse-profiles/spark-profile.md +++ /dev/null @@ -1,150 +0,0 @@ ---- -title: "Apache Spark Profile" -id: "spark-profile" ---- - -## Overview of dbt-spark - -**Maintained by:** core dbt maintainers -**Author:** dbt Labs -**Source:** [Github](https://github.com/dbt-labs/dbt-spark) -**dbt Cloud:** Supported -**dbt Slack channel** [Link to channel](https://getdbt.slack.com/archives/CNGCW8HKL) - - -![dbt-spark stars](https://img.shields.io/github/stars/dbt-labs/dbt-spark?style=for-the-badge) - -## Connection Methods - -dbt-spark can connect to Spark clusters by three different methods: - -- `odbc` is the preferred method when connecting to Databricks. It supports connecting to a SQL Endpoint or an all-purpose interactive cluster. -- `http` is a more generic method for connecting to a managed service that provides an HTTP endpoint. Currently, this includes connections to a Databricks interactive cluster. -- `thrift` connects directly to the lead node of a cluster, either locally hosted / on premise or in the cloud (e.g. Amazon EMR). - -### ODBC - -New in v0.18.1 - -Use the `odbc` connection method if you are connecting to a Databricks SQL endpoint or interactive cluster via ODBC driver. (Download the latest version of the official driver [here](https://databricks.com/spark/odbc-driver-download).) - - - -```yaml -your_profile_name: - target: dev - outputs: - dev: - type: spark - method: odbc - driver: [path/to/driver] - schema: [database/schema name] - host: [yourorg.sparkhost.com] - organization: [org id] # Azure Databricks only - token: [abc123] - - # one of: - endpoint: [endpoint id] - cluster: [cluster id] - - # optional - port: [port] # default 443 - user: [user] - -``` - - - -### Thrift - -Use the `thrift` connection method if you are connecting to a Thrift server sitting in front of a Spark cluster, e.g. a cluster running locally or on Amazon EMR. - - - -```yaml -your_profile_name: - target: dev - outputs: - dev: - type: spark - method: thrift - schema: [database/schema name] - host: [hostname] - - # optional - port: [port] # default 10001 - user: [user] - auth: [e.g. KERBEROS] - kerberos_service_name: [e.g. hive] -``` - - - -### HTTP - -Use the `http` method if your Spark provider supports generic connections over HTTP (e.g. Databricks interactive cluster). - - - -```yaml -your_profile_name: - target: dev - outputs: - dev: - type: spark - method: http - schema: [database/schema name] - host: [yourorg.sparkhost.com] - organization: [org id] # Azure Databricks only - token: [abc123] - cluster: [cluster id] - - # optional - port: [port] # default: 443 - user: [user] - connect_timeout: 60 # default 10 - connect_retries: 5 # default 0 -``` - - - -Databricks interactive clusters can take several minutes to start up. You may -include the optional profile configs `connect_timeout` and `connect_retries`, -and dbt will periodically retry the connection. - -## Installation and Distribution - -dbt's adapter for Apache Spark and Databricks is managed in its own repository, [dbt-spark](https://github.com/dbt-labs/dbt-spark). To use it, -you must install the `dbt-spark` plugin. - -### Using pip -The following commands will install the latest version of `dbt-spark` as well as the requisite version of `dbt-core`. - -If connecting to Databricks via ODBC driver, it requires `pyodbc`. Depending on your system, you can install it seperately or via pip. See the [`pyodbc` wiki](https://github.com/mkleehammer/pyodbc/wiki/Install) for OS-specific installation details. - -If connecting to a Spark cluster via the generic thrift or http methods, it requires `PyHive`. - -``` -# odbc connections -$ pip install "dbt-spark[ODBC]" - -# thrift or http connections -$ pip install "dbt-spark[PyHive]" -``` - -## Caveats - -### Usage with EMR -To connect to Apache Spark running on an Amazon EMR cluster, you will need to run `sudo /usr/lib/spark/sbin/start-thriftserver.sh` on the master node of the cluster to start the Thrift server (see [the docs](https://aws.amazon.com/premiumsupport/knowledge-center/jdbc-connection-emr/) for more information). You will also need to connect to port 10001, which will connect to the Spark backend Thrift server; port 10000 will instead connect to a Hive backend, which will not work correctly with dbt. - -### Supported Functionality - -Most dbt Core functionality is supported, but some features are only available -on Delta Lake (Databricks). - -Delta-only features: -1. Incremental model updates by `unique_key` instead of `partition_by` (see [`merge` strategy](spark-configs#the-merge-strategy)) -2. [Snapshots](snapshots) - -Some dbt features, available on the core adapters, are not yet supported on Spark: -1. [Persisting](persist_docs) column-level descriptions as database comments diff --git a/website/docs/reference/warehouse-profiles/trino-profile.md b/website/docs/reference/warehouse-profiles/trino-profile.md deleted file mode 100644 index 03deafe599b..00000000000 --- a/website/docs/reference/warehouse-profiles/trino-profile.md +++ /dev/null @@ -1,74 +0,0 @@ ---- -title: "Starburst & Trino Profile" ---- - -:::info Vendor-supported plugin - -Certain core functionality may vary. If you would like to report a bug, request a feature, or contribute, you can check out the linked repository and open an issue. - -::: - -## Overview of dbt-trino - -**Maintained by:** Starburst Data, Inc. -**Source:** [Github](https://github.com/starburstdata/dbt-trino) -**Core version:** v0.20.0 and newer -**dbt Cloud:** Not Supported -**dbt Slack channel:** [Slack](https://getdbt.slack.com/archives/CNNPBQ24R) - -![dbt-presto stars](https://img.shields.io/github/stars/starburstdata/dbt-trino?style=for-the-badge) - -## Installation and Distribution - -dbt's Trino adapter is managed in its own repository, [dbt-trino](https://github.com/starburstdata/dbt-trino). To use the Trino adapter, you must install the `dbt-trino` plugin: - -### Using pip -The following command will install the latest version of `dbt-trino` as well as the requisite version of `dbt-core`: - -``` -pip install dbt-trino -``` - - -## Set up a Trino Target - -Trino targets should be set up using the following configuration in your `profiles.yml` file. - - - -```yaml -trino: - target: dev - outputs: - dev: - type: trino - method: none # optional, one of {none | ldap | kerberos} - user: [user] - password: [password] # required if method is ldap or kerberos - database: [database name] - host: [hostname] - port: [port number] - schema: [your dbt schema] - threads: [1 or more] - http_scheme: [http or https] - session_properties: - query_max_run_time: 5d - exchange_compression: True - - -``` - - - -## Incremental models - -The incremental strategy supported by the adapter is to append new records without updating/overwriting any existing data from the target model. - -## Caveats - -### Unsupported Functionality - -Due to the nature of Trino, not all core dbt functionality is supported. The following features of dbt are not implemented on Trino: - -1. [Snapshots](snapshots) - diff --git a/website/docs/reference/warehouse-setups/alloydb-setup.md b/website/docs/reference/warehouse-setups/alloydb-setup.md new file mode 100644 index 00000000000..b65b0759eed --- /dev/null +++ b/website/docs/reference/warehouse-setups/alloydb-setup.md @@ -0,0 +1,32 @@ +--- +title: "AlloyDB setup" +meta: + maintained_by: Community? + authors: 'dbt-labs' + github_repo: 'dbt-labs/dbt-postgres' + pypi_package: 'dbt-postgres' + min_core_version: 'v1.0.0' + cloud_support: Not Supported + min_supported_version: '?' + slack_channel_name: '#db-postgres' + slack_channel_link: 'https://getdbt.slack.com/archives/C0172G2E273' + platform_name: 'AlloyDB' + config_page: 'postgres-configs' +--- + +## Overview of AlloyDB support + +
    +
  • Maintained by: {frontMatter.meta.maintained_by}
  • +
  • Authors: {frontMatter.meta.authors}
  • +
  • GitHub repo: {frontMatter.meta.github_repo}
  • +
  • PyPI package: {frontMatter.meta.pypi_package}
  • +
  • Slack channel: {frontMatter.meta.slack_channel_name}
  • +
  • Supported dbt Core version: {frontMatter.meta.min_core_version} and newer
  • +
  • dbt Cloud support: {frontMatter.meta.cloud_support}
  • +
  • Minimum data platform version: {frontMatter.meta.min_supported_version}
  • +
+ +## Profile Configuration + +AlloyDB targets are configured exactly the same as [Postgres targets](postgres-setup#profile-configuration). diff --git a/website/docs/reference/warehouse-setups/athena-setup.md b/website/docs/reference/warehouse-setups/athena-setup.md new file mode 100644 index 00000000000..e95b89d69f4 --- /dev/null +++ b/website/docs/reference/warehouse-setups/athena-setup.md @@ -0,0 +1,65 @@ +--- +title: "Athena setup" +meta: + maintained_by: Community + authors: 'Tomme' + github_repo: 'Tomme/dbt-athena' + pypi_package: 'dbt-athena-adapter' + min_core_version: 'v1.0.1' + cloud_support: Not Supported + min_supported_version: 'engine version 2' + slack_channel_name: '#db-athena' + slack_channel_link: 'https://getdbt.slack.com/archives/C013MLFR7BQ' + platform_name: 'Athena' + config_page: 'no-configs' +--- + +

Overview of {frontMatter.meta.pypi_package}

+ +
    +
  • Maintained by: {frontMatter.meta.maintained_by}
  • +
  • Authors: {frontMatter.meta.authors}
  • +
  • GitHub repo: {frontMatter.meta.github_repo}
  • +
  • PyPI package: {frontMatter.meta.pypi_package}
  • +
  • Slack channel: {frontMatter.meta.slack_channel_name}
  • +
  • Supported dbt Core version: {frontMatter.meta.min_core_version} and newer
  • +
  • dbt Cloud support: {frontMatter.meta.cloud_support}
  • +
  • Minimum data platform version: {frontMatter.meta.min_supported_version}
  • +
+ +

Installing {frontMatter.meta.pypi_package}

+ +pip is the easiest way to install the adapter: + +pip install {frontMatter.meta.pypi_package} + +

Installing {frontMatter.meta.pypi_package} will also install dbt-core and any other dependencies.

+ +

Configuring {frontMatter.meta.pypi_package}

+ +

For {frontMatter.meta.platform_name}-specifc configuration please refer to {frontMatter.meta.platform_name} Configuration

+ +

For further info, refer to the GitHub repository: {frontMatter.meta.github_repo}

+ +## Connecting to Athena with dbt-athena + +This plugin does not accept any credentials directly. Instead, [credentials are determined automatically](https://boto3.amazonaws.com/v1/documentation/api/latest/guide/credentials.html) based on AWS CLI/boto3 conventions and stored login info. You can configure the AWS profile name to use via aws_profile_name. Check out the dbt profile configuration below for details. + + + +```yaml +default: + outputs: + dev: + type: athena + s3_staging_dir: [s3_staging_dir] + region_name: [region_name] + database: [database name] + schema: [dev_schema] + aws_profile_name: + [optional, profile to use from your AWS shared credentials file.] + + target: dev +``` + + diff --git a/website/docs/reference/warehouse-setups/azuresynapse-setup.md b/website/docs/reference/warehouse-setups/azuresynapse-setup.md new file mode 100644 index 00000000000..28e1b4b3dea --- /dev/null +++ b/website/docs/reference/warehouse-setups/azuresynapse-setup.md @@ -0,0 +1,96 @@ +--- +title: "Microsoft Azure Synapse DWH setup" +meta: + maintained_by: Community + authors: 'dbt-msft community (https://github.com/dbt-msft)' + github_repo: 'dbt-msft/dbt-synapse' + pypi_package: 'dbt-synapse' + min_core_version: 'v0.18.0' + cloud_support: Not Supported + min_supported_version: 'Azure Synapse 10' + slack_channel_name: '#db-synapse' + slack_channel_link: 'https://getdbt.slack.com/archives/C01DRQ178LQ' + platform_name: 'Synapse' + config_page: 'no-configs' +--- + +:::info Community plugin + +Some core functionality may be limited. If you're interested in contributing, check out the source code for each repository listed below. + +::: + +

Overview of {frontMatter.meta.pypi_package}

+ +
    +
  • Maintained by: {frontMatter.meta.maintained_by}
  • +
  • Authors: {frontMatter.meta.authors}
  • +
  • GitHub repo: {frontMatter.meta.github_repo}
  • +
  • PyPI package: {frontMatter.meta.pypi_package}
  • +
  • Slack channel: {frontMatter.meta.slack_channel_name}
  • +
  • Supported dbt Core version: {frontMatter.meta.min_core_version} and newer
  • +
  • dbt Cloud support: {frontMatter.meta.cloud_support}
  • +
  • Minimum data platform version: {frontMatter.meta.min_supported_version}
  • +
+ +

Installing {frontMatter.meta.pypi_package}

+ +pip is the easiest way to install the adapter: + +pip install {frontMatter.meta.pypi_package} + +

Installing {frontMatter.meta.pypi_package} will also install dbt-core and any other dependencies.

+ +

Configuring {frontMatter.meta.pypi_package}

+ +

For {frontMatter.meta.platform_name}-specifc configuration please refer to {frontMatter.meta.platform_name} Configuration

+ +

For further info, refer to the GitHub repository: {frontMatter.meta.github_repo}

+ +:::info Dedicated SQL only + +Azure Synapse offers both Dedicated and Serverless SQL Pools. +**This adapter supports only Dedicated SQL Pools. If you must use Serverless pools, there is an experimental project that may help, but it has not been updated recently: [dbt-synapse-serverless](https://github.com/dbt-msft/dbt-synapse-serverless)** + +::: + +### Prerequisites + +On Ubuntu, make sure you have the ODBC header files before installing: + + sudo apt install unixodbc-dev + +Download and install the [Microsoft ODBC Driver 17 for SQL Server](https://docs.microsoft.com/en-us/sql/connect/odbc/download-odbc-driver-for-sql-server?view=sql-server-ver15). If you already have ODBC Driver 17 installed, then that one will work as well. + +:::tip Default settings change in dbt-synapse v1.2 / ODBC Driver 18 +Microsoft made several changes related to connection encryption. Read more about the changes [here](mssql-profile#connection-encryption). +::: + +### Authentication methods + +This adapter is based on the adapter for Microsoft SQL Server, and the same authentication methods are supported. + +The configuration is the same except for one significant difference: +Specify `type: synapse` rather than `type: sqlserver`. + +Example: + + + +```yaml +your_profile_name: + target: dev + outputs: + dev: + type: synapse + driver: 'ODBC Driver 17 for SQL Server' # (The ODBC Driver installed on your system) + server: workspacename.sql.azuresynapse.net # (Dedicated SQL endpoint of your workspace here) + port: 1433 + schema: schema_name + user: username + password: password +``` + + + +You can find all available options, the documentation, and how to configure them on [the documentation page for the dbt-sqlserver adapter](mssql-profile#connecting-to-azure-sql-server-with-dbt-sqlserver). diff --git a/website/docs/reference/warehouse-profiles/bigquery-profile.md b/website/docs/reference/warehouse-setups/bigquery-setup.md similarity index 57% rename from website/docs/reference/warehouse-profiles/bigquery-profile.md rename to website/docs/reference/warehouse-setups/bigquery-setup.md index 4e5a691009e..82c92872758 100644 --- a/website/docs/reference/warehouse-profiles/bigquery-profile.md +++ b/website/docs/reference/warehouse-setups/bigquery-setup.md @@ -1,13 +1,45 @@ --- -title: "BigQuery Profile" +title: "BigQuery setup" +meta: + maintained_by: dbt Labs + authors: 'core dbt maintainers' + github_repo: 'dbt-labs/dbt-bigquery' + pypi_package: 'dbt-bigquery' + min_core_version: 'v0.10.0' + cloud_support: Supported + min_supported_version: 'n/a' + slack_channel_name: '#db-bigquery' + slack_channel_link: 'https://getdbt.slack.com/archives/C99SNSRTK' + platform_name: 'Big Query' + config_page: 'bigquery-configs' --- -## Overview of dbt-bigquery -**Maintained by:** core dbt maintainers -**Author:** dbt Labs -**Source:** [Github](https://github.com/dbt-labs/dbt-bigquery) -**dbt Cloud:** Supported -**dbt Slack channel** [Link to channel](https://getdbt.slack.com/archives/C99SNSRTK) +

Overview of {frontMatter.meta.pypi_package}

+ +
    +
  • Maintained by: {frontMatter.meta.maintained_by}
  • +
  • Authors: {frontMatter.meta.authors}
  • +
  • GitHub repo: {frontMatter.meta.github_repo}
  • +
  • PyPI package: {frontMatter.meta.pypi_package}
  • +
  • Slack channel: {frontMatter.meta.slack_channel_name}
  • +
  • Supported dbt Core version: {frontMatter.meta.min_core_version} and newer
  • +
  • dbt Cloud support: {frontMatter.meta.cloud_support}
  • +
  • Minimum data platform version: {frontMatter.meta.min_supported_version}
  • +
+ +

Installing {frontMatter.meta.pypi_package}

+ +pip is the easiest way to install the adapter: + +pip install {frontMatter.meta.pypi_package} + +

Installing {frontMatter.meta.pypi_package} will also install dbt-core and any other dependencies.

+ +

Configuring {frontMatter.meta.pypi_package}

+ +

For {frontMatter.meta.platform_name}-specifc configuration please refer to {frontMatter.meta.platform_name} Configuration

+ +

For further info, refer to the GitHub repository: {frontMatter.meta.github_repo}

## Authentication Methods @@ -195,7 +227,93 @@ my-profile: priority: interactive ``` -### Timeouts +### Timeouts and Retries + + + +The `dbt-bigquery` plugin uses the BigQuery Python client library to submit queries. Each query requires two steps: +1. Job creation: Submit the query job to BigQuery, and receive its job ID. +2. Job execution: Wait for the query job to finish executing, and receive its result. + +Some queries inevitably fail, at different points in process. To handle these cases, dbt supports fine-grained configuration for query timeouts and retries. + +#### job_execution_timeout_seconds + +Use the `job_execution_timeout_seconds` configuration to set the number of seconds dbt should wait for queries to complete, after being submitted successfully. Of the four configurations that control timeout and retries, this one is the most common to use. + +:::info Renamed config + +In older versions of `dbt-bigquery`, this same config was called `timeout_seconds`. + +::: + +No timeout is set by default. (For historical reasons, some query types use a default of 300 seconds when the `job_execution_timeout_seconds` configuration is not set.) When `job_execution_timeout_seconds` is set, if any dbt query, including a model's SQL transformation, takes longer than 300 seconds to complete, BigQuery might cancel the query and issue the following error: + +``` + Operation did not complete within the designated timeout. +``` + +You can change the timeout seconds for the job execution step by configuring `job_execution_timeout_seconds` in the BigQuery profile: + +```yaml +my-profile: + target: dev + outputs: + dev: + type: bigquery + method: oauth + project: abc-123 + dataset: my_dataset + job_execution_timeout_seconds: 600 # 10 minutes +``` + +#### job_creation_timeout_seconds + +It is also possible for a query job to fail to submit in the first place. You can configure the maximum timeout for the job creation step by configuring `job_creation_timeout_seconds`. No timeout is set by default. + +In the job creation step, dbt is simply submitting a query job to BigQuery's `Jobs.Insert` API, and receiving a query job ID in return. It should take a few seconds at most. In some rare situations, it could take longer. + +#### job_retries + +Google's BigQuery Python client has native support for retrying query jobs that time out, or queries that run into transient errors and are likely to succeed if run again. You can configure the maximum number of retries by configuring `job_retries`. + +:::info Renamed config + +In older versions of `dbt-bigquery`, the `job_retries` config was just called `retries`. + +::: + +The default value is 1, meaning that dbt will retry failing queries exactly once. You can set the configuration to 0 to disable retries entirely. + +#### job_retry_deadline_seconds + +After a query job times out, or encounters a transient error, dbt will wait one second before retrying the same query. In cases where queries are repeatedly timing out, this can add up to a long wait. You can set the `job_retry_deadline_seconds` configuration to set the total number of seconds you're willing to wait ("deadline") while retrying the same query. If dbt hits the deadline, it will give up and return an error. + +Combining the four configurations above, we can maximize our chances of mitigating intermittent query errors. In the example below, we will wait up to 30 seconds for initial job creation. Then, we'll wait up to 10 minutes (600 seconds) for the query to return results. If the query times out, or encounters a transient error, we will retry it up to 5 times. The whole process cannot take longer than 20 minutes (1200 seconds). At that point, dbt will raise an error. + + + +```yaml +my-profile: + target: dev + outputs: + dev: + type: bigquery + method: oauth + project: abc-123 + dataset: my_dataset + job_creation_timeout_seconds: 30 + job_execution_timeout_seconds: 600 + job_retries: 5 + job_retry_deadline_seconds: 1200 + +``` + + + + + + BigQuery supports query timeouts. By default, the timeout is set to 300 seconds. If a dbt model takes longer than this timeout to complete, then BigQuery may cancel the query and issue the following error: @@ -205,6 +323,8 @@ BigQuery supports query timeouts. By default, the timeout is set to 300 seconds. To change this timeout, use the `timeout_seconds` configuration: + + ```yaml my-profile: target: dev @@ -217,7 +337,7 @@ my-profile: timeout_seconds: 600 # 10 minutes ``` -### Retries + The `retries` profile configuration designates the number of times dbt should retry queries that result in unhandled server errors. This configuration is only specified for BigQuery targets. Example: @@ -241,10 +361,12 @@ my-profile: + + ### Dataset locations The location of BigQuery datasets can be configured using the `location` configuration in a BigQuery profile. -`location` may be iether a multi-regional location (e.g. `EU`, `US`), or a regional location (e.g. `us-west2` ) as per the [the BigQuery documentation](https://cloud.google.com/bigquery/docs/locations) describes. +`location` may be either a multi-regional location (e.g. `EU`, `US`), or a regional location (e.g. `us-west2` ) as per [the BigQuery documentation](https://cloud.google.com/bigquery/docs/locations) describes. Example: ```yaml @@ -331,8 +453,8 @@ my-profile: For a general overview of this process, see the official docs for [Creating Short-lived Service Account Credentials](https://cloud.google.com/iam/docs/creating-short-lived-service-account-credentials). - - + + ### Execution project New in v0.21.0 @@ -355,13 +477,41 @@ my-profile: execution_project: buck-stops-here-456 ``` + + +### Running Python models on Dataproc + +To run dbt Python models on GCP, dbt uses companion services, Dataproc and Cloud Storage, that offer tight integrations with BigQuery. You may use an existing Dataproc cluster and Cloud Storage bucket, or create new ones: +- https://cloud.google.com/dataproc/docs/guides/create-cluster +- https://cloud.google.com/storage/docs/creating-buckets + +Then, add the bucket name, cluster name, and cluster region to your connection profile: + +```yaml +my-profile: + target: dev + outputs: + dev: + type: bigquery + method: oauth + project: abc-123 + dataset: my_dataset + + # for dbt Python models + gcs_bucket: dbt-python + dataproc_cluster_name: dbt-python + dataproc_region: us-central1 +``` + + + ## Required permissions BigQuery's permission model is dissimilar from more conventional databases like Snowflake and Redshift. The following permissions are required for dbt user accounts: - BigQuery Data Editor - BigQuery User -This set of permissions will permit dbt users to read from and create tables and views in a BigQuery project. +This set of permissions will permit dbt users to read from and create tables and views in a BigQuery project. ## Local OAuth gcloud setup @@ -377,6 +527,6 @@ https://www.googleapis.com/auth/drive.readonly,\ https://www.googleapis.com/auth/iam.test ``` -A browser window should open, and you should be promoted to log into your Google account. Once you've done that, dbt will use your oauth'd credentials to connect to BigQuery! +A browser window should open, and you should be prompted to log into your Google account. Once you've done that, dbt will use your oauth'd credentials to connect to BigQuery! This command uses the `--scopes` flag to request access to Google Sheets. This makes it possible to transform data in Google Sheets using dbt. If your dbt project does not transform data in Google Sheets, then you may omit the `--scopes` flag. diff --git a/website/docs/reference/warehouse-setups/clickhouse-setup.md b/website/docs/reference/warehouse-setups/clickhouse-setup.md new file mode 100644 index 00000000000..5c66eab6df3 --- /dev/null +++ b/website/docs/reference/warehouse-setups/clickhouse-setup.md @@ -0,0 +1,113 @@ +--- +title: "ClickHouse setup" +meta: + maintained_by: Community + authors: 'Geoff Genz' + github_repo: 'ClickHouse/dbt-clickhouse' + pypi_package: 'dbt-clickhouse' + min_core_version: 'v0.19.0' + cloud_support: Not Supported + min_supported_version: '?' + slack_channel_name: '#db-clickhouse' + slack_channel_link: 'https://getdbt.slack.com/archives/C01DRQ178LQ' + platform_name: 'Clickhouse' + config_page: 'clickhouse-configs' +--- + +Some core functionality may be limited. If you're interested in contributing, check out the source code for each repository listed below. + + +

Overview of {frontMatter.meta.pypi_package}

+ +
    +
  • Maintained by: {frontMatter.meta.maintained_by}
  • +
  • Authors: {frontMatter.meta.authors}
  • +
  • GitHub repo: {frontMatter.meta.github_repo}
  • +
  • PyPI package: {frontMatter.meta.pypi_package}
  • +
  • Slack channel: {frontMatter.meta.slack_channel_name}
  • +
  • Supported dbt Core version: {frontMatter.meta.min_core_version} and newer
  • +
  • dbt Cloud support: {frontMatter.meta.cloud_support}
  • +
  • Minimum data platform version: {frontMatter.meta.min_supported_version}
  • +
+ + +

Installing {frontMatter.meta.pypi_package}

+ +pip is the easiest way to install the adapter: + +pip install {frontMatter.meta.pypi_package} + +

Installing {frontMatter.meta.pypi_package} will also install dbt-core and any other dependencies.

+ +

Configuring {frontMatter.meta.pypi_package}

+ +

For {frontMatter.meta.platform_name}-specifc configuration please refer to {frontMatter.meta.platform_name} Configuration

+ +

For further info, refer to the GitHub repository: {frontMatter.meta.github_repo}

+ +## Connecting to ClickHouse with **dbt-clickhouse** + +To connect to ClickHouse from dbt, you'll need to add a [profile](https://docs.getdbt.com/dbt-cli/configure-your-profile) to your `profiles.yml` file. A ClickHouse profile conforms to the following syntax: + + + +```yaml +: + target: + outputs: + : + type: clickhouse + schema: + user: + password: + #optional fields + driver: http|native + port: + host: + retries: 1 + verify: False + secure: True + connect_timeout: 10 + send_receive_timeout: 300 + sync_request_timeout: 5 + compression: False + compress_block_size: 1048576 + database_engine: + check_exchange: True + custom_settings: + +``` + + + +#### Description of ClickHouse Profile Fields + + +| Field | Description | +|------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `type` | This must be included either in `profiles.yml` or in the `dbt_project.yml` file. Must be set to `clickhouse`. | +| `schema` | Required. A ClickHouse's database name. The dbt model database.schema.table is not compatible with ClickHouse because ClickHouse does not support a schema. So we use a simple model schema.table, where schema is the ClickHouse's database. We don't recommend using the `default` database. | +| `user` | Required. A ClickHouse username with adequate permissions to access the specified `schema`. | +| `password` | Required. The password associated with the specified `user`. | +| `driver` | Optional. The ClickHouse client interface, `http` or `native`. Defaults to `http` unless the `port` is set to 9440 or 9400, in which case the `native` driver is assumed. | +| `port` | Optional. ClickHouse server port number. Defaults to 8123/8443 (secure) if the driver is `http`, and to 9000/9440(secure) if the driver is `native`. | +| `host` | Optional. The host name of the connection. Default is `localhost`. | +| `retries` | Optional. Number of times to retry the initial connection attempt if the error appears to be recoverable. | +| `verify` | Optional. For (`secure=True`) connections, validate the ClickHouse server TLS certificate, including matching hostname, expiration, and signed by a trusted Certificate Authority. Defaults to True. | +| `secure` | Optional. Whether the connection (either http or native) is secured by TLS. This converts an http driver connection to https, and a native driver connection to the native ClickHouse protocol over TLS. the Defaults to False. | +| `cluster_mode` | Optional. Add connection settings to improve compatibility with clusters using the Replicated Database Engine. Default False. | +| `connect_timeout` | Optional. Connection timeout in seconds. Defaults is 10 seconds. | +| `send_receive_timeout` | Optional. Timeout for receiving data from or sending data to ClickHouse. Defaults to 5 minutes (300 seconds) | +| `sync_request_timeout` | Optional. Timeout for connection ping request (native connection only). Defaults to 5 seconds. | +| `compression` | Optional. Use compression in the connection. Defaults to `False`. If set to `True` for HTTP, this enables gzip compression. If set to `True` for the native protocol, this enabled lz4 compression. Other valid values are `lz4hc` and `zstd` for the native driver only. | +| `compress_block_size` | Optional. Compression block size (in bytes) when using compression with the native driver. Defaults to 1MB | +| `database_engine` | Optional. Database engine to use when creating new ClickHouse schemas (databases). If not set (the default), new databases will use the default ClickHouse database engine (usually Atomic). | +| `check_exchange` | Optional. On connecting to the ClickHouse, if this is parameter is `True` DBT will validate that the ClickHouse server supports atomic exchange of tables. Using atomic exchange (when available) improves reliability and parallelism. This check is unnecessary for ClickHouse running on recent Linux operating system, and in those circumstances can be disabled by setting `check_exchange` to `False` to avoid additional overhead on startup. Defaults to `True`. | +| `custom_settings` | Optional. A mapping of ClickHouse specific user settings to use with the connection. See the ClickHouse documentation for supported settings. | + +#### Troubleshooting Connections + +If you encounter issues connecting to ClickHouse from dbt, make sure the following criteria are met: +- The engine must be one of the [supported engines](clickhouse-configs#supported-table-engines). +- You must have adequate permissions to access the database. +- If you're not using the default table engine for the database, you must specify a table engine in your model configuration. \ No newline at end of file diff --git a/website/docs/reference/warehouse-setups/databricks-setup.md b/website/docs/reference/warehouse-setups/databricks-setup.md new file mode 100644 index 00000000000..314a7f77d6f --- /dev/null +++ b/website/docs/reference/warehouse-setups/databricks-setup.md @@ -0,0 +1,98 @@ +--- +title: "Databricks setup" +id: "databricks-setup" +meta: + maintained_by: Databricks + authors: 'some dbt loving Bricksters' + github_repo: 'databricks/dbt-databricks' + pypi_package: 'dbt-databricks' + min_core_version: 'v0.18.0' + cloud_support: Coming Soon + min_supported_version: 'n/a' + slack_channel_name: '#db-databricks-and-spark' + slack_channel_link: 'https://getdbt.slack.com/archives/CNGCW8HKL' + platform_name: 'Databricks' + config_page: 'spark-configs' +--- + +

Overview of {frontMatter.meta.pypi_package}

+ +
    +
  • Maintained by: {frontMatter.meta.maintained_by}
  • +
  • Authors: {frontMatter.meta.authors}
  • +
  • GitHub repo: {frontMatter.meta.github_repo}
  • +
  • PyPI package: {frontMatter.meta.pypi_package}
  • +
  • Slack channel: {frontMatter.meta.slack_channel_name}
  • +
  • Supported dbt Core version: {frontMatter.meta.min_core_version} and newer
  • +
  • dbt Cloud support: {frontMatter.meta.cloud_support}
  • +
  • Minimum data platform version: {frontMatter.meta.min_supported_version}
  • +
+ +## Installation and Distribution + + +

Installing {frontMatter.meta.pypi_package}

+ +pip is the easiest way to install the adapter: + +pip install {frontMatter.meta.pypi_package} + +

Installing {frontMatter.meta.pypi_package} will also install dbt-core and any other dependencies.

+ +

Configuring {frontMatter.meta.pypi_package}

+ +

For {frontMatter.meta.platform_name}-specifc configuration please refer to {frontMatter.meta.platform_name} Configuration

+ +

For further info, refer to the GitHub repository: {frontMatter.meta.github_repo}

+ + +### Set up a Databricks Target + +dbt-databricks can connect to Databricks all-purpose clusters as well as SQL endpoints. +The latter provides an opinionated way of running SQL workloads with optimal performance and price; the former provides all the flexibility of Spark. + + + +```yaml +your_profile_name: + target: dev + outputs: + dev: + type: databricks + catalog: [optional catalog name, if you are using Unity Catalog, is only available in dbt-databricks>=1.1.1] + schema: [schema name] + host: [yourorg.databrickshost.com] + http_path: [/sql/your/http/path] + token: [dapiXXXXXXXXXXXXXXXXXXXXXXX] # Personal Access Token (PAT) + threads: [1 or more] # optional, default 1 +``` + + + +See the [Databricks documentation](https://docs.databricks.com/dev-tools/dbt.html#) on how +to obtain the credentials for configuring your profile. + +## Caveats + +### Supported Functionality + +Most dbt Core functionality is supported, but some features are only available +on Delta Lake. + +Delta-only features: +1. Incremental model updates by `unique_key` instead of `partition_by` (see [`merge` strategy](spark-configs#the-merge-strategy)) +2. [Snapshots](https://docs.getdbt.com/docs/building-a-dbt-project/snapshots) + +### Choosing between dbt-databricks and dbt-spark + +While `dbt-spark` can be used to connect to Databricks, `dbt-databricks` was created to make it +even easier to use dbt with the Databricks Lakehouse. + +`dbt-databricks` includes: +- No need to install additional drivers or dependencies for use on the CLI +- Use of Delta Lake for all models out of the box +- SQL macros that are optimzed to run with [Photon](https://docs.databricks.com/runtime/photon.html) + +### Support for Unity Catalog + +The adapter `dbt-databricks>=1.1.1` supports the 3-level namespace of Unity Catalog (catalog / schema / relations) so you can organize and secure your data the way you like. diff --git a/website/docs/reference/warehouse-setups/dremio-setup.md b/website/docs/reference/warehouse-setups/dremio-setup.md new file mode 100644 index 00000000000..6b7d871f120 --- /dev/null +++ b/website/docs/reference/warehouse-setups/dremio-setup.md @@ -0,0 +1,76 @@ +--- +title: "Dremio setup" +meta: + maintained_by: Community + authors: 'Fabrice Etanchaud (Maif-vie)' + github_repo: 'fabrice-etanchaud/dbt-dremio' + pypi_package: 'dbt-dremio' + min_core_version: 'v0.18.0' + cloud_support: Not Supported + min_supported_version: 'Dremio 4.7' + slack_channel_name: 'n/a' + slack_channel_link: 'https://www.getdbt.com/community' + platform_name: 'Dremio' + config_page: 'no-configs' +--- + +:::info Community plugin + +Some core functionality may be limited. If you're interested in contributing, check out the source code for each repository listed below. + +::: + +

Overview of {frontMatter.meta.pypi_package}

+ +
    +
  • Maintained by: {frontMatter.meta.maintained_by}
  • +
  • Authors: {frontMatter.meta.authors}
  • +
  • GitHub repo: {frontMatter.meta.github_repo}
  • +
  • PyPI package: {frontMatter.meta.pypi_package}
  • +
  • Slack channel: {frontMatter.meta.slack_channel_name}
  • +
  • Supported dbt Core version: {frontMatter.meta.min_core_version} and newer
  • +
  • dbt Cloud support: {frontMatter.meta.cloud_support}
  • +
  • Minimum data platform version: {frontMatter.meta.min_supported_version}
  • +
+ + +

Installing {frontMatter.meta.pypi_package}

+ +pip is the easiest way to install the adapter: + +pip install {frontMatter.meta.pypi_package} + +

Installing {frontMatter.meta.pypi_package} will also install dbt-core and any other dependencies.

+ +

Configuring {frontMatter.meta.pypi_package}

+ +

For {frontMatter.meta.platform_name}-specifc configuration please refer to {frontMatter.meta.platform_name} Configuration

+ +

For further info, refer to the GitHub repository: {frontMatter.meta.github_repo}

+ dbt-dremio + +Follow the repository's link for os dependencies. + +## Connecting to Dremio with **dbt-dremio** + +### Connecting with ZooKeeper + +I have no means to test [connection with ZooKeeper](https://docs.dremio.com/drivers/dremio-connector.html#connecting-to-zookeeper). +If you do need this, contact me and I will provide you with a branch you can test. + +### Direct connection to a coordinator + +```yaml +my_profile: + outputs: + my_target: + type: dremio + threads: 2 +# please replace driver below with the one you gave to your dremio odbc driver installation + driver: Dremio ODBC Driver 64-bit + host: [coordinator host] + port: 31010 + schema: [schema] + user: [user] + password: [password] + target: my_target diff --git a/website/docs/reference/warehouse-setups/duckdb-setup.md b/website/docs/reference/warehouse-setups/duckdb-setup.md new file mode 100644 index 00000000000..d4488a2ead6 --- /dev/null +++ b/website/docs/reference/warehouse-setups/duckdb-setup.md @@ -0,0 +1,75 @@ +--- +title: "DuckDB setup" +meta: + maintained_by: Community + authors: 'Josh Wills (https://github.com/jwills)' + github_repo: 'jwills/dbt-duckdb' + pypi_package: 'dbt-duckdb' + min_core_version: 'v1.0.1' + cloud_support: Not Supported + min_supported_version: 'DuckDB 0.3.2' + slack_channel_name: '#db-duckdb' + slack_channel_link: 'https://getdbt.slack.com/archives/C039D1J1LA2' + platform_name: 'Duck DB' + config_page: 'no-configs' +--- + +:::info Community plugin + +Some core functionality may be limited. If you're interested in contributing, check out the source code for each repository listed below. + +::: + +

Overview of {frontMatter.meta.pypi_package}

+ +
    +
  • Maintained by: {frontMatter.meta.maintained_by}
  • +
  • Authors: {frontMatter.meta.authors}
  • +
  • GitHub repo: {frontMatter.meta.github_repo}
  • +
  • PyPI package: {frontMatter.meta.pypi_package}
  • +
  • Slack channel: {frontMatter.meta.slack_channel_name}
  • +
  • Supported dbt Core version: {frontMatter.meta.min_core_version} and newer
  • +
  • dbt Cloud support: {frontMatter.meta.cloud_support}
  • +
  • Minimum data platform version: {frontMatter.meta.min_supported_version}
  • +
+ + +

Installing {frontMatter.meta.pypi_package}

+ +pip is the easiest way to install the adapter: + +pip install {frontMatter.meta.pypi_package} + +

Installing {frontMatter.meta.pypi_package} will also install dbt-core and any other dependencies.

+ +

Configuring {frontMatter.meta.pypi_package}

+ +

For {frontMatter.meta.platform_name}-specifc configuration please refer to {frontMatter.meta.platform_name} Configuration

+ +

For further info, refer to the GitHub repository: {frontMatter.meta.github_repo}

+ + +## Connecting to DuckDB with dbt-duckdb + +[DuckDB](http://duckdb.org) is an embedded database, similar to SQLite, but designed for OLAP-style analytics instead of OLTP. The only configuration parameter that is required in your profile (in addition to `type: duckdb`) is the `path` field, which should refer to a path on your local filesystem where you would like the DuckDB database file (and it's associated write-ahead log) to be written. You can also specify the `schema` parameter if you would like to use a schema besides the default (which is called `main`). + +There is also a `database` field defined in the `DuckDBCredentials` class for consistency with the parent `Credentials` class, but it defaults to `main` and setting it to be something else will likely cause strange things to happen that cannot be fully predicted, so please avoid changing it. + +Example: + + + +```yaml +your_profile_name: + target: dev + outputs: + dev: + type: duckdb + path: 'file_path/database_name.duckdb' + #optional fields + schema: schema_name +``` + + + + diff --git a/website/docs/reference/warehouse-setups/exasol-setup.md b/website/docs/reference/warehouse-setups/exasol-setup.md new file mode 100644 index 00000000000..1e29db02513 --- /dev/null +++ b/website/docs/reference/warehouse-setups/exasol-setup.md @@ -0,0 +1,76 @@ +--- +title: "Exasol setup" +meta: + maintained_by: Community + authors: 'Torsten Glunde, Ilija Kutle' + github_repo: 'tglunde/dbt-exasol' + pypi_package: 'dbt-exasol' + min_core_version: 'v0.14.0' + cloud_support: Not Supported + min_supported_version: 'Exasol 6.x' + slack_channel_name: 'n/a' + slack_channel_link: 'https://www.getdbt.com/community' + platform_name: 'Exasol' + config_page: 'no-configs' +--- + +:::info Community plugin + +Some core functionality may be limited. If you're interested in contributing, check out the source code for each repository listed below. + +::: + +

Overview of {frontMatter.meta.pypi_package}

+ +
    +
  • Maintained by: {frontMatter.meta.maintained_by}
  • +
  • Authors: {frontMatter.meta.authors}
  • +
  • GitHub repo: {frontMatter.meta.github_repo}
  • +
  • PyPI package: {frontMatter.meta.pypi_package}
  • +
  • Slack channel: {frontMatter.meta.slack_channel_name}
  • +
  • Supported dbt Core version: {frontMatter.meta.min_core_version} and newer
  • +
  • dbt Cloud support: {frontMatter.meta.cloud_support}
  • +
  • Minimum data platform version: {frontMatter.meta.min_supported_version}
  • +
+ + +

Installing {frontMatter.meta.pypi_package}

+ +pip is the easiest way to install the adapter: + +pip install {frontMatter.meta.pypi_package} + +

Installing {frontMatter.meta.pypi_package} will also install dbt-core and any other dependencies.

+ +

Configuring {frontMatter.meta.pypi_package}

+ +

For {frontMatter.meta.platform_name}-specifc configuration please refer to {frontMatter.meta.platform_name} Configuration

+ +

For further info, refer to the GitHub repository: {frontMatter.meta.github_repo}

+ dbt-exasol + +### Connecting to Exasol with **dbt-exasol** + +#### User / password authentication + +Configure your dbt profile for using Exasol: + +##### Exasol connection information + + + +```yaml +dbt-exasol: + target: dev + outputs: + dev: + type: exasol + threads: 1 + dsn: HOST:PORT + user: USERNAME + password: PASSWORD + dbname: db + schema: SCHEMA +``` + + diff --git a/website/docs/reference/warehouse-setups/firebolt-setup.md b/website/docs/reference/warehouse-setups/firebolt-setup.md new file mode 100644 index 00000000000..7c724307131 --- /dev/null +++ b/website/docs/reference/warehouse-setups/firebolt-setup.md @@ -0,0 +1,125 @@ +--- +title: "Firebolt setup" +meta: + maintained_by: Firebolt + authors: 'Firebolt' + github_repo: 'firebolt-db/dbt-firebolt' + pypi_package: 'dbt-firebolt' + min_core_version: 'v1.1.0' + cloud_support: Not Supported + min_supported_version: 'n/a' + slack_channel_name: '#db-firebolt' + slack_channel_link: 'https://getdbt.slack.com/archives/C03K2PTHHTP' + platform_name: 'Firebolt' + config_page: 'firebolt-configs' +--- + + +Some core functionality may be limited. If you're interested in contributing, check out the source code for the repository listed below. + + +

Overview of {frontMatter.meta.pypi_package}

+ +
    +
  • Maintained by: {frontMatter.meta.maintained_by}
  • +
  • Authors: {frontMatter.meta.authors}
  • +
  • GitHub repo: {frontMatter.meta.github_repo}
  • +
  • PyPI package: {frontMatter.meta.pypi_package}
  • +
  • Slack channel: {frontMatter.meta.slack_channel_name}
  • +
  • Supported dbt Core version: {frontMatter.meta.min_core_version} and newer
  • +
  • dbt Cloud support: {frontMatter.meta.cloud_support}
  • +
  • Minimum data platform version: {frontMatter.meta.min_supported_version}
  • +
+ + +

Installing {frontMatter.meta.pypi_package}

+ +pip is the easiest way to install the adapter: + +pip install {frontMatter.meta.pypi_package} + +

Installing {frontMatter.meta.pypi_package} will also install dbt-core and any other dependencies.

+ +

Configuring {frontMatter.meta.pypi_package}

+ +

For {frontMatter.meta.platform_name}-specifc configuration please refer to {frontMatter.meta.platform_name} Configuration

+ +

For further info, refer to the GitHub repository: {frontMatter.meta.github_repo}

+ + +For other information including Firebolt feature support, see the [GitHub README](https://github.com/firebolt-db/dbt-firebolt/blob/main/README.md) and the [changelog](https://github.com/firebolt-db/dbt-firebolt/blob/main/CHANGELOG.md). + + +## Connecting to Firebolt + +To connect to Firebolt from dbt, you'll need to add a [profile](https://docs.getdbt.com/dbt-cli/configure-your-profile) to your `profiles.yml` file. A Firebolt profile conforms to the following syntax: + + + +```yml +: + target: + outputs: + : + type: firebolt + user: "" + password: "" + database: "" + engine_name: "" + schema: + threads: 1 + #optional fields + jar_path: + host: "" + account_name: "" +``` + + + + +#### Description of Firebolt Profile Fields + +To specify values as environment variables, use the format `{{ env_var('' }}`. For example, `{{ env_var('DATABASE_NAME' }}`. + +| Field | Description | +|--------------------------|--------------------------------------------------------------------------------------------------------| +| `type` | This must be included either in `profiles.yml` or in the `dbt_project.yml` file. Must be set to `firebolt`. | +| `user` | Required. A Firebolt username with adequate permissions to access the specified `engine_name`. | +| `password` | Required. The password associated with the specified `user`. | +| `database` | Required. The name of the Firebolt database to connect to. | +| `engine_name` | Required in version 0.21.10 and later. Optional in earlier versions. The name (not the URL) of the Firebolt engine to use in the specified `database`. This must be a general purpose read-write engine and the engine must be running. If omitted in earlier versions, the default engine for the specified `database` is used. | +| `schema` | Recommended. A string to add as a prefix to the names of generated tables when using the [custom schemas workaround](https://docs.getdbt.com/reference/warehouse-profiles/firebolt-profile#supporting-concurrent-development). | +| `threads` | Required. Must be set to `1`. Multi-threading is not currently supported. | +| `jar_path` | Required only with versions earlier than 0.21.0. Ignored in 0.21.0 and later. The path to your JDBC driver on your local drive. | +| `host` | Optional. The host name of the connection. For all customers it is `api.app.firebolt.io`, which will be used if omitted. | +| `account_name` | Required if more than one account is associated with the specified `user1`. Specifies the account name (not the account ID) under which the specified `database` exists. If omitted, the default account is assumed. | + + +#### Troubleshooting Connections + +If you encounter issues connecting to Firebolt from dbt, make sure the following criteria are met: +- The engine must be a general-purpose read-write engine, not an analytics engine. +- You must have adequate permissions to access the engine. +- The engine must be running. +- If you're not using the default engine for the database, you must specify an engine name. +- If there is more than one account associated with your credentials, you must specify an account. + + +## Supporting Concurrent Development + +In dbt, database schemas are used to compartmentalize developer environments so that concurrent development does not cause name collisions. Firebolt, however, does not currently support database schemas (it is on the roadmap). To work around this, we recommend that you add the following macro to your project. This macro will take the `schema` field of your `profiles.yml` file and use it as a table name prefix. + +```sql +-- macros/generate_alias_name.sql +{% macro generate_alias_name(custom_alias_name=none, node=none) -%} + {%- if custom_alias_name is none -%} + {{ node.schema }}__{{ node.name }} + {%- else -%} + {{ node.schema }}__{{ custom_alias_name | trim }} + {%- endif -%} +{%- endmacro %} +``` + +For an example of how this works, let’s say Shahar and Eric are both working on the same project. + +In her `.dbt/profiles.yml`, Sharar sets `schema=sh`, whereas Eric sets `schema=er` in his. When each runs the `customers` model, the models will land in the database as tables named `sh_customers` and `er_customers`, respectively. When running dbt in production, you would use yet another `profiles.yml` with a string of your choice. diff --git a/website/docs/reference/warehouse-setups/glue-setup.md b/website/docs/reference/warehouse-setups/glue-setup.md new file mode 100644 index 00000000000..93af196cf01 --- /dev/null +++ b/website/docs/reference/warehouse-setups/glue-setup.md @@ -0,0 +1,273 @@ +--- +title: "AWS Glue Setup" +id: "glue-setup" +meta: + maintained_by: Community + authors: 'Benjamin Menuet, Moshir Mikael, Armando Segnini and Amine El Mallem' + github_repo: 'aws-samples/dbt-glue' + pypi_package: 'dbt-glue' + min_core_version: 'v0.24.0' + cloud_support: Not Supported + min_supported_version: 'Glue 2.0' + slack_channel_name: '#db-glue' + slack_channel_link: 'https://getdbt.slack.com/archives/C02R4HSMBAT' + platform_name: 'AWS Glue' + config_page: 'glue-configs' +--- + +:::info Community plugin + +Some core functionality may be limited. If you're interested in contributing, check out the source code for each repository listed below. + +::: + +

Overview of {frontMatter.meta.pypi_package}

+ +
    +
  • Maintained by: {frontMatter.meta.maintained_by}
  • +
  • Authors: {frontMatter.meta.authors}
  • +
  • GitHub repo: {frontMatter.meta.github_repo}
  • +
  • PyPI package: {frontMatter.meta.pypi_package}
  • +
  • Slack channel: {frontMatter.meta.slack_channel_name}
  • +
  • Supported dbt Core version: {frontMatter.meta.min_core_version} and newer
  • +
  • dbt Cloud support: {frontMatter.meta.cloud_support}
  • +
  • Minimum data platform version: {frontMatter.meta.min_supported_version}
  • +
+ + +

Installing {frontMatter.meta.pypi_package}

+ +pip is the easiest way to install the adapter: + +pip install {frontMatter.meta.pypi_package} + +

Installing {frontMatter.meta.pypi_package} will also install dbt-core and any other dependencies.

+ +

Configuring {frontMatter.meta.pypi_package}

+ +

For {frontMatter.meta.platform_name}-specifc configuration please refer to {frontMatter.meta.platform_name} Configuration

+ +

For further info, refer to the GitHub repository: {frontMatter.meta.github_repo}

+ +For further (and more likely up-to-date) info, see the [README](https://github.com/aws-samples/dbt-glue#readme) + + +## Connection Methods + + +### Configuring your AWS profile for Glue Interactive Session +There are two IAM principals used with interactive sessions. +- Client principal: The princpal (either user or role) calling the AWS APIs (Glue, Lake Formation, Interactive Sessions) +from the local client. This is the principal configured in the AWS CLI and likely the same. +- Service role: The IAM role that AWS Glue uses to execute your session. This is the same as AWS Glue +ETL. + +Read [this documentation](https://docs.aws.amazon.com/glue/latest/dg/glue-is-security.html) to configure these principals. + + +You will find bellow a least privileged policy to enjoy all features of **`dbt-glue`** adapter. + +Please to update variables between **`<>`**, here are explanations of these arguments: + +|Args |Description | +|---|---| +|region|The region where your Glue database is stored | +|AWS Account|The AWS account where you run your pipeline| +|dbt output database|The database updated by dbt (this is the database configured in the profile.yml of your dbt environment)| +|dbt source database|All databases used as source| +|dbt output bucket|The bucket name where the data will be generated by dbt (the location configured in the profile.yml of your dbt environment)| +|dbt source bucket|The bucket name of source databases (if they are not managed by Lake Formation)| + + + +```yml +{ + "Version": "2012-10-17", + "Statement": [ + { + "Sid": "Read_and_write_databases", + "Action": [ + "glue:SearchTables", + "glue:BatchCreatePartition", + "glue:CreatePartitionIndex", + "glue:DeleteDatabase", + "glue:GetTableVersions", + "glue:GetPartitions", + "glue:DeleteTableVersion", + "glue:UpdateTable", + "glue:DeleteTable", + "glue:DeletePartitionIndex", + "glue:GetTableVersion", + "glue:UpdateColumnStatisticsForTable", + "glue:CreatePartition", + "glue:UpdateDatabase", + "glue:CreateTable", + "glue:GetTables", + "glue:GetDatabases", + "glue:GetTable", + "glue:GetDatabase", + "glue:GetPartition", + "glue:UpdateColumnStatisticsForPartition", + "glue:CreateDatabase", + "glue:BatchDeleteTableVersion", + "glue:BatchDeleteTable", + "glue:DeletePartition", + "lakeformation:ListResources", + "lakeformation:BatchGrantPermissions", + "lakeformation:ListPermissions" + ], + "Resource": [ + "arn:aws:glue:::catalog", + "arn:aws:glue:::table//*", + "arn:aws:glue:::database/" + ], + "Effect": "Allow" + }, + { + "Sid": "Read_only_databases", + "Action": [ + "glue:SearchTables", + "glue:GetTableVersions", + "glue:GetPartitions", + "glue:GetTableVersion", + "glue:GetTables", + "glue:GetDatabases", + "glue:GetTable", + "glue:GetDatabase", + "glue:GetPartition", + "lakeformation:ListResources", + "lakeformation:ListPermissions" + ], + "Resource": [ + "arn:aws:glue:::table//*", + "arn:aws:glue:::database/", + "arn:aws:glue:::database/default", + "arn:aws:glue:::database/global_temp" + ], + "Effect": "Allow" + }, + { + "Sid": "Storage_all_buckets", + "Action": [ + "s3:GetBucketLocation", + "s3:ListBucket" + ], + "Resource": [ + "arn:aws:s3:::", + "arn:aws:s3:::" + ], + "Effect": "Allow" + }, + { + "Sid": "Read_and_write_buckets", + "Action": [ + "s3:PutObject", + "s3:PutObjectAcl", + "s3:GetObject", + "s3:DeleteObject" + ], + "Resource": [ + "arn:aws:s3:::" + ], + "Effect": "Allow" + }, + { + "Sid": "Read_only_buckets", + "Action": [ + "s3:GetObject" + ], + "Resource": [ + "arn:aws:s3:::" + ], + "Effect": "Allow" + } + ] +} +``` + + +### Configuration of the local environment + +Because **`dbt`** and **`dbt-glue`** adapter are compatible with Python versions 3.7, 3.8, and 3.9, check the version of Python: + +```bash +$ python3 --version +``` + +Configure a Python virtual environment to isolate package version and code dependencies: + +```bash +$ sudo yum install git +$ python3 -m venv dbt_venv +$ source dbt_venv/bin/activate +$ python3 -m pip install --upgrade pip +``` + +Configure the last version of AWS CLI + +```bash +$ curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" +$ unzip awscliv2.zip +$ sudo ./aws/install +``` + +Configure the aws-glue-session package + +```bash +$ sudo yum install gcc krb5-devel.x86_64 python3-devel.x86_64 -y +$ pip3 install —upgrade boto3 +$ pip3 install —upgrade aws-glue-sessions +``` + +### Example config + + +```yml +type: glue +query-comment: This is a glue dbt example +role_arn: arn:aws:iam::1234567890:role/GlueInteractiveSessionRole +region: us-east-1 +workers: 2 +worker_type: G.1X +idle_timeout: 10 +schema: "dbt_demo" +database: "dbt_demo" +session_provisioning_timeout_in_seconds: 120 +location: "s3://dbt_demo_bucket/dbt_demo_data" +``` + + + +The table below describes all the options. + +|Option |Description | Mandatory | +|---|---|---| +|project_name |The dbt project name. This must be the same as the one configured in the dbt project. |yes| +|type |The driver to use. |yes| +|query-comment |A string to inject as a comment in each query that dbt runs. |no| +|role_arn |The ARN of the interactive session role created as part of the CloudFormation template. |yes| +|region |The AWS Region where you run the data pipeline. |yes| +|workers |The number of workers of a defined workerType that are allocated when a job runs. |yes| +|worker_type |The type of predefined worker that is allocated when a job runs. Accepts a value of Standard, G.1X, or G.2X. |yes| +|schema |The schema used to organize data stored in Amazon S3. |yes| +|database |The database in Lake Formation. The database stores metadata tables in the Data Catalog. |yes| +|session_provisioning_timeout_in_seconds |The timeout in seconds for AWS Glue interactive session provisioning. |yes| +|location |The Amazon S3 location of your target data. |yes| +|idle_timeout |The AWS Glue session idle timeout in minutes. (The session stops after being idle for the specified amount of time.) |no| +|glue_version |The version of AWS Glue for this session to use. Currently, the only valid options are 2.0 and 3.0. The default value is 2.0. |no| +|security_configuration |The security configuration to use with this session. |no| +|connections |A comma-separated list of connections to use in the session. |no| + + +## Caveats + +### Supported Functionality + +Most dbt Core functionality is supported, but some features are only available with Apache Hudi. + +Apache Hudi-only features: +1. Incremental model updates by `unique_key` instead of `partition_by` (see [`merge` strategy](glue-configs#the-merge-strategy)) + +Some dbt features, available on the core adapters, are not yet supported on Glue: +1. [Persisting](persist_docs) column-level descriptions as database comments +2. [Snapshots](snapshots) diff --git a/website/docs/reference/warehouse-setups/greenplum-setup.md b/website/docs/reference/warehouse-setups/greenplum-setup.md new file mode 100644 index 00000000000..2d708bb3d5f --- /dev/null +++ b/website/docs/reference/warehouse-setups/greenplum-setup.md @@ -0,0 +1,80 @@ +--- +title: "Greenplum setup" +id: "greenplum-setup" +meta: + maintained_by: Community + authors: 'Mark Poroshin, Dmitry Bevz' + github_repo: 'markporoshin/dbt-greenplum' + pypi_package: 'dbt-greenplum' + min_core_version: 'v1.0.0' + cloud_support: Not Supported + min_supported_version: 'Greenplum 6.0' + slack_channel_name: 'n/a' + slack_channel_link: 'https://www.getdbt.com/community' + platform_name: 'Greenplum' + config_page: 'greenplum-configs' +--- + +

Overview of {frontMatter.meta.pypi_package}

+ +
    +
  • Maintained by: {frontMatter.meta.maintained_by}
  • +
  • Authors: {frontMatter.meta.authors}
  • +
  • GitHub repo: {frontMatter.meta.github_repo}
  • +
  • PyPI package: {frontMatter.meta.pypi_package}
  • +
  • Slack channel: {frontMatter.meta.slack_channel_name}
  • +
  • Supported dbt Core version: {frontMatter.meta.min_core_version} and newer
  • +
  • dbt Cloud support: {frontMatter.meta.cloud_support}
  • +
  • Minimum data platform version: {frontMatter.meta.min_supported_version}
  • +
+ + +

Installing {frontMatter.meta.pypi_package}

+ +pip is the easiest way to install the adapter: + +pip install {frontMatter.meta.pypi_package} + +

Installing {frontMatter.meta.pypi_package} will also install dbt-core and any other dependencies.

+ +

Configuring {frontMatter.meta.pypi_package}

+ +

For {frontMatter.meta.platform_name}-specifc configuration please refer to {frontMatter.meta.platform_name} Configuration

+ +

For further info, refer to the GitHub repository: {frontMatter.meta.github_repo}

+ +For further (and more likely up-to-date) info, see the [README](https://github.com/markporoshin/dbt-greenplum#README.md) + + +## Profile Configuration + +Greenplum targets should be set up using the following configuration in your `profiles.yml` file. + + + +```yaml +company-name: + target: dev + outputs: + dev: + type: greenplum + host: [hostname] + user: [username] + password: [password] + port: [port] + dbname: [database name] + schema: [dbt schema] + threads: [1 or more] + keepalives_idle: 0 # default 0, indicating the system default. See below + connect_timeout: 10 # default 10 seconds + search_path: [optional, override the default postgres search_path] + role: [optional, set the role dbt assumes when executing queries] + sslmode: [optional, set the sslmode used to connect to the database] + +``` + + + +### Notes + +This adapter strongly depends on dbt-postgres, so you can read more about configurations here [Profile Setup](postgres-setup) diff --git a/website/docs/reference/warehouse-setups/hive-setup.md b/website/docs/reference/warehouse-setups/hive-setup.md new file mode 100644 index 00000000000..1c03533fc3c --- /dev/null +++ b/website/docs/reference/warehouse-setups/hive-setup.md @@ -0,0 +1,174 @@ +--- +title: "Apache Hive setup" +id: "hive-setup" +meta: + maintained_by: Cloudera + authors: 'Cloudera' + github_repo: 'cloudera/dbt-impala' + pypi_package: 'dbt-impala' + min_core_version: 'v1.1.0' + cloud_support: Not Supported + min_supported_version: 'n/a' + slack_channel_name: '#db-hive' + slack_channel_link: 'https://getdbt.slack.com/archives/C0401DTNSKW' + platform_name: 'Hive' + config_page: 'hive-configs' +--- + +

Overview of {frontMatter.meta.pypi_package}

+ +
    +
  • Maintained by: {frontMatter.meta.maintained_by}
  • +
  • Authors: {frontMatter.meta.authors}
  • +
  • GitHub repo: {frontMatter.meta.github_repo}
  • +
  • PyPI package: {frontMatter.meta.pypi_package}
  • +
  • Slack channel: {frontMatter.meta.slack_channel_name}
  • +
  • Supported dbt Core version: {frontMatter.meta.min_core_version} and newer
  • +
  • dbt Cloud support: {frontMatter.meta.cloud_support}
  • +
  • Minimum data platform version: {frontMatter.meta.min_supported_version}
  • +
+ + +

Installing {frontMatter.meta.pypi_package}

+ +pip is the easiest way to install the adapter: + +pip install {frontMatter.meta.pypi_package} + +

Installing {frontMatter.meta.pypi_package} will also install dbt-core and any other dependencies.

+ +

Configuring {frontMatter.meta.pypi_package}

+ +

For {frontMatter.meta.platform_name}-specifc configuration please refer to {frontMatter.meta.platform_name} Configuration

+ +

For further info, refer to the GitHub repository: {frontMatter.meta.github_repo}

+ + +## Connection Methods + +dbt-hive can connect to Apache Hive and Cloudera Data Platform clusters. The [Impyla](https://github.com/cloudera/impyla/) library is used to establish connections to Hive. + +dbt-hive supports two transport mechanisms: +- binary +- HTTP(S) + +The default mechanism is `binary`. To use HTTP transport, use the boolean option `use_http_transport: [true / false]`. + +## Authentication Methods + +dbt-hive supports two authentication mechanisms: +- [`insecure`](#Insecure) No authentication is used, only recommended for testing. +- [`ldap`](#ldap) Authentication via LDAP + +### Insecure + +This method is only recommended if you have a local install of Hive and want to test out the dbt-hive adapter. + + + +```yaml +your_profile_name: + target: dev + outputs: + dev: + type: hive + host: localhost + port: [port] # default value: 10000 + schema: [schema name] + +``` + + + +### LDAP + +LDAP allows you to authenticate with a username and password when Hive is [configured with LDAP Auth](https://cwiki.apache.org/confluence/display/Hive/Setting+Up+HiveServer2). LDAP is supported over Binary & HTTP connection mechanisms. + +This is the recommended authentication mechanism to use with Cloudera Data Platform (CDP). + + + +```yaml +your_profile_name: + target: dev + outputs: + dev: + type: hive + host: [host name] + http_path: [optional, http path to Hive] # default value: None + port: [port] # default value: 10000 + auth_type: ldap + use_http_transport: [true / false] # default value: true + use_ssl: [true / false] # TLS should always be used with LDAP to ensure secure transmission of credentials, default value: true + username: [username] + password: [password] + schema: [schema name] +``` + + + +Note: When creating workload user in CDP, make sure the user has CREATE, SELECT, ALTER, INSERT, UPDATE, DROP, INDEX, READ and WRITE permissions. If you need the user to execute GRANT statements, you should also configure the appropriate GRANT permissions for them. When using Apache Ranger, permissions for allowing GRANT are typically set using "Delegate Admin" option. For more information, see [`grants`](/reference/resource-configs/grants) and [on-run-start & on-run-end](/reference/project-configs/on-run-start-on-run-en). + +### Kerberos + +The Kerberos authentication mechanism uses GSSAPI to share Kerberos credentials when Hive is [configured with Kerberos Auth](https://ambari.apache.org/1.2.5/installing-hadoop-using-ambari/content/ambari-kerb-2-3-3.html). + + + +```yaml +your_profile_name: + target: dev + outputs: + dev: + type: hive + host: [hostname] + port: [port] # default value: 10000 + auth_type: [GSSAPI] + kerberos_service_name: [kerberos service name] # default value: None + use_http_transport: true # default value: true + use_ssl: true # TLS should always be used to ensure secure transmission of credentials, default value: true + schema: [schema name] + +``` + + + +Note: A typical setup of Cloudera Private Cloud will involve the following steps to setup Kerberos before one can execute dbt commands: +- Get the correct realm config file for your installation (krb5.conf) +- Set environment variable to point to the config file (export KRB5_CONFIG=/path/to/krb5.conf) +- Set correct permissions for config file (sudo chmod 644 /path/to/krb5.conf) +- Obtain keytab using kinit (kinit username@YOUR_REALM.YOUR_DOMAIN) +- The keytab is valid for certain period after which you will need to run kinit again to renew validity of the keytab. +- User will need CREATE, DROP, INSERT permissions on the schema provided in profiles.yml + +### Instrumentation +By default, the adapter will collect instrumentation events to help improve functionality and understand bugs. If you want to specifically switch this off, for instance, in a production environment, you can explicitly set the flag `usage_tracking: false` in your `profiles.yml` file. + +## Installation and Distribution + +dbt's adapter for Apache Hive is managed in its own repository, [dbt-hive](https://github.com/cloudera/dbt-hive). To use it, +you must install the `dbt-hive` plugin. + +### Using pip +The following commands will install the latest version of `dbt-hive` as well as the requisite version of `dbt-core` and `impyla` driver used for connections. + +``` +pip install dbt-hive +``` + +### Supported Functionality + +| Name | Supported | +|------|-----------| +|Materialization: Table|Yes| +|Materialization: View|Yes| +|Materialization: Incremental - Append|Yes| +|Materialization: Incremental - Insert+Overwrite|Yes| +|Materialization: Incremental - Merge|No| +|Materialization: Ephemeral|No| +|Seeds|Yes| +|Tests|Yes| +|Snapshots|No| +|Documentation|Yes| +|Authentication: LDAP|Yes| +|Authentication: Kerberos|Yes| diff --git a/website/docs/reference/warehouse-setups/ibmdb2-setup.md b/website/docs/reference/warehouse-setups/ibmdb2-setup.md new file mode 100644 index 00000000000..c601b1cb763 --- /dev/null +++ b/website/docs/reference/warehouse-setups/ibmdb2-setup.md @@ -0,0 +1,112 @@ +--- +title: "IBM DB2 setup" +id: "ibmdb2-setup" +meta: + maintained_by: Community + authors: 'Rasmus Nyberg (https://github.com/aurany)' + github_repo: 'aurany/dbt-ibmdb2' + pypi_package: 'dbt-ibmdb2' + min_core_version: 'v1.0.4' + cloud_support: Not Supported + min_supported_version: 'IBM DB2 V9fp2' + slack_channel_name: 'n/a' + slack_channel_link: 'https://www.getdbt.com/community' + platform_name: 'IBM DB2' + config_page: 'no-configs' +--- + +:::info Community plugin + +Some core functionality may be limited. If you're interested in contributing, check out the source code for each repository listed below. + +::: + +## Overview of dbt-ibmdb2 + +
    +
  • Maintained by: {frontMatter.meta.maintained_by}
  • +
  • Authors: {frontMatter.meta.authors}
  • +
  • GitHub repo: {frontMatter.meta.github_repo}
  • +
  • PyPI package: {frontMatter.meta.pypi_package}
  • +
  • Slack channel: {frontMatter.meta.slack_channel_name}
  • +
  • Supported dbt Core version: {frontMatter.meta.min_core_version} and newer
  • +
  • dbt Cloud support: {frontMatter.meta.cloud_support}
  • +
  • Minimum data platform version: {frontMatter.meta.min_supported_version}
  • +
+ + +

Installing {frontMatter.meta.pypi_package}

+ +pip is the easiest way to install the adapter: + +pip install {frontMatter.meta.pypi_package} + +

Installing {frontMatter.meta.pypi_package} will also install dbt-core and any other dependencies.

+ +

Configuring {frontMatter.meta.pypi_package}

+ +

For {frontMatter.meta.platform_name}-specifc configuration please refer to {frontMatter.meta.platform_name} Configuration

+ +

For further info, refer to the GitHub repository: {frontMatter.meta.github_repo}

+ + +This is an experimental plugin: +- We have not tested it extensively +- Tested with [dbt-adapter-tests](https://pypi.org/project/pytest-dbt-adapter/) and DB2 LUW on Mac OS+RHEL8 +- Compatibility with other [dbt packages](https://hub.getdbt.com/) (like [dbt_utils](https://hub.getdbt.com/dbt-labs/dbt_utils/latest/)) is only partially tested + +## Connecting to IBM DB2 with dbt-ibmdb2 + +IBM DB2 targets should be set up using the following configuration in your `profiles.yml` file. + +Example: + + + +```yaml +your_profile_name: + target: dev + outputs: + dev: + type: ibmdb2 + schema: analytics + database: test + host: localhost + port: 50000 + protocol: TCPIP + username: my_username + password: my_password +``` + + + +#### Description of IBM DB2 Profile Fields + +| Option | Description | Required? | Example | +| --------------- | ----------------------------------------------------------------------------------- | ------------------------------------------------------------------ | ---------------------------------------------- | +| type | The specific adapter to use | Required | `ibmdb2` | +| schema | Specify the schema (database) to build models into | Required | `analytics` | +| database | Specify the database you want to connect to | Required | `testdb` | +| host | Hostname or IP-adress | Required | `localhost` | +| port | The port to use | Optional | `50000` | +| protocol | Protocol to use | Optional | `TCPIP` | +| username | The username to use to connect to the server | Required | `my-username` | +| password | The password to use for authenticating to the server | Required | `my-password` | + + +## Supported features + +| DB2 LUW | DB2 z/OS | Feature | +|:---------:|:---:|---------------------| +| ✅ | 🤷 | Table materialization | +| ✅ | 🤷 | View materialization | +| ✅ | 🤷 | Incremental materialization | +| ✅ | 🤷 | Ephemeral materialization | +| ✅ | 🤷 | Seeds | +| ✅ | 🤷 | Sources | +| ✅ | 🤷 | Custom data tests | +| ✅ | 🤷 | Docs generate | +| ✅ | 🤷 | Snapshots | + +## Notes +- dbt-ibmdb2 is built on the ibm_db python package and there are some known encoding issues related to z/OS. diff --git a/website/docs/reference/warehouse-setups/impala-setup.md b/website/docs/reference/warehouse-setups/impala-setup.md new file mode 100644 index 00000000000..61a2c7188f5 --- /dev/null +++ b/website/docs/reference/warehouse-setups/impala-setup.md @@ -0,0 +1,164 @@ +--- +title: "Apache Impala setup" +id: "impala-setup" +meta: + maintained_by: Cloudera + authors: 'Cloudera' + github_repo: 'cloudera/dbt-impala' + pypi_package: 'dbt-impala' + min_core_version: 'v1.1.0' + cloud_support: Not Supported + min_supported_version: 'n/a' + slack_channel_name: '#db-impala' + slack_channel_link: 'https://getdbt.slack.com/archives/C01PWAH41A5' + platform_name: 'Impala' + config_page: 'impala-configs' +--- + +

Overview of {frontMatter.meta.pypi_package}

+ +
    +
  • Maintained by: {frontMatter.meta.maintained_by}
  • +
  • Authors: {frontMatter.meta.authors}
  • +
  • GitHub repo: {frontMatter.meta.github_repo}
  • +
  • PyPI package: {frontMatter.meta.pypi_package}
  • +
  • Slack channel: {frontMatter.meta.slack_channel_name}
  • +
  • Supported dbt Core version: {frontMatter.meta.min_core_version} and newer
  • +
  • dbt Cloud support: {frontMatter.meta.cloud_support}
  • +
  • Minimum data platform version: {frontMatter.meta.min_supported_version}
  • +
+ + +

Installing {frontMatter.meta.pypi_package}

+ +pip is the easiest way to install the adapter: + +pip install {frontMatter.meta.pypi_package} + +

Installing {frontMatter.meta.pypi_package} will also install dbt-core and any other dependencies.

+ +

Configuring {frontMatter.meta.pypi_package}

+ +

For {frontMatter.meta.platform_name}-specifc configuration please refer to {frontMatter.meta.platform_name} Configuration

+ +

For further info, refer to the GitHub repository: {frontMatter.meta.github_repo}

+ + +## Connection Methods + +dbt-impala can connect to Apache Impala and Cloudera Data Platform clusters. + +The [Impyla](https://github.com/cloudera/impyla/) library is used to establish connections to Impala. + +Two transport mechanisms are supported: +- binary +- HTTP(S) + +The default mechanism is `binary`. To use HTTP transport, use the boolean option `use_http_transport: [true / false]`. + +## Authentication Methods + +dbt-impala supports three authentication mechanisms: +- [`insecure`](#Insecure) No authentication is used, only recommended for testing. +- [`ldap`](#ldap) Authentication via LDAP +- [`kerbros`](#kerbros) Authentication via Kerberos (GSSAPI) + +### Insecure + +This method is only recommended if you have a local install of Impala and want to test out the dbt-impala adapter. + + + +```yaml +your_profile_name: + target: dev + outputs: + dev: + type: impala + host: localhost + port: 21050 + dbname: [db name] # this should be same as schema name provided below + schema: [schema name] + +``` + + + +### LDAP + +LDAP allows you to authenticate with a username & password when Impala is [configured with LDAP Auth](https://impala.apache.org/docs/build/html/topics/impala_ldap.html). LDAP is supported over Binary & HTTP connection mechanisms. + +This is the recommended authentication mechanism to use with Cloudera Data Platform (CDP). + + + +```yaml +your_profile_name: + target: dev + outputs: + dev: + type: impala + host: [host name] + http_path: [optional, http path to Impala] + port: [port] + auth_type: ldap + use_http_transport: [true / false] + use_ssl: [true / false] # TLS should always be used with LDAP to ensure secure transmission of credentials + username: [username] + password: [password] + dbname: [db name] # this should be same as schema name provided below, starting with 1.1.2 this parameter is optional + schema: [schema name] +``` + + + +Note: When creating workload user in CDP ensure that the user has CREATE, SELECT, ALTER, INSERT, UPDATE, DROP, INDEX, READ and WRITE permissions. If the user is required to execute GRANT statements, see for instance (https://docs.getdbt.com/reference/resource-configs/grants) or (https://docs.getdbt.com/reference/project-configs/on-run-start-on-run-end) appropriate GRANT permissions should be configured. When using Apache Ranger, permissions for allowing GRANT are typically set using "Delegate Admin" option. + +### Kerberos + +The Kerberos authentication mechanism uses GSSAPI to share Kerberos credentials when Impala is [configured with Kerberos Auth](https://impala.apache.org/docs/build/html/topics/impala_kerberos.html). + + + +```yaml +your_profile_name: + target: dev + outputs: + dev: + type: impala + host: [hostname] + port: [port] + auth_type: [GSSAPI] + kerberos_service_name: [kerberos service name] + use_http_transport: true + use_ssl: true # TLS should always be used with LDAP to ensure secure transmission of credentials + dbname: [db name] # this should be same as schema name provided below, starting with 1.1.2 this parameter is optional + schema: [schema name] + +``` + + + +Note: A typical setup of Cloudera EDH will involve the following steps to setup Kerberos before one can execute dbt commands: +- Get the correct realm config file for your installation (krb5.conf) +- Set environment variable to point to the config file (export KRB5_CONFIG=/path/to/krb5.conf) +- Set correct permissions for config file (sudo chmod 644 /path/to/krb5.conf) +- Obtain keytab using kinit (kinit username@YOUR_REALM.YOUR_DOMAIN) +- The keytab is valid for certain period after which you will need to run kinit again to renew validity of the keytab. + +### Supported Functionality + +| Name | Supported | +|------|-----------| +|Materialization: Table|Yes| +|Materialization: View|Yes| +|Materialization: Incremental - Append|Yes| +|Materialization: Incremental - Insert+Overwrite|Yes| +|Materialization: Incremental - Merge|No| +|Materialization: Ephemeral|No| +|Seeds|Yes| +|Tests|Yes| +|Snapshots|Yes| +|Documentation|Yes| +|Authentication: LDAP|Yes| +|Authentication: Kerberos|Yes| diff --git a/website/docs/reference/warehouse-setups/iomete-setup.md b/website/docs/reference/warehouse-setups/iomete-setup.md new file mode 100644 index 00000000000..bbc02a56683 --- /dev/null +++ b/website/docs/reference/warehouse-setups/iomete-setup.md @@ -0,0 +1,90 @@ +--- +title: "iomete setup" +id: "iomete-setup" +meta: + maintained_by: iomete + authors: 'Namig Aliyev' + github_repo: 'iomete/dbt-iomete' + pypi_package: 'dbt-iomete' + min_core_version: 'v0.18.0' + cloud_support: Not Supported + min_supported_version: 'n/a' + slack_channel_name: '##db-iomete' + slack_channel_link: 'https://getdbt.slack.com/archives/C03JFG22EP9' + platform_name: 'iomete' + config_page: 'no-configs' +--- + +

Overview of {frontMatter.meta.pypi_package}

+ +
    +
  • Maintained by: {frontMatter.meta.maintained_by}
  • +
  • Authors: {frontMatter.meta.authors}
  • +
  • GitHub repo: {frontMatter.meta.github_repo}
  • +
  • PyPI package: {frontMatter.meta.pypi_package}
  • +
  • Slack channel: {frontMatter.meta.slack_channel_name}
  • +
  • Supported dbt Core version: {frontMatter.meta.min_core_version} and newer
  • +
  • dbt Cloud support: {frontMatter.meta.cloud_support}
  • +
  • Minimum data platform version: {frontMatter.meta.min_supported_version}
  • +
+ +## Installation and Distribution + + +

Installing {frontMatter.meta.pypi_package}

+ +pip is the easiest way to install the adapter: + +pip install {frontMatter.meta.pypi_package} + +

Installing {frontMatter.meta.pypi_package} will also install dbt-core and any other dependencies.

+ +

Configuring {frontMatter.meta.pypi_package}

+ +

For {frontMatter.meta.platform_name}-specifc configuration please refer to {frontMatter.meta.platform_name} Configuration

+ +

For further info, refer to the GitHub repository: {frontMatter.meta.github_repo}

+ + +Set up a iomete Target + +iomete targets should be set up using the following configuration in your profiles.yml file. + + + +```yaml +iomete: + target: dev + outputs: + dev: + type: iomete + cluster: cluster_name + host: .iomete.com + port: 443 + schema: database_name + account_number: iomete_account_number + user: iomete_user_name + password: iomete_user_password +``` + + + +##### Description of Profile Fields + +| Field | Description | Required | Example | +|----------|-----------------------------------------------------------------------------------------------------------------------------------------|----------|------------------------| +| type | The specific adapter to use | Required | `iomete` | +| cluster | The cluster to connect | Required | `reporting` | +| host | The host name of the connection. It is a combination of
`account_number` with the prefix `dwh-`
and the suffix `.iomete.com`. | Required | `dwh-12345.iomete.com` | +| port | The port to use. | Required | `443` | +| schema | Specify the schema (database) to build models into. | Required | `dbt_finance` | +| account_number | The iomete account number with single quotes. | Required | `'1234566789123'` | +| username | The iomete username to use to connect to the server. | Required | `dbt_user` | +| password | The iomete user password to use to connect to the server. | Required | `strong_password` | + +## Supported Functionality + +Most dbt Core functionality is supported. + +Iceberg specific improvements. +1. Joining the results of `show tables` and `show views`. diff --git a/website/docs/reference/warehouse-setups/layer-setup.md b/website/docs/reference/warehouse-setups/layer-setup.md new file mode 100644 index 00000000000..f1a9b8b8940 --- /dev/null +++ b/website/docs/reference/warehouse-setups/layer-setup.md @@ -0,0 +1,165 @@ +--- +title: "Layer setup" +id: "layer-setup" +meta: + maintained_by: Layer + authors: 'Mehmet Ecevit' + github_repo: 'layerai/dbt-layer' + pypi_package: 'dbt-layer-bigquery' + min_core_version: 'v1.0.0' + cloud_support: Not Supported + min_supported_version: 'n/a' + slack_channel_name: '#tools-layer' + slack_channel_link: 'https://getdbt.slack.com/archives/C03STA39TFE' + platform_name: 'Layer' + config_page: 'no-configs' +--- + + +

Overview of {frontMatter.meta.pypi_package}

+ +
    +
  • Maintained by: {frontMatter.meta.maintained_by}
  • +
  • Authors: {frontMatter.meta.authors}
  • +
  • GitHub repo: {frontMatter.meta.github_repo}
  • +
  • PyPI package: {frontMatter.meta.pypi_package}
  • +
  • Slack channel: {frontMatter.meta.slack_channel_name}
  • +
  • Supported dbt Core version: {frontMatter.meta.min_core_version} and newer
  • +
  • dbt Cloud support: {frontMatter.meta.cloud_support}
  • +
  • Minimum data platform version: {frontMatter.meta.min_supported_version}
  • +
+ + + +

Installing {frontMatter.meta.pypi_package}

+ +pip is the easiest way to install the adapter: + +pip install {frontMatter.meta.pypi_package} + +

Installing {frontMatter.meta.pypi_package} will also install dbt-core and any other dependencies.

+ +

Configuring {frontMatter.meta.pypi_package}

+ +

For {frontMatter.meta.platform_name}-specifc configuration please refer to {frontMatter.meta.platform_name} Configuration

+ +

For further info, refer to the GitHub repository: {frontMatter.meta.github_repo}

+ +### Profile Configuration + +Layer Bigquery targets should be set up using the following sections in your `profiles.yml` file. +#### Layer Authentication +Add your `layer_api_key` to your `profiles.yaml` to authenticate with Layer. To get your Layer API Key: +- First, [create your free Layer account](https://app.layer.ai/login?returnTo=%2Fgetting-started). +- Go to [app.layer.ai](https://app.layer.ai) > **Settings** (Cog Icon by your profile photo) > **Developer** > **Create API key** to get your Layer API Key. + +#### Bigquery Authentication +You can use any [authentication method](https://docs.getdbt.com/reference/warehouse-profiles/bigquery-setup) supported in the official dbt Bigquery adapter since Layer uses `dbt-bigquery` adapter to connect to your Bigquery instance. + + +A sample profile: + + + +```yaml +layer-profile: + target: dev + outputs: + dev: + # Layer authentication + type: layer_bigquery + layer_api_key: [the API Key to access your Layer account (opt)] + # Bigquery authentication + method: service-account + project: [GCP project id] + dataset: [the name of your dbt dataset] + threads: [1 or more] + keyfile: [/path/to/bigquery/keyfile.json] +``` + + + +#### Description of Layer Bigquery Profile Fields + +The following fields are required: + +Parameter | Default | Type | Description +----------------------- | ----------- |--------------| --- +`type` | | string | Specifies the adapter you want to use. It should be `layer_bigquery`. +`layer_api_key` | | string (opt) | Specifies your Layer API key. If you want to make predictions with public ML models from Layer, you don't need to have this key in your profile. It's required if you load ML models from your Layer account or train an AutoML model. +`layer_project` | | string (opt) | Specifies your target Layer project. If you don't specify, Layer will use the project same name with your dbt project. +`method` | | string | Specifies the authentication type to connect to your BigQuery. + +Rest of the parameters depends on the BigQuery authentication method you specified. + +## Usage + +### AutoML + +You can automatically build state-of-art ML models using your own dbt models with plain SQL. To train an AutoML model all you have to do is pass your model type, input data (features) and target column you want to predict to `layer.automl()` in your SQL. The Layer AutoML will pick the best performing model and enable you to call it by its dbt model name to make predictions as shown above. + +_Syntax:_ +``` +layer.automl("MODEL_TYPE", ARRAY[FEATURES], TARGET) +``` + +_Parameters:_ + +| Syntax | Description | +| --------- |---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `MODEL_TYPE` | Type of the model your want to train. There are two options:
- `classifier`: A model to predict classes/labels or categories such as spam detection
- `regressor`: A model to predict continious outcomes such as CLV prediction. | +| `FEATURES` | Input column names as a list to train your AutoML model. | +| `TARGET` | Target column that you want to predict. | + + +_Requirements:_ +- You need to put `layer_api_key` to your dbt profile to make AutoML work. + +_Example:_ + +Check out [Order Review AutoML Project](https://github.com/layerai/dbt-layer/tree/mecevit/update-docs/examples/order_review_prediction): + +```sql +SELECT order_id, + layer.automl( + -- This is a regression problem + 'regressor', + -- Data (input features) to train our model + ARRAY[ + days_between_purchase_and_delivery, order_approved_late, + actual_delivery_vs_expectation_bucket, total_order_price, total_order_freight, is_multiItems_order,seller_shipped_late], + -- Target column we want to predict + review_score + ) +FROM {{ ref('training_data') }} +``` + +### Prediction + +You can make predictions using any Layer ML model within your dbt models. Layer dbt Adapter helps you score your data resides on your warehouse within your dbt DAG with SQL. + +_Syntax:_ +``` +layer.predict("LAYER_MODEL_PATH", ARRAY[FEATURES]) +``` + +_Parameters:_ + +| Syntax | Description | +| --------- |----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `LAYER_MODEL_PATH` | This is the Layer model path in form of `/[organization_name]/[project_name]/models/[model_name]`. You can use only the model name if you want to use an AutoML model within the same dbt project. | +| `FEATURES` | These are the columns that this model requires to make a prediction. You should pass the columns as a list like `ARRAY[column1, column2, column3]`. | + +_Example:_ + +Check out [Cloth Detection Project](https://github.com/layerai/dbt-layer/tree/mecevit/update-docs/examples/cloth_detector): + +```sql +SELECT + id, + layer.predict("layer/clothing/models/objectdetection", ARRAY[image]) +FROM + {{ ref("products") }} +``` + + diff --git a/website/docs/reference/warehouse-setups/materialize-setup.md b/website/docs/reference/warehouse-setups/materialize-setup.md new file mode 100644 index 00000000000..821d8477059 --- /dev/null +++ b/website/docs/reference/warehouse-setups/materialize-setup.md @@ -0,0 +1,109 @@ +--- +title: "Materialize setup" +id: "materialize-setup" +meta: + maintained_by: Materialize Inc. + authors: 'Materialize team' + github_repo: 'MaterializeInc/materialize/blob/main/misc/dbt-materialize' + min_core_version: 'v0.18.0' + cloud_support: Not Supported + min_supported_version: 'n/a' + slack_channel_name: '#db-materialize' + slack_channel_link: 'https://getdbt.slack.com/archives/C01PWAH41A5' + platform_name: 'Materialize' + config_page: 'no-configs' +--- + +:::info Vendor-supported plugin + +Certain core functionality may vary. If you would like to report a bug, request a feature, or contribute, you can check out the linked repository and open an issue. + +::: + +

Overview of {frontMatter.meta.pypi_package}

+ +
    +
  • Maintained by: {frontMatter.meta.maintained_by}
  • +
  • Authors: {frontMatter.meta.authors}
  • +
  • GitHub repo: {frontMatter.meta.github_repo}
  • +
  • PyPI package: {frontMatter.meta.pypi_package}
  • +
  • Slack channel: {frontMatter.meta.slack_channel_name}
  • +
  • Supported dbt Core version: {frontMatter.meta.min_core_version} and newer
  • +
  • dbt Cloud support: {frontMatter.meta.cloud_support}
  • +
  • Minimum data platform version: {frontMatter.meta.min_supported_version}
  • +
+ +

Installing {frontMatter.meta.pypi_package}

+ +pip is the easiest way to install the adapter: + +pip install {frontMatter.meta.pypi_package} + +

Installing {frontMatter.meta.pypi_package} will also install dbt-core and any other dependencies.

+ +

Configuring {frontMatter.meta.pypi_package}

+ +

For {frontMatter.meta.platform_name}-specifc configuration please refer to {frontMatter.meta.platform_name} Configuration

+ +

For further info, refer to the GitHub repository: {frontMatter.meta.github_repo}

+ +## Connecting to Materialize + +Once you have Materialize [installed and running](https://materialize.com/docs/install/), adapt your `profiles.yml` to connect to your instance using the following reference profile configuration: + + + +```yaml +dbt-materialize: + target: dev + outputs: + dev: + type: materialize + threads: 1 + host: [host] + port: [port] + user: [user] + pass: [password] + dbname: [database] + schema: [name of your dbt schema] +``` + + + +To test the connection to Materialize, run: + +``` +dbt debug +``` + +If the output reads "All checks passed!", you’re good to go! Check the [dbt and Materialize guide](https://materialize.com/docs/guides/dbt/) to learn more and get started. + +## Supported Features + +### Materializations + +Because Materialize is optimized for transformations on streaming data and the core of dbt is built around batch, the `dbt-materialize` adapter implements a few custom materialization types: + +Type | Supported? | Details +-----|------------|---------------- +`source` | YES | Creates a [source](https://materialize.com/docs/sql/create-source/). +`view` | YES | Creates a [view](https://materialize.com/docs/sql/create-view/#main). +`materializedview` | YES | Creates a [materialized view](https://materialize.com/docs/sql/create-materialized-view/#main). +`table` | YES | Creates a [materialized view](https://materialize.com/docs/sql/create-materialized-view/#main). (Actual table support pending [#5266](https://github.com/MaterializeInc/materialize/issues/5266)) +`index` | YES | (Deprecated) Creates an index. Use the [`indexes` config](materialize-configs#indexes) to create indexes on `materializedview`, `view` or `source` relations instead. +`sink` | YES | Creates a [sink](https://materialize.com/docs/sql/create-sink/#main). +`ephemeral` | YES | Executes queries using CTEs. +`incremental` | NO | Use the `materializedview` instead. Materialized views will always return up-to-date results without manual or configured refreshes. For more information, check out [Materialize documentation](https://materialize.com/docs/). + +### Seeds + +Running [`dbt seed`](commands/seed) will create a static materialized from a CSV file. You will not be able to add to or update this view after it has been created. If you want to rerun `dbt seed`, you must first drop existing views manually with `drop view`. + +### Tests + +Running [`dbt test`](commands/test) with the optional `--store-failures` flag or [`store_failures` config](resource-configs/store_failures) will create a materialized view for each test you've chosen to store. This view is a continuously updating representation of failures. + +## Resources + +- [dbt and Materialize guide](https://materialize.com/docs/guides/dbt/) +- [Get started](https://github.com/MaterializeInc/demos/tree/main/dbt-get-started) using dbt and Materialize together diff --git a/website/docs/reference/warehouse-setups/mindsdb-setup.md b/website/docs/reference/warehouse-setups/mindsdb-setup.md new file mode 100644 index 00000000000..9c5a691aa80 --- /dev/null +++ b/website/docs/reference/warehouse-setups/mindsdb-setup.md @@ -0,0 +1,80 @@ +--- +title: "MindsDB setup" +id: "mindsdb-setup" +meta: + maintained_by: MindsDB + authors: 'MindsDB team' + github_repo: 'mindsdb/dbt-mindsdb' + pypi_package: 'dbt-mindsdb' + min_core_version: 'v1.0.1' + cloud_support: Not Supported + min_supported_version: '?' + slack_channel_name: 'n/a' + slack_channel_link: 'https://www.getdbt.com/community' + platform_name: 'MindsDB' + config_page: 'mindsdb-configs' +--- + +:::info Vendor-supported plugin + +The dbt-mindsdb package allows dbt to connect to [MindsDB](https://github.com/mindsdb/mindsdb). + +

Overview of {frontMatter.meta.pypi_package}

+ +
    +
  • Maintained by: {frontMatter.meta.maintained_by}
  • +
  • Authors: {frontMatter.meta.authors}
  • +
  • GitHub repo: {frontMatter.meta.github_repo}
  • +
  • PyPI package: {frontMatter.meta.pypi_package}
  • +
  • Slack channel: {frontMatter.meta.slack_channel_name}
  • +
  • Supported dbt Core version: {frontMatter.meta.min_core_version} and newer
  • +
  • dbt Cloud support: {frontMatter.meta.cloud_support}
  • +
  • Minimum data platform version: {frontMatter.meta.min_supported_version}
  • +
+ +## Installation + + +

Installing {frontMatter.meta.pypi_package}

+ +pip is the easiest way to install the adapter: + +pip install {frontMatter.meta.pypi_package} + +

Installing {frontMatter.meta.pypi_package} will also install dbt-core and any other dependencies.

+ +

Configuring {frontMatter.meta.pypi_package}

+ +

For {frontMatter.meta.platform_name}-specifc configuration please refer to {frontMatter.meta.platform_name} Configuration

+ +

For further info, refer to the GitHub repository: {frontMatter.meta.github_repo}

+s + +## Configurations + +Basic `profile.yml` for connecting to MindsDB: + +```yml +mindsdb: + outputs: + dev: + database: 'mindsdb' + host: '127.0.0.1' + password: '' + port: 47335 + schema: 'mindsdb' + type: mindsdb + username: 'mindsdb' + target: dev + +``` +| Key | Required | Description | Example | +| -------- | -------- | ---------------------------------------------------- | ------------------------------ | +| type | ✔️ | The specific adapter to use | `mindsdb` | +| host | ✔️ | The MindsDB (hostname) to connect to | `cloud.mindsdb.com` | +| port | ✔️ | The port to use | `3306` or `47335` | +| schema | ✔️ | Specify the schema (database) to build models into | The MindsDB datasource | +| username | ✔️ | The username to use to connect to the server | `mindsdb` or mindsdb cloud user| +| password | ✔️ | The password to use for authenticating to the server | `pass | + + diff --git a/website/docs/reference/warehouse-setups/mssql-setup.md b/website/docs/reference/warehouse-setups/mssql-setup.md new file mode 100644 index 00000000000..6d786d9349b --- /dev/null +++ b/website/docs/reference/warehouse-setups/mssql-setup.md @@ -0,0 +1,459 @@ +--- +title: "Microsoft SQL Server setup" +id: "mssql-setup" +meta: + maintained_by: Community + authors: 'dbt-msft community (https://github.com/dbt-msft)' + github_repo: 'dbt-msft/dbt-sqlserver' + pypi_package: 'dbt-sqlserver' + min_core_version: 'v0.14.0' + cloud_support: Not Supported + min_supported_version: 'SQL Server 2016' + slack_channel_name: '#db-sqlserver' + slack_channel_link: 'https://getdbt.slack.com/archives/CMRMDDQ9W' + platform_name: 'SQL Server' + config_page: 'mssql-configs' +--- + +:::info Community plugin + +Some core functionality may be limited. If you're interested in contributing, check out the source code for each repository listed below. + +::: + +

Overview of {frontMatter.meta.pypi_package}

+ +
    +
  • Maintained by: {frontMatter.meta.maintained_by}
  • +
  • Authors: {frontMatter.meta.authors}
  • +
  • GitHub repo: {frontMatter.meta.github_repo}
  • +
  • PyPI package: {frontMatter.meta.pypi_package}
  • +
  • Slack channel: {frontMatter.meta.slack_channel_name}
  • +
  • Supported dbt Core version: {frontMatter.meta.min_core_version} and newer
  • +
  • dbt Cloud support: {frontMatter.meta.cloud_support}
  • +
  • Minimum data platform version: {frontMatter.meta.min_supported_version}
  • +
+ + +

Installing {frontMatter.meta.pypi_package}

+ +pip is the easiest way to install the adapter: + +pip install {frontMatter.meta.pypi_package} + +

Installing {frontMatter.meta.pypi_package} will also install dbt-core and any other dependencies.

+ +

Configuring {frontMatter.meta.pypi_package}

+ +

For {frontMatter.meta.platform_name}-specifc configuration please refer to {frontMatter.meta.platform_name} Configuration

+ +

For further info, refer to the GitHub repository: {frontMatter.meta.github_repo}

+ + +:::tip Default settings change in dbt-sqlserver v1.2 / ODBC Driver 18 +Microsoft made several changes related to connection encryption. Read more about the changes [below](#connection-encryption). +::: + +### Prerequisites + +On Debian/Ubuntu make sure you have the ODBC header files before installing + +```bash +sudo apt install unixodbc-dev +``` + +Download and install the [Microsoft ODBC Driver 18 for SQL Server](https://docs.microsoft.com/en-us/sql/connect/odbc/download-odbc-driver-for-sql-server?view=sql-server-ver15). +If you already have ODBC Driver 17 installed, then that one will work as well. + +The adapter is tested with SQL Server 2017, SQL Server 2019, SQL Server 2022 and Azure SQL Database. These versions are tested with Microsoft ODBC Driver 17 and Microsoft ODBC Driver 18. + +## Authentication methods & profile configuration + +### Common configuration + +For all the authentication methods below, the following configuration options can be set in your `profiles.yml` file: + +* `driver`: The ODBC driver to use. E.g. `ODBC Driver 18 for SQL Server` +* `server`: The server hostname. E.g. `localhost` +* `port`: The server port. E.g. `1433` +* `database`: The database name. +* `schema`: The schema name. E.g. `dbo` +* `retries`: The number of automatic times to retry a query before failing. Defaults to `1`. Note that queries with syntax errors will not be retried. This setting can be used to overcome intermittent network issues. +* `encrypt`: Whether to encrypt the connection to the server. Defaults to `true`. Read more about encryption [below](#connection-encryption). +* `trust_cert`: Whether to trust the server certificate. Defaults to `false`. Read more about encryption [below](#connection-encryption). + +### Connection encryption + +Microsoft made several changes in the release of ODBC Driver 18 that affects how connection encryption is configured. +To accommodate these changes, starting in dbt-sqlserver 1.2.0 or newer the default vallues of `encrypt` and `trust_cert` have changed. +Both of these settings will now **always** be included in the connection string to the server, regardless if you've left them out of your profile configuration or not. + +* The default value of `encrypt` is `true`, meaning that connections are encrypted by default. +* The default value of `trust_cert` is `false`, meaning that the server certificate will be validated. By setting this to `true`, a self-signed certificate will be accepted. + +More details about how these values affect your connection and how they are used differently in versions of the ODBC driver can be found in the [Microsoft documentation](https://learn.microsoft.com/en-us/sql/connect/odbc/dsn-connection-string-attribute?view=sql-server-ver16#encrypt). + +### Standard SQL Server authentication + +SQL Server credentials are supported for on-premise servers as well as Azure, +and it is the default authentication method for `dbt-sqlserver`. + +When running on Windows, you can also use your Windows credentials to authenticate. + + + + + + + +```yaml +your_profile_name: + target: dev + outputs: + dev: + type: sqlserver + driver: 'ODBC Driver 18 for SQL Server' # (The ODBC Driver installed on your system) + server: hostname or IP of your server + port: 1433 + database: database + schema: schema_name + user: username + password: password +``` + + + + + + + + + + +```yaml +your_profile_name: + target: dev + outputs: + dev: + type: sqlserver + driver: 'ODBC Driver 18 for SQL Server' # (The ODBC Driver installed on your system) + server: hostname or IP of your server + port: 1433 + database: exampledb + schema: schema_name + windows_login: True +``` + + + + + + + +### Azure Active Directory Authentication (AAD) + +While you can use the SQL username and password authentication as mentioned above, +you might opt to use one of the authentication methods below for Azure SQL. + +The following additional methods are available to authenticate to Azure SQL products: + +* AAD username and password +* Service principal (a.k.a. AAD Application) +* Managed Identity +* Environment-based authentication +* Azure CLI authentication +* VS Code authentication (available through the automatic option below) +* Azure PowerShell module authentication (available through the automatic option below) +* Automatic authentication + +The automatic authentication setting is in most cases the easiest choice and works for all of the above. + + + + + + + +```yaml +your_profile_name: + target: dev + outputs: + dev: + type: sqlserver + driver: 'ODBC Driver 18 for SQL Server' # (The ODBC Driver installed on your system) + server: hostname or IP of your server + port: 1433 + database: exampledb + schema: schema_name + authentication: ActiveDirectoryPassword + user: bill.gates@microsoft.com + password: iheartopensource +``` + + + + + + + +Client ID is often also referred to as Application ID. + + + +```yaml +your_profile_name: + target: dev + outputs: + dev: + type: sqlserver + driver: 'ODBC Driver 18 for SQL Server' # (The ODBC Driver installed on your system) + server: hostname or IP of your server + port: 1433 + database: exampledb + schema: schema_name + authentication: ServicePrincipal + tenant_id: 00000000-0000-0000-0000-000000001234 + client_id: 00000000-0000-0000-0000-000000001234 + client_secret: S3cret! +``` + + + + + + + +Both system-assigned and user-assigned managed identities will work. + + + +```yaml +your_profile_name: + target: dev + outputs: + dev: + type: sqlserver + driver: 'ODBC Driver 18 for SQL Server' # (The ODBC Driver installed on your system) + server: hostname or IP of your server + port: 1433 + database: exampledb + schema: schema_name + authentication: MSI +``` + + + + + + + +This authentication option allows you to dynamically select an authentication method depending on the available environment variables. + +[The Microsoft docs on EnvironmentCredential](https://docs.microsoft.com/en-us/python/api/azure-identity/azure.identity.environmentcredential?view=azure-python) +explain the available combinations of environment variables you can use. + + + +```yaml +your_profile_name: + target: dev + outputs: + dev: + type: sqlserver + driver: 'ODBC Driver 18 for SQL Server' # (The ODBC Driver installed on your system) + server: hostname or IP of your server + port: 1433 + database: exampledb + schema: schema_name + authentication: environment +``` + + + + + + + +First, install the [Azure CLI](https://docs.microsoft.com/en-us/cli/azure/install-azure-cli), then, log in: + +`az login` + + + +```yaml +your_profile_name: + target: dev + outputs: + dev: + type: sqlserver + driver: 'ODBC Driver 18 for SQL Server' # (The ODBC Driver installed on your system) + server: hostname or IP of your server + port: 1433 + database: exampledb + schema: schema_name + authentication: CLI +``` + + + + + + + +This authentication option will automatically try to use all available authentication methods. + +The following methods are tried in order: + +1. Environment-based authentication +2. Managed Identity authentication +3. Visual Studio authentication (*Windows only, ignored on other operating systems*) +4. Visual Studio Code authentication +5. Azure CLI authentication +6. Azure PowerShell module authentication + + + +```yaml +your_profile_name: + target: dev + outputs: + dev: + type: sqlserver + driver: 'ODBC Driver 18 for SQL Server' # (The ODBC Driver installed on your system) + server: hostname or IP of your server + port: 1433 + database: exampledb + schema: schema_name + authentication: auto +``` + + + + + + + +#### Additional options for AAD on Windows + +On Windows systems, the following additional authentication methods are also available for Azure SQL: + +* AAD interactive +* AAD integrated +* Visual Studio authentication (available through the automatic option above) + + + + + +This setting can optionally show Multi-Factor Authentication prompts. + + + +```yaml +your_profile_name: + target: dev + outputs: + dev: + type: sqlserver + driver: 'ODBC Driver 18 for SQL Server' # (The ODBC Driver installed on your system) + server: hostname or IP of your server + port: 1433 + database: exampledb + schema: schema_name + authentication: ActiveDirectoryInteractive + user: bill.gates@microsoft.com +``` + + + + + + + +This uses the credentials you're logged in with on the current machine. + + + +```yaml +your_profile_name: + target: dev + outputs: + dev: + type: sqlserver + driver: 'ODBC Driver 18 for SQL Server' # (The ODBC Driver installed on your system) + server: hostname or IP of your server + port: 1433 + database: exampledb + schema: schema_name + authentication: ActiveDirectoryIntegrated +``` + + + + + + + +### Automatic AAD principal provisioning for grants + +In dbt 1.2 or newer you can use the [grants](https://docs.getdbt.com/reference/resource-configs/grants) config block to automatically grant/revoke permissions on your models to users or groups. This is fully supported in this adapter and comes with an additional feature. + +By setting `auto_provision_aad_principals` to `true` in your model configuration, you can automatically provision Azure Active Directory (AAD) principals (users or groups) that don't exist yet. + +In Azure SQL, you can sign in using AAD authentication, but to be able to grant an AAD principal certain permissions, it needs to be linked in the database first. ([Microsoft documentation](https://learn.microsoft.com/en-us/azure/azure-sql/database/authentication-aad-configure?view=azuresql)) + +Note that principals will not be deleted automatically when they are removed from the `grants` block. + +### Reference of all connection options + +| configuration option | description | required | default value | +|----------------------|-------------------------------------------------------------------------------------------------------------------------------------------------|--------------------|---------------| +| `driver` | The ODBC driver to use. | :white_check_mark: | | +| `host` | The hostname of the database server. | :white_check_mark: | | +| `port` | The port of the database server. | | `1433` | +| `database` | The name of the database to connect to. | :white_check_mark: | | +| `schema` | The schema to use. | :white_check_mark: | | +| `authentication` | The authentication method to use. This is not required for Windows authentication. | | `'sql'` | | | | +| `UID` | Username used to authenticate. This can be left out depending on the authentication method. | | | +| `PWD` | Password used to authenticate. This can be left out depending on the authentication method. | | | +| `windows_login` | Set this to `true` to use Windows authentication. This is only available for SQL Server. | | | +| `tenant_id` | The tenant ID of the Azure Active Directory instance. This is only used when connecting to Azure SQL with a service principal. | | | +| `client_id` | The client ID of the Azure Active Directory service principal. This is only used when connecting to Azure SQL with an AAD service principal. | | | +| `client_secret` | The client secret of the Azure Active Directory service principal. This is only used when connecting to Azure SQL with an AAD service principal. | | | +| `encrypt` | Set this to `false` to disable the use of encryption. See [above](#connection-encryption). | | `true` | +| `trust_cert` | Set this to `true` to trust the server certificate. See [above](#connection-encryption). | | `false` | +| `retries` | The number of times to retry a failed connection. | | `1` | + +Valid values for `authentication`: + +* `sql`: SQL authentication using username and password +* `ActiveDirectoryPassword`: Active Directory authentication using username and password +* `ActiveDirectoryInteractive`: Active Directory authentication using a username and MFA prompts +* `ActiveDirectoryIntegrated`: Active Directory authentication using the current user's credentials +* `ServicePrincipal`: Azure Active Directory authentication using a service principal +* `CLI`: Azure Active Directory authentication using the account you're logged in with in the Azure CLI +* `MSI`: Azure Active Directory authentication using a managed identity available on the system +* `environment`: Azure Active Directory authentication using environment variables as documented [here](https://learn.microsoft.com/en-us/python/api/azure-identity/azure.identity.environmentcredential?view=azure-python) +* `auto`: Azure Active Directory authentication trying the previous authentication methods until it finds one that works diff --git a/website/docs/reference/warehouse-setups/mysql-setup.md b/website/docs/reference/warehouse-setups/mysql-setup.md new file mode 100644 index 00000000000..c91e48c30ec --- /dev/null +++ b/website/docs/reference/warehouse-setups/mysql-setup.md @@ -0,0 +1,122 @@ +--- +title: "MySQL setup" +id: "mysql-setup" +meta: + maintained_by: Community + authors: 'Doug Beatty (https://github.com/dbeatty10)' + github_repo: 'dbeatty10/dbt-mysql' + pypi_package: 'dbt-mysql' + min_core_version: 'v0.18.0' + cloud_support: Not Supported + min_supported_version: 'MySQL 5.7 and 8.0' + slack_channel_name: '#db-mysql-family' + slack_channel_link: 'https://getdbt.slack.com/archives/C03BK0SHC64' + platform_name: 'MySQL' + config_page: 'no-configs' +--- + +:::info Community plugin + +Some core functionality may be limited. If you're interested in contributing, check out the source code for each repository listed below. + +::: + +

Overview of {frontMatter.meta.pypi_package}

+ +
    +
  • Maintained by: {frontMatter.meta.maintained_by}
  • +
  • Authors: {frontMatter.meta.authors}
  • +
  • GitHub repo: {frontMatter.meta.github_repo}
  • +
  • PyPI package: {frontMatter.meta.pypi_package}
  • +
  • Slack channel: {frontMatter.meta.slack_channel_name}
  • +
  • Supported dbt Core version: {frontMatter.meta.min_core_version} and newer
  • +
  • dbt Cloud support: {frontMatter.meta.cloud_support}
  • +
  • Minimum data platform version: {frontMatter.meta.min_supported_version}
  • +
+ +

Installing {frontMatter.meta.pypi_package}

+ +pip is the easiest way to install the adapter: + +pip install {frontMatter.meta.pypi_package} + +

Installing {frontMatter.meta.pypi_package} will also install dbt-core and any other dependencies.

+ +

Configuring {frontMatter.meta.pypi_package}

+ +

For {frontMatter.meta.platform_name}-specifc configuration please refer to {frontMatter.meta.platform_name} Configuration

+ +

For further info, refer to the GitHub repository: {frontMatter.meta.github_repo}

+ +This is an experimental plugin: +- It has not been tested extensively. +- Storage engines other than the default of InnoDB are untested. +- Only tested with [dbt-adapter-tests](https://github.com/dbt-labs/dbt-adapter-tests) with the following versions: + - MySQL 5.7 + - MySQL 8.0 + - MariaDB 10.5 +- Compatibility with other [dbt packages](https://hub.getdbt.com/) (like [dbt_utils](https://hub.getdbt.com/dbt-labs/dbt_utils/latest/)) are also untested. + +Please read these docs carefully and use at your own risk. [Issues](https://github.com/dbeatty10/dbt-mysql/issues/new) and [PRs](https://github.com/dbeatty10/dbt-mysql/blob/main/CONTRIBUTING.rst#contributing) welcome! + + +## Connecting to MySQL with dbt-mysql + +MySQL targets should be set up using the following configuration in your `profiles.yml` file. + +Example: + + + +```yaml +your_profile_name: + target: dev + outputs: + dev: + type: mysql + server: localhost + port: 3306 + schema: analytics + username: your_mysql_username + password: your_mysql_password + ssl_disabled: True +``` + + + +#### Description of MySQL Profile Fields + +| Option | Description | Required? | Example | +| --------------- | ----------------------------------------------------------------------------------- | ------------------------------------------------------------------ | ---------------------------------------------- | +| type | The specific adapter to use | Required | `mysql`, `mysql5` or `mariadb` | +| server | The server (hostname) to connect to | Required | `yourorg.mysqlhost.com` | +| port | The port to use | Optional | `3306` | +| schema | Specify the schema (database) to build models into | Required | `analytics` | +| username | The username to use to connect to the server | Required | `dbt_admin` | +| password | The password to use for authenticating to the server | Required | `correct-horse-battery-staple` | +| ssl_disabled | Set to enable or disable TLS connectivity to mysql5.x | Optional | `True` or `False` | + +## Supported features + +| MariaDB 10.5 | MySQL 5.7 | MySQL 8.0 | Feature | +|:---------:|:---------:|:---:|-----------------------------| +| ✅ | ✅ | ✅ | Table materialization | +| ✅ | ✅ | ✅ | View materialization | +| ✅ | ✅ | ✅ | Incremental materialization | +| ✅ | ❌ | ✅ | Ephemeral materialization | +| ✅ | ✅ | ✅ | Seeds | +| ✅ | ✅ | ✅ | Sources | +| ✅ | ✅ | ✅ | Custom data tests | +| ✅ | ✅ | ✅ | Docs generate | +| 🤷 | 🤷 | ✅ | Snapshots | + +## Notes +- Ephemeral materializations rely upon [Common Table Expressions](https://en.wikipedia.org/wiki/Hierarchical_and_recursive_queries_in_SQL) (CTEs), which are not supported until MySQL 8.0. +- MySQL 5.7 has some configuration gotchas that might affect dbt snapshots to not work properly due to [automatic initialization and updating for `TIMESTAMP`](https://dev.mysql.com/doc/refman/5.7/en/timestamp-initialization.html). + - If the output of `SHOW VARIABLES LIKE 'sql_mode'` includes `NO_ZERO_DATE`. A solution is to include the following in a `*.cnf` file: + ``` + [mysqld] + explicit_defaults_for_timestamp = true + sql_mode = "ALLOW_INVALID_DATES,{other_sql_modes}" + ``` + - Where `{other_sql_modes}` is the rest of the modes from the `SHOW VARIABLES LIKE 'sql_mode'` output. diff --git a/website/docs/reference/warehouse-setups/oracle-setup.md b/website/docs/reference/warehouse-setups/oracle-setup.md new file mode 100644 index 00000000000..dfd9ad07207 --- /dev/null +++ b/website/docs/reference/warehouse-setups/oracle-setup.md @@ -0,0 +1,498 @@ +--- +title: "Oracle setup" +id: "oracle-setup" +meta: + maintained_by: Oracle + authors: 'Oracle' + github_repo: 'oracle/dbt-oracle' + pypi_package: 'dbt-oracle' + min_core_version: 'v1.2.1' + cloud_support: Not Supported + min_supported_version: 'SQlite Version 3.0' + slack_channel_name: '#db-oracle' + slack_channel_link: 'https://getdbt.slack.com/archives/C01PWH4TXLY' + platform_name: 'Oracle' + config_page: 'no-configs' +--- + +

Overview of {frontMatter.meta.pypi_package}

+ +
    +
  • Maintained by: {frontMatter.meta.maintained_by}
  • +
  • Authors: {frontMatter.meta.authors}
  • +
  • GitHub repo: {frontMatter.meta.github_repo}
  • +
  • PyPI package: {frontMatter.meta.pypi_package}
  • +
  • Slack channel: {frontMatter.meta.slack_channel_name}
  • +
  • Supported dbt Core version: {frontMatter.meta.min_core_version} and newer
  • +
  • dbt Cloud support: {frontMatter.meta.cloud_support}
  • +
  • Minimum data platform version: {frontMatter.meta.min_supported_version}
  • +
+ +## Installation + + +

Installing {frontMatter.meta.pypi_package}

+ +pip is the easiest way to install the adapter: + +pip install {frontMatter.meta.pypi_package} + +

Installing {frontMatter.meta.pypi_package} will also install dbt-core and any other dependencies.

+ +

Configuring {frontMatter.meta.pypi_package}

+ +

For {frontMatter.meta.platform_name}-specifc configuration please refer to {frontMatter.meta.platform_name} Configuration

+ +

For further info, refer to the GitHub repository: {frontMatter.meta.github_repo}

+ + +### Configure the Python driver mode + +:::info +[python-oracledb](https://oracle.github.io/python-oracledb/) is the renamed, major release of Oracle's popular cx_Oracle interface +::: + +[python-oracledb](https://oracle.github.io/python-oracledb/) makes it optional to install the Oracle Client libraries. +This driver supports 2 modes + +1. **Thin mode (preferred) ** : Python process directly connects to the Oracle database. This mode does not need the Oracle Client libraries +2. **Thick mode** : Python process links with the Oracle Client libraries. Some advanced Oracle database functionalities (for e.g. Advanced Queuing and Scrollable cursors) are currently available via Oracle Client libraries + +It is highly recommended to use the **thin** mode as it vastly simplifies installation. You can configure the driver mode using the environment variable `ORA_PYTHON_DRIVER_TYPE` + +| Driver Mode | Oracle Client libraries required? | Configuration | +|------------------------|-----------------------------------| ------------- | +| Thin | No | `ORA_PYTHON_DRIVER_TYPE=thin`| +| Thick | Yes | `ORA_PYTHON_DRIVER_TYPE=thick` | +| cx_oracle (old driver) | Yes | `ORA_PYTHON_DRIVER_TYPE=cx` | + +The default value of `ORA_PYTHON_DRIVER_TYPE` is `cx`. This might change in the future as more users migrate towards the new python driver. + + + + + + ```bash + export ORA_PYTHON_DRIVER_TYPE=thin + ``` + + + + + + ```bash + export ORA_PYTHON_DRIVER_TYPE=thick + # or + export ORA_PYTHON_DRIVER_TYPE=cx # default + ``` + +### Install Oracle Instant Client libraries + +In thick mode or the old cx_oracle mode, you will need the [Oracle Instant Client libraries](https://www.oracle.com/database/technologies/instant-client.html) installed. These provide the necessary network connectivity allowing dbt-oracle to access an Oracle Database instance. + +Oracle client libraries versions 21, 19, 18, 12, and 11.2 are supported where available on Linux, Windows and macOS (Intel x86). It is recommended to use the latest client possible: Oracle’s standard client-server version interoperability allows connection to both older and newer databases. + + + + + +1. Download an Oracle 21, 19, 18, 12, or 11.2 “Basic” or “Basic Light” zip file matching your Python 64-bit or 32-bit architecture: + 1. [x86-64 64-bit](https://www.oracle.com/database/technologies/instant-client/linux-x86-64-downloads.html) + 2. [x86 32-bit](https://www.oracle.com/database/technologies/instant-client/linux-x86-32-downloads.html) + 3. [ARM (aarch64) 64-bit](https://www.oracle.com/database/technologies/instant-client/linux-arm-aarch64-downloads.html) + +2. Unzip the package into a single directory that is accessible to your application. For example: + ```bash + mkdir -p /opt/oracle + cd /opt/oracle + unzip instantclient-basic-linux.x64-21.1.0.0.0.zip + ``` + +3. Install the libaio package with sudo or as the root user. For example: + ```bash + sudo yum install libaio + ``` + On some Linux distributions this package is called `libaio1` instead. + + + +4. if there is no other Oracle software on the machine that will be impacted, permanently add Instant Client to the runtime link path. For example, with sudo or as the root user: + + ```bash + sudo sh -c "echo /opt/oracle/instantclient_21_1 > /etc/ld.so.conf.d/oracle-instantclient.conf" + sudo ldconfig + ``` + + Alternatively, set the environment variable `LD_LIBRARY_PATH` + + ```bash + export LD_LIBRARY_PATH=/opt/oracle/instantclient_21_1:$LD_LIBRARY_PATH + ``` + + + + + +1. Download an Oracle 21, 19, 18, 12, or 11.2 “Basic” or “Basic Light” zip file: [64-bit](https://www.oracle.com/database/technologies/instant-client/winx64-64-downloads.html) or [32-bit](https://www.oracle.com/database/technologies/instant-client/microsoft-windows-32-downloads.html), matching your Python architecture. + +:::info Windows 7 users +Note that Oracle Client versions 21c and 19c are not supported on Windows 7. +::: + +2. Unzip the package into a directory that is accessible to your application. For example unzip `instantclient-basic-windows.x64-19.11.0.0.0dbru.zip` to `C:\oracle\instantclient_19_11`. + +3. Oracle Instant Client libraries require a Visual Studio redistributable with a 64-bit or 32-bit architecture to match Instant Client’s architecture. + 1. For Instant Client 21 install [VS 2019](https://docs.microsoft.com/en-US/cpp/windows/latest-supported-vc-redist?view=msvc-170) or later + 2. For Instant Client 19 install [VS 2017](https://docs.microsoft.com/en-US/cpp/windows/latest-supported-vc-redist?view=msvc-170) + 3. For Instant Client 18 or 12.2 install [VS 2013](https://docs.microsoft.com/en-US/cpp/windows/latest-supported-vc-redist?view=msvc-170#visual-studio-2013-vc-120) + 4. For Instant Client 12.1 install [VS 2010](https://docs.microsoft.com/en-US/cpp/windows/latest-supported-vc-redist?view=msvc-170#visual-studio-2010-vc-100-sp1-no-longer-supported) + 5. For Instant Client 11.2 install [VS 2005 64-bit](https://docs.microsoft.com/en-US/cpp/windows/latest-supported-vc-redist?view=msvc-170#visual-studio-2005-vc-80-sp1-no-longer-supported) + +4. Add the Oracle Instant Client directory to the `PATH` environment variable.The directory must occur in `PATH` before any other Oracle directories. Restart any open command prompt windows. + + ```bash + SET PATH=C:\oracle\instantclient_19_9;%PATH% + ``` + + + + + +1. Download the instant client DMG package + + ```bash + cd $HOME/Downloads + curl -O https://download.oracle.com/otn_software/mac/instantclient/198000/instantclient-basic-macos.x64-19.8.0.0.0dbru.dmg + ``` + +2. Mount the instant client DMG package + + ```bash + hdiutil mount instantclient-basic-macos.x64-19.8.0.0.0dbru.dmg + + ``` + +3. Run the install script in the mounted package + + ```bash + /Volumes/instantclient-basic-macos.x64-19.8.0.0.0dbru/install_ic.sh + ``` + +4. Unmount the package + + ```bash + hdiutil unmount /Volumes/instantclient-basic-macos.x64-19.8.0.0.0dbru + ``` + +5. The Instant Client directory will be `$HOME/Downloads/instantclient_19_8`. You could move it to some place convenient. + +6. Add links to `~/lib` or `/usr/local/lib` to enable dbt to find the libraries. + + ```bash + mkdir ~/lib + ln -s ~/instantclient_19_8/libclntsh.dylib ~/lib/ + ``` + + + + + + + + +## Configure wallet for Oracle Autonomous Database in Cloud + +dbt can connect to Oracle Autonomous Database (ADB) in Oracle Cloud using either TLS (Transport Layer Security) or mutual TLS (mTLS). TLS and mTLS provide enhanced security for authentication and encryption. +A database username and password is still required for dbt connections which can be configured as explained in the next section [Connecting to Oracle Database](#connecting-to-oracle-database). + + + + + +With TLS, dbt can connect to Oracle ADB without using a wallet. Both Thin and Thick modes of the python-oracledb driver support TLS. + +:::info +In Thick mode, dbt can connect through TLS only when using Oracle Client library versions 19.14 (or later) or 21.5 (or later). +::: + +Refer to Oracle documentation to [connect to an ADB instance using TLS authentication](https://docs.oracle.com/en/cloud/paas/autonomous-database/adbsa/connecting-nodejs-tls.html#GUID-B3809B88-D2FB-4E08-8F9B-65A550F93A07) and the blog post [Easy wallet-less connections to Oracle Autonomous Databases in Python](https://blogs.oracle.com/opal/post/easy-way-to-connect-python-applications-to-oracle-autonomous-databases) to enable TLS for your Oracle ADB instance. + + + + +For mutual TLS connections, a wallet needs be downloaded from the OCI console and the python driver needs to be configured to use it. + +#### Install the Wallet and Network Configuration Files + +From the Oracle Cloud console for the database, download the wallet zip file using the `DB Connection` button. The zip contains the wallet and network configuration files. + +:::warning Note +Keep wallet files in a secure location and share them only with authorized users. +::: + +Unzip the wallet zip file. + + + + +In Thin mode, only two files from the zip are needed: + +- `tnsnames.ora` - Maps net service names used for application connection strings to your database services + +- `ewallet.pem` - Enables SSL/TLS connections in Thin mode. Keep this file secure + +After unzipping the files in a secure directory, set the **TNS_ADMIN** and **WALLET_LOCATION** environment variables to the directory name. + +```bash +export WALLET_LOCATION=/path/to/directory_containing_ewallet.pem +export WALLET_PASSWORD=*** +export TNS_ADMIN=/path/to/directory_containing_tnsnames.ora +``` +Optionally, if `ewallet.pem` file is encrypted using a wallet password, specify the password using environment variable **WALLET_PASSWORD** + + + + +In Thick mode, the following files from the zip are needed: + +- `tnsnames.ora` - Maps net service names used for application connection strings to your database services +- `sqlnet.ora` - Configures Oracle Network settings +- `cwallet.sso` - Enables SSL/TLS connections + +After unzipping the files in a secure directory, set the **TNS_ADMIN** environment variable to that directory name. + +```bash +export TNS_ADMIN=/path/to/directory_containing_tnsnames.ora +``` + +Next, edit the `sqlnet.ora` file to point to the wallet directory. + + + +```text +WALLET_LOCATION = (SOURCE = (METHOD = file) (METHOD_DATA = (DIRECTORY="/path/to/wallet/directory"))) +SSL_SERVER_DN_MATCH=yes +``` + + + + + + + + + + +## Connecting to Oracle Database + +Define the following mandatory parameters as environment variables and refer them in the connection profile using [env_var](https://docs.getdbt.com/reference/dbt-jinja-functions/env_var) jinja function. Optionally, you can also define these directly in the `profiles.yml` file, but this is not recommended + +```bash +export DBT_ORACLE_USER= +export DBT_ORACLE_PASSWORD=*** +export DBT_ORACLE_SCHEMA= +``` + +Starting with `dbt-oracle==1.0.2`, it is **optional** to set the database name + +```bash +export DBT_ORACLE_DATABASE=example_db2022adb +``` + +If database name is not set, adapter will retrieve it using the following query. + +```sql +SELECT SYS_CONTEXT('userenv', 'DB_NAME') FROM DUAL +``` + +An Oracle connection profile for dbt can be set using any one of the following methods + + + + + +The `tnsnames.ora` file is a configuration file that contains network service names mapped to connect descriptors. +The directory location of `tnsnames.ora` file can be specified using `TNS_ADMIN` environment variable + + + +```text +db2022adb_high = (description = + (retry_count=20)(retry_delay=3) + (address=(protocol=tcps) + (port=1522) + (host=adb.example.oraclecloud.com)) + (connect_data=(service_name=example_high.adb.oraclecloud.com)) + (security=(ssl_server_cert_dn="CN=adb.example.oraclecloud.com, + OU=Oracle BMCS US,O=Oracle Corporation,L=Redwood City,ST=California,C=US"))) +``` + + + +The TNS alias `db2022adb_high` can be defined as environment variable and referred in `profiles.yml` + +```bash +export DBT_ORACLE_TNS_NAME=db2022adb_high +``` + + + +```yaml +dbt_test: + target: dev + outputs: + dev: + type: oracle + user: "{{ env_var('DBT_ORACLE_USER') }}" + pass: "{{ env_var('DBT_ORACLE_PASSWORD') }}" + database: "{{ env_var('DBT_ORACLE_DATABASE') }}" + tns_name: "{{ env_var('DBT_ORACLE_TNS_NAME') }}" + schema: "{{ env_var('DBT_ORACLE_SCHEMA') }}" + threads: 4 +``` + + + + + +The connection string identifies which database service to connect to. It can be one of the following + +- An [Oracle Easy Connect String](https://docs.oracle.com/en/database/oracle/oracle-database/21/netag/configuring-naming-methods.html#GUID-B0437826-43C1-49EC-A94D-B650B6A4A6EE) +- An Oracle Net Connect Descriptor String +- A Net Service Name mapping to a connect descriptor + +```bash +export DBT_ORACLE_CONNECT_STRING="(description=(retry_count=20)(retry_delay=3)(address=(protocol=tcps)(port=1522) + (host=adb.example.oraclecloud.com))(connect_data=(service_name=example_high.adb.oraclecloud.com)) + (security=(ssl_server_cert_dn=\"CN=adb.example.oraclecloud.com, + OU=Oracle BMCS US,O=Oracle Corporation,L=Redwood City,ST=California,C=US\")))" +``` + + + +```yaml +dbt_test: + target: "{{ env_var('DBT_TARGET', 'dev') }}" + outputs: + dev: + type: oracle + user: "{{ env_var('DBT_ORACLE_USER') }}" + pass: "{{ env_var('DBT_ORACLE_PASSWORD') }}" + database: "{{ env_var('DBT_ORACLE_DATABASE') }}" + schema: "{{ env_var('DBT_ORACLE_SCHEMA') }}" + connection_string: "{{ env_var('DBT_ORACLE_CONNECT_STRING') }}" +``` + + + + + + +To connect using the database hostname or IP address, you need to specify the following +- host +- port (1521 or 1522) +- protocol (tcp or tcps) +- service + +```bash +export DBT_ORACLE_HOST=adb.example.oraclecloud.com +export DBT_ORACLE_SERVICE=example_high.adb.oraclecloud.com +``` + + + + +```yaml +dbt_test: + target: "{{ env_var('DBT_TARGET', 'dev') }}" + outputs: + dev: + type: oracle + user: "{{ env_var('DBT_ORACLE_USER') }}" + pass: "{{ env_var('DBT_ORACLE_PASSWORD') }}" + protocol: "tcps" + host: "{{ env_var('DBT_ORACLE_HOST') }}" + port: 1522 + service: "{{ env_var('DBT_ORACLE_SERVICE') }}" + database: "{{ env_var('DBT_ORACLE_DATABASE') }}" + schema: "{{ env_var('DBT_ORACLE_SCHEMA') }}" + retry_count: 1 + retry_delay: 3 + threads: 4 +``` + + + + + + +```yaml +dbt_test: + target: "{{ env_var('DBT_TARGET', 'dev') }}" + outputs: + dev: + type: oracle + user: "{{ env_var('DBT_ORACLE_USER') }}" + pass: "{{ env_var('DBT_ORACLE_PASSWORD') }}" + protocol: "tcps" + host: "{{ env_var('DBT_ORACLE_HOST') }}" + port: 1522 + service: "{{ env_var('DBT_ORACLE_SERVICE') }}" + database: "{{ env_var('DBT_ORACLE_DATABASE') }}" + schema: "{{ env_var('DBT_ORACLE_SCHEMA') }}" + threads: 4 +``` + + + + + + + + +## Supported Features + +- Table materialization +- View materialization +- Incremental materialization +- Seeds +- Data sources +- Singular tests +- Generic tests; Not null, Unique, Accepted values and Relationships +- Operations +- Analyses +- Exposures +- Document generation +- Serve project documentation as a website +- All dbt commands are supported + +## Not Supported features +- Ephemeral materialization + diff --git a/website/docs/reference/warehouse-setups/postgres-setup.md b/website/docs/reference/warehouse-setups/postgres-setup.md new file mode 100644 index 00000000000..bbfcdb6e572 --- /dev/null +++ b/website/docs/reference/warehouse-setups/postgres-setup.md @@ -0,0 +1,106 @@ +--- +title: "Postgres setup" +id: "postgres-setup" +meta: + maintained_by: dbt Labs + authors: 'core dbt maintainers' + github_repo: 'dbt-labs/dbt-postgres' + pypi_package: 'dbt-postgres' + min_core_version: 'v0.4.0' + cloud_support: Supported + min_supported_version: 'n/a' + slack_channel_name: '#db-postgres' + slack_channel_link: 'https://getdbt.slack.com/archives/C0172G2E273' + platform_name: 'Postgres' + config_page: 'postgres-configs' +--- + +

Overview of {frontMatter.meta.pypi_package}

+ +
    +
  • Maintained by: {frontMatter.meta.maintained_by}
  • +
  • Authors: {frontMatter.meta.authors}
  • +
  • GitHub repo: {frontMatter.meta.github_repo}
  • +
  • PyPI package: {frontMatter.meta.pypi_package}
  • +
  • Slack channel: {frontMatter.meta.slack_channel_name}
  • +
  • Supported dbt Core version: {frontMatter.meta.min_core_version} and newer
  • +
  • dbt Cloud support: {frontMatter.meta.cloud_support}
  • +
  • Minimum data platform version: {frontMatter.meta.min_supported_version}
  • +
+ + +

Installing {frontMatter.meta.pypi_package}

+ +pip is the easiest way to install the adapter: + +pip install {frontMatter.meta.pypi_package} + +

Installing {frontMatter.meta.pypi_package} will also install dbt-core and any other dependencies.

+ +

Configuring {frontMatter.meta.pypi_package}

+ +

For {frontMatter.meta.platform_name}-specifc configuration please refer to {frontMatter.meta.platform_name} Configuration

+ +

For further info, refer to the GitHub repository: {frontMatter.meta.github_repo}

+ + +## Profile Configuration + +Postgres targets should be set up using the following configuration in your `profiles.yml` file. + + + +```yaml +company-name: + target: dev + outputs: + dev: + type: postgres + host: [hostname] + user: [username] + password: [password] + port: [port] + dbname: [database name] + schema: [dbt schema] + threads: [1 or more] + [keepalives_idle](#keepalives_idle): 0 # default 0, indicating the system default. See below + connect_timeout: 10 # default 10 seconds + [retries](#retries): 1 # default 1 retry on error/timeout when opening connections + [search_path](#search_path): [optional, override the default postgres search_path] + [role](#role): [optional, set the role dbt assumes when executing queries] + [sslmode](#sslmode): [optional, set the sslmode used to connect to the database] + +``` + + + +### Configurations + +#### search_path + +The `search_path` config controls the Postgres "search path" that dbt configures when opening new connections to the database. By default, the Postgres search path is `"$user, public"`, meaning that unqualified names will be searched for in the `public` schema, or a schema with the same name as the logged-in user. **Note:** Setting the `search_path` to a custom value is not necessary or recommended for typical usage of dbt. + +#### role + + Added in v0.16.0 + +The `role` config controls the Postgres role that dbt assumes when opening new connections to the database. + +#### sslmode + + Added in v0.16.0 + +The `sslmode` config controls how dbt connectes to Postgres databases using SSL. See [the Postgres docs](https://www.postgresql.org/docs/9.1/libpq-ssl.html) on `sslmode` for usage information. When unset, dbt will connect to databases using the Postgres default, `prefer`, as the `sslmode`. + +### `keepalives_idle` +If the database closes its connection while dbt is waiting for data, you may see the error `SSL SYSCALL error: EOF detected`. Lowering the [`keepalives_idle` value](https://www.postgresql.org/docs/9.3/libpq-connect.html) may prevent this, because the server will send a ping to keep the connection active more frequently. + +[dbt's default setting](https://github.com/dbt-labs/dbt-core/blob/main/plugins/postgres/dbt/adapters/postgres/connections.py#L28) is 0 (the server's default value), but can be configured lower (perhaps 120 or 60 seconds), at the cost of a chattier network connection. + + + +#### retries + +If `dbt-postgres` encounters an operational error or timeout when opening a new connection, it will retry up to the number of times configured by `retries`. The default value is 1 retry. If set to 2+ retries, dbt will wait 1 second before retrying. If set to 0, dbt will not retry at all. + + diff --git a/website/docs/reference/warehouse-setups/redshift-setup.md b/website/docs/reference/warehouse-setups/redshift-setup.md new file mode 100644 index 00000000000..28276594ba8 --- /dev/null +++ b/website/docs/reference/warehouse-setups/redshift-setup.md @@ -0,0 +1,145 @@ +--- +title: "Redshift setup" +id: "redshift-setup" +meta: + maintained_by: dbt Labs + authors: 'core dbt maintainers' + github_repo: 'dbt-labs/dbt-redshift' + pypi_package: 'dbt-redshift' + min_core_version: 'v0.10.0' + cloud_support: Supported + min_supported_version: 'n/a' + slack_channel_name: '#db-redshift' + slack_channel_link: 'https://getdbt.slack.com/archives/C01DRQ178LQ' + platform_name: 'Redshift' + config_page: 'redshift-configs' +--- + +

Overview of {frontMatter.meta.pypi_package}

+ +
    +
  • Maintained by: {frontMatter.meta.maintained_by}
  • +
  • Authors: {frontMatter.meta.authors}
  • +
  • GitHub repo: {frontMatter.meta.github_repo}
  • +
  • PyPI package: {frontMatter.meta.pypi_package}
  • +
  • Slack channel: {frontMatter.meta.slack_channel_name}
  • +
  • Supported dbt Core version: {frontMatter.meta.min_core_version} and newer
  • +
  • dbt Cloud support: {frontMatter.meta.cloud_support}
  • +
  • Minimum data platform version: {frontMatter.meta.min_supported_version}
  • +
+ + +

Installing {frontMatter.meta.pypi_package}

+ +pip is the easiest way to install the adapter: + +pip install {frontMatter.meta.pypi_package} + +

Installing {frontMatter.meta.pypi_package} will also install dbt-core and any other dependencies.

+ +

Configuring {frontMatter.meta.pypi_package}

+ +

For {frontMatter.meta.platform_name}-specifc configuration please refer to {frontMatter.meta.platform_name} Configuration

+ +

For further info, refer to the GitHub repository: {frontMatter.meta.github_repo}

+ + +## Authentication Methods + +### Password-based authentication + + + +```yaml +company-name: + target: dev + outputs: + dev: + type: redshift + host: hostname.region.redshift.amazonaws.com + user: username + password: password1 + port: 5439 + dbname: analytics + schema: analytics + threads: 4 + keepalives_idle: 240 # default 240 seconds + connect_timeout: 10 # default 10 seconds + # search_path: public # optional, not recommended + sslmode: [optional, set the sslmode used to connect to the database (in case this parameter is set, will look for ca in ~/.postgresql/root.crt)] + ra3_node: true # enables cross-database sources +``` + + + +### IAM Authentication + +To set up a Redshift profile using IAM Authentication, set the `method` +parameter to `iam` as shown below. Note that a password is not required when +using IAM Authentication. For more information on this type of authentication, +consult the [Redshift Documentation](https://docs.aws.amazon.com/redshift/latest/mgmt/generating-user-credentials.html) +and [boto3 +docs](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/redshift.html#Redshift.Client.get_cluster_credentials) +on generating user credentials with IAM Auth. + +If you receive the "You must specify a region" error when using IAM +Authentication, then your aws credentials are likely misconfigured. Try running +`aws configure` to set up AWS access keys, and pick a default region. If you have any questions, +please refer to the official AWS documentation on [Configuration and credential file settings](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-files.html). + + + +```yaml +my-redshift-db: + target: dev + outputs: + dev: + type: redshift + method: iam + cluster_id: CLUSTER_ID + host: hostname.region.redshift.amazonaws.com + user: alice + iam_profile: data_engineer # optional + iam_duration_seconds: 900 # optional + autocreate: true # optional + db_groups: ['ANALYSTS'] # optional + + # Other Redshift configs: + port: 5439 + dbname: analytics + schema: analytics + threads: 4 + [keepalives_idle](#keepalives_idle): 240 # default 240 seconds + connect_timeout: 10 # default 10 seconds + [retries](#retries): 1 # default 1 retry on error/timeout when opening connections + # search_path: public # optional, but not recommended + sslmode: [optional, set the sslmode used to connect to the database (in case this parameter is set, will look for ca in ~/.postgresql/root.crt)] + ra3_node: true # enables cross-database sources + +``` + + + +### Specifying an IAM Profile + +:::info New in dbt v0.18.0 +The `iam_profile` config option for Redshift profiles is new in dbt v0.18.0 +::: + +When the `iam_profile` configuration is set, dbt will use the specified profile from your `~/.aws/config` file instead of using the profile name `default` +## Redshift notes +### `sort` and `dist` keys +Where possible, dbt enables the use of `sort` and `dist` keys. See the section on [Redshift specific configurations](redshift-configs). + +### `keepalives_idle` +If the database closes its connection while dbt is waiting for data, you may see the error `SSL SYSCALL error: EOF detected`. Lowering the [`keepalives_idle` value](https://www.postgresql.org/docs/9.3/libpq-connect.html) may prevent this, because the server will send a ping to keep the connection active more frequently. + +[dbt's default setting](https://github.com/dbt-labs/dbt-redshift/blob/main/dbt/adapters/redshift/connections.py#L51) is 240 (seconds), but can be configured lower (perhaps 120 or 60), at the cost of a chattier network connection. + + + +#### retries + +If `dbt-redshift` encounters an operational error or timeout when opening a new connection, it will retry up to the number of times configured by `retries`. If set to 2+ retries, dbt will wait 1 second before retrying. The default value is 1 retry. If set to 0, dbt will not retry at all. + + diff --git a/website/docs/reference/warehouse-setups/rockset-setup.md b/website/docs/reference/warehouse-setups/rockset-setup.md new file mode 100644 index 00000000000..c80b28a5f68 --- /dev/null +++ b/website/docs/reference/warehouse-setups/rockset-setup.md @@ -0,0 +1,83 @@ +--- +title: "Rockset setup" +id: "rockset-setup" +meta: + maintained_by: Rockset, Inc. + authors: 'Rockset, Inc.' + github_repo: 'rockset/dbt-rockset' + pypi_package: 'dbt-rockset' + min_core_version: 'v0.19.2' + cloud_support: Not Supported + min_supported_version: '?' + slack_channel_name: '#dbt-rockset' + slack_channel_link: 'https://getdbt.slack.com/archives/C02J7AZUAMN' + platform_name: 'Rockset' + config_page: 'no-configs' +--- + +:::info Vendor-supported plugin + +Certain core functionality may vary. If you would like to report a bug, request a feature, or contribute, you can check out the linked repository and open an issue. + +::: + +

Overview of {frontMatter.meta.pypi_package}

+ +
    +
  • Maintained by: {frontMatter.meta.maintained_by}
  • +
  • Authors: {frontMatter.meta.authors}
  • +
  • GitHub repo: {frontMatter.meta.github_repo}
  • +
  • PyPI package: {frontMatter.meta.pypi_package}
  • +
  • Slack channel: {frontMatter.meta.slack_channel_name}
  • +
  • Supported dbt Core version: {frontMatter.meta.min_core_version} and newer
  • +
  • dbt Cloud support: {frontMatter.meta.cloud_support}
  • +
  • Minimum data platform version: {frontMatter.meta.min_supported_version}
  • +
+ + +

Installing {frontMatter.meta.pypi_package}

+ +pip is the easiest way to install the adapter: + +pip install {frontMatter.meta.pypi_package} + +

Installing {frontMatter.meta.pypi_package} will also install dbt-core and any other dependencies.

+ +

Configuring {frontMatter.meta.pypi_package}

+ +

For {frontMatter.meta.platform_name}-specifc configuration please refer to {frontMatter.meta.platform_name} Configuration

+ +

For further info, refer to the GitHub repository: {frontMatter.meta.github_repo}

+ +## Connecting to Rockset with **dbt-rockset** + +The dbt profile for Rockset is very simple and contains the following fields: + + + +```yaml +rockset: + target: dev + outputs: + dev: + type: rockset + workspace: [schema] + api_key: [api_key] + api_server: [api_server] # (Default is api.rs2.usw2.rockset.com) +``` + + + +### Materializations + +Type | Supported? | Details +-----|------------|---------------- +view | YES | Creates a [view](https://rockset.com/docs/views/#gatsby-focus-wrapper). +table | YES | Creates a [collection](https://rockset.com/docs/collections/#gatsby-focus-wrapper). +ephemeral | YES | Executes queries using CTEs. +incremental | YES | Creates a [collection](https://rockset.com/docs/collections/#gatsby-focus-wrapper) if it doesn't exist, and then writes results to it. + +## Caveats +1. `unique_key` is not supported with incremental, unless it is set to [_id](https://rockset.com/docs/special-fields/#the-_id-field), which acts as a natural `unique_key` in Rockset anyway. +2. The `table` is slower in Rockset than most due to Rockset's architecture as a low-latency, real-time database. Creating new collections requires provisioning hot storage to index and serve fresh data, which takes about a minute. +3. Rockset queries have a two-minute timeout. Any model which runs a query that takes longer to execute than two minutes will fail. diff --git a/website/docs/reference/warehouse-setups/singlestore-setup.md b/website/docs/reference/warehouse-setups/singlestore-setup.md new file mode 100644 index 00000000000..d0b88c1f0ac --- /dev/null +++ b/website/docs/reference/warehouse-setups/singlestore-setup.md @@ -0,0 +1,108 @@ +--- +title: "SingleStore setup" +id: "singlestore-setup" +meta: + maintained_by: SingleStore, Inc. + authors: 'SingleStore, Inc.' + github_repo: 'memsql/dbt-singlestore' + pypi_package: 'dbt-singlestore' + min_core_version: 'v1.0.0' + cloud_support: Supported + min_supported_version: 'v7.5' + slack_channel_name: 'db-singlestore' + slack_channel_link: 'https://getdbt.slack.com/archives/C02V2QHFF7U' + platform_name: 'SingleStore' + config_page: 'no-configs' +--- + +:::info Vendor-supported plugin + +Certain core functionality may vary. If you would like to report a bug, request a feature, or contribute, you can check out the linked repository and open an issue. + +::: + +

Overview of {frontMatter.meta.pypi_package}

+ +
    +
  • Maintained by: {frontMatter.meta.maintained_by}
  • +
  • Authors: {frontMatter.meta.authors}
  • +
  • GitHub repo: {frontMatter.meta.github_repo}
  • +
  • PyPI package: {frontMatter.meta.pypi_package}
  • +
  • Slack channel: {frontMatter.meta.slack_channel_name}
  • +
  • Supported dbt Core version: {frontMatter.meta.min_core_version} and newer
  • +
  • dbt Cloud support: {frontMatter.meta.cloud_support}
  • +
  • Minimum data platform version: {frontMatter.meta.min_supported_version}
  • +
+ +## Installation and Distribution + + +

Installing {frontMatter.meta.pypi_package}

+ +pip is the easiest way to install the adapter: + +pip install {frontMatter.meta.pypi_package} + +

Installing {frontMatter.meta.pypi_package} will also install dbt-core and any other dependencies.

+ +

Configuring {frontMatter.meta.pypi_package}

+ +

For {frontMatter.meta.platform_name}-specifc configuration please refer to {frontMatter.meta.platform_name} Configuration

+ +

For further info, refer to the GitHub repository: {frontMatter.meta.github_repo}

+ + +### Set up a SingleStore Target + +SingleStore targets should be set up using the following configuration in your `profiles.yml` file. If you are using SingleStore Managed Service, required connection details can be found on your Cluster Page under "Connect" -> "SQL IDE" tab. + + + +```yaml +singlestore: + target: dev + outputs: + dev: + type: singlestore + host: [hostname] # optional, default localhost + port: [port number] # optional, default 3306 + user: [user] # optional, default root + password: [password] # optional, default empty + database: [database name] # required + schema: [prefix for tables that dbt will generate] # required + threads: [1 or more] # optional, default 1 +``` + + +It is recommended to set optional parameters as well. + +### Description of SingleStore Profile Fields + +| Field | Required | Description | +|--------------------------|----------|--------------------------------------------------------------------------------------------------------| +| `type` | Yes | Must be set to `singlestore`. This must be included either in `profiles.yml` or in the `dbt_project.yml` file. | +| `host` | No | The host name of the SingleStore server to connect to. | +| `user` | No | Your SingleStore database username. | +| `password` | No | Your SingleStore database password. | +| `database` | Yes | The name of your database. If you are using custom database names in your models config, they must be created prior to running those models. | +| `schema` | Yes | The string to prefix the names of generated tables if `generate_alias_name` macro is added (see below). If you are using a custom schema name in your model config, it will be concatenated with the one specified in profile using `_`. | +| `threads` | No | The number of threads available to dbt. | + +## Schema and Concurrent Development + +SingleStore doesn't have a concept of `schema` that corresponds to one used in `dbt` (namespace within a database). `schema` in your profile is required for `dbt` to work correctly with your project metadata. For example, you will see it on "dbt docs" page, even though it's not present in the database. + +In order to support concurrent development, `schema` can be used to prefix names that `dbt` is building within your database. In order to enable this, add the following macro to your project. This macro will take the `schema` field of your `profiles.yml` file and use it as a table name prefix. + +```sql +-- macros/generate_alias_name.sql +{% macro generate_alias_name(custom_alias_name=none, node=none) -%} + {%- if custom_alias_name is none -%} + {{ node.schema }}__{{ node.name }} + {%- else -%} + {{ node.schema }}__{{ custom_alias_name | trim }} + {%- endif -%} +{%- endmacro %} +``` + +Therefore, if you set `schema=dev` in your `.dbt/profiles.yml` file and run the `customers` model with the corresponding profile, `dbt` will create a table named `dev__customers` in your database. diff --git a/website/docs/reference/warehouse-profiles/snowflake-profile.md b/website/docs/reference/warehouse-setups/snowflake-setup.md similarity index 58% rename from website/docs/reference/warehouse-profiles/snowflake-profile.md rename to website/docs/reference/warehouse-setups/snowflake-setup.md index 896e411a54d..6486f1e1752 100644 --- a/website/docs/reference/warehouse-profiles/snowflake-profile.md +++ b/website/docs/reference/warehouse-setups/snowflake-setup.md @@ -1,13 +1,47 @@ --- -title: "Snowflake Profile" +title: "Snowflake setup" +id: "snowflake-setup" +meta: + maintained_by: dbt Labs + authors: 'core dbt maintainers' + github_repo: 'dbt-labs/dbt-snowflake' + pypi_package: 'dbt-snowflake' + min_core_version: 'v0.8.0' + cloud_support: Supported + min_supported_version: 'n/a' + slack_channel_name: '#db-snowflake' + slack_channel_link: 'https://getdbt.slack.com/archives/C01DRQ178LQ' + platform_name: 'Snowflake' + config_page: 'snowflake-configs' --- -## Overview of dbt-snowflake -**Maintained by:** core dbt maintainers -**Author:** dbt Labs -**Source:** [Github](https://github.com/dbt-labs/dbt-snowflake) -**dbt Cloud:** Supported -**dbt Slack channel** [Link to channel](https://getdbt.slack.com/archives/CJN7XRF1B) +

Overview of {frontMatter.meta.pypi_package}

+ +
    +
  • Maintained by: {frontMatter.meta.maintained_by}
  • +
  • Authors: {frontMatter.meta.authors}
  • +
  • GitHub repo: {frontMatter.meta.github_repo}
  • +
  • PyPI package: {frontMatter.meta.pypi_package}
  • +
  • Slack channel: {frontMatter.meta.slack_channel_name}
  • +
  • Supported dbt Core version: {frontMatter.meta.min_core_version} and newer
  • +
  • dbt Cloud support: {frontMatter.meta.cloud_support}
  • +
  • Minimum data platform version: {frontMatter.meta.min_supported_version}
  • +
+ + +

Installing {frontMatter.meta.pypi_package}

+ +pip is the easiest way to install the adapter: + +pip install {frontMatter.meta.pypi_package} + +

Installing {frontMatter.meta.pypi_package} will also install dbt-core and any other dependencies.

+ +

Configuring {frontMatter.meta.pypi_package}

+ +

For {frontMatter.meta.platform_name}-specifc configuration please refer to {frontMatter.meta.platform_name} Configuration

+ +

For further info, refer to the GitHub repository: {frontMatter.meta.github_repo}

## Authentication Methods @@ -47,6 +81,40 @@ my-snowflake-db: +### User / Password + DUO MFA authentication + +Snowflake integrates the DUO Mobile app to add 2-Factor authentication to basic user/password as seen below. + +```yaml +my-snowflake-db: + target: dev + outputs: + dev: + type: snowflake + account: [account id] + + # User/password auth + user: [username] + password: [password] + authenticator: username_password_mfa + + role: [user role] + database: [database name] + warehouse: [warehouse name] + schema: [dbt schema] + threads: [1 or more] + client_session_keep_alive: False + query_tag: [anything] + + # optional + connect_retries: 0 # default 0 + connect_timeout: 10 # default: 10 + retry_on_database_errors: False # default: false + retry_all: False # default: false +``` + +Along with adding the `authenticator` parameter, be sure to run `alter account set allow_client_mfa_caching = true;` in your Snowflake warehouse. Together, these will allow you to easily verify authenatication with the DUO Mobile app (skipping this results in push notifications for every model built on every `dbt run`). + ### Key Pair Authentication To use key pair authentication, omit a `password` and instead provide a `private_key_path` and, optionally, a `private_key_passphrase` in your target. **Note:** Versions of dbt before 0.16.0 required that private keys were encrypted and a `private_key_passphrase` was provided. This behavior was changed in dbt v0.16.0. @@ -137,16 +205,16 @@ The "base" configs for Snowflake targets are shown below. Note that you should a | warehouse | Yes | The warehouse to use when building models | | schema | Yes | The schema to build models into by default. Can be overridden with [custom schemas](using-custom-schemas) | | role | No (but recommended) | The role to assume when running queries as the specified user. | -| client_session_keep_alive | No | If provided, issue a periodic `select` statement to keep the connection open when particularly long-running queries are executing (> 4 hours). Default: False (see note below) | +| client_session_keep_alive | No | If `True`, the snowflake client will keep connections for longer than the default 4 hours. This is helpful when particularly long-running queries are executing (> 4 hours). Default: False (see [note below](#client_session_keep_alive)) | | threads | No | The number of concurrent models dbt should build. Set this to a higher number if using a bigger warehouse. Default=1 | | query_tag | No | A value with which to tag all queries, for later searching in [QUERY_HISTORY view](https://docs.snowflake.com/en/sql-reference/account-usage/query_history.html) | -| retry_all | No | A boolean flag indicating whether to retry on all [Snowflake connector errors](https://github.com/snowflakedb/snowflake-connector-python/blob/master/src/snowflake/connector/errors.py) | +| retry_all | No | A boolean flag indicating whether to retry on all [Snowflake connector errors](https://github.com/snowflakedb/snowflake-connector-python/blob/main/src/snowflake/connector/errors.py) | | retry_on_database_errors | No | A boolean flag indicating whether to retry after encountering errors of type [snowflake.connector.errors.DatabaseError](https://github.com/snowflakedb/snowflake-connector-python/blob/ffdd6b3339aa71885878d047141fe9a77c4a4ae3/src/snowflake/connector/errors.py#L361-L364) | | connect_retries | No | The number of times to retry after an unsuccessful connection | | connect_timeout | No | The number of seconds to sleep between failed connection retries | ### account -For AWS accounts in the default US West region, this will be something like `abc123` (without any other segments). For AWS accounts *not* in the default US West region and for GCP and Azure-based accounts, you also have to append the cloud platform, such as `aws`, `gcp` or `azure`, respectively (for example: `abc123.us-central1.gcp`) See [Snowflake's documentation](https://docs.snowflake.com/en/user-guide/intro-regions.html#specifying-region-information-in-your-account-hostname) for more information. +For AWS accounts in the US West default region, you can use `abc123` (without any other segments). For some AWS accounts you will have to append the region and/or cloud platform. For example, `abc123.eu-west-1` or `abc123.eu-west-2.aws`. For GCP and Azure-based accounts, you have to append the region and cloud platform, such as `gcp` or `azure`, respectively. For example, `abc123.us-central1.gcp`. For details, see Snowflake's documention: "[Specifying Region Information in Your Account Hostname](https://docs.snowflake.com/en/user-guide/intro-regions.html#specifying-region-information-in-your-account-hostname)" and "[Account Identifier Formats by Cloud Platform and Region](https://docs.snowflake.com/en/user-guide/admin-account-identifier.html#account-identifier-formats-by-cloud-platform-and-region)". ### client_session_keep_alive @@ -171,4 +239,4 @@ The `retry_on_database_errors` flag along with the `connect_retries` count speci New in v1.0.0. -The `retry_all` flag along with the `connect_retries` count specification is intended to make retries configurable after the snowflake connector encounters any error. \ No newline at end of file +The `retry_all` flag along with the `connect_retries` count specification is intended to make retries configurable after the snowflake connector encounters any error. diff --git a/website/docs/reference/warehouse-setups/spark-setup.md b/website/docs/reference/warehouse-setups/spark-setup.md new file mode 100644 index 00000000000..14254683637 --- /dev/null +++ b/website/docs/reference/warehouse-setups/spark-setup.md @@ -0,0 +1,236 @@ +--- +title: "Apache Spark Profile" +id: "spark-setup" +meta: + maintained_by: dbt Labs + authors: 'core dbt maintainers' + github_repo: 'dbt-labs/dbt-spark' + pypi_package: 'dbt-spark' + min_core_version: 'v0.15.0' + cloud_support: Supported + min_supported_version: 'n/a' + slack_channel_name: 'db-databricks-and-spark' + slack_channel_link: 'https://getdbt.slack.com/archives/CNGCW8HKL' + platform_name: 'Spark' + config_page: 'spark-configs' +--- + +

Overview of {frontMatter.meta.pypi_package}

+ +
    +
  • Maintained by: {frontMatter.meta.maintained_by}
  • +
  • Authors: {frontMatter.meta.authors}
  • +
  • GitHub repo: {frontMatter.meta.github_repo}
  • +
  • PyPI package: {frontMatter.meta.pypi_package}
  • +
  • Slack channel: {frontMatter.meta.slack_channel_name}
  • +
  • Supported dbt Core version: {frontMatter.meta.min_core_version} and newer
  • +
  • dbt Cloud support: {frontMatter.meta.cloud_support}
  • +
  • Minimum data platform version: {frontMatter.meta.min_supported_version}
  • +
+ +

Installing {frontMatter.meta.pypi_package}

+ +pip is the easiest way to install the adapter: + +pip install {frontMatter.meta.pypi_package} + +

Installing {frontMatter.meta.pypi_package} will also install dbt-core and any other dependencies.

+ +If connecting to Databricks via ODBC driver, it requires `pyodbc`. Depending on your system, you can install it seperately or via pip. See the [`pyodbc` wiki](https://github.com/mkleehammer/pyodbc/wiki/Install) for OS-specific installation details. + +If connecting to a Spark cluster via the generic thrift or http methods, it requires `PyHive`. + +```zsh +# odbc connections +$ pip install "dbt-spark[ODBC]" + +# thrift or http connections +$ pip install "dbt-spark[PyHive]" +``` + + + +```zsh +# session connections +$ pip install "dbt-spark[session]" +``` + + + +

Configuring {frontMatter.meta.pypi_package}

+ +

For {frontMatter.meta.platform_name}-specifc configuration please refer to {frontMatter.meta.platform_name} Configuration

+ +

For further info, refer to the GitHub repository: {frontMatter.meta.github_repo}

+ +## Connection Methods + +dbt-spark can connect to Spark clusters by three different methods: + +- [`odbc`](#odbc) is the preferred method when connecting to Databricks. It supports connecting to a SQL Endpoint or an all-purpose interactive cluster. +- [`thrift`](#thrift) connects directly to the lead node of a cluster, either locally hosted / on premise or in the cloud (e.g. Amazon EMR). +- [`http`](#http) is a more generic method for connecting to a managed service that provides an HTTP endpoint. Currently, this includes connections to a Databricks interactive cluster. + + + +- [`session`](#session) connects to a pySpark session, running locally or on a remote machine. + +:::info Advanced functionality +The `session` connection method is intended for advanced users and experimental dbt development. This connection method is not supported by dbt Cloud. +::: + + + +### ODBC + +New in v0.18.1 + +Use the `odbc` connection method if you are connecting to a Databricks SQL endpoint or interactive cluster via ODBC driver. (Download the latest version of the official driver [here](https://databricks.com/spark/odbc-driver-download).) + + + +```yaml +your_profile_name: + target: dev + outputs: + dev: + type: spark + method: odbc + driver: [path/to/driver] + schema: [database/schema name] + host: [yourorg.sparkhost.com] + organization: [org id] # Azure Databricks only + token: [abc123] + + # one of: + endpoint: [endpoint id] + cluster: [cluster id] + + # optional + port: [port] # default 443 + user: [user] + server_side_parameters: + # cluster configuration parameters, otherwise applied via `SET` statements + # for example: + # "spark.databricks.delta.schema.autoMerge.enabled": True +``` + + + +### Thrift + +Use the `thrift` connection method if you are connecting to a Thrift server sitting in front of a Spark cluster, e.g. a cluster running locally or on Amazon EMR. + + + +```yaml +your_profile_name: + target: dev + outputs: + dev: + type: spark + method: thrift + schema: [database/schema name] + host: [hostname] + + # optional + port: [port] # default 10001 + user: [user] + auth: [e.g. KERBEROS] + kerberos_service_name: [e.g. hive] + use_ssl: [true|false] # value of hive.server2.use.SSL, default false +``` + + + +### HTTP + +Use the `http` method if your Spark provider supports generic connections over HTTP (e.g. Databricks interactive cluster). + + + +```yaml +your_profile_name: + target: dev + outputs: + dev: + type: spark + method: http + schema: [database/schema name] + host: [yourorg.sparkhost.com] + organization: [org id] # Azure Databricks only + token: [abc123] + cluster: [cluster id] + + # optional + port: [port] # default: 443 + user: [user] + connect_timeout: 60 # default 10 + connect_retries: 5 # default 0 +``` + + + +Databricks interactive clusters can take several minutes to start up. You may +include the optional profile configs `connect_timeout` and `connect_retries`, +and dbt will periodically retry the connection. + + + +### Session + +Use the `session` method if you want to run `dbt` against a pySpark session. + + + +```yaml +your_profile_name: + target: dev + outputs: + dev: + type: spark + method: session + schema: [database/schema name] + host: NA # not used, but required by `dbt-core` +``` + + + + + + + +## Optional configurations + +### Retries + +Intermittent errors can crop up unexpectedly while running queries against Apache Spark. If `retry_all` is enabled, dbt-spark will naively retry any query that fails, based on the configuration supplied by `connect_timeout` and `connect_retries`. It does not attempt to determine if the query failure was transient or likely to succeed on retry. This configuration is recommended in production environments, where queries ought to be succeeding. + +For instance, this will instruct dbt to retry all failed queries up to 3 times, with a 5 second delay between each retry: + + + +```yaml +retry_all: true +connect_timeout: 5 +connect_retries: 3 +``` + + + + + +## Caveats + +### Usage with EMR +To connect to Apache Spark running on an Amazon EMR cluster, you will need to run `sudo /usr/lib/spark/sbin/start-thriftserver.sh` on the master node of the cluster to start the Thrift server (see [the docs](https://aws.amazon.com/premiumsupport/knowledge-center/jdbc-connection-emr/) for more information). You will also need to connect to port 10001, which will connect to the Spark backend Thrift server; port 10000 will instead connect to a Hive backend, which will not work correctly with dbt. + +### Supported Functionality + +Most dbt Core functionality is supported, but some features are only available +on Delta Lake (Databricks). + +Delta-only features: +1. Incremental model updates by `unique_key` instead of `partition_by` (see [`merge` strategy](spark-configs#the-merge-strategy)) +2. [Snapshots](snapshots) +3. [Persisting](persist_docs) column-level descriptions as database comments diff --git a/website/docs/reference/warehouse-setups/sqlite-setup.md b/website/docs/reference/warehouse-setups/sqlite-setup.md new file mode 100644 index 00000000000..acdf1fd7e64 --- /dev/null +++ b/website/docs/reference/warehouse-setups/sqlite-setup.md @@ -0,0 +1,122 @@ +--- +title: "SQLite setup" +id: "sqlite-setup" +meta: + maintained_by: Community + authors: 'Jeff Chiu (https://github.com/codeforkjeff)' + github_repo: 'codeforkjeff/dbt-sqlite' + pypi_package: 'dbt-sqlite' + min_core_version: 'v1.1.0' + cloud_support: Not Supported + min_supported_version: 'SQlite Version 3.0' + slack_channel_name: 'n/a' + slack_channel_link: 'https://www.getdbt.com/community' + platform_name: 'SQLite' + config_page: 'no-configs' +--- + +:::info Community plugin + +Some core functionality may be limited. If you're interested in contributing, check out the source code for each repository listed below. + +::: + +

Overview of {frontMatter.meta.pypi_package}

+ +
    +
  • Maintained by: {frontMatter.meta.maintained_by}
  • +
  • Authors: {frontMatter.meta.authors}
  • +
  • GitHub repo: {frontMatter.meta.github_repo}
  • +
  • PyPI package: {frontMatter.meta.pypi_package}
  • +
  • Slack channel: {frontMatter.meta.slack_channel_name}
  • +
  • Supported dbt Core version: {frontMatter.meta.min_core_version} and newer
  • +
  • dbt Cloud support: {frontMatter.meta.cloud_support}
  • +
  • Minimum data platform version: {frontMatter.meta.min_supported_version}
  • +
+ + +

Installing {frontMatter.meta.pypi_package}

+ +pip is the easiest way to install the adapter: + +pip install {frontMatter.meta.pypi_package} + +

Installing {frontMatter.meta.pypi_package} will also install dbt-core and any other dependencies.

+ +

Configuring {frontMatter.meta.pypi_package}

+ +

For {frontMatter.meta.platform_name}-specifc configuration please refer to {frontMatter.meta.platform_name} Configuration

+ +

For further info, refer to the GitHub repository: {frontMatter.meta.github_repo}

+ + +Starting with the release of dbt-core 1.0.0, versions of dbt-sqlite are aligned to the same major+minor [version](https://semver.org/) of dbt-core. +- versions 1.1.x of this adapter work with dbt-core 1.1.x +- versions 1.0.x of this adapter work with dbt-core 1.0.x +- versions 0.2.x of this adapter work with dbt 0.20.x and 0.21.x +- versions 0.1.x of this adapter work with dbt 0.19.x +- versions 0.0.x of this adapter work with dbt 0.18.x + +## Connecting to SQLite with dbt-sqlite + +SQLite targets should be set up using the following configuration in your `profiles.yml` file. + +Example: + + + +```yaml +your_profile_name: + target: dev + outputs: + dev: + type: sqlite + threads: 1 + database: 'database' + schema: 'main' + schemas_and_paths: + main: 'file_path/database_name.db' + schema_directory: 'file_path' + #optional fields + extensions: + - "/path/to/sqlean/crypto.so" +``` + + + +#### Description of SQLite Profile Fields + +| Field | Description | +|--------------------------|--------------------------------------------------------------------------------------------------------| +| `type` | Required. Must be set to `sqlite`. | +| `threads` | Required. Must be set to `1`. SQLite locks the whole db on writes so anything > 1 won't help. | +| `database` | Required but the value is arbitrary because there is no 'database' portion of relation names in SQLite so it gets stripped from the output of ref() and from SQL everywhere. It still needs to be set in the configuration and is used by dbt internally.| +| `schema` | Value of 'schema' must be defined in schema_paths below. in most cases, this should be main. | +| `schemas_and_paths` | Connect schemas to paths: at least one of these must be 'main' | +| `schema_directory` | Directory where all *.db files are attached as schema, using base filename as schema name, and where new schemas are created. This can overlap with the dirs of files in schemas_and_paths as long as there's no conflicts. | +| `extensions` | Optional. List of file paths of SQLite extensions to load. crypto.so is needed for snapshots to work; see SQLlite Extensions below. | + +## Caveats + +- Schemas are implemented as attached database files. (SQLite conflates databases and schemas.) + + - SQLite automatically assigns 'main' to the file you initially connect to, so this must be defined in your profile. Other schemas defined in your profile + get attached when database connection is created. + + - If dbt needs to create a new schema, it will be created in `schema_directory` as `schema_name.db`. Dropping a schema results in dropping all its relations and detaching the database file from the session. + + - Schema names are stored in view definitions, so when you access a non-'main' database file outside dbt, you'll need to attach it using the same name, or the views won't work. + + - SQLite does not allow views in one schema (i.e. database file) to reference objects in another schema. You'll get this error from SQLite: "view [someview] cannot reference objects in database [somedatabase]". You must set `materialized='table'` in models that reference other schemas. + +- Materializations are simplified: they drop and re-create the model, instead of doing the backup-and-swap-in new model that the other dbt database adapters support. This choice was made because SQLite doesn't support `DROP ... CASCADE` or `ALTER VIEW` or provide information about relation dependencies in something information_schema-like. These limitations make it really difficult to make the backup-and-swap-in functionality work properly. Given how SQLite aggressively [locks](https://sqlite.org/lockingv3.html the database anyway, it's probably not worth the effort. + +## SQLite Extensions + +For snapshots to work, you'll need the `crypto` module from SQLean to get an `md5()` function. It's recommended that you install all the SQLean modules, as they provide many common SQL functions missing from SQLite. + +Precompiled binaries are available for download from the [SQLean github repository page](https://github.com/nalgeon/sqlean). You can also compile them yourself if you want. + +Point to these module files in your profile config as shown in the example above. + +Mac OS seems to ship with [SQLite libraries that do not have support for loading extensions compiled in](https://docs.python.org/3/library/sqlite3.html#f1), so this won't work "out of the box." Accordingly, snapshots won't work. If you need snapshot functionality, you'll need to compile SQLite/python or find a python distribution for Mac OS with this support. diff --git a/website/docs/reference/warehouse-setups/teradata-setup.md b/website/docs/reference/warehouse-setups/teradata-setup.md new file mode 100644 index 00000000000..72b137097c5 --- /dev/null +++ b/website/docs/reference/warehouse-setups/teradata-setup.md @@ -0,0 +1,128 @@ +--- +title: "Teradata setup" +id: "teradata-setup" +meta: + maintained_by: Teradata + authors: Doug Beatty and Adam Tworkiewicz + github_repo: 'Teradata/dbt-teradata' + pypi_package: 'dbt-teradata' + min_core_version: 'v0.21.0' + cloud_support: Not Supported + min_supported_version: 'n/a' + slack_channel_name: '#db-teradata' + slack_channel_link: 'https://getdbt.slack.com/archives/C027B6BHMT3' + platform_name: 'Teradata' + config_page: 'teradata-configs' +--- + +Some core functionality may be limited. If you're interested in contributing, check out the source code for the repository listed below. + + +

Overview of {frontMatter.meta.pypi_package}

+ +
    +
  • Maintained by: {frontMatter.meta.maintained_by}
  • +
  • Authors: {frontMatter.meta.authors}
  • +
  • GitHub repo: {frontMatter.meta.github_repo}
  • +
  • PyPI package: {frontMatter.meta.pypi_package}
  • +
  • Slack channel: {frontMatter.meta.slack_channel_name}
  • +
  • Supported dbt Core version: {frontMatter.meta.min_core_version} and newer
  • +
  • dbt Cloud support: {frontMatter.meta.cloud_support}
  • +
  • Minimum data platform version: {frontMatter.meta.min_supported_version}
  • +
+ + +

Installing {frontMatter.meta.pypi_package}

+ +pip is the easiest way to install the adapter: + +pip install {frontMatter.meta.pypi_package} + +

Installing {frontMatter.meta.pypi_package} will also install dbt-core and any other dependencies.

+ +

Configuring {frontMatter.meta.pypi_package}

+ +

For {frontMatter.meta.platform_name}-specifc configuration please refer to {frontMatter.meta.platform_name} Configuration

+ +

For further info, refer to the GitHub repository: {frontMatter.meta.github_repo}

+ + +### Connecting to Teradata + +To connect to Teradata Vantage from dbt, you'll need to add a [profile](https://docs.getdbt.com/dbt-cli/configure-your-profile) to your `profiles.yml` file. A Teradata profile conforms to the following syntax: + + + +```yaml +: + target: + outputs: + : + type: teradata + user: + password: + schema: + tmode: ANSI + threads: 1 + #optional fields + +``` + + + +#### Description of Teradata Profile Fields + +The following fields are required: + +Parameter | Default | Type | Description +----------------------- | ----------- | -------------- | --- +`user` | | string | Specifies the database username. Equivalent to the Teradata JDBC Driver `USER` connection parameter. +`password` | | string | Specifies the database password. Equivalent to the Teradata JDBC Driver `PASSWORD` connection parameter. +`schema` | | string | Specifies the initial database to use after logon, instead of the user's default database. +`tmode` | `"ANSI"` | string | Specifies the transaction mode. Only `ANSI` mode is currently supported. + + +The plugin also supports the following optional connection parameters: + +Parameter | Default | Type | Description +----------------------- | ----------- | -------------- | --- +`account` | | string | Specifies the database account. Equivalent to the Teradata JDBC Driver `ACCOUNT` connection parameter. +`column_name` | `"false"` | quoted boolean | Controls the behavior of cursor `.description` sequence `name` items. Equivalent to the Teradata JDBC Driver `COLUMN_NAME` connection parameter. False specifies that a cursor `.description` sequence `name` item provides the AS-clause name if available, or the column name if available, or the column title. True specifies that a cursor `.description` sequence `name` item provides the column name if available, but has no effect when StatementInfo parcel support is unavailable. +`connect_failure_ttl` | `"0"` | quoted integer | Specifies the time-to-live in seconds to remember the most recent connection failure for each IP address/port combination. The driver subsequently skips connection attempts to that IP address/port for the duration of the time-to-live. The default value of zero disables this feature. The recommended value is half the database restart time. Equivalent to the Teradata JDBC Driver `CONNECT_FAILURE_TTL` connection parameter. +`cop` | `"true"` | quoted boolean | Specifies whether COP Discovery is performed. Equivalent to the Teradata JDBC Driver `COP` connection parameter. +`coplast` | `"false"` | quoted boolean | Specifies how COP Discovery determines the last COP hostname. Equivalent to the Teradata JDBC Driver `COPLAST` connection parameter. When `coplast` is `false` or omitted, or COP Discovery is turned off, then no DNS lookup occurs for the coplast hostname. When `coplast` is `true`, and COP Discovery is turned on, then a DNS lookup occurs for a coplast hostname. +`dbs_port` | `"1025"` | quoted integer | Specifies the database port number. Equivalent to the Teradata JDBC Driver `DBS_PORT` connection parameter. +`encryptdata` | `"false"` | quoted boolean | Controls encryption of data exchanged between the driver and the database. Equivalent to the Teradata JDBC Driver `ENCRYPTDATA` connection parameter. +`fake_result_sets` | `"false"` | quoted boolean | Controls whether a fake result set containing statement metadata precedes each real result set. +`field_quote` | `"\""` | string | Specifies a single character string used to quote fields in a CSV file. +`field_sep` | `","` | string | Specifies a single character string used to separate fields in a CSV file. Equivalent to the Teradata JDBC Driver `FIELD_SEP` connection parameter. +`host` | | string | Specifies the database hostname. +`https_port` | `"443"` | quoted integer | Specifies the database port number for HTTPS/TLS connections. Equivalent to the Teradata JDBC Driver `HTTPS_PORT` connection parameter. +`lob_support` | `"true"` | quoted boolean | Controls LOB support. Equivalent to the Teradata JDBC Driver `LOB_SUPPORT` connection parameter. +`log` | `"0"` | quoted integer | Controls debug logging. Somewhat equivalent to the Teradata JDBC Driver `LOG` connection parameter. This parameter's behavior is subject to change in the future. This parameter's value is currently defined as an integer in which the 1-bit governs function and method tracing, the 2-bit governs debug logging, the 4-bit governs transmit and receive message hex dumps, and the 8-bit governs timing. Compose the value by adding together 1, 2, 4, and/or 8. +`logdata` | | string | Specifies extra data for the chosen logon authentication method. Equivalent to the Teradata JDBC Driver `LOGDATA` connection parameter. +`logmech` | `"TD2"` | string | Specifies the logon authentication method. Equivalent to the Teradata JDBC Driver `LOGMECH` connection parameter. Possible values are `TD2` (the default), `JWT`, `LDAP`, `KRB5` for Kerberos, or `TDNEGO`. +`max_message_body` | `"2097000"` | quoted integer | Specifies the maximum Response Message size in bytes. Equivalent to the Teradata JDBC Driver `MAX_MESSAGE_BODY` connection parameter. +`partition` | `"DBC/SQL"` | string | Specifies the database partition. Equivalent to the Teradata JDBC Driver `PARTITION` connection parameter. +`sip_support` | `"true"` | quoted boolean | Controls whether StatementInfo parcel is used. Equivalent to the Teradata JDBC Driver `SIP_SUPPORT` connection parameter. +`sslca` | | string | Specifies the file name of a PEM file that contains Certificate Authority (CA) certificates for use with `sslmode` values `VERIFY-CA` or `VERIFY-FULL`. Equivalent to the Teradata JDBC Driver `SSLCA` connection parameter. +`sslcapath` | | string | Specifies a directory of PEM files that contain Certificate Authority (CA) certificates for use with `sslmode` values `VERIFY-CA` or `VERIFY-FULL`. Only files with an extension of `.pem` are used. Other files in the specified directory are not used. Equivalent to the Teradata JDBC Driver `SSLCAPATH` connection parameter. +`sslcipher` | | string | Specifies the TLS cipher for HTTPS/TLS connections. Equivalent to the Teradata JDBC Driver `SSLCIPHER` connection parameter. +`sslmode` | `"PREFER"` | string | Specifies the mode for connections to the database. Equivalent to the Teradata JDBC Driver `SSLMODE` connection parameter.
• `DISABLE` disables HTTPS/TLS connections and uses only non-TLS connections.
• `ALLOW` uses non-TLS connections unless the database requires HTTPS/TLS connections.
• `PREFER` uses HTTPS/TLS connections unless the database does not offer HTTPS/TLS connections.
• `REQUIRE` uses only HTTPS/TLS connections.
• `VERIFY-CA` uses only HTTPS/TLS connections and verifies that the server certificate is valid and trusted.
• `VERIFY-FULL` uses only HTTPS/TLS connections, verifies that the server certificate is valid and trusted, and verifies that the server certificate matches the database hostname. +`sslprotocol` | `"TLSv1.2"` | string | Specifies the TLS protocol for HTTPS/TLS connections. Equivalent to the Teradata JDBC Driver `SSLPROTOCOL` connection parameter. +`teradata_values` | `"true"` | quoted boolean | Controls whether `str` or a more specific Python data type is used for certain result set column value types. + +For the full description of the connection parameters see https://github.com/Teradata/python-driver#connection-parameters. + +## Supported Features + +### Materializations + +* `view` +* `table` +* `ephemeral` +* `incremental` + +### Commands + +All dbt commands are supported. diff --git a/website/docs/reference/warehouse-setups/tidb-setup.md b/website/docs/reference/warehouse-setups/tidb-setup.md new file mode 100644 index 00000000000..d1a5f887bdf --- /dev/null +++ b/website/docs/reference/warehouse-setups/tidb-setup.md @@ -0,0 +1,131 @@ +--- +title: "TiDB setup" +id: "tidb-setup" +meta: + maintained_by: PingCAP + authors: Xiang Zhang, Qiang Wu, Yuhang Shi + github_repo: 'pingcap/dbt-tidb' + pypi_package: 'dbt-tidb' + core_version: 'v1.0.0 and newer' + cloud_support: Not Supported + slack_channel_name: '#db-tidb' + slack_channel_link: 'https://getdbt.slack.com/archives/C03CC86R1NY' + platform_name: 'TiDB' + config_page: 'no-configs' +--- + +:::info Vendor-supported plugin + +Some [core functionality](https://github.com/pingcap/dbt-tidb/blob/main/README.md#supported-features) may be limited. +If you're interested in contributing, check out the source code repository listed below. + +::: + +

Overview of {frontMatter.meta.pypi_package}

+ +
    +
  • Maintained by: {frontMatter.meta.maintained_by}
  • +
  • Authors: {frontMatter.meta.authors}
  • +
  • GitHub repo: {frontMatter.meta.github_repo}
  • +
  • PyPI package: {frontMatter.meta.pypi_package}
  • +
  • Slack channel: {frontMatter.meta.slack_channel_name}
  • +
  • Supported dbt Core version: {frontMatter.meta.min_core_version} and newer
  • +
  • dbt Cloud support: {frontMatter.meta.cloud_support}
  • +
  • Minimum data platform version: {frontMatter.meta.min_supported_version}
  • +
+ + +

Installing {frontMatter.meta.pypi_package}

+ +pip is the easiest way to install the adapter: + +pip install {frontMatter.meta.pypi_package} + +

Installing {frontMatter.meta.pypi_package} will also install dbt-core and any other dependencies.

+ +

Configuring {frontMatter.meta.pypi_package}

+ +

For {frontMatter.meta.platform_name}-specifc configuration please refer to {frontMatter.meta.platform_name} Configuration

+ +

For further info, refer to the GitHub repository: {frontMatter.meta.github_repo}

+ + +## Connecting to TiDB with **dbt-tidb** + +### User / Password Authentication + +Configure your dbt profile for using TiDB: + +#### TiDB connection profile + + +```yaml +dbt-tidb: + target: dev + outputs: + dev: + type: tidb + server: 127.0.0.1 + port: 4000 + schema: database_name + username: tidb_username + password: tidb_password + + # optional + retries: 3 # default 1 +``` + + + +#### Description of Profile Fields + +| Option | Description | Required? | Example | +|----------|------------------------------------------------------|-----------|---------------------| +| type | The specific adapter to use | Required | `tidb` | +| server | The server (hostname) to connect to | Required | `yourorg.tidb.com` | +| port | The port to use | Required | `4000` | +| schema | Specify the schema (database) to build models into | Required | `analytics` | +| username | The username to use to connect to the server | Required | `dbt_admin` | +| password | The password to use for authenticating to the server | Required | `awesome_password` | +| retries | The retry times after an unsuccessful connection | Optional | `default 1` | + +## Database User Privileges + +Your database user would be able to have some abilities to read or write, such as `SELECT`, `CREATE`, and so on. +You can find some help [here](https://docs.pingcap.com/tidb/v4.0/privilege-management) with TiDB privileges management. + +| Required Privilege | +|------------------------| +| SELECT | +| CREATE | +| CREATE TEMPORARY TABLE | +| CREATE VIEW | +| INSERT | +| DROP | +| SHOW DATABASE | +| SHOW VIEW | +| SUPER | + +## Supported features + +| TiDB 4.X | TiDB 5.0 ~ 5.2 | TiDB >= 5.3 | Feature | +|:--------:|:--------------:|:-----------:|:---------------------------:| +| ✅ | ✅ | ✅ | Table materialization | +| ✅ | ✅ | ✅ | View materialization | +| ❌ | ❌ | ✅ | Incremental materialization | +| ❌ | ✅ | ✅ | Ephemeral materialization | +| ✅ | ✅ | ✅ | Seeds | +| ✅ | ✅ | ✅ | Sources | +| ✅ | ✅ | ✅ | Custom data tests | +| ✅ | ✅ | ✅ | Docs generate | +| ❌ | ❌ | ✅ | Snapshots | +| ✅ | ✅ | ✅ | Grant | +| ✅ | ✅ | ✅ | Connection retry | + +**Note:** + +* TiDB 4.0 ~ 5.0 does not support [CTE](https://docs.pingcap.com/tidb/dev/sql-statement-with), + you should avoid using `WITH` in your SQL code. +* TiDB 4.0 ~ 5.2 does not support creating a [temporary table or view](https://docs.pingcap.com/tidb/v5.2/sql-statement-create-table#:~:text=sec\)-,MySQL%20compatibility,-TiDB%20does%20not). +* TiDB 4.X does not support using SQL func in `CREATE VIEW`, avoid it in your SQL code. + You can find more detail [here](https://github.com/pingcap/tidb/pull/27252). diff --git a/website/docs/reference/warehouse-setups/trino-setup.md b/website/docs/reference/warehouse-setups/trino-setup.md new file mode 100644 index 00000000000..7939f4d5d7d --- /dev/null +++ b/website/docs/reference/warehouse-setups/trino-setup.md @@ -0,0 +1,119 @@ +--- +title: "Starburst & Trino setup" +id: "trino-setup" +meta: + maintained_by: Starburst Data, Inc. + authors: Matthew Carter, Andy Regan, Andrew Hedengren + github_repo: 'starburstdata/dbt-trino' + pypi_package: 'dbt-trino' + min_core_version: 'v0.20.0' + cloud_support: Not Supported + min_supported_version: 'n/a' + slack_channel_name: '#db-clickhouse' + slack_channel_link: 'https://getdbt.slack.com/archives/C01DRQ178LQ' + platform_name: 'Trino' + config_page: 'no-configs' +--- + +:::info Vendor-supported plugin + +Certain core functionality may vary. If you would like to report a bug, request a feature, or contribute, you can check out the linked repository and open an issue. + +::: + +

Overview of {frontMatter.meta.pypi_package}

+ +
    +
  • Maintained by: {frontMatter.meta.maintained_by}
  • +
  • Authors: {frontMatter.meta.authors}
  • +
  • GitHub repo: {frontMatter.meta.github_repo}
  • +
  • PyPI package: {frontMatter.meta.pypi_package}
  • +
  • Slack channel: {frontMatter.meta.slack_channel_name}
  • +
  • Supported dbt Core version: {frontMatter.meta.min_core_version} and newer
  • +
  • dbt Cloud support: {frontMatter.meta.cloud_support}
  • +
  • Minimum data platform version: {frontMatter.meta.min_supported_version}
  • +
+ + +

Installing {frontMatter.meta.pypi_package}

+ +pip is the easiest way to install the adapter: + +pip install {frontMatter.meta.pypi_package} + +

Installing {frontMatter.meta.pypi_package} will also install dbt-core and any other dependencies.

+ +

Configuring {frontMatter.meta.pypi_package}

+ +

For {frontMatter.meta.platform_name}-specifc configuration please refer to {frontMatter.meta.platform_name} Configuration

+ +

For further info, refer to the GitHub repository: {frontMatter.meta.github_repo}

+ + + +## Set up a Trino or Starburst Target + +Trino or Starburst targets should be set up using the following configuration in your `profiles.yml` file. + +See all possible profile configuration options [here](#configuration). + + + +```yaml +trino: + target: dev + outputs: + dev: + type: trino + method: none # optional, one of {none | ldap | kerberos | oauth | jwt | certificate} + user: [user] + password: [password] # required if method is ldap or kerberos + database: [database name] + host: [hostname] + port: [port number] + schema: [your dbt schema] + threads: [1 or more] + retries: [1 or more] # default: 3 + http_scheme: [http or https] + session_properties: + [some_session_property]: [value] # run SHOW SESSION query to get current session properties +``` + + + +## Incremental models + +Incremental strategies supported by the adapter are: + +- append (default incremental strategy) - append only adds the new records based on the condition specified in the is_incremental() conditional block. +- delete+insert - Through the delete+insert incremental strategy, you can instruct dbt to use a two-step incremental approach. It will first delete the records detected through the configured is_incremental() block and re-insert them. +- merge - Through the merge incremental strategy, dbt-trino constructs a MERGE statement which inserts new and updates existing records based on the unique key (specified by unique_key). +If your unique_key is not actually unique, the delete+insert strategy can be used instead. Note that some connectors in Trino have limited or no support for MERGE. + +## Configuration + +A dbt-trino profile can be configured to run against Trino or Starburst using the following configuration: + +| Option | Description | Required? | Example | +|--------------------------------|--------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------|----------------------------------| +| method | The Trino authentication method to use | Optional (default is `none`, supported methods are `ldap`, `kerberos`, `jwt`, `oauth` or `certificate`) | `none` or `kerberos` | +| user | Username for authentication | Optional (required if `method` is `none`, `ldap` or `kerberos`) | `commander` | +| password | Password for authentication | Optional (required if `method` is `ldap`) | `none` or `abc123` | +| keytab | Path to keytab for kerberos authentication | Optional (may be required if `method` is `kerberos`) | `/tmp/trino.keytab` | +| krb5_config | Path to config for kerberos authentication | Optional (may be required if `method` is `kerberos`) | `/tmp/krb5.conf` | +| principal | Principal for kerberos authentication | Optional (may be required if `method` is `kerberos`) | `trino@EXAMPLE.COM` | +| service_name | Service name for kerberos authentication | Optional (default is `trino`) | `abc123` | +| jwt_token | JWT token for authentication | Optional (required if `method` is `jwt`) | `none` or `abc123` | +| client_certificate | Path to client certificate to be used for certificate based authentication | Optional (required if `method` is `certificate`) | `/tmp/tls.crt` | +| client_private_key | Path to client private key to be used for certificate based authentication | Optional (required if `method` is `certificate`) | `/tmp/tls.key` | +| http_headers | HTTP Headers to send alongside requests to Trino, specified as a yaml dictionary of (header, value) pairs. | Optional | `X-Trino-Client-Info: dbt-trino` | +| http_scheme | The HTTP scheme to use for requests to Trino | Optional (default is `http`, or `https` for `method: kerberos`, `ldap` or `jwt`) | `https` or `http` | +| cert | The full path to a certificate file for authentication with trino | Optional | | +| session_properties | Sets Trino session properties used in the connection | Optional | `query_max_run_time: 5d` | +| database | Specify the database to build models into | Required | `analytics` | +| schema | Specify the schema to build models into. Note: it is not recommended to use upper or mixed case schema names | Required | `public` | +| host | The hostname to connect to | Required | `127.0.0.1` | +| port | The port to connect to the host on | Required | `8080` | +| threads | How many threads dbt should use | Optional (default is `1`) | `8` | +| prepared_statements_enabled | Enable usage of Trino prepared statements (used in `dbt seed` commands) | Optional (default is `true`) | `true` or `false` | +| retries | Configure how many times a database operation is retried when connection issues arise | Optional (default is `3`) diff --git a/website/docs/reference/warehouse-setups/vertica-setup.md b/website/docs/reference/warehouse-setups/vertica-setup.md new file mode 100644 index 00000000000..23f5d581a71 --- /dev/null +++ b/website/docs/reference/warehouse-setups/vertica-setup.md @@ -0,0 +1,83 @@ +--- +title: "Vertica setup" +id: "vertica-setup" +meta: + maintained_by: Community + authors: Matthew Carter, Andy Regan, Andrew Hedengren + github_repo: 'mpcarter/dbt-vertica' + pypi_package: 'dbt-vertica' + min_core_version: 'v0.21.0' + cloud_support: Not Supported + min_supported_version: 'Vertica 10.0' + slack_channel_name: 'n/a' + slack_channel_link: 'https://www.getdbt.com/community/' + platform_name: 'Vertica' + config_page: 'no-configs' + +--- + +:::info Community plugin + +Some core functionality may be limited. If you're interested in contributing, check out the source code for each repository listed below. + +::: + +

Overview of {frontMatter.meta.pypi_package}

+ +
    +
  • Maintained by: {frontMatter.meta.maintained_by}
  • +
  • Authors: {frontMatter.meta.authors}
  • +
  • GitHub repo: {frontMatter.meta.github_repo}
  • +
  • PyPI package: {frontMatter.meta.pypi_package}
  • +
  • Slack channel: {frontMatter.meta.slack_channel_name}
  • +
  • Supported dbt Core version: {frontMatter.meta.min_core_version} and newer
  • +
  • dbt Cloud support: {frontMatter.meta.cloud_support}
  • +
  • Minimum data platform version: {frontMatter.meta.min_supported_version}
  • +
+ + +

Installing {frontMatter.meta.pypi_package}

+ +pip is the easiest way to install the adapter: + +pip install {frontMatter.meta.pypi_package} + +

Installing {frontMatter.meta.pypi_package} will also install dbt-core and any other dependencies.

+ +

Configuring {frontMatter.meta.pypi_package}

+ +

For {frontMatter.meta.platform_name}-specifc configuration please refer to {frontMatter.meta.platform_name} Configuration

+ +

For further info, refer to the GitHub repository: {frontMatter.meta.github_repo}

+ + +### Connecting to Vertica with **dbt-vertica** + +#### Username / password authentication + +Configure your dbt profile for using Vertica: + +##### Vertica connection information + + + +```yaml +your-profile: + outputs: + dev: + type: vertica # Don't change this! + host: vertica-host-name + port: 5433 # or your custom port (optional) + username: your-username + password: your-password + database: vertica-database-name + schema: your-default-schema + target: dev +``` + + + +By default, `dbt-vertica` will request `ConnectionLoadBalance=true` (which is generally a good thing), and set a session label of `dbt_your-username`. + +There are three options for SSL: `ssl`, `ssl_env_cafile`, and `ssl_uri`. +See their use in the code [here](https://github.com/mpcarter/dbt-vertica/blob/d15f925049dabd2833b4d88304edd216e3f654ed/dbt/adapters/vertica/connections.py#L72-L87). diff --git a/website/docs/terms/cte.md b/website/docs/terms/cte.md new file mode 100644 index 00000000000..e6fe678fce7 --- /dev/null +++ b/website/docs/terms/cte.md @@ -0,0 +1,192 @@ +--- +id: cte +title: CTE in SQL +description: A CTE is a temporary result set that can be used in a SQL query. You can think of a CTE as a separate, smaller query within the larger query you’re building up. +displayText: CTE +hoverSnippet: A Common Table Expression (CTE) is a temporary result set that can be used in a SQL query. You can use CTEs to break up complex queries into simpler blocks of code that can connect and build on each other. +--- + + + CTE in SQL: Quite possibly the best thing to happen to SQL + + +In a formal sense, a Common Table Expression (CTE), is a temporary result set that can be used in a SQL query. You can use CTEs to break up complex queries into simpler blocks of code that can connect and build on each other. In a less formal, more human-sense, you can think of a CTE as a separate, smaller query within the larger query you’re building up. Creating a CTE is essentially like making a temporary that you can access throughout the rest of the query you are writing. + +There are two-types of CTEs: recursive and non-recursive. This glossary focuses on non-recursive CTEs. + +## Why you should care about CTEs + +Have you ever read through a query and thought: + +- “What does this part of the query do?” +- “What are all the sources referenced in this query? Why did I reference this dependency?” +- “My query is not producing the results I expect and I’m not sure which part of the query is causing that.” + +These thoughts often arise when we’ve written SQL queries and models that utilize complex business logic, references and joins multiple upstream dependencies, and are not outputting expected results. In a nutshell, these thoughts can occur often when you’re trying to write data models! + +How can you make these complexities in your code more digestible and usable? CTEs to the rescue! + +## CTE Syntax: How it works + +To use CTEs, you begin by defining your first CTE using the `WITH` statement followed by a `SELECT` statement. + +Let’s break down this example involving a `rename_columns` CTE below: + +```sql +with rename_columns as ( + + select + + id as customer_id, + lower(first_name) as customer_first_name, + lower(last_name) as customer_last_initial + + from {{ ref('raw_customers') }} + +) + +select * from rename_columns +``` + +In this query above, you first create a CTE called `rename_columns` where you conduct a +simple `SELECT` statement that renames and lower cases some columns from a `raw_customers` /model. The final `select * from rename_columns` selects all results from the `rename_columns` CTE. + +While you shouldn't always think of CTEs as having classical arguments like SQL functions, you’ve got to call the necessary inputs for CTEs something. + +- CTE_EXPRESSION_NAME: This is the name of the CTE you can reference in other CTEs or SELECT statements. In our example, `rename_columns` is the CTE_EXPRESSION_NAME. **If you are using multiple CTEs in one query, it’s important to note that each CTE_EXPRESSION_NAME must be unique.** +- CTE_QUERY: This is the `SELECT` statement whose result set is produced by the CTE. In our example above, the `select … from {{ ref('raw_customers') }}` is the CTE_QUERY. The CTE_QUERY is framed by parenthesis. + +## When to use CTEs + +The primary motivation to implement CTEs in your code is to simplify the complexity of your queries and increase your code’s readability. There are other great benefits to using CTEs in your queries which we’ll outline below. + +### Simplification + +When people talk about how CTEs can simplify your queries, they specifically mean how CTEs can help simplify the structure, readability, and debugging process of your code. + +#### Establish Structure + +In leveraging CTEs, you can break complex code into smaller segments, ultimately helping provide structure to your code. At dbt Labs, we often like to use the [import, logical, and final structure](guides/getting-started/learning-more/refactoring-legacy-sql#implement-cte-groupings) for CTEs which creates a predictable and organized structure to your dbt models. + +#### Easily identify dependencies + +When you import all of your dependencies as CTEs in the beginning of your query/model, you can automatically see which models, tables, or views your model relies on. + +#### Clearly label code blocks + +Utilizing the CTE_EXPRESSION_NAME, you can title what your CTE is accomplishing. This provides greater insight into what each block of code is performing and can help contextualize why that code is needed. This is incredibly helpful for both the developer who writes the query and the future developer who may inherit it. + +#### Test and debug more easily + +When queries are long, involve multiple joins, and/or complex business logic, it can be hard to understand why your query is not outputting the result you expect. By breaking your query into CTEs, you can separately test that each CTE is working properly. Using the process of elimination of your CTEs, you can more easily identify the root cause. + +### Substitution for a view + +Oftentimes you want to reference data in a query that could, or may have existed at one point, as a view. Instead of worrying about the view actually existing, you can leverage CTEs to create the temporary result you would want from the view. + +### Support reusability + +Using CTEs, you can reference the same resulting set multiple times in one query without having to duplicate your work by referencing the CTE_EXPRESSION_NAME in your from statement. + +## CTE example + +Time to dive into an example using CTEs! For this example, you'll be using the data from our [jaffle_shop demo dbt](https://github.com/dbt-labs/jaffle_shop) project. In the `jaffle_shop`, you have three tables: one for customers, orders, and payments. + +In this query, you're creating three CTEs to ultimately allow you to segment buyers by how many times they’ve purchased. + +```sql +with import_orders as ( + + select * from {{ ref('orders') }} + +), +aggregate_orders as ( + + select + + customer_id, + count(order_id) as count_orders + + from import_orders + where status not in ('returned', 'return pending') + group by 1 + +), +segment_users as ( + + select + + *, + case + when count_orders >= 3 then 'super_buyer' + when count_orders <3 and count_orders >= 2 then + 'regular_buyer' + else 'single_buyer' + end as buyer_type + + from aggregate_orders + +) +select * from segment_users +``` + +Let’s break this query down a bit: + +1. In the first `import_orders` CTE, you are simply importing the `orders` table which holds the data I’m interested in creating the customer segment off of. Note that this first CTE starts with a `WITH` statement and no following CTEs begin with a `WITH` statement. +2. The second `aggregate_orders` CTE utilizes the `import_orders` CTE to get a count of orders per user with a filter applied. +3. The last `segment_users` CTE builds off of the `aggregate_orders` by selecting the `customer_id`, `count_orders`, and creating your `buyer_type` segment. Note that the final `segment_users` CTE does not have a comma after its closing parenthesis. +4. The final `select * from segment_users` statement simply selects all results from the `segment_users` CTE. + +Your results from running this query look a little like this: + +| USER_ID | COUNT_ORDERS | BUYER_TYPE | +|---|---|---| +| 3 | 3 | super_buyer | +| 64 | 1 | single_buyer | +| 94 | 2 | regular_buyer | + +:::tip Tip +If you are finding yourself using the same code for a certain CTE across multiple +queries or models, that’s probably a good sign that CTE should be its own [model](https://docs.getdbt.com/docs/building-a-dbt-project/building-models) or view. +::: + +## CTE vs Subquery + +A is a nested query that can oftentimes be used in place of a CTE. Subqueries have different syntax than CTEs, but often have similar use cases. This content won’t go too deep into subqueries here, but it'll highlight some of the main differences between CTEs and subqueries below. + +| CTE | Subquery | +|---|---| +| Typically more readable since CTEs can be used to give structure to your query | Typically less readable, especially if there are many nested queries | +| Allows for recursiveness | Does not allow for recursiveness | +| CTEs must have unique CTE_EXPRESSION_NAMES when used in a query | Subqueries don’t always have to be explicitly named | +| CTEs cannot be used in a `WHERE` clause | Subqueries can be used in a `WHERE` clause | + +## Data warehouse support for CTEs + +CTEs are likely to be supported across most, if not all, [modern data warehouses](https://blog.getdbt.com/future-of-the-modern-data-stack/). Please use this table to see more information about using CTEs in your specific . + +| Data Warehouse | Support CTEs? | +|---|---| +|[Snowflake](https://docs.snowflake.com/en/user-guide/queries-cte.html) | :white_check_mark: | +|[Amazon Redshift](https://docs.aws.amazon.com/redshift/latest/dg/r_WITH_clause.html) | :white_check_mark: | +|[Google BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/query-syntax) | :white_check_mark: | +|[Databricks](https://docs.databricks.com/sql/language-manual/sql-ref-syntax-qry-select-cte.html) | :white_check_mark: | +|[Postgres](https://www.postgresqltutorial.com/postgresql-cte/) | :white_check_mark: | + +## Conclusion + +CTEs are essentially temporary views that can be used throughout a query. They are a great way to give your SQL more structure and readability, and offer simplified ways to debug your code. You can leverage appropriately-named CTEs to easily identify upstream dependencies and code functionality. CTEs also support recursiveness and reusability in the same query. Overall, CTEs can be an effective way to level-up your SQL to be more organized and understandable. + +## Futher Reading + +If you’re interested in reading more about CTE best practices, check out some of our favorite content around model refactoring and style: + +- [Refactoring Legacy SQL to dbt](guides/getting-started/learning-more/refactoring-legacy-sql#implement-cte-groupings) +- [dbt Labs Style Guide](https://github.com/dbt-labs/corp/blob/main/dbt_style_guide.md#ctes) +- [Modular Data Modeling Technique](https://www.getdbt.com/analytics-engineering/modular-data-modeling-technique/) + +Want to know why dbt Labs loves CTEs? Check out the following pieces: + +- [Why we use so many CTEs](https://discourse.getdbt.com/t/why-the-fishtown-sql-style-guide-uses-so-many-ctes/1091) +- [CTEs are Passthroughs](https://discourse.getdbt.com/t/ctes-are-passthroughs-some-research/155) + diff --git a/website/docs/terms/dag.md b/website/docs/terms/dag.md new file mode 100644 index 00000000000..f70f2539f14 --- /dev/null +++ b/website/docs/terms/dag.md @@ -0,0 +1,111 @@ +--- +id: dag +title: DAG +description: A DAG is a Directed Acyclic Graph, a type of graph whose nodes are directionally related to each other and don’t form a directional closed loop. +displayText: DAG +hoverSnippet: A DAG is a Directed Acyclic Graph, a type of graph whose nodes are directionally related to each other and don’t form a directional closed loop. +--- + + + What is a DAG and why is it important? - dbt Labs + + +A DAG is a **D**irected **A**cyclic **G**raph, a type of graph whose nodes are directionally related to each other and don’t form a directional closed loop. In the practice of analytics engineering, DAGs are often used to visually represent the relationships between your data models. + +While the concept of a DAG originated in mathematics and gained popularity in computational work, DAGs have found a home in the modern data world. They offer a great way to visualize data pipelines and lineage, and they offer an easy way to understand dependencies between data models. + +## DAG use cases and best practices + +DAGs are an effective tool to help you understand relationships between your data models and areas of improvement for your overall data transformations. + +### Unpacking relationships and data lineage + +Can you look at one of your data models today and quickly identify all the upstream and downstream models? If you can’t, that’s probably a good sign to start building or looking at your existing DAG. + +:::tip Upstream or downstream? + +How do you know if a model is upstream or downstream from the model you’re currently looking at? Upstream models are models that must be performed prior to the current model. In simple terms, the current model depends on upstream models in order to exist. Downstream relationships are the outputs from your current model. In a visual DAG, such as the dbt Lineage Graph, upstream models are to the left of your selected model and downstream models are to the right of your selected model. Ever confused? Use the arrows that create the directedness of a DAG to understand the direction of movement. + +::: + +One of the great things about DAGs is that they are *visual*. You can clearly identify the nodes that connect to each other and follow the lines of directions. When looking at a DAG, you should be able to identify where your data sources are going and where that data is potentially being referenced. + +Take this mini-DAG for an example: + + + +What can you learn from this DAG? Immediately, you may notice a handful of things: + +- `stg_users`and `stg_user_groups` models are the parent models for `int_users` +- A join is happening between `stg_users` and `stg_user_groups` to form the `int_users` model +- `stg_orgs` and `int_users` are the parent models for `dim_users` +- `dim_users` is a the end of the DAG and is therefore downstream from a total of four different models + +Within 10 seconds of looking at this DAG, you can quickly unpack some of the most important elements about a project: dependencies and data lineage. Obviously, this is a simplified version of DAGs you may see in real life, but the practice of identifying relationships and data flows remains very much the same, regardless of the size of the DAG. + +What happens if `stg_user_groups` just up and disappears one day? How would you know which models are potentially impacted by this change? Look at your DAG and understand model dependencies to mitigate downstream impacts. + +### Auditing projects + +A potentially bold statement, but there is no such thing as a perfect DAG. DAGs are special in-part because they are unique to your business, data, and data models. There’s usually always room for improvement, whether that means making a CTE into its own view or performing a join earlier upstream, and your DAG can be an effective way to diagnose inefficient data models and relationships. + +You can additionally use your DAG to help identify bottlenecks, long-running data models that severely impact the performance of your data pipeline. Bottlenecks can happen for multiple reasons: +- Expensive joins +- Extensive filtering or [use of window functions](https://docs.getdbt.com/blog/how-we-shaved-90-minutes-off-model) +- Complex logic stored in views +- Good old large volumes of data + +...to name just a few. Understanding the factors impacting model performance can help you decide on [refactoring approaches](https://courses.getdbt.com/courses/refactoring-sql-for-modularity), [changing model materialization](https://docs.getdbt.com/blog/how-we-shaved-90-minutes-off-model#attempt-2-moving-to-an-incremental-model)s, replacing multiple joins with surrogate keys, or other methods. + + + +### Modular data modeling best practices + +See the DAG above? It follows a more traditional approach to data modeling where new data models are often built from raw sources instead of relying on intermediary and reusable data models. This type of project does not scale with team or data growth. As a result, analytics engineers tend to aim to have their DAGs not look like this. + +Instead, there are some key elements that can help you create a more streamlined DAG and [modular data models](https://www.getdbt.com/analytics-engineering/modular-data-modeling-technique/): + +- Leveraging [staging, intermediate, and mart layers](https://docs.getdbt.com/guides/best-practices/how-we-structure/1-guide-overview) to create layers of distinction between sources and transformed data +- Abstracting code that’s used across multiple models to its own model +- Joining on surrogate keys versus on multiple values + +These are only a few examples of some best practices to help you organize your data models, business logic, and DAG. + +:::tip Is your DAG keeping up with best practices? + +Instead of manually auditing your DAG for best practices, the [dbt project evaluator package](https://github.com/dbt-labs/dbt-project-evaluator) can help audit your project and find areas of improvement. + +::: + +## dbt and DAGs + +The marketing team at dbt Labs would be upset with us if we told you we think dbt actually stood for “dag build tool,” but one of the key elements of dbt is its ability to generate documentation and infer relationships between models. And one of the hallmark features of [dbt Docs](https://docs.getdbt.com/docs/building-a-dbt-project/documentation) is the Lineage Graph (DAG) of your dbt project. + +Whether you’re using dbt Core or Cloud, dbt docs and the Lineage Graph are available to all dbt developers. The Lineage Graph in dbt Docs can show a model or source’s entire lineage, all within a visual frame. Clicking within a model, you can view the Lineage Graph and adjust selectors to only show certain models within the DAG. Analyzing the DAG here is a great way to diagnose potential inefficiencies or lack of modularity in your dbt project. + + + +The DAG is also [available in the dbt Cloud IDE](https://www.getdbt.com/blog/on-dags-hierarchies-and-ides/), so you and your team can refer to your lineage while you build your models. + +:::tip Leverage exposures + +One of the newer features of dbt is [exposures](https://docs.getdbt.com/docs/building-a-dbt-project/exposures), which allow you to define downstream use of your data models outside of your dbt project *within your dbt project*. What does this mean? This means you can add key dashboards, machine learning or data science pipelines, reverse ETL syncs, or other downstream use cases to your dbt project’s DAG. + +This level of interconnectivity and transparency can help boost data governance (who has access to and who [owns](https://docs.getdbt.com/reference/resource-configs/meta#designate-a-model-owner) this data) and transparency (what are the data sources and models affecting your key reports). + +::: + +## Conclusion + +A Directed acyclic graphs (DAG) is a visual representation of your data models and their connection to each other. The key components of a DAG are that nodes (sources/models/exposures) are directionally linked and don’t form acyclic loops. Overall, DAGs are an effective tool for understanding data lineage, dependencies, and areas of improvement in your data models. + +> *Get started with [dbt today](https://www.getdbt.com/signup/) to start building your own DAG!* + +## Further reading + +Ready to restructure (or create your first) DAG? Check out some of the resources below to better understand data modularity, data lineage, and how dbt helps bring it all together: + +- [Data modeling techniques for more modularity](https://www.getdbt.com/analytics-engineering/modular-data-modeling-technique/) +- [How we structure our dbt projects](https://docs.getdbt.com/guides/best-practices/how-we-structure/1-guide-overview) +- [How to audit your DAG](https://www.youtube.com/watch?v=5W6VrnHVkCA) +- [Refactoring legacy SQL to dbt](https://docs.getdbt.com/guides/getting-started/learning-more/refactoring-legacy-sql) diff --git a/website/docs/terms/data-extraction.md b/website/docs/terms/data-extraction.md new file mode 100644 index 00000000000..9a53562c97f --- /dev/null +++ b/website/docs/terms/data-extraction.md @@ -0,0 +1,78 @@ +--- +id: data-extraction +title: Data extraction +description: Data extraction is the process by which data is retrieved from multiple sources, often varying in volume and structure. +displayText: data extraction +hoverSnippet: Data extraction is the process by which data is retrieved from multiple sources, often varying in volume and structure. +--- + + + Data extraction: The first step of the ELT process + + +There is no data work without data. So how do data teams get the data they need? Data extraction is the process by which data is retrieved from multiple sources, often varying in volume and structure. Most data extraction processes are followed by a loading process, where that extracted data is loaded into a central . + +To actually extract said data, teams will often rely on various [ETL tools](https://docs.getdbt.com/terms/elt#elt-tools) or create custom scripts to call API endpoints. Other times data teams may be forced to do some hacky work like manually making and dropping a CSV into an S3 bucket. Definitely a rarity. But not unheard of. + +Come take a deep dive into data extraction, the process that allows us data folk to actually play with, well, said data. + +## Data extraction process: How does it work? + +There are two primary ways modern data teams are using to extract data: tools and custom scripts. + +- **Extraction via ETL tools**: SaaS ETL tools like Fivetran, Airbyte, and more, allow data folks to select connectors or data sources and sync their required data directly to their data warehouses. These platforms reduce the need to write custom API calls to data sources and instead allow data folks to worry more on transforming their data when it hits their data warehouse. +- **Extraction via custom scripts**: It’s probably inevitable, but at one point, you’re likely to find yourself hacking together a Python script to make API calls to a data source that doesn’t have a connector in an ETL tool. But let’s be real: while this is intimidating, it isn’t the end of the world. Writing and maintaining custom scripts for extracting data from data source APIs is not the most fun and there are real concerns (API limits, access tokens, lack of documentation, changing APIs, writing to external storage or directly to your data warehouse) to look out for, but gear up, read up on some basic curl requests and Python, and you got this. + +These two methods above are for automated extraction, processes that you only need to run once (in theory) to get the data you need on a regular basis. For non-automated processes, such as one-time extractions or uploads to your data warehouse, data folks can upload their data to external storage, such as S3 buckets, to load to your data warehouse, or leverage [dbt seeds](https://docs.getdbt.com/docs/building-a-dbt-project/seeds). + +## Commonly extracted data + +Obviously, the type of business you work for and the systems your team uses will determine the data you extract. However, there are usually some common sources that data teams will extract for business users: +- Ad platforms such as Facebook Ads, Google Ads, or Pinterest Ads +- Accounting softwares like Netsuite +- Sales CRMs such as Salesforce or HubSpot +- Backend application databases +- Customer service SaaS products like Zendesk or Kustomer + +The data that is typically extracted and loaded in your data warehouse is data that business users will need for baseline reporting, OKR measurement, or other analytics. + +:::tip Don’t fix what’s not broken +As we just said, there are usually common data sources that data teams will extract from, regardless of business. Instead of writing transformations for these tables and data sources, leverage [dbt packages](https://hub.getdbt.com/) to save yourself some carpal tunnel and use the work someone else has already done for you :) +::: + +## Data extraction tools + +If you’re not writing your own extraction scripts, you’re likely using an [ELT tool](https://docs.getdbt.com/terms/elt#elt-tools) to help you extract and load your various data sources into your data warehouse. Below, you’ll find some commonly used tools to help you do just that. + +| Tool | Description | Open source option? | +|:---:|:---:|:---:| +| Airbyte | Airbyte is an open-source and cloud service that allows teams to create data extraction and load pipelines. | ✅ | +| Stitch by Talend | Stitch (part of Talend) is another SaaS product that has many data connectors to extract data and load it into data warehouses. | ❌ | +| Fivetran/HVR | Fivetran is a SaaS company that helps data teams extract, load, and perform some transformation on their data. Fivetran easily integrates with modern data warehouses and dbt. They also offer transformations that leverage dbt Core. | ❌ | +| Funnel | Funnel is another product that can extract and load data. Funnel’s data connectors are primarily focused around marketing data sources. | ❌ | + +## Data extraction challenges to look out for + +There are definitely some considerable considerations in data extraction, mainly around costs and viability. + +- **Cadence and costs**: How often does your data need to be synced or refreshed? How often will your stakeholders really be looking at the data? There can be considerable costs to hitting API endpoints or retrieving data via ELT tools depending on the cadence you set for your data extractions. Talk to your stakeholders, understand when folks would leverage fresher data, and run some basic cost-benefit analyses to understand the cadence that works for your data extractions. +- **Viability**: Can you even extract the data your stakeholders need? As analytics engineers, your initial reaction is to check if an ETL tool has an existing connector for it. If it doesn’t, you may have to whip up a script to call the API (if there is one). If there is no API available, well, then it’s time to put on your creativity hat and get hacky! +- **PII concerns**: Oftentimes, data teams may be interested in masking PII data before it even hits their data warehouse. This would involve masking or removing the PII data immediately after extraction and immediately prior to loading the data into your data warehouse. For folks that want to mask PII, but are okay with masking it once it’s in their data warehouse, data teams can create masking policies using dbt packages. +- **Data accuracy**: This is less of a concern for data extracted via ETL tools or custom scripts, but for internal sources, such as static CSV files manually input by someone on your marketing team, you’re going to want to ensure that data is accurate (ideally before it hits your data warehouse). Not the end of the world if it does, but more of a nuisance than anything and something to look out for. + +:::tip Testing your data sources +Using dbt, data folks can run automated tests on their raw data that is loaded into their data warehouse via [sources](https://docs.getdbt.com/docs/building-a-dbt-project/using-sources). +::: + +## Conclusion + +Having no data extraction is the equivalent of a conductor not having an orchestra at their disposal: sad. Overall, data extraction in analytics engineering is the process of extracting data, usually via an automated ETL tool or script, for data sources that will later be loaded into a central data warehouse. There are some considerations to look at prior to the data extraction process, such as cost, viability, and PII concerns. + +## Further reading + +Ready to take a deeper dive into all things data extraction, ELT and dbt? Check out some of our favorite resources below: + +- [Glossary: ELT](https://docs.getdbt.com/terms/elt) +- [Glossary: ETL](https://docs.getdbt.com/terms/etl) +- [Four questions to help accurately scope analytics engineering projects](https://www.getdbt.com/blog/4-questions-to-help-you-more-accurately-scope-analytics-engineering-projects/) +- [Five principles that will keep your data warehouse organized](https://www.getdbt.com/blog/five-principles-that-will-keep-your-data-warehouse-organized/) diff --git a/website/docs/terms/data-lineage.md b/website/docs/terms/data-lineage.md new file mode 100644 index 00000000000..41b6b4426f4 --- /dev/null +++ b/website/docs/terms/data-lineage.md @@ -0,0 +1,116 @@ +--- +id: data-lineage +title: Data lineage +description: Data lineage provides a holistic view of how data moves through an organization, where it’s transformed and consumed. +displayText: data lineage +hoverSnippet: Data lineage provides a holistic view of how data moves through an organization, where it’s transformed and consumed. +--- + + + Data lineage: What it is and how to automate it - dbt Labs + + +Data lineage provides a holistic view of how data moves through an organization, where it’s transformed and consumed. Overall, data lineage is a fundamental concept to understand in the practice of analytics engineering and modern data work. + +At a high level, a data lineage system typically provides data teams and consumers with one or both of the following resources: + +- A visual graph (DAG) of sequential workflows at the data set or column level +- A data catalog of data asset origins, owners, definitions, and policies + +This holistic view of the data pipeline allows data teams to build, troubleshoot, and analyze workflows more efficiently. It also enables business users to understand the origins of reporting data and provides a means for data discovery. + +We’ll unpack why data lineage is important, how it works in the context of analytics engineering, and where some existing challenges still exist for data lineage. + +## **Why is data lineage important?** + +As a data landscape grows in size and complexity, the benefits of data lineage become more apparent. For data teams, the three main advantages of data lineage include reducing root-cause analysis headaches, minimizing unexpected downstream headaches when making upstream changes, and empowering business users. + +### **Root cause analysis** + +It happens: dashboards and reporting fall victim to data pipeline breaks. Data teams quickly need to diagnose what’s wrong, fix where things may be broken, and provide up-to-date numbers to their end business users. But when these breaks happen (and they surely do) how can teams quickly identify the root cause of the problem? + +If data teams have some form of data lineage in place, they can more easily identify the root cause of the broken pipeline or data quality issue. By backing out into the data models, sources, and pipelines powering a dashboard a report, data teams can understand all the upstream elements impacting that work and see where the issues lie. + +Will a data lineage or a DAG solve your breaking pipelines? Definitely not. Will it potentially make your life easier to find problems in your data work? Heck yes. + +### **Downstream impacts on upstream changes** + +You may have been here—your backend engineering team drops the `customers` table to create a newer, more accurate `users` table. The only bad thing is…[they forgot to tell the data team about the change](https://docs.getdbt.com/blog/when-backend-devs-spark-joy). + +When you have a data lineage system, you can visually see which downstream models, nodes, and exposures are impacted by big upstream changes such as source or model renaming or removals. Referring to your DAG or data lineage system before any significant change to your analytics work is a great way to help prevent accidental downstream issues. + +### **Value to business users** + +While data lineage makes it easier for data teams to manage pipelines, stakeholders and leaders also benefit from data lineage, primarily around promoting data transparency into the data pipelines. + +**Shared data literacy** + +New hires, existing team members, and internal data practitioners can independently explore a holistic view of the data pipeline with a data lineage system. For data teams using a DAG to encapsulate their data work, business users have a clear visual representation of how data flows from different sources to the dashboards they consume in their BI tool, providing an increased level of transparency in data work. At the end of the day, the added visibility makes it easier for everyone to be on the same page. + +**Pipeline cleanliness** + +A visual graph (DAG) of how data flows through various workflows makes it easy to identify redundant loads of source system data or workflows that produce identical reporting insights. + +Spotlighting redundant data models can help trim down on WET (write every time/write everything twice) code, non-performant joins, and ultimately help promote reusability, modularity, and standardization within a data pipeline. + +Overall, data lineage and data-driven business go hand-in-hand. A data lineage system allows data teams to be more organized and efficient, business users to be more confident, and data pipelines to be more modular. + +## **How does data lineage work?** + +In the greater data world, you may often hear of data lineage systems based on tagging, patterns or parsing-based systems. In analytics engineering however, you’ll often see data lineage implemented in a DAG or through third-party tooling that integrates into your data pipeline. + +### **DAGs (directed acyclic graphs)** + +If you use a transformation tool such as dbt that automatically infers relationships between data sources and models, a DAG automatically populates to show you the lineage that exists for your data transformations. + + + +Your DAG is used to visually show upstream dependencies, the nodes that must come before a current model, and downstream relationships, the work that is impacted by the current model. DAGs are also directional—they show a defined flow of movement and form non-cyclical loops. + +Ultimately, DAGs are an effective way to see relationships between data sources, models, and dashboards. DAGs are also a great way to see visual bottlenecks, or inefficiencies in your data work (see image below for a DAG with...many bottlenecks). Data teams can additionally add [meta fields](https://docs.getdbt.com/reference/resource-configs/meta) and documentation to nodes in the DAG to add an additional layer of governance to their dbt project. + + + +:::tip Automatic > Manual + +DAGs shouldn’t be dependent on manual updates. Instead, your DAG should be automatically inferred and created with your data transformation and pipelines. Leverage tools such as dbt to build your own version-controlled DAG as you develop your data models. + +::: + +### **Third-party tooling** + +Data teams may also choose to use third-party tools  with  lineage capabilities such as [Atlan](https://ask.atlan.com/hc/en-us/articles/4433673207313-How-to-set-up-dbt-Cloud), Alation, [Collibra](https://marketplace.collibra.com/listings/dbt-lineage-to-collibra-integration/), Metaphor, [Monte Carlo](https://docs.getmontecarlo.com/docs/dbt-cloud) or [Select Star](https://docs.selectstar.com/integrations/dbt/dbt-cloud). These tools often integrate directly with your data pipelines and dbt workflows and offer zoomed-in data lineage capabilities such as column-level or business logic-level lineage. + +## **The challenges of data lineage** + +The biggest challenges around data lineage become more apparent as your data, systems, and business questions grow. + +### **Scaling data pipelines** + +As dbt projects scale with data and organization growth, the number of sources, models, macros, seeds, and [exposures](https://docs.getdbt.com/docs/building-a-dbt-project/exposures) invariably grow. And with an increasing number of nodes in your DAG, it can become harder to audit your DAG for WET code or inefficiencies. + +Working with dbt projects with thousands of models and nodes can feel overwhelming, but remember: your DAG and data lineage are meant to help you, not be your enemy. Tackle DAG audits in chunks, document all models, and [leverage strong structure conventions](https://docs.getdbt.com/guides/best-practices/how-we-structure/1-guide-overview). + +:::tip dbt project evaluator + +Is your DAG keeping up with best practices? Instead of manually auditing your DAG, the [dbt project evaluator package](https://github.com/dbt-labs/dbt-project-evaluator) can help audit your project and find areas of improvement. + +::: + +### **Column-level lineage** + +Complex workflows also add to the difficulties a data lineage system will encounter. For example, consider the challenges in describing a data source's movement through a pipeline as it's filtered, pivoted, and joined with other tables. These challenges increase when the granularity of the data lineage shifts from the table to the column level. + +As data lineage graphs mature and grow, it becomes clear that column or field-level lineage is often a needed layer of specificity that is not typically built-in to data lineage systems. [Some of the third party tooling](#third---party-tooling) from above can support column-level lineage. + +## **Conclusion** + +Data lineage is the holistic overview of how data moves through an organization or system, and is typically represented by a DAG. Analytics engineering practitioners use their DAG and data lineage to unpack root causes in broken pipelines, audit their models for inefficiencies, and promote greater transparency in their data work to business users. Overall, using your data lineage and DAG to know when your data is transformed and where it’s consumed is the foundation for good analytics work. + +## **Further reading** + +DAGs, data lineage, and root cause analysis…tell me more! Check out some of our favorite resources of writing modular models, DRY code, and data modeling best practices: + +- [Glossary: DRY](https://docs.getdbt.com/terms/dry) +- [Data techniques for modularity](https://www.getdbt.com/analytics-engineering/modular-data-modeling-technique/) +- [How we structure our dbt projects](https://docs.getdbt.com/guides/best-practices/how-we-structure/1-guide-overview) \ No newline at end of file diff --git a/website/docs/terms/data-warehouse.md b/website/docs/terms/data-warehouse.md new file mode 100644 index 00000000000..2c64fbaa7b7 --- /dev/null +++ b/website/docs/terms/data-warehouse.md @@ -0,0 +1,89 @@ +--- +id: data-warehouse +title: Data warehouse +description: How have data warehouses evolved over the last 40 years? Explore the nuanced changes in use case since Inmon first coined the term. +displayText: data warehouse +hoverSnippet: A data warehouse is a data management system used for data storage and computing that allows for analytics activities such as transforming and sharing data. +--- + + + Data warehouses in the modern data stack - dbt Labs + + +A data warehouse is a data management system used for data storage and computing that allows for analytics activities such as transforming and sharing data. It helps businesses to capture and store data from external sources. Analytics engineers and data analysts use it to query datasets using SQL, helping to transform them into powerful data models and reports. Data warehouses are the central source of truth for any modern data stack. Data is ingested, transformed, and shared to other tools from the warehouse. + +There are two main types of data warehouses — on-prem warehouses and cloud warehouses. An on-prem data warehouse is a physical location where companies need to maintain hardware and software in order to store data. A cloud data warehouse is available anywhere and doesn’t include a physical location that you need to access. In this arrangement, you pay to use the storage space and compute power that is provided and maintained by another company. + +## History of data warehouses + +While data has been stored throughout history, it wasn’t until the 1980s that technology began to accelerate and the first official data warehouse was created. It was an on-prem warehouse consisting of a lot of computer processing and storage towers, taking up a lot of space. As you can imagine, this caused a lot of problems. It not only took up a lot of physical space, but employees had to maintain the hardware and software of these warehouses. This quickly became expensive and unrealistic for smaller companies without the budget or space. + +When Amazon began scaling their on-prem data warehouses to support their business, they noticed an opportunity to sell compute capacity to other businesses in order to save costs. This is when Redshift, Amazon’s cloud data warehouse product, came to be. Shortly after, other tech giants like Google and Microsoft who were also building data infrastructure followed suit. + +Now, you can be anywhere and access the power of an online warehouse. You no longer need to maintain the infrastructure yourself but can pay a company to do this for you. This is cheaper and allows for faster data capabilities. + + +## Why businesses need data warehouses + +Data warehouses were once unrealistic due to the costs associated with them. Now that cloud warehouses make them available to nearly everyone, they have a plethora of benefits to offer businesses. Cloud warehouses allow for scalability, availability, cost savings, and increased security- all of which are handled by the provider themself. + +### Scalability + +Data warehouses allow you to scale computing up or down depending on how fast you need your transformations to run and how much you are willing to spend. You can turn computing resources on or off as well in order to save on costs. + +### Availability + +Data warehouses are always available. While latency may vary based on source and destination locations, your data can be accessed anywhere, at any time. This is ideal for the remote culture that we are currently living in, where anyone can work from anywhere. + +### Cost savings + +Because you no longer need to maintain all of the infrastructure, you can save on costs related to maintenance. Because the data warehouse companies manage so much data, they are able to unlock cost-savings that you wouldn’t be able to otherwise. + +### Security + +Data warehouses offer advanced security features that ensure your data is always secure. They often directly handle certain compliance strategies needed with healthcare and financial data, eliminating the need for you to do this yourself. They also have features such as roles and users which help you control who has access to your data. But we will get into this more later. + +## Potential business use cases + +Businesses can leverage data warehouses for many different reasons. Most of these reasons end up savings time and money for the business, whether directly or indirectly. + +### Consolidating all of your data in one place + +First, a data warehouse acts as a single source of truth for all of your data. Rather than having all of your data spread across different platforms, it is available to you in one place. This allows you to standardize all of your core metrics and data definitions, rather than depending on the metrics calculated by platforms like Google and Facebook. If you find that different metrics don’t align across platforms, a data warehouse acts as a dependable source for the right metric. Rather than relying on external platforms, you now have one that centralizes all of your data. + +Not to mention, you will save your analytics engineer and data analyst a few headaches. They would otherwise have to manually pull needed data from various sources. Not having a single source of truth decreases your data quality, wastes your data team’s precious time, and makes it difficult to combine data from different sources. + +### Ability to control who has access and the type of access they have + +Data warehouses have extensive security features which allow you to control who has access to what. You have the ability to give someone as little or extensive permissions as you wish. Warehouses give you the ability to create users and assign them roles. Each role has its own set of permissions to which databases and tables it can see. Then, you can also choose who is allowed to query those tables or even update and delete them. + +When anyone in your organization can easily access your data, bad things can happen. You risk the potential of important data being deleted, incorrectly edited, or inappropriately accessed. Data warehouses users, roles, policies, and security measures can help ensure data is in the right hands of the right people. + +### Fast reporting + +Because all of your data is located in the same place, it allows for faster reporting compared to pulling data from many different sources. A central location allows for you to quickly access and query millions of rows of data, allowing transformations and reporting to be done much faster. + +## Data platforms that support data warehousing workloads + +| **Data platform** | **Description** | +|---|---| +| Snowflake | Snowflake is a fully-managed platform for data warehousing, data lakes, data engineering, data science, and data application development. | +| Databricks | Databricks is a cloud-based collaborative data science, data engineering, and data analytics platform that combines the best of data warehouses and data lakes into a lakehouse architecture. | +| Google BigQuery | Google BigQuery is a serverless, highly scalable data warehouse that comes with a built-in query engine. | +| Amazon Redshift | Amazon Redshift is a fully-managed petabyte-scale cloud-based data warehouse designed for large scale data set storage and analysis. | +| Postgres | PostgreSQL is an advanced, enterprise class open source relational database that supports both SQL (relational) and (non-relational) querying. | + +## Data warehouse vs data lake + +A data lake is a system where you store, process, and query unstructured, semi-structured, and structured data at almost any scale. The main difference between a data warehouse and a data lake is the type and way data is stored. Data warehouses contain structured data that is meant to organize data for analytics use. Data lakes can contain pretty much any kind of data—structured or unstructured—and data is usually left it its raw format until it's ready to use. Compare that to data warehouses, whose primary goal is to be a place for data teams to store both raw and transformed, usable data. + +## Conclusion + +Data warehouses have come a long way [in the last 40 years](https://www.getdbt.com/blog/future-of-the-modern-data-stack/). They began as a physical location with huge costs associated with them to a system available to anyone, anywhere at an affordable cost. They have the power to centralize all of your business’s data, allowing for faster analytics operations, standardized KPIs, and a single source of truth. All businesses need a data warehouse in order to operate quickly and efficiently with data that they can rely on. The question isn’t whether or not you need a data warehouse, but which data warehouse you should choose. Make a list of the key features needed for your business and use that to assess the options above. + +## Additional reading + +- [Operational analytics](https://www.getdbt.com/analytics-engineering/use-cases/operational-analytics/) +- [Glossary: ETL](https://docs.getdbt.com/terms/etl/) +- [Glossary: ELT](https://docs.getdbt.com/terms/elt/) + diff --git a/website/docs/terms/dataframe.md b/website/docs/terms/dataframe.md new file mode 100644 index 00000000000..8981c8e4648 --- /dev/null +++ b/website/docs/terms/dataframe.md @@ -0,0 +1,107 @@ +--- +id: dataframe +title: DataFrame +description: A DataFrame is a way of storing and manipulating tabular data in Python. They gained popularity first as a part of R and then as a part of pandas. +displayText: dataframe +hoverSnippet: A DataFrame is a two-dimensional data structure (rows and columns). It's the most common way of representing and interacting with large datasets in Python. +--- + + What is a DataFrame in Python? - dbt Labs + + +A DataFrame is a way of storing and manipulating tabular data in Python. DataFrames are often likened to tables with columns and rows that you could find in any , Google Sheet, or Excel workbook. + +A DataFrame entry in an analytics engineering glossary…what is happening? You’re reading this right. While SQL is the go-to programming language for most analytics engineering work, there are likely inevitable situations where you've found yourself writing some Python and using DataFrames. + +While DataFrames are also used in other languages for data processing, such as R and Scala, the focus of this glossary page will be on Python DataFrames, their use cases, and their relation to analytics engineering work. + +## How DataFrames work + +DataFrames have a long history ([going back to 1990](https://towardsdatascience.com/preventing-the-death-of-the-dataframe-8bca1c0f83c8#:~:text=The%20earliest%20%E2%80%9Cdataframe%E2%80%9D%2C%20originally,Hastie%20in%201992%20%5B1%5D)!), but gained popularity first as a part of R and then as a part of [pandas](https://pandas.pydata.org/), an open source Python library of useful data analysis and manipulation tools. To work with DataFrames in Python, folks typically need to import the pandas library in the beginning of their script, `.py` file, or Python notebook with the conventional `import pandas as pd`. + +One of the strengths of DataFrames lies in its ability to take data in its original form (ex. array, list, , parquet, dictionary) and form a tabular (rows and columns) format out of it. Once this data is in a tabular format, you can apply functions and packages to that data to clean, transform, and enrich it. + +Below is an example creation of a Python DataFrame from a list and some light enrichment on it: + +```python +import pandas as pd + +def is_credit_card_purchase(x): + if x == 'credit_card': + return True + else: + return False + +jaffle_shop_orders = [[1, 1, 'credit_card', 1000], [2, 2, 'credit_card', 2000], [3,3, 'coupon', 100]] +orders_df = pd.DataFrame(jaffle_shop_orders, columns=['unique_id', 'order_id', 'payment_method', 'amount']) +orders_df.set_index(['unique_id'], inplace=True) +orders_df['is_credit_card'] = orders_df['payment_method'].apply(is_credit_card_purchase) + +print(orders_df) +``` + +This script will return an `orders_df` DataFrame that looks like this: + +| unique_id | order_id | payment_method | amount | is_credit_card | +|---|---|---|---|---| +| 1 | 1 | credit_card | 1000 | True +| 2 | 2 | credit_card | 2000 | True +| 3 | 3 | coupon | 100 | False + +:::info A note on Python flavors +If you’re running Python in Snowflake via Snowpark, you would typically be working with [Snowpark](https://docs.snowflake.com/en/developer-guide/snowpark/python/working-with-dataframes.html) or pandas DataFrames. For folks running Python from Google BigQuery or Databricks users, they can use both pandas or [PySpark DataFrames](https://docs.databricks.com/spark/latest/dataframes-datasets/introduction-to-dataframes-python.html). There might be slight syntax differences between the different Python flavors of Snowpark, PySpark, and pandas, but much of the functionality remains the same. +::: + +It's also possible and common practice to string together a number of DataFrame transformations. For example, if `df` represents a DataFrame containing one row per person living in the Eastern United States over the last decade, you can calculate the number of people living in Philadelphia each year: + +```python +df.filter("city == 'Philadelphia'") + .withColumn("population", count("name")) + .group_by("year") +``` + +In most distributed frameworks, these transformations are evaluated "lazily." Rather than performing each transformation, calculating its results, and storing those results, the framework develops a *plan* for how it *will* perform those calculations. When you want to *act* on the transformed DataFrame—see the top 10 results, or write it back to a table in the database—then the framework's optimizer calculates the most efficient way to deliver those results, based on all the steps you have defined. + +If you're familiar with SQL, you can think of a DataFrame like a `select` statement, and each new DataFrame operation as a separate . + +You can write a long SQL query containing many complex CTEs. When you run the query with `limit 10` to see a sample of its results, or create that query as a table in the database (what dbt does when it runs your model), the data warehouse optimizes your query and produces the results in the most efficient way possible. + +## DataFrame use cases + +You could probably write hundreds of pages on DataFrame use cases and examples, but at their core, DataFrames, *in the context of analytics engineering*, are often used to manipulate data outside of SQL capabilities, work with data during API extraction, and leverage data science and machine learning. + +### Enrichment and manipulation of data outside of SQL capabilities + +Let’s just say it: there’s a lot of things you can do in Python that could do in SQL and vice versa, but Python packages typically win out when it comes to data enrichment. A typical use case for Python DataFrames is the ability to apply Python libraries or functions to data in the DataFrame. + +In practice, this could look like applying an [IP parser](https://pypi.org/project/ipparser/) to an IP address column, using a package to determine whether a [date falls on a holiday](https://docs.getdbt.com/docs/building-a-dbt-project/building-models/python-models#using-pypi-packages), or leveraging [numpy](https://numpy.org/) for performant and complex mathematical computations. + +:::tip dbt x Python DataFrames +With v1.3, dbt now supports the use of beta [Python models in dbt](https://docs.getdbt.com/docs/building-a-dbt-project/building-models/python-models). What does this mean exactly? This means that Python-defined data transformations can be created and used in a dbt project in the same vein as a classic dbt SQL model. These Python models are incredibly new and the team is eagerly looking for feedback in how folks want to use and ritualize them. +::: + +### Manipulation of data during extraction and loading scripts + +It’s not the most pleasant of experiences, but as an analytics engineer, you’re going to find yourself writing a hacky Python script at one point to extract data from a system or API that doesn’t have an innate connector in an [ETL tool](https://docs.getdbt.com/terms/elt#elt-tools). + +As you unpack and unnest the JSON received from these API endpoints, you’ll likely use DataFrames to make your data (and life) a little easier to work with. We won’t go into great depth here since this probably won’t happen too often in your career as an analytics engineer, but it’s beneficial to understand the basics of DataFrames and working with [requests, JSON, and DataFrames](https://stackoverflow.com/questions/42518864/convert-json-data-from-request-into-pandas-dataframe). + +### Data science and machine learning + +If SQL is an analytics engineer’s oven, Python is a data scientist's stovetop. Data scientists and machine learning engineers often use Python and DataFrames to perform exploratory analysis, feature engineering and data preparation, and the application of models and algorithms on datasets. Understanding and using DataFrames is step 1 (of many steps) to becoming a data person that can create meaningful data science and machine learning models. + +All this data science and machine learning talk…“But, I’m an analytics engineer,” you say adamantly. One of the great, beautiful, and sometimes frustrating qualities about analytics engineers is their jack-of-all-trades-ness. You can transform data in your sleep, talk ROI and CPAs all day with your VP of marketing, and use git like you studied computer science in college—what can’t you do?? You’ve probably experimented with a predictive analytics model, some light forecasting, or sentiment analysis at one point in your data journey. You may not be interested in making the conversion to full-fledged data scientists or machine learning engineer, but enjoy a challenge from time to time. + +There’s a reason data warehouses and platforms like Snowflake, BigQuery, and Databricks are providing support for Python: because folks are asking for it. There are endless use cases for Python and DataFrames that fall outside of data science and machine learning work, but as you start working and feeling more comfortable in Python, you may be tempted to start experimenting with these different forms of data work. And the world’s your oyster, right? + +## Conclusion + +A DataFrame is a tabular data storage format in Python that is widely used across different roles in the data world. Since a DataFrame stores data in rows and columns, similar to how analytics engineers manipulate tables stored in data warehouses, data folks can transform, engineer, and enrich data in DataFrames using Python and Python packages. Analytics engineers may find themselves using DataFrames when they’re extracting data via APIs, enriching data with third-party packages, or experimenting with data science and machine learning models. + +## Further reading + +Are you ready to dip your toes in DataFrames, Python, and dbt? Check out some of the resources below to learn more about how dbt is embracing Python: + +- [Python models in dbt](https://docs.getdbt.com/docs/building-a-dbt-project/building-models/python-models) +- #beta-feedback-python-models Slack channel in the [dbt Community Slack](https://www.getdbt.com/community/join-the-community/) +- [Best practices for developing Python models in dbt discussion](https://github.com/dbt-labs/docs.getdbt.com/discussions/1811) \ No newline at end of file diff --git a/website/docs/terms/ddl.md b/website/docs/terms/ddl.md new file mode 100644 index 00000000000..c4324e75fa9 --- /dev/null +++ b/website/docs/terms/ddl.md @@ -0,0 +1,128 @@ +--- +id: ddl +title: DDL +description: Data Definition Language (DDL) is a group of SQL statements that you can execute to manage database objects, including tables, views, and more. +displayText: DDL +hoverSnippet: Data Definition Language (DDL) is a group of SQL statements that you can execute to manage database objects, including tables, views, and more. +--- + + + What is Data Definition Language (DDL) in SQL? + + +Data Definition Language (DDL) is a group of SQL statements that you can execute to manage database objects, including tables, views, and more. Using DDL statements, you can perform powerful commands in your database such as creating, modifying, and dropping objects. DDL commands are usually executed in a SQL browser or stored procedure. + +DDL is contrasted with Data Manipulation Language (DML) which is the SQL that is used to actually access and manipulate data in database objects. The majority of data analysts will rarely execute DDL commands and will do the majority of their work creating DML statements to model and analyze data. + +:::note Note +Data folks don’t typically write DDL [since dbt will do it for them](https://docs.getdbt.com/docs/about/overview#:~:text=dbt%20allows%20analysts%20avoid%20writing,dbt%20takes%20care%20of%20materialization.). +::: + +To be honest, DDL is definitely some of the drier content that exists out there in the greater data world. However, because DDL commands are often uncompromising and should be used with caution, it’s incredibly important to understand how they work and when they should be used. We hope you can use this page to learn about the basics, strengths, and limitations of DDL statements. + +## Types of DDL Statements + +DDL statements are used to create, drop, and manipulate objects in your database. They are often, but not always, unforgiving and irreversible. “With great power comes great responsibility,” is usually the first thing I think of before I execute a DDL command. We’ll highlight some of the primary DDL commands that are used by analytics engineers below. + +:::important Important +The syntax for DDL commands can be pretty database-specific. We are trying to make this glossary page as generic as possible, but please use the “Further Reading” section to see the specifics on how the following DDL commands would be implemented in your database of interest! +::: + +### ALTER + +Using the `ALTER` DDL command, you can change an object in your database that already exists. By "change", we specifically mean you can: + +- Add new, remove, and rename columns to views and tables +- Rename a view or table +- Modify the structure of a view or table +- And more! + +The generic syntax to use the ALTER command is as follows: + +```sql +ALTER ; +``` + +To alter a table’s column, you may do something like this: + +```sql +ALTER TABLE customers rename column last_name as last_initial; +``` + +In this example, you have to rename the `last_name` column [in jaffle_shop’s](https://github.com/dbt-labs/jaffle_shop) `customers` table to be called `last_initial`. + +### DROP + +The `DROP` command. Probably the most high-stakes DDL statement one can execute. One that should be used with the *utmost* of care. At its core, an executed `DROP` statement will remove that object from the . You can drop tables, views, schemas, databases, users, functions, and more. + +Some data warehouses such as Snowflake allow you to add restrictions to `DROP` statements to caution you about the impact of dropping a table, view, or schema before it’s actually dropped. In practice, we recommend you never drop raw source tables as they are often your baseline of truth. Your database user also usually needs the correct permissions to drop database objects. + +The syntax to use the `DROP` command is as follows: + +```sql +DROP ; +``` + +You can drop your `customer` table like this: + +```sql +DROP TABLE customers; +``` + +### CREATE + +With the `CREATE` statement, you can create new objects in your data warehouse. The most common objects created with this statement are tables, schemas, views, and functions. Unlike `DROP`, `ALTER`, and `TRUNCATE` commands, there’s little risk with running `CREATE` statements since you can always drop what you create. + +Creating tables and views with the `CREATE` command requires a strong understanding of how you want the data structured, including column name and data type. Using the `CREATE` command to establish tables and views can be laborious and repetitive, especially if the schema objects contain many columns, but is an effective way to create new objects in a database. After you create a table, you can use DML `INSERT` statements and/or a transformation tool such as dbt to actually get data in it. + +The generic syntax to use the `CREATE` command is as follows: + +```sql +CREATE ; +``` + +Creating a table using the `CREATE` statement may look a something like this: + +```sql +CREATE TABLE prod.jaffle_shop.jaffles ( + id varchar(255), + jaffle_name varchar(255) + created_at timestamp, + ingredients_list varchar(255), + is_active boolean +); +``` + +Note that you had to explicitly define column names and column data type here. *You must have a strong understanding of your data’s structure when using the CREATE command for tables and views.* + +### TRUNCATE + +The `TRUNCATE` command will remove all rows from a table while maintaining the underlying table structure. The `TRUNCATE` command is only applicable for table objects in a database. Unlike `DROP` statements, `TRUNCATE` statements don’t remove the actual table from the database, just the data stored in them. + +The syntax to use the `TRUNCATE` command is as follows: + +```sql +TRUNCATE TABLE ; +``` + +You can truncate your jaffle_shop’s `payments` table by executing this statement: + +```sql +TRUNCATE TABLE payments; +``` + +Previously, this table was 113 rows. After executing this statement, the table is still in your database, but now has zero rows. + +## Conclusion + +DDL statements allow you to remove, edit, and add database objects. Some of the most common DDL statements you’ll execute include `CREATE`, `DROP`, `COMMENT`, `ALTER`, and more. DDL commands are typically executed in a SQL browser or stored procedure. Ultimately, DDL commands are all-powerful and potentially high-risk and should be used with the greatest of care. In the case of DDL, **do not** throw caution to the wind… + +## Further reading + +For database-specific DDL resources, check out the following: + +- [DDL commands in Snowflake](https://docs.snowflake.com/en/sql-reference/sql-ddl-summary.html) +- [SQL commands in Amazon Redshift](https://docs.aws.amazon.com/redshift/latest/dg/c_SQL_commands.html) (contains DDL) +- [DDL statements in Google BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language) +- [DDL statements in Databricks](https://docs.databricks.com/sql/language-manual/index.html#ddl-statements) +- [DDL in Amazon Athena](https://docs.aws.amazon.com/athena/latest/ug/language-reference.html) diff --git a/website/docs/terms/dimensional-modeling.md b/website/docs/terms/dimensional-modeling.md new file mode 100644 index 00000000000..f54f601b7d3 --- /dev/null +++ b/website/docs/terms/dimensional-modeling.md @@ -0,0 +1,159 @@ +--- +id: dimensional-modeling +title: Dimensional modeling +description: Dimensional modeling is a data modeling technique where you break data up into “facts” and “dimensions” to organize and describe entities in your data warehouse +displayText: dimensional modeling +hoverSnippet: Dimensional modeling is a data modeling technique where you break data up into “facts” and “dimensions” to organize and describe entities within your data warehouse. +--- + + + Dimensional modeling: An essential concept in data modeling + + +Dimensional modeling is a data modeling technique where you break data up into “facts” and “dimensions” to organize and describe entities within your data warehouse. The result is a staging layer in the data warehouse that cleans and organizes the data into the business end of the warehouse that is more accessible to data consumers. + +By breaking your data down into clearly defined and organized entities, your consumers can make sense of what that data is, what it’s used for, and how to join it with new or additional data. Ultimately, using dimensional modeling for your data can help create the appropriate layer of models to expose in an end business intelligence (BI) tool. + +There are a few different methodologies for dimensional modeling that have evolved over the years. The big hitters are the Kimball methodology and the Inmon methodology. Ralph Kimball’s work formed much of the foundation for how data teams approached data management and data modeling. Here, we’ll focus on dimensional modeling from Kimball’s perspective—why it exists, where it drives value for teams, and how it’s evolved in recent years. + +## What are we trying to do here? + +Let’s take a step back for a second and ask ourselves: why should you read this glossary page? What are you trying to accomplish with dimensional modeling and data modeling in general? Why have you taken up this rewarding, but challenging career? Why are *you* here? + +This may come as a surprise to you, but we’re not trying to build a top-notch foundation for analytics—we’re actually trying to build a bakery. + +Not the answer you expected? Well, let’s open up our minds a bit and explore this analogy. + +If you run a bakery (and we’d be interested in seeing the data person + baker venn diagram), you may not realize you’re doing a form of dimensional modeling. What’s the final output from a bakery? It’s that glittering, glass display of delicious-looking cupcakes, cakes, cookies, and everything in between. But a cupcake just didn’t magically appear in the display case! Raw ingredients went through a rigorous process of preparation, mixing, melting, and baking before they got there. + +Just as eating raw flour isn’t that appetizing, neither is deriving insights from raw data since it rarely has a nice structure that makes it poised for analytics. There’s some considerable work that’s needed to organize data and make it usable for business users. + +This is where dimensional modeling comes into play; it’s a method that can help data folks create meaningful entities (cupcakes and cookies) to live inside their [data mart](https://docs.getdbt.com/guides/best-practices/how-we-structure/4-marts) (your glass display) and eventually use for business intelligence purposes (eating said cookies). + +So I guess we take it back—you’re not just trying to build a bakery, you’re also trying to build a top-notch foundation for meaningful analytics. Dimensional modeling can be a method to get you part of the way there. + +## Facts vs. dimensions + +The ultimate goal of dimensional modeling is to be able to categorize your data into their fact or dimension models, making them the key components to understand. So what are these components? + +### Facts + +A fact is a collection of information that typically refers to an action, event, or result of a business process. As such, people typically liken facts to verbs. In terms of a real business, some facts may look like account creations, payments, or emails sent. + +It’s important to note that fact tables act as a historical record of those actions. You should almost never overwrite that data when it needs updating. Instead, you add new data as additional rows onto that table. + +For many businesses, marketing and finance teams need to understand all the touchpoints leading up to a sale or conversion. A fact table for a scenario like this might look like a `fct_account_touchpoints` table: + +| **unique_id** | **touchpoint_id** | **account_id** | **touchpoint_name** | **touchpoint_created_at_utc** | +|---|---|---|---|---| +| 23534 | 34 | 325611 | fall_convention_2020 | 2022-01-30 00:11:26 | +| 12312 | 29 | 325611 | demo_1 | 2022-05-29 01:42:07 | +| 66782 | 67 | 325611 | demo_2 | 2022-06-25 04:10:32 | +| 85311 | 15 | 105697 | fall_convention_2020 | 2022-05-29 06:13:45 | + +Accounts may have many touch points and this table acts as a true log of events leading up to an account conversion. + +This table is great and all for helping understanding what might have led to a conversion or account creation, but what if business users need additional context on these accounts or touchpoints? That’s where dimensions come into play. + +### Dimensions +A dimension is a collection of data that describe who or what took action or was affected by the action. Dimensions are typically likened to nouns. They add context to the stored events in fact tables. In terms of a business, some dimensions may look like users, accounts, customers, and invoices. + +A noun can take multiple actions or be affected by multiple actions. It’s important to call out: a noun doesn’t become a new thing whenever it does something. As such, when updating dimension tables, you should overwrite that data instead of duplicating them, like you would in a fact table. + +Following the example from above, a dimension table for this business would look like an `dim_accounts` table with some descriptors: + +| account_id | account_created_at_utc | account_name | account_status | billing_address | +|---|---|---|---|---| +| 325611 | 2022-06-29 12:11:43 | Not a Pyramid Scheme | active | 9999 Snake Oil Rd, Los Angeles, CA | +| 234332 | 2019-01-03 07:34:50 | Charlie’s Angels’ Chocolate Factory | inactive | 123 Wonka Way, Indianapolis, IN | +| 105697 | 2020-12-11 11:50:22 | Baggins Thievery | active | The Shire | + +In this table, each account only has one row. If an account’s name or status were to be updated, new values would overwrite existing records versus appending new rows. + +:::tip Snapshots +For fact tables you want to keep track of changes to, folks can leverage [dbt snapshots](https://docs.getdbt.com/docs/building-a-dbt-project/snapshots). +::: + +### Facts and dimensions at play with each other +Cool, you think you’ve got some facts and dimensions that can be used to qualify your business. There’s one big consideration left to think about: how do these facts and dimensions interact with each other? + +![Image of depicting how facts and dimensions join together to create analytics ready datasets](/img/docs/terms/dimensional-modeling/fact-star.png) + +Pre-cloud data warehouses, there were two dominant design options, star schemas and snowflake schemas, that were used to concretely separate out the lines between fact and dimension tables. + +- In a star schema, there’s one central fact table that can join to relevant dimension tables. +- A snowflake schema is simply an extension of a star schema; dimension tables link to other dimension tables making it form a snowflake-esque shape. + +It sounds really nice to have this clean setup with star or snowflake schemas. Almost as if it’s too good to be true (and it very well could be). + +The development of cheap cloud storage, BI tools great at handling joins, the evolution of SQL capabilities, and data analysts with growing skill sets have changed the way data folks use to look at dimensional modeling and star schemas. Wide tables consisting of fact and dimension tables joined together are now a competitive option for data teams. + +Below, we’ll dig more into the design process of dimensional modeling, wide tables, and the beautiful ambiguity of it all. + +## The dimensional modeling design process + +According to the Kimball Group, the official(™) four-step design process is (1) selecting a business process to analyze, (2) declaring the , (3) Identifying the dimensions, and (4) Identifying the facts. That makes dimensional modeling sound really easy, but in reality, it’s packed full of nuance. + +Coming back down to planet Earth, your design process is how you make decisions about: + +- Whether something should be a fact or a dimension +- Whether you should keep fact and dimension tables separate or create wide, joined tables + +This is something that data philosophers and thinkers could debate long after we’re all gone, but let’s explore some of the major questions to hold you over in the meantime. + +### Should this entity be a fact or dimension? + +Time to put on your consultant hat because that dreaded answer is coming: it depends. This is what makes dimensional modeling a challenge! + +Kimball would say that a fact must be numeric. The inconvenient truth is: an entity can be viewed as a fact or a dimension depending on the analysis you are trying to run. + +:::note Birds of a feather +If you ran a clinic, you would probably have a log of appointments by patient. At first, you could think of appointments as facts—they are, after all, events that happen and patients can have multiple appointments—and patients as dimensions. But what if your business team really cared about the appointment data itself—how well it went, when it happened, the duration of the visit. You could, in this scenario, make the case for treating this appointments table as a dimension table. If you cared more about looking at your data at a patient-level, it probably makes sense to keep appointments as facts and patients as dimensions. All this to say is that there’s inherent complexity in dimensional modeling, and it’s up to you to draw those lines and build those models. +::: + +So then, how do you know which is which if there aren’t any hard rules!? Life is a gray area, my friend. Get used to it. + +A general rule of thumb: go with your gut! If something feels like it should be a fact to meet your stakeholders' needs, then it’s a fact. If it feels like a dimension, it’s a dimension. The world is your oyster. If you find that you made the wrong decision down the road, (it’s usually) no big deal. You can remodel that data. Just remember: you’re not a surgeon. No one will die if you mess up (hopefully). So, just go with what feels right because you’re the expert on your data 👉😎👉 + +Also, this is why we have data teams. Dimensional modeling and data modeling is usually a collaborative effort; working with folks on your team to understand the data and stakeholder wants will ultimately lead to some rad data marts. + +### Should I make a wide table or keep them separate? + +Yet again, it depends. Don’t roll your eyes. Strap in for a quick history lesson because the answer to this harkens back to the very inception of dimensional modeling. + +Back in the day before cloud technology adoption was accessible and prolific, storing data was expensive and joining data was relatively cheap. Dimensional modeling came about as a solution to these issues. Separating collections of data into smaller, individual tables (star schema-esque) made the data cheaper to store and easier to understand. So, individual tables were the thing to do back then. + +Things are different today. Cloud storage costs have gotten really inexpensive. Instead, computing is the primary cost driver. Now, keeping all of your tables separate can be expensive because every time you join those tables, you’re spending usage credits. + +Should you just add everything to one, wide table? No. One table will never rule them all. Knowing whether something should be its own fact table or get added on to an existing table generally comes down to understanding who will be your primary end consumers. + +For end business users who are writing their own SQL, feel comfortable performing joins, or use a tool that joins tables for them, keeping your data as separate fact and dimension tables is pretty on-par. In this setup, these users have the freedom and flexibility to join and explore as they please. + +If your end data consumers are less comfortable with SQL and your BI tool doesn’t handle joins well, you should consider joining several fact and dimension tables into wide tables. Another consideration: these wide, heavily joined tables can tend to wind up pretty specialized and specific to business departments. Would these types of wide tables be helpful for you, your data team, and your business users? Well, that’s for you to unpack. + +## Advantages and disadvantages of dimensional modeling + +The benefits and drawbacks of dimensional modeling are pretty straightforward. Generally, the main advantages can be boiled down to: + +* **More accessibility**: Since the output of good dimensional modeling is a [data mart](https://docs.getdbt.com/guides/best-practices/how-we-structure/4-marts), the tables created are easier to understand and more accessible to end consumers. +* **More flexibility**: Easy to slice, dice, filter, and view your data in whatever way suits your purpose. +* **Performance**: Fact and dimension models are typically materialized as tables or [incremental models](https://docs.getdbt.com/docs/building-a-dbt-project/building-models/configuring-incremental-models). Since these often form the core understanding of a business, they are queried often. Materializing them as tables allows them to be more performant in downstream BI platforms. + +The disadvantages include: +* **Navigating ambiguity**: You need to rely on your understanding of your data and stakeholder wants to model your data in a comprehensible and useful way. What you know about your data and what people really need out of the data are two of the most fundamental and difficult things to understand and balance as a data person. +* **Utility limited by your BI tool**: Some BI tools don’t handle joins well, which can make queries from separated fact and dimensional tables painful. Other tools have long query times, which can make querying from ultra-wide tables not fun. + +## Conclusion + +Dimensional data modeling is a data modeling technique that allows you to organize your data into distinct entities that can be mixed and matched in many ways. That can give your stakeholders a lot of flexibility. [While the exact methodologies have changed](https://www.getdbt.com/analytics-engineering/modular-data-modeling-technique/)—and will continue to, the philosophical principle of having tables that are sources of truth and tables that describe them will continue to be important in the work of analytics engineering practitioners. + + +## Additional Reading + +Dimensional modeling is a tough, complex, and opinionated topic in the data world. Below you’ll find some additional resources that may help you identify the data modeling approach that works best for you, your data team, and your end business users: + + + +* [Modular data modeling techniques](https://www.getdbt.com/analytics-engineering/modular-data-modeling-technique/) +* [Stakeholder-friendly model naming conventions](https://docs.getdbt.com/blog/stakeholder-friendly-model-names/) +* [How we structure our dbt projects guide](https://docs.getdbt.com/guides/best-practices/how-we-structure/1-guide-overview) diff --git a/website/docs/terms/dml.md b/website/docs/terms/dml.md new file mode 100644 index 00000000000..fb8a0f6d610 --- /dev/null +++ b/website/docs/terms/dml.md @@ -0,0 +1,107 @@ +--- +id: dml +title: DML +description: Data Manipulation Language (DML) is a class of SQL statements that are used to query, edit, add and delete row-level data from database tables or views. +displayText: DML +hoverSnippet: Data Manipulation Language (DML) is a class of SQL statements that are used to query, edit, add and delete row-level data from database tables or views. The main DML statements are SELECT, INSERT, DELETE, and UPDATE. +--- + + + DML: The SQL statements that make the data world go 'round + + +Data Manipulation Language (DML) is a class of SQL statements that are used to query, edit, add and delete row-level data from database tables or views. The main DML statements are `SELECT`, `INSERT`, `DELETE`, and `UPDATE`. + +DML is contrasted with Data Definition Language (DDL) which is a series of SQL statements that you can use to edit and manipulate the *structure* of databases and the objects in them. + +Similar to DDL, DML can be a *tad* bit boring. However, DML statements are what allows analysts and analytics engineers to do their work. We hope you can use this glossary to understand when and why DML statements are used and how they may contrast with similar DDL commands. + + +## Types of DML Statements + +The primary DML statements are `SELECT`, `INSERT`, `DELETE`, and `UPDATE`. With the exception of `SELECT` statements, all of the others are only applicable to data within tables in a database. The primary difference between `SELECT` and all the other DML statements is its impact to row-level data: + +- To *change* the actual data that lives in tables, use `INSERT`, `DELETE`, and `UPDATE` statements +- To *access* the data in databse object, use `SELECT` statements + +:::important Important +For the most part, the syntax for DML statements are pretty universal across [Supported Data Platforms](https://docs.getdbt.com/docs/supported-data-platforms) including Google Bigquery, Databricks, Postgres, Amazon Redshift, and Snowflake. Regardless, please use the “Further Reading” section to see the specifics on how the following DML statements would be implemented in your database of interest! +::: + +### SELECT + +Ah, our favorite of DML statements! This is the SQL we all know and love (most of the time). Because the `SELECT` statement allows you to access and manipulate data that exists in database objects, it makes it the true powerhouse in data analysis and analytics engineering. + +You write `SELECT` statements to create queries that build data models and perform robust analysis. With `SELECT` statements, you can join different views and tables, qualify data by setting filters, apply functions and operators on the data, and more. `SELECT` statements, unlike `INSERT`, `DELETE`, and `UPDATE`, don’t actually change the row-level value stored in the tables/views. Instead, you write `SELECT` statements to express the business logic needed to perform analysis. + +All `SELECT` statements need three elements: a `SELECT` clause in the beginning, the actual field selection and manipulation, and a `FROM` statement which is specifying which database object you’re trying to access. + +Here’s an example `SELECT` statement: + +```sql +select + + payment_method, + sum(amount) AS amount + +from {{ ref('raw_payments') }} +group by 1 +``` + +In this example, your selection of the `payment_method` column and summation of the `amount` column is the meat of your query. The `from {{ ref('raw_payments') }}` specifies the actual table you want to do the selecting from. + +### INSERT + +Using the `INSERT` DML command, you can add rows to a table that exists in your database. To be honest, data folks are rarely inserting data into tables manually with the `INSERT` command. Instead, data team members will most often use data that’s already been inserted by an tool or other data ingestion process. + +You can insert a record [in jaffle_shop’s](https://github.com/dbt-labs/jaffle_shop) `raw_customers` table like this: + +```sql +INSERT INTO raw_customers VALUES (101, 'Kira', 'F.'); +``` + +As you can see from this example, you clearly set all the column values that exist in your `raw_customers` table. For `INSERT` statements, you can explicitly specify the values you want to insert or use a query result to set the column values. + +### DELETE + +The `DELETE` command will remove rows in an existing table in your database. In practice, you will usually specify a `WHERE` clause with your `DELETE` statement to only remove specific rows from a table. But, you shouldn't really ever delete rows from tables. Instead, you should apply filters on queries themselves to remove rows from your modeling or analysis. + +For the most part, if you wanted to remove all existing rows in a table, but keep the underlying table structure, you would use the `TRUNCATE` DDL command. If you wanted to remove all rows and drop the entire table, you could use the `DROP` DDL command. + +You can delete the record for any Henry W. in jaffle_shop’s `customers` table by executing this statement: + +```sql +DELETE FROM customers WHERE first_name = 'Henry' AND last_name = 'W.'; +``` + +### UPDATE + +With the `UPDATE` statement, you can change the actual data in existing rows in a table. Unlike the `ALTER` DDL command that changes the underlying structure or naming of database objects, the `UPDATE` statement will alter the actual row-level data. You can qualify an `UPDATE` command with a `WHERE` statement to change the values of columns of only specific rows. + +You can manually update the status column of an order in your orders table like this: + +```sql +UPDATE orders SET status = 'returned' WHERE order_id = 7; +``` + +:::tip Tip +The `UPDATE` statement is often compared to the `MERGE` statement. With `MERGE` statements, you can insert, update, *and* delete records in a single command. Merges are often utilized when there is data between two tables that needs to be reconciled or updated. You'll see merges most commonly executed when a source table is updated and a downstream table needs to be updated as a result of this change. Learn more about [how dbt uses merges in incremental models here](https://docs.getdbt.com/docs/building-a-dbt-project/building-models/configuring-incremental-models#how-do-incremental-models-work-behind-the-scenes). +::: + +## Conclusion + +DML statements allow you to query, edit, add, and remove data stored in database objects. The primary DML commands are `SELECT`, `INSERT`, `DELETE`, and `UPDATE`. Using DML statements, you can perform powerful actions on the actual data stored in your system. You'll typically see DML `SELECT` statements written in data models to conduct data analysis or create new tables and views. In many ways, DML is the air that us data folks breathe! + +## Further reading + +For more resources on why people who use dbt don’t write DML, check out the following: + +- [Why not write DML](/faqs/project/why-not-write-dml) +- [SQL dialect](/faqs/models/sql-dialect) + +For database-specific DML documents, please check out the resources below: + +- [DML in Snowflake](https://docs.snowflake.com/en/sql-reference/sql-dml.html) +- [Updating tables with DML commands in Redshift](https://docs.aws.amazon.com/redshift/latest/dg/t_Updating_tables_with_DML_commands.html) +- [DML in Google BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-manipulation-language) +- [Delta Lake DML for Databricks](https://databricks.com/blog/2020/09/29/diving-into-delta-lake-dml-internals-update-delete-merge.html) diff --git a/website/docs/terms/dry.md b/website/docs/terms/dry.md new file mode 100644 index 00000000000..0a0d6f14393 --- /dev/null +++ b/website/docs/terms/dry.md @@ -0,0 +1,95 @@ +--- +id: dry +title: DRY +description: DRY is a software development principle that stands for “Don’t Repeat Yourself.” Living by this principle means that your aim is to reduce repetitive patterns and code. +displayText: DRY +hoverSnippet: DRY is a software development principle that stands for “Don’t Repeat Yourself.” Living by this principle means that your aim is to reduce repetitive patterns and duplicate code and logic in favor of modular and referenceable code. +--- + + + What is DRY? Hint: It makes for great code - dbt Labs + + +DRY is a software development principle that stands for “Don’t Repeat Yourself.” Living by this principle means that your aim is to reduce repetitive patterns and duplicate code and logic in favor of modular and referenceable code. + +The DRY code principle was originally made with software engineering in mind and coined by Andy Hunt and Dave Thomas in their book, _The Pragmatic Programmer_. They believed that “every piece of knowledge must have a single, unambiguous, authoritative representation within a system.” As the field of analytics engineering and data transformation develops, there’s a growing need to adopt [software engineering best practices](https://www.getdbt.com/product/what-is-dbt/), including writing DRY code. + +## Why write DRY code? + +DRY code is one of the practices that makes a good developer, a great developer. Solving a problem by any means is great to a point, but eventually, you need to be able to write code that's maintainable by people other than yourself and scalable as system load increases. That's the essence of DRY code. + +But what's so great about being DRY as a bone anyway, when you can be WET? + +### Don’t be WET + +WET, which stands for “Write Everything Twice,” is the opposite of DRY. It's a tongue-in-cheek reference to code that doesn’t exactly meet the DRY standard. In a practical sense, WET code typically involves the repeated _writing_ of the same code throughout a project, whereas DRY code would represent the repeated _reference_ of that code. + +Well, how would you know if your code isn't DRY enough? That’s kind of subjective and will vary by the norms set within your organization. That said, a good rule of thumb is [the Rule of Three](https://en.wikipedia.org/wiki/Rule_of_three_(writing)#:~:text=The%20rule%20of%20three%20is,or%20effective%20than%20other%20numbers.). This rule states that the _third_ time you encounter a certain pattern, you should probably abstract it into some reusable unit. + +There is, of course, a tradeoff between simplicity and conciseness in code. The more abstractions you create, the harder it can be for others to understand and maintain your code without proper documentation. So, the moral of the story is: DRY code is great as long as you [write great documentation.](https://docs.getdbt.com/docs/building-a-dbt-project/documentation) + +### Save time & energy + +DRY code means you get to write duplicate code less often. You're saving lots of time writing the same thing over and over. Not only that, but you're saving your cognitive energy for bigger problems you'll end up needing to solve, instead of wasting that time and energy on tedious syntax. + +Sure, you might have to frontload some of your cognitive energy to create a good abstraction. But in the long run, it'll save you a lot of headaches. Especially if you're building something complex and one typo can be your undoing. + +### Create more consistent definitions + +Let's go back to what Andy and Dave said in _The Pragmatic Programmer_: “Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.” As a data person, the words “single” and “unambiguous” might have stood out to you. + +Most teams have essential business logic that defines the successes and failures of a business. For a subscription-based DTC company, this could be [monthly recurring revenue (MRR)](https://www.getdbt.com/blog/modeling-subscription-revenue/) and for a SaaS product, this could look like customer lifetime value (CLV). Standardizing the SQL that generates those metrics is essential to creating consistent definitions and values. + +By writing DRY definitions for key business logic and metrics that are referenced throughout a dbt project and/or BI (business intelligence) tool, data teams can create those single, unambiguous, and authoritative representations for their essential transformations. Gone are the days of 15 different definitions and values for churn, and in are the days of standardization and DRYness. + +:::note Experimental dbt Metrics! +dbt v1.0 currently supports the use of experimental metrics, time series aggregations over a table that support zero or one dimensions. Using [dbt Metrics](https://docs.getdbt.com/docs/building-a-dbt-project/metrics), data teams can define metric calculations, ownerships, and definitions in a yaml file that lives within their dbt project. dbt Metrics are in their experimental stage; if you’re interesting in learning more about dbt Metrics, please make sure to join the #dbt-metrics-and-server channel in the [dbt Community Slack](https://www.getdbt.com/community/join-the-community/). +::: + +## Tools to help you write DRY code + +Let’s just say it: Writing DRY code is easier said than done. For classical software engineers, there’s a ton of resources out there to help them write DRY code. In the world of data transformation, there are also some tools and methodologies that can help folks in [the field of analytics engineering](https://www.getdbt.com/what-is-analytics-engineering/) write more DRY and [modular code](https://www.getdbt.com/analytics-engineering/modular-data-modeling-technique/). + + +### Common Table Expressions (CTEs) + +CTEs are a great way to help you write more DRY code in your data analysis and dbt models. In a formal sense, a CTE is a temporary results set that can be used in a query. In a much more human and practical sense, we like to think of CTEs as separate, smaller queries within the larger query you’re building up. Essentially, you can use CTEs to break up complex queries into simpler blocks of code that are easier to debug and can connect and build off of each other. + +If you’re referencing a specific query, perhaps for aggregations that join back to an unaggregated view, CTEs can simply be referenced throughout a query with its CTE_EXPRESSION_NAME. + + +### View materializations + +View [materializations](https://docs.getdbt.com/docs/building-a-dbt-project/building-models/materializations) are also extremely useful for abstracting code that might otherwise be repeated often. A is a defined passthrough SQL query that can be run against a database. Unlike a table, it doesn’t store data, but it defines the logic that you need to use to fetch the underlying data. + +If you’re referencing the same query, CTE, or block of code, throughout multiple data models, that’s probably a good sign that code should be its own view. + +For example, you might define a SQL view to count new users created in a day: + +```sql + select + created_date, + count(distinct(user_id)) as new_users + from {{ ref('users') }} + group by created_date +``` + +While this is a simple query, writing this logic every time you need it would be super tedious. And what if the `user_id` field changed to a new name? If you’d written this in a WET way, you’d have to find every instance of this code and make the change to the new field versus just updating it once in the code for the view. + +To make any subsequent references to this view DRY-er, you simply reference the view in your data model or query. + +### dbt macros and packages + +dbt also supports the use of [macros](https://docs.getdbt.com/docs/building-a-dbt-project/jinja-macros) and [packages](https://docs.getdbt.com/docs/building-a-dbt-project/package-management) to help data folks write DRY code in their dbt projects. Macros are Jinja-supported functions that can be reused and applied throughout a dbt project. Packages are libraries of dbt code, typically models, macros, and/or tests, that can be referenced and used in a dbt project. They are a great way to use transformations for common data sources (like [ad platforms](https://hub.getdbt.com/dbt-labs/facebook_ads/latest/)) or use more [custom tests for your data models](https://hub.getdbt.com/calogica/dbt_expectations/0.1.2/) _without having to write out the code yourself_. At the end of the day, is there really anything more DRY than that? + +## Conclusion + +DRY code is a principle that you should always be striving for. It saves you time and energy. It makes your code more maintainable and extensible. And potentially most importantly, it’s the fine line that can help transform you from a good analytics engineer to a great one. + +## Further reading + +* [Data modeling technique for more modularity](https://www.getdbt.com/analytics-engineering/modular-data-modeling-technique/) +* [Why we use so many CTEs](https://docs.getdbt.com/docs/guides/best-practices) +* [Glossary: CTE](https://docs.getdbt.com/terms/cte) +* [Glossary: Materialization](https://docs.getdbt.com/terms/materialization) +* [Glossary: View](https://docs.getdbt.com/terms/view) diff --git a/website/docs/terms/edw.md b/website/docs/terms/edw.md new file mode 100644 index 00000000000..1ac0f37ee47 --- /dev/null +++ b/website/docs/terms/edw.md @@ -0,0 +1,63 @@ +--- +id: edw +title: EDW +description: The primary difference between an EDW and a regular data warehouse is, well, semantics and perspective. An EDW like any other data warehouse, is a collection of databases that centralize a business's data +displayText: EDW +hoverSnippet: An Enterprise Data Warehouse (EDW), like any other data warehouse, is a collection of databases that centralize a business's information from multiple sources and applications. +--- + + + What does an EDW (Enterprise Data Warehouse) really mean? + + +An Enterprise Data Warehouse (EDW), like any other , is a collection of databases that centralize a business's information from multiple sources and applications. The primary difference between an EDW and a regular data warehouse is, well, semantics and perspective. + +The data stored in an EDW comes from all different functions of a company—marketing, finance, engineering, product, and more. The primary goal of an EDW is to provide a central and organized home for both the raw and transformed version of this data. EDWs in modern data practices are typically set-up in the cloud, meaning that the servers used to run the warehouse are owned and managed by a cloud provider such as Snowflake, AWS Redshift, or Google BigQuery. + + +## Data warehouse vs enterprise data warehouse + +![](/img/docs/terms/edw/meme.png) + +In an EDW, all departments of an organization store their raw and transformed data in databases within a main warehouse. For organizations that are not calling their data warehouse an EDW and have a more siloed setup, there’s a chance each department each has *their own separate* data warehouse for storage and computation. **But practically, the difference between a data warehouse and an enterprise data warehouse is semantics.** + +Organization size, distribution, data complexity, and business needs can all determine whether a company wants a centralized data warehouse or distributed warehouses per function. Nonetheless, if your organization only has one data warehouse that centrally houses all of your data sources, the distinction isn't really necessary, but *technically* that could be called an EDW. + +In the world of analytics engineering, most teams have one central data warehouse that houses data from all of their different departments and functions. + + +### Why is this distinction necessary? + +One of the main distinctions is in an organization’s users and distribution. If an organization has multiple databases, a central data warehouse is used to create separate entities between raw and source data, staging work, and ready-for-use analytics datasets. In this EDW and classic data warehouse setup, data is accessible across an organization, data teams can create tables that join data from multiple sources, and users can gain enriched perspectives into their data. + +If a company has very siloed departments that manage their own data, budgets, and have little need for crossover with other departments or data sources, emphasizing the difference between a central EDW data warehouse and their own data warehouse could be a necessity for budgeting and governance reasons. + +Lastly, the somewhat exponential adoption of cloud data warehouses in the last decade has shifted the terminology from what many people called an EDW to a data warehouse. + + +## Enterprise data warehouse use cases + +There are a variety of reasons why an organization might opt to have an EDW or data warehouse. A centralized and organized data warehouse provide advantages for the following use cases: + +- Create clear partitions between raw, staging, and heavily transformed data +- Standardize data definitions and metrics across multiple data sources +- Connect a BI tool to one central data warehouse and surface that data to users across a business + +### Benefits of an EDW + +Like most other data warehouses, the benefit of an EDW is the ability to store raw and transformed data from multiple sources in one single data warehouse. Users across different departments and data team members embedded in different functions can all have access to the same data. Cloud data warehouses also scale with data and users, making EDWs an appropriate place for organizations to grow their analytics work. + +EDWs also help in building a 360-degree view of the company by combining different sources of information, such as customer feedback, financial records, product inventory, and marketing insights. All of this information can then be organized in data marts, schemas, and tables within one EDW that are eventually exposed to a BI tool. + +In addition, because all of an organization’s data is stored in one place, data teams can provide access to only those who need access to specific schemas and tables. Keeping these access patterns and changes in only one data warehouse will limit the amount of data needed to go through for auditing and other security regulations. + +## Conclusion + +An enterprise data warehouse is, in general, like any other data warehouse; it acts as a central home for multiple departments’ raw and transformed data. An EDW is often composed of multiple databases to store raw, staging, development, and production-ready data. The primary benefits for an EDW are centralization, standardization, and accessibility. You probably have a data warehouse setup like an EDW, you’re likely just not calling it that 😉 + + +## Additional reading +EDW, data warehouse, or something different altogether? Check out some of our favorite resources on the fundamental of data storage and organization: + +- [Glossary: Dimensional modeling](https://docs.getdbt.com/terms/dimensional-modeling) +- [Glossary: Data warehouse](https://docs.getdbt.com/terms/data-warehouse) \ No newline at end of file diff --git a/website/docs/terms/elt.md b/website/docs/terms/elt.md new file mode 100644 index 00000000000..b36c0486d9e --- /dev/null +++ b/website/docs/terms/elt.md @@ -0,0 +1,142 @@ +--- +id: elt +title: ELT +description: ELT is the process of first extraction data from different sources, then loading it into a data warehouse, and finally transforming it. +displayText: ELT +hoverSnippet: Extract, Load, Transform (ELT) is the process of first extracting data from different data sources, loading it into a target data warehouse, and finally transforming it. +--- + + ELT: What it is and why it's often better than ETL + +Extract, Load, Transform (ELT) is the process of first extracting data from different data sources, then loading it into a target , and finally transforming it. + +ELT has emerged as a paradigm for how to manage information flows in a modern data warehouse. This represents a fundamental shift from how data previously was handled when Extract, Transform, Load (ETL) was the data workflow most companies implemented. + +Transitioning from ETL to ELT means that you no longer have to capture your transformations during the initial loading of the data into your data warehouse. Rather, you are able to load all of your data, then build transformations on top of it. Data teams report that the ELT workflow has several advantages over the traditional ETL workflow which we’ll go over [in-depth later in this glossary](#benefits-of-elt). + +## How ELT works + +In an ELT process, data is extracted from data sources, loaded into a target data platform, and finally transformed for analytics use. We’ll go over the three components (extract, load, transform) in detail here. + +![Diagram depicting the ELT workflow. Data is depicted being extracted from example data sources like an Email CRM, Facebook Ads platform, Backend databases, and Netsuite. The data is then loaded as raw data into a data warehouse. From there, the data is transformed within the warehouse by renaming, casting, joining, or enriching the raw data. The result is then modeled data inside your data warehouse.](/img/docs/terms/elt/elt-diagram.png) + +### Extract + +In the extraction process, data is extracted from multiple data sources. The data extracted is, for the most part, data that teams eventually want to use for analytics work. Some examples of data sources can include: + +- Backend application databases +- Marketing platforms +- Email and sales CRMs +- and more! + +Accessing these data sources using Application Programming Interface (API) calls can be a challenge for individuals and teams who don't have the technical expertise or resources to create their own scripts and automated processes. However, the recent development of certain open-source and Software as a Service (SaaS) products has removed the need for this custom development work. By establishing the option to create and manage pipelines in an automated way, you can extract the data from data sources and load it into data warehouses via a user interface. + +Since not every data source will integrate with SaaS tools for extraction and loading, it’s sometimes inevitable that teams will write custom ingestion scripts in addition to their SaaS tools. + +### Load + +During the loading stage, data that was extracted is loaded into the target data warehouse. Some examples of modern data warehouses include Snowflake, Amazon Redshift, and Google BigQuery. Examples of other data storage platforms include data lakes such as Databricks’s Data Lakes. Most of the SaaS applications that extract data from your data sources will also load it into your target data warehouse. Custom or in-house extraction and load processes usually require strong data engineering and technical skills. + +At this point in the ELT process, the data is mostly unchanged from its point of extraction. If you use an extraction and loading tool like Fivetran, there may have been some light normalization on your data. But for all intents and purposes, the data loaded into your data warehouse at this stage is in its raw format. + +### Transform + +In the final transformation step, the raw data that has been loaded into your data warehouse is finally ready for modeling! When you first look at this data, you may notice a few things about it… + +- Column names may or may not be clear +- Some columns are potentially the incorrect data type +- Tables are not joined to other tables +- Timestamps may be in the incorrect timezone for your reporting +- fields may need to be unnested +- Tables may be missing primary keys +- And more! + +...hence the need for transformation! During the transformation process, data from your data sources is usually: + +- **Lightly Transformed**: Fields are cast correctly, timestamp fields’ timezones are made uniform, tables and fields are renamed appropriately, and more. +- **Heavily Transformed**: Business logic is added, appropriate materializations are established, data is joined together, etc. +- **QA’d**: Data is tested according to business standards. In this step, data teams may ensure primary keys are unique, model relations match-up, column values are appropriate, and more. + +Common ways to transform your data include leveraging modern technologies such as dbt, writing custom SQL scripts that are automated by a scheduler, utilizing stored procedures, and more. + +## ELT vs ETL + +The primary difference between the traditional ETL and the modern ELT workflow is when data transformation and loading take place. In ETL workflows, data extracted from data sources is transformed prior to being loaded into target data platforms. Newer ELT workflows have data being transformed after being loaded into the data platform of choice. Why is this such a big deal? + +| | ELT | ETL | +|---|---|---| +| Programming skills required| Often little to no code to extract and load data into your data warehouse. | Often requires custom scripts or considerable data engineering lift to extract and transform data prior to load. | +| Separation of concerns | Extraction, load, and transformation layers can be explicitly separated out by different products. | ETL processes are often encapsulated in one product. | +| Distribution of transformations | Since transformations take place last, there is greater flexibility in the modeling process. Worry first about getting your data in one place, then you have time to explore the data to understand the best way to transform it. | Because transformation occurs before data is loaded into the target location, teams must conduct thorough work prior to make sure data is transformed properly. Heavy transformations often take place downstream in the BI layer. | +| [Data team distribution](https://www.getdbt.com/data-teams/analytics-job-descriptions/) | ELT workflows empower data team members who know SQL to create their own extraction and loading pipelines and transformations. | ETL workflows often require teams with greater technical skill to create and maintain pipelines. | + +Why has ELT adoption grown so quickly in recent years? A few reasons: + +- **The abundance of cheap cloud storage with modern data warehouses.** The creation of modern data warehouses such Redshift and Snowflake has made it so teams of all sizes can store and scale their data at a more efficient cost. This was a huge enabler for the ELT workflow. +- **The development of low-code or no-code data extractors and loaders.** Products that require little technical expertise such as Fivetran and Stitch, which can extract data from many data sources and load it into many different data warehouses, have helped lower the barrier of entry to the ELT workflow. Data teams can now relieve some of the data engineering lift needed to extract data and create complex transformations. +- **A true code-based, version-controlled transformation layer with the development of dbt.** Prior to the development of dbt, there was no singular transformation layer product. dbt helps data analysts apply software engineering best practices (version control, CI/CD, and testing) to data transformation, ultimately allowing for anyone who knows SQL to be a part of the ELT process. +- **Increased compatibility between ELT layers and technology in recent years.** With the expansion of extraction, loading, and transformation layers that integrate closely together and with cloud storage, the ELT workflow has never been more accessible. For example, Fivetran creates and maintains [dbt packages](https://hub.getdbt.com/) to help write dbt transformations for the data sources they connect to. + +## Benefits of ELT + +You often hear about the benefits of the ELT workflow to data, but you can sometimes forget to talk about the benefits it brings to people. There are a variety of benefits that this workflow brings to the actual data (which we’ll outline in detail below), such as the ability to recreate historical transformations, test data and data models, and more. We'll also want to use this section to emphasize the empowerment the ELT workflow brings to both data team members and business stakeholders. + +### Data as code + +Ok we said it earlier: The ELT workflow allows data teams to function like software engineers. But what does this really mean? How does it actually impact your data? + +#### Analytics code can now follow the same best practices as software code + +At its core, data transformations that occur last in a data pipeline allow for code-based and version-controlled transformations. These two factors alone permit data team members to: + +- Easily recreate historical transformations by rolling back commits +- Establish code-based tests +- Implement CI/CD workflows +- Document data models like typical software code. + +#### Scaling, made sustainable + +As your business grows, the number of data sources correspondingly increases along with it. As such, so do the number of transformations and models needed for your business. Managing a high number of transformations without version control or automation is not scalable. + +The ELT workflow capitalizes on transformations occurring last to provide flexibility and software engineering best practices to data transformation. Instead of having to worry about how your extraction scripts scale as your data increases, data can be extracted and loaded automatically with a few clicks. + +### Bring the power to the people + +The ELT workflow opens up a world of opportunity for the people that work on that data, not just the data itself. + +#### Empowers data team members + +Data analysts, analytics engineers, and even data scientists no longer have to be dependent on data engineers to create custom pipelines and models. Instead, they can use point-and-click products such as Fivetran and Airbyte to extract and load the data for them. + +Having the transformation as the final step in the ELT workflow also allows data folks to leverage their understanding of the data and SQL to focus more on actually modeling the data. + +#### Promotes greater transparency for end busines users + +Data teams can expose the version-controlled code used to transform data for analytics to end business users by no longer having transformations hidden in the ETL process. Instead of having to manually respond to the common question, “How is this data generated?” data folks can direct business users to documentation and repositories. Having end business users involved or viewing the data transformations promote greater collaboration and awareness between business and data folks. + +## ELT tools + +As mentioned earlier, the recent development of certain technologies and products has helped lower the barrier of entry to implementing the ELT workflow. Most of these new products act as one or two parts of the ELT process, but some have crossover across all three parts. We’ll outline some of the current tools in the ELT ecosystem below. + +| Product | E/L/T? | Description | Open source option? | +|---|---|---|---| +| Fivetran/HVR | E, some T, L | Fivetran is a SaaS company that helps data teams extract, load, and perform some transformation on their data. Fivetran easily integrates with modern data warehouses and dbt. They also offer transformations that leverage dbt Core. | :x: | +| Stitch by Talend | E, L | Stitch (part of Talend) is another SaaS product that has many data connectors to extract data and load it into data warehouses. | :x: | +| Airbyte | E, L | Airbyte is an open-source and cloud service that allows teams to create and load pipelines. | :white_check_mark: | +| Funnel | E, some T, L | Funnel is another product that can extract and load data. Funnel’s data connectors are primarily focused around marketing data sources. | :x: | +| dbt | T | dbt is the transformation tool that enables data analysts and engineers to transform, test, and document data in the cloud data warehouse. dbt offers both an open-source and cloud-based product. | :white_check_mark: | + +## Conclusion + +The past few years have been a whirlwind for the data world. The increased accessibility and affordability of cloud warehouses, no-code data extractors and loaders, and a true transformation layer with dbt has allowed for the ELT workflow to become the preferred analytics workflow. ETL predates ELT and differs in when data is transformed. In both processes, data is first extracted from different sources. However, in ELT processes, data is loaded into the target data platform and then transformed. The ELT workflow ultimately allows for data team members to extract, load, and model their own data in a flexible, accessible, and scalable way. + +## Further reading + +Here's some of our favorite content about the ELT workflow: + +- [The case for the ELT workflow](https://www.getdbt.com/analytics-engineering/case-for-elt-workflow/) +- [A love letter to ETL tools](https://www.getdbt.com/analytics-engineering/etl-tools-a-love-letter/) +- [What, exactly, is dbt?](https://blog.getdbt.com/what-exactly-is-dbt/) +- [What is analytics engineering?](https://www.getdbt.com/what-is-analytics-engineering/) +- [How Fivetran operationalizes data transformations](https://www.getdbt.com/coalesce-2021/how-fivetran-operationalizes-data-transformations/) + diff --git a/website/docs/terms/etl.md b/website/docs/terms/etl.md new file mode 100644 index 00000000000..acc0e7b1c40 --- /dev/null +++ b/website/docs/terms/etl.md @@ -0,0 +1,127 @@ +--- +id: etl +title: ETL +description: ETL is the process of first extracting data from a data source, transforming it, and then loading it into a target data warehouse. +displayText: ETL +hoverSnippet: Extract, Transform, Load (ETL)is the process of first extracting data from a data source, transforming it, and then loading it into a target data warehouse. +--- + + + ETL: What is it and is it still relevant? - dbt Labs + + +ETL, or “Extract, Transform, Load”, is the process of first extracting data from a data source, transforming it, and then loading it into a target . In ETL workflows, much of the meaningful data transformation occurs outside this primary pipeline in a downstream business intelligence (BI) platform. + +ETL is contrasted with the newer (Extract, Load, Transform) workflow, where transformation occurs after data has been loaded into the target data warehouse. In many ways, the ETL workflow could have been renamed the ETLT workflow, because a considerable portion of meaningful data transformations happen outside the data pipeline. The same transformations can occur in both ETL and ELT workflows, the primary difference is *when* (inside or outside the primary ETL workflow) and *where* the data is transformed (ETL platform/BI tool/data warehouse). + +It’s important to talk about ETL and understand how it works, where it provides value, and how it can hold people back. If you don’t talk about the benefits and drawbacks of systems, how can you expect to improve them? + +## How ETL works + +In an ETL process, data is first extracted from a source, transformed, and then loaded into a target data platform. We’ll go into greater depth for all three steps below. + +![A diagram depicting the ETL workflow. The diagram starts by depicting raw data being extracted from various example data sources like an email CRM, Facebook Ads platform, a backend database, and Netsuite. Once the data is extracted, the raw data is transformed within the data pipeline via renaming, casting, joining, and enriching. After the data is transformed within the data pipeline, the modeled data is loaded into a data warehouse.](/img/docs/terms/etl/etl-diagram.png) + +### Extract + +In this first step, data is extracted from different data sources. Data that is extracted at this stage is likely going to be eventually used by end business users to make decisions. Some examples of these data sources include: + +- Ad platforms (Facebook Ads, Google Ads, etc.) +- Backend application databases +- Sales CRMs +- And more! + +To actually get this data, data engineers may write custom scripts that make Application Programming Interface (API) calls to extract all the relevant data. Because making and automating these API calls gets harder as data sources and data volume grows, this method of extraction often requires strong technical skills. In addition, these extraction scripts also involve considerable maintenance since APIs change relatively often. Data engineers are often incredibly competent at using different programming languages such as Python and Java. Data teams can also extract from these data sources with open source and Software as a Service (SaaS) products. + +### Transform + +At this stage, the raw data that has been extracted is normalized and modeled. In ETL workflows, much of the actual meaningful business logic, metric calculations, and entity joins tend to happen further down in a downstream BI platform. As a result, the transformation stage here is focused on data cleanup and normalization – renaming of columns, correct casting of fields, timestamp conversions. + +To actually transform the data, there’s two primary methods teams will use: + +- **Custom solutions**: In this solution, data teams (typically data engineers on the team), will write custom scripts and create automated pipelines to transform the data. Unlike ELT transformations that typically use SQL for modeling, ETL transformations are often written in other programming languages such as Python or Scala. Data engineers may leverage technologies such as Apache Spark or Hadoop at this point to help process large volumes of data. +- **ETL products**: There are ETL products that will extract, transform, and load your data in one platform. [These tools](#etl-tools) often involve little to no code and instead use Graphical User Interfaces (GUI) to create pipelines and transformations. + +### Load + +In the final stage, the transformed data is loaded into your target data warehouse. Once this transformed data is in its final destination, it’s most commonly exposed to end business users either in a BI tool or in the data warehouse directly. + +The ETL workflow implies that your raw data does not live in your data warehouse. *Because transformations occur before load, only transformed data lives in your data warehouse in the ETL process.* This can make it harder to ensure that transformations are performing the correct functionality. + +## ETL use cases and challenges + +### Example ETL use cases + +While ELT adoption is growing, we still see ETL use cases for processing large volumes of data and adhering to strong data governance principles. + +- **Efficiently normalize large volumes of data**: ETL can be an efficient way to perform simple normalizations across large data sets. Doing these lighter transformations across a large volume of data during loading can help get the data formatted properly and quickly for downstream use. In addition, end business users sometimes need quick access to raw or somewhat normalized data. Through an ETL workflow, data teams can conduct lightweight transformations on data sources and quickly expose them in their target data warehouse and downstream BI tool. +- **Hash PII prior to load**: Some companies will want to mask, hash, or remove PII values before it enters their data warehouse. In an ETL workflow, teams can transform PII to hashed values or remove them completely during the loading process. This limits where PII is available or accessible in an organization’s data warehouse. + +### ETL drawbacks + +There are reasons ETL has persisted as a workflow for over twenty years. However, there are also reasons why there’s been such immense innovation in this part of the data world in the past decade. From our perspective, the technical and human limitations we describe below are some of the reasons ELT has surpassed ETL as the preferred workflow. + +#### Technical limitations + +**Limited or lack of version control** + +When transformations exist as standalone scripts or deeply woven in ETL products, it can be hard to version control the transformations. Not having version control on transformation as code means that data teams can’t easily recreate or rollback historical transformations and perform code reviews. + +**Immense amount of business logic living in BI tools** + +Some teams with ETL workflows only implement much of their business logic in their BI platform versus earlier in their transformation phase. While most organizations have some business logic in their BI tools, an excess of this logic downstream can make rendering data in the BI tool incredibly slow and potentially hard to track if the code in the BI tool is not version controlled or exposed in documentation. + +**Challenging QA processes** + +While data quality testing can be done in ETL processes, not having the raw data living somewhere in the data warehouse inevitably makes it harder to ensure data models are performing the correct functionality. In addition, quality control continually gets harder as the number of data sources and pipelines within your system grows. + +#### Human limitations + +**Data analysts can be excluded from ETL work** + +Because ETL workflows often involve incredibly technical processes, they've restricted data analysts from being involved in the data workflow process. One of the greatest strengths of data analysts is their knowledge of the data and SQL, and when extractions and transformations involve unfamiliar code or applications, they and their expertise can be left out of the process. Data analysts and scientists also become dependent on other people to create the schemas, tables, and datasets they need for their work. + +**Business users are kept in the dark** + +Transformations and business logic can often be buried deep in custom scripts, ETL tools, and BI platforms. At the end of the day, this can hurt business users: They're kept out of the data modeling process and have limited views into how data transformation takes place. As a result, end business users often have little clarity on data definition, quality, and freshness, which ultimately can decrease trust in the data and data team. + +## ETL vs ELT + +You may read other articles or technical documents that use ETL and ELT interchangeably. On paper, the only difference is the order in which the T and the L appear. However, this mere switching of letters dramatically changes the way data exists in and flows through a business’ system. + +In both processes, data from different data sources is extracted in similar ways. However, in ELT, data is then directly loaded into the target data platform versus being transformed in ETL. Now, via ELT workflows, both raw and transformed data can live in a data warehouse. In ELT workflows, data folks have the flexibility to model the data after they’ve had the opportunity to explore and analyze the raw data. ETL workflows can be more constraining since transformations happen immediately after extraction. We break down some of the other major differences between the two below: + +| | ELT | ETL | +|---|---|---| +| Programming skills required | Often requires little to no code to extract and load data into your data warehouse. | Often requires custom scripts or considerable data engineering lift to extract and transform data prior to load. | +| Separation of concerns | Extraction, load, and transformation layers can be explicitly separated out by different products. | ETL processes are often encapsulated in one product. | +| Distribution of transformations | Since transformations take place last, there is greater flexibility in the modeling process. Worry first about getting your data in one place, then you have time to explore the data to understand the best way to transform it. | Because transformation occurs before data is loaded into the target location, teams must conduct thorough work prior to make sure data is transformed properly. Heavy transformations often take place downstream in the BI layer. | +| [Data team roles](https://www.getdbt.com/data-teams/analytics-job-descriptions/) | ELT workflows empower data team members who know SQL to create their own extraction and loading pipelines and transformations. | ETL workflows often require teams with greater technical skill to create and maintain pipelines. | + +While ELT is growing in adoption, it’s still important to talk about when ETL might be appropriate and where you'll see challenges with the ETL workflow. + +## ETL tools + +There exists a variety of ETL technologies to help teams get data into their data warehouse. A good portion of ETL tools on the market today are geared toward enterprise businesses and teams, but there are some that are also applicable for smaller organizations. + +| Platform | E/T/L? | Description | Open source option? | +|---|---|---|---| +| Informatica | E, T, L | An all-purpose ETL platform that supports low or no-code extraction, transformations and loading. Informatica also offers a broad suite of data management solutions beyond ETL and is often leveraged by enterprise organizations. | :x: | +| Integrate.io | E, T, L | A newer ETL product focused on both low-code ETL as well as reverse ETL pipelines. | :x: | +| Matillion | E, T, L | Matillion is an end-to-end ETL solution with a variety of native data connectors and GUI-based transformations. | :x: | +| Microsoft SISS | E, T, L | Microsoft’s SQL Server Integration Services (SISS) offers a robust, GUI-based platform for ETL services. SISS is often used by larger enterprise teams. | :x: | +| Talend Open Studio | E, T, L | An open source suite of GUI-based ETL tools. | :white_check_mark: | + +## Conclusion + +ETL, or “Extract, Transform, Load,” is the process of extracting data from different data sources, transforming it, and loading that transformed data into a data warehouse. ETL typically supports lighter transformations during the phase prior to loading and more meaningful transformations to take place in downstream BI tools. We’re seeing now that ETL is fading out and the newer ELT workflow is replacing it as a practice for many data teams. However, it’s important to note that ETL allowed us to get us to where we are today: Capable of building workflows that extract data within simple UIs, store data in scalable cloud data warehouses, and write data transformations like software engineers. + +## Further Reading + +Please check out some of our favorites reads regarding ETL and ELT below: + +- [Glossary: ELT](https://docs.getdbt.com/terms/elt) +- [The case for the ELT workflow](https://www.getdbt.com/analytics-engineering/case-for-elt-workflow/) +- [A love letter to ETL tools](https://www.getdbt.com/analytics-engineering/etl-tools-a-love-letter/) +- [Reverse ETL](https://www.getdbt.com/analytics-engineering/use-cases/operational-analytics/) + diff --git a/website/docs/terms/grain.md b/website/docs/terms/grain.md new file mode 100644 index 00000000000..608a5c6391d --- /dev/null +++ b/website/docs/terms/grain.md @@ -0,0 +1,36 @@ +--- +id: grain +title: Data grain +description: Grain is the combination of columns at which records in a table are unique. Ideally, this is captured in a single column or a unique primary key. +displayText: grain +hoverSnippet: Your data's grain is the combination of columns at which records in a table are unique. Ideally, this is captured in a single column and a unique primary key. +--- + + + Data grain: What granularity means in terms of data modeling + + +Grain is the combination of columns at which records in a table are unique. Ideally, this is captured in a single column, a unique , but even then, there is descriptive grain behind that unique id. Let’s look at some examples to better understand this concept. + +| user_id | address | +| --- | --- | +| 1 | 123 Jaffle Ln | +| 2 | 456 Waffle St | +| 3 | 789 Raffle Rd | + +In the above table, each `user_id` is unique. This table is at the *user* *grain*. + +| user_id | address | +| --- | --- | +| 1 | 123 Jaffle Ln | +| 1 | 420 Jaffle Ln | +| 2 | 456 Waffle St | +| 3 | 789 Raffle Rd | + +In the above table, `user_id` is no longer unique. The combination of `user_id` and `address` creates a unique combination, thus this table is at the *user* *address* *grain*. We generally describe the grain conceptually based on the names of the columns that make it unique. A more realistic combination you might see in the wild would be a table that capture the state of all users at midnight every day. The combination of the captured `updated_date` and `user_id` would be unique, meaning our table is at *user per day* grain. + +In both examples listed in the previous paragraph, we’d want to create a of some sort from the combination of columns that comprise the grain. This gives our table a primary key, which is crucial for testing and optimization, and always a best practice. Typically, we’ll name this primary key based on the verbal description of the grain. For the latter example, we’d have `user_per_day_id`. This will be more solid and efficient than testing than repeatedly relying on the combination of those two columns. + +Thinking deeply about grain is a crucial part of data modeling. As we design models, we need to consider the entities we’re describing, and what dimensions (time, attributes, etc.) might fan those entities out so they’re no longer unique, as well as how we want to deal with those. Do we need to apply transformations to deduplicate and collapse the grain? Or do we intentionally want to expand the grain out, like in our *user per day* example? + +There’s no right answer here, we have the power to do either as it meets our needs. The key is just to make sure we have a clear sense of our grain for every model we create, that we’ve captured it in a primary key, and that we’re applying tests to ensure that our primary key column is unique and not null. \ No newline at end of file diff --git a/website/docs/terms/idempotent.md b/website/docs/terms/idempotent.md new file mode 100644 index 00000000000..245728953c4 --- /dev/null +++ b/website/docs/terms/idempotent.md @@ -0,0 +1,23 @@ +--- +id: idempotent +title: Idempotent +description: Idempotent is an adjective to describe a process that gives you the same result no matter how many times you run it. +displayText: idempotent +hoverSnippet: Idempotent describes a process that gives you the same result no matter how many times you run it. +--- + + + What is idempotency and why is the concept important in data? + + +Idempotent is an adjective to describe a process that gives you the same result no matter how many times you run it. + +For a mathematical example, adding 1 changes the results, but multiplying by 1 is idempotent. When you add 1 to a number and then add 1 again, you get different results. If you multiply a number by 1 and multiply by 1 again, you do get the same result. + +A more real-world example of idempotency is the process of saving a file in a word processor. Given the same inputs (i.e. the same document contents), clicking "_Save_" one time will leave your system in the exact same state as clicking "_Save_" five times in a row. + +A non-idempotent version of the "_Save_" button might do something like "Append the paragraph I just wrote to the end of the file". Doing _that_ five times in a row will _not_ leave you in the same state as doing it one time; your most recent paragraph would have duplicates. + +If word processors only gave us non-idempotent "Append paragraph" / "Update paragraph" / "Delete paragraph" operations, then saving our document changes would be a lot more difficult! We'd have to keep track of which paragraphs we previously saved, and either make sure to not save them again or have a process in place to regularly clean up duplicate paragraphs. The implementation of the "_Save_" button in word processors takes the collection of low-level non-idempotent filesystem operations (read/append/overwrite/delete), and systematically runs them in a certain order so that the _user_ doesn't have to deal with the non-idempotency. The user can just focus on writing -- choosing words, editing for clarity, ensuring paragraphs aren't too long, etc. -- and the word processor deals with making sure the words get persisted properly to disk. + +This word processing analogy is very similar to what dbt does for data transformation: it takes the collection of low-level non-idempotent database operations (`SELECT`/`INSERT`/`UPDATE`/`DELETE` -- collectively known as DML statements), and systematically runs them in a certain order so that analytics engineers don't have to deal with non-idempotency. We can just focus on the data -- [choosing good model and column names](https://docs.getdbt.com/blog/on-the-importance-of-naming), [documenting them](https://docs.getdbt.com/docs/about/viewpoint#documentation), [ensuring data consumers can understand them](https://docs.getdbt.com/docs/guides/best-practices#consider-the-information-architecture-of-your-data-warehouse), etc. -- and [`dbt run`](https://docs.getdbt.com/reference/commands/run) will make sure the database ends up in the right state. diff --git a/website/docs/terms/json.md b/website/docs/terms/json.md new file mode 100644 index 00000000000..652fb58cbe3 --- /dev/null +++ b/website/docs/terms/json.md @@ -0,0 +1,103 @@ +--- +id: json +title: JSON +description: JSON (JavaScript Object Notation) is a minimal format for semi-structured data used to capture relationships between fields and values. +displayText: JSON +hoverSnippet: JSON (JavaScript Object Notation) is a minimal format for semi-structured data used to capture relationships between fields and values. +--- + +JSON stands for JavaScript Object Notation. JSON is a minimal format which is great for processing data for applications. It can capture many types of relationships in a concise format and is a commonly used format for semi-structured data. The tables in your contain structured data (as opposed to semi-structured) where for each row, each field typically contains one value. Structured data, or tabular data, is intuitive and easy to read, but semi-structured data offers more flexibility. + +Let’s talk through what that looks like in practice so you can get a better sense of what we mean. + +## JSON syntax example + +When looking at data formatted in JSON, we say that the data is stored in **JSON objects**. These are composed of key-value pairs. JSON objects are enclosed in curly brackets (`{ }`) and each key-value pair is separated by a comma. Here’s an example: + +```json +order = {"customer_id":2947, "order_id":4923, "order_items":"cheesecake"} +``` + +`order` is the JSON object. `"customer_id":2947` is one of the key-value pairs within this JSON object. + +If I wanted to find the `customer_id`, I could return that value with `order["customer_id"]` or `order.customer_id`. It’s easy for us to simply read the `customer_id` just by looking at the JSON object in this example, but what if your JSON object contains hundreds of key-value pairs or complex nesting? Being aware of how to pull information out of JSON is essential if you’re working with it in the wild. + +A key feature of JSON is that it can contain data types that aren’t normally found in relational databases, namely **dictionaries** and **arrays**. Let’s break down what that means and then we’ll look at an example to pull everything together. + +### Dictionaries and arrays in JSON + +JSON inherits its syntax from JavaScript (JS) so dictionaries and arrays are formatted in the same way as they are in JS. Dictionaries are formatted just like JSON objects and consist of key-value pairs. Arrays are lists of values and they’re enclosed in square brackets (`[ ]`) and each value is separated by a comma, like so: + +```json +menu_items = ["cheesecake", "danish", "coffee"] +``` + +Individual values from an array can be called by referencing the location of a value within the array. Arrays are zero-indexed which means that the first item is at position 0 and we count up from there. + +- `menu_items[0]` will return “cheesecake” +- `menu_items[1]` will return “danish” +- `menu_items[2]` will return “coffee” + +Dictionaries and arrays can be nested in JSON objects as well as nested in each other. **Dictionaries and arrays can only be values. They can never be keys.** + +Here’s an example of a JSON object describing a tweet from [Twitter’s developer platform](https://developer.twitter.com/en/docs/twitter-api/v1/data-dictionary/overview). + +```json +tweet = +{ + "created_at": "Thu Apr 06 15:24:15 +0000 2017", + "id_str": "850006245121695744", + "text": "1\/ Today we\u2019re sharing our vision for the future of the Twitter API platform!\nhttps:\/\/t.co\/XweGngmxlP", + "user": { + "id": 2244994945, + "name": "Twitter Dev", + "screen_name": "TwitterDev", + "location": "Internet", + "url": "https:\/\/dev.twitter.com\/", + "description": "Your official source for Twitter Platform news, updates & events. Need technical help? Visit https:\/\/twittercommunity.com\/ \u2328\ufe0f #TapIntoTwitter" + }, + "place": { + }, + "entities": { + "hashtags": [ + ], + "urls": [ + { + "url": "https:\/\/t.co\/XweGngmxlP", + "unwound": { + "url": "https:\/\/cards.twitter.com\/cards\/18ce53wgo4h\/3xo1c", + "title": "Building the Future of the Twitter API Platform" + } + } + ], + "user_mentions": [ + ] + } +} +``` + +Here's a quick quiz to see if you're understanding the file's structure: + +
+How would you call the user ID? +tweet['user']['id'] +
+ +
+How would you call the unwound url? +tweet['entities']['urls'][0]['unwound']['url'] +
+ +As you can see, JSON objects can get complex pretty quickly. + +## Why is JSON important in modern analytics? + +Semi-structured data offers flexibility with the trade-off of being more complex. JSON doesn’t require a pre-defined schema. It allows nesting, values can be different data types, and it lends itself well to changes in the shape of the incoming data. As you can imagine, the above Tweet object would look very different if we tried to restructure it so it could fit into a table. It would be hard to read or we would lose information or both. + +## Use cases for JSON + +JSON is lightweight and often used to transfer data over a network connection. As we’ve seen, data from social media sites are often stored as JSON objects. JSON is also commonly how data from IoT sensors is formatted and you’ll often see JSON when using an API. + +## Conclusion + +The greatest strength of JSON also acts as its weakness—the data it contains informs the shape the object takes, rather than the other way around. Structured data is the bread and butter of analytics work, but a semi-structured format is an alternative option when a tabular format becomes too rigid to describe the relationships between different entities. \ No newline at end of file diff --git a/website/docs/terms/materialization.md b/website/docs/terms/materialization.md new file mode 100644 index 00000000000..fdeaaebfcc8 --- /dev/null +++ b/website/docs/terms/materialization.md @@ -0,0 +1,20 @@ +--- +id: materialization +title: Materialization +description: A materialization is the exact Data Definition Language (DDL) that dbt will use when creating the model’s equivalent in a data warehouse. +displayText: materialization +hoverSnippet: The exact Data Definition Language (DDL) that dbt will use when creating the model’s equivalent in a data warehouse. +--- + + + What does materialization mean in the context of dbt? + + +:::important This page could use some love +This term would benefit from additional depth and examples. Have knowledge to contribute? [Create a discussion in the docs.getdbt.com GitHub repository](https://github.com/dbt-labs/docs.getdbt.com/discussions) to begin the process of becoming a glossary contributor! +::: + +The exact Data Definition Language (DDL) that dbt will use when creating the model’s equivalent in a . It's the manner in which the data is represented, and each of those options is defined either canonically (tables, views, incremental), or bespoke. + +It is important to consider the downstream impacts of your materialization choice on query run times and macro capabilities. + diff --git a/website/docs/terms/primary-key.md b/website/docs/terms/primary-key.md new file mode 100644 index 00000000000..de4c84a92cb --- /dev/null +++ b/website/docs/terms/primary-key.md @@ -0,0 +1,165 @@ +--- +id: primary-key +title: Primary key +description: A primary key is a non-null column in a database object that uniquely identifies each row. Primary keys take the form of a natural or surrogate key. +displayText: primary key +hoverSnippet: A primary key is a non-null column in a database object that uniquely identifies each row. +--- + + + Primary key in SQL (AKA Constraints) — dbt Labs + + +A primary key is a non-null column in a database object that uniquely identifies each row. Primary keys take the form of a natural or . It’s important to note that for each or in your database, there must only be one primary key column per database object. + +At their core, you create and use these row-level unique identifiers to: + +* Ensure a lack of duplicate rows in your tables +* Identify table grains easily +* Help unpack how tables join together +* Establish a consistent naming system for primary keys across your data models + +One of the great things about data modeling is that there are very few rules to it. You have the flexibility to create the models and columns that are applicable to your business and the SQL you use to accomplish that is pretty much up to you and your team. _Having a primary key in each data model is pretty much the one rule you can’t break._ Without primary keys that are tested for non-nullness and uniqueness, duplicate or null records can slip undetected into your data models and cause counts to be incorrect. These two reasons coupled together can create a sense of distrust in the data and data team. + +Use this glossary page to understand the importance of primary keys, how natural keys and surrogate keys differ, and how support for primary keys varies. + +## Types of primary keys + +Primary keys can be established two ways: naturally or derived through the data in a surrogate key. + +* A **natural key** is a primary key that is innate to the data. Perhaps in tables there’s a unique `id` field in each table that would act as the natural key. You can use documentation like entity relationship diagrams (ERDs) to help understand natural keys in APIs or tables. In a perfect world, all of our primary keys would be natural keys… _but this is an imperfect world!_ +* A **surrogate key** is a hashed value of multiple fields in a dataset that create a uniqueness constraint on that dataset. You’ll essentially need to make a surrogate key in every table that lacks a natural key. An example of this could be a custom table that reports daily performance per `ad_id` from an ad platform. You can derive a surrogate key by hashing the `date` and `ad_id` fields to create a unique value per row. + +A note on primary key data types: natural keys will often take the form of an integer or other numeric value (ex. 45932). Surrogate keys, on the other hand, are usually alphanumeric strings since they are hashed values (ex. ‘62aef884fbe3470ce7d9a92140b09b17’). + +:::tip Tip +dbt supports [packages](https://docs.getdbt.com/docs/building-a-dbt-project/package-management), libraries of open-source macros and data models, to help data teams avoid doing duplicative work. One of these packages, [dbt_utils](https://github.com/dbt-labs/dbt-utils), contains a series of macros that are built to alleviate common struggles in data modeling. The [surrogate_key](https://github.com/dbt-labs/dbt-utils#surrogate_key-source) macro offers a DRY (don’t repeat yourself) solution to creating surrogate keys across different data warehouses in the event that your data doesn’t contain natural keys. +::: + +## Data warehouse support for primary keys + +What do we mean when we say a primary key is supported in a database? What does it mean if primary keys are enforced? + +* **Support**: If a primary key is supported in a database, that means they allow you to explicitly let the system know if a specific field is a primary key. This will happen in the DDL (data definition language) to create the table, like in the example below, or an `ALTER` statement that specifies which field is the primary key. +* **Enforcement**: If a database enforces primary keys, that means it would raise an error if one of the constraints on primary keys (uniqueness and non-null) was broken during an `INSERT` or `UPDATE` statement. + +The table below gives an overview of primary key support and enforcement in some of the major data warehouses. Below the table you’ll additionally see a breakdown of some details around primary key implementation for these data warehouses. + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Supports primary keys? + Fully enforces primary keys? +
Snowflake + ✅ + ❌ +
Amazon Redshift + ✅ + ❌ +
Google BigQuery + ❌ + ❌ +
Databricks + ❌ + ❌ +
Postgres + ✅ + ✅ +
+ +### Snowflake + +Snowflake allows for data folks to explicitly identify primary keys during table creation or using an `ALTER` statement. To see identified primary keys in your database, you can run the `SHOW PRIMARY KEYS` command. It’s important to note, however, that Snowflake primary key indicators are purely descriptive–meaning they don’t enforce either non-nullness or uniqueness requirements. However, Snowflake offers a separate `NOT NULL` constraint that will be enforced for specified fields. + +### Amazon Redshift + +With Redshift, you can specify primary keys constraints on tables, but Redshift won’t provide out-of-the-box primary key enforcement. Similar to Snowflake, Redshift does allow users to add a [`NOT NULL` constraint](https://docs.aws.amazon.com/redshift/latest/dg/r_CREATE_TABLE_NEW.html) that is actually enforced. + +In general for Redshift, it’s still good practice to define your primary keys (regardless of the lack of uniqueness enforcement) because they can help the [query planner](https://docs.getdbt.com/blog/redshift-configurations-dbt-model-optimizations) more quickly identify uniqueness and foreign key relationships. + +### Google BigQuery + +BigQuery is pretty unique here in that it doesn’t support or enforce primary keys. If your team is on BigQuery, you’ll need to have some [pretty solid testing](https://docs.getdbt.com/docs/building-a-dbt-project/tests) in place to ensure your primary key fields are unique and non-null. + +### Databricks + +Databricks’ Delta tables don’t provide classical support for primary keys; instead, they call them constraints. Databricks currently offers two constraint types: `not-null` and `check`. The `not-null` one is pretty straightforward, but the `check` constraint is more unique to Databricks. With the `check` constraint, you can test that a certain boolean expression executes as `true` for each row in a table. This constraint is more likely to be helpful for ensuring accepted values are met for fields rather than for primary key requirements. + +### Postgres + +Postgres is the true standout here in that it both supports and enforces primary keys! However, you shouldn’t be too surprised about this. One of the primary use cases for Postgres is that it often serves as the home for backend application tables and is usually managed by a [team of backend developers](https://docs.getdbt.com/blog/when-backend-devs-spark-joy). Since these tables often act as a source of truth for many businesses, it’s critical that primary key fields must exist, be non-null, and unique. + +## How to indicate primary keys + +For data warehouses that support primary keys (like Snowflake, Amazon Redshift, and Postgres), you can add a primary key indicator to the column you want to use as a primary key in the DDL to create the table. You may also use an `ALTER` DDL statement to set a column as a primary key if the table is already created. + +In the example below, you can add a new `jaffles` table to the [jaffle_shop](https://github.com/dbt-labs/jaffle_shop) project and make the `id` field the primary key. + +```sql +CREATE TABLE prod.jaffle_shop.jaffles ( + id varchar(255) primary key, + jaffle_name varchar(255) + created_at timestamp, + ingredients_list varchar(255), + is_active boolean +); +``` + +:::note Note +If you don't have a field in your table that would act as a natural primary key, you’ll need to[ create a surrogate key](https://docs.getdbt.com/blog/sql-surrogate-keys) for it. +::: + +If your data warehouse doesn’t provide out-of-the box support and enforcement for primary keys, it’s important to clearly label and put your own constraints on primary key fields. This could look like: + +* **Creating a consistent naming convention for your primary keys**: You may see an `id` field or fields prefixed with `pk_` (ex. `pk_order_id`) to identify primary keys. You may also see the primary key be named as the obvious table grain (ex. In the jaffle shop’s `orders` table, the primary key is called `order_id`). +* **Adding automated [tests](https://docs.getdbt.com/docs/building-a-dbt-project/tests) to your data models**: Use a data tool, such as dbt, to create not null and unique tests for your primary key fields. + +## Testing primary keys + +When we talk about testing our primary keys, we really mean testing their uniqueness and non-nullness. Given that not all modern data warehouses support or enforce primary key constraints, your data team will likely fall under two scenarios: + +1. For databases that support primary key enforcement, you should receive failures when your constraints are broken. +2. For databases that don’t offer support and enforcement of primary keys, you’re going to need to regularly test that primary keys aren’t violating their golden rule of uniqueness and non-nullness. To do this, we recommend implementing a tool like dbt that allows you to define version-controlled and code-based tests on your data models. Using these tests, you should create [not null](https://docs.getdbt.com/reference/resource-properties/tests#not_null) and [unique](https://docs.getdbt.com/reference/resource-properties/tests#unique) tests for every primary key field throughout your dbt project. Other methods for primary key testing may look like writing custom tests or ad hoc queries that check for uniqueness and non-nullness. + +:::tip Tip +You can use dbt’s [documentation](https://docs.getdbt.com/docs/building-a-dbt-project/documentation) and [testing](https://docs.getdbt.com/reference/resource-properties/tests) capabilities to clearly identify and QA primary keys in your data models. For your primary key column, you should mention that the field is the unique identifier for that table and test for uniqueness and non-nullness. +::: + +## Conclusion + +Say it with me or get it tattooed on your lower back: every database object in your data warehouse needs a primary key. At their core, primary keys are fields that uniquely identify each row in a table and help ensure there are no duplicates in the data. Primary keys take shape as either natural keys, fields that are innate to the data, or as surrogate keys, hashed column values that create a uniqueness constraint on the data. Not every modern data warehouse provides explicit support or enforcement of primary keys, so it’s incredibly important to have a method to test that your primary keys are unique and not null. + +## Further reading + +* [Testing primary keys in dbt](https://docs.getdbt.com/blog/primary-key-testing) +* [Surrogate keys and dbt](https://docs.getdbt.com/blog/sql-surrogate-keys) +* [dbt Constraints Snowflake Labs package](https://hub.getdbt.com/snowflake-labs/dbt_constraints/latest/) \ No newline at end of file diff --git a/website/docs/terms/reverse-etl.md b/website/docs/terms/reverse-etl.md new file mode 100644 index 00000000000..522ab364174 --- /dev/null +++ b/website/docs/terms/reverse-etl.md @@ -0,0 +1,93 @@ +--- +id: reverse-etl +title: Reverse ETL +description: Reverse ETL is the process of getting your transformed data stored in your data warehouse to end business platforms, such as sales CRMs and ad platforms. +displayText: reverse ETL +hoverSnippet: Reverse ETL is the process of getting your transformed data stored in your data warehouse to end business platforms, such as sales CRMs and ad platforms. +--- + + + Reverse ETL, demystified: What it is in plain english + + +Reverse ETL is the process of getting your transformed data stored in your data warehouse to end business platforms, such as sales CRMs and ad platforms. Once in an end platform, that data is often used to drive meaningful business actions, such as creating custom audiences in ad platforms, personalizing email campaigns, or supplementing data in a sales CRM. You may also hear about reverse ETL referred to as operational analytics or data activation. + +Reverse ETL efforts typically happen after data teams have set up their [modern data stack](https://www.getdbt.com/blog/future-of-the-modern-data-stack/) and ultimately have a consistent and automated way to extract, load, and transform data. Data teams are also often responsible for setting up the pipelines to send down data to business platforms, and business users are typically responsible for *using the data* once it gets to their end platform. + +Ultimately, reverse ETL is a way to put data where the work is already happening, support self-service efforts, and help business users derive real action out of their data. + +## How reverse ETL works + +In the reverse ETL process, transformed data is synced from a data warehouse to external tools in order to be leveraged by different business teams. + +![A diagram depicting how the reverse ETL process works. It starts with data being extract from data sources like email CRMs, Facebook Ad platforms, backend databases, and NetSuite. The raw data is then loaded into a data warehouse. After loading, the data is transformed and modeled. The modeled data is then loaded directly back into the tools that created the data, like Email CRMs, Facebook Ad platforms, and others so the insights are more accessible to business users.](/img/docs/terms/reverse-etl/reverse-etl-diagram.png) + +The power of reverse ETL comes from sending down *already transformed data* to business platforms. Raw data, while beautiful in its own way, typically lacks the structure, aggregations, and aliasing to be useful for end business users off the bat. After data teams transform data for business use in ELT pipelines, typically to expose in an end business intelligence (BI) tool, they can also send this cleaned and meaningful data to other platforms where business users can derive value using [reverse ETL tools](#reverse-etl-tools). + +Data teams can choose to write additional transformations that may need to happen for end business tools in reverse ETL tools themselves or by creating [additional models in dbt](https://getdbt.com/open-source-data-culture/reverse-etl-playbook/). + +## Why use reverse ETL? + +There’s a few reasons why your team may want to consider using reverse ETL: + +### Putting data where the work is happening + +While most data teams would love it if business users spent a significant portion of their time in their BI tool, that’s neither practical nor necessarily the most efficient use of their time. In the real world, many business users will spend some time in a BI tool, identify the data that could be useful in a platform they spend a significant amount of time in, and work with the data team to get that data where they need it. Users feel comfortable and confident in the systems they use everyday—why not put the data in the places that allow them to thrive? + +### Manipulating data to fit end platform requirements + +Reverse ETL helps you to put data your business users need *in the format their end tool expects*. Oftentimes, end platforms expect data fields to be named or cast in a certain way. Instead of business users having to manually input those values in the correct format, you can transform your data using a product like dbt or directly in a reverse ETL tool itself, and sync down that data in an automated way. + +### Supporting self-service efforts + +By sending down data-team approved data in reverse ETL pipelines, your business users have the flexibility to use that data however they see fit. Soon, your business users will be making audiences, testing personalization efforts, and running their end platform like a well-oiled, data-powered machine. + + +## Reverse ETL use cases + +Just as there are almost endless opportunities with data, there are many potential different use cases for reverse ETL. We won’t go into every possible option, but we’ll cover some of the common use cases that exist for reverse ETL efforts. + +### Personalization + +Reverse ETL allows business users to access data that they normally would only have access to in a BI tool *in the platforms they use every day*. As a result, business users can now use this data to personalize how they create ads, send emails, and communicate with customers. + +Personalization was all the hype a few years ago and now, you rarely ever see an email come into your inbox without some sort of personalization in-place. Data teams using reverse ETL are able to pass down important customer information, such as location, customer lifetime value (CLV), tenure, and other fields, that can be used to create personalized emails, establish appropriate messaging, and segment email flows. All we can say: the possibilities for personalization powered by reverse ETL are endless. + +### Sophisticated paid marketing initiatives + +At the end of the day, businesses want to serve the right ads to the right people (and at the right cost). A common use case for reverse ETL is for teams to use their customer data to create audiences in ad platforms to either serve specific audiences or create lookalikes. While ad platforms have gotten increasingly sophisticated with their algorithms to identify high-value audiences, it usually never hurts to try supplementing those audiences with your own data to create sophisticated audiences or lookalikes. + +### Self-service analytics culture + +We hinted at it earlier, but reverse ETL efforts can be an effective way to promote a self-service analytics culture. When data teams put the data where business users need it, business users can confidently access it on their own, driving even faster insights and action. Instead of requesting a data pull from a data team member, they can find the data they need directly within the platform that they use. Reverse ETL allows business users to act on metrics that have already been built out and validated by data teams without creating ad-hoc requests. + +### “Real-time” data + +It would be amiss if we didn’t mention reverse ETL and the notion of “real-time” data. While you can have the debate over the meaningfulness and true value-add of real-time data another time, reverse ETL can be a mechanism to bring data to end business platforms in a more “real-time” way. + +Data teams can set up syncs in reverse ETL tools at higher cadences, allowing business users to have the data they need, faster. Obviously, there’s some cost-benefit analysis on how often you want to be loading data via [ETL tools](https://www.getdbt.com/analytics-engineering/etl-tools-a-love-letter/) and hitting your data warehouse, but reverse ETL can help move data into external tools at a quicker cadence if deemed necessary. + +All this to say: move with caution in the realm of “real-time”, understand your stakeholders’ wants and decision-making process for real-time data, and work towards a solution that’s both practical and impactful. + +## Reverse ETL tools + +Reverse ETL tools typically establish the connection between your data warehouse and end business tools, offer an interface to create additional transformations or audiences, and support automation of downstream syncs. Below are some examples of tools that support reverse ETL pipelines. + +| Tool | Description | Open source option? | +|:---:|:---:|:---:| +| Hightouch | A platform to sync data models and create custom audiences for downstream business platforms. | :x: | +| Census | Another reverse ETL tool that can sync data from your data warehouse to your go-to-market tools. | :x: | +| Rudderstack | Also a CDP (customer data platform), Rudderstack additionally supports pushing down data and audience to external tools, such as ad platforms and email CRMs. | :white_check_mark: | +| Grouparoo | Grouparoo, part of Airbyte, is an open source framework to move data from data warehouses to different cloud-based tools. | :white_check_mark: | + +## Conclusion + +Reverse ETL enables you to sync your transformed data stored in your data warehouse to external platforms often used by marketing, sales, and product teams. It allows you to leverage your data in a whole new way. Reverse ETL pipelines can support personalization efforts, sophisticated paid marketing initiatives, and ultimately offer new ways to leverage your data. In doing this, it creates a self-service analytics culture where stakeholders can receive the data they need in, in the places they need, in an automated way. + +## Further reading + +If you’re interested learning more about reverse ETL and the impact it could have on your team, check out the following: + +- [How dbt Labs’s data team approaches reverse ETL](https://getdbt.com/open-source-data-culture/reverse-etl-playbook/) +- [The operational data warehouse in action: Reverse ETL, CDPs, and the future of data activation](https://www.getdbt.com/coalesce-2021/operational-data-warehouse-reverse-etl-cdp-data-activation/) +- [The analytics engineering guide: Operational analytics](https://www.getdbt.com/analytics-engineering/use-cases/operational-analytics/) diff --git a/website/docs/terms/subquery.md b/website/docs/terms/subquery.md new file mode 100644 index 00000000000..d7aecdd52cc --- /dev/null +++ b/website/docs/terms/subquery.md @@ -0,0 +1,224 @@ +--- +id: subquery +title: Subquery in SQL +description: "A subquery is what the name suggests: a query within another query. The true inception of SQL. Subqueries are often used when you need to process data in several steps." +displayText: subquery +hoverSnippet: A subquery is a query within another query. Subqueries are often used when you need to process data in multiple steps. +--- + + + What is a Subquery in SQL and when are they useful? - dbt Labs + +A subquery is what the name suggests: a query within another query. _The true inception of SQL_. Subqueries are often used when you need to process data in several steps. For the majority of subqueries you’ll see in actual practice, the inner query will execute first and pass its result to the outer query it's nested in. + +Subqueries are usually contrasted with Common Table Expressions (CTEs) as they have similar use cases. Unlike CTEs, which are usually separate `SELECT` statements within a query, subqueries are usually `SELECT` statements nested within a `JOIN`, `FROM`, or `WHERE` statement in a query. + +To be honest, we rarely write subqueries here at dbt Labs since we prefer to use CTEs. We find that CTEs, in general, support better query readability, organization, and debugging. However, subqueries are a foundational concept in SQL and still widely used. We hope you can use this glossary to better understand how to use subqueries and how they differ from CTEs. + +## Subquery syntax + +While there are technically several types of subqueries, the general syntax to build them is the same. A subquery usually consists of the following: + +- Enclosing parentheses +- A name +- An actual SELECT statement +- A main query it is nested in via a FROM, WHERE, or JOIN clause + +Let’s take this to an example, using the [sample jaffle_shop dataset](https://github.com/dbt-labs/jaffle_shop). + +```sql +select customer_id, count(order_id) as cnt_orders + from ( + select * from {{ ref('orders') }} + ) all_orders +group by 1 +``` + +Given the elements of subqueries laid out in the beginning, let’s break down this example into its respective parts. + +| Subquery elements | Example | +|---|---| +| Enclosing parentheses | :white_check_mark: | +| Subquery name | `all_orders` | +| `SELECT` statement | `select * from {{ ref('orders') }}` | +| Main query it is nested in | `select customer_id, count(order_id) as cnt_orders from all_orders group by 1` | + +When this query is actually executed, it will start by running the innermost query first. In this case, it would run `select * from {{ ref('orders') }}` first. Then, it would pass those results to the outer query, which is where you grab the count of orders by `customer_id`. + +```note Note +If you want to learn more about what a `ref` is, [check out our documentation on it.](https://docs.getdbt.com/reference/dbt-jinja-functions/ref) +``` + +This is a relatively straightforward example, but should hopefully show you that subqueries start off like most other queries. As you nest more subqueries together, that’s when you unearth the power of subqueries, but also when you start to notice some readability tradeoffs. If you are using subqueries regularly, you'll want to leverage indenting and [strong naming conventions](https://docs.getdbt.com/blog/on-the-importance-of-naming) for your subqueries to clearly distinguish code functionality. + +## Types of subqueries + +In your day-to-day, you won’t normally formalize the names of the different types of subqueries you can write, but when someone uses the term “correlated subquery” at a data conference, you'll want to know what that means! + +### Nested subqueries + +Nested subqueries are subqueries like the one you saw in the first example: a subquery where the inner query is executed first (and once) and passes its result to the main query. The majority of subqueries you will see in the real world are likely to be a nested subquery. These are most useful when you need to process data in multiple steps. + +:::tip Debugging subqueries tip +It’s important to note that since the inner query is executed first in a nested subquery, the inner query must be able to execute by itself. If it’s unable to successfully run independently, it cannot pass results to the outer query. +::: + +### Correlated subqueries + +A correlated subquery is a nested subquery’s counterpart. If nested subqueries execute the inner query first and pass their result to the outer query, correlated subqueries execute the outer query first and pass their result to their inner query. For correlated subqueries, it’s useful to think about how the code is actually executed. + +In a correlated subquery, the outer query will execute row-by-row. For each row, that result from the outer query will be passed to the inner query. Compare this to nested queries: in a nested query, the inner query is executed first and only once before being passed to the outer query. + +These types of subqueries are most useful when you need to conduct analysis on a row-level. + +### Scalar and non-scalar subqueries + +Scalar subqueries are queries that only return a single value. More specifically, this means if you execute a scalar subquery, it would return one column value of one specific row. Non-scalar subqueries, however, can return single or multiple rows and may contain multiple columns. + +You may want to use a scalar subquery if you’re interested in passing only a single-row value into an outer query. This type of subquery can be useful when you’re trying to remove or update a specific row’s value using a Data Manipulation Language (DML) statement. + +## Subquery examples + +You may often see subqueries in joins and DML statements. The following sections contain examples for each scenario. + +### Subquery in a join + +In this example, you want to get the lifetime value per customer using your `raw_orders` and `raw_payments` table. Let’s take a look at how you can do that with a subquery in a join: + +```sql +select + + orders.user_id, + sum(payments.amount) as lifetime_value + +from {{ ref('raw_orders') }} as orders +left join ( + + select + + order_id, + amount + + from {{ ref('raw_payments') }} + +) all_payments +on orders.id = payments.order_id +group by 1 +``` + +Similar to what you saw in the first example, let’s break down the elements of this query. + +| Subquery elements | Example | +|---|---| +| Enclosing parentheses | :white_check_mark: | +| Subquery name | `all_payments` | +| `SELECT` statement | `select order_id, amount from {{ ref('raw_payments') }}` | +| Main query it is nested in | `select orders.user_id, sum(payments.amount) as lifetime_value from {{ ref('raw_orders') }} as orders...` | + +In this example, the `all_payments` subquery will execute first. you use the data from this query to join on the `raw_orders` table to calculate lifetime value per user. Unlike the first example, the subquery happens in the join statement. Subqueries can happen in `JOIN`, `FROM`, and `WHERE` clauses. + +### Subquery in a DML command + +You may also see subqueries used in DML commands. As a jogger, DML commands are a series of SQL statements that you can write to access and manipulate row-level data in database objects. Oftentimes, you’ll want to use a query result in a qualifying `WHERE` clause to only delete, update, or manipulate certain rows of data. + +In the following example, you'll attempt to update the status of certain orders based on the payment method used in the `raw_payments` table. + +```sql +UPDATE raw_orders +set status = 'returned' +where order_id in ( +select order_id +from raw_payments +where payment_method = 'bank_transfer') +``` + +## Subquery vs CTE + +A subquery is a nested query that can oftentimes be used in place of a CTE. Subqueries have different syntax than CTEs, but often have similar use cases. The content won’t go too deep into CTEs here, but it’ll highlight some of the main differences between CTEs and subqueries below. + +| CTE | Subquery | +|---|---| +| Typically more readable since CTEs can be used to give structure to your query | Typically less readable, especially if there are many nested queries | +| Reusable in the same query | Must declare the subquery everytime it is used in a query | +| Allows for recursiveness | Does not allow for recursiveness | +| CTEs must have unique CTE_EXPRESSION_NAMES when used in a query | Subqueries don’t always have to be explicitly named | +| CTEs cannot be used in a `WHERE` clause | Subqueries can be used in a `WHERE` clause | + +### Subquery vs CTE example + +The following example demonstrates the similarities and differences between subqueries and CTEs. Using the [first subquery example](#subquery-in-a-join), you can compare how you would perform that query using subquery or a CTE: + + + + +```sql Subquery example +select customer_id, count(order_id) as cnt_orders + from ( + + select * from {{ ref('orders') }} + + ) all_orders +group by 1 +``` + + + +```sql CTE example +with all_orders as ( + +select * from {{ ref('orders') }} + +), +aggregate_orders as ( + + select + + customer_id, + count(order_id) as cnt_orders + + from all_orders + group by 1 + +) +select * from aggregate_orders +``` + + + + +While the code for the query involving CTEs may be longer in lines, it also allows us to explicitly define code functionality using the CTE name. Unlike the subquery example that executes its inner query and then the outer query, the query using CTEs executes moving down the code. + +Again, choosing to use CTEs over subqueries is a personal choice. It may help to write out the same code functionality in a subquery and with CTEs and see what is more understandable to you. + +## Data warehouse support for subqueries + +Subqueries are likely to be supported across most, if not all, modern data warehouses. Please use this table to see more information about using subqueries in your specific data warehouse. + +| Data warehouse | Supports subqueries? | +|---|---| +| [Snowflake](https://docs.snowflake.com/en/user-guide/querying-subqueries.html) | :white_check_mark: | +| [Amazon Redshift](https://docs.aws.amazon.com/redshift/latest/dg/r_Subquery_examples.html) | :white_check_mark: | +| [Google BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/subqueries) | :white_check_mark: | +| [Databricks](https://docs.databricks.com/sql/language-manual/sql-ref-syntax-qry-query.html) | :white_check_mark: | +| [Postgres](https://www.postgresqltutorial.com/postgresql-subquery/) | :white_check_mark: | + +## Conclusion + +I’m going to be honest, I was hesitant to start writing the glossary page for SQL subqueries. As someone who has been using CTEs almost exclusively in their data career, I was intimidated by this concept. However, I am excited to say: Subqueries are not as scary as I expected them to be! + +At their core, subqueries are nested queries within a main query. They are often implemented in `FROM`, `WHERE`, and `JOIN` clauses and are used to write code that builds on itself. Despite the fact that subqueries are SQL like any other query, it is important to note that subqueries can struggle in their readability, structure, and debugging process due to their nested nature. Because of these downsides, we recommend leveraging CTEs over subqueries whenever possible. + +I have not been made a subquery convert, but I’m walking away from this a little less intimidated by subqueries and I hope you are too. + +## Further reading + +Please check out some of our favorite readings related to subqueries! + +- [Glossary: CTE](https://docs.getdbt.com/terms/cte) +- [On the importance of naming: model naming conventions (Part 1)](https://docs.getdbt.com/blog/on-the-importance-of-naming) diff --git a/website/docs/terms/surrogate-key.md b/website/docs/terms/surrogate-key.md new file mode 100644 index 00000000000..f1cdfa2fafe --- /dev/null +++ b/website/docs/terms/surrogate-key.md @@ -0,0 +1,260 @@ +--- +id: surrogate-key +title: Surrogate key +description: A surrogate key is a unique identifier derived from the data itself. It's commonly a hashed value of multiple columns that will create a unique id for each row. +displayText: surrogate key +hoverSnippet: A surrogate key is a unique identifier derived from the data itself. It often takes the form of a hashed value of multiple columns that will create a uniqueness constraint for each row. +--- + + + What is a surrogate key in database table? - dbt Labs + + +A surrogate key is a unique identifier derived from the data itself. It often takes the form of a hashed value of multiple columns that will create a uniqueness constraint for each row. You will need to create a surrogate key for every table that doesn't have a natural . + +Why would you ever need to make a surrogate key? Shouldn’t all tables innately just have a field that uniquely identifies each row? Now that would be too easy… + +Let’s say you have a table with all license plate numbers and the state of the plate. While license plate numbers are unique to their state, there could be duplicate license plate numbers across different states. So by default, there’s no natural key that can uniquely identify each row here. In order to uniquely identify each record in this table, you could create a surrogate key based on the unique combination of license plate number and its state. + +## Surrogate keys, natural keys, and primary keys oh my! + +Primary keys can be established two ways: naturally or derived through the data in a surrogate key. + +* A __natural key__ is a primary key that is innate to the data. Perhaps in some tables there’s a unique `id` field in each table that would act as the natural key. You can use documentation like entity relationship diagrams (ERDs) to help understand natural keys in APIs or backend application database tables. +* A __surrogate key__ is a hashed value of multiple fields in a dataset that create a uniqueness constraint on that dataset. You’ll essentially need to make a surrogate key in every table that lacks a natural key. + +:::note Note +You may also hear about primary keys being a form of a _constraint_ on a database object. Column constraints are specified in the to create or alter a database object. For data warehouses that support the enforcement of primary key constraints, this means that an error would be raised if a field's uniqueness or non-nullness was broken upon an `INSERT` or `UPDATE` statement. Most modern data warehouses don’t support _and_ enforce [primary key constraints](https://docs.getdbt.com/terms/primary-key#Data-warehouse-support-for-primary-keys), so it’s important to have [automated testing](https://docs.getdbt.com/blog/primary-key-testing#how-to-test-primary-keys-with-dbt) in-place to ensure your primary keys are unique and not null. +::: + +## How surrogate keys are created + +In analytics engineering, you can generate surrogate keys using a hashing method of your choice. Remember, in order to truly create a uniqueness constraint on a database object, you’ll need to hash the fields together that _make each row unique_; when you generate a correct surrogate key for a dataset, you’re really establishing the true of that dataset. + +Let’s take this to an example. Below, there is a table you pull from an ad platform that collects `calendar_date`, `ad_id`, and some performance columns. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
calendar_date + ad_id + impressions + spend + clicks + conversions +
2022-05-16 + 212 + 88744 + 4523.00 + 9432 + 166 +
2022-05-16 + 214 + 323 + 6.49 + 4 + 0 +
2022-05-05 + 212 + 125600 + 117244.56 + 17318 + 56 +
+ + +In this state, this table has no natural key that can act as a primary key. You know the grain of this table: this is showing performance for each `ad_id` per `calendar_date`. Therefore, hashing those two fields will create a uniqueness constraint on this table. + +To create a surrogate key for this table using the MD5 function, run the following: + +```sql +select + md5(calendar_date || ad_id) as unique_id, + * +from {{ source('ad_platform', 'custom_daily_report')}} +``` + +After executing this, the table would now have the `unique_id` field now uniquely identifying each row. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
unique_id + calendar_date + ad_id + impressions + spend + clicks + conversions +
62aef884fbe3470ce7d9a92140b09b17 + 2022-05-16 + 212 + 88744 + 4523.00 + 9432 + 166 +
ea385f7a5e560ef4d8a78f7d913927e4 + 2022-05-16 + 214 + 323 + 6.49 + 4 + 0 +
53a33f257d1d4f2446469ac5adad1c0c + 2022-05-05 + 212 + 125600 + 117244.56 + 17318 + 56 +
+ +## Testing surrogate keys + +Amazing, you just made a surrogate key! You can just move on to the next data model, right? No!! It’s critically important to test your surrogate keys for uniqueness and non-null values to ensure that the correct fields were chosen to create the surrogate key. + +In order to test for null and unique values you can utilize code-based tests like [dbt tests](https://docs.getdbt.com/docs/building-a-dbt-project/tests), that can check fields for nullness and uniqueness. You can additionally utilize simple SQL queries or unit tests to check if surrogate key count and non-nullness is correct. + +## A note on hashing algorithms + +Depending on your data warehouse, there’s several cryptographic hashing options to create surrogate keys. The primary hashing methods include MD5 or other algorithms, like HASH or SHA. Choosing the appropriate hashing function is dependent on your dataset and what your warehouse supports. + + + + + + + + + + + + + + + + + + + + + + +
Hashing algorithm + Bit length + Known collisions? +
HASH + 64 bits + Yes, past ~4 billion elements +
MD5 + 128 bits + Yes, but incredibly unlikely +
SHA256 + 256 bits + No +
+ +:::note Note +A collision occurs when two pieces of data that are different end up hashing to the same value. If a collision occurs, a different hashing method should be used. +::: + + +## Why we like surrogate keys + +Let’s keep it brief: surrogate keys allow data folks to quickly understand the grain of the database object and are compatible across many different data warehouses. + + +### Readability + +Because surrogate keys are comprised of the fields that make a uniqueness constraint on the data, you can quickly identify the grain of the data. For example, if you see in your data model that the surrogate key field is created by hashing the `ad_id` and `calendar_date` fields, you can immediately know the true grain of the data. When you clearly understand the grain of a database object, this can make for an easier understanding of how entities join together and fan out. + + +### Compatibility + +Making a surrogate key involves a relatively straightforward usage of SQL: maybe some coalescing, concatenation, and a hashing method. Most, if not all, modern data warehouses support both the ability to concat, coalesce, and hash fields. They may not have the exact same syntax or hashing functions available, but their core functionality is the same. + +:::tip Tip +dbt supports several macros to help data folks write DRY (don’t repeat yourself) code. The [surrogate_key macro](https://github.com/dbt-labs/dbt-utils#surrogate_key-source) helps you create surrogate keys with the MD5 function without having to worry about coalescing potentially null field values. +::: + + +## Performance concerns for surrogate keys + +In the past, you may have seen surrogate keys take the form of monotonically increasing integers (ex. 1, 2, 3, 4). These surrogate keys were often limited to 4-bit integers that could be indexed quickly. However, in the practice of analytics engineering, surrogate keys derived from the data often take the form of a hashed string value. Given this form, these surrogate keys are not necessarily optimized for performance for large table scans and complex joins. For large data models (millions, billions, trillions of rows) that have surrogate keys, you should materialize them as tables or [incremental models](https://docs.getdbt.com/docs/building-a-dbt-project/building-models/configuring-incremental-models) to help make joining entities more efficient. + +## Conclusion + +Surrogate keys are unique row identifiers that are created by using columns in a database object to create a uniqueness constraint on the data. To create a surrogate key, you will use a cryptographic algorithm usually in the form of the MD5 function to hash together fields that create a uniqueness constraint on the dataset. Ultimately, surrogate keys are a great way to create unique row identifiers for database objects that lack them naturally and allow folks to easily identify the grain of the data. + +## Further reading + +Want to learn more about keys, dbt, and everything in-between? Check out the following: + +* [Glossary: Primary keys](https://docs.getdbt.com/terms/primary-key) +* [Generating surrogate keys across warehouses](https://docs.getdbt.com/blog/sql-surrogate-keys) +* [Generating an auto-incrementing ID in dbt](https://discourse.getdbt.com/t/generating-an-auto-incrementing-id-in-dbt/579/2) +* [The most underutilized function in SQL](https://www.getdbt.com/blog/the-most-underutilized-function-in-sql/) \ No newline at end of file diff --git a/website/docs/terms/table.md b/website/docs/terms/table.md new file mode 100644 index 00000000000..08289a84c8e --- /dev/null +++ b/website/docs/terms/table.md @@ -0,0 +1,27 @@ +--- +id: table +title: Table +displayText: table +hoverSnippet: In simplest terms, a table is the direct storage of data in rows and columns. Think excel sheet with raw values in each of the cells. +--- +:::important This page could use some love +This term would benefit from additional depth and examples. Have knowledge to contribute? [Create a discussion in the docs.getdbt.com GitHub repository](https://github.com/dbt-labs/docs.getdbt.com/discussions) to begin the process of becoming a glossary contributor! +::: + +In simplest terms, a table is the direct storage of data in rows and columns. Think excel sheet with raw values in each of the cells. + +Here is an example of a table: + +| character_id | first_name | last_name | email | +| ------------ | ------------ | --------- | --------------------- | +| 01 | Frodo | Baggins | frodo@lotr.com | +| 02 | Bilbo | Baggins | bilbo@theshire.co.uk | +| 03 | Gandalf | The Grey | greywizard1@gmail.com | + +Tables do use storage in your . The data can be queried directly because you are directly pulling from the raw data itself. If a particular table was created by underlying data, the table will not be automatically updated. + +This table definition applies to most data warehouses, however, there are different flavors of tables for different warehouses. For example, Snowflake has transient and temporary tables that support different features. + +## Why are tables useful? + +Tables are an excellent choice for persisting transformed data in your warehouse at the time of execution. However, if the underlying data used is changed, the table will not reflect the underlying changes. If that is something you need, dbt Labs recommends views. diff --git a/website/docs/terms/view.md b/website/docs/terms/view.md new file mode 100644 index 00000000000..7357e8c60c8 --- /dev/null +++ b/website/docs/terms/view.md @@ -0,0 +1,35 @@ +--- +id: view +title: View +displayText: view +hoverSnippet: A view (as opposed to a table) is a defined passthrough SQL query that can be run against a database (or data warehouse). +--- +:::important This page could use some love +This term would benefit from additional depth and examples. Have knowledge to contribute? [Create a discussion in the docs.getdbt.com GitHub repository](https://github.com/dbt-labs/docs.getdbt.com/discussions) to begin the process of becoming a glossary contributor! +::: + +A view (as opposed to a ) is a defined passthrough SQL query that can be run against a database (or ). A view doesn’t store data, like a table does, but it defines the logic that you need to fetch the underlying data. + +For example, you might define a SQL view to count new users in a day: + +```sql + select + created_date, + count(distinct(user_id)) as new_users + from users + group by created_date +``` + +But this SQL might get tedious to write over and over again, so instead you could define it as a view called `new_users`, and instead query `select * from new_users`. + +When that `new_users` query runs, the underlying view compiles and runs against the database. + +## Tips on using views + +A healthy relationship with views is built on expectations. + +You shouldn’t expect a view in itself to be your final destination in terms of data modeling (they’re slow + often more costly to query than tables, not great for connecting to a downstream process like reporting), but you should trust them to get you from point A to point B. + +## Further reading + +- [Best practices guide on choosing table vs view materializations](/guides/best-practices) diff --git a/website/docs/tutorial/1-setting-up.md b/website/docs/tutorial/1-setting-up.md deleted file mode 100644 index 3ebaacc98d2..00000000000 --- a/website/docs/tutorial/1-setting-up.md +++ /dev/null @@ -1,123 +0,0 @@ ---- -title: Setting up -id: setting-up ---- - -In this tutorial, we will be turning the below query into a dbt project that is tested, documented, and deployed — you can check out the generated documentation for the project we're building [here](https://www.getdbt.com/getting-started-tutorial/#!/overview?g_v=1). - -This tutorial is geared at first-time users who want detailed instructions on how to go from zero to a deployed dbt project. You'll need a working knowledge of SQL in order to do this tutorial. - - - - -We recommend you go through this project once from beginning to end. Once you've completed it, you should go back through and read some of the FAQs to broaden your understanding of dbt. - -This tutorial is based on a fictional business named `jaffle_shop`, so you'll see this name used throughout the project. At this organization, the following query is used to build a `customers` table. - -```sql -with customers as ( - - select - id as customer_id, - first_name, - last_name - - from `dbt-tutorial`.jaffle_shop.customers - -), - -orders as ( - - select - id as order_id, - user_id as customer_id, - order_date, - status - - from `dbt-tutorial`.jaffle_shop.orders - -), - -customer_orders as ( - - select - customer_id, - - min(order_date) as first_order_date, - max(order_date) as most_recent_order_date, - count(order_id) as number_of_orders - - from orders - - group by 1 - -), - - -final as ( - - select - customers.customer_id, - customers.first_name, - customers.last_name, - customer_orders.first_order_date, - customer_orders.most_recent_order_date, - coalesce(customer_orders.number_of_orders, 0) as number_of_orders - - from customers - - left join customer_orders using (customer_id) - -) - -select * from final -``` - -## Create a BigQuery project -For this tutorial, we've created a public dataset in BigQuery that anyone can `select` from. - -We're using BigQuery since anyone with a Google Account can use BigQuery, but dbt works with [many data warehouses](available-adapters). - -:::info -BigQuery has a generous free tier. If you have an existing GCP account that has surpassed these tiers on BigQuery, running queries for this tutorial will incur a very small (less than a few USD) cost. -::: - - - -1. Go to [the BigQuery Console](https://console.cloud.google.com/bigquery) — if you don't have a Google Cloud Platform account you will be asked to create one. -2. Create a new project for this tutorial — if you've just created a BigQuery account, you'll be prompted to create a new project straight away. If you already have an existing account, you can select the project drop down in the header bar, and create a new project from there. - -3. Head back to [the BigQuery Console](https://console.cloud.google.com/bigquery), and ensure your new project is selected. Copy and paste the above query into the Query Editor to validate that you are able to run it successfully. - - - -### FAQs - - -## Generate BigQuery credentials -In order to let dbt connect to your warehouse, you'll need generate a keyfile. This is analogous to using a database user name and password with most other data warehouses. - - - -1. Go to the [BigQuery credential wizard](https://console.cloud.google.com/apis/credentials/wizard). Ensure that your new project is selected in the header bar. -2. Generate credentials with the following options: - * **Which API are you using?** BigQuery API - * **What data will you be accessing?** Application data (you'll be creating a service account) - * **Are you planning to use this API with App Engine or Compute Engine?** No - * **Service account name:** `dbt-user` - * **Role:** BigQuery Job User & BigQuery User - * **Key type:** JSON -3. Download the JSON file and save it in an easy-to-remember spot, with a clear filename (e.g. `dbt-user-creds.json`) - -### FAQs - - -## Choose the way you want to develop -There’s two main ways of working with dbt: - -1. Edit files and run projects using the web-based Integrated Development Environment (IDE) in **dbt Cloud**. -2. Edit files locally using a code editor, and run projects using the Command Line Interface (**dbt CLI**). - -To use the CLI, it's important that you know some basics of your terminal. In particular, you should understand `cd`, `ls` and `pwd` to navigate through the directory structure of your computer easily. As such, if you are new to programming, we recommend using **dbt Cloud** for this tutorial. - -If you wish to use the CLI, please follow the [installation instructions](/dbt-cli/install/overview) for your operating system. diff --git a/website/docs/tutorial/2a-create-a-project-dbt-cloud.md b/website/docs/tutorial/2a-create-a-project-dbt-cloud.md deleted file mode 100644 index a22a147871f..00000000000 --- a/website/docs/tutorial/2a-create-a-project-dbt-cloud.md +++ /dev/null @@ -1,62 +0,0 @@ ---- -title: 'dbt Cloud: Create a project' -sidebar_label: dbt Cloud -id: create-a-project-dbt-cloud -description: Now that we're set up, let's create a starter project with example models in dbt Cloud. ---- - -Now that we've successfully run our sample query in BigQuery, and chosen the way we want to develop, we can create a dbt project! In this step, we'll create a starter project with example models, before we build our own models. - -:::info - -These are the instructions for developing a project in dbt Cloud. If you're -using the dbt CLI, follow the instructions [here](/tutorial/create-a-project-dbt-cli) - -::: - - - -## Create the starter project -1. Create a dbt Cloud account [here](https://cloud.getdbt.com/signup/). If your organization already has a dbt Cloud account, ask an admin to add you as a Developer. -2. If you created a new account, a new project should automatically be created. If you were added to an existing account: - * Click the hamburger menu, then `Account Settings`, then `Projects`. - * Name your project "dbt Tutorial", and click `Save`. There's no need to fill in the other details. - * Click the hamburger menu, and then `Home`. - * Switch the project in the header bar to your new "dbt Tutorial" project. -3. Complete the project setup flow: - * Connect to BigQuery using the credentials file from the [Setting Up](/tutorial/setting-up) instructions. - * Add a repository — choose managed repository, and name it `dbt-tutorial`. If you're comfortable with git, you can also choose to link to an existing, but bare, repository. - - - -4. Go to the `Develop` interface by either: - * Selecting `Start Developing`, or - * Selecting the hamburger menu, and then `Develop`. -5. Select `Initialize a project` to create your project. You should see a directory structure with `.sql` and `.yml` files that were generated by the `init` command. - - -6. Update the following values in the `dbt_project.yml` file: - - - -```yaml -name: jaffle_shop # this normally says my_new_package - -... - -models: - jaffle_shop: #this normally says my_new_package. It should match the value for `name:` - ... -``` - - - -## Perform your first dbt run -Our sample project has some example models in it. We're going to check that we can run them to confirm everything is in order. In the terminal bar at the bottom of the screen, type in `dbt run` and hit enter. - - - -## Commit your changes -We need to commit our changes so that our repository has up-to-date code. Click the `commit` button, with a message like "Create a starter project" - - diff --git a/website/docs/tutorial/2b-create-a-project-dbt-cli.md b/website/docs/tutorial/2b-create-a-project-dbt-cli.md deleted file mode 100644 index 1582eb70584..00000000000 --- a/website/docs/tutorial/2b-create-a-project-dbt-cli.md +++ /dev/null @@ -1,146 +0,0 @@ ---- -title: 'dbt CLI: Create a project' -sidebar_label: dbt CLI -id: create-a-project-dbt-cli -description: Now that we're set up, let's create a starter project with example models using the dbt CLI. ---- - -Now that we've successfully run our sample query in BigQuery, and chosen the way we want to develop, we can create a dbt project! In this step, we'll create a starter project with example models, before we build our own models. - -:::info - -These are the instructions for developing a project using the dbt CLI. If you're developing in dbt Cloud, follow the instructions [here](/tutorial/create-a-project-dbt-cloud). - -::: - -## Create a repository -We're going to use [GitHub](https://github.com/) as our git provider for this tutorial, but you can use any git provider. If you don't yet have a GitHub account, [create one now](https://github.com/join). - - -1. Create a new GitHub repository [here](https://github.com/new) named `dbt-tutorial`. -2. Click **Create repository** (without `.gitignore` and without a license). - - - - -## Create a project - - -The dbt CLI comes with a command to help you scaffold a dbt project. To create your dbt project: -1. Ensure dbt is installed by running `dbt --version`: -```shell-session -$ dbt --version -``` - -:::info - -dbt should have been installed as part of the [Setting Up](/tutorial/setting-up) part of the tutorial. If it was not installed, please follow the [installation instructions](dbt-cli/install/overview). - -::: - -2. Run the `init` command: -```shell-session -$ dbt init jaffle-shop -``` -3. `cd` into your project: -```shell-session -$ cd jaffle-shop -``` -You can use `pwd` to confirm that you are in the right spot. - -3. Open your project (i.e. the directory you just created) in a code editor like Atom or VSCode. You should see a directory structure with `.sql` and `.yml` files that were generated by the `init` command. - - - - -4. Update the following values in the `dbt_project.yml` file: - - - -```yaml -name: jaffle_shop # this normally says my_new_project - -... - -profile: jaffle_shop # this normally says default - -... - -models: - jaffle_shop: #this normally says my_new_project. It should match the value for `name:` - ... -``` - - - -## Connect to BigQuery -When developing locally, dbt connects to your data warehouse using a [profile](/dbt-cli/configure-your-profile) — a yaml file with all the connection details to your warehouse. - -1. Create a file in the `~/.dbt/` directory named `profiles.yml`. -2. Move your BigQuery keyfile into this directory. -3. Copy the following into the file — make sure you update the values where indicated. - - - -```yaml -jaffle_shop: # this needs to match the profile: in your dbt_project.yml file - target: dev - outputs: - dev: - type: bigquery - method: service-account - keyfile: /Users/claire/.dbt/dbt-user-creds.json # replace this with the full path to your keyfile - project: grand-highway-265418 # Replace this with your project id - dataset: dbt_alice # Replace this with dbt_your_name, e.g. dbt_bob - threads: 1 - timeout_seconds: 300 - location: US - priority: interactive -``` - - - -4. Execute the debug command from your project to confirm that you can successfully connect -```shell-session -$ dbt debug -``` -Confirm that the last line of the output is `Connection test: OK connection ok`. - - - -### FAQs - - - - - - - -## Perform your first dbt run -Our sample project has some example models in it. We're going to check that we can run them to confirm everything is in order. - -1. Execute the `run` command to build the example models: -```shell-session -$ dbt run -``` -You should have an ouput that looks like this: - - - -## Commit your changes -We need to commit our changes so that our repository has up-to-date code. - - -1. Link the GitHub repository you created to your dbt project by running the following commands. Make sure you use the correct git URL for your repository. -```shell-session -$ git init -$ git branch -M main -$ git add . -$ git commit -m "Create a dbt project" -$ git remote add origin https://github.com/USERNAME/dbt-tutorial.git -$ git push -u origin main -``` - -:::info -If this is your first time using git, it's worth taking some time to understand the basics. -::: diff --git a/website/docs/tutorial/3-build-your-first-models.md b/website/docs/tutorial/3-build-your-first-models.md deleted file mode 100644 index 02e2b6441c3..00000000000 --- a/website/docs/tutorial/3-build-your-first-models.md +++ /dev/null @@ -1,295 +0,0 @@ ---- -title: Build your first models -id: build-your-first-models -description: With our starter project setup, it's time to get to the fun part — building models! ---- - -With our starter project setup, it's time to get to the fun part — building [models](building-models)! We're going to take the query from the [Setting up](/tutorial/setting-up) instructions, and turn it into a model in our dbt project. - -## Checkout a new git branch - - -
- -1. Ensure you're in the Develop interface. If you're not, click the hamburger menu, and then `Develop`. The master branch should now be set to "read only" mode, so you'll need to create a new branch. - -2. Click the "create new branch" button, and name your branch `add-customers-model`. - - -
-
- -It's a good idea to check out a new git branch when working on new code. - -1. Run `git checkout -b add-customers-model` to create a new branch. - - - -
-
- -## Build your first model - - -
- - - -1. Ensure you're in the Develop interface. If you're not, click the hamburger menu, and then `Develop`. -2. Create a new file in the `models` directory named `models/customers.sql`. -3. Paste the query from the [Setting up](/tutorial/setting-up) instructions into the file. -4. Execute `dbt run` in the command prompt at the bottom of the screen. You should get a successful run, like so: - - - -If you switch back to the BigQuery console you'll be able to `select` from this model. - -
-
- - - -1. Open your project in a code editor -2. Create a new SQL file in the `models` directory, named `models/customers.sql`. -3. Paste the query from the [Setting up](/tutorial/setting-up) instructions into the file. -4. From the command line, execute `dbt run`. Your output should look like this: - - - -If you switch back to the BigQuery console you'll be able to `select` from this model. - -
-
- -### FAQs - - - - - - - - -## Change the way your model is materialized - -One of the most powerful features of dbt is that you can change the way a model is materialized in your warehouse, simply by changing a configuration value. Let's see this in action. - -:::info Using the `+` sign in your `dbt_project.yml` -These videos were recorded with a slightly older version of dbt (dbt v0.15.0), which did not use the `+` sign in the `dbt_project.yml` file (this was introduced in dbt v0.17.0). - -We'll try to update the videos soon, but for now, take extra note of the `+` signs in the code samples below, under the `models:` key. - -::: - - - - - - -1. Edit the following in your `dbt_project.yml` file: - - - -```yaml -models: - jaffle_shop: - +materialized: table - example: - +materialized: view -``` - - - -2. Execute `dbt run`. Your model, `customers` should now be built as a table! -:::info -To do this, dbt had to first run a `drop view` statement (or API call on BigQuery), then a `create table as` statement. -::: - - -3. Edit `models/customers.sql` to have the following snippet at the top: - - - -```sql -{{ - config( - materialized='view' - ) -}} - -with customers as ( - - select - id as customer_id - ... - -) - -``` - - - -4. Execute `dbt run`. Your model, `customers` should be built as a view. You may need to run `dbt run --full-refresh` for this to take effect on BigQuery. - -### FAQs - - - - -## Delete the example models - -We don't need the sample files that dbt created for us anymore! Let's delete them. - - - - - - -1. Delete the `models/example/` directory -2. Delete the `example:` key from your `dbt_project.yml` file, and any configurations that are listed under it - - - -```yaml -# before -models: - jaffle_shop: - +materialized: table - example: - +materialized: view -``` - - - - -```yaml -# after -models: - jaffle_shop: - +materialized: table -``` - - - -### FAQs - - - - -## Build models on top of other models -Often, it's a good idea to clean your data in one place, before doing additional transformations downstream. Our query already uses CTEs to this effect, but now we're going to experiment with using the [ref](ref) function to separate this clean-up into upstream models, like so: - - - - - - - - - -1. Create a new SQL file, `models/stg_customers.sql`, with the SQL from the `customers` CTE in our original query: - - - -```sql -select - id as customer_id, - first_name, - last_name - -from `dbt-tutorial`.jaffle_shop.customers -``` - - - -2. Create a second new SQL file, `models/stg_orders.sql`, with the SQL from the `orders` CTE in our original query: - - - -```sql -select - id as order_id, - user_id as customer_id, - order_date, - status - -from `dbt-tutorial`.jaffle_shop.orders -``` - - - -3. Edit the SQL in your `models/customers.sql` file as follows: - - - -```sql -with customers as ( - - select * from {{ ref('stg_customers') }} - -), - -orders as ( - - select * from {{ ref('stg_orders') }} - -), - -customer_orders as ( - - select - customer_id, - - min(order_date) as first_order_date, - max(order_date) as most_recent_order_date, - count(order_id) as number_of_orders - - from orders - - group by 1 - -), - - -final as ( - - select - customers.customer_id, - customers.first_name, - customers.last_name, - customer_orders.first_order_date, - customer_orders.most_recent_order_date, - coalesce(customer_orders.number_of_orders, 0) as number_of_orders - - from customers - - left join customer_orders using (customer_id) - -) - -select * from final -``` - - - -4. Execute `dbt run` - -This time when dbt ran, separate views/tables were created for `stg_customers`, `stg_orders` and `customers`. dbt was able to infer the order in which to run these models in — `customers` depends on `stg_customers` and `stg_orders`, so gets built last. There's no need to explicitly define these dependencies. - - -### FAQs - - - - -## Extra exercises -* Write some bad SQL to cause an error — can you debug this error? -* Run only a single model at a time ([docs](/reference/node-selection/syntax)) -* Group your models with a `stg_` prefix into a `staging` subdirectory (i.e. `models/staging/stg_customers.sql`) - * Configure your `staging` models to be views - * Run only the `staging` models - - - - - diff --git a/website/docs/tutorial/4-test-and-document-your-project.md b/website/docs/tutorial/4-test-and-document-your-project.md deleted file mode 100644 index bbc7b6da253..00000000000 --- a/website/docs/tutorial/4-test-and-document-your-project.md +++ /dev/null @@ -1,160 +0,0 @@ ---- -title: Test and document your project -id: test-and-document-your-project -description: Let's test and document our models to build trust in our data. ---- - -## Add tests to your models -Adding [tests](/docs/building-a-dbt-project/tests) to a project helps validate that your models are working correctly. So let's add some tests to our project! - - - - - - -1. Create a new YAML file in the `models` directory, named `models/schema.yml` -2. Add the following contents to the file: - - - -```yaml -version: 2 - -models: - - name: customers - columns: - - name: customer_id - tests: - - unique - - not_null - - - name: stg_customers - columns: - - name: customer_id - tests: - - unique - - not_null - - - name: stg_orders - columns: - - name: order_id - tests: - - unique - - not_null - - name: status - tests: - - accepted_values: - values: ['placed', 'shipped', 'completed', 'return_pending', 'returned'] - - name: customer_id - tests: - - not_null - - relationships: - to: ref('stg_customers') - field: customer_id - -``` - - - -3. Execute `dbt test`, and confirm that all your tests passed. - - - - - - -:::info - -When you run `dbt test`, dbt iterates through your YAML files, and constructs a query for each test. Each query will return the number of records that fail the test. If this number is 0, then the test is successful. - -::: - -### FAQs - - - - - - - - - -## Document your models -Adding [documentation](/docs/building-a-dbt-project/documentation) to your project allows you to describe your models in rich detail, and share that information with your team. Here, we're going to add some basic documentation to our project. - - - - - - -1. Update your `models/schema.yml` file to include some descriptions, such as those below. - - - -```yaml -version: 2 - -models: - - name: customers - description: One record per customer - columns: - - name: customer_id - description: Primary key - tests: - - unique - - not_null - - name: first_order_date - description: NULL when a customer has not yet placed an order. - - - name: stg_customers - description: This model cleans up customer data - columns: - - name: customer_id - description: Primary key - tests: - - unique - - not_null - - - name: stg_orders - description: This model cleans up order data - columns: - - name: order_id - description: Primary key - tests: - - unique - - not_null - - name: status - tests: - - accepted_values: - values: ['placed', 'shipped', 'completed', 'return_pending', 'returned'] - -``` - - - -2. Execute `dbt docs generate` to generate the documentation for your project. dbt introspects your project and your warehouse to generate a json file with rich documentation about your project. -3. [CLI] Execute `dbt docs serve` to launch the documentation in a local website. [Cloud] Click the link above the file tree in the develop interface to launch documentation in a new tab. - - -:::tip - -Great work ⭐️! You've just built your first dbt project that's tested and documented! - -::: - - -### FAQs - - - - -## Extra exercises - - - - - - -* Write a test that fails, for example, omit one of the order statuses in the `accepted_values` list. What does a failing test look like? Can you debug the failure? -* Run the tests for one model only. If you grouped your `stg_` models into a directory, try running the tests for all the models in that directory. -* Use a [docs block](/docs/building-a-dbt-project/documentation#using-docs-blocks) to add a Markdown description to a model. diff --git a/website/docs/tutorial/5-deploy-your-project.md b/website/docs/tutorial/5-deploy-your-project.md deleted file mode 100644 index ce916e6255a..00000000000 --- a/website/docs/tutorial/5-deploy-your-project.md +++ /dev/null @@ -1,94 +0,0 @@ ---- -title: Deploy your project -id: deploy-your-project -description: In this part of the tutorial, we'll go through how you can deploy your project with dbt Cloud. ---- - -As the `jaffle_shop` business gains more customers, and those customers create more orders, there will be more records added to your source data. Since the `customers` model is materialized as a table, you'll need to periodically rebuild your table to ensure that the data stays up-to-date. - -This is often referred to as "deploying a project" or "[running a project in production](/docs/running-a-dbt-project/running-dbt-in-production)". In this part of the tutorial, we'll go through how you can deploy your project with dbt Cloud. - -## Commit your changes -First off, we need to commit the changes we made to our project so that our repository has our latest code. - -### dbt Cloud - - -1. Click the `commit` button, with a message like "Add customers model, tests, docs" -2. Click the `merge to master` button - -### dbt CLI - - -1. Add all your changes to git: `git add -A` -2. Commit your changes: `git commit -m "Add customers model, tests, docs"` -3. Push your changes to your repository: `git push` -4. Navigate to your repository, and open a Pull Request to merge the code into your master branch. - -## Connect dbt Cloud to your repository -Connecting dbt Cloud to your repository will allow you to have the latest code whenever your dbt project runs. - -:::info -This step only applies to folks who use the dbt CLI to develop their project. If you developed your project in dbt Cloud, you can skip this step! -::: - - - -1. Create a dbt Cloud account [here](https://cloud.getdbt.com/signup/). If your organization already has a dbt Cloud account, ask an admin to add you as a Developer. -2. If you created a new account, a new project should automatically be created. If you were added to an existing account: - * Click the hamburger menu, then `Account Settings`, then `Projects`. - * Name your project "dbt Tutorial", and click `Save`. There's no need to fill - in the other details. - * Click the hamburger menu, and then `Home`. - * Switch the project in the header bar to your new "dbt Tutorial" project. -3. Complete the onboarding flow: - * Connect to BigQuery using the credentials file from the [Setting Up](/tutorial/setting-up) instructions. - * Add a repository — choose the GitHub integration, and connect to your `dbt-tutorial` repository that we set up on the [Create a Project](/tutorial/create-a-project-dbt-cli) instructions. - - -## Create a deployment environment - - -1. Click the hamburger menu, and then `Home` -2. Under "Deployment Environments" select "Create a new one" -3. Name your deployment environment (e.g. "Production") -4. Add a target dataset (e.g. "analytics") -- this is the dataset that dbt will build into. For other warehouses this is usually named "schema" - -## Create and run a job -_See above video_ - -Jobs are a set of dbt commands (e.g. `dbt run`, `dbt test`) that you want to run on a schedule. - -1. After creating your deployment environment, you should be directed to the page for new environment. If not, select the hamburger menu, and then `Jobs`. -2. Click `New Job` giving it a name (e.g. "Production run"), and linking it to the Environment you just created. -3. Check the box for "Generate docs". -4. Ensure you have the following commands as part of your job: - * `dbt run` - * `dbt test` -5. **Do not** set a schedule for your project to run -- while your organization's project **should** run regularly, there's no need to run this project on a schedule, and doing so could result in using up your BigQuery credits. -6. Select `Save`, and then `Run now` to run your job. -7. Click into the run to see the progress — once the run is complete, click "View Documentation" to see the docs for your project. - -### FAQs - - -## Next steps - -:::tip -Congratulations 🎉! You've just deployed your first dbt project! -::: - -Here's a few suggestions to keep learning: - -### Start working on your own project -Ready to get started with your own project? We recommend doing the tutorial a second time to create a new project. You should use your own warehouse, along with a query that you frequently run, to build your first models! - -### Learn some best practices -Now that you've got a working dbt project, read more about some of our [best practices](/docs/guides/best-practices), or go back this tutorial and read some of the FAQs. - -### Keep building this project -Here's some suggested exercises to level-up your dbt skills: -* Try turning your raw data references (e.g. `` `dbt-tutorial`.jaffle_shop.orders``) into [sources](/docs/building-a-dbt-project/using-sources). -* Build a new models for `orders`, that uses the `payments` table to calculate the total order amount. -* Reorganize your project into our [recommended structure](https://discourse.getdbt.com/t/how-we-structure-our-dbt-projects/355) -* Use some Jinja in your project — check out the [Jinja tutorial](/tutorial/using-jinja). diff --git a/website/docs/useful_components.md b/website/docs/useful_components.md deleted file mode 100644 index ba0223692c4..00000000000 --- a/website/docs/useful_components.md +++ /dev/null @@ -1,105 +0,0 @@ -## Tabs for configs on multiple resources - - - - - - - -```sql - -{{ config( - -) }} - -select ... - - -``` - - - - - -```yml -models: - [](resource-path): - - -``` - - - - - - - - - -```yml -sources: - [](resource-path): - - -``` - - - - - - - - - -```yml -seeds: - [](resource-path): - - -``` - - - - - - - - - -```sql -{% snapshot [snapshot_name](snapshot_name) %} - -{{ config( - -) }} - -select ... - -{% endsnapshot %} - -``` - - - - - -```yml -snapshots: - [](resource-path): - enabled: true | false - -``` - - - - - - diff --git a/website/docusaurus.config.js b/website/docusaurus.config.js index 11f090d1e3a..ebdea716aea 100644 --- a/website/docusaurus.config.js +++ b/website/docusaurus.config.js @@ -1,5 +1,9 @@ - const path = require('path'); +const math = require('remark-math'); +const katex = require('rehype-katex'); +const { versions, versionedPages } = require('./dbt-versions'); +require('dotenv').config() + /* Debugging */ var SITE_URL; @@ -16,38 +20,11 @@ if (!process.env.CONTEXT || process.env.CONTEXT == 'production') { GIT_BRANCH = process.env.HEAD; } -var PRERELEASE = (process.env.PRERELEASE || false); - -var WARNING_BANNER; -if (!PRERELEASE) { - WARNING_BANNER = {}; -} else { - WARNING_BANNER = { - id: 'prerelease', // Any value that will identify this message. - content: - 'CAUTION: Prerelease! This documentation reflects the next minor version of dbt. View current docs.', - backgroundColor: '#ffa376', // Defaults to `#fff`. - textColor: '#033744', // Defaults to `#000`. - } -} - -var ALGOLIA_API_KEY; -if (!process.env.ALGOLIA_API_KEY) { - ALGOLIA_API_KEY = '0e9665cbb272719dddc6e7113b4131a5'; -} else { - ALGOLIA_API_KEY = process.env.ALGOLIA_API_KEY; -} - -var ALGOLIA_INDEX_NAME; -if (!process.env.ALGOLIA_INDEX_NAME) { - ALGOLIA_INDEX_NAME = 'dbt'; -} else { - ALGOLIA_INDEX_NAME = process.env.ALGOLIA_INDEX_NAME; -} +let { ALGOLIA_APP_ID, ALGOLIA_API_KEY, ALGOLIA_INDEX_NAME } = process.env; let metatags = [] // If Not Current Branch, do not index site -if(GIT_BRANCH !== 'current') { +if (GIT_BRANCH !== 'current') { metatags.push({ tagName: 'meta', attributes: { @@ -60,31 +37,42 @@ if(GIT_BRANCH !== 'current') { console.log("DEBUG: CONTEXT =", process.env.CONTEXT); console.log("DEBUG: DEPLOY_URL =", process.env.DEPLOY_URL); console.log("DEBUG: SITE_URL = ", SITE_URL); -console.log("DEBUG: PRERELEASE = ", PRERELEASE); console.log("DEBUG: ALGOLIA_INDEX_NAME = ", ALGOLIA_INDEX_NAME); console.log("DEBUG: metatags = ", metatags); -module.exports = { +var siteSettings = { baseUrl: '/', favicon: '/img/favicon.ico', - tagline: 'End user documentation, guides and technical reference for dbt (data build tool)', + tagline: 'End user documentation, guides and technical reference for dbt', title: 'dbt Docs', url: SITE_URL, onBrokenLinks: 'warn', - + trailingSlash: false, themeConfig: { image: '/img/avatar.png', colorMode: { - disableSwitch: true + defaultMode: 'light', + disableSwitch: false, + respectPrefersColorScheme: true, }, - announcementBar: WARNING_BANNER, + // Adding non-empty strings for Algolia config + // allows Docusaurus to run locally without .env file algolia: { - apiKey: ALGOLIA_API_KEY, + apiKey: ALGOLIA_API_KEY ? ALGOLIA_API_KEY : 'dbt', + indexName: ALGOLIA_INDEX_NAME ? ALGOLIA_INDEX_NAME : 'dbt', + appId: ALGOLIA_APP_ID ? ALGOLIA_APP_ID : 'dbt' //debug: true, - indexName: ALGOLIA_INDEX_NAME, - algoliaOptions: { - }, }, + announcementBar: { + id: "live_qa", + content: + "Register now for Coalesce 2022. The Analytics Engineering Conference!", + backgroundColor: "#047377", + textColor: "#fff", + isCloseable: true + }, + announcementBarActive: true, + announcementBarLink: "https://coalesce.getdbt.com/", prism: { theme: (() => { var theme = require('prism-react-renderer/themes/nightOwl'); @@ -106,8 +94,10 @@ module.exports = { additionalLanguages: ['bash'], }, navbar: { + hideOnScroll: true, logo: { - src: '/img/dbt-logo-light.svg', + src: '/img/dbt-logo.svg', + srcDark: 'img/dbt-logo-light.svg', alt: 'dbt Logo', }, items: [ @@ -136,25 +126,27 @@ module.exports = { activeBasePath: 'docs/dbt-cloud' }, { - to: '/faqs/all', - label: 'FAQs', + to: '/guides/getting-started', + label: 'Guides', position: 'left', - activeBasePath: 'faqs' + activeBasePath: 'guides' + }, + { + to: '/blog/', + label: 'Developer Blog', + position: 'right', + activeBasePath: 'blog' }, { - label: 'Learn', + label: 'Courses', position: 'right', items: [ { - label: 'Getting Started Tutorial', - to: '/tutorial/setting-up', - }, - { - label: 'Online Courses', + label: 'Online courses', href: 'https://courses.getdbt.com', }, { - label: 'Live Courses', + label: 'Live courses', href: 'https://learn.getdbt.com/public', } ], @@ -163,6 +155,10 @@ module.exports = { label: 'Community', position: 'right', items: [ + { + label: 'Maintaining a Slack Channel', + to: '/community/maintaining-a-channel', + }, { label: 'dbt Slack', href: 'https://community.getdbt.com/', @@ -173,14 +169,34 @@ module.exports = { }, { label: 'GitHub', - href: 'https://github.com/fishtown-analytics/dbt', + href: 'https://github.com/dbt-labs/dbt-core', }, ] }, ], }, footer: { - copyright: `Copyright © ${new Date().getFullYear()} dbt Labs, Inc. All Rights Reserved.`, + links: [ + { + html: ` + + + + ` + }, + ], + + copyright: `Copyright © ${new Date().getFullYear()} dbt Labs™, Inc. All Rights Reserved.` }, }, presets: [ @@ -194,36 +210,88 @@ module.exports = { path: 'docs', routeBasePath: '/', sidebarPath: require.resolve('./sidebars.js'), + remarkPlugins: [math], + rehypePlugins: [katex], - editUrl: 'https://github.com/fishtown-analytics/docs.getdbt.com/edit/' + GIT_BRANCH + '/website/', - showLastUpdateTime: false, + editUrl: 'https://github.com/dbt-labs/docs.getdbt.com/edit/' + GIT_BRANCH + '/website/', + showLastUpdateTime: true, //showLastUpdateAuthor: false, sidebarCollapsible: true, - } + }, + blog: { + blogTitle: 'dbt Developer Blog', + blogDescription: 'Technical tutorials from the dbt Community.', + postsPerPage: 20, + blogSidebarTitle: 'Recent posts', + blogSidebarCount: 5, + remarkPlugins: [math], + rehypePlugins: [katex], + }, + }, ], ], plugins: [ [ - path.resolve('plugins/insertMetaTags'), - { metatags } + path.resolve('plugins/insertMetaTags'), + { metatags } ], path.resolve('plugins/svg'), path.resolve('plugins/customWebpackConfig'), + [ + path.resolve('plugins/buildGlobalData'), + { versionedPages } + ], + path.resolve('plugins/buildAuthorPages') ], scripts: [ - 'https://code.jquery.com/jquery-3.4.1.min.js', - 'https://cdn.jsdelivr.net/npm/featherlight@1.7.14/release/featherlight.min.js', + { + src: 'https://code.jquery.com/jquery-3.4.1.min.js', + defer: true + }, + { + src: 'https://cdn.jsdelivr.net/npm/featherlight@1.7.14/release/featherlight.min.js', + defer: true + }, '/js/gtm.js', + 'https://kit.fontawesome.com/7110474d41.js' ], stylesheets: [ '/css/fonts.css', '/css/entypo.css', '/css/search.css', '/css/api.css', - 'https://cdn.jsdelivr.net/npm/featherlight@1.7.14/release/featherlight.min.css', 'https://fonts.googleapis.com/css2?family=Source+Sans+Pro:wght@400;500;600;700&display=swap', - 'https://fonts.googleapis.com/css2?family=Source+Code+Pro:wght@400;500;600;700&display=swap' - ] -}; + 'https://fonts.googleapis.com/css2?family=Source+Code+Pro:wght@400;500;600;700&display=swap', + { + href: 'https://cdn.jsdelivr.net/npm/katex@0.13.24/dist/katex.min.css', + type: 'text/css', + integrity: + 'sha384-odtC+0UGzzFL/6PNoE8rX/SPcQDXBJ+uRepguP4QkPCm2LBxH3FA3y+fKSiJ+AmM', + crossorigin: 'anonymous', + }, + ], +} + +// If versions json file found, add versions dropdown to nav +if (versions) { + siteSettings.themeConfig.navbar.items.push({ + label: 'Versions', + position: 'left', + className: 'nav-versioning', + items: [ + ...versions.reduce((acc, version) => { + if (version?.version) { + acc.push({ + label: `${version.version}`, + href: '#', + }) + } + return acc + }, []) + ] + }) +} + +module.exports = siteSettings; diff --git a/website/functions/get-discourse-topics.js b/website/functions/get-discourse-topics.js new file mode 100644 index 00000000000..2ddc8cce8bf --- /dev/null +++ b/website/functions/get-discourse-topics.js @@ -0,0 +1,138 @@ +const axios = require('axios') + +async function getDiscourseTopics({ body }) { + const { DISCOURSE_API_KEY , DISCOURSE_USER } = process.env + + try { + // Set API endpoint and headers + let discourse_endpoint = `https://discourse.getdbt.com` + let headers = { + 'Accept': 'application/json', + 'Api-Key': DISCOURSE_API_KEY, + 'Api-Username': DISCOURSE_USER, + } + + const query = buildQueryString(body) + if(!query) throw new Error('Unable to build query string.') + + // Get topics from Discourse + let { data: { posts, topics } } = await axios.get(`${discourse_endpoint}/search?q=${query}`, { headers }) + + if(!topics || topics?.length <= 0) + throw new Error('Unable to get results from api request.') + + // Set author and like_count for topics if not querying by specific term + let allTopics = topics + if(!body?.term) { + allTopics = topics.reduce((topicsArr, topic) => { + // Get first post in topic + const firstTopicPost = posts?.find(post => + post?.post_number === 1 && + post?.topic_id === topic?.id + ) + // If post found + // Get username + if(firstTopicPost?.username) { + topic.author = firstTopicPost.username + } + // Get like count + if(firstTopicPost?.like_count) { + topic.like_count = firstTopicPost.like_count + } + + // Push updated topic to array + topicsArr.push(topic) + + return topicsArr + }, []) + } + + // Return topics + return await returnResponse(200, allTopics) + } catch(err) { + // Log and return the error + console.log('err', err) + return await returnResponse(500, { error: 'Unable to get topics from Discourse.'}) + } +} + +async function returnResponse(status, res) { + const headers = { + 'Content-Type': 'application/json', + 'Access-Control-Allow-Origin': '*', + 'Access-Control-Allow-Headers': '*', + 'Access-Control-Allow-Methods': 'POST, OPTIONS' + } + const resObj = { + statusCode: status, + headers, + body: JSON.stringify(res) + } + return resObj +} + +function buildQueryString(body) { + if(!body) return null + + // start with empty query string + let query = '' + + // check param and apply to query if set + for(const [key, value] of Object.entries(JSON.parse(body))) { + // validate categories + // if valid, add to query string + if(validateItem({ key, value })) { + if(key === 'category') { + query += `#${value} ` + } else if(key === 'inString') { + query += `in:${value}` + } else if(key === 'status' && Array.isArray(value)) { + value?.map(item => { + query += `${key}:${item} ` + }) + } else { + query += `${key}:${value} ` + } + } + } + + if(query) { + const encodedQuery = encodeURIComponent(query) + return encodedQuery + } +} + +function validateItem({ key, value }) { + // predefined Discourse values + // https://docs.discourse.org/#tag/Search/operation/search + const inStringValues = ['title', 'first', 'pinned', 'wiki'] + const orderValues = ['latest', 'likes', 'views', 'latest_topic'] + const statusValues = ['open', 'closed', 'public', 'archived', 'noreplies', 'single_user', 'solved', 'unsolved'] + + // validate keys + if(key === 'inString') { + return inStringValues.includes(value) + ? true + : false + } else if(key === 'order') { + return orderValues.includes(value) + ? true + : false + } else if(key === 'status') { + if(Array.isArray(value)) { + let isValid = true + value?.map(item => { + if(!statusValues.includes(item)) isValid = false + }) + return isValid + } else { + return statusValues.includes(value) + ? true + : false + } + } else { + return true + } +} + +exports.handler = getDiscourseTopics diff --git a/website/jest.setup.js b/website/jest.setup.js new file mode 100644 index 00000000000..c44951a680d --- /dev/null +++ b/website/jest.setup.js @@ -0,0 +1 @@ +import '@testing-library/jest-dom' diff --git a/website/package-lock.json b/website/package-lock.json index a419c8b5222..d922ceeb069 100644 --- a/website/package-lock.json +++ b/website/package-lock.json @@ -7,28 +7,47 @@ "": { "version": "0.0.0", "dependencies": { - "@docusaurus/core": "^2.0.0-beta.6", - "@docusaurus/plugin-ideal-image": "^2.0.0-beta.6", - "@docusaurus/preset-classic": "^2.0.0-beta.6", - "@docusaurus/theme-search-algolia": "^2.0.0-beta.6", + "@docusaurus/core": "2.0.0-beta.17", + "@docusaurus/plugin-ideal-image": "2.0.0-beta.17", + "@docusaurus/preset-classic": "2.0.0-beta.17", + "@docusaurus/theme-search-algolia": "2.0.0-beta.17", "@mdx-js/react": "^1.6.21", "@svgr/webpack": "^5.5.0", - "classnames": "^2.2.6", + "axios": "^0.27.2", + "classnames": "^2.3.1", "clsx": "^1.1.1", "color": "^3.1.2", - "core-js": "^3.6.4", + "core-js": "^3.15.2", "file-loader": "^6.2.0", - "mobx": "^6.3.3", + "fs": "0.0.2", + "gray-matter": "^4.0.3", + "hast-util-is-element": "^1.1.0", + "js-yaml": "^4.1.0", + "mobx": "^6.3.7", "node-polyfill-webpack-plugin": "^1.1.4", "prism-react-renderer": "^1.2.1", "react": "^17.0.1", "react-dom": "^17.0.1", + "react-is": "^18.1.0", + "react-tooltip": "^4.2.21", "redoc": "^2.0.0-rc.57", - "styled-components": "^5.0.1", + "rehype-katex": "^5.0.0", + "remark-math": "^3.0.1", + "slugify": "^1.6.1", + "styled-components": "5.3.3", "url-loader": "^4.1.1" }, "devDependencies": { + "@swc/core": "^1.2.174", + "@swc/jest": "^0.2.20", + "@testing-library/jest-dom": "^5.16.2", + "@testing-library/react": "^12.1.3", + "@testing-library/user-event": "^13.5.0", "css-loader": "^3.4.2", + "cypress": "^10.3.0", + "dotenv": "^10.0.0", + "jest": "^27.5.1", + "jest-cli": "^27.5.1", "path-browserify": "^1.0.1", "process": "^0.11.10", "stream-http": "^3.2.0", @@ -38,19 +57,19 @@ } }, "node_modules/@algolia/autocomplete-core": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@algolia/autocomplete-core/-/autocomplete-core-1.2.2.tgz", - "integrity": "sha512-JOQaURze45qVa8OOFDh+ozj2a/ObSRsVyz6Zd0aiBeej+RSTqrr1hDVpGNbbXYLW26G5ujuc9QIdH+rBHn95nw==", + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-core/-/autocomplete-core-1.5.2.tgz", + "integrity": "sha512-DY0bhyczFSS1b/CqJlTE/nQRtnTAHl6IemIkBy0nEWnhDzRDdtdx4p5Uuk3vwAFxwEEgi1WqKwgSSMx6DpNL4A==", "dependencies": { - "@algolia/autocomplete-shared": "1.2.2" + "@algolia/autocomplete-shared": "1.5.2" } }, "node_modules/@algolia/autocomplete-preset-algolia": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@algolia/autocomplete-preset-algolia/-/autocomplete-preset-algolia-1.2.2.tgz", - "integrity": "sha512-AZkh+bAMaJDzMZTelFOXJTJqkp5VPGH8W3n0B+Ggce7DdozlMRsDLguKTCQAkZ0dJ1EbBPyFL5ztL/JImB137Q==", + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-preset-algolia/-/autocomplete-preset-algolia-1.5.2.tgz", + "integrity": "sha512-3MRYnYQFJyovANzSX2CToS6/5cfVjbLLqFsZTKcvF3abhQzxbqwwaMBlJtt620uBUOeMzhdfasKhCc40+RHiZw==", "dependencies": { - "@algolia/autocomplete-shared": "1.2.2" + "@algolia/autocomplete-shared": "1.5.2" }, "peerDependencies": { "@algolia/client-search": "^4.9.1", @@ -58,164 +77,181 @@ } }, "node_modules/@algolia/autocomplete-shared": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@algolia/autocomplete-shared/-/autocomplete-shared-1.2.2.tgz", - "integrity": "sha512-mLTl7d2C1xVVazHt/bqh9EE/u2lbp5YOxLDdcjILXmUqOs5HH1D4SuySblXaQG1uf28FhTqMGp35qE5wJQnqAw==" + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-shared/-/autocomplete-shared-1.5.2.tgz", + "integrity": "sha512-ylQAYv5H0YKMfHgVWX0j0NmL8XBcAeeeVQUmppnnMtzDbDnca6CzhKj3Q8eF9cHCgcdTDdb5K+3aKyGWA0obug==" }, "node_modules/@algolia/cache-browser-local-storage": { - "version": "4.10.5", - "resolved": "https://registry.npmjs.org/@algolia/cache-browser-local-storage/-/cache-browser-local-storage-4.10.5.tgz", - "integrity": "sha512-cfX2rEKOtuuljcGI5DMDHClwZHdDqd2nT2Ohsc8aHtBiz6bUxKVyIqxr2gaC6tU8AgPtrTVBzcxCA+UavXpKww==", + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/@algolia/cache-browser-local-storage/-/cache-browser-local-storage-4.13.0.tgz", + "integrity": "sha512-nj1vHRZauTqP/bluwkRIgEADEimqojJgoTRCel5f6q8WCa9Y8QeI4bpDQP28FoeKnDRYa3J5CauDlN466jqRhg==", "dependencies": { - "@algolia/cache-common": "4.10.5" + "@algolia/cache-common": "4.13.0" } }, "node_modules/@algolia/cache-common": { - "version": "4.10.5", - "resolved": "https://registry.npmjs.org/@algolia/cache-common/-/cache-common-4.10.5.tgz", - "integrity": "sha512-1mClwdmTHll+OnHkG+yeRoFM17kSxDs4qXkjf6rNZhoZGXDvfYLy3YcZ1FX4Kyz0DJv8aroq5RYGBDsWkHj6Tw==" + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/@algolia/cache-common/-/cache-common-4.13.0.tgz", + "integrity": "sha512-f9mdZjskCui/dA/fA/5a+6hZ7xnHaaZI5tM/Rw9X8rRB39SUlF/+o3P47onZ33n/AwkpSbi5QOyhs16wHd55kA==" }, "node_modules/@algolia/cache-in-memory": { - "version": "4.10.5", - "resolved": "https://registry.npmjs.org/@algolia/cache-in-memory/-/cache-in-memory-4.10.5.tgz", - "integrity": "sha512-+ciQnfIGi5wjMk02XhEY8fmy2pzy+oY1nIIfu8LBOglaSipCRAtjk6WhHc7/KIbXPiYzIwuDbM2K1+YOwSGjwA==", + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/@algolia/cache-in-memory/-/cache-in-memory-4.13.0.tgz", + "integrity": "sha512-hHdc+ahPiMM92CQMljmObE75laYzNFYLrNOu0Q3/eyvubZZRtY2SUsEEgyUEyzXruNdzrkcDxFYa7YpWBJYHAg==", "dependencies": { - "@algolia/cache-common": "4.10.5" + "@algolia/cache-common": "4.13.0" } }, "node_modules/@algolia/client-account": { - "version": "4.10.5", - "resolved": "https://registry.npmjs.org/@algolia/client-account/-/client-account-4.10.5.tgz", - "integrity": "sha512-I9UkSS2glXm7RBZYZIALjBMmXSQbw/fI/djPcBHxiwXIheNIlqIFl2SNPkvihpPF979BSkzjqdJNRPhE1vku3Q==", + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/@algolia/client-account/-/client-account-4.13.0.tgz", + "integrity": "sha512-FzFqFt9b0g/LKszBDoEsW+dVBuUe1K3scp2Yf7q6pgHWM1WqyqUlARwVpLxqyc+LoyJkTxQftOKjyFUqddnPKA==", "dependencies": { - "@algolia/client-common": "4.10.5", - "@algolia/client-search": "4.10.5", - "@algolia/transporter": "4.10.5" + "@algolia/client-common": "4.13.0", + "@algolia/client-search": "4.13.0", + "@algolia/transporter": "4.13.0" } }, "node_modules/@algolia/client-analytics": { - "version": "4.10.5", - "resolved": "https://registry.npmjs.org/@algolia/client-analytics/-/client-analytics-4.10.5.tgz", - "integrity": "sha512-h2owwJSkovPxzc+xIsjY1pMl0gj+jdVwP9rcnGjlaTY2fqHbSLrR9yvGyyr6305LvTppxsQnfAbRdE/5Z3eFxw==", + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/@algolia/client-analytics/-/client-analytics-4.13.0.tgz", + "integrity": "sha512-klmnoq2FIiiMHImkzOm+cGxqRLLu9CMHqFhbgSy9wtXZrqb8BBUIUE2VyBe7azzv1wKcxZV2RUyNOMpFqmnRZA==", "dependencies": { - "@algolia/client-common": "4.10.5", - "@algolia/client-search": "4.10.5", - "@algolia/requester-common": "4.10.5", - "@algolia/transporter": "4.10.5" + "@algolia/client-common": "4.13.0", + "@algolia/client-search": "4.13.0", + "@algolia/requester-common": "4.13.0", + "@algolia/transporter": "4.13.0" } }, "node_modules/@algolia/client-common": { - "version": "4.10.5", - "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-4.10.5.tgz", - "integrity": "sha512-21FAvIai5qm8DVmZHm2Gp4LssQ/a0nWwMchAx+1hIRj1TX7OcdW6oZDPyZ8asQdvTtK7rStQrRnD8a95SCUnzA==", + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-4.13.0.tgz", + "integrity": "sha512-GoXfTp0kVcbgfSXOjfrxx+slSipMqGO9WnNWgeMmru5Ra09MDjrcdunsiiuzF0wua6INbIpBQFTC2Mi5lUNqGA==", "dependencies": { - "@algolia/requester-common": "4.10.5", - "@algolia/transporter": "4.10.5" + "@algolia/requester-common": "4.13.0", + "@algolia/transporter": "4.13.0" } }, "node_modules/@algolia/client-personalization": { - "version": "4.10.5", - "resolved": "https://registry.npmjs.org/@algolia/client-personalization/-/client-personalization-4.10.5.tgz", - "integrity": "sha512-nH+IyFKBi8tCyzGOanJTbXC5t4dspSovX3+ABfmwKWUYllYzmiQNFUadpb3qo+MLA3jFx5IwBesjneN6dD5o3w==", + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/@algolia/client-personalization/-/client-personalization-4.13.0.tgz", + "integrity": "sha512-KneLz2WaehJmNfdr5yt2HQETpLaCYagRdWwIwkTqRVFCv4DxRQ2ChPVW9jeTj4YfAAhfzE6F8hn7wkQ/Jfj6ZA==", "dependencies": { - "@algolia/client-common": "4.10.5", - "@algolia/requester-common": "4.10.5", - "@algolia/transporter": "4.10.5" + "@algolia/client-common": "4.13.0", + "@algolia/requester-common": "4.13.0", + "@algolia/transporter": "4.13.0" } }, "node_modules/@algolia/client-search": { - "version": "4.10.5", - "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-4.10.5.tgz", - "integrity": "sha512-1eQFMz9uodrc5OM+9HeT+hHcfR1E1AsgFWXwyJ9Q3xejA2c1c4eObGgOgC9ZoshuHHdptaTN1m3rexqAxXRDBg==", + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-4.13.0.tgz", + "integrity": "sha512-blgCKYbZh1NgJWzeGf+caKE32mo3j54NprOf0LZVCubQb3Kx37tk1Hc8SDs9bCAE8hUvf3cazMPIg7wscSxspA==", "dependencies": { - "@algolia/client-common": "4.10.5", - "@algolia/requester-common": "4.10.5", - "@algolia/transporter": "4.10.5" + "@algolia/client-common": "4.13.0", + "@algolia/requester-common": "4.13.0", + "@algolia/transporter": "4.13.0" } }, + "node_modules/@algolia/events": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@algolia/events/-/events-4.0.1.tgz", + "integrity": "sha512-FQzvOCgoFXAbf5Y6mYozw2aj5KCJoA3m4heImceldzPSMbdyS4atVjJzXKMsfX3wnZTFYwkkt8/z8UesLHlSBQ==" + }, "node_modules/@algolia/logger-common": { - "version": "4.10.5", - "resolved": "https://registry.npmjs.org/@algolia/logger-common/-/logger-common-4.10.5.tgz", - "integrity": "sha512-gRJo9zt1UYP4k3woEmZm4iuEBIQd/FrArIsjzsL/b+ihNoOqIxZKTSuGFU4UUZOEhvmxDReiA4gzvQXG+TMTmA==" + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/@algolia/logger-common/-/logger-common-4.13.0.tgz", + "integrity": "sha512-8yqXk7rMtmQJ9wZiHOt/6d4/JDEg5VCk83gJ39I+X/pwUPzIsbKy9QiK4uJ3aJELKyoIiDT1hpYVt+5ia+94IA==" }, "node_modules/@algolia/logger-console": { - "version": "4.10.5", - "resolved": "https://registry.npmjs.org/@algolia/logger-console/-/logger-console-4.10.5.tgz", - "integrity": "sha512-4WfIbn4253EDU12u9UiYvz+QTvAXDv39mKNg9xSoMCjKE5szcQxfcSczw2byc6pYhahOJ9PmxPBfs1doqsdTKQ==", + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/@algolia/logger-console/-/logger-console-4.13.0.tgz", + "integrity": "sha512-YepRg7w2/87L0vSXRfMND6VJ5d6699sFJBRWzZPOlek2p5fLxxK7O0VncYuc/IbVHEgeApvgXx0WgCEa38GVuQ==", "dependencies": { - "@algolia/logger-common": "4.10.5" + "@algolia/logger-common": "4.13.0" } }, "node_modules/@algolia/requester-browser-xhr": { - "version": "4.10.5", - "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-4.10.5.tgz", - "integrity": "sha512-53/MURQEqtK+bGdfq4ITSPwTh5hnADU99qzvpAINGQveUFNSFGERipJxHjTJjIrjFz3vxj5kKwjtxDnU6ygO9g==", + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-4.13.0.tgz", + "integrity": "sha512-Dj+bnoWR5MotrnjblzGKZ2kCdQi2cK/VzPURPnE616NU/il7Ypy6U6DLGZ/ZYz+tnwPa0yypNf21uqt84fOgrg==", "dependencies": { - "@algolia/requester-common": "4.10.5" + "@algolia/requester-common": "4.13.0" } }, "node_modules/@algolia/requester-common": { - "version": "4.10.5", - "resolved": "https://registry.npmjs.org/@algolia/requester-common/-/requester-common-4.10.5.tgz", - "integrity": "sha512-UkVa1Oyuj6NPiAEt5ZvrbVopEv1m/mKqjs40KLB+dvfZnNcj+9Fry4Oxnt15HMy/HLORXsx4UwcthAvBuOXE9Q==" + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/@algolia/requester-common/-/requester-common-4.13.0.tgz", + "integrity": "sha512-BRTDj53ecK+gn7ugukDWOOcBRul59C4NblCHqj4Zm5msd5UnHFjd/sGX+RLOEoFMhetILAnmg6wMrRrQVac9vw==" }, "node_modules/@algolia/requester-node-http": { - "version": "4.10.5", - "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-4.10.5.tgz", - "integrity": "sha512-aNEKVKXL4fiiC+bS7yJwAHdxln81ieBwY3tsMCtM4zF9f5KwCzY2OtN4WKEZa5AAADVcghSAUdyjs4AcGUlO5w==", + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-4.13.0.tgz", + "integrity": "sha512-9b+3O4QFU4azLhGMrZAr/uZPydvzOR4aEZfSL8ZrpLZ7fbbqTO0S/5EVko+QIgglRAtVwxvf8UJ1wzTD2jvKxQ==", "dependencies": { - "@algolia/requester-common": "4.10.5" + "@algolia/requester-common": "4.13.0" } }, "node_modules/@algolia/transporter": { - "version": "4.10.5", - "resolved": "https://registry.npmjs.org/@algolia/transporter/-/transporter-4.10.5.tgz", - "integrity": "sha512-F8DLkmIlvCoMwSCZA3FKHtmdjH3o5clbt0pi2ktFStVNpC6ZDmY307HcK619bKP5xW6h8sVJhcvrLB775D2cyA==", + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/@algolia/transporter/-/transporter-4.13.0.tgz", + "integrity": "sha512-8tSQYE+ykQENAdeZdofvtkOr5uJ9VcQSWgRhQ9h01AehtBIPAczk/b2CLrMsw5yQZziLs5cZ3pJ3478yI+urhA==", + "dependencies": { + "@algolia/cache-common": "4.13.0", + "@algolia/logger-common": "4.13.0", + "@algolia/requester-common": "4.13.0" + } + }, + "node_modules/@ampproject/remapping": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz", + "integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==", "dependencies": { - "@algolia/cache-common": "4.10.5", - "@algolia/logger-common": "4.10.5", - "@algolia/requester-common": "4.10.5" + "@jridgewell/gen-mapping": "^0.1.0", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" } }, "node_modules/@babel/code-frame": { - "version": "7.15.8", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.15.8.tgz", - "integrity": "sha512-2IAnmn8zbvC/jKYhq5Ki9I+DwjlrtMPUCH/CpHvqI4dNnlwHwsxoIhlc8WcYY5LSYknXQtAlFYuHfqAFCvQ4Wg==", + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz", + "integrity": "sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==", "dependencies": { - "@babel/highlight": "^7.14.5" + "@babel/highlight": "^7.16.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/compat-data": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.15.0.tgz", - "integrity": "sha512-0NqAC1IJE0S0+lL1SWFMxMkz1pKCNCjI4tr2Zx4LJSXxCLAdr6KyArnY+sno5m3yH9g737ygOyPABDsnXkpxiA==", + "version": "7.17.10", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.17.10.tgz", + "integrity": "sha512-GZt/TCsG70Ms19gfZO1tM4CVnXsPgEPBCpJu+Qz3L0LUDsY5nZqFZglIoPC1kIYOtNBZlrnFT+klg12vFGZXrw==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { - "version": "7.15.8", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.15.8.tgz", - "integrity": "sha512-3UG9dsxvYBMYwRv+gS41WKHno4K60/9GPy1CJaH6xy3Elq8CTtvtjT5R5jmNhXfCYLX2mTw+7/aq5ak/gOE0og==", - "dependencies": { - "@babel/code-frame": "^7.15.8", - "@babel/generator": "^7.15.8", - "@babel/helper-compilation-targets": "^7.15.4", - "@babel/helper-module-transforms": "^7.15.8", - "@babel/helpers": "^7.15.4", - "@babel/parser": "^7.15.8", - "@babel/template": "^7.15.4", - "@babel/traverse": "^7.15.4", - "@babel/types": "^7.15.6", + "version": "7.17.10", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.17.10.tgz", + "integrity": "sha512-liKoppandF3ZcBnIYFjfSDHZLKdLHGJRkoWtG8zQyGJBQfIYobpnVGI5+pLBNtS6psFLDzyq8+h5HiVljW9PNA==", + "dependencies": { + "@ampproject/remapping": "^2.1.0", + "@babel/code-frame": "^7.16.7", + "@babel/generator": "^7.17.10", + "@babel/helper-compilation-targets": "^7.17.10", + "@babel/helper-module-transforms": "^7.17.7", + "@babel/helpers": "^7.17.9", + "@babel/parser": "^7.17.10", + "@babel/template": "^7.16.7", + "@babel/traverse": "^7.17.10", + "@babel/types": "^7.17.10", "convert-source-map": "^1.7.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", - "json5": "^2.1.2", - "semver": "^6.3.0", - "source-map": "^0.5.0" + "json5": "^2.2.1", + "semver": "^6.3.0" }, "engines": { "node": ">=6.9.0" @@ -234,49 +270,49 @@ } }, "node_modules/@babel/generator": { - "version": "7.15.8", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.15.8.tgz", - "integrity": "sha512-ECmAKstXbp1cvpTTZciZCgfOt6iN64lR0d+euv3UZisU5awfRawOvg07Utn/qBGuH4bRIEZKrA/4LzZyXhZr8g==", + "version": "7.17.10", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.17.10.tgz", + "integrity": "sha512-46MJZZo9y3o4kmhBVc7zW7i8dtR1oIK/sdO5NcfcZRhTGYi+KKJRtHNgsU6c4VUcJmUNV/LQdebD/9Dlv4K+Tg==", "dependencies": { - "@babel/types": "^7.15.6", - "jsesc": "^2.5.1", - "source-map": "^0.5.0" + "@babel/types": "^7.17.10", + "@jridgewell/gen-mapping": "^0.1.0", + "jsesc": "^2.5.1" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-annotate-as-pure": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.15.4.tgz", - "integrity": "sha512-QwrtdNvUNsPCj2lfNQacsGSQvGX8ee1ttrBrcozUP2Sv/jylewBP/8QFe6ZkBsC8T/GYWonNAWJV4aRR9AL2DA==", + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.16.7.tgz", + "integrity": "sha512-s6t2w/IPQVTAET1HitoowRGXooX8mCgtuP5195wD/QJPV6wYjpujCGF7JuMODVX2ZAJOf1GT6DT9MHEZvLOFSw==", "dependencies": { - "@babel/types": "^7.15.4" + "@babel/types": "^7.16.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-builder-binary-assignment-operator-visitor": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.15.4.tgz", - "integrity": "sha512-P8o7JP2Mzi0SdC6eWr1zF+AEYvrsZa7GSY1lTayjF5XJhVH0kjLYUZPvTMflP7tBgZoe9gIhTa60QwFpqh/E0Q==", + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.16.7.tgz", + "integrity": "sha512-C6FdbRaxYjwVu/geKW4ZeQ0Q31AftgRcdSnZ5/jsH6BzCJbtvXvhpfkbkThYSuutZA7nCXpPR6AD9zd1dprMkA==", "dependencies": { - "@babel/helper-explode-assignable-expression": "^7.15.4", - "@babel/types": "^7.15.4" + "@babel/helper-explode-assignable-expression": "^7.16.7", + "@babel/types": "^7.16.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.15.4.tgz", - "integrity": "sha512-rMWPCirulnPSe4d+gwdWXLfAXTTBj8M3guAf5xFQJ0nvFY7tfNAFnWdqaHegHlgDZOCT4qvhF3BYlSJag8yhqQ==", + "version": "7.17.10", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.17.10.tgz", + "integrity": "sha512-gh3RxjWbauw/dFiU/7whjd0qN9K6nPJMqe6+Er7rOavFh0CQUSwhAE3IcTho2rywPJFxej6TUUHDkWcYI6gGqQ==", "dependencies": { - "@babel/compat-data": "^7.15.0", - "@babel/helper-validator-option": "^7.14.5", - "browserslist": "^4.16.6", + "@babel/compat-data": "^7.17.10", + "@babel/helper-validator-option": "^7.16.7", + "browserslist": "^4.20.2", "semver": "^6.3.0" }, "engines": { @@ -295,16 +331,17 @@ } }, "node_modules/@babel/helper-create-class-features-plugin": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.15.4.tgz", - "integrity": "sha512-7ZmzFi+DwJx6A7mHRwbuucEYpyBwmh2Ca0RvI6z2+WLZYCqV0JOaLb+u0zbtmDicebgKBZgqbYfLaKNqSgv5Pw==", + "version": "7.17.9", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.17.9.tgz", + "integrity": "sha512-kUjip3gruz6AJKOq5i3nC6CoCEEF/oHH3cp6tOZhB+IyyyPyW0g1Gfsxn3mkk6S08pIA2y8GQh609v9G/5sHVQ==", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.15.4", - "@babel/helper-function-name": "^7.15.4", - "@babel/helper-member-expression-to-functions": "^7.15.4", - "@babel/helper-optimise-call-expression": "^7.15.4", - "@babel/helper-replace-supers": "^7.15.4", - "@babel/helper-split-export-declaration": "^7.15.4" + "@babel/helper-annotate-as-pure": "^7.16.7", + "@babel/helper-environment-visitor": "^7.16.7", + "@babel/helper-function-name": "^7.17.9", + "@babel/helper-member-expression-to-functions": "^7.17.7", + "@babel/helper-optimise-call-expression": "^7.16.7", + "@babel/helper-replace-supers": "^7.16.7", + "@babel/helper-split-export-declaration": "^7.16.7" }, "engines": { "node": ">=6.9.0" @@ -314,12 +351,12 @@ } }, "node_modules/@babel/helper-create-regexp-features-plugin": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.14.5.tgz", - "integrity": "sha512-TLawwqpOErY2HhWbGJ2nZT5wSkR192QpN+nBg1THfBfftrlvOh+WbhrxXCH4q4xJ9Gl16BGPR/48JA+Ryiho/A==", + "version": "7.17.0", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.17.0.tgz", + "integrity": "sha512-awO2So99wG6KnlE+TPs6rn83gCz5WlEePJDTnLEqbchMVrBeAujURVphRdigsk094VhvZehFoNOihSlcBjwsXA==", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.14.5", - "regexpu-core": "^4.7.1" + "@babel/helper-annotate-as-pure": "^7.16.7", + "regexpu-core": "^5.0.1" }, "engines": { "node": ">=6.9.0" @@ -329,9 +366,9 @@ } }, "node_modules/@babel/helper-define-polyfill-provider": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.2.3.tgz", - "integrity": "sha512-RH3QDAfRMzj7+0Nqu5oqgO5q9mFtQEVvCRsi8qCEfzLR9p2BHfn5FzhSB2oj1fF7I2+DcTORkYaQ6aTR9Cofew==", + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.3.1.tgz", + "integrity": "sha512-J9hGMpJQmtWmj46B3kBHmL38UhJGhYX7eqkcq+2gsstyYt341HmPeWspihX43yVRA0mS+8GGk2Gckc7bY/HCmA==", "dependencies": { "@babel/helper-compilation-targets": "^7.13.0", "@babel/helper-module-imports": "^7.12.13", @@ -354,220 +391,220 @@ "semver": "bin/semver.js" } }, - "node_modules/@babel/helper-explode-assignable-expression": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.15.4.tgz", - "integrity": "sha512-J14f/vq8+hdC2KoWLIQSsGrC9EFBKE4NFts8pfMpymfApds+fPqR30AOUWc4tyr56h9l/GA1Sxv2q3dLZWbQ/g==", + "node_modules/@babel/helper-environment-visitor": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.16.7.tgz", + "integrity": "sha512-SLLb0AAn6PkUeAfKJCCOl9e1R53pQlGAfc4y4XuMRZfqeMYLE0dM1LMhqbGAlGQY0lfw5/ohoYWAe9V1yibRag==", "dependencies": { - "@babel/types": "^7.15.4" + "@babel/types": "^7.16.7" }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/helper-function-name": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.15.4.tgz", - "integrity": "sha512-Z91cOMM4DseLIGOnog+Z8OI6YseR9bua+HpvLAQ2XayUGU+neTtX+97caALaLdyu53I/fjhbeCnWnRH1O3jFOw==", + "node_modules/@babel/helper-explode-assignable-expression": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.16.7.tgz", + "integrity": "sha512-KyUenhWMC8VrxzkGP0Jizjo4/Zx+1nNZhgocs+gLzyZyB8SHidhoq9KK/8Ato4anhwsivfkBLftky7gvzbZMtQ==", "dependencies": { - "@babel/helper-get-function-arity": "^7.15.4", - "@babel/template": "^7.15.4", - "@babel/types": "^7.15.4" + "@babel/types": "^7.16.7" }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/helper-get-function-arity": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.15.4.tgz", - "integrity": "sha512-1/AlxSF92CmGZzHnC515hm4SirTxtpDnLEJ0UyEMgTMZN+6bxXKg04dKhiRx5Enel+SUA1G1t5Ed/yQia0efrA==", + "node_modules/@babel/helper-function-name": { + "version": "7.17.9", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.17.9.tgz", + "integrity": "sha512-7cRisGlVtiVqZ0MW0/yFB4atgpGLWEHUVYnb448hZK4x+vih0YO5UoS11XIYtZYqHd0dIPMdUSv8q5K4LdMnIg==", "dependencies": { - "@babel/types": "^7.15.4" + "@babel/template": "^7.16.7", + "@babel/types": "^7.17.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-hoist-variables": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.15.4.tgz", - "integrity": "sha512-VTy085egb3jUGVK9ycIxQiPbquesq0HUQ+tPO0uv5mPEBZipk+5FkRKiWq5apuyTE9FUrjENB0rCf8y+n+UuhA==", + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.7.tgz", + "integrity": "sha512-m04d/0Op34H5v7pbZw6pSKP7weA6lsMvfiIAMeIvkY/R4xQtBSMFEigu9QTZ2qB/9l22vsxtM8a+Q8CzD255fg==", "dependencies": { - "@babel/types": "^7.15.4" + "@babel/types": "^7.16.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-member-expression-to-functions": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.15.4.tgz", - "integrity": "sha512-cokOMkxC/BTyNP1AlY25HuBWM32iCEsLPI4BHDpJCHHm1FU2E7dKWWIXJgQgSFiu4lp8q3bL1BIKwqkSUviqtA==", + "version": "7.17.7", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.17.7.tgz", + "integrity": "sha512-thxXgnQ8qQ11W2wVUObIqDL4p148VMxkt5T/qpN5k2fboRyzFGFmKsTGViquyM5QHKUy48OZoca8kw4ajaDPyw==", "dependencies": { - "@babel/types": "^7.15.4" + "@babel/types": "^7.17.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-imports": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.15.4.tgz", - "integrity": "sha512-jeAHZbzUwdW/xHgHQ3QmWR4Jg6j15q4w/gCfwZvtqOxoo5DKtLHk8Bsf4c5RZRC7NmLEs+ohkdq8jFefuvIxAA==", + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.16.7.tgz", + "integrity": "sha512-LVtS6TqjJHFc+nYeITRo6VLXve70xmq7wPhWTqDJusJEgGmkAACWwMiTNrvfoQo6hEhFwAIixNkvB0jPXDL8Wg==", "dependencies": { - "@babel/types": "^7.15.4" + "@babel/types": "^7.16.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.15.8", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.15.8.tgz", - "integrity": "sha512-DfAfA6PfpG8t4S6npwzLvTUpp0sS7JrcuaMiy1Y5645laRJIp/LiLGIBbQKaXSInK8tiGNI7FL7L8UvB8gdUZg==", + "version": "7.17.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.17.7.tgz", + "integrity": "sha512-VmZD99F3gNTYB7fJRDTi+u6l/zxY0BE6OIxPSU7a50s6ZUQkHwSDmV92FfM+oCG0pZRVojGYhkR8I0OGeCVREw==", "dependencies": { - "@babel/helper-module-imports": "^7.15.4", - "@babel/helper-replace-supers": "^7.15.4", - "@babel/helper-simple-access": "^7.15.4", - "@babel/helper-split-export-declaration": "^7.15.4", - "@babel/helper-validator-identifier": "^7.15.7", - "@babel/template": "^7.15.4", - "@babel/traverse": "^7.15.4", - "@babel/types": "^7.15.6" + "@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.17.3", + "@babel/types": "^7.17.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-optimise-call-expression": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.15.4.tgz", - "integrity": "sha512-E/z9rfbAOt1vDW1DR7k4SzhzotVV5+qMciWV6LaG1g4jeFrkDlJedjtV4h0i4Q/ITnUu+Pk08M7fczsB9GXBDw==", + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.16.7.tgz", + "integrity": "sha512-EtgBhg7rd/JcnpZFXpBy0ze1YRfdm7BnBX4uKMBd3ixa3RGAE002JZB66FJyNH7g0F38U05pXmA5P8cBh7z+1w==", "dependencies": { - "@babel/types": "^7.15.4" + "@babel/types": "^7.16.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-plugin-utils": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.14.5.tgz", - "integrity": "sha512-/37qQCE3K0vvZKwoK4XU/irIJQdIfCJuhU5eKnNxpFDsOkgFaUAwbv+RYw6eYgsC0E4hS7r5KqGULUogqui0fQ==", + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.16.7.tgz", + "integrity": "sha512-Qg3Nk7ZxpgMrsox6HreY1ZNKdBq7K72tDSliA6dCl5f007jR4ne8iD5UzuNnCJH2xBf2BEEVGr+/OL6Gdp7RxA==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-remap-async-to-generator": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.15.4.tgz", - "integrity": "sha512-v53MxgvMK/HCwckJ1bZrq6dNKlmwlyRNYM6ypaRTdXWGOE2c1/SCa6dL/HimhPulGhZKw9W0QhREM583F/t0vQ==", + "version": "7.16.8", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.16.8.tgz", + "integrity": "sha512-fm0gH7Flb8H51LqJHy3HJ3wnE1+qtYR2A99K06ahwrawLdOFsCEWjZOrYricXJHoPSudNKxrMBUPEIPxiIIvBw==", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.15.4", - "@babel/helper-wrap-function": "^7.15.4", - "@babel/types": "^7.15.4" + "@babel/helper-annotate-as-pure": "^7.16.7", + "@babel/helper-wrap-function": "^7.16.8", + "@babel/types": "^7.16.8" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-replace-supers": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.15.4.tgz", - "integrity": "sha512-/ztT6khaXF37MS47fufrKvIsiQkx1LBRvSJNzRqmbyeZnTwU9qBxXYLaaT/6KaxfKhjs2Wy8kG8ZdsFUuWBjzw==", + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.16.7.tgz", + "integrity": "sha512-y9vsWilTNaVnVh6xiJfABzsNpgDPKev9HnAgz6Gb1p6UUwf9NepdlsV7VXGCftJM+jqD5f7JIEubcpLjZj5dBw==", "dependencies": { - "@babel/helper-member-expression-to-functions": "^7.15.4", - "@babel/helper-optimise-call-expression": "^7.15.4", - "@babel/traverse": "^7.15.4", - "@babel/types": "^7.15.4" + "@babel/helper-environment-visitor": "^7.16.7", + "@babel/helper-member-expression-to-functions": "^7.16.7", + "@babel/helper-optimise-call-expression": "^7.16.7", + "@babel/traverse": "^7.16.7", + "@babel/types": "^7.16.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-simple-access": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.15.4.tgz", - "integrity": "sha512-UzazrDoIVOZZcTeHHEPYrr1MvTR/K+wgLg6MY6e1CJyaRhbibftF6fR2KU2sFRtI/nERUZR9fBd6aKgBlIBaPg==", + "version": "7.17.7", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.17.7.tgz", + "integrity": "sha512-txyMCGroZ96i+Pxr3Je3lzEJjqwaRC9buMUgtomcrLe5Nd0+fk1h0LLA+ixUF5OW7AhHuQ7Es1WcQJZmZsz2XA==", "dependencies": { - "@babel/types": "^7.15.4" + "@babel/types": "^7.17.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-skip-transparent-expression-wrappers": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.15.4.tgz", - "integrity": "sha512-BMRLsdh+D1/aap19TycS4eD1qELGrCBJwzaY9IE8LrpJtJb+H7rQkPIdsfgnMtLBA6DJls7X9z93Z4U8h7xw0A==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.16.0.tgz", + "integrity": "sha512-+il1gTy0oHwUsBQZyJvukbB4vPMdcYBrFHa0Uc4AizLxbq6BOYC51Rv4tWocX9BLBDLZ4kc6qUFpQ6HRgL+3zw==", "dependencies": { - "@babel/types": "^7.15.4" + "@babel/types": "^7.16.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-split-export-declaration": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.15.4.tgz", - "integrity": "sha512-HsFqhLDZ08DxCpBdEVtKmywj6PQbwnF6HHybur0MAnkAKnlS6uHkwnmRIkElB2Owpfb4xL4NwDmDLFubueDXsw==", + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.7.tgz", + "integrity": "sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw==", "dependencies": { - "@babel/types": "^7.15.4" + "@babel/types": "^7.16.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.15.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.15.7.tgz", - "integrity": "sha512-K4JvCtQqad9OY2+yTU8w+E82ywk/fe+ELNlt1G8z3bVGlZfn/hOcQQsUhGhW/N+tb3fxK800wLtKOE/aM0m72w==", + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz", + "integrity": "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-option": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.14.5.tgz", - "integrity": "sha512-OX8D5eeX4XwcroVW45NMvoYaIuFI+GQpA2a8Gi+X/U/cDUIRsV37qQfF905F0htTRCREQIB4KqPeaveRJUl3Ow==", + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.16.7.tgz", + "integrity": "sha512-TRtenOuRUVo9oIQGPC5G9DgK4743cdxvtOw0weQNpZXaS16SCBi5MNjZF8vba3ETURjZpTbVn7Vvcf2eAwFozQ==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-wrap-function": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.15.4.tgz", - "integrity": "sha512-Y2o+H/hRV5W8QhIfTpRIBwl57y8PrZt6JM3V8FOo5qarjshHItyH5lXlpMfBfmBefOqSCpKZs/6Dxqp0E/U+uw==", + "version": "7.16.8", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.16.8.tgz", + "integrity": "sha512-8RpyRVIAW1RcDDGTA+GpPAwV22wXCfKOoM9bet6TLkGIFTkRQSkH1nMQ5Yet4MpoXe1ZwHPVtNasc2w0uZMqnw==", "dependencies": { - "@babel/helper-function-name": "^7.15.4", - "@babel/template": "^7.15.4", - "@babel/traverse": "^7.15.4", - "@babel/types": "^7.15.4" + "@babel/helper-function-name": "^7.16.7", + "@babel/template": "^7.16.7", + "@babel/traverse": "^7.16.8", + "@babel/types": "^7.16.8" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helpers": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.15.4.tgz", - "integrity": "sha512-V45u6dqEJ3w2rlryYYXf6i9rQ5YMNu4FLS6ngs8ikblhu2VdR1AqAd6aJjBzmf2Qzh6KOLqKHxEN9+TFbAkAVQ==", + "version": "7.17.9", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.17.9.tgz", + "integrity": "sha512-cPCt915ShDWUEzEp3+UNRktO2n6v49l5RSnG9M5pS24hA+2FAc5si+Pn1i4VVbQQ+jh+bIZhPFQOJOzbrOYY1Q==", "dependencies": { - "@babel/template": "^7.15.4", - "@babel/traverse": "^7.15.4", - "@babel/types": "^7.15.4" + "@babel/template": "^7.16.7", + "@babel/traverse": "^7.17.9", + "@babel/types": "^7.17.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/highlight": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.5.tgz", - "integrity": "sha512-qf9u2WFWVV0MppaL877j2dBtQIDgmidgjGk5VIMw3OadXvYaXn66U1BFlH2t4+t3i+8PhedppRv+i40ABzd+gg==", + "version": "7.17.9", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.17.9.tgz", + "integrity": "sha512-J9PfEKCbFIv2X5bjTMiZu6Vf341N05QIY+d6FvVKynkG1S7G0j3I0QoRtWIrXhZ+/Nlb5Q0MzqL7TokEJ5BNHg==", "dependencies": { - "@babel/helper-validator-identifier": "^7.14.5", + "@babel/helper-validator-identifier": "^7.16.7", "chalk": "^2.0.0", "js-tokens": "^4.0.0" }, @@ -575,23 +612,10 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/highlight/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/@babel/parser": { - "version": "7.15.8", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.15.8.tgz", - "integrity": "sha512-BRYa3wcQnjS/nqI8Ac94pYYpJfojHVvVXJ97+IDCImX4Jc8W8Xv1+47enbruk+q1etOpsQNwnfFcNGw+gtPGxA==", + "version": "7.17.10", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.17.10.tgz", + "integrity": "sha512-n2Q6i+fnJqzOaq2VkdXxy2TCPCWQZHiCo0XqmrCvDWcZQKRyZzYi4Z0yxlBuN0w+r2ZHmre+Q087DSrw3pbJDQ==", "bin": { "parser": "bin/babel-parser.js" }, @@ -599,14 +623,28 @@ "node": ">=6.0.0" } }, + "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.16.7.tgz", + "integrity": "sha512-anv/DObl7waiGEnC24O9zqL0pSuI9hljihqiDuFHC8d7/bjr/4RLGPWuc8rYOff/QPzbEPSkzG8wGG9aDuhHRg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.15.4.tgz", - "integrity": "sha512-eBnpsl9tlhPhpI10kU06JHnrYXwg3+V6CaP2idsCXNef0aeslpqyITXQ74Vfk5uHgY7IG7XP0yIH8b42KSzHog==", + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.16.7.tgz", + "integrity": "sha512-di8vUHRdf+4aJ7ltXhaDbPoszdkh59AQtJM5soLsuHpQJdFQZOA4uGj0V2u/CZ8bJ/u8ULDL5yq6FO/bCXnKHw==", "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5", - "@babel/helper-skip-transparent-expression-wrappers": "^7.15.4", - "@babel/plugin-proposal-optional-chaining": "^7.14.5" + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.16.0", + "@babel/plugin-proposal-optional-chaining": "^7.16.7" }, "engines": { "node": ">=6.9.0" @@ -616,12 +654,12 @@ } }, "node_modules/@babel/plugin-proposal-async-generator-functions": { - "version": "7.15.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.15.8.tgz", - "integrity": "sha512-2Z5F2R2ibINTc63mY7FLqGfEbmofrHU9FitJW1Q7aPaKFhiPvSq6QEt/BoWN5oME3GVyjcRuNNSRbb9LC0CSWA==", + "version": "7.16.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.16.8.tgz", + "integrity": "sha512-71YHIvMuiuqWJQkebWJtdhQTfd4Q4mF76q2IX37uZPkG9+olBxsX+rH1vkhFto4UeJZ9dPY2s+mDvhDm1u2BGQ==", "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5", - "@babel/helper-remap-async-to-generator": "^7.15.4", + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/helper-remap-async-to-generator": "^7.16.8", "@babel/plugin-syntax-async-generators": "^7.8.4" }, "engines": { @@ -632,12 +670,12 @@ } }, "node_modules/@babel/plugin-proposal-class-properties": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.14.5.tgz", - "integrity": "sha512-q/PLpv5Ko4dVc1LYMpCY7RVAAO4uk55qPwrIuJ5QJ8c6cVuAmhu7I/49JOppXL6gXf7ZHzpRVEUZdYoPLM04Gg==", + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.16.7.tgz", + "integrity": "sha512-IobU0Xme31ewjYOShSIqd/ZGM/r/cuOz2z0MDbNrhF5FW+ZVgi0f2lyeoj9KFPDOAqsYxmLWZte1WOwlvY9aww==", "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.14.5", - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-create-class-features-plugin": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7" }, "engines": { "node": ">=6.9.0" @@ -647,12 +685,12 @@ } }, "node_modules/@babel/plugin-proposal-class-static-block": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.15.4.tgz", - "integrity": "sha512-M682XWrrLNk3chXCjoPUQWOyYsB93B9z3mRyjtqqYJWDf2mfCdIYgDrA11cgNVhAQieaq6F2fn2f3wI0U4aTjA==", + "version": "7.17.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.17.6.tgz", + "integrity": "sha512-X/tididvL2zbs7jZCeeRJ8167U/+Ac135AM6jCAx6gYXDUviZV5Ku9UDvWS2NCuWlFjIRXklYhwo6HhAC7ETnA==", "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.15.4", - "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-create-class-features-plugin": "^7.17.6", + "@babel/helper-plugin-utils": "^7.16.7", "@babel/plugin-syntax-class-static-block": "^7.14.5" }, "engines": { @@ -663,11 +701,11 @@ } }, "node_modules/@babel/plugin-proposal-dynamic-import": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.14.5.tgz", - "integrity": "sha512-ExjiNYc3HDN5PXJx+bwC50GIx/KKanX2HiggnIUAYedbARdImiCU4RhhHfdf0Kd7JNXGpsBBBCOm+bBVy3Gb0g==", + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.16.7.tgz", + "integrity": "sha512-I8SW9Ho3/8DRSdmDdH3gORdyUuYnk1m4cMxUAdu5oy4n3OfN8flDEH+d60iG7dUfi0KkYwSvoalHzzdRzpWHTg==", "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-plugin-utils": "^7.16.7", "@babel/plugin-syntax-dynamic-import": "^7.8.3" }, "engines": { @@ -678,11 +716,11 @@ } }, "node_modules/@babel/plugin-proposal-export-namespace-from": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.14.5.tgz", - "integrity": "sha512-g5POA32bXPMmSBu5Dx/iZGLGnKmKPc5AiY7qfZgurzrCYgIztDlHFbznSNCoQuv57YQLnQfaDi7dxCtLDIdXdA==", + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.16.7.tgz", + "integrity": "sha512-ZxdtqDXLRGBL64ocZcs7ovt71L3jhC1RGSyR996svrCi3PYqHNkb3SwPJCs8RIzD86s+WPpt2S73+EHCGO+NUA==", "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-plugin-utils": "^7.16.7", "@babel/plugin-syntax-export-namespace-from": "^7.8.3" }, "engines": { @@ -693,11 +731,11 @@ } }, "node_modules/@babel/plugin-proposal-json-strings": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.14.5.tgz", - "integrity": "sha512-NSq2fczJYKVRIsUJyNxrVUMhB27zb7N7pOFGQOhBKJrChbGcgEAqyZrmZswkPk18VMurEeJAaICbfm57vUeTbQ==", + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.16.7.tgz", + "integrity": "sha512-lNZ3EEggsGY78JavgbHsK9u5P3pQaW7k4axlgFLYkMd7UBsiNahCITShLjNQschPyjtO6dADrL24757IdhBrsQ==", "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-plugin-utils": "^7.16.7", "@babel/plugin-syntax-json-strings": "^7.8.3" }, "engines": { @@ -708,11 +746,11 @@ } }, "node_modules/@babel/plugin-proposal-logical-assignment-operators": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.14.5.tgz", - "integrity": "sha512-YGn2AvZAo9TwyhlLvCCWxD90Xq8xJ4aSgaX3G5D/8DW94L8aaT+dS5cSP+Z06+rCJERGSr9GxMBZ601xoc2taw==", + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.16.7.tgz", + "integrity": "sha512-K3XzyZJGQCr00+EtYtrDjmwX7o7PLK6U9bi1nCwkQioRFVUv6dJoxbQjtWVtP+bCPy82bONBKG8NPyQ4+i6yjg==", "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-plugin-utils": "^7.16.7", "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" }, "engines": { @@ -723,11 +761,11 @@ } }, "node_modules/@babel/plugin-proposal-nullish-coalescing-operator": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.14.5.tgz", - "integrity": "sha512-gun/SOnMqjSb98Nkaq2rTKMwervfdAoz6NphdY0vTfuzMfryj+tDGb2n6UkDKwez+Y8PZDhE3D143v6Gepp4Hg==", + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.16.7.tgz", + "integrity": "sha512-aUOrYU3EVtjf62jQrCj63pYZ7k6vns2h/DQvHPWGmsJRYzWXZ6/AsfgpiRy6XiuIDADhJzP2Q9MwSMKauBQ+UQ==", "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-plugin-utils": "^7.16.7", "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" }, "engines": { @@ -738,11 +776,11 @@ } }, "node_modules/@babel/plugin-proposal-numeric-separator": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.14.5.tgz", - "integrity": "sha512-yiclALKe0vyZRZE0pS6RXgjUOt87GWv6FYa5zqj15PvhOGFO69R5DusPlgK/1K5dVnCtegTiWu9UaBSrLLJJBg==", + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.16.7.tgz", + "integrity": "sha512-vQgPMknOIgiuVqbokToyXbkY/OmmjAzr/0lhSIbG/KmnzXPGwW/AdhdKpi+O4X/VkWiWjnkKOBiqJrTaC98VKw==", "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-plugin-utils": "^7.16.7", "@babel/plugin-syntax-numeric-separator": "^7.10.4" }, "engines": { @@ -753,15 +791,15 @@ } }, "node_modules/@babel/plugin-proposal-object-rest-spread": { - "version": "7.15.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.15.6.tgz", - "integrity": "sha512-qtOHo7A1Vt+O23qEAX+GdBpqaIuD3i9VRrWgCJeq7WO6H2d14EK3q11urj5Te2MAeK97nMiIdRpwd/ST4JFbNg==", + "version": "7.17.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.17.3.tgz", + "integrity": "sha512-yuL5iQA/TbZn+RGAfxQXfi7CNLmKi1f8zInn4IgobuCWcAb7i+zj4TYzQ9l8cEzVyJ89PDGuqxK1xZpUDISesw==", "dependencies": { - "@babel/compat-data": "^7.15.0", - "@babel/helper-compilation-targets": "^7.15.4", - "@babel/helper-plugin-utils": "^7.14.5", + "@babel/compat-data": "^7.17.0", + "@babel/helper-compilation-targets": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7", "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-transform-parameters": "^7.15.4" + "@babel/plugin-transform-parameters": "^7.16.7" }, "engines": { "node": ">=6.9.0" @@ -771,11 +809,11 @@ } }, "node_modules/@babel/plugin-proposal-optional-catch-binding": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.14.5.tgz", - "integrity": "sha512-3Oyiixm0ur7bzO5ybNcZFlmVsygSIQgdOa7cTfOYCMY+wEPAYhZAJxi3mixKFCTCKUhQXuCTtQ1MzrpL3WT8ZQ==", + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.16.7.tgz", + "integrity": "sha512-eMOH/L4OvWSZAE1VkHbr1vckLG1WUcHGJSLqqQwl2GaUqG6QjddvrOaTUMNYiv77H5IKPMZ9U9P7EaHwvAShfA==", "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-plugin-utils": "^7.16.7", "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" }, "engines": { @@ -786,12 +824,12 @@ } }, "node_modules/@babel/plugin-proposal-optional-chaining": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.14.5.tgz", - "integrity": "sha512-ycz+VOzo2UbWNI1rQXxIuMOzrDdHGrI23fRiz/Si2R4kv2XZQ1BK8ccdHwehMKBlcH/joGW/tzrUmo67gbJHlQ==", + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.16.7.tgz", + "integrity": "sha512-eC3xy+ZrUcBtP7x+sq62Q/HYd674pPTb/77XZMb5wbDPGWIdUbSr4Agr052+zaUPSb+gGRnjxXfKFvx5iMJ+DA==", "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5", - "@babel/helper-skip-transparent-expression-wrappers": "^7.14.5", + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.16.0", "@babel/plugin-syntax-optional-chaining": "^7.8.3" }, "engines": { @@ -802,12 +840,12 @@ } }, "node_modules/@babel/plugin-proposal-private-methods": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.14.5.tgz", - "integrity": "sha512-838DkdUA1u+QTCplatfq4B7+1lnDa/+QMI89x5WZHBcnNv+47N8QEj2k9I2MUU9xIv8XJ4XvPCviM/Dj7Uwt9g==", + "version": "7.16.11", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.16.11.tgz", + "integrity": "sha512-F/2uAkPlXDr8+BHpZvo19w3hLFKge+k75XUprE6jaqKxjGkSYcK+4c+bup5PdW/7W/Rpjwql7FTVEDW+fRAQsw==", "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.14.5", - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-create-class-features-plugin": "^7.16.10", + "@babel/helper-plugin-utils": "^7.16.7" }, "engines": { "node": ">=6.9.0" @@ -817,13 +855,13 @@ } }, "node_modules/@babel/plugin-proposal-private-property-in-object": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.15.4.tgz", - "integrity": "sha512-X0UTixkLf0PCCffxgu5/1RQyGGbgZuKoI+vXP4iSbJSYwPb7hu06omsFGBvQ9lJEvwgrxHdS8B5nbfcd8GyUNA==", + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.16.7.tgz", + "integrity": "sha512-rMQkjcOFbm+ufe3bTZLyOfsOUOxyvLXZJCTARhJr+8UMSoZmqTe1K1BgkFcrW37rAchWg57yI69ORxiWvUINuQ==", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.15.4", - "@babel/helper-create-class-features-plugin": "^7.15.4", - "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-annotate-as-pure": "^7.16.7", + "@babel/helper-create-class-features-plugin": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7", "@babel/plugin-syntax-private-property-in-object": "^7.14.5" }, "engines": { @@ -834,12 +872,12 @@ } }, "node_modules/@babel/plugin-proposal-unicode-property-regex": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.14.5.tgz", - "integrity": "sha512-6axIeOU5LnY471KenAB9vI8I5j7NQ2d652hIYwVyRfgaZT5UpiqFKCuVXCDMSrU+3VFafnu2c5m3lrWIlr6A5Q==", + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.16.7.tgz", + "integrity": "sha512-QRK0YI/40VLhNVGIjRNAAQkEHws0cswSdFFjpFyt943YmJIU1da9uW63Iu6NFV6CxTZW5eTDCrwZUstBWgp/Rg==", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.14.5", - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-create-regexp-features-plugin": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7" }, "engines": { "node": ">=4" @@ -859,6 +897,18 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/plugin-syntax-bigint": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", + "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, "node_modules/@babel/plugin-syntax-class-properties": { "version": "7.12.13", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", @@ -906,6 +956,18 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, "node_modules/@babel/plugin-syntax-json-strings": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", @@ -918,11 +980,11 @@ } }, "node_modules/@babel/plugin-syntax-jsx": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.14.5.tgz", - "integrity": "sha512-ohuFIsOMXJnbOMRfX7/w7LocdR6R7whhuRD4ax8IipLcLPlZGJKkBxgHp++U4N/vKyU16/YDQr2f5seajD3jIw==", + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.16.7.tgz", + "integrity": "sha512-Esxmk7YjA8QysKeT3VhTXvF6y77f/a91SIs4pWb4H2eWGQkCKFgQaG6hdoEVZtGsrAcb2K5BW66XsOErD4WU3Q==", "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.16.7" }, "engines": { "node": ">=6.9.0" @@ -1026,11 +1088,11 @@ } }, "node_modules/@babel/plugin-syntax-typescript": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.14.5.tgz", - "integrity": "sha512-u6OXzDaIXjEstBRRoBCQ/uKQKlbuaeE5in0RvWdA4pN6AhqxTIwUsnHPU1CFZA/amYObMsuWhYfRl3Ch90HD0Q==", + "version": "7.17.10", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.17.10.tgz", + "integrity": "sha512-xJefea1DWXW09pW4Tm9bjwVlPDyYA2it3fWlmEjpYz6alPvTUjL0EOzNzI/FEOyI3r4/J7uVH5UqKgl1TQ5hqQ==", "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.16.7" }, "engines": { "node": ">=6.9.0" @@ -1040,11 +1102,11 @@ } }, "node_modules/@babel/plugin-transform-arrow-functions": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.14.5.tgz", - "integrity": "sha512-KOnO0l4+tD5IfOdi4x8C1XmEIRWUjNRV8wc6K2vz/3e8yAOoZZvsRXRRIF/yo/MAOFb4QjtAw9xSxMXbSMRy8A==", + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.16.7.tgz", + "integrity": "sha512-9ffkFFMbvzTvv+7dTp/66xvZAWASuPD5Tl9LK3Z9vhOmANo6j94rik+5YMBt4CwHVMWLWpMsriIc2zsa3WW3xQ==", "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.16.7" }, "engines": { "node": ">=6.9.0" @@ -1054,13 +1116,13 @@ } }, "node_modules/@babel/plugin-transform-async-to-generator": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.14.5.tgz", - "integrity": "sha512-szkbzQ0mNk0rpu76fzDdqSyPu0MuvpXgC+6rz5rpMb5OIRxdmHfQxrktL8CYolL2d8luMCZTR0DpIMIdL27IjA==", + "version": "7.16.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.16.8.tgz", + "integrity": "sha512-MtmUmTJQHCnyJVrScNzNlofQJ3dLFuobYn3mwOTKHnSCMtbNsqvF71GQmJfFjdrXSsAA7iysFmYWw4bXZ20hOg==", "dependencies": { - "@babel/helper-module-imports": "^7.14.5", - "@babel/helper-plugin-utils": "^7.14.5", - "@babel/helper-remap-async-to-generator": "^7.14.5" + "@babel/helper-module-imports": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/helper-remap-async-to-generator": "^7.16.8" }, "engines": { "node": ">=6.9.0" @@ -1070,11 +1132,11 @@ } }, "node_modules/@babel/plugin-transform-block-scoped-functions": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.14.5.tgz", - "integrity": "sha512-dtqWqdWZ5NqBX3KzsVCWfQI3A53Ft5pWFCT2eCVUftWZgjc5DpDponbIF1+c+7cSGk2wN0YK7HGL/ezfRbpKBQ==", + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.16.7.tgz", + "integrity": "sha512-JUuzlzmF40Z9cXyytcbZEZKckgrQzChbQJw/5PuEHYeqzCsvebDx0K0jWnIIVcmmDOAVctCgnYs0pMcrYj2zJg==", "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.16.7" }, "engines": { "node": ">=6.9.0" @@ -1084,11 +1146,11 @@ } }, "node_modules/@babel/plugin-transform-block-scoping": { - "version": "7.15.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.15.3.tgz", - "integrity": "sha512-nBAzfZwZb4DkaGtOes1Up1nOAp9TDRRFw4XBzBBSG9QK7KVFmYzgj9o9sbPv7TX5ofL4Auq4wZnxCoPnI/lz2Q==", + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.16.7.tgz", + "integrity": "sha512-ObZev2nxVAYA4bhyusELdo9hb3H+A56bxH3FZMbEImZFiEDYVHXQSJ1hQKFlDnlt8G9bBrCZ5ZpURZUrV4G5qQ==", "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.16.7" }, "engines": { "node": ">=6.9.0" @@ -1098,16 +1160,17 @@ } }, "node_modules/@babel/plugin-transform-classes": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.15.4.tgz", - "integrity": "sha512-Yjvhex8GzBmmPQUvpXRPWQ9WnxXgAFuZSrqOK/eJlOGIXwvv8H3UEdUigl1gb/bnjTrln+e8bkZUYCBt/xYlBg==", - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.15.4", - "@babel/helper-function-name": "^7.15.4", - "@babel/helper-optimise-call-expression": "^7.15.4", - "@babel/helper-plugin-utils": "^7.14.5", - "@babel/helper-replace-supers": "^7.15.4", - "@babel/helper-split-export-declaration": "^7.15.4", + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.16.7.tgz", + "integrity": "sha512-WY7og38SFAGYRe64BrjKf8OrE6ulEHtr5jEYaZMwox9KebgqPi67Zqz8K53EKk1fFEJgm96r32rkKZ3qA2nCWQ==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.16.7", + "@babel/helper-environment-visitor": "^7.16.7", + "@babel/helper-function-name": "^7.16.7", + "@babel/helper-optimise-call-expression": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/helper-replace-supers": "^7.16.7", + "@babel/helper-split-export-declaration": "^7.16.7", "globals": "^11.1.0" }, "engines": { @@ -1118,11 +1181,11 @@ } }, "node_modules/@babel/plugin-transform-computed-properties": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.14.5.tgz", - "integrity": "sha512-pWM+E4283UxaVzLb8UBXv4EIxMovU4zxT1OPnpHJcmnvyY9QbPPTKZfEj31EUvG3/EQRbYAGaYEUZ4yWOBC2xg==", + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.16.7.tgz", + "integrity": "sha512-gN72G9bcmenVILj//sv1zLNaPyYcOzUho2lIJBMh/iakJ9ygCo/hEF9cpGb61SCMEDxbbyBoVQxrt+bWKu5KGw==", "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.16.7" }, "engines": { "node": ">=6.9.0" @@ -1132,11 +1195,11 @@ } }, "node_modules/@babel/plugin-transform-destructuring": { - "version": "7.14.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.14.7.tgz", - "integrity": "sha512-0mDE99nK+kVh3xlc5vKwB6wnP9ecuSj+zQCa/n0voENtP/zymdT4HH6QEb65wjjcbqr1Jb/7z9Qp7TF5FtwYGw==", + "version": "7.17.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.17.7.tgz", + "integrity": "sha512-XVh0r5yq9sLR4vZ6eVZe8FKfIcSgaTBxVBRSYokRj2qksf6QerYnTxz9/GTuKTH/n/HwLP7t6gtlybHetJ/6hQ==", "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.16.7" }, "engines": { "node": ">=6.9.0" @@ -1146,12 +1209,12 @@ } }, "node_modules/@babel/plugin-transform-dotall-regex": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.14.5.tgz", - "integrity": "sha512-loGlnBdj02MDsFaHhAIJzh7euK89lBrGIdM9EAtHFo6xKygCUGuuWe07o1oZVk287amtW1n0808sQM99aZt3gw==", + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.16.7.tgz", + "integrity": "sha512-Lyttaao2SjZF6Pf4vk1dVKv8YypMpomAbygW+mU5cYP3S5cWTfCJjG8xV6CFdzGFlfWK81IjL9viiTvpb6G7gQ==", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.14.5", - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-create-regexp-features-plugin": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7" }, "engines": { "node": ">=6.9.0" @@ -1161,11 +1224,11 @@ } }, "node_modules/@babel/plugin-transform-duplicate-keys": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.14.5.tgz", - "integrity": "sha512-iJjbI53huKbPDAsJ8EmVmvCKeeq21bAze4fu9GBQtSLqfvzj2oRuHVx4ZkDwEhg1htQ+5OBZh/Ab0XDf5iBZ7A==", + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.16.7.tgz", + "integrity": "sha512-03DvpbRfvWIXyK0/6QiR1KMTWeT6OcQ7tbhjrXyFS02kjuX/mu5Bvnh5SDSWHxyawit2g5aWhKwI86EE7GUnTw==", "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.16.7" }, "engines": { "node": ">=6.9.0" @@ -1175,12 +1238,12 @@ } }, "node_modules/@babel/plugin-transform-exponentiation-operator": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.14.5.tgz", - "integrity": "sha512-jFazJhMBc9D27o9jDnIE5ZErI0R0m7PbKXVq77FFvqFbzvTMuv8jaAwLZ5PviOLSFttqKIW0/wxNSDbjLk0tYA==", + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.16.7.tgz", + "integrity": "sha512-8UYLSlyLgRixQvlYH3J2ekXFHDFLQutdy7FfFAMm3CPZ6q9wHCwnUyiXpQCe3gVVnQlHc5nsuiEVziteRNTXEA==", "dependencies": { - "@babel/helper-builder-binary-assignment-operator-visitor": "^7.14.5", - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7" }, "engines": { "node": ">=6.9.0" @@ -1190,11 +1253,11 @@ } }, "node_modules/@babel/plugin-transform-for-of": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.15.4.tgz", - "integrity": "sha512-DRTY9fA751AFBDh2oxydvVm4SYevs5ILTWLs6xKXps4Re/KG5nfUkr+TdHCrRWB8C69TlzVgA9b3RmGWmgN9LA==", + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.16.7.tgz", + "integrity": "sha512-/QZm9W92Ptpw7sjI9Nx1mbcsWz33+l8kuMIQnDwgQBG5s3fAfQvkRjQ7NqXhtNcKOnPkdICmUHyCaWW06HCsqg==", "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.16.7" }, "engines": { "node": ">=6.9.0" @@ -1204,12 +1267,13 @@ } }, "node_modules/@babel/plugin-transform-function-name": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.14.5.tgz", - "integrity": "sha512-vbO6kv0fIzZ1GpmGQuvbwwm+O4Cbm2NrPzwlup9+/3fdkuzo1YqOZcXw26+YUJB84Ja7j9yURWposEHLYwxUfQ==", + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.16.7.tgz", + "integrity": "sha512-SU/C68YVwTRxqWj5kgsbKINakGag0KTgq9f2iZEXdStoAbOzLHEBRYzImmA6yFo8YZhJVflvXmIHUO7GWHmxxA==", "dependencies": { - "@babel/helper-function-name": "^7.14.5", - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-compilation-targets": "^7.16.7", + "@babel/helper-function-name": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7" }, "engines": { "node": ">=6.9.0" @@ -1219,11 +1283,11 @@ } }, "node_modules/@babel/plugin-transform-literals": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.14.5.tgz", - "integrity": "sha512-ql33+epql2F49bi8aHXxvLURHkxJbSmMKl9J5yHqg4PLtdE6Uc48CH1GS6TQvZ86eoB/ApZXwm7jlA+B3kra7A==", + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.16.7.tgz", + "integrity": "sha512-6tH8RTpTWI0s2sV6uq3e/C9wPo4PTqqZps4uF0kzQ9/xPLFQtipynvmT1g/dOfEJ+0EQsHhkQ/zyRId8J2b8zQ==", "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.16.7" }, "engines": { "node": ">=6.9.0" @@ -1233,11 +1297,11 @@ } }, "node_modules/@babel/plugin-transform-member-expression-literals": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.14.5.tgz", - "integrity": "sha512-WkNXxH1VXVTKarWFqmso83xl+2V3Eo28YY5utIkbsmXoItO8Q3aZxN4BTS2k0hz9dGUloHK26mJMyQEYfkn/+Q==", + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.16.7.tgz", + "integrity": "sha512-mBruRMbktKQwbxaJof32LT9KLy2f3gH+27a5XSuXo6h7R3vqltl0PgZ80C8ZMKw98Bf8bqt6BEVi3svOh2PzMw==", "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.16.7" }, "engines": { "node": ">=6.9.0" @@ -1247,12 +1311,12 @@ } }, "node_modules/@babel/plugin-transform-modules-amd": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.14.5.tgz", - "integrity": "sha512-3lpOU8Vxmp3roC4vzFpSdEpGUWSMsHFreTWOMMLzel2gNGfHE5UWIh/LN6ghHs2xurUp4jRFYMUIZhuFbody1g==", + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.16.7.tgz", + "integrity": "sha512-KaaEtgBL7FKYwjJ/teH63oAmE3lP34N3kshz8mm4VMAw7U3PxjVwwUmxEFksbgsNUaO3wId9R2AVQYSEGRa2+g==", "dependencies": { - "@babel/helper-module-transforms": "^7.14.5", - "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-module-transforms": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7", "babel-plugin-dynamic-import-node": "^2.3.3" }, "engines": { @@ -1271,13 +1335,13 @@ } }, "node_modules/@babel/plugin-transform-modules-commonjs": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.15.4.tgz", - "integrity": "sha512-qg4DPhwG8hKp4BbVDvX1s8cohM8a6Bvptu4l6Iingq5rW+yRUAhe/YRup/YcW2zCOlrysEWVhftIcKzrEZv3sA==", + "version": "7.17.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.17.9.tgz", + "integrity": "sha512-2TBFd/r2I6VlYn0YRTz2JdazS+FoUuQ2rIFHoAxtyP/0G3D82SBLaRq9rnUkpqlLg03Byfl/+M32mpxjO6KaPw==", "dependencies": { - "@babel/helper-module-transforms": "^7.15.4", - "@babel/helper-plugin-utils": "^7.14.5", - "@babel/helper-simple-access": "^7.15.4", + "@babel/helper-module-transforms": "^7.17.7", + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/helper-simple-access": "^7.17.7", "babel-plugin-dynamic-import-node": "^2.3.3" }, "engines": { @@ -1296,14 +1360,14 @@ } }, "node_modules/@babel/plugin-transform-modules-systemjs": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.15.4.tgz", - "integrity": "sha512-fJUnlQrl/mezMneR72CKCgtOoahqGJNVKpompKwzv3BrEXdlPspTcyxrZ1XmDTIr9PpULrgEQo3qNKp6dW7ssw==", - "dependencies": { - "@babel/helper-hoist-variables": "^7.15.4", - "@babel/helper-module-transforms": "^7.15.4", - "@babel/helper-plugin-utils": "^7.14.5", - "@babel/helper-validator-identifier": "^7.14.9", + "version": "7.17.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.17.8.tgz", + "integrity": "sha512-39reIkMTUVagzgA5x88zDYXPCMT6lcaRKs1+S9K6NKBPErbgO/w/kP8GlNQTC87b412ZTlmNgr3k2JrWgHH+Bw==", + "dependencies": { + "@babel/helper-hoist-variables": "^7.16.7", + "@babel/helper-module-transforms": "^7.17.7", + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/helper-validator-identifier": "^7.16.7", "babel-plugin-dynamic-import-node": "^2.3.3" }, "engines": { @@ -1322,12 +1386,12 @@ } }, "node_modules/@babel/plugin-transform-modules-umd": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.14.5.tgz", - "integrity": "sha512-RfPGoagSngC06LsGUYyM9QWSXZ8MysEjDJTAea1lqRjNECE3y0qIJF/qbvJxc4oA4s99HumIMdXOrd+TdKaAAA==", + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.16.7.tgz", + "integrity": "sha512-EMh7uolsC8O4xhudF2F6wedbSHm1HHZ0C6aJ7K67zcDNidMzVcxWdGr+htW9n21klm+bOn+Rx4CBsAntZd3rEQ==", "dependencies": { - "@babel/helper-module-transforms": "^7.14.5", - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-module-transforms": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7" }, "engines": { "node": ">=6.9.0" @@ -1337,11 +1401,11 @@ } }, "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { - "version": "7.14.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.14.9.tgz", - "integrity": "sha512-l666wCVYO75mlAtGFfyFwnWmIXQm3kSH0C3IRnJqWcZbWkoihyAdDhFm2ZWaxWTqvBvhVFfJjMRQ0ez4oN1yYA==", + "version": "7.17.10", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.17.10.tgz", + "integrity": "sha512-v54O6yLaJySCs6mGzaVOUw9T967GnH38T6CQSAtnzdNPwu84l2qAjssKzo/WSO8Yi7NF+7ekm5cVbF/5qiIgNA==", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.14.5" + "@babel/helper-create-regexp-features-plugin": "^7.17.0" }, "engines": { "node": ">=6.9.0" @@ -1351,11 +1415,11 @@ } }, "node_modules/@babel/plugin-transform-new-target": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.14.5.tgz", - "integrity": "sha512-Nx054zovz6IIRWEB49RDRuXGI4Gy0GMgqG0cII9L3MxqgXz/+rgII+RU58qpo4g7tNEx1jG7rRVH4ihZoP4esQ==", + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.16.7.tgz", + "integrity": "sha512-xiLDzWNMfKoGOpc6t3U+etCE2yRnn3SM09BXqWPIZOBpL2gvVrBWUKnsJx0K/ADi5F5YC5f8APFfWrz25TdlGg==", "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.16.7" }, "engines": { "node": ">=6.9.0" @@ -1365,12 +1429,12 @@ } }, "node_modules/@babel/plugin-transform-object-super": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.14.5.tgz", - "integrity": "sha512-MKfOBWzK0pZIrav9z/hkRqIk/2bTv9qvxHzPQc12RcVkMOzpIKnFCNYJip00ssKWYkd8Sf5g0Wr7pqJ+cmtuFg==", + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.16.7.tgz", + "integrity": "sha512-14J1feiQVWaGvRxj2WjyMuXS2jsBkgB3MdSN5HuC2G5nRspa5RK9COcs82Pwy5BuGcjb+fYaUj94mYcOj7rCvw==", "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5", - "@babel/helper-replace-supers": "^7.14.5" + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/helper-replace-supers": "^7.16.7" }, "engines": { "node": ">=6.9.0" @@ -1380,11 +1444,11 @@ } }, "node_modules/@babel/plugin-transform-parameters": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.15.4.tgz", - "integrity": "sha512-9WB/GUTO6lvJU3XQsSr6J/WKvBC2hcs4Pew8YxZagi6GkTdniyqp8On5kqdK8MN0LMeu0mGbhPN+O049NV/9FQ==", + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.16.7.tgz", + "integrity": "sha512-AT3MufQ7zZEhU2hwOA11axBnExW0Lszu4RL/tAlUJBuNoRak+wehQW8h6KcXOcgjY42fHtDxswuMhMjFEuv/aw==", "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.16.7" }, "engines": { "node": ">=6.9.0" @@ -1394,11 +1458,11 @@ } }, "node_modules/@babel/plugin-transform-property-literals": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.14.5.tgz", - "integrity": "sha512-r1uilDthkgXW8Z1vJz2dKYLV1tuw2xsbrp3MrZmD99Wh9vsfKoob+JTgri5VUb/JqyKRXotlOtwgu4stIYCmnw==", + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.16.7.tgz", + "integrity": "sha512-z4FGr9NMGdoIl1RqavCqGG+ZuYjfZ/hkCIeuH6Do7tXmSm0ls11nYVSJqFEUOSJbDab5wC6lRE/w6YjVcr6Hqw==", "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.16.7" }, "engines": { "node": ">=6.9.0" @@ -1408,11 +1472,11 @@ } }, "node_modules/@babel/plugin-transform-react-constant-elements": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.14.5.tgz", - "integrity": "sha512-NBqLEx1GxllIOXJInJAQbrnwwYJsV3WaMHIcOwD8rhYS0AabTWn7kHdHgPgu5RmHLU0q4DMxhAMu8ue/KampgQ==", + "version": "7.17.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.17.6.tgz", + "integrity": "sha512-OBv9VkyyKtsHZiHLoSfCn+h6yU7YKX8nrs32xUmOa1SRSk+t03FosB6fBZ0Yz4BpD1WV7l73Nsad+2Tz7APpqw==", "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.16.7" }, "engines": { "node": ">=6.9.0" @@ -1422,11 +1486,11 @@ } }, "node_modules/@babel/plugin-transform-react-display-name": { - "version": "7.15.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.15.1.tgz", - "integrity": "sha512-yQZ/i/pUCJAHI/LbtZr413S3VT26qNrEm0M5RRxQJA947/YNYwbZbBaXGDrq6CG5QsZycI1VIP6d7pQaBfP+8Q==", + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.16.7.tgz", + "integrity": "sha512-qgIg8BcZgd0G/Cz916D5+9kqX0c7nPZyXaP8R2tLNN5tkyIZdG5fEwBrxwplzSnjC1jvQmyMNVwUCZPcbGY7Pg==", "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.16.7" }, "engines": { "node": ">=6.9.0" @@ -1436,15 +1500,15 @@ } }, "node_modules/@babel/plugin-transform-react-jsx": { - "version": "7.14.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.14.9.tgz", - "integrity": "sha512-30PeETvS+AeD1f58i1OVyoDlVYQhap/K20ZrMjLmmzmC2AYR/G43D4sdJAaDAqCD3MYpSWbmrz3kES158QSLjw==", + "version": "7.17.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.17.3.tgz", + "integrity": "sha512-9tjBm4O07f7mzKSIlEmPdiE6ub7kfIe6Cd+w+oQebpATfTQMAgW+YOuWxogbKVTulA+MEO7byMeIUtQ1z+z+ZQ==", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.14.5", - "@babel/helper-module-imports": "^7.14.5", - "@babel/helper-plugin-utils": "^7.14.5", - "@babel/plugin-syntax-jsx": "^7.14.5", - "@babel/types": "^7.14.9" + "@babel/helper-annotate-as-pure": "^7.16.7", + "@babel/helper-module-imports": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/plugin-syntax-jsx": "^7.16.7", + "@babel/types": "^7.17.0" }, "engines": { "node": ">=6.9.0" @@ -1454,11 +1518,11 @@ } }, "node_modules/@babel/plugin-transform-react-jsx-development": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.14.5.tgz", - "integrity": "sha512-rdwG/9jC6QybWxVe2UVOa7q6cnTpw8JRRHOxntG/h6g/guAOe6AhtQHJuJh5FwmnXIT1bdm5vC2/5huV8ZOorQ==", + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.16.7.tgz", + "integrity": "sha512-RMvQWvpla+xy6MlBpPlrKZCMRs2AGiHOGHY3xRwl0pEeim348dDyxeH4xBsMPbIMhujeq7ihE702eM2Ew0Wo+A==", "dependencies": { - "@babel/plugin-transform-react-jsx": "^7.14.5" + "@babel/plugin-transform-react-jsx": "^7.16.7" }, "engines": { "node": ">=6.9.0" @@ -1468,12 +1532,12 @@ } }, "node_modules/@babel/plugin-transform-react-pure-annotations": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.14.5.tgz", - "integrity": "sha512-3X4HpBJimNxW4rhUy/SONPyNQHp5YRr0HhJdT2OH1BRp0of7u3Dkirc7x9FRJMKMqTBI079VZ1hzv7Ouuz///g==", + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.16.7.tgz", + "integrity": "sha512-hs71ToC97k3QWxswh2ElzMFABXHvGiJ01IB1TbYQDGeWRKWz/MPUTh5jGExdHvosYKpnJW5Pm3S4+TA3FyX+GA==", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.14.5", - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-annotate-as-pure": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7" }, "engines": { "node": ">=6.9.0" @@ -1483,11 +1547,11 @@ } }, "node_modules/@babel/plugin-transform-regenerator": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.14.5.tgz", - "integrity": "sha512-NVIY1W3ITDP5xQl50NgTKlZ0GrotKtLna08/uGY6ErQt6VEQZXla86x/CTddm5gZdcr+5GSsvMeTmWA5Ii6pkg==", + "version": "7.17.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.17.9.tgz", + "integrity": "sha512-Lc2TfbxR1HOyn/c6b4Y/b6NHoTb67n/IoWLxTu4kC7h4KQnWlhCq2S8Tx0t2SVvv5Uu87Hs+6JEJ5kt2tYGylQ==", "dependencies": { - "regenerator-transform": "^0.14.2" + "regenerator-transform": "^0.15.0" }, "engines": { "node": ">=6.9.0" @@ -1497,11 +1561,11 @@ } }, "node_modules/@babel/plugin-transform-reserved-words": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.14.5.tgz", - "integrity": "sha512-cv4F2rv1nD4qdexOGsRQXJrOcyb5CrgjUH9PKrrtyhSDBNWGxd0UIitjyJiWagS+EbUGjG++22mGH1Pub8D6Vg==", + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.16.7.tgz", + "integrity": "sha512-KQzzDnZ9hWQBjwi5lpY5v9shmm6IVG0U9pB18zvMu2i4H90xpT4gmqwPYsn8rObiadYe2M0gmgsiOIF5A/2rtg==", "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.16.7" }, "engines": { "node": ">=6.9.0" @@ -1511,15 +1575,15 @@ } }, "node_modules/@babel/plugin-transform-runtime": { - "version": "7.15.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.15.8.tgz", - "integrity": "sha512-+6zsde91jMzzvkzuEA3k63zCw+tm/GvuuabkpisgbDMTPQsIMHllE3XczJFFtEHLjjhKQFZmGQVRdELetlWpVw==", - "dependencies": { - "@babel/helper-module-imports": "^7.15.4", - "@babel/helper-plugin-utils": "^7.14.5", - "babel-plugin-polyfill-corejs2": "^0.2.2", - "babel-plugin-polyfill-corejs3": "^0.2.5", - "babel-plugin-polyfill-regenerator": "^0.2.2", + "version": "7.17.10", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.17.10.tgz", + "integrity": "sha512-6jrMilUAJhktTr56kACL8LnWC5hx3Lf27BS0R0DSyW/OoJfb/iTHeE96V3b1dgKG3FSFdd/0culnYWMkjcKCig==", + "dependencies": { + "@babel/helper-module-imports": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7", + "babel-plugin-polyfill-corejs2": "^0.3.0", + "babel-plugin-polyfill-corejs3": "^0.5.0", + "babel-plugin-polyfill-regenerator": "^0.3.0", "semver": "^6.3.0" }, "engines": { @@ -1538,11 +1602,11 @@ } }, "node_modules/@babel/plugin-transform-shorthand-properties": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.14.5.tgz", - "integrity": "sha512-xLucks6T1VmGsTB+GWK5Pl9Jl5+nRXD1uoFdA5TSO6xtiNjtXTjKkmPdFXVLGlK5A2/or/wQMKfmQ2Y0XJfn5g==", + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.16.7.tgz", + "integrity": "sha512-hah2+FEnoRoATdIb05IOXf+4GzXYTq75TVhIn1PewihbpyrNWUt2JbudKQOETWw6QpLe+AIUpJ5MVLYTQbeeUg==", "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.16.7" }, "engines": { "node": ">=6.9.0" @@ -1552,12 +1616,12 @@ } }, "node_modules/@babel/plugin-transform-spread": { - "version": "7.15.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.15.8.tgz", - "integrity": "sha512-/daZ8s2tNaRekl9YJa9X4bzjpeRZLt122cpgFnQPLGUe61PH8zMEBmYqKkW5xF5JUEh5buEGXJoQpqBmIbpmEQ==", + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.16.7.tgz", + "integrity": "sha512-+pjJpgAngb53L0iaA5gU/1MLXJIfXcYepLgXB3esVRf4fqmj8f2cxM3/FKaHsZms08hFQJkFccEWuIpm429TXg==", "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5", - "@babel/helper-skip-transparent-expression-wrappers": "^7.15.4" + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.16.0" }, "engines": { "node": ">=6.9.0" @@ -1567,11 +1631,11 @@ } }, "node_modules/@babel/plugin-transform-sticky-regex": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.14.5.tgz", - "integrity": "sha512-Z7F7GyvEMzIIbwnziAZmnSNpdijdr4dWt+FJNBnBLz5mwDFkqIXU9wmBcWWad3QeJF5hMTkRe4dAq2sUZiG+8A==", + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.16.7.tgz", + "integrity": "sha512-NJa0Bd/87QV5NZZzTuZG5BPJjLYadeSZ9fO6oOUoL4iQx+9EEuw/eEM92SrsT19Yc2jgB1u1hsjqDtH02c3Drw==", "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.16.7" }, "engines": { "node": ">=6.9.0" @@ -1581,11 +1645,11 @@ } }, "node_modules/@babel/plugin-transform-template-literals": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.14.5.tgz", - "integrity": "sha512-22btZeURqiepOfuy/VkFr+zStqlujWaarpMErvay7goJS6BWwdd6BY9zQyDLDa4x2S3VugxFb162IZ4m/S/+Gg==", + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.16.7.tgz", + "integrity": "sha512-VwbkDDUeenlIjmfNeDX/V0aWrQH2QiVyJtwymVQSzItFDTpxfyJh3EVaQiS0rIN/CqbLGr0VcGmuwyTdZtdIsA==", "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.16.7" }, "engines": { "node": ">=6.9.0" @@ -1595,11 +1659,11 @@ } }, "node_modules/@babel/plugin-transform-typeof-symbol": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.14.5.tgz", - "integrity": "sha512-lXzLD30ffCWseTbMQzrvDWqljvZlHkXU+CnseMhkMNqU1sASnCsz3tSzAaH3vCUXb9PHeUb90ZT1BdFTm1xxJw==", + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.16.7.tgz", + "integrity": "sha512-p2rOixCKRJzpg9JB4gjnG4gjWkWa89ZoYUnl9snJ1cWIcTH/hvxZqfO+WjG6T8DRBpctEol5jw1O5rA8gkCokQ==", "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.16.7" }, "engines": { "node": ">=6.9.0" @@ -1609,13 +1673,13 @@ } }, "node_modules/@babel/plugin-transform-typescript": { - "version": "7.15.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.15.8.tgz", - "integrity": "sha512-ZXIkJpbaf6/EsmjeTbiJN/yMxWPFWvlr7sEG1P95Xb4S4IBcrf2n7s/fItIhsAmOf8oSh3VJPDppO6ExfAfKRQ==", + "version": "7.16.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.16.8.tgz", + "integrity": "sha512-bHdQ9k7YpBDO2d0NVfkj51DpQcvwIzIusJ7mEUaMlbZq3Kt/U47j24inXZHQ5MDiYpCs+oZiwnXyKedE8+q7AQ==", "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.15.4", - "@babel/helper-plugin-utils": "^7.14.5", - "@babel/plugin-syntax-typescript": "^7.14.5" + "@babel/helper-create-class-features-plugin": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/plugin-syntax-typescript": "^7.16.7" }, "engines": { "node": ">=6.9.0" @@ -1625,11 +1689,11 @@ } }, "node_modules/@babel/plugin-transform-unicode-escapes": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.14.5.tgz", - "integrity": "sha512-crTo4jATEOjxj7bt9lbYXcBAM3LZaUrbP2uUdxb6WIorLmjNKSpHfIybgY4B8SRpbf8tEVIWH3Vtm7ayCrKocA==", + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.16.7.tgz", + "integrity": "sha512-TAV5IGahIz3yZ9/Hfv35TV2xEm+kaBDaZQCn2S/hG9/CZ0DktxJv9eKfPc7yYCvOYR4JGx1h8C+jcSOvgaaI/Q==", "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.16.7" }, "engines": { "node": ">=6.9.0" @@ -1639,12 +1703,12 @@ } }, "node_modules/@babel/plugin-transform-unicode-regex": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.14.5.tgz", - "integrity": "sha512-UygduJpC5kHeCiRw/xDVzC+wj8VaYSoKl5JNVmbP7MadpNinAm3SvZCxZ42H37KZBKztz46YC73i9yV34d0Tzw==", + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.16.7.tgz", + "integrity": "sha512-oC5tYYKw56HO75KZVLQ+R/Nl3Hro9kf8iG0hXoaHP7tjAyCpvqBiSNe6vGrZni1Z6MggmUOC6A7VP7AVmw225Q==", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.14.5", - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-create-regexp-features-plugin": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7" }, "engines": { "node": ">=6.9.0" @@ -1654,30 +1718,31 @@ } }, "node_modules/@babel/preset-env": { - "version": "7.15.8", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.15.8.tgz", - "integrity": "sha512-rCC0wH8husJgY4FPbHsiYyiLxSY8oMDJH7Rl6RQMknbN9oDDHhM9RDFvnGM2MgkbUJzSQB4gtuwygY5mCqGSsA==", - "dependencies": { - "@babel/compat-data": "^7.15.0", - "@babel/helper-compilation-targets": "^7.15.4", - "@babel/helper-plugin-utils": "^7.14.5", - "@babel/helper-validator-option": "^7.14.5", - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.15.4", - "@babel/plugin-proposal-async-generator-functions": "^7.15.8", - "@babel/plugin-proposal-class-properties": "^7.14.5", - "@babel/plugin-proposal-class-static-block": "^7.15.4", - "@babel/plugin-proposal-dynamic-import": "^7.14.5", - "@babel/plugin-proposal-export-namespace-from": "^7.14.5", - "@babel/plugin-proposal-json-strings": "^7.14.5", - "@babel/plugin-proposal-logical-assignment-operators": "^7.14.5", - "@babel/plugin-proposal-nullish-coalescing-operator": "^7.14.5", - "@babel/plugin-proposal-numeric-separator": "^7.14.5", - "@babel/plugin-proposal-object-rest-spread": "^7.15.6", - "@babel/plugin-proposal-optional-catch-binding": "^7.14.5", - "@babel/plugin-proposal-optional-chaining": "^7.14.5", - "@babel/plugin-proposal-private-methods": "^7.14.5", - "@babel/plugin-proposal-private-property-in-object": "^7.15.4", - "@babel/plugin-proposal-unicode-property-regex": "^7.14.5", + "version": "7.17.10", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.17.10.tgz", + "integrity": "sha512-YNgyBHZQpeoBSRBg0xixsZzfT58Ze1iZrajvv0lJc70qDDGuGfonEnMGfWeSY0mQ3JTuCWFbMkzFRVafOyJx4g==", + "dependencies": { + "@babel/compat-data": "^7.17.10", + "@babel/helper-compilation-targets": "^7.17.10", + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/helper-validator-option": "^7.16.7", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.16.7", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.16.7", + "@babel/plugin-proposal-async-generator-functions": "^7.16.8", + "@babel/plugin-proposal-class-properties": "^7.16.7", + "@babel/plugin-proposal-class-static-block": "^7.17.6", + "@babel/plugin-proposal-dynamic-import": "^7.16.7", + "@babel/plugin-proposal-export-namespace-from": "^7.16.7", + "@babel/plugin-proposal-json-strings": "^7.16.7", + "@babel/plugin-proposal-logical-assignment-operators": "^7.16.7", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.16.7", + "@babel/plugin-proposal-numeric-separator": "^7.16.7", + "@babel/plugin-proposal-object-rest-spread": "^7.17.3", + "@babel/plugin-proposal-optional-catch-binding": "^7.16.7", + "@babel/plugin-proposal-optional-chaining": "^7.16.7", + "@babel/plugin-proposal-private-methods": "^7.16.11", + "@babel/plugin-proposal-private-property-in-object": "^7.16.7", + "@babel/plugin-proposal-unicode-property-regex": "^7.16.7", "@babel/plugin-syntax-async-generators": "^7.8.4", "@babel/plugin-syntax-class-properties": "^7.12.13", "@babel/plugin-syntax-class-static-block": "^7.14.5", @@ -1692,44 +1757,44 @@ "@babel/plugin-syntax-optional-chaining": "^7.8.3", "@babel/plugin-syntax-private-property-in-object": "^7.14.5", "@babel/plugin-syntax-top-level-await": "^7.14.5", - "@babel/plugin-transform-arrow-functions": "^7.14.5", - "@babel/plugin-transform-async-to-generator": "^7.14.5", - "@babel/plugin-transform-block-scoped-functions": "^7.14.5", - "@babel/plugin-transform-block-scoping": "^7.15.3", - "@babel/plugin-transform-classes": "^7.15.4", - "@babel/plugin-transform-computed-properties": "^7.14.5", - "@babel/plugin-transform-destructuring": "^7.14.7", - "@babel/plugin-transform-dotall-regex": "^7.14.5", - "@babel/plugin-transform-duplicate-keys": "^7.14.5", - "@babel/plugin-transform-exponentiation-operator": "^7.14.5", - "@babel/plugin-transform-for-of": "^7.15.4", - "@babel/plugin-transform-function-name": "^7.14.5", - "@babel/plugin-transform-literals": "^7.14.5", - "@babel/plugin-transform-member-expression-literals": "^7.14.5", - "@babel/plugin-transform-modules-amd": "^7.14.5", - "@babel/plugin-transform-modules-commonjs": "^7.15.4", - "@babel/plugin-transform-modules-systemjs": "^7.15.4", - "@babel/plugin-transform-modules-umd": "^7.14.5", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.14.9", - "@babel/plugin-transform-new-target": "^7.14.5", - "@babel/plugin-transform-object-super": "^7.14.5", - "@babel/plugin-transform-parameters": "^7.15.4", - "@babel/plugin-transform-property-literals": "^7.14.5", - "@babel/plugin-transform-regenerator": "^7.14.5", - "@babel/plugin-transform-reserved-words": "^7.14.5", - "@babel/plugin-transform-shorthand-properties": "^7.14.5", - "@babel/plugin-transform-spread": "^7.15.8", - "@babel/plugin-transform-sticky-regex": "^7.14.5", - "@babel/plugin-transform-template-literals": "^7.14.5", - "@babel/plugin-transform-typeof-symbol": "^7.14.5", - "@babel/plugin-transform-unicode-escapes": "^7.14.5", - "@babel/plugin-transform-unicode-regex": "^7.14.5", - "@babel/preset-modules": "^0.1.4", - "@babel/types": "^7.15.6", - "babel-plugin-polyfill-corejs2": "^0.2.2", - "babel-plugin-polyfill-corejs3": "^0.2.5", - "babel-plugin-polyfill-regenerator": "^0.2.2", - "core-js-compat": "^3.16.0", + "@babel/plugin-transform-arrow-functions": "^7.16.7", + "@babel/plugin-transform-async-to-generator": "^7.16.8", + "@babel/plugin-transform-block-scoped-functions": "^7.16.7", + "@babel/plugin-transform-block-scoping": "^7.16.7", + "@babel/plugin-transform-classes": "^7.16.7", + "@babel/plugin-transform-computed-properties": "^7.16.7", + "@babel/plugin-transform-destructuring": "^7.17.7", + "@babel/plugin-transform-dotall-regex": "^7.16.7", + "@babel/plugin-transform-duplicate-keys": "^7.16.7", + "@babel/plugin-transform-exponentiation-operator": "^7.16.7", + "@babel/plugin-transform-for-of": "^7.16.7", + "@babel/plugin-transform-function-name": "^7.16.7", + "@babel/plugin-transform-literals": "^7.16.7", + "@babel/plugin-transform-member-expression-literals": "^7.16.7", + "@babel/plugin-transform-modules-amd": "^7.16.7", + "@babel/plugin-transform-modules-commonjs": "^7.17.9", + "@babel/plugin-transform-modules-systemjs": "^7.17.8", + "@babel/plugin-transform-modules-umd": "^7.16.7", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.17.10", + "@babel/plugin-transform-new-target": "^7.16.7", + "@babel/plugin-transform-object-super": "^7.16.7", + "@babel/plugin-transform-parameters": "^7.16.7", + "@babel/plugin-transform-property-literals": "^7.16.7", + "@babel/plugin-transform-regenerator": "^7.17.9", + "@babel/plugin-transform-reserved-words": "^7.16.7", + "@babel/plugin-transform-shorthand-properties": "^7.16.7", + "@babel/plugin-transform-spread": "^7.16.7", + "@babel/plugin-transform-sticky-regex": "^7.16.7", + "@babel/plugin-transform-template-literals": "^7.16.7", + "@babel/plugin-transform-typeof-symbol": "^7.16.7", + "@babel/plugin-transform-unicode-escapes": "^7.16.7", + "@babel/plugin-transform-unicode-regex": "^7.16.7", + "@babel/preset-modules": "^0.1.5", + "@babel/types": "^7.17.10", + "babel-plugin-polyfill-corejs2": "^0.3.0", + "babel-plugin-polyfill-corejs3": "^0.5.0", + "babel-plugin-polyfill-regenerator": "^0.3.0", + "core-js-compat": "^3.22.1", "semver": "^6.3.0" }, "engines": { @@ -1748,9 +1813,9 @@ } }, "node_modules/@babel/preset-modules": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.4.tgz", - "integrity": "sha512-J36NhwnfdzpmH41M1DrnkkgAqhZaqr/NBdPfQ677mLzlaXo+oDiv1deyCDtgAhz8p328otdob0Du7+xgHGZbKg==", + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.5.tgz", + "integrity": "sha512-A57th6YRG7oR3cq/yt/Y84MvGgE0eJG2F1JLhKuyG+jFxEgrd/HAMJatiFtmOiZurz+0DkrvbheCLaV5f2JfjA==", "dependencies": { "@babel/helper-plugin-utils": "^7.0.0", "@babel/plugin-proposal-unicode-property-regex": "^7.4.4", @@ -1763,16 +1828,16 @@ } }, "node_modules/@babel/preset-react": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.14.5.tgz", - "integrity": "sha512-XFxBkjyObLvBaAvkx1Ie95Iaq4S/GUEIrejyrntQ/VCMKUYvKLoyKxOBzJ2kjA3b6rC9/KL6KXfDC2GqvLiNqQ==", + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.16.7.tgz", + "integrity": "sha512-fWpyI8UM/HE6DfPBzD8LnhQ/OcH8AgTaqcqP2nGOXEUV+VKBR5JRN9hCk9ai+zQQ57vtm9oWeXguBCPNUjytgA==", "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5", - "@babel/helper-validator-option": "^7.14.5", - "@babel/plugin-transform-react-display-name": "^7.14.5", - "@babel/plugin-transform-react-jsx": "^7.14.5", - "@babel/plugin-transform-react-jsx-development": "^7.14.5", - "@babel/plugin-transform-react-pure-annotations": "^7.14.5" + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/helper-validator-option": "^7.16.7", + "@babel/plugin-transform-react-display-name": "^7.16.7", + "@babel/plugin-transform-react-jsx": "^7.16.7", + "@babel/plugin-transform-react-jsx-development": "^7.16.7", + "@babel/plugin-transform-react-pure-annotations": "^7.16.7" }, "engines": { "node": ">=6.9.0" @@ -1782,13 +1847,13 @@ } }, "node_modules/@babel/preset-typescript": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.15.0.tgz", - "integrity": "sha512-lt0Y/8V3y06Wq/8H/u0WakrqciZ7Fz7mwPDHWUJAXlABL5hiUG42BNlRXiELNjeWjO5rWmnNKlx+yzJvxezHow==", + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.16.7.tgz", + "integrity": "sha512-WbVEmgXdIyvzB77AQjGBEyYPZx+8tTsO50XtfozQrkW8QB2rLJpH2lgx0TRw5EJrBxOZQ+wCcyPVQvS8tjEHpQ==", "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5", - "@babel/helper-validator-option": "^7.14.5", - "@babel/plugin-transform-typescript": "^7.15.0" + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/helper-validator-option": "^7.16.7", + "@babel/plugin-transform-typescript": "^7.16.7" }, "engines": { "node": ">=6.9.0" @@ -1798,9 +1863,9 @@ } }, "node_modules/@babel/runtime": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.15.4.tgz", - "integrity": "sha512-99catp6bHCaxr4sJ/DbTGgHS4+Rs2RVd2g7iOap6SLGPDknRK9ztKNsE/Fg6QhSeh1FGE5f6gHGQmvvn3I3xhw==", + "version": "7.17.9", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.17.9.tgz", + "integrity": "sha512-lSiBBvodq29uShpWGNbgFdKYNiFDo5/HIYsaCEY9ff4sb10x9jizo2+pRrSyF4jKZCXqgzuqBOQKbUm90gQwJg==", "dependencies": { "regenerator-runtime": "^0.13.4" }, @@ -1809,11 +1874,11 @@ } }, "node_modules/@babel/runtime-corejs3": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.15.4.tgz", - "integrity": "sha512-lWcAqKeB624/twtTc3w6w/2o9RqJPaNBhPGK6DKLSiwuVWC7WFkypWyNg+CpZoyJH0jVzv1uMtXZ/5/lQOLtCg==", + "version": "7.17.9", + "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.17.9.tgz", + "integrity": "sha512-WxYHHUWF2uZ7Hp1K+D1xQgbgkGUfA+5UPOegEXGt2Y5SMog/rYCVaifLZDbw8UkNXozEqqrZTy6bglL7xTaCOw==", "dependencies": { - "core-js-pure": "^3.16.0", + "core-js-pure": "^3.20.2", "regenerator-runtime": "^0.13.4" }, "engines": { @@ -1821,30 +1886,31 @@ } }, "node_modules/@babel/template": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.15.4.tgz", - "integrity": "sha512-UgBAfEa1oGuYgDIPM2G+aHa4Nlo9Lh6mGD2bDBGMTbYnc38vulXPuC1MGjYILIEmlwl6Rd+BPR9ee3gm20CBtg==", + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.16.7.tgz", + "integrity": "sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w==", "dependencies": { - "@babel/code-frame": "^7.14.5", - "@babel/parser": "^7.15.4", - "@babel/types": "^7.15.4" + "@babel/code-frame": "^7.16.7", + "@babel/parser": "^7.16.7", + "@babel/types": "^7.16.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.15.4.tgz", - "integrity": "sha512-W6lQD8l4rUbQR/vYgSuCAE75ADyyQvOpFVsvPPdkhf6lATXAsQIG9YdtOcu8BB1dZ0LKu+Zo3c1wEcbKeuhdlA==", - "dependencies": { - "@babel/code-frame": "^7.14.5", - "@babel/generator": "^7.15.4", - "@babel/helper-function-name": "^7.15.4", - "@babel/helper-hoist-variables": "^7.15.4", - "@babel/helper-split-export-declaration": "^7.15.4", - "@babel/parser": "^7.15.4", - "@babel/types": "^7.15.4", + "version": "7.17.10", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.17.10.tgz", + "integrity": "sha512-VmbrTHQteIdUUQNTb+zE12SHS/xQVIShmBPhlNP12hD5poF2pbITW1Z4172d03HegaQWhLffdkRJYtAzp0AGcw==", + "dependencies": { + "@babel/code-frame": "^7.16.7", + "@babel/generator": "^7.17.10", + "@babel/helper-environment-visitor": "^7.16.7", + "@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.17.10", + "@babel/types": "^7.17.10", "debug": "^4.1.0", "globals": "^11.1.0" }, @@ -1853,30 +1919,138 @@ } }, "node_modules/@babel/types": { - "version": "7.15.6", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.15.6.tgz", - "integrity": "sha512-BPU+7QhqNjmWyDO0/vitH/CuhpV8ZmK1wpKva8nuyNF5MJfuRNWMc+hc14+u9xT93kvykMdncrJT19h74uB1Ig==", + "version": "7.17.10", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.17.10.tgz", + "integrity": "sha512-9O26jG0mBYfGkUYCYZRnBwbVLd1UZOICEr2Em6InB6jVfsAv1GKgwXHmrSg+WFWDmeKTA6vyTZiN8tCSM5Oo3A==", "dependencies": { - "@babel/helper-validator-identifier": "^7.14.9", + "@babel/helper-validator-identifier": "^7.16.7", "to-fast-properties": "^2.0.0" }, "engines": { "node": ">=6.9.0" } }, + "node_modules/@bcoe/v8-coverage": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", + "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", + "dev": true + }, + "node_modules/@colors/colors": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", + "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", + "optional": true, + "engines": { + "node": ">=0.1.90" + } + }, + "node_modules/@cypress/request": { + "version": "2.88.10", + "resolved": "https://registry.npmjs.org/@cypress/request/-/request-2.88.10.tgz", + "integrity": "sha512-Zp7F+R93N0yZyG34GutyTNr+okam7s/Fzc1+i3kcqOP8vk6OuajuE9qZJ6Rs+10/1JFtXFYMdyarnU1rZuJesg==", + "dev": true, + "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", + "http-signature": "~1.3.6", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "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": "^8.3.2" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/@cypress/request/node_modules/form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "dev": true, + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 0.12" + } + }, + "node_modules/@cypress/request/node_modules/qs": { + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz", + "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==", + "dev": true, + "engines": { + "node": ">=0.6" + } + }, + "node_modules/@cypress/request/node_modules/tough-cookie": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", + "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", + "dev": true, + "dependencies": { + "psl": "^1.1.28", + "punycode": "^2.1.1" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/@cypress/request/node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "dev": true, + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/@cypress/xvfb": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@cypress/xvfb/-/xvfb-1.2.4.tgz", + "integrity": "sha512-skbBzPggOVYCbnGgV+0dmBdW/s77ZkAOXIC1knS8NagwDjBrNC1LuXtQJeiN6l+m7lzmHtaoUw/ctJKdqkG57Q==", + "dev": true, + "dependencies": { + "debug": "^3.1.0", + "lodash.once": "^4.1.1" + } + }, + "node_modules/@cypress/xvfb/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, "node_modules/@docsearch/css": { - "version": "3.0.0-alpha.40", - "resolved": "https://registry.npmjs.org/@docsearch/css/-/css-3.0.0-alpha.40.tgz", - "integrity": "sha512-PrOTPgJMl+Iji1zOH0+J0PEDMriJ1teGxbgll7o4h8JrvJW6sJGqQw7/bLW7enWiFaxbJMK76w1yyPNLFHV7Qg==" + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@docsearch/css/-/css-3.0.0.tgz", + "integrity": "sha512-1kkV7tkAsiuEd0shunYRByKJe3xQDG2q7wYg24SOw1nV9/2lwEd4WrUYRJC/ukGTl2/kHeFxsaUvtiOy0y6fFA==" }, "node_modules/@docsearch/react": { - "version": "3.0.0-alpha.40", - "resolved": "https://registry.npmjs.org/@docsearch/react/-/react-3.0.0-alpha.40.tgz", - "integrity": "sha512-aKxnu7sgpP1R7jtgOV/pZdJEHXx6Ts+jnS9U/ejSUS2BMUpwQI5SA3oLs1BA5TA9kIViJ5E+rrjh0VsbcsJ6sQ==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@docsearch/react/-/react-3.0.0.tgz", + "integrity": "sha512-yhMacqS6TVQYoBh/o603zszIb5Bl8MIXuOc6Vy617I74pirisDzzcNh0NEaYQt50fVVR3khUbeEhUEWEWipESg==", "dependencies": { - "@algolia/autocomplete-core": "1.2.2", - "@algolia/autocomplete-preset-algolia": "1.2.2", - "@docsearch/css": "3.0.0-alpha.40", + "@algolia/autocomplete-core": "1.5.2", + "@algolia/autocomplete-preset-algolia": "1.5.2", + "@docsearch/css": "3.0.0", "algoliasearch": "^4.0.0" }, "peerDependencies": { @@ -1886,1312 +2060,1167 @@ } }, "node_modules/@docusaurus/core": { - "version": "2.0.0-beta.6", - "resolved": "https://registry.npmjs.org/@docusaurus/core/-/core-2.0.0-beta.6.tgz", - "integrity": "sha512-XMeI+lJKeJBGYBNOfO/Tc+5FMf21E5p1xZjfe75cgYcfZdERZ+W7aemXquwReno8xxHb4Rnfmi9dxkbOLDjqDA==", + "version": "2.0.0-beta.17", + "resolved": "https://registry.npmjs.org/@docusaurus/core/-/core-2.0.0-beta.17.tgz", + "integrity": "sha512-iNdW7CsmHNOgc4PxD9BFxa+MD8+i7ln7erOBkF3FSMMPnsKUeVqsR3rr31aLmLZRlTXMITSPLxlXwtBZa3KPCw==", "dependencies": { - "@babel/core": "^7.12.16", - "@babel/generator": "^7.12.15", + "@babel/core": "^7.17.5", + "@babel/generator": "^7.17.3", "@babel/plugin-syntax-dynamic-import": "^7.8.3", - "@babel/plugin-transform-runtime": "^7.12.15", - "@babel/preset-env": "^7.12.16", - "@babel/preset-react": "^7.12.13", - "@babel/preset-typescript": "^7.12.16", - "@babel/runtime": "^7.12.5", - "@babel/runtime-corejs3": "^7.12.13", - "@babel/traverse": "^7.12.13", - "@docusaurus/cssnano-preset": "2.0.0-beta.6", - "@docusaurus/react-loadable": "5.5.0", - "@docusaurus/types": "2.0.0-beta.6", - "@docusaurus/utils": "2.0.0-beta.6", - "@docusaurus/utils-common": "2.0.0-beta.6", - "@docusaurus/utils-validation": "2.0.0-beta.6", - "@slorber/static-site-generator-webpack-plugin": "^4.0.0", - "@svgr/webpack": "^5.5.0", - "autoprefixer": "^10.2.5", - "babel-loader": "^8.2.2", + "@babel/plugin-transform-runtime": "^7.17.0", + "@babel/preset-env": "^7.16.11", + "@babel/preset-react": "^7.16.7", + "@babel/preset-typescript": "^7.16.7", + "@babel/runtime": "^7.17.2", + "@babel/runtime-corejs3": "^7.17.2", + "@babel/traverse": "^7.17.3", + "@docusaurus/cssnano-preset": "2.0.0-beta.17", + "@docusaurus/logger": "2.0.0-beta.17", + "@docusaurus/mdx-loader": "2.0.0-beta.17", + "@docusaurus/react-loadable": "5.5.2", + "@docusaurus/utils": "2.0.0-beta.17", + "@docusaurus/utils-common": "2.0.0-beta.17", + "@docusaurus/utils-validation": "2.0.0-beta.17", + "@slorber/static-site-generator-webpack-plugin": "^4.0.1", + "@svgr/webpack": "^6.2.1", + "autoprefixer": "^10.4.2", + "babel-loader": "^8.2.3", "babel-plugin-dynamic-import-node": "2.3.0", - "boxen": "^5.0.1", - "chalk": "^4.1.1", - "chokidar": "^3.5.1", - "clean-css": "^5.1.5", + "boxen": "^6.2.1", + "chokidar": "^3.5.3", + "clean-css": "^5.2.4", + "cli-table3": "^0.6.1", + "combine-promises": "^1.1.0", "commander": "^5.1.0", - "copy-webpack-plugin": "^9.0.0", - "core-js": "^3.9.1", - "css-loader": "^5.1.1", - "css-minimizer-webpack-plugin": "^3.0.1", - "cssnano": "^5.0.4", + "copy-webpack-plugin": "^10.2.4", + "core-js": "^3.21.1", + "css-loader": "^6.6.0", + "css-minimizer-webpack-plugin": "^3.4.1", + "cssnano": "^5.0.17", "del": "^6.0.0", "detect-port": "^1.3.0", "escape-html": "^1.0.3", - "eta": "^1.12.1", - "express": "^4.17.1", + "eta": "^1.12.3", "file-loader": "^6.2.0", - "fs-extra": "^10.0.0", - "github-slugger": "^1.3.0", - "globby": "^11.0.2", - "html-minifier-terser": "^5.1.1", + "fs-extra": "^10.0.1", + "html-minifier-terser": "^6.1.0", "html-tags": "^3.1.0", - "html-webpack-plugin": "^5.3.2", + "html-webpack-plugin": "^5.5.0", "import-fresh": "^3.3.0", "is-root": "^2.1.0", "leven": "^3.1.0", - "lodash": "^4.17.20", - "mini-css-extract-plugin": "^1.6.0", - "module-alias": "^2.2.2", + "lodash": "^4.17.21", + "mini-css-extract-plugin": "^2.5.3", "nprogress": "^0.2.0", - "postcss": "^8.2.15", - "postcss-loader": "^5.3.0", - "prompts": "^2.4.1", - "react-dev-utils": "^11.0.1", - "react-error-overlay": "^6.0.9", - "react-helmet": "^6.1.0", - "react-loadable": "^5.5.0", + "postcss": "^8.4.7", + "postcss-loader": "^6.2.1", + "prompts": "^2.4.2", + "react-dev-utils": "^12.0.0", + "react-helmet-async": "^1.2.3", + "react-loadable": "npm:@docusaurus/react-loadable@5.5.2", "react-loadable-ssr-addon-v5-slorber": "^1.0.1", "react-router": "^5.2.0", "react-router-config": "^5.1.1", "react-router-dom": "^5.2.0", "remark-admonitions": "^1.2.1", - "resolve-pathname": "^3.0.0", - "rtl-detect": "^1.0.3", + "rtl-detect": "^1.0.4", "semver": "^7.3.4", "serve-handler": "^6.1.3", - "shelljs": "^0.8.4", - "std-env": "^2.2.1", - "strip-ansi": "^6.0.0", - "terser-webpack-plugin": "^5.1.3", - "tslib": "^2.2.0", + "shelljs": "^0.8.5", + "terser-webpack-plugin": "^5.3.1", + "tslib": "^2.3.1", "update-notifier": "^5.1.0", "url-loader": "^4.1.1", - "wait-on": "^5.3.0", - "webpack": "^5.40.0", - "webpack-bundle-analyzer": "^4.4.2", - "webpack-dev-server": "^3.11.2", + "wait-on": "^6.0.1", + "webpack": "^5.69.1", + "webpack-bundle-analyzer": "^4.5.0", + "webpack-dev-server": "^4.7.4", "webpack-merge": "^5.8.0", - "webpackbar": "^5.0.0-3" + "webpackbar": "^5.0.2" }, "bin": { - "docusaurus": "bin/docusaurus.js" + "docusaurus": "bin/docusaurus.mjs" }, "engines": { - "node": ">=12.13.0" + "node": ">=14" }, "peerDependencies": { "react": "^16.8.4 || ^17.0.0", "react-dom": "^16.8.4 || ^17.0.0" } }, - "node_modules/@docusaurus/core/node_modules/css-loader": { - "version": "5.2.7", - "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-5.2.7.tgz", - "integrity": "sha512-Q7mOvpBNBG7YrVGMxRxcBJZFL75o+cH2abNASdibkj/fffYD8qWbInZrD0S9ccI6vZclF3DsHE7njGlLtaHbhg==", - "dependencies": { - "icss-utils": "^5.1.0", - "loader-utils": "^2.0.0", - "postcss": "^8.2.15", - "postcss-modules-extract-imports": "^3.0.0", - "postcss-modules-local-by-default": "^4.0.0", - "postcss-modules-scope": "^3.0.0", - "postcss-modules-values": "^4.0.0", - "postcss-value-parser": "^4.1.0", - "schema-utils": "^3.0.0", - "semver": "^7.3.5" - }, + "node_modules/@docusaurus/core/node_modules/@svgr/babel-plugin-add-jsx-attribute": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-6.0.0.tgz", + "integrity": "sha512-MdPdhdWLtQsjd29Wa4pABdhWbaRMACdM1h31BY+c6FghTZqNGT7pEYdBoaGeKtdTOBC/XNFQaKVj+r/Ei2ryWA==", "engines": { - "node": ">= 10.13.0" + "node": ">=10" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" + "type": "github", + "url": "https://github.com/sponsors/gregberge" }, "peerDependencies": { - "webpack": "^4.27.0 || ^5.0.0" - } - }, - "node_modules/@docusaurus/cssnano-preset": { - "version": "2.0.0-beta.6", - "resolved": "https://registry.npmjs.org/@docusaurus/cssnano-preset/-/cssnano-preset-2.0.0-beta.6.tgz", - "integrity": "sha512-RCizp2NAbADopkX5nUz1xrAbU6hGZzziQk9RdSDGJLzMgVCN6RDotq9odS8VgzNa9x2Lx3WN527UxeEbzc2GVQ==", - "dependencies": { - "cssnano-preset-advanced": "^5.1.1", - "postcss": "^8.2.15", - "postcss-sort-media-queries": "^3.10.11" + "@babel/core": "^7.0.0-0" } }, - "node_modules/@docusaurus/lqip-loader": { - "version": "2.0.0-beta.6", - "resolved": "https://registry.npmjs.org/@docusaurus/lqip-loader/-/lqip-loader-2.0.0-beta.6.tgz", - "integrity": "sha512-8kXfqWiv1XY+EeWzpKGhiwcftj6Kd4wZ+ThxbmiSWU7LTUcEkvX25wGiK1mHLHDGzrTZYrCRSs8DvXY/PiYIAw==", - "dependencies": { - "file-loader": "^6.2.0", - "lodash": "^4.17.20", - "node-vibrant": "^3.1.5", - "sharp": "^0.28.2" - }, + "node_modules/@docusaurus/core/node_modules/@svgr/babel-plugin-remove-jsx-attribute": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-6.0.0.tgz", + "integrity": "sha512-aVdtfx9jlaaxc3unA6l+M9YRnKIZjOhQPthLKqmTXC8UVkBLDRGwPKo+r8n3VZN8B34+yVajzPTZ+ptTSuZZCw==", "engines": { - "node": ">=12.13.0" + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@docusaurus/mdx-loader": { - "version": "2.0.0-beta.6", - "resolved": "https://registry.npmjs.org/@docusaurus/mdx-loader/-/mdx-loader-2.0.0-beta.6.tgz", - "integrity": "sha512-yO6N+OESR77WZ/pXz7muOJGLletYYksx7s7wrwrr0x+A8tzdSwiHZ9op0NyjjpW5AnItU/WQQfcjv37qv4K6HA==", - "dependencies": { - "@babel/parser": "^7.12.16", - "@babel/traverse": "^7.12.13", - "@docusaurus/core": "2.0.0-beta.6", - "@docusaurus/utils": "2.0.0-beta.6", - "@mdx-js/mdx": "^1.6.21", - "@mdx-js/react": "^1.6.21", - "chalk": "^4.1.1", - "escape-html": "^1.0.3", - "file-loader": "^6.2.0", - "fs-extra": "^10.0.0", - "github-slugger": "^1.3.0", - "gray-matter": "^4.0.3", - "mdast-util-to-string": "^2.0.0", - "remark-emoji": "^2.1.0", - "stringify-object": "^3.3.0", - "unist-util-visit": "^2.0.2", - "url-loader": "^4.1.1", - "webpack": "^5.40.0" - }, + "node_modules/@docusaurus/core/node_modules/@svgr/babel-plugin-remove-jsx-empty-expression": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-6.0.0.tgz", + "integrity": "sha512-Ccj42ApsePD451AZJJf1QzTD1B/BOU392URJTeXFxSK709i0KUsGtbwyiqsKu7vsYxpTM0IA5clAKDyf9RCZyA==", "engines": { - "node": ">=12.13.0" - }, - "peerDependencies": { - "react": "^16.8.4 || ^17.0.0", - "react-dom": "^16.8.4 || ^17.0.0" - } - }, - "node_modules/@docusaurus/plugin-content-blog": { - "version": "2.0.0-beta.6", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-blog/-/plugin-content-blog-2.0.0-beta.6.tgz", - "integrity": "sha512-ohfMt7+rPiFQImc4Clpvc9m/1yWUQAjpG3e/coJywlJYbDXvi1pmH0VKkDUMBSe/35Wtz9457DYgNFG81lhV7Q==", - "dependencies": { - "@docusaurus/core": "2.0.0-beta.6", - "@docusaurus/mdx-loader": "2.0.0-beta.6", - "@docusaurus/types": "2.0.0-beta.6", - "@docusaurus/utils": "2.0.0-beta.6", - "@docusaurus/utils-validation": "2.0.0-beta.6", - "chalk": "^4.1.1", - "escape-string-regexp": "^4.0.0", - "feed": "^4.2.2", - "fs-extra": "^10.0.0", - "globby": "^11.0.2", - "js-yaml": "^4.0.0", - "loader-utils": "^2.0.0", - "lodash": "^4.17.20", - "reading-time": "^1.3.0", - "remark-admonitions": "^1.2.1", - "tslib": "^2.2.0", - "webpack": "^5.40.0" + "node": ">=10" }, - "engines": { - "node": ">=12.13.0" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" }, "peerDependencies": { - "react": "^16.8.4 || ^17.0.0", - "react-dom": "^16.8.4 || ^17.0.0" + "@babel/core": "^7.0.0-0" } }, - "node_modules/@docusaurus/plugin-content-blog/node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" - }, - "node_modules/@docusaurus/plugin-content-blog/node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "node_modules/@docusaurus/core/node_modules/@svgr/babel-plugin-replace-jsx-attribute-value": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-6.0.0.tgz", + "integrity": "sha512-88V26WGyt1Sfd1emBYmBJRWMmgarrExpKNVmI9vVozha4kqs6FzQJ/Kp5+EYli1apgX44518/0+t9+NU36lThQ==", "engines": { "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@docusaurus/plugin-content-blog/node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/@docusaurus/plugin-content-docs": { - "version": "2.0.0-beta.6", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-docs/-/plugin-content-docs-2.0.0-beta.6.tgz", - "integrity": "sha512-cM5WWogWmX+qKPKv332eDWGRVVT5OjskbmFKe2QimwoaON3Cv6XY8Fo2xdYopqGIU0r0z8dVtRmoGS0ji7zB7w==", - "dependencies": { - "@docusaurus/core": "2.0.0-beta.6", - "@docusaurus/mdx-loader": "2.0.0-beta.6", - "@docusaurus/types": "2.0.0-beta.6", - "@docusaurus/utils": "2.0.0-beta.6", - "@docusaurus/utils-validation": "2.0.0-beta.6", - "chalk": "^4.1.1", - "combine-promises": "^1.1.0", - "escape-string-regexp": "^4.0.0", - "execa": "^5.0.0", - "fs-extra": "^10.0.0", - "globby": "^11.0.2", - "import-fresh": "^3.2.2", - "js-yaml": "^4.0.0", - "loader-utils": "^1.2.3", - "lodash": "^4.17.20", - "remark-admonitions": "^1.2.1", - "shelljs": "^0.8.4", - "tslib": "^2.2.0", - "utility-types": "^3.10.0", - "webpack": "^5.40.0" - }, - "engines": { - "node": ">=12.13.0" + "type": "github", + "url": "https://github.com/sponsors/gregberge" }, "peerDependencies": { - "react": "^16.8.4 || ^17.0.0", - "react-dom": "^16.8.4 || ^17.0.0" + "@babel/core": "^7.0.0-0" } }, - "node_modules/@docusaurus/plugin-content-docs/node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" - }, - "node_modules/@docusaurus/plugin-content-docs/node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "node_modules/@docusaurus/core/node_modules/@svgr/babel-plugin-svg-dynamic-title": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-6.0.0.tgz", + "integrity": "sha512-F7YXNLfGze+xv0KMQxrl2vkNbI9kzT9oDK55/kUuymh1ACyXkMV+VZWX1zEhSTfEKh7VkHVZGmVtHg8eTZ6PRg==", "engines": { "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@docusaurus/plugin-content-docs/node_modules/execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", - "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - }, + "node_modules/@docusaurus/core/node_modules/@svgr/babel-plugin-svg-em-dimensions": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-6.0.0.tgz", + "integrity": "sha512-+rghFXxdIqJNLQK08kwPBD3Z22/0b2tEZ9lKiL/yTfuyj1wW8HUXu4bo/XkogATIYuXSghVQOOCwURXzHGKyZA==", "engines": { "node": ">=10" }, "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@docusaurus/plugin-content-docs/node_modules/get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "node_modules/@docusaurus/core/node_modules/@svgr/babel-plugin-transform-react-native-svg": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-6.0.0.tgz", + "integrity": "sha512-VaphyHZ+xIKv5v0K0HCzyfAaLhPGJXSk2HkpYfXIOKb7DjLBv0soHDxNv6X0vr2titsxE7klb++u7iOf7TSrFQ==", "engines": { "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@docusaurus/plugin-content-docs/node_modules/is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "node_modules/@docusaurus/core/node_modules/@svgr/babel-plugin-transform-svg-component": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-6.2.0.tgz", + "integrity": "sha512-bhYIpsORb++wpsp91fymbFkf09Z/YEKR0DnFjxvN+8JHeCUD2unnh18jIMKnDJTWtvpTaGYPXELVe4OOzFI0xg==", "engines": { - "node": ">=8" + "node": ">=12" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@docusaurus/plugin-content-docs/node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dependencies": { - "argparse": "^2.0.1" + "type": "github", + "url": "https://github.com/sponsors/gregberge" }, - "bin": { - "js-yaml": "bin/js-yaml.js" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@docusaurus/plugin-content-docs/node_modules/json5": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", - "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "node_modules/@docusaurus/core/node_modules/@svgr/babel-preset": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-preset/-/babel-preset-6.2.0.tgz", + "integrity": "sha512-4WQNY0J71JIaL03DRn0vLiz87JXx0b9dYm2aA8XHlQJQoixMl4r/soYHm8dsaJZ3jWtkCiOYy48dp9izvXhDkQ==", "dependencies": { - "minimist": "^1.2.0" + "@svgr/babel-plugin-add-jsx-attribute": "^6.0.0", + "@svgr/babel-plugin-remove-jsx-attribute": "^6.0.0", + "@svgr/babel-plugin-remove-jsx-empty-expression": "^6.0.0", + "@svgr/babel-plugin-replace-jsx-attribute-value": "^6.0.0", + "@svgr/babel-plugin-svg-dynamic-title": "^6.0.0", + "@svgr/babel-plugin-svg-em-dimensions": "^6.0.0", + "@svgr/babel-plugin-transform-react-native-svg": "^6.0.0", + "@svgr/babel-plugin-transform-svg-component": "^6.2.0" }, - "bin": { - "json5": "lib/cli.js" + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@docusaurus/plugin-content-docs/node_modules/loader-utils": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", - "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", + "node_modules/@docusaurus/core/node_modules/@svgr/core": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/@svgr/core/-/core-6.2.1.tgz", + "integrity": "sha512-NWufjGI2WUyrg46mKuySfviEJ6IxHUOm/8a3Ph38VCWSp+83HBraCQrpEM3F3dB6LBs5x8OElS8h3C0oOJaJAA==", "dependencies": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^1.0.1" + "@svgr/plugin-jsx": "^6.2.1", + "camelcase": "^6.2.0", + "cosmiconfig": "^7.0.1" }, "engines": { - "node": ">=4.0.0" + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" } }, - "node_modules/@docusaurus/plugin-content-docs/node_modules/npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "node_modules/@docusaurus/core/node_modules/@svgr/hast-util-to-babel-ast": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-6.2.1.tgz", + "integrity": "sha512-pt7MMkQFDlWJVy9ULJ1h+hZBDGFfSCwlBNW1HkLnVi7jUhyEXUaGYWi1x6bM2IXuAR9l265khBT4Av4lPmaNLQ==", "dependencies": { - "path-key": "^3.0.0" + "@babel/types": "^7.15.6", + "entities": "^3.0.1" }, "engines": { - "node": ">=8" + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" } }, - "node_modules/@docusaurus/plugin-content-pages": { - "version": "2.0.0-beta.6", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-pages/-/plugin-content-pages-2.0.0-beta.6.tgz", - "integrity": "sha512-N6wARzOA8gTFeBXZSKbAN5s1Ej6R/pVg+J946E8GCYefXTFikTNRQ8+OPhax4MRzgzoOvhTQbLbRCSoAzSmjig==", - "dependencies": { - "@docusaurus/core": "2.0.0-beta.6", - "@docusaurus/mdx-loader": "2.0.0-beta.6", - "@docusaurus/types": "2.0.0-beta.6", - "@docusaurus/utils": "2.0.0-beta.6", - "@docusaurus/utils-validation": "2.0.0-beta.6", - "globby": "^11.0.2", - "lodash": "^4.17.20", - "remark-admonitions": "^1.2.1", - "tslib": "^2.1.0", - "webpack": "^5.40.0" + "node_modules/@docusaurus/core/node_modules/@svgr/plugin-jsx": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/@svgr/plugin-jsx/-/plugin-jsx-6.2.1.tgz", + "integrity": "sha512-u+MpjTsLaKo6r3pHeeSVsh9hmGRag2L7VzApWIaS8imNguqoUwDq/u6U/NDmYs/KAsrmtBjOEaAAPbwNGXXp1g==", + "dependencies": { + "@babel/core": "^7.15.5", + "@svgr/babel-preset": "^6.2.0", + "@svgr/hast-util-to-babel-ast": "^6.2.1", + "svg-parser": "^2.0.2" }, "engines": { - "node": ">=12.13.0" + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" }, "peerDependencies": { - "react": "^16.8.4 || ^17.0.0", - "react-dom": "^16.8.4 || ^17.0.0" + "@svgr/core": "^6.0.0" } }, - "node_modules/@docusaurus/plugin-debug": { - "version": "2.0.0-beta.6", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-debug/-/plugin-debug-2.0.0-beta.6.tgz", - "integrity": "sha512-TJXDBR2Gr/mhBrcj+/4+rTShSm/Qg56Jfezbm/2fFvuPgVlUwy6oj08s2/kYSTmkfG7G+c4iX1GBHjtyo1KxZA==", + "node_modules/@docusaurus/core/node_modules/@svgr/plugin-svgo": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/@svgr/plugin-svgo/-/plugin-svgo-6.2.0.tgz", + "integrity": "sha512-oDdMQONKOJEbuKwuy4Np6VdV6qoaLLvoY86hjvQEgU82Vx1MSWRyYms6Sl0f+NtqxLI/rDVufATbP/ev996k3Q==", "dependencies": { - "@docusaurus/core": "2.0.0-beta.6", - "@docusaurus/types": "2.0.0-beta.6", - "@docusaurus/utils": "2.0.0-beta.6", - "fs-extra": "^9.1.0", - "react-json-view": "^1.21.3", - "tslib": "^2.1.0" + "cosmiconfig": "^7.0.1", + "deepmerge": "^4.2.2", + "svgo": "^2.5.0" }, "engines": { - "node": ">=12.13.0" + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" }, "peerDependencies": { - "react": "^16.8.4 || ^17.0.0", - "react-dom": "^16.8.4 || ^17.0.0" + "@svgr/core": "^6.0.0" } }, - "node_modules/@docusaurus/plugin-debug/node_modules/fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "node_modules/@docusaurus/core/node_modules/@svgr/webpack": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/@svgr/webpack/-/webpack-6.2.1.tgz", + "integrity": "sha512-h09ngMNd13hnePwgXa+Y5CgOjzlCvfWLHg+MBnydEedAnuLRzUHUJmGS3o2OsrhxTOOqEsPOFt5v/f6C5Qulcw==", "dependencies": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" + "@babel/core": "^7.15.5", + "@babel/plugin-transform-react-constant-elements": "^7.14.5", + "@babel/preset-env": "^7.15.6", + "@babel/preset-react": "^7.14.5", + "@babel/preset-typescript": "^7.15.0", + "@svgr/core": "^6.2.1", + "@svgr/plugin-jsx": "^6.2.1", + "@svgr/plugin-svgo": "^6.2.0" }, "engines": { "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" } }, - "node_modules/@docusaurus/plugin-google-analytics": { - "version": "2.0.0-beta.6", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-analytics/-/plugin-google-analytics-2.0.0-beta.6.tgz", - "integrity": "sha512-AHbMNPN3gkWXYFnmHL9MBcRODByAgzHZoH/5v3xwbSV2FOZo6kx4Hp94I6oFM0o5mp+i6X7slDncgGTWSGxCMg==", + "node_modules/@docusaurus/core/node_modules/css-loader": { + "version": "6.7.1", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.7.1.tgz", + "integrity": "sha512-yB5CNFa14MbPJcomwNh3wLThtkZgcNyI2bNMRt8iE5Z8Vwl7f8vQXFAzn2HDOJvtDq2NTZBUGMSUNNyrv3/+cw==", "dependencies": { - "@docusaurus/core": "2.0.0-beta.6" + "icss-utils": "^5.1.0", + "postcss": "^8.4.7", + "postcss-modules-extract-imports": "^3.0.0", + "postcss-modules-local-by-default": "^4.0.0", + "postcss-modules-scope": "^3.0.0", + "postcss-modules-values": "^4.0.0", + "postcss-value-parser": "^4.2.0", + "semver": "^7.3.5" }, "engines": { - "node": ">=12.13.0" + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" }, "peerDependencies": { - "react": "^16.8.4 || ^17.0.0", - "react-dom": "^16.8.4 || ^17.0.0" + "webpack": "^5.0.0" } }, - "node_modules/@docusaurus/plugin-google-gtag": { - "version": "2.0.0-beta.6", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-gtag/-/plugin-google-gtag-2.0.0-beta.6.tgz", - "integrity": "sha512-uJyQ30sXbVRS3TGtVJFA0s1ozrluuREu6NK2Z3TLtKpeT2NTe5iaqXN0Xp749hr3bjbgpEe6gMixVh//jg503w==", + "node_modules/@docusaurus/core/node_modules/css-tree": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz", + "integrity": "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==", "dependencies": { - "@docusaurus/core": "2.0.0-beta.6" + "mdn-data": "2.0.14", + "source-map": "^0.6.1" }, "engines": { - "node": ">=12.13.0" - }, - "peerDependencies": { - "react": "^16.8.4 || ^17.0.0", - "react-dom": "^16.8.4 || ^17.0.0" + "node": ">=8.0.0" } }, - "node_modules/@docusaurus/plugin-ideal-image": { - "version": "2.0.0-beta.6", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-ideal-image/-/plugin-ideal-image-2.0.0-beta.6.tgz", - "integrity": "sha512-v8IkaELNHGG90Z0KbtpCPsxcNFwlzZF37LoqyHTzAvvIVmctUWkWUgysIwccbrN3qiYVydPUZA4HZ8X+cTB7Zw==", - "dependencies": { - "@docusaurus/core": "2.0.0-beta.6", - "@docusaurus/lqip-loader": "2.0.0-beta.6", - "@docusaurus/responsive-loader": "1.4.0", - "@docusaurus/types": "2.0.0-beta.6", - "@endiliey/react-ideal-image": "^0.0.11", - "react-waypoint": "^10.1.0", - "sharp": "^0.28.2", - "tslib": "^2.1.0", - "webpack": "^5.40.0" - }, + "node_modules/@docusaurus/core/node_modules/entities": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-3.0.1.tgz", + "integrity": "sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q==", "engines": { - "node": ">=12.13.0" + "node": ">=0.12" }, - "peerDependencies": { - "react": "^16.8.4 || ^17.0.0", - "react-dom": "^16.8.4 || ^17.0.0" + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" } }, - "node_modules/@docusaurus/plugin-sitemap": { - "version": "2.0.0-beta.6", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-sitemap/-/plugin-sitemap-2.0.0-beta.6.tgz", - "integrity": "sha512-jpTaODqyCgg+20RtMw8gSvCKQOvH18FpKhIu6FG+z4zgHP33qaJouVM7/1ZKPrfNt4z7xDOyBNUzzdmpssHA8A==", - "dependencies": { - "@docusaurus/core": "2.0.0-beta.6", - "@docusaurus/types": "2.0.0-beta.6", - "@docusaurus/utils": "2.0.0-beta.6", - "@docusaurus/utils-common": "2.0.0-beta.6", - "@docusaurus/utils-validation": "2.0.0-beta.6", - "fs-extra": "^10.0.0", - "sitemap": "^7.0.0", - "tslib": "^2.2.0" - }, + "node_modules/@docusaurus/core/node_modules/icss-utils": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", + "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", "engines": { - "node": ">=12.13.0" + "node": "^10 || ^12 || >= 14" }, "peerDependencies": { - "react": "^16.8.4 || ^17.0.0", - "react-dom": "^16.8.4 || ^17.0.0" + "postcss": "^8.1.0" } }, - "node_modules/@docusaurus/preset-classic": { - "version": "2.0.0-beta.6", - "resolved": "https://registry.npmjs.org/@docusaurus/preset-classic/-/preset-classic-2.0.0-beta.6.tgz", - "integrity": "sha512-riqQRcNssNH7oto8nAjYIO79/ZucidexHTDlgD+trP56ploHLJp4kIlxb44IGOmx3es8/z4egWtM+acY/39N2Q==", - "dependencies": { - "@docusaurus/core": "2.0.0-beta.6", - "@docusaurus/plugin-content-blog": "2.0.0-beta.6", - "@docusaurus/plugin-content-docs": "2.0.0-beta.6", - "@docusaurus/plugin-content-pages": "2.0.0-beta.6", - "@docusaurus/plugin-debug": "2.0.0-beta.6", - "@docusaurus/plugin-google-analytics": "2.0.0-beta.6", - "@docusaurus/plugin-google-gtag": "2.0.0-beta.6", - "@docusaurus/plugin-sitemap": "2.0.0-beta.6", - "@docusaurus/theme-classic": "2.0.0-beta.6", - "@docusaurus/theme-search-algolia": "2.0.0-beta.6" - }, + "node_modules/@docusaurus/core/node_modules/mdn-data": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz", + "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==" + }, + "node_modules/@docusaurus/core/node_modules/postcss-modules-extract-imports": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz", + "integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==", "engines": { - "node": ">=12.13.0" + "node": "^10 || ^12 || >= 14" }, "peerDependencies": { - "react": "^16.8.4 || ^17.0.0", - "react-dom": "^16.8.4 || ^17.0.0" + "postcss": "^8.1.0" } }, - "node_modules/@docusaurus/react-loadable": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@docusaurus/react-loadable/-/react-loadable-5.5.0.tgz", - "integrity": "sha512-Ld/kwUE6yATIOTLq3JCsWiTa/drisajwKqBQ2Rw6IcT+sFsKfYek8F2jSH8f68AT73xX97UehduZeCSlnuCBIg==", + "node_modules/@docusaurus/core/node_modules/postcss-modules-local-by-default": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.0.tgz", + "integrity": "sha512-sT7ihtmGSF9yhm6ggikHdV0hlziDTX7oFoXtuVWeDd3hHObNkcHRo9V3yg7vCAY7cONyxJC/XXCmmiHHcvX7bQ==", "dependencies": { - "prop-types": "^15.6.2" + "icss-utils": "^5.0.0", + "postcss-selector-parser": "^6.0.2", + "postcss-value-parser": "^4.1.0" + }, + "engines": { + "node": "^10 || ^12 || >= 14" }, "peerDependencies": { - "react": "*" + "postcss": "^8.1.0" } }, - "node_modules/@docusaurus/responsive-loader": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/responsive-loader/-/responsive-loader-1.4.0.tgz", - "integrity": "sha512-qkVjSEUM4dVNmgOWkjbuRetZegOiCnzGPOzS1FPmxMrc9jCI70Rusx67EYdYPyAu47F2cvUf8PwX0o6AUzfNTQ==", + "node_modules/@docusaurus/core/node_modules/postcss-modules-scope": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.0.0.tgz", + "integrity": "sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg==", "dependencies": { - "loader-utils": "^2.0.0" + "postcss-selector-parser": "^6.0.4" }, "engines": { - "node": ">=10" + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" } }, - "node_modules/@docusaurus/theme-classic": { - "version": "2.0.0-beta.6", - "resolved": "https://registry.npmjs.org/@docusaurus/theme-classic/-/theme-classic-2.0.0-beta.6.tgz", - "integrity": "sha512-fMb6gAKUdaojInZabimIJE+yPWs8dQfmZII7v/LHmgxafh/FylmrBkKhyJfa2ix4QRibo9E01LGX44/aKzemxw==", - "dependencies": { - "@docusaurus/core": "2.0.0-beta.6", - "@docusaurus/plugin-content-blog": "2.0.0-beta.6", - "@docusaurus/plugin-content-docs": "2.0.0-beta.6", - "@docusaurus/plugin-content-pages": "2.0.0-beta.6", - "@docusaurus/theme-common": "2.0.0-beta.6", - "@docusaurus/types": "2.0.0-beta.6", - "@docusaurus/utils": "2.0.0-beta.6", - "@docusaurus/utils-common": "2.0.0-beta.6", - "@docusaurus/utils-validation": "2.0.0-beta.6", - "@mdx-js/mdx": "^1.6.21", - "@mdx-js/react": "^1.6.21", - "chalk": "^4.1.1", - "clsx": "^1.1.1", - "copy-text-to-clipboard": "^3.0.1", - "fs-extra": "^10.0.0", - "globby": "^11.0.2", - "infima": "0.2.0-alpha.33", - "lodash": "^4.17.20", - "parse-numeric-range": "^1.2.0", - "postcss": "^8.2.15", - "prism-react-renderer": "^1.2.1", - "prismjs": "^1.23.0", - "prop-types": "^15.7.2", - "react-router-dom": "^5.2.0", - "rtlcss": "^3.1.2" + "node_modules/@docusaurus/core/node_modules/postcss-modules-values": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", + "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", + "dependencies": { + "icss-utils": "^5.0.0" }, "engines": { - "node": ">=12.13.0" + "node": "^10 || ^12 || >= 14" }, "peerDependencies": { - "react": "^16.8.4 || ^17.0.0", - "react-dom": "^16.8.4 || ^17.0.0" + "postcss": "^8.1.0" } }, - "node_modules/@docusaurus/theme-common": { - "version": "2.0.0-beta.6", - "resolved": "https://registry.npmjs.org/@docusaurus/theme-common/-/theme-common-2.0.0-beta.6.tgz", - "integrity": "sha512-53nFWMjpFdyHEvBfQQQoDm9rNKgGangy7vSp1B/F3+uRyYAItE7O4l8MdOALXFALlddiiPYvCtI1qGx2dnzndA==", - "dependencies": { - "@docusaurus/core": "2.0.0-beta.6", - "@docusaurus/plugin-content-blog": "2.0.0-beta.6", - "@docusaurus/plugin-content-docs": "2.0.0-beta.6", - "@docusaurus/plugin-content-pages": "2.0.0-beta.6", - "@docusaurus/types": "2.0.0-beta.6", - "clsx": "^1.1.1", - "fs-extra": "^10.0.0", - "tslib": "^2.1.0" + "node_modules/@docusaurus/core/node_modules/svgo": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-2.8.0.tgz", + "integrity": "sha512-+N/Q9kV1+F+UeWYoSiULYo4xYSDQlTgb+ayMobAXPwMnLvop7oxKMo9OzIrX5x3eS4L4f2UHhc9axXwY8DpChg==", + "dependencies": { + "@trysound/sax": "0.2.0", + "commander": "^7.2.0", + "css-select": "^4.1.3", + "css-tree": "^1.1.3", + "csso": "^4.2.0", + "picocolors": "^1.0.0", + "stable": "^0.1.8" }, - "engines": { - "node": ">=12.13.0" + "bin": { + "svgo": "bin/svgo" }, - "peerDependencies": { - "prism-react-renderer": "^1.2.1", - "react": "^16.8.4 || ^17.0.0", - "react-dom": "^16.8.4 || ^17.0.0" + "engines": { + "node": ">=10.13.0" } }, - "node_modules/@docusaurus/theme-search-algolia": { - "version": "2.0.0-beta.6", - "resolved": "https://registry.npmjs.org/@docusaurus/theme-search-algolia/-/theme-search-algolia-2.0.0-beta.6.tgz", - "integrity": "sha512-GaaYdf6EEKL3jwmt9LRyiMtNvobOhw4vGuYJKbJcgba/M75kOJSbZPRrhALBAe6o4gOYbV44afzFC/jUUp7dsA==", - "dependencies": { - "@docsearch/react": "^3.0.0-alpha.39", - "@docusaurus/core": "2.0.0-beta.6", - "@docusaurus/theme-common": "2.0.0-beta.6", - "@docusaurus/utils": "2.0.0-beta.6", - "@docusaurus/utils-validation": "2.0.0-beta.6", - "algoliasearch": "^4.8.4", - "algoliasearch-helper": "^3.3.4", - "clsx": "^1.1.1", - "eta": "^1.12.1", - "lodash": "^4.17.20" - }, + "node_modules/@docusaurus/core/node_modules/svgo/node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", "engines": { - "node": ">=12.13.0" - }, - "peerDependencies": { - "react": "^16.8.4 || ^17.0.0", - "react-dom": "^16.8.4 || ^17.0.0" + "node": ">= 10" } }, - "node_modules/@docusaurus/types": { - "version": "2.0.0-beta.6", - "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-2.0.0-beta.6.tgz", - "integrity": "sha512-TrwxyI93XTZEhOmdEI8FPKDbGV61zE9PzXCdE1alwz1NOV+YXwcv+9sRTZEVLqBpr+TIja+IeeS6mxnyen/Ptg==", + "node_modules/@docusaurus/cssnano-preset": { + "version": "2.0.0-beta.17", + "resolved": "https://registry.npmjs.org/@docusaurus/cssnano-preset/-/cssnano-preset-2.0.0-beta.17.tgz", + "integrity": "sha512-DoBwtLjJ9IY9/lNMHIEdo90L4NDayvU28nLgtjR2Sc6aBIMEB/3a5Ndjehnp+jZAkwcDdNASA86EkZVUyz1O1A==", "dependencies": { - "commander": "^5.1.0", - "joi": "^17.4.0", - "querystring": "0.2.0", - "webpack": "^5.40.0", - "webpack-merge": "^5.8.0" + "cssnano-preset-advanced": "^5.1.12", + "postcss": "^8.4.7", + "postcss-sort-media-queries": "^4.2.1" } }, - "node_modules/@docusaurus/utils": { - "version": "2.0.0-beta.6", - "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-2.0.0-beta.6.tgz", - "integrity": "sha512-S72/o7VDaTvrXJy+NpfuctghGGoMW30m94PMkrL3I6V+o5eE2Uzax7dbM++moclmHvi0/Khv+TXmRIQs6ZvwgQ==", + "node_modules/@docusaurus/logger": { + "version": "2.0.0-beta.17", + "resolved": "https://registry.npmjs.org/@docusaurus/logger/-/logger-2.0.0-beta.17.tgz", + "integrity": "sha512-F9JDl06/VLg+ylsvnq9NpILSUeWtl0j4H2LtlLzX5gufEL4dGiCMlnUzYdHl7FSHSzYJ0A/R7vu0SYofsexC4w==", "dependencies": { - "@docusaurus/types": "2.0.0-beta.6", - "@types/github-slugger": "^1.3.0", - "chalk": "^4.1.1", - "escape-string-regexp": "^4.0.0", - "fs-extra": "^10.0.0", - "globby": "^11.0.4", - "gray-matter": "^4.0.3", - "lodash": "^4.17.20", - "micromatch": "^4.0.4", - "resolve-pathname": "^3.0.0", - "tslib": "^2.2.0" + "chalk": "^4.1.2", + "tslib": "^2.3.1" }, "engines": { - "node": ">=12.13.0" + "node": ">=14" } }, - "node_modules/@docusaurus/utils-common": { - "version": "2.0.0-beta.6", - "resolved": "https://registry.npmjs.org/@docusaurus/utils-common/-/utils-common-2.0.0-beta.6.tgz", - "integrity": "sha512-MKm6bJxvsYWRl072jLR60z+71tTWSxoERh2eTmCYlegFnu3Tby3HOC8I3jDcC6VpVuoDGsBGNoQbOgy2LqQbXQ==", + "node_modules/@docusaurus/logger/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dependencies": { - "@docusaurus/types": "2.0.0-beta.6", - "tslib": "^2.2.0" + "color-convert": "^2.0.1" }, "engines": { - "node": ">=12.13.0" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/@docusaurus/utils-validation": { - "version": "2.0.0-beta.6", - "resolved": "https://registry.npmjs.org/@docusaurus/utils-validation/-/utils-validation-2.0.0-beta.6.tgz", - "integrity": "sha512-v0nk9bpawUd2JFDFyiHDmZuMG+/O1UvxtxvcRbvrxrul+rlzD7Q9CGxMgW3Grp2OCKQ4yFXRidBIccwqON5AVw==", + "node_modules/@docusaurus/logger/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dependencies": { - "@docusaurus/utils": "2.0.0-beta.6", - "chalk": "^4.1.1", - "joi": "^17.4.0", - "tslib": "^2.1.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, - "engines": { - "node": ">=12.13.0" - } - }, - "node_modules/@docusaurus/utils/node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "engines": { "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/@emotion/is-prop-valid": { - "version": "0.8.8", - "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-0.8.8.tgz", - "integrity": "sha512-u5WtneEAr5IDG2Wv65yhunPSMLIpuKsbuOktRojfrEiEvRyC85LgPMZI63cr7NUqT8ZIGdSVg8ZKGxIug4lXcA==", + "node_modules/@docusaurus/logger/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dependencies": { - "@emotion/memoize": "0.7.4" + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" } }, - "node_modules/@emotion/memoize": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.7.4.tgz", - "integrity": "sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw==" - }, - "node_modules/@emotion/stylis": { - "version": "0.8.5", - "resolved": "https://registry.npmjs.org/@emotion/stylis/-/stylis-0.8.5.tgz", - "integrity": "sha512-h6KtPihKFn3T9fuIrwvXXUOwlx3rfUvfZIcP5a6rh8Y7zjE3O06hT5Ss4S/YI1AYhuZ1kjaE/5EaOOI2NqSylQ==" - }, - "node_modules/@emotion/unitless": { - "version": "0.7.5", - "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.7.5.tgz", - "integrity": "sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg==" + "node_modules/@docusaurus/logger/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, - "node_modules/@endiliey/react-ideal-image": { - "version": "0.0.11", - "resolved": "https://registry.npmjs.org/@endiliey/react-ideal-image/-/react-ideal-image-0.0.11.tgz", - "integrity": "sha512-QxMjt/Gvur/gLxSoCy7VIyGGGrGmDN+VHcXkN3R2ApoWX0EYUE+hMgPHSW/PV6VVebZ1Nd4t2UnGRBDihu16JQ==", + "node_modules/@docusaurus/logger/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "engines": { - "node": ">= 8.9.0", - "npm": "> 3" - }, - "peerDependencies": { - "prop-types": ">=15", - "react": ">=0.14.x", - "react-waypoint": ">=9.0.2" + "node": ">=8" } }, - "node_modules/@exodus/schemasafe": { - "version": "1.0.0-rc.6", - "resolved": "https://registry.npmjs.org/@exodus/schemasafe/-/schemasafe-1.0.0-rc.6.tgz", - "integrity": "sha512-dDnQizD94EdBwEj/fh3zPRa/HWCS9O5au2PuHhZBbuM3xWHxuaKzPBOEWze7Nn0xW68MIpZ7Xdyn1CoCpjKCuQ==" - }, - "node_modules/@hapi/hoek": { - "version": "9.2.1", - "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.2.1.tgz", - "integrity": "sha512-gfta+H8aziZsm8pZa0vj04KO6biEiisppNgA1kbJvFrrWu9Vm7eaUEy76DIxsuTaWvti5fkJVhllWc6ZTE+Mdw==" - }, - "node_modules/@hapi/topo": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-5.1.0.tgz", - "integrity": "sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==", + "node_modules/@docusaurus/logger/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dependencies": { - "@hapi/hoek": "^9.0.0" + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" } }, - "node_modules/@jimp/bmp": { - "version": "0.16.1", - "resolved": "https://registry.npmjs.org/@jimp/bmp/-/bmp-0.16.1.tgz", - "integrity": "sha512-iwyNYQeBawrdg/f24x3pQ5rEx+/GwjZcCXd3Kgc+ZUd+Ivia7sIqBsOnDaMZdKCBPlfW364ekexnlOqyVa0NWg==", + "node_modules/@docusaurus/lqip-loader": { + "version": "2.0.0-beta.17", + "resolved": "https://registry.npmjs.org/@docusaurus/lqip-loader/-/lqip-loader-2.0.0-beta.17.tgz", + "integrity": "sha512-pqwVuSYOthQgVVUmc8lI36hHzewKbBZBjLgxl3Khd2xL1gShZcb8o0Zx0IXSvqskZaq3E3TXRuzBAjyvIRaKdw==", "dependencies": { - "@babel/runtime": "^7.7.2", - "@jimp/utils": "^0.16.1", - "bmp-js": "^0.1.0" + "@docusaurus/logger": "2.0.0-beta.17", + "file-loader": "^6.2.0", + "lodash": "^4.17.21", + "node-vibrant": "^3.1.6", + "sharp": "^0.30.1", + "tslib": "^2.3.1" }, - "peerDependencies": { - "@jimp/custom": ">=0.3.5" + "engines": { + "node": ">=14" } }, - "node_modules/@jimp/core": { - "version": "0.16.1", - "resolved": "https://registry.npmjs.org/@jimp/core/-/core-0.16.1.tgz", - "integrity": "sha512-la7kQia31V6kQ4q1kI/uLimu8FXx7imWVajDGtwUG8fzePLWDFJyZl0fdIXVCL1JW2nBcRHidUot6jvlRDi2+g==", - "dependencies": { - "@babel/runtime": "^7.7.2", - "@jimp/utils": "^0.16.1", - "any-base": "^1.1.0", - "buffer": "^5.2.0", - "exif-parser": "^0.1.12", - "file-type": "^9.0.0", - "load-bmfont": "^1.3.1", - "mkdirp": "^0.5.1", - "phin": "^2.9.1", - "pixelmatch": "^4.0.2", - "tinycolor2": "^1.4.1" + "node_modules/@docusaurus/mdx-loader": { + "version": "2.0.0-beta.17", + "resolved": "https://registry.npmjs.org/@docusaurus/mdx-loader/-/mdx-loader-2.0.0-beta.17.tgz", + "integrity": "sha512-AhJ3GWRmjQYCyINHE595pff5tn3Rt83oGpdev5UT9uvG9lPYPC8nEmh1LI6c0ogfw7YkNznzxWSW4hyyVbYQ3A==", + "dependencies": { + "@babel/parser": "^7.17.3", + "@babel/traverse": "^7.17.3", + "@docusaurus/logger": "2.0.0-beta.17", + "@docusaurus/utils": "2.0.0-beta.17", + "@mdx-js/mdx": "^1.6.22", + "escape-html": "^1.0.3", + "file-loader": "^6.2.0", + "fs-extra": "^10.0.1", + "image-size": "^1.0.1", + "mdast-util-to-string": "^2.0.0", + "remark-emoji": "^2.1.0", + "stringify-object": "^3.3.0", + "tslib": "^2.3.1", + "unist-util-visit": "^2.0.2", + "url-loader": "^4.1.1", + "webpack": "^5.69.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "react": "^16.8.4 || ^17.0.0", + "react-dom": "^16.8.4 || ^17.0.0" } }, - "node_modules/@jimp/custom": { - "version": "0.16.1", - "resolved": "https://registry.npmjs.org/@jimp/custom/-/custom-0.16.1.tgz", - "integrity": "sha512-DNUAHNSiUI/j9hmbatD6WN/EBIyeq4AO0frl5ETtt51VN1SvE4t4v83ZA/V6ikxEf3hxLju4tQ5Pc3zmZkN/3A==", + "node_modules/@docusaurus/module-type-aliases": { + "version": "2.0.0-beta.17", + "resolved": "https://registry.npmjs.org/@docusaurus/module-type-aliases/-/module-type-aliases-2.0.0-beta.17.tgz", + "integrity": "sha512-Tu+8geC/wyygBudbSwvWIHEvt5RwyA7dEoE1JmPbgQtmqUxOZ9bgnfemwXpJW5mKuDiJASbN4of1DhbLqf4sPg==", "dependencies": { - "@babel/runtime": "^7.7.2", - "@jimp/core": "^0.16.1" + "@docusaurus/types": "2.0.0-beta.17", + "@types/react": "*", + "@types/react-router-config": "*", + "@types/react-router-dom": "*", + "react-helmet-async": "*" + }, + "peerDependencies": { + "react": "*", + "react-dom": "*" } }, - "node_modules/@jimp/gif": { - "version": "0.16.1", - "resolved": "https://registry.npmjs.org/@jimp/gif/-/gif-0.16.1.tgz", - "integrity": "sha512-r/1+GzIW1D5zrP4tNrfW+3y4vqD935WBXSc8X/wm23QTY9aJO9Lw6PEdzpYCEY+SOklIFKaJYUAq/Nvgm/9ryw==", - "dependencies": { - "@babel/runtime": "^7.7.2", - "@jimp/utils": "^0.16.1", - "gifwrap": "^0.9.2", - "omggif": "^1.0.9" + "node_modules/@docusaurus/plugin-content-blog": { + "version": "2.0.0-beta.17", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-blog/-/plugin-content-blog-2.0.0-beta.17.tgz", + "integrity": "sha512-gcX4UR+WKT4bhF8FICBQHy+ESS9iRMeaglSboTZbA/YHGax/3EuZtcPU3dU4E/HFJeZ866wgUdbLKpIpsZOidg==", + "dependencies": { + "@docusaurus/core": "2.0.0-beta.17", + "@docusaurus/logger": "2.0.0-beta.17", + "@docusaurus/mdx-loader": "2.0.0-beta.17", + "@docusaurus/utils": "2.0.0-beta.17", + "@docusaurus/utils-common": "2.0.0-beta.17", + "@docusaurus/utils-validation": "2.0.0-beta.17", + "cheerio": "^1.0.0-rc.10", + "feed": "^4.2.2", + "fs-extra": "^10.0.1", + "lodash": "^4.17.21", + "reading-time": "^1.5.0", + "remark-admonitions": "^1.2.1", + "tslib": "^2.3.1", + "utility-types": "^3.10.0", + "webpack": "^5.69.1" + }, + "engines": { + "node": ">=14" }, "peerDependencies": { - "@jimp/custom": ">=0.3.5" + "react": "^16.8.4 || ^17.0.0", + "react-dom": "^16.8.4 || ^17.0.0" } }, - "node_modules/@jimp/jpeg": { - "version": "0.16.1", - "resolved": "https://registry.npmjs.org/@jimp/jpeg/-/jpeg-0.16.1.tgz", - "integrity": "sha512-8352zrdlCCLFdZ/J+JjBslDvml+fS3Z8gttdml0We759PnnZGqrnPRhkOEOJbNUlE+dD4ckLeIe6NPxlS/7U+w==", - "dependencies": { - "@babel/runtime": "^7.7.2", - "@jimp/utils": "^0.16.1", - "jpeg-js": "0.4.2" + "node_modules/@docusaurus/plugin-content-docs": { + "version": "2.0.0-beta.17", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-docs/-/plugin-content-docs-2.0.0-beta.17.tgz", + "integrity": "sha512-YYrBpuRfTfE6NtENrpSHTJ7K7PZifn6j6hcuvdC0QKE+WD8pS+O2/Ws30yoyvHwLnAnfhvaderh1v9Kaa0/ANg==", + "dependencies": { + "@docusaurus/core": "2.0.0-beta.17", + "@docusaurus/logger": "2.0.0-beta.17", + "@docusaurus/mdx-loader": "2.0.0-beta.17", + "@docusaurus/utils": "2.0.0-beta.17", + "@docusaurus/utils-validation": "2.0.0-beta.17", + "combine-promises": "^1.1.0", + "fs-extra": "^10.0.1", + "import-fresh": "^3.3.0", + "js-yaml": "^4.1.0", + "lodash": "^4.17.21", + "remark-admonitions": "^1.2.1", + "tslib": "^2.3.1", + "utility-types": "^3.10.0", + "webpack": "^5.69.1" + }, + "engines": { + "node": ">=14" }, "peerDependencies": { - "@jimp/custom": ">=0.3.5" + "react": "^16.8.4 || ^17.0.0", + "react-dom": "^16.8.4 || ^17.0.0" } }, - "node_modules/@jimp/plugin-resize": { - "version": "0.16.1", - "resolved": "https://registry.npmjs.org/@jimp/plugin-resize/-/plugin-resize-0.16.1.tgz", - "integrity": "sha512-u4JBLdRI7dargC04p2Ha24kofQBk3vhaf0q8FwSYgnCRwxfvh2RxvhJZk9H7Q91JZp6wgjz/SjvEAYjGCEgAwQ==", - "dependencies": { - "@babel/runtime": "^7.7.2", - "@jimp/utils": "^0.16.1" + "node_modules/@docusaurus/plugin-content-pages": { + "version": "2.0.0-beta.17", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-pages/-/plugin-content-pages-2.0.0-beta.17.tgz", + "integrity": "sha512-d5x0mXTMJ44ojRQccmLyshYoamFOep2AnBe69osCDnwWMbD3Or3pnc2KMK9N7mVpQFnNFKbHNCLrX3Rv0uwEHA==", + "dependencies": { + "@docusaurus/core": "2.0.0-beta.17", + "@docusaurus/mdx-loader": "2.0.0-beta.17", + "@docusaurus/utils": "2.0.0-beta.17", + "@docusaurus/utils-validation": "2.0.0-beta.17", + "fs-extra": "^10.0.1", + "remark-admonitions": "^1.2.1", + "tslib": "^2.3.1", + "webpack": "^5.69.1" + }, + "engines": { + "node": ">=14" }, "peerDependencies": { - "@jimp/custom": ">=0.3.5" + "react": "^16.8.4 || ^17.0.0", + "react-dom": "^16.8.4 || ^17.0.0" } }, - "node_modules/@jimp/png": { - "version": "0.16.1", - "resolved": "https://registry.npmjs.org/@jimp/png/-/png-0.16.1.tgz", - "integrity": "sha512-iyWoCxEBTW0OUWWn6SveD4LePW89kO7ZOy5sCfYeDM/oTPLpR8iMIGvZpZUz1b8kvzFr27vPst4E5rJhGjwsdw==", + "node_modules/@docusaurus/plugin-debug": { + "version": "2.0.0-beta.17", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-debug/-/plugin-debug-2.0.0-beta.17.tgz", + "integrity": "sha512-p26fjYFRSC0esEmKo/kRrLVwXoFnzPCFDumwrImhPyqfVxbj+IKFaiXkayb2qHnyEGE/1KSDIgRF4CHt/pyhiw==", "dependencies": { - "@babel/runtime": "^7.7.2", - "@jimp/utils": "^0.16.1", - "pngjs": "^3.3.3" + "@docusaurus/core": "2.0.0-beta.17", + "@docusaurus/utils": "2.0.0-beta.17", + "fs-extra": "^10.0.1", + "react-json-view": "^1.21.3", + "tslib": "^2.3.1" + }, + "engines": { + "node": ">=14" }, "peerDependencies": { - "@jimp/custom": ">=0.3.5" + "react": "^16.8.4 || ^17.0.0", + "react-dom": "^16.8.4 || ^17.0.0" } }, - "node_modules/@jimp/tiff": { - "version": "0.16.1", - "resolved": "https://registry.npmjs.org/@jimp/tiff/-/tiff-0.16.1.tgz", - "integrity": "sha512-3K3+xpJS79RmSkAvFMgqY5dhSB+/sxhwTFA9f4AVHUK0oKW+u6r52Z1L0tMXHnpbAdR9EJ+xaAl2D4x19XShkQ==", + "node_modules/@docusaurus/plugin-google-analytics": { + "version": "2.0.0-beta.17", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-analytics/-/plugin-google-analytics-2.0.0-beta.17.tgz", + "integrity": "sha512-jvgYIhggYD1W2jymqQVAAyjPJUV1xMCn70bAzaCMxriureMWzhQ/kQMVQpop0ijTMvifOxaV9yTcL1VRXev++A==", "dependencies": { - "@babel/runtime": "^7.7.2", - "utif": "^2.0.1" + "@docusaurus/core": "2.0.0-beta.17", + "@docusaurus/utils-validation": "2.0.0-beta.17", + "tslib": "^2.3.1" + }, + "engines": { + "node": ">=14" }, "peerDependencies": { - "@jimp/custom": ">=0.3.5" + "react": "^16.8.4 || ^17.0.0", + "react-dom": "^16.8.4 || ^17.0.0" } }, - "node_modules/@jimp/types": { - "version": "0.16.1", - "resolved": "https://registry.npmjs.org/@jimp/types/-/types-0.16.1.tgz", - "integrity": "sha512-g1w/+NfWqiVW4CaXSJyD28JQqZtm2eyKMWPhBBDCJN9nLCN12/Az0WFF3JUAktzdsEC2KRN2AqB1a2oMZBNgSQ==", + "node_modules/@docusaurus/plugin-google-gtag": { + "version": "2.0.0-beta.17", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-gtag/-/plugin-google-gtag-2.0.0-beta.17.tgz", + "integrity": "sha512-1pnWHtIk1Jfeqwvr8PlcPE5SODWT1gW4TI+ptmJbJ296FjjyvL/pG0AcGEJmYLY/OQc3oz0VQ0W2ognw9jmFIw==", "dependencies": { - "@babel/runtime": "^7.7.2", - "@jimp/bmp": "^0.16.1", - "@jimp/gif": "^0.16.1", - "@jimp/jpeg": "^0.16.1", - "@jimp/png": "^0.16.1", - "@jimp/tiff": "^0.16.1", - "timm": "^1.6.1" + "@docusaurus/core": "2.0.0-beta.17", + "@docusaurus/utils-validation": "2.0.0-beta.17", + "tslib": "^2.3.1" + }, + "engines": { + "node": ">=14" }, "peerDependencies": { - "@jimp/custom": ">=0.3.5" + "react": "^16.8.4 || ^17.0.0", + "react-dom": "^16.8.4 || ^17.0.0" } }, - "node_modules/@jimp/utils": { - "version": "0.16.1", - "resolved": "https://registry.npmjs.org/@jimp/utils/-/utils-0.16.1.tgz", - "integrity": "sha512-8fULQjB0x4LzUSiSYG6ZtQl355sZjxbv8r9PPAuYHzS9sGiSHJQavNqK/nKnpDsVkU88/vRGcE7t3nMU0dEnVw==", - "dependencies": { - "@babel/runtime": "^7.7.2", - "regenerator-runtime": "^0.13.3" + "node_modules/@docusaurus/plugin-ideal-image": { + "version": "2.0.0-beta.17", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-ideal-image/-/plugin-ideal-image-2.0.0-beta.17.tgz", + "integrity": "sha512-9ZUi3cVnQsOCW4NSDyQRbH4UmlLqclKjQNQv+O/BKwO5EkjLeB4Q2TeHaXkivntrY4nARGjRcGBHKb3L9zzJXA==", + "dependencies": { + "@docusaurus/core": "2.0.0-beta.17", + "@docusaurus/lqip-loader": "2.0.0-beta.17", + "@docusaurus/responsive-loader": "^1.7.0", + "@docusaurus/theme-translations": "2.0.0-beta.17", + "@docusaurus/utils-validation": "2.0.0-beta.17", + "@endiliey/react-ideal-image": "^0.0.11", + "react-waypoint": "^10.1.0", + "sharp": "^0.30.1", + "tslib": "^2.3.1", + "webpack": "^5.69.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "jimp": "*", + "react": "^16.8.4 || ^17.0.0", + "react-dom": "^16.8.4 || ^17.0.0" + }, + "peerDependenciesMeta": { + "jimp": { + "optional": true + } } }, - "node_modules/@mdx-js/mdx": { - "version": "1.6.22", - "resolved": "https://registry.npmjs.org/@mdx-js/mdx/-/mdx-1.6.22.tgz", - "integrity": "sha512-AMxuLxPz2j5/6TpF/XSdKpQP1NlG0z11dFOlq+2IP/lSgl11GY8ji6S/rgsViN/L0BDvHvUMruRb7ub+24LUYA==", + "node_modules/@docusaurus/plugin-sitemap": { + "version": "2.0.0-beta.17", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-sitemap/-/plugin-sitemap-2.0.0-beta.17.tgz", + "integrity": "sha512-19/PaGCsap6cjUPZPGs87yV9e1hAIyd0CTSeVV6Caega8nmOKk20FTrQGFJjZPeX8jvD9QIXcdg6BJnPxcKkaQ==", "dependencies": { - "@babel/core": "7.12.9", - "@babel/plugin-syntax-jsx": "7.12.1", - "@babel/plugin-syntax-object-rest-spread": "7.8.3", - "@mdx-js/util": "1.6.22", - "babel-plugin-apply-mdx-type-prop": "1.6.22", - "babel-plugin-extract-import-names": "1.6.22", - "camelcase-css": "2.0.1", - "detab": "2.0.4", - "hast-util-raw": "6.0.1", - "lodash.uniq": "4.5.0", - "mdast-util-to-hast": "10.0.1", - "remark-footnotes": "2.0.0", - "remark-mdx": "1.6.22", - "remark-parse": "8.0.3", - "remark-squeeze-paragraphs": "4.0.0", - "style-to-object": "0.3.0", - "unified": "9.2.0", - "unist-builder": "2.0.3", - "unist-util-visit": "2.0.3" + "@docusaurus/core": "2.0.0-beta.17", + "@docusaurus/utils": "2.0.0-beta.17", + "@docusaurus/utils-common": "2.0.0-beta.17", + "@docusaurus/utils-validation": "2.0.0-beta.17", + "fs-extra": "^10.0.1", + "sitemap": "^7.1.1", + "tslib": "^2.3.1" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "react": "^16.8.4 || ^17.0.0", + "react-dom": "^16.8.4 || ^17.0.0" } }, - "node_modules/@mdx-js/mdx/node_modules/@babel/core": { - "version": "7.12.9", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.12.9.tgz", - "integrity": "sha512-gTXYh3M5wb7FRXQy+FErKFAv90BnlOuNn1QkCK2lREoPAjrQCO49+HVSrFoe5uakFAF5eenS75KbO2vQiLrTMQ==", + "node_modules/@docusaurus/preset-classic": { + "version": "2.0.0-beta.17", + "resolved": "https://registry.npmjs.org/@docusaurus/preset-classic/-/preset-classic-2.0.0-beta.17.tgz", + "integrity": "sha512-7YUxPEgM09aZWr25/hpDEp1gPl+1KsCPV1ZTRW43sbQ9TinPm+9AKR3rHVDa8ea8MdiS7BpqCVyK+H/eiyQrUw==", "dependencies": { - "@babel/code-frame": "^7.10.4", - "@babel/generator": "^7.12.5", - "@babel/helper-module-transforms": "^7.12.1", - "@babel/helpers": "^7.12.5", - "@babel/parser": "^7.12.7", - "@babel/template": "^7.12.7", - "@babel/traverse": "^7.12.9", - "@babel/types": "^7.12.7", - "convert-source-map": "^1.7.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.1", - "json5": "^2.1.2", - "lodash": "^4.17.19", - "resolve": "^1.3.2", - "semver": "^5.4.1", - "source-map": "^0.5.0" + "@docusaurus/core": "2.0.0-beta.17", + "@docusaurus/plugin-content-blog": "2.0.0-beta.17", + "@docusaurus/plugin-content-docs": "2.0.0-beta.17", + "@docusaurus/plugin-content-pages": "2.0.0-beta.17", + "@docusaurus/plugin-debug": "2.0.0-beta.17", + "@docusaurus/plugin-google-analytics": "2.0.0-beta.17", + "@docusaurus/plugin-google-gtag": "2.0.0-beta.17", + "@docusaurus/plugin-sitemap": "2.0.0-beta.17", + "@docusaurus/theme-classic": "2.0.0-beta.17", + "@docusaurus/theme-common": "2.0.0-beta.17", + "@docusaurus/theme-search-algolia": "2.0.0-beta.17" }, "engines": { - "node": ">=6.9.0" + "node": ">=14" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/babel" + "peerDependencies": { + "react": "^16.8.4 || ^17.0.0", + "react-dom": "^16.8.4 || ^17.0.0" } }, - "node_modules/@mdx-js/mdx/node_modules/@babel/plugin-syntax-jsx": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.12.1.tgz", - "integrity": "sha512-1yRi7yAtB0ETgxdY9ti/p2TivUxJkTdhu/ZbF9MshVGqOx1TdB3b7xCXs49Fupgg50N45KcAsRP/ZqWjs9SRjg==", + "node_modules/@docusaurus/react-loadable": { + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/@docusaurus/react-loadable/-/react-loadable-5.5.2.tgz", + "integrity": "sha512-A3dYjdBGuy0IGT+wyLIGIKLRE+sAk1iNk0f1HjNDysO7u8lhL4N3VEm+FAubmJbAztn94F7MxBTPmnixbiyFdQ==", "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" + "@types/react": "*", + "prop-types": "^15.6.2" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "react": "*" } }, - "node_modules/@mdx-js/mdx/node_modules/is-buffer": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz", - "integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" + "node_modules/@docusaurus/responsive-loader": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@docusaurus/responsive-loader/-/responsive-loader-1.7.0.tgz", + "integrity": "sha512-N0cWuVqTRXRvkBxeMQcy/OF2l7GN8rmni5EzR3HpwR+iU2ckYPnziceojcxvvxQ5NqZg1QfEW0tycQgHp+e+Nw==", + "dependencies": { + "loader-utils": "^2.0.0" + }, + "engines": { + "node": ">=12" + }, + "peerDependencies": { + "jimp": "*", + "sharp": "*" + }, + "peerDependenciesMeta": { + "jimp": { + "optional": true }, - { - "type": "consulting", - "url": "https://feross.org/support" + "sharp": { + "optional": true } - ], - "engines": { - "node": ">=4" - } - }, - "node_modules/@mdx-js/mdx/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "bin": { - "semver": "bin/semver" } }, - "node_modules/@mdx-js/mdx/node_modules/unified": { - "version": "9.2.0", - "resolved": "https://registry.npmjs.org/unified/-/unified-9.2.0.tgz", - "integrity": "sha512-vx2Z0vY+a3YoTj8+pttM3tiJHCwY5UFbYdiWrwBEbHmK8pvsPj2rtAX2BFfgXen8T39CJWblWRDT4L5WGXtDdg==", - "dependencies": { - "bail": "^1.0.0", - "extend": "^3.0.0", - "is-buffer": "^2.0.0", - "is-plain-obj": "^2.0.0", - "trough": "^1.0.0", - "vfile": "^4.0.0" + "node_modules/@docusaurus/theme-classic": { + "version": "2.0.0-beta.17", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-classic/-/theme-classic-2.0.0-beta.17.tgz", + "integrity": "sha512-xfZ9kpgqo0lP9YO4rJj79wtiQJXU6ARo5wYy10IIwiWN+lg00scJHhkmNV431b05xIUjUr0cKeH9nqZmEsQRKg==", + "dependencies": { + "@docusaurus/core": "2.0.0-beta.17", + "@docusaurus/plugin-content-blog": "2.0.0-beta.17", + "@docusaurus/plugin-content-docs": "2.0.0-beta.17", + "@docusaurus/plugin-content-pages": "2.0.0-beta.17", + "@docusaurus/theme-common": "2.0.0-beta.17", + "@docusaurus/theme-translations": "2.0.0-beta.17", + "@docusaurus/utils": "2.0.0-beta.17", + "@docusaurus/utils-common": "2.0.0-beta.17", + "@docusaurus/utils-validation": "2.0.0-beta.17", + "@mdx-js/react": "^1.6.22", + "clsx": "^1.1.1", + "copy-text-to-clipboard": "^3.0.1", + "infima": "0.2.0-alpha.37", + "lodash": "^4.17.21", + "postcss": "^8.4.7", + "prism-react-renderer": "^1.2.1", + "prismjs": "^1.27.0", + "react-router-dom": "^5.2.0", + "rtlcss": "^3.3.0" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "react": "^16.8.4 || ^17.0.0", + "react-dom": "^16.8.4 || ^17.0.0" } }, - "node_modules/@mdx-js/react": { - "version": "1.6.22", - "resolved": "https://registry.npmjs.org/@mdx-js/react/-/react-1.6.22.tgz", - "integrity": "sha512-TDoPum4SHdfPiGSAaRBw7ECyI8VaHpK8GJugbJIJuqyh6kzw9ZLJZW3HGL3NNrJGxcAixUvqROm+YuQOo5eXtg==", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "node_modules/@docusaurus/theme-common": { + "version": "2.0.0-beta.17", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-common/-/theme-common-2.0.0-beta.17.tgz", + "integrity": "sha512-LJBDhx+Qexn1JHBqZbE4k+7lBaV1LgpE33enXf43ShB7ebhC91d5HLHhBwgt0pih4+elZU4rG+BG/roAmsNM0g==", + "dependencies": { + "@docusaurus/module-type-aliases": "2.0.0-beta.17", + "@docusaurus/plugin-content-blog": "2.0.0-beta.17", + "@docusaurus/plugin-content-docs": "2.0.0-beta.17", + "@docusaurus/plugin-content-pages": "2.0.0-beta.17", + "clsx": "^1.1.1", + "parse-numeric-range": "^1.3.0", + "prism-react-renderer": "^1.3.1", + "tslib": "^2.3.1", + "utility-types": "^3.10.0" + }, + "engines": { + "node": ">=14" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0" + "react": "^16.8.4 || ^17.0.0", + "react-dom": "^16.8.4 || ^17.0.0" } }, - "node_modules/@mdx-js/util": { - "version": "1.6.22", - "resolved": "https://registry.npmjs.org/@mdx-js/util/-/util-1.6.22.tgz", - "integrity": "sha512-H1rQc1ZOHANWBvPcW+JpGwr+juXSxM8Q8YCkm3GhZd8REu1fHR3z99CErO1p9pkcfcxZnMdIZdIsXkOHY0NilA==", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" + "node_modules/@docusaurus/theme-search-algolia": { + "version": "2.0.0-beta.17", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-search-algolia/-/theme-search-algolia-2.0.0-beta.17.tgz", + "integrity": "sha512-W12XKM7QC5Jmrec359bJ7aDp5U8DNkCxjVKsMNIs8rDunBoI/N+R35ERJ0N7Bg9ONAWO6o7VkUERQsfGqdvr9w==", + "dependencies": { + "@docsearch/react": "^3.0.0", + "@docusaurus/core": "2.0.0-beta.17", + "@docusaurus/logger": "2.0.0-beta.17", + "@docusaurus/theme-common": "2.0.0-beta.17", + "@docusaurus/theme-translations": "2.0.0-beta.17", + "@docusaurus/utils": "2.0.0-beta.17", + "@docusaurus/utils-validation": "2.0.0-beta.17", + "algoliasearch": "^4.12.1", + "algoliasearch-helper": "^3.7.0", + "clsx": "^1.1.1", + "eta": "^1.12.3", + "fs-extra": "^10.0.1", + "lodash": "^4.17.21", + "tslib": "^2.3.1", + "utility-types": "^3.10.0" }, "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "engines": { - "node": ">= 8" + "node": ">=14" + }, + "peerDependencies": { + "react": "^16.8.4 || ^17.0.0", + "react-dom": "^16.8.4 || ^17.0.0" } }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "node_modules/@docusaurus/theme-translations": { + "version": "2.0.0-beta.17", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-translations/-/theme-translations-2.0.0-beta.17.tgz", + "integrity": "sha512-oxCX6khjZH3lgdRCL0DH06KkUM/kDr9+lzB35+vY8rpFeQruVgRdi8ekPqG3+Wr0U/N+LMhcYE5BmCb6D0Fv2A==", "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" + "fs-extra": "^10.0.1", + "tslib": "^2.3.1" }, "engines": { - "node": ">= 8" + "node": ">=14" } }, - "node_modules/@polka/url": { - "version": "1.0.0-next.21", - "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.21.tgz", - "integrity": "sha512-a5Sab1C4/icpTZVzZc5Ghpz88yQtGOyNqYXcZgOssB2uuAr+wF/MvN6bgtW32q7HHrvBki+BsZ0OuNv6EV3K9g==" - }, - "node_modules/@redocly/ajv": { - "version": "8.6.2", - "resolved": "https://registry.npmjs.org/@redocly/ajv/-/ajv-8.6.2.tgz", - "integrity": "sha512-tU8fQs0D76ZKhJ2cWtnfQthWqiZgGBx0gH0+5D8JvaBEBaqA8foPPBt3Nonwr3ygyv5xrw2IzKWgIY86BlGs+w==", + "node_modules/@docusaurus/types": { + "version": "2.0.0-beta.17", + "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-2.0.0-beta.17.tgz", + "integrity": "sha512-4o7TXu5sKlQpybfFFtsGUElBXwSpiXKsQyyWaRKj7DRBkvMtkDX6ITZNnZO9+EHfLbP/cfrokB8C/oO7mCQ5BQ==", "dependencies": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" + "commander": "^5.1.0", + "joi": "^17.6.0", + "querystring": "0.2.1", + "utility-types": "^3.10.0", + "webpack": "^5.69.1", + "webpack-merge": "^5.8.0" } }, - "node_modules/@redocly/ajv/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" - }, - "node_modules/@redocly/openapi-core": { - "version": "1.0.0-beta.63", - "resolved": "https://registry.npmjs.org/@redocly/openapi-core/-/openapi-core-1.0.0-beta.63.tgz", - "integrity": "sha512-ZnIoUyZ6BJZ4wnkGM9YAHe8MqHNcgEHVTjM1IsZkvwoDQ6TTV/B7P7gHOKCcgkyBb/sQNShgSAO5Y+lIfKU2+g==", + "node_modules/@docusaurus/utils": { + "version": "2.0.0-beta.17", + "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-2.0.0-beta.17.tgz", + "integrity": "sha512-yRKGdzSc5v6M/6GyQ4omkrAHCleevwKYiIrufCJgRbOtkhYE574d8mIjjirOuA/emcyLxjh+TLtqAA5TwhIryA==", "dependencies": { - "@redocly/ajv": "^8.6.2", - "@types/node": "^14.11.8", - "colorette": "^1.2.0", - "js-levenshtein": "^1.1.6", + "@docusaurus/logger": "2.0.0-beta.17", + "@svgr/webpack": "^6.0.0", + "file-loader": "^6.2.0", + "fs-extra": "^10.0.1", + "github-slugger": "^1.4.0", + "globby": "^11.0.4", + "gray-matter": "^4.0.3", "js-yaml": "^4.1.0", - "lodash.isequal": "^4.5.0", - "minimatch": "^3.0.4", - "node-fetch": "^2.6.1", - "yaml-ast-parser": "0.0.43" + "lodash": "^4.17.21", + "micromatch": "^4.0.4", + "resolve-pathname": "^3.0.0", + "shelljs": "^0.8.5", + "tslib": "^2.3.1", + "url-loader": "^4.1.1", + "webpack": "^5.69.1" }, "engines": { - "node": ">=12.0.0" + "node": ">=14" } }, - "node_modules/@redocly/openapi-core/node_modules/@types/node": { - "version": "14.17.25", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.17.25.tgz", - "integrity": "sha512-85DGKK4X9h+JEbs69xggu9j6y/aAExbfZzTrUMSqSwATwYXywbxRLaNQyJ7WibJjsC4OcxJWJwtuANUzDqMc7A==" - }, - "node_modules/@redocly/openapi-core/node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" - }, - "node_modules/@redocly/openapi-core/node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "node_modules/@docusaurus/utils-common": { + "version": "2.0.0-beta.17", + "resolved": "https://registry.npmjs.org/@docusaurus/utils-common/-/utils-common-2.0.0-beta.17.tgz", + "integrity": "sha512-90WCVdj6zYzs7neEIS594qfLO78cUL6EVK1CsRHJgVkkGjcYlCQ1NwkyO7bOb+nIAwdJrPJRc2FBSpuEGxPD3w==", "dependencies": { - "argparse": "^2.0.1" + "tslib": "^2.3.1" }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/@redocly/react-dropdown-aria": { - "version": "2.0.12", - "resolved": "https://registry.npmjs.org/@redocly/react-dropdown-aria/-/react-dropdown-aria-2.0.12.tgz", - "integrity": "sha512-feQEZlyBvQsbT/fvpJ4jJ5OLGaUPpnskHYDsY8DGpPymN+HUeDQrqkBEbbKRwMKidFTI2cxk2kJNNTnvdS9jyw==", - "peerDependencies": { - "react": "^16.8.4 || ^17.0.0", - "react-dom": "^16.8.4 || ^17.0.0", - "styled-components": "^5.1.1" - } - }, - "node_modules/@sideway/address": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.2.tgz", - "integrity": "sha512-idTz8ibqWFrPU8kMirL0CoPH/A29XOzzAzpyN3zQ4kAWnzmNfFmRaoMNN6VI8ske5M73HZyhIaW4OuSFIdM4oA==", - "dependencies": { - "@hapi/hoek": "^9.0.0" - } - }, - "node_modules/@sideway/formula": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.0.tgz", - "integrity": "sha512-vHe7wZ4NOXVfkoRb8T5otiENVlT7a3IAiw7H5M2+GO+9CDgcVUUsX1zalAztCmwyOr2RUTGJdgB+ZvSVqmdHmg==" - }, - "node_modules/@sideway/pinpoint": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@sideway/pinpoint/-/pinpoint-2.0.0.tgz", - "integrity": "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==" - }, - "node_modules/@sindresorhus/is": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", - "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==", "engines": { - "node": ">=6" + "node": ">=14" } }, - "node_modules/@slorber/static-site-generator-webpack-plugin": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@slorber/static-site-generator-webpack-plugin/-/static-site-generator-webpack-plugin-4.0.1.tgz", - "integrity": "sha512-PSv4RIVO1Y3kvHxjvqeVisk3E9XFoO04uwYBDWe217MFqKspplYswTuKLiJu0aLORQWzuQjfVsSlLPojwfYsLw==", + "node_modules/@docusaurus/utils-validation": { + "version": "2.0.0-beta.17", + "resolved": "https://registry.npmjs.org/@docusaurus/utils-validation/-/utils-validation-2.0.0-beta.17.tgz", + "integrity": "sha512-5UjayUP16fDjgd52eSEhL7SlN9x60pIhyS+K7kt7RmpSLy42+4/bSr2pns2VlATmuaoNOO6iIFdB2jgSYJ6SGA==", "dependencies": { - "bluebird": "^3.7.1", - "cheerio": "^0.22.0", - "eval": "^0.1.4", - "url": "^0.11.0", - "webpack-sources": "^1.4.3" - } - }, - "node_modules/@slorber/static-site-generator-webpack-plugin/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "@docusaurus/logger": "2.0.0-beta.17", + "@docusaurus/utils": "2.0.0-beta.17", + "joi": "^17.6.0", + "tslib": "^2.3.1" + }, "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/@slorber/static-site-generator-webpack-plugin/node_modules/webpack-sources": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", - "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", - "dependencies": { - "source-list-map": "^2.0.0", - "source-map": "~0.6.1" + "node": ">=14" } }, - "node_modules/@svgr/babel-plugin-add-jsx-attribute": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-5.4.0.tgz", - "integrity": "sha512-ZFf2gs/8/6B8PnSofI0inYXr2SDNTDScPXhN7k5EqD4aZ3gi6u+rbmZHVB8IM3wDyx8ntKACZbtXSm7oZGRqVg==", + "node_modules/@docusaurus/utils/node_modules/@svgr/babel-plugin-add-jsx-attribute": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-6.0.0.tgz", + "integrity": "sha512-MdPdhdWLtQsjd29Wa4pABdhWbaRMACdM1h31BY+c6FghTZqNGT7pEYdBoaGeKtdTOBC/XNFQaKVj+r/Ei2ryWA==", "engines": { "node": ">=10" }, "funding": { "type": "github", "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@svgr/babel-plugin-remove-jsx-attribute": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-5.4.0.tgz", - "integrity": "sha512-yaS4o2PgUtwLFGTKbsiAy6D0o3ugcUhWK0Z45umJ66EPWunAz9fuFw2gJuje6wqQvQWOTJvIahUwndOXb7QCPg==", + "node_modules/@docusaurus/utils/node_modules/@svgr/babel-plugin-remove-jsx-attribute": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-6.0.0.tgz", + "integrity": "sha512-aVdtfx9jlaaxc3unA6l+M9YRnKIZjOhQPthLKqmTXC8UVkBLDRGwPKo+r8n3VZN8B34+yVajzPTZ+ptTSuZZCw==", "engines": { "node": ">=10" }, "funding": { "type": "github", "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@svgr/babel-plugin-remove-jsx-empty-expression": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-5.0.1.tgz", - "integrity": "sha512-LA72+88A11ND/yFIMzyuLRSMJ+tRKeYKeQ+mR3DcAZ5I4h5CPWN9AHyUzJbWSYp/u2u0xhmgOe0+E41+GjEueA==", + "node_modules/@docusaurus/utils/node_modules/@svgr/babel-plugin-remove-jsx-empty-expression": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-6.0.0.tgz", + "integrity": "sha512-Ccj42ApsePD451AZJJf1QzTD1B/BOU392URJTeXFxSK709i0KUsGtbwyiqsKu7vsYxpTM0IA5clAKDyf9RCZyA==", "engines": { "node": ">=10" }, "funding": { "type": "github", "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@svgr/babel-plugin-replace-jsx-attribute-value": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-5.0.1.tgz", - "integrity": "sha512-PoiE6ZD2Eiy5mK+fjHqwGOS+IXX0wq/YDtNyIgOrc6ejFnxN4b13pRpiIPbtPwHEc+NT2KCjteAcq33/F1Y9KQ==", + "node_modules/@docusaurus/utils/node_modules/@svgr/babel-plugin-replace-jsx-attribute-value": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-6.0.0.tgz", + "integrity": "sha512-88V26WGyt1Sfd1emBYmBJRWMmgarrExpKNVmI9vVozha4kqs6FzQJ/Kp5+EYli1apgX44518/0+t9+NU36lThQ==", "engines": { "node": ">=10" }, "funding": { "type": "github", "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@svgr/babel-plugin-svg-dynamic-title": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-5.4.0.tgz", - "integrity": "sha512-zSOZH8PdZOpuG1ZVx/cLVePB2ibo3WPpqo7gFIjLV9a0QsuQAzJiwwqmuEdTaW2pegyBE17Uu15mOgOcgabQZg==", + "node_modules/@docusaurus/utils/node_modules/@svgr/babel-plugin-svg-dynamic-title": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-6.0.0.tgz", + "integrity": "sha512-F7YXNLfGze+xv0KMQxrl2vkNbI9kzT9oDK55/kUuymh1ACyXkMV+VZWX1zEhSTfEKh7VkHVZGmVtHg8eTZ6PRg==", "engines": { "node": ">=10" }, "funding": { "type": "github", "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@svgr/babel-plugin-svg-em-dimensions": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-5.4.0.tgz", - "integrity": "sha512-cPzDbDA5oT/sPXDCUYoVXEmm3VIoAWAPT6mSPTJNbQaBNUuEKVKyGH93oDY4e42PYHRW67N5alJx/eEol20abw==", + "node_modules/@docusaurus/utils/node_modules/@svgr/babel-plugin-svg-em-dimensions": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-6.0.0.tgz", + "integrity": "sha512-+rghFXxdIqJNLQK08kwPBD3Z22/0b2tEZ9lKiL/yTfuyj1wW8HUXu4bo/XkogATIYuXSghVQOOCwURXzHGKyZA==", "engines": { "node": ">=10" }, "funding": { "type": "github", "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@svgr/babel-plugin-transform-react-native-svg": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-5.4.0.tgz", - "integrity": "sha512-3eYP/SaopZ41GHwXma7Rmxcv9uRslRDTY1estspeB1w1ueZWd/tPlMfEOoccYpEMZU3jD4OU7YitnXcF5hLW2Q==", + "node_modules/@docusaurus/utils/node_modules/@svgr/babel-plugin-transform-react-native-svg": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-6.0.0.tgz", + "integrity": "sha512-VaphyHZ+xIKv5v0K0HCzyfAaLhPGJXSk2HkpYfXIOKb7DjLBv0soHDxNv6X0vr2titsxE7klb++u7iOf7TSrFQ==", "engines": { "node": ">=10" }, "funding": { "type": "github", "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@svgr/babel-plugin-transform-svg-component": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-5.5.0.tgz", - "integrity": "sha512-q4jSH1UUvbrsOtlo/tKcgSeiCHRSBdXoIoqX1pgcKK/aU3JD27wmMKwGtpB8qRYUYoyXvfGxUVKchLuR5pB3rQ==", + "node_modules/@docusaurus/utils/node_modules/@svgr/babel-plugin-transform-svg-component": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-6.2.0.tgz", + "integrity": "sha512-bhYIpsORb++wpsp91fymbFkf09Z/YEKR0DnFjxvN+8JHeCUD2unnh18jIMKnDJTWtvpTaGYPXELVe4OOzFI0xg==", "engines": { - "node": ">=10" + "node": ">=12" }, "funding": { "type": "github", "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@svgr/babel-preset": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-preset/-/babel-preset-5.5.0.tgz", - "integrity": "sha512-4FiXBjvQ+z2j7yASeGPEi8VD/5rrGQk4Xrq3EdJmoZgz/tpqChpo5hgXDvmEauwtvOc52q8ghhZK4Oy7qph4ig==", + "node_modules/@docusaurus/utils/node_modules/@svgr/babel-preset": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-preset/-/babel-preset-6.2.0.tgz", + "integrity": "sha512-4WQNY0J71JIaL03DRn0vLiz87JXx0b9dYm2aA8XHlQJQoixMl4r/soYHm8dsaJZ3jWtkCiOYy48dp9izvXhDkQ==", "dependencies": { - "@svgr/babel-plugin-add-jsx-attribute": "^5.4.0", - "@svgr/babel-plugin-remove-jsx-attribute": "^5.4.0", - "@svgr/babel-plugin-remove-jsx-empty-expression": "^5.0.1", - "@svgr/babel-plugin-replace-jsx-attribute-value": "^5.0.1", - "@svgr/babel-plugin-svg-dynamic-title": "^5.4.0", - "@svgr/babel-plugin-svg-em-dimensions": "^5.4.0", - "@svgr/babel-plugin-transform-react-native-svg": "^5.4.0", - "@svgr/babel-plugin-transform-svg-component": "^5.5.0" + "@svgr/babel-plugin-add-jsx-attribute": "^6.0.0", + "@svgr/babel-plugin-remove-jsx-attribute": "^6.0.0", + "@svgr/babel-plugin-remove-jsx-empty-expression": "^6.0.0", + "@svgr/babel-plugin-replace-jsx-attribute-value": "^6.0.0", + "@svgr/babel-plugin-svg-dynamic-title": "^6.0.0", + "@svgr/babel-plugin-svg-em-dimensions": "^6.0.0", + "@svgr/babel-plugin-transform-react-native-svg": "^6.0.0", + "@svgr/babel-plugin-transform-svg-component": "^6.2.0" }, "engines": { "node": ">=10" @@ -3199,16 +3228,19 @@ "funding": { "type": "github", "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@svgr/core": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@svgr/core/-/core-5.5.0.tgz", - "integrity": "sha512-q52VOcsJPvV3jO1wkPtzTuKlvX7Y3xIcWRpCMtBF3MrteZJtBfQw/+u0B1BHy5ColpQc1/YVTrPEtSYIMNZlrQ==", + "node_modules/@docusaurus/utils/node_modules/@svgr/core": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/@svgr/core/-/core-6.2.1.tgz", + "integrity": "sha512-NWufjGI2WUyrg46mKuySfviEJ6IxHUOm/8a3Ph38VCWSp+83HBraCQrpEM3F3dB6LBs5x8OElS8h3C0oOJaJAA==", "dependencies": { - "@svgr/plugin-jsx": "^5.5.0", + "@svgr/plugin-jsx": "^6.2.1", "camelcase": "^6.2.0", - "cosmiconfig": "^7.0.0" + "cosmiconfig": "^7.0.1" }, "engines": { "node": ">=10" @@ -3218,12 +3250,13 @@ "url": "https://github.com/sponsors/gregberge" } }, - "node_modules/@svgr/hast-util-to-babel-ast": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-5.5.0.tgz", - "integrity": "sha512-cAaR/CAiZRB8GP32N+1jocovUtvlj0+e65TB50/6Lcime+EA49m/8l+P2ko+XPJ4dw3xaPS3jOL4F2X4KWxoeQ==", + "node_modules/@docusaurus/utils/node_modules/@svgr/hast-util-to-babel-ast": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-6.2.1.tgz", + "integrity": "sha512-pt7MMkQFDlWJVy9ULJ1h+hZBDGFfSCwlBNW1HkLnVi7jUhyEXUaGYWi1x6bM2IXuAR9l265khBT4Av4lPmaNLQ==", "dependencies": { - "@babel/types": "^7.12.6" + "@babel/types": "^7.15.6", + "entities": "^3.0.1" }, "engines": { "node": ">=10" @@ -3233,14 +3266,14 @@ "url": "https://github.com/sponsors/gregberge" } }, - "node_modules/@svgr/plugin-jsx": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@svgr/plugin-jsx/-/plugin-jsx-5.5.0.tgz", - "integrity": "sha512-V/wVh33j12hGh05IDg8GpIUXbjAPnTdPTKuP4VNLggnwaHMPNQNae2pRnyTAILWCQdz5GyMqtO488g7CKM8CBA==", + "node_modules/@docusaurus/utils/node_modules/@svgr/plugin-jsx": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/@svgr/plugin-jsx/-/plugin-jsx-6.2.1.tgz", + "integrity": "sha512-u+MpjTsLaKo6r3pHeeSVsh9hmGRag2L7VzApWIaS8imNguqoUwDq/u6U/NDmYs/KAsrmtBjOEaAAPbwNGXXp1g==", "dependencies": { - "@babel/core": "^7.12.3", - "@svgr/babel-preset": "^5.5.0", - "@svgr/hast-util-to-babel-ast": "^5.5.0", + "@babel/core": "^7.15.5", + "@svgr/babel-preset": "^6.2.0", + "@svgr/hast-util-to-babel-ast": "^6.2.1", "svg-parser": "^2.0.2" }, "engines": { @@ -3249,16 +3282,19 @@ "funding": { "type": "github", "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@svgr/core": "^6.0.0" } }, - "node_modules/@svgr/plugin-svgo": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@svgr/plugin-svgo/-/plugin-svgo-5.5.0.tgz", - "integrity": "sha512-r5swKk46GuQl4RrVejVwpeeJaydoxkdwkM1mBKOgJLBUJPGaLci6ylg/IjhrRsREKDkr4kbMWdgOtbXEh0fyLQ==", + "node_modules/@docusaurus/utils/node_modules/@svgr/plugin-svgo": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/@svgr/plugin-svgo/-/plugin-svgo-6.2.0.tgz", + "integrity": "sha512-oDdMQONKOJEbuKwuy4Np6VdV6qoaLLvoY86hjvQEgU82Vx1MSWRyYms6Sl0f+NtqxLI/rDVufATbP/ev996k3Q==", "dependencies": { - "cosmiconfig": "^7.0.0", + "cosmiconfig": "^7.0.1", "deepmerge": "^4.2.2", - "svgo": "^1.2.2" + "svgo": "^2.5.0" }, "engines": { "node": ">=10" @@ -3266,1642 +3302,1859 @@ "funding": { "type": "github", "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@svgr/core": "^6.0.0" } }, - "node_modules/@svgr/plugin-svgo/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "node_modules/@docusaurus/utils/node_modules/@svgr/webpack": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/@svgr/webpack/-/webpack-6.2.1.tgz", + "integrity": "sha512-h09ngMNd13hnePwgXa+Y5CgOjzlCvfWLHg+MBnydEedAnuLRzUHUJmGS3o2OsrhxTOOqEsPOFt5v/f6C5Qulcw==", "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" + "@babel/core": "^7.15.5", + "@babel/plugin-transform-react-constant-elements": "^7.14.5", + "@babel/preset-env": "^7.15.6", + "@babel/preset-react": "^7.14.5", + "@babel/preset-typescript": "^7.15.0", + "@svgr/core": "^6.2.1", + "@svgr/plugin-jsx": "^6.2.1", + "@svgr/plugin-svgo": "^6.2.0" }, "engines": { - "node": ">=4" + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" } }, - "node_modules/@svgr/plugin-svgo/node_modules/css-select": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-2.1.0.tgz", - "integrity": "sha512-Dqk7LQKpwLoH3VovzZnkzegqNSuAziQyNZUcrdDM401iY+R5NkGBXGmtO05/yaXQziALuPogeG0b7UAgjnTJTQ==", - "dependencies": { - "boolbase": "^1.0.0", - "css-what": "^3.2.1", - "domutils": "^1.7.0", - "nth-check": "^1.0.2" + "node_modules/@docusaurus/utils/node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "engines": { + "node": ">= 10" } }, - "node_modules/@svgr/plugin-svgo/node_modules/css-tree": { - "version": "1.0.0-alpha.37", - "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.37.tgz", - "integrity": "sha512-DMxWJg0rnz7UgxKT0Q1HU/L9BeJI0M6ksor0OgqOnF+aRCDWg/N2641HmVyU9KVIu0OVVWOb2IpC9A+BJRnejg==", + "node_modules/@docusaurus/utils/node_modules/css-tree": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz", + "integrity": "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==", "dependencies": { - "mdn-data": "2.0.4", + "mdn-data": "2.0.14", "source-map": "^0.6.1" }, "engines": { "node": ">=8.0.0" } }, - "node_modules/@svgr/plugin-svgo/node_modules/css-what": { - "version": "3.4.2", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-3.4.2.tgz", - "integrity": "sha512-ACUm3L0/jiZTqfzRM3Hi9Q8eZqd6IK37mMWPLz9PJxkLWllYeRf+EHUSHYEtFop2Eqytaq1FizFVh7XfBnXCDQ==", + "node_modules/@docusaurus/utils/node_modules/entities": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-3.0.1.tgz", + "integrity": "sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q==", "engines": { - "node": ">= 6" + "node": ">=0.12" }, "funding": { - "url": "https://github.com/sponsors/fb55" + "url": "https://github.com/fb55/entities?sponsor=1" } }, - "node_modules/@svgr/plugin-svgo/node_modules/dom-serializer": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz", - "integrity": "sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==", + "node_modules/@docusaurus/utils/node_modules/mdn-data": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz", + "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==" + }, + "node_modules/@docusaurus/utils/node_modules/svgo": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-2.8.0.tgz", + "integrity": "sha512-+N/Q9kV1+F+UeWYoSiULYo4xYSDQlTgb+ayMobAXPwMnLvop7oxKMo9OzIrX5x3eS4L4f2UHhc9axXwY8DpChg==", "dependencies": { - "domelementtype": "^2.0.1", - "entities": "^2.0.0" + "@trysound/sax": "0.2.0", + "commander": "^7.2.0", + "css-select": "^4.1.3", + "css-tree": "^1.1.3", + "csso": "^4.2.0", + "picocolors": "^1.0.0", + "stable": "^0.1.8" + }, + "bin": { + "svgo": "bin/svgo" + }, + "engines": { + "node": ">=10.13.0" } }, - "node_modules/@svgr/plugin-svgo/node_modules/dom-serializer/node_modules/domelementtype": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz", - "integrity": "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ] - }, - "node_modules/@svgr/plugin-svgo/node_modules/domelementtype": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", - "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==" - }, - "node_modules/@svgr/plugin-svgo/node_modules/domutils": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz", - "integrity": "sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==", + "node_modules/@emotion/is-prop-valid": { + "version": "0.8.8", + "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-0.8.8.tgz", + "integrity": "sha512-u5WtneEAr5IDG2Wv65yhunPSMLIpuKsbuOktRojfrEiEvRyC85LgPMZI63cr7NUqT8ZIGdSVg8ZKGxIug4lXcA==", "dependencies": { - "dom-serializer": "0", - "domelementtype": "1" + "@emotion/memoize": "0.7.4" } }, - "node_modules/@svgr/plugin-svgo/node_modules/mdn-data": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.4.tgz", - "integrity": "sha512-iV3XNKw06j5Q7mi6h+9vbx23Tv7JkjEVgKHW4pimwyDGWm0OIQntJJ+u1C6mg6mK1EaTv42XQ7w76yuzH7M2cA==" + "node_modules/@emotion/memoize": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.7.4.tgz", + "integrity": "sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw==" }, - "node_modules/@svgr/plugin-svgo/node_modules/nth-check": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz", - "integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==", - "dependencies": { - "boolbase": "~1.0.0" - } + "node_modules/@emotion/stylis": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/@emotion/stylis/-/stylis-0.8.5.tgz", + "integrity": "sha512-h6KtPihKFn3T9fuIrwvXXUOwlx3rfUvfZIcP5a6rh8Y7zjE3O06hT5Ss4S/YI1AYhuZ1kjaE/5EaOOI2NqSylQ==" }, - "node_modules/@svgr/plugin-svgo/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "node_modules/@emotion/unitless": { + "version": "0.7.5", + "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.7.5.tgz", + "integrity": "sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg==" + }, + "node_modules/@endiliey/react-ideal-image": { + "version": "0.0.11", + "resolved": "https://registry.npmjs.org/@endiliey/react-ideal-image/-/react-ideal-image-0.0.11.tgz", + "integrity": "sha512-QxMjt/Gvur/gLxSoCy7VIyGGGrGmDN+VHcXkN3R2ApoWX0EYUE+hMgPHSW/PV6VVebZ1Nd4t2UnGRBDihu16JQ==", "engines": { - "node": ">=0.10.0" + "node": ">= 8.9.0", + "npm": "> 3" + }, + "peerDependencies": { + "prop-types": ">=15", + "react": ">=0.14.x", + "react-waypoint": ">=9.0.2" } }, - "node_modules/@svgr/plugin-svgo/node_modules/svgo": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/svgo/-/svgo-1.3.2.tgz", - "integrity": "sha512-yhy/sQYxR5BkC98CY7o31VGsg014AKLEPxdfhora76l36hD9Rdy5NZA/Ocn6yayNPgSamYdtX2rFJdcv07AYVw==", - "deprecated": "This SVGO version is no longer supported. Upgrade to v2.x.x.", + "node_modules/@exodus/schemasafe": { + "version": "1.0.0-rc.6", + "resolved": "https://registry.npmjs.org/@exodus/schemasafe/-/schemasafe-1.0.0-rc.6.tgz", + "integrity": "sha512-dDnQizD94EdBwEj/fh3zPRa/HWCS9O5au2PuHhZBbuM3xWHxuaKzPBOEWze7Nn0xW68MIpZ7Xdyn1CoCpjKCuQ==" + }, + "node_modules/@hapi/hoek": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz", + "integrity": "sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==" + }, + "node_modules/@hapi/topo": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-5.1.0.tgz", + "integrity": "sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==", "dependencies": { - "chalk": "^2.4.1", - "coa": "^2.0.2", - "css-select": "^2.0.0", - "css-select-base-adapter": "^0.1.1", - "css-tree": "1.0.0-alpha.37", - "csso": "^4.0.2", + "@hapi/hoek": "^9.0.0" + } + }, + "node_modules/@istanbuljs/load-nyc-config": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", + "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", + "dev": true, + "dependencies": { + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "get-package-type": "^0.1.0", "js-yaml": "^3.13.1", - "mkdirp": "~0.5.1", - "object.values": "^1.1.0", - "sax": "~1.2.4", - "stable": "^0.1.8", - "unquote": "~1.1.1", - "util.promisify": "~1.0.0" - }, - "bin": { - "svgo": "bin/svgo" + "resolve-from": "^5.0.0" }, "engines": { - "node": ">=4.0.0" + "node": ">=8" } }, - "node_modules/@svgr/webpack": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@svgr/webpack/-/webpack-5.5.0.tgz", - "integrity": "sha512-DOBOK255wfQxguUta2INKkzPj6AIS6iafZYiYmHn6W3pHlycSRRlvWKCfLDG10fXfLWqE3DJHgRUOyJYmARa7g==", + "node_modules/@istanbuljs/load-nyc-config/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, "dependencies": { - "@babel/core": "^7.12.3", - "@babel/plugin-transform-react-constant-elements": "^7.12.1", - "@babel/preset-env": "^7.12.1", - "@babel/preset-react": "^7.12.5", - "@svgr/core": "^5.5.0", - "@svgr/plugin-jsx": "^5.5.0", - "@svgr/plugin-svgo": "^5.5.0", - "loader-utils": "^2.0.0" - }, + "sprintf-js": "~1.0.2" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true, "engines": { - "node": ">=10" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" + "node": ">=6" } }, - "node_modules/@szmarczak/http-timer": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz", - "integrity": "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==", + "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, "dependencies": { - "defer-to-connect": "^1.0.1" + "argparse": "^1.0.7", + "esprima": "^4.0.0" }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, "engines": { - "node": ">=6" + "node": ">=8" } }, - "node_modules/@trysound/sax": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", - "integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==", + "node_modules/@istanbuljs/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "dev": true, "engines": { - "node": ">=10.13.0" + "node": ">=8" } }, - "node_modules/@types/eslint": { - "version": "7.28.1", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-7.28.1.tgz", - "integrity": "sha512-XhZKznR3i/W5dXqUhgU9fFdJekufbeBd5DALmkuXoeFcjbQcPk+2cL+WLHf6Q81HWAnM2vrslIHpGVyCAviRwg==", + "node_modules/@jest/console": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-27.5.1.tgz", + "integrity": "sha512-kZ/tNpS3NXn0mlXXXPNuDZnb4c0oZ20r4K5eemM2k30ZC3G0T02nXUvyhf5YdbXWHPEJLc9qGLxEZ216MdL+Zg==", + "dev": true, "dependencies": { - "@types/estree": "*", - "@types/json-schema": "*" + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "jest-message-util": "^27.5.1", + "jest-util": "^27.5.1", + "slash": "^3.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "node_modules/@types/eslint-scope": { - "version": "3.7.1", - "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.1.tgz", - "integrity": "sha512-SCFeogqiptms4Fg29WpOTk5nHIzfpKCemSN63ksBQYKTcXoJEmJagV+DhVmbapZzY4/5YaOV1nZwrsU79fFm1g==", + "node_modules/@jest/console/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, "dependencies": { - "@types/eslint": "*", - "@types/estree": "*" + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/@types/estree": { - "version": "0.0.50", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.50.tgz", - "integrity": "sha512-C6N5s2ZFtuZRj54k2/zyRhNDjJwwcViAM3Nbm8zjBpbqAdZ00mr0CFxvSKeO8Y/e03WVFLpQMdHYVfUd6SB+Hw==" - }, - "node_modules/@types/github-slugger": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@types/github-slugger/-/github-slugger-1.3.0.tgz", - "integrity": "sha512-J/rMZa7RqiH/rT29TEVZO4nBoDP9XJOjnbbIofg7GQKs4JIduEO3WLpte+6WeUz/TcrXKlY+bM7FYrp8yFB+3g==" - }, - "node_modules/@types/glob": { - "version": "7.1.4", - "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.4.tgz", - "integrity": "sha512-w+LsMxKyYQm347Otw+IfBXOv9UWVjpHpCDdbBMt8Kz/xbvCYNjP+0qPh91Km3iKfSRLBB0P7fAMf0KHrPu+MyA==", + "node_modules/@jest/console/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "dependencies": { - "@types/minimatch": "*", - "@types/node": "*" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/@types/hast": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/@types/hast/-/hast-2.3.4.tgz", - "integrity": "sha512-wLEm0QvaoawEDoTRwzTXp4b4jpwiJDvR5KMnFnVodm3scufTlBOWRD6N1OBf9TZMhjlNsSfcO5V+7AF4+Vy+9g==", - "dependencies": { - "@types/unist": "*" - } - }, - "node_modules/@types/html-minifier-terser": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-5.1.2.tgz", - "integrity": "sha512-h4lTMgMJctJybDp8CQrxTUiiYmedihHWkjnF/8Pxseu2S6Nlfcy8kwboQ8yejh456rP2yWoEVm1sS/FVsfM48w==" - }, - "node_modules/@types/json-schema": { - "version": "7.0.9", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.9.tgz", - "integrity": "sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==" - }, - "node_modules/@types/lodash": { - "version": "4.14.175", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.175.tgz", - "integrity": "sha512-XmdEOrKQ8a1Y/yxQFOMbC47G/V2VDO1GvMRnl4O75M4GW/abC5tnfzadQYkqEveqRM1dEJGFFegfPNA2vvx2iw==" - }, - "node_modules/@types/mdast": { - "version": "3.0.10", - "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.10.tgz", - "integrity": "sha512-W864tg/Osz1+9f4lrGTZpCSO5/z4608eUp19tbozkq2HJK6i3z1kT0H9tlADXuYIb1YYOBByU4Jsqkk75q48qA==", + "node_modules/@jest/console/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, "dependencies": { - "@types/unist": "*" + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" } }, - "node_modules/@types/minimatch": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.5.tgz", - "integrity": "sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==" - }, - "node_modules/@types/node": { - "version": "16.10.8", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.10.8.tgz", - "integrity": "sha512-atlRPM4gM/BABQ2MiXm38veMVL+kz6vFAj1hvqC1wDxWNrnr3t58PozLSecgLBrKNGISunQl2SxxIJcYV3tO2w==" + "node_modules/@jest/console/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true }, - "node_modules/@types/parse-json": { + "node_modules/@jest/console/node_modules/has-flag": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==" - }, - "node_modules/@types/parse5": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/@types/parse5/-/parse5-5.0.3.tgz", - "integrity": "sha512-kUNnecmtkunAoQ3CnjmMkzNU/gtxG8guhi+Fk2U/kOpIKjIMKnXGp4IJCgQJrXSgMsWYimYG4TGjz/UzbGEBTw==" - }, - "node_modules/@types/q": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/@types/q/-/q-1.5.5.tgz", - "integrity": "sha512-L28j2FcJfSZOnL1WBjDYp2vUHCeIFlyYI/53EwD/rKUBQ7MtUUfbQWiyKJGpcnv4/WgrhWsFKrcPstcAt/J0tQ==" - }, - "node_modules/@types/sax": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@types/sax/-/sax-1.2.3.tgz", - "integrity": "sha512-+QSw6Tqvs/KQpZX8DvIl3hZSjNFLW/OqE5nlyHXtTwODaJvioN2rOWpBNEWZp2HZUFhOh+VohmJku/WxEXU2XA==", - "dependencies": { - "@types/node": "*" + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" } }, - "node_modules/@types/unist": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.6.tgz", - "integrity": "sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ==" - }, - "node_modules/@webassemblyjs/ast": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.1.tgz", - "integrity": "sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw==", + "node_modules/@jest/console/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, "dependencies": { - "@webassemblyjs/helper-numbers": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1" + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" } }, - "node_modules/@webassemblyjs/floating-point-hex-parser": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz", - "integrity": "sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ==" - }, - "node_modules/@webassemblyjs/helper-api-error": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz", - "integrity": "sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg==" - }, - "node_modules/@webassemblyjs/helper-buffer": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz", - "integrity": "sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA==" - }, - "node_modules/@webassemblyjs/helper-numbers": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz", - "integrity": "sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ==", + "node_modules/@jest/core": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-27.5.1.tgz", + "integrity": "sha512-AK6/UTrvQD0Cd24NSqmIA6rKsu0tKIxfiCducZvqxYdmMisOYAsdItspT+fQDQYARPf8XgjAFZi0ogW2agH5nQ==", + "dev": true, "dependencies": { - "@webassemblyjs/floating-point-hex-parser": "1.11.1", - "@webassemblyjs/helper-api-error": "1.11.1", - "@xtuc/long": "4.2.2" + "@jest/console": "^27.5.1", + "@jest/reporters": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "emittery": "^0.8.1", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-changed-files": "^27.5.1", + "jest-config": "^27.5.1", + "jest-haste-map": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-regex-util": "^27.5.1", + "jest-resolve": "^27.5.1", + "jest-resolve-dependencies": "^27.5.1", + "jest-runner": "^27.5.1", + "jest-runtime": "^27.5.1", + "jest-snapshot": "^27.5.1", + "jest-util": "^27.5.1", + "jest-validate": "^27.5.1", + "jest-watcher": "^27.5.1", + "micromatch": "^4.0.4", + "rimraf": "^3.0.0", + "slash": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } } }, - "node_modules/@webassemblyjs/helper-wasm-bytecode": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz", - "integrity": "sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q==" - }, - "node_modules/@webassemblyjs/helper-wasm-section": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz", - "integrity": "sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg==", + "node_modules/@jest/core/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, "dependencies": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-buffer": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/wasm-gen": "1.11.1" + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/@webassemblyjs/ieee754": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz", - "integrity": "sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ==", + "node_modules/@jest/core/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "dependencies": { - "@xtuc/ieee754": "^1.2.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/@webassemblyjs/leb128": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.1.tgz", - "integrity": "sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw==", + "node_modules/@jest/core/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, "dependencies": { - "@xtuc/long": "4.2.2" + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" } }, - "node_modules/@webassemblyjs/utf8": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.1.tgz", - "integrity": "sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ==" + "node_modules/@jest/core/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true }, - "node_modules/@webassemblyjs/wasm-edit": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz", - "integrity": "sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA==", - "dependencies": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-buffer": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/helper-wasm-section": "1.11.1", - "@webassemblyjs/wasm-gen": "1.11.1", - "@webassemblyjs/wasm-opt": "1.11.1", - "@webassemblyjs/wasm-parser": "1.11.1", - "@webassemblyjs/wast-printer": "1.11.1" + "node_modules/@jest/core/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" } }, - "node_modules/@webassemblyjs/wasm-gen": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz", - "integrity": "sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA==", + "node_modules/@jest/core/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, "dependencies": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/ieee754": "1.11.1", - "@webassemblyjs/leb128": "1.11.1", - "@webassemblyjs/utf8": "1.11.1" + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" } }, - "node_modules/@webassemblyjs/wasm-opt": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz", - "integrity": "sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw==", + "node_modules/@jest/create-cache-key-function": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/create-cache-key-function/-/create-cache-key-function-27.5.1.tgz", + "integrity": "sha512-dmH1yW+makpTSURTy8VzdUwFnfQh1G8R+DxO2Ho2FFmBbKFEVm+3jWdvFhE2VqB/LATCTokkP0dotjyQyw5/AQ==", + "dev": true, "dependencies": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-buffer": "1.11.1", - "@webassemblyjs/wasm-gen": "1.11.1", - "@webassemblyjs/wasm-parser": "1.11.1" + "@jest/types": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "node_modules/@webassemblyjs/wasm-parser": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz", - "integrity": "sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA==", + "node_modules/@jest/environment": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-27.5.1.tgz", + "integrity": "sha512-/WQjhPJe3/ghaol/4Bq480JKXV/Rfw8nQdN7f41fM8VDHLcxKXou6QyXAh3EFr9/bVG3x74z1NWDkP87EiY8gA==", + "dev": true, "dependencies": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-api-error": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/ieee754": "1.11.1", - "@webassemblyjs/leb128": "1.11.1", - "@webassemblyjs/utf8": "1.11.1" + "@jest/fake-timers": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "jest-mock": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "node_modules/@webassemblyjs/wast-printer": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz", - "integrity": "sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg==", + "node_modules/@jest/fake-timers": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-27.5.1.tgz", + "integrity": "sha512-/aPowoolwa07k7/oM3aASneNeBGCmGQsc3ugN4u6s4C/+s5M64MFo/+djTdiwcbQlRfFElGuDXWzaWj6QgKObQ==", + "dev": true, "dependencies": { - "@webassemblyjs/ast": "1.11.1", - "@xtuc/long": "4.2.2" + "@jest/types": "^27.5.1", + "@sinonjs/fake-timers": "^8.0.1", + "@types/node": "*", + "jest-message-util": "^27.5.1", + "jest-mock": "^27.5.1", + "jest-util": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "node_modules/@xtuc/ieee754": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", - "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==" - }, - "node_modules/@xtuc/long": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", - "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==" - }, - "node_modules/accepts": { - "version": "1.3.7", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", - "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", + "node_modules/@jest/globals": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-27.5.1.tgz", + "integrity": "sha512-ZEJNB41OBQQgGzgyInAv0UUfDDj3upmHydjieSxFvTRuZElrx7tXg/uVQ5hYVEwiXs3+aMsAeEc9X7xiSKCm4Q==", + "dev": true, "dependencies": { - "mime-types": "~2.1.24", - "negotiator": "0.6.2" + "@jest/environment": "^27.5.1", + "@jest/types": "^27.5.1", + "expect": "^27.5.1" }, "engines": { - "node": ">= 0.6" + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "node_modules/acorn": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.5.0.tgz", - "integrity": "sha512-yXbYeFy+jUuYd3/CDcg2NkIYE991XYX/bje7LmjJigUciaeO1JR4XxXgCIV1/Zc/dRuFEyw1L0pbA+qynJkW5Q==", - "bin": { - "acorn": "bin/acorn" + "node_modules/@jest/reporters": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-27.5.1.tgz", + "integrity": "sha512-cPXh9hWIlVJMQkVk84aIvXuBB4uQQmFqZiacloFuGiP3ah1sbCxCosidXFDfqG8+6fO1oR2dTJTlsOy4VFmUfw==", + "dev": true, + "dependencies": { + "@bcoe/v8-coverage": "^0.2.3", + "@jest/console": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "collect-v8-coverage": "^1.0.0", + "exit": "^0.1.2", + "glob": "^7.1.2", + "graceful-fs": "^4.2.9", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-instrument": "^5.1.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.0", + "istanbul-reports": "^3.1.3", + "jest-haste-map": "^27.5.1", + "jest-resolve": "^27.5.1", + "jest-util": "^27.5.1", + "jest-worker": "^27.5.1", + "slash": "^3.0.0", + "source-map": "^0.6.0", + "string-length": "^4.0.1", + "terminal-link": "^2.0.0", + "v8-to-istanbul": "^8.1.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-import-assertions": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz", - "integrity": "sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==", "peerDependencies": { - "acorn": "^8" - } - }, - "node_modules/acorn-walk": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", - "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/address": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/address/-/address-1.1.2.tgz", - "integrity": "sha512-aT6camzM4xEA54YVJYSqxz1kv4IHnQZRtThJJHhUMRExaU5spC7jX5ugSwTaTgJliIgs4VhZOk7htClvQ/LmRA==", - "engines": { - "node": ">= 0.12.0" + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } } }, - "node_modules/aggregate-error": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", - "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "node_modules/@jest/reporters/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, "dependencies": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" + "color-convert": "^2.0.1" }, "engines": { "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "node_modules/@jest/reporters/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/ajv-errors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-1.0.1.tgz", - "integrity": "sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ==", - "peerDependencies": { - "ajv": ">=5.0.0" + "node_modules/@jest/reporters/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" } }, - "node_modules/ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "peerDependencies": { - "ajv": "^6.9.1" - } + "node_modules/@jest/reporters/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true }, - "node_modules/algoliasearch": { - "version": "4.10.5", - "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-4.10.5.tgz", - "integrity": "sha512-KmH2XkiN+8FxhND4nWFbQDkIoU6g2OjfeU9kIv4Lb+EiOOs3Gpp7jvd+JnatsCisAZsnWQdjd7zVlW7I/85QvQ==", - "dependencies": { - "@algolia/cache-browser-local-storage": "4.10.5", - "@algolia/cache-common": "4.10.5", - "@algolia/cache-in-memory": "4.10.5", - "@algolia/client-account": "4.10.5", - "@algolia/client-analytics": "4.10.5", - "@algolia/client-common": "4.10.5", - "@algolia/client-personalization": "4.10.5", - "@algolia/client-search": "4.10.5", - "@algolia/logger-common": "4.10.5", - "@algolia/logger-console": "4.10.5", - "@algolia/requester-browser-xhr": "4.10.5", - "@algolia/requester-common": "4.10.5", - "@algolia/requester-node-http": "4.10.5", - "@algolia/transporter": "4.10.5" + "node_modules/@jest/reporters/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" } }, - "node_modules/algoliasearch-helper": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/algoliasearch-helper/-/algoliasearch-helper-3.6.0.tgz", - "integrity": "sha512-F4Smiq+Vyv/JJytuKNFuzXndPSb4pjtiHZSkEztQCcB+SORu71A8grgt2NSJhbB5VhqHW19QDtlPKbdYdcNrLg==", + "node_modules/@jest/reporters/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, "dependencies": { - "events": "^1.1.1" + "has-flag": "^4.0.0" }, - "peerDependencies": { - "algoliasearch": ">= 3.1 < 5" + "engines": { + "node": ">=8" } }, - "node_modules/algoliasearch-helper/node_modules/events": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", - "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=", + "node_modules/@jest/source-map": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-27.5.1.tgz", + "integrity": "sha512-y9NIHUYF3PJRlHk98NdC/N1gl88BL08aQQgu4k4ZopQkCw9t9cV8mtl3TV8b/YCB8XaVTFrmUTAJvjsntDireg==", + "dev": true, + "dependencies": { + "callsites": "^3.0.0", + "graceful-fs": "^4.2.9", + "source-map": "^0.6.0" + }, "engines": { - "node": ">=0.4.x" + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "node_modules/alphanum-sort": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/alphanum-sort/-/alphanum-sort-1.0.2.tgz", - "integrity": "sha1-l6ERlkmyEa0zaR2fn0hqjsn74KM=" + "node_modules/@jest/test-result": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-27.5.1.tgz", + "integrity": "sha512-EW35l2RYFUcUQxFJz5Cv5MTOxlJIQs4I7gxzi2zVU7PJhOwfYq1MdC5nhSmYjX1gmMmLPvB3sIaC+BkcHRBfag==", + "dev": true, + "dependencies": { + "@jest/console": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } }, - "node_modules/ansi-align": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", - "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", + "node_modules/@jest/test-sequencer": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-27.5.1.tgz", + "integrity": "sha512-LCheJF7WB2+9JuCS7VB/EmGIdQuhtqjRNI9A43idHv3E4KltCTsPsLxvdaubFHSYwY/fNjMWjl6vNRhDiN7vpQ==", + "dev": true, "dependencies": { - "string-width": "^4.1.0" + "@jest/test-result": "^27.5.1", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^27.5.1", + "jest-runtime": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "node_modules/ansi-colors": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.4.tgz", - "integrity": "sha512-hHUXGagefjN2iRrID63xckIvotOXOojhQKWIPUZ4mNUZ9nLZW+7FMNoE1lOkEhNWYsx/7ysGIuJYCiMAA9FnrA==", + "node_modules/@jest/transform": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-27.5.1.tgz", + "integrity": "sha512-ipON6WtYgl/1329g5AIJVbUuEh0wZVbdpGwC99Jw4LwuoBNS95MVphU6zOeD9pDkon+LLbFL7lOQRapbB8SCHw==", + "dev": true, + "dependencies": { + "@babel/core": "^7.1.0", + "@jest/types": "^27.5.1", + "babel-plugin-istanbul": "^6.1.1", + "chalk": "^4.0.0", + "convert-source-map": "^1.4.0", + "fast-json-stable-stringify": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^27.5.1", + "jest-regex-util": "^27.5.1", + "jest-util": "^27.5.1", + "micromatch": "^4.0.4", + "pirates": "^4.0.4", + "slash": "^3.0.0", + "source-map": "^0.6.1", + "write-file-atomic": "^3.0.0" + }, "engines": { - "node": ">=6" + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "node_modules/ansi-escapes": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", - "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "node_modules/@jest/transform/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, "dependencies": { - "type-fest": "^0.21.3" + "color-convert": "^2.0.1" }, "engines": { "node": ">=8" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/ansi-escapes/node_modules/type-fest": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", - "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "node_modules/@jest/transform/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, "engines": { "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/ansi-html": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/ansi-html/-/ansi-html-0.0.7.tgz", - "integrity": "sha1-gTWEAhliqenm/QOflA0S9WynhZ4=", - "engines": [ - "node >= 0.8.0" - ], - "bin": { - "ansi-html": "bin/ansi-html" + "node_modules/@jest/transform/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" } }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "node_modules/@jest/transform/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/@jest/transform/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, "engines": { "node": ">=8" } }, - "node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "node_modules/@jest/transform/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, "dependencies": { - "color-convert": "^1.9.0" + "has-flag": "^4.0.0" }, "engines": { - "node": ">=4" + "node": ">=8" } }, - "node_modules/any-base": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/any-base/-/any-base-1.1.0.tgz", - "integrity": "sha512-uMgjozySS8adZZYePpaWs8cxB9/kdzmpX6SgJZ+wbz1K5eYk5QMYDVJaZKhxyIHUdnnJkfR7SVgStgH7LkGUyg==" - }, - "node_modules/anymatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", - "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", + "node_modules/@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "dev": true, "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" }, "engines": { - "node": ">= 8" + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "node_modules/aproba": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", - "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" - }, - "node_modules/are-we-there-yet": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz", - "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==", + "node_modules/@jest/types/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, "dependencies": { - "delegates": "^1.0.0", - "readable-stream": "^2.0.6" + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/are-we-there-yet/node_modules/readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "node_modules/@jest/types/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "dependencies": { - "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" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/are-we-there-yet/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/arg": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.1.tgz", - "integrity": "sha512-e0hDa9H2Z9AwFkk2qDlwhoMYE4eToKarchkQHovNdLTCYMHZHeRjI71crOh+dio4K6u1IcwubQqo79Ga4CyAQA==" - }, - "node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "node_modules/@jest/types/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, "dependencies": { - "sprintf-js": "~1.0.2" - } - }, - "node_modules/arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/arr-flatten": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", - "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/arr-union": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", - "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", + "color-name": "~1.1.4" + }, "engines": { - "node": ">=0.10.0" + "node": ">=7.0.0" } }, - "node_modules/array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" + "node_modules/@jest/types/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true }, - "node_modules/array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "node_modules/@jest/types/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, "engines": { "node": ">=8" } }, - "node_modules/array-uniq": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", - "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "node_modules/@jest/types/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, - "node_modules/asap": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", - "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=" - }, - "node_modules/asn1.js": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", - "integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==", + "node_modules/@jimp/bmp": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/@jimp/bmp/-/bmp-0.16.1.tgz", + "integrity": "sha512-iwyNYQeBawrdg/f24x3pQ5rEx+/GwjZcCXd3Kgc+ZUd+Ivia7sIqBsOnDaMZdKCBPlfW364ekexnlOqyVa0NWg==", "dependencies": { - "bn.js": "^4.0.0", - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0", - "safer-buffer": "^2.1.0" + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.1", + "bmp-js": "^0.1.0" + }, + "peerDependencies": { + "@jimp/custom": ">=0.3.5" } }, - "node_modules/asn1.js/node_modules/bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" - }, - "node_modules/assert": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/assert/-/assert-2.0.0.tgz", - "integrity": "sha512-se5Cd+js9dXJnu6Ag2JFc00t+HmHOen+8Q+L7O9zI0PqQXr20uk2J0XQqMxZEeo5U50o8Nvmmx7dZrl+Ufr35A==", + "node_modules/@jimp/core": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/@jimp/core/-/core-0.16.1.tgz", + "integrity": "sha512-la7kQia31V6kQ4q1kI/uLimu8FXx7imWVajDGtwUG8fzePLWDFJyZl0fdIXVCL1JW2nBcRHidUot6jvlRDi2+g==", "dependencies": { - "es6-object-assign": "^1.1.0", - "is-nan": "^1.2.1", - "object-is": "^1.0.1", - "util": "^0.12.0" - } - }, - "node_modules/assign-symbols": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", - "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", - "engines": { - "node": ">=0.10.0" + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.1", + "any-base": "^1.1.0", + "buffer": "^5.2.0", + "exif-parser": "^0.1.12", + "file-type": "^9.0.0", + "load-bmfont": "^1.3.1", + "mkdirp": "^0.5.1", + "phin": "^2.9.1", + "pixelmatch": "^4.0.2", + "tinycolor2": "^1.4.1" } }, - "node_modules/async": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", - "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", + "node_modules/@jimp/core/node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], "dependencies": { - "lodash": "^4.17.14" + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" } }, - "node_modules/async-each": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz", - "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==" - }, - "node_modules/async-limiter": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", - "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==" - }, - "node_modules/at-least-node": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", - "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", - "engines": { - "node": ">= 4.0.0" + "node_modules/@jimp/custom": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/@jimp/custom/-/custom-0.16.1.tgz", + "integrity": "sha512-DNUAHNSiUI/j9hmbatD6WN/EBIyeq4AO0frl5ETtt51VN1SvE4t4v83ZA/V6ikxEf3hxLju4tQ5Pc3zmZkN/3A==", + "dependencies": { + "@babel/runtime": "^7.7.2", + "@jimp/core": "^0.16.1" } }, - "node_modules/atob": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", - "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", - "bin": { - "atob": "bin/atob.js" + "node_modules/@jimp/gif": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/@jimp/gif/-/gif-0.16.1.tgz", + "integrity": "sha512-r/1+GzIW1D5zrP4tNrfW+3y4vqD935WBXSc8X/wm23QTY9aJO9Lw6PEdzpYCEY+SOklIFKaJYUAq/Nvgm/9ryw==", + "dependencies": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.1", + "gifwrap": "^0.9.2", + "omggif": "^1.0.9" }, - "engines": { - "node": ">= 4.5.0" + "peerDependencies": { + "@jimp/custom": ">=0.3.5" } }, - "node_modules/autoprefixer": { - "version": "10.3.7", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.3.7.tgz", - "integrity": "sha512-EmGpu0nnQVmMhX8ROoJ7Mx8mKYPlcUHuxkwrRYEYMz85lu7H09v8w6R1P0JPdn/hKU32GjpLBFEOuIlDWCRWvg==", + "node_modules/@jimp/jpeg": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/@jimp/jpeg/-/jpeg-0.16.1.tgz", + "integrity": "sha512-8352zrdlCCLFdZ/J+JjBslDvml+fS3Z8gttdml0We759PnnZGqrnPRhkOEOJbNUlE+dD4ckLeIe6NPxlS/7U+w==", "dependencies": { - "browserslist": "^4.17.3", - "caniuse-lite": "^1.0.30001264", - "fraction.js": "^4.1.1", - "normalize-range": "^0.1.2", - "picocolors": "^0.2.1", - "postcss-value-parser": "^4.1.0" - }, - "bin": { - "autoprefixer": "bin/autoprefixer" - }, - "engines": { - "node": "^10 || ^12 || >=14" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.1", + "jpeg-js": "0.4.2" }, "peerDependencies": { - "postcss": "^8.1.0" + "@jimp/custom": ">=0.3.5" } }, - "node_modules/autoprefixer/node_modules/picocolors": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", - "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" - }, - "node_modules/available-typed-arrays": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", - "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", - "engines": { - "node": ">= 0.4" + "node_modules/@jimp/plugin-resize": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/@jimp/plugin-resize/-/plugin-resize-0.16.1.tgz", + "integrity": "sha512-u4JBLdRI7dargC04p2Ha24kofQBk3vhaf0q8FwSYgnCRwxfvh2RxvhJZk9H7Q91JZp6wgjz/SjvEAYjGCEgAwQ==", + "dependencies": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.1" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "peerDependencies": { + "@jimp/custom": ">=0.3.5" } }, - "node_modules/axios": { - "version": "0.21.4", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz", - "integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==", + "node_modules/@jimp/png": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/@jimp/png/-/png-0.16.1.tgz", + "integrity": "sha512-iyWoCxEBTW0OUWWn6SveD4LePW89kO7ZOy5sCfYeDM/oTPLpR8iMIGvZpZUz1b8kvzFr27vPst4E5rJhGjwsdw==", "dependencies": { - "follow-redirects": "^1.14.0" + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.1", + "pngjs": "^3.3.3" + }, + "peerDependencies": { + "@jimp/custom": ">=0.3.5" } }, - "node_modules/babel-loader": { - "version": "8.2.2", - "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.2.2.tgz", - "integrity": "sha512-JvTd0/D889PQBtUXJ2PXaKU/pjZDMtHA9V2ecm+eNRmmBCMR09a+fmpGTNwnJtFmFl5Ei7Vy47LjBb+L0wQ99g==", + "node_modules/@jimp/tiff": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/@jimp/tiff/-/tiff-0.16.1.tgz", + "integrity": "sha512-3K3+xpJS79RmSkAvFMgqY5dhSB+/sxhwTFA9f4AVHUK0oKW+u6r52Z1L0tMXHnpbAdR9EJ+xaAl2D4x19XShkQ==", "dependencies": { - "find-cache-dir": "^3.3.1", - "loader-utils": "^1.4.0", - "make-dir": "^3.1.0", - "schema-utils": "^2.6.5" - }, - "engines": { - "node": ">= 8.9" + "@babel/runtime": "^7.7.2", + "utif": "^2.0.1" }, "peerDependencies": { - "@babel/core": "^7.0.0", - "webpack": ">=2" + "@jimp/custom": ">=0.3.5" } }, - "node_modules/babel-loader/node_modules/json5": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", - "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", - "dependencies": { - "minimist": "^1.2.0" - }, - "bin": { - "json5": "lib/cli.js" + "node_modules/@jimp/types": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/@jimp/types/-/types-0.16.1.tgz", + "integrity": "sha512-g1w/+NfWqiVW4CaXSJyD28JQqZtm2eyKMWPhBBDCJN9nLCN12/Az0WFF3JUAktzdsEC2KRN2AqB1a2oMZBNgSQ==", + "dependencies": { + "@babel/runtime": "^7.7.2", + "@jimp/bmp": "^0.16.1", + "@jimp/gif": "^0.16.1", + "@jimp/jpeg": "^0.16.1", + "@jimp/png": "^0.16.1", + "@jimp/tiff": "^0.16.1", + "timm": "^1.6.1" + }, + "peerDependencies": { + "@jimp/custom": ">=0.3.5" } }, - "node_modules/babel-loader/node_modules/loader-utils": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", - "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", + "node_modules/@jimp/utils": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/@jimp/utils/-/utils-0.16.1.tgz", + "integrity": "sha512-8fULQjB0x4LzUSiSYG6ZtQl355sZjxbv8r9PPAuYHzS9sGiSHJQavNqK/nKnpDsVkU88/vRGcE7t3nMU0dEnVw==", "dependencies": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^1.0.1" - }, - "engines": { - "node": ">=4.0.0" + "@babel/runtime": "^7.7.2", + "regenerator-runtime": "^0.13.3" } }, - "node_modules/babel-loader/node_modules/schema-utils": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz", - "integrity": "sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==", + "node_modules/@jridgewell/gen-mapping": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz", + "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==", "dependencies": { - "@types/json-schema": "^7.0.5", - "ajv": "^6.12.4", - "ajv-keywords": "^3.5.2" + "@jridgewell/set-array": "^1.0.0", + "@jridgewell/sourcemap-codec": "^1.4.10" }, "engines": { - "node": ">= 8.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" + "node": ">=6.0.0" } }, - "node_modules/babel-plugin-apply-mdx-type-prop": { - "version": "1.6.22", - "resolved": "https://registry.npmjs.org/babel-plugin-apply-mdx-type-prop/-/babel-plugin-apply-mdx-type-prop-1.6.22.tgz", - "integrity": "sha512-VefL+8o+F/DfK24lPZMtJctrCVOfgbqLAGZSkxwhazQv4VxPg3Za/i40fu22KR2m8eEda+IfSOlPLUSIiLcnCQ==", - "dependencies": { - "@babel/helper-plugin-utils": "7.10.4", - "@mdx-js/util": "1.6.22" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - }, - "peerDependencies": { - "@babel/core": "^7.11.6" + "node_modules/@jridgewell/resolve-uri": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.0.6.tgz", + "integrity": "sha512-R7xHtBSNm+9SyvpJkdQl+qrM3Hm2fea3Ef197M3mUug+v+yR+Rhfbs7PBtcBUVnIWJ4JcAdjvij+c8hXS9p5aw==", + "engines": { + "node": ">=6.0.0" } }, - "node_modules/babel-plugin-apply-mdx-type-prop/node_modules/@babel/helper-plugin-utils": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz", - "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==" + "node_modules/@jridgewell/set-array": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.0.tgz", + "integrity": "sha512-SfJxIxNVYLTsKwzB3MoOQ1yxf4w/E6MdkvTgrgAt1bfxjSrLUoHMKrDOykwN14q65waezZIdqDneUIPh4/sKxg==", + "engines": { + "node": ">=6.0.0" + } }, - "node_modules/babel-plugin-dynamic-import-node": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.0.tgz", - "integrity": "sha512-o6qFkpeQEBxcqt0XYlWzAVxNCSCZdUgcR8IRlhD/8DylxjjO4foPcvTW0GGKa/cVt3rvxZ7o5ippJ+/0nvLhlQ==", + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.11", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.11.tgz", + "integrity": "sha512-Fg32GrJo61m+VqYSdRSjRXMjQ06j8YIYfcTqndLYVAaHmroZHLJZCydsWBOTDqXS2v+mjxohBWEMfg97GXmYQg==" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", "dependencies": { - "object.assign": "^4.1.0" + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" } }, - "node_modules/babel-plugin-extract-import-names": { + "node_modules/@leichtgewicht/ip-codec": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.3.tgz", + "integrity": "sha512-nkalE/f1RvRGChwBnEIoBfSEYOXnCRdleKuv6+lePbMDrMZXeDQnqak5XDOeBgrPPyPfAdcCu/B5z+v3VhplGg==" + }, + "node_modules/@mdx-js/mdx": { "version": "1.6.22", - "resolved": "https://registry.npmjs.org/babel-plugin-extract-import-names/-/babel-plugin-extract-import-names-1.6.22.tgz", - "integrity": "sha512-yJ9BsJaISua7d8zNT7oRG1ZLBJCIdZ4PZqmH8qa9N5AK01ifk3fnkc98AXhtzE7UkfCsEumvoQWgoYLhOnJ7jQ==", + "resolved": "https://registry.npmjs.org/@mdx-js/mdx/-/mdx-1.6.22.tgz", + "integrity": "sha512-AMxuLxPz2j5/6TpF/XSdKpQP1NlG0z11dFOlq+2IP/lSgl11GY8ji6S/rgsViN/L0BDvHvUMruRb7ub+24LUYA==", "dependencies": { - "@babel/helper-plugin-utils": "7.10.4" + "@babel/core": "7.12.9", + "@babel/plugin-syntax-jsx": "7.12.1", + "@babel/plugin-syntax-object-rest-spread": "7.8.3", + "@mdx-js/util": "1.6.22", + "babel-plugin-apply-mdx-type-prop": "1.6.22", + "babel-plugin-extract-import-names": "1.6.22", + "camelcase-css": "2.0.1", + "detab": "2.0.4", + "hast-util-raw": "6.0.1", + "lodash.uniq": "4.5.0", + "mdast-util-to-hast": "10.0.1", + "remark-footnotes": "2.0.0", + "remark-mdx": "1.6.22", + "remark-parse": "8.0.3", + "remark-squeeze-paragraphs": "4.0.0", + "style-to-object": "0.3.0", + "unified": "9.2.0", + "unist-builder": "2.0.3", + "unist-util-visit": "2.0.3" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/unified" } }, - "node_modules/babel-plugin-extract-import-names/node_modules/@babel/helper-plugin-utils": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz", - "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==" - }, - "node_modules/babel-plugin-polyfill-corejs2": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.2.2.tgz", - "integrity": "sha512-kISrENsJ0z5dNPq5eRvcctITNHYXWOA4DUZRFYCz3jYCcvTb/A546LIddmoGNMVYg2U38OyFeNosQwI9ENTqIQ==", + "node_modules/@mdx-js/mdx/node_modules/@babel/core": { + "version": "7.12.9", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.12.9.tgz", + "integrity": "sha512-gTXYh3M5wb7FRXQy+FErKFAv90BnlOuNn1QkCK2lREoPAjrQCO49+HVSrFoe5uakFAF5eenS75KbO2vQiLrTMQ==", "dependencies": { - "@babel/compat-data": "^7.13.11", - "@babel/helper-define-polyfill-provider": "^0.2.2", - "semver": "^6.1.1" + "@babel/code-frame": "^7.10.4", + "@babel/generator": "^7.12.5", + "@babel/helper-module-transforms": "^7.12.1", + "@babel/helpers": "^7.12.5", + "@babel/parser": "^7.12.7", + "@babel/template": "^7.12.7", + "@babel/traverse": "^7.12.9", + "@babel/types": "^7.12.7", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.1", + "json5": "^2.1.2", + "lodash": "^4.17.19", + "resolve": "^1.3.2", + "semver": "^5.4.1", + "source-map": "^0.5.0" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/babel-plugin-polyfill-corejs2/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "bin": { - "semver": "bin/semver.js" + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" } }, - "node_modules/babel-plugin-polyfill-corejs3": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.2.5.tgz", - "integrity": "sha512-ninF5MQNwAX9Z7c9ED+H2pGt1mXdP4TqzlHKyPIYmJIYz0N+++uwdM7RnJukklhzJ54Q84vA4ZJkgs7lu5vqcw==", + "node_modules/@mdx-js/mdx/node_modules/@babel/plugin-syntax-jsx": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.12.1.tgz", + "integrity": "sha512-1yRi7yAtB0ETgxdY9ti/p2TivUxJkTdhu/ZbF9MshVGqOx1TdB3b7xCXs49Fupgg50N45KcAsRP/ZqWjs9SRjg==", "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.2.2", - "core-js-compat": "^3.16.2" + "@babel/helper-plugin-utils": "^7.10.4" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, - "node_modules/babel-plugin-polyfill-regenerator": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.2.2.tgz", - "integrity": "sha512-Goy5ghsc21HgPDFtzRkSirpZVW35meGoTmTOb2bxqdl60ghub4xOidgNTHaZfQ2FaxQsKmwvXtOAkcIS4SMBWg==", - "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.2.2" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node_modules/@mdx-js/mdx/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "bin": { + "semver": "bin/semver" } }, - "node_modules/babel-plugin-styled-components": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/babel-plugin-styled-components/-/babel-plugin-styled-components-1.13.2.tgz", - "integrity": "sha512-Vb1R3d4g+MUfPQPVDMCGjm3cDocJEUTR7Xq7QS95JWWeksN1wdFRYpD2kulDgI3Huuaf1CZd+NK4KQmqUFh5dA==", - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.0.0", - "@babel/helper-module-imports": "^7.0.0", - "babel-plugin-syntax-jsx": "^6.18.0", - "lodash": "^4.17.11" + "node_modules/@mdx-js/mdx/node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@mdx-js/react": { + "version": "1.6.22", + "resolved": "https://registry.npmjs.org/@mdx-js/react/-/react-1.6.22.tgz", + "integrity": "sha512-TDoPum4SHdfPiGSAaRBw7ECyI8VaHpK8GJugbJIJuqyh6kzw9ZLJZW3HGL3NNrJGxcAixUvqROm+YuQOo5eXtg==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" }, "peerDependencies": { - "styled-components": ">= 2" + "react": "^16.13.1 || ^17.0.0" } }, - "node_modules/babel-plugin-syntax-jsx": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz", - "integrity": "sha1-CvMqmm4Tyno/1QaeYtew9Y0NiUY=" - }, - "node_modules/bail": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/bail/-/bail-1.0.5.tgz", - "integrity": "sha512-xFbRxM1tahm08yHBP16MMjVUAvDaBMD38zsM9EMAUN61omwLmKlOpB/Zku5QkjZ8TZ4vn53pj+t518cH0S03RQ==", + "node_modules/@mdx-js/util": { + "version": "1.6.22", + "resolved": "https://registry.npmjs.org/@mdx-js/util/-/util-1.6.22.tgz", + "integrity": "sha512-H1rQc1ZOHANWBvPcW+JpGwr+juXSxM8Q8YCkm3GhZd8REu1fHR3z99CErO1p9pkcfcxZnMdIZdIsXkOHY0NilA==", "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" - }, - "node_modules/base": { - "version": "0.11.2", - "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", - "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", "dependencies": { - "cache-base": "^1.0.1", - "class-utils": "^0.3.5", - "component-emitter": "^1.2.1", - "define-property": "^1.0.0", - "isobject": "^3.0.1", - "mixin-deep": "^1.2.0", - "pascalcase": "^0.1.1" + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" }, "engines": { - "node": ">=0.10.0" + "node": ">= 8" } }, - "node_modules/base/node_modules/define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dependencies": { - "is-descriptor": "^1.0.0" - }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", "engines": { - "node": ">=0.10.0" + "node": ">= 8" } }, - "node_modules/base/node_modules/is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", "dependencies": { - "kind-of": "^6.0.0" + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" }, "engines": { - "node": ">=0.10.0" + "node": ">= 8" } }, - "node_modules/base/node_modules/is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "node_modules/@polka/url": { + "version": "1.0.0-next.21", + "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.21.tgz", + "integrity": "sha512-a5Sab1C4/icpTZVzZc5Ghpz88yQtGOyNqYXcZgOssB2uuAr+wF/MvN6bgtW32q7HHrvBki+BsZ0OuNv6EV3K9g==" + }, + "node_modules/@redocly/ajv": { + "version": "8.6.4", + "resolved": "https://registry.npmjs.org/@redocly/ajv/-/ajv-8.6.4.tgz", + "integrity": "sha512-y9qNj0//tZtWB2jfXNK3BX18BSBp9zNR7KE7lMysVHwbZtY392OJCjm6Rb/h4UHH2r1AqjNEHFD6bRn+DqU9Mw==", "dependencies": { - "kind-of": "^6.0.0" + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" }, - "engines": { - "node": ">=0.10.0" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/base/node_modules/is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "node_modules/@redocly/openapi-core": { + "version": "1.0.0-beta.94", + "resolved": "https://registry.npmjs.org/@redocly/openapi-core/-/openapi-core-1.0.0-beta.94.tgz", + "integrity": "sha512-xTklcobv+51bQVkUOpUiNY0GztL+0u3yGsy2BtldaHpcnNGMu3lu/utsoOHkiNTpgVEGyEWVZzBtF6Sz5v/Fkg==", "dependencies": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - }, + "@redocly/ajv": "^8.6.4", + "@types/node": "^14.11.8", + "colorette": "^1.2.0", + "js-levenshtein": "^1.1.6", + "js-yaml": "^4.1.0", + "lodash.isequal": "^4.5.0", + "minimatch": "^3.0.4", + "node-fetch": "^2.6.1", + "pluralize": "^8.0.0", + "yaml-ast-parser": "0.0.43" + }, "engines": { - "node": ">=0.10.0" + "node": ">=12.0.0" } }, - "node_modules/base16": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/base16/-/base16-1.0.0.tgz", - "integrity": "sha1-4pf2DX7BAUp6lxo568ipjAtoHnA=" - }, - "node_modules/base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] + "node_modules/@redocly/openapi-core/node_modules/@types/node": { + "version": "14.18.16", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.16.tgz", + "integrity": "sha512-X3bUMdK/VmvrWdoTkz+VCn6nwKwrKCFTHtqwBIaQJNx4RUIBBUFXM00bqPz/DsDd+Icjmzm6/tyYZzeGVqb6/Q==" }, - "node_modules/batch": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", - "integrity": "sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY=" + "node_modules/@redocly/react-dropdown-aria": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/@redocly/react-dropdown-aria/-/react-dropdown-aria-2.0.12.tgz", + "integrity": "sha512-feQEZlyBvQsbT/fvpJ4jJ5OLGaUPpnskHYDsY8DGpPymN+HUeDQrqkBEbbKRwMKidFTI2cxk2kJNNTnvdS9jyw==", + "peerDependencies": { + "react": "^16.8.4 || ^17.0.0", + "react-dom": "^16.8.4 || ^17.0.0", + "styled-components": "^5.1.1" + } }, - "node_modules/big.js": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", - "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", - "engines": { - "node": "*" + "node_modules/@sideway/address": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.4.tgz", + "integrity": "sha512-7vwq+rOHVWjyXxVlR76Agnvhy8I9rpzjosTESvmhNeXOXdZZB15Fl+TI9x1SiHZH5Jv2wTGduSxFDIaq0m3DUw==", + "dependencies": { + "@hapi/hoek": "^9.0.0" } }, - "node_modules/binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "node_modules/@sideway/formula": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.0.tgz", + "integrity": "sha512-vHe7wZ4NOXVfkoRb8T5otiENVlT7a3IAiw7H5M2+GO+9CDgcVUUsX1zalAztCmwyOr2RUTGJdgB+ZvSVqmdHmg==" + }, + "node_modules/@sideway/pinpoint": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@sideway/pinpoint/-/pinpoint-2.0.0.tgz", + "integrity": "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==" + }, + "node_modules/@sindresorhus/is": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", + "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==", "engines": { - "node": ">=8" + "node": ">=6" } }, - "node_modules/bindings": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", - "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", - "optional": true, + "node_modules/@sinonjs/commons": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.3.tgz", + "integrity": "sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ==", + "dev": true, "dependencies": { - "file-uri-to-path": "1.0.0" + "type-detect": "4.0.8" } }, - "node_modules/bl": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", - "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "node_modules/@sinonjs/fake-timers": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-8.1.0.tgz", + "integrity": "sha512-OAPJUAtgeINhh/TAlUID4QTs53Njm7xzddaVlEs/SXwgtiD1tW22zAB/W1wdqfrpmikgaWQ9Fw6Ws+hsiRm5Vg==", + "dev": true, "dependencies": { - "buffer": "^5.5.0", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" + "@sinonjs/commons": "^1.7.0" } }, - "node_modules/bluebird": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", - "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" - }, - "node_modules/bmp-js": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/bmp-js/-/bmp-js-0.1.0.tgz", - "integrity": "sha1-4Fpj95amwf8l9Hcex62twUjAcjM=" - }, - "node_modules/bn.js": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.0.tgz", - "integrity": "sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw==" + "node_modules/@slorber/static-site-generator-webpack-plugin": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@slorber/static-site-generator-webpack-plugin/-/static-site-generator-webpack-plugin-4.0.4.tgz", + "integrity": "sha512-FvMavoWEIePps6/JwGCOLYKCRhuwIHhMtmbKpBFgzNkxwpa/569LfTkrbRk1m1I3n+ezJK4on9E1A6cjuZmD9g==", + "dependencies": { + "bluebird": "^3.7.1", + "cheerio": "^0.22.0", + "eval": "^0.1.8", + "webpack-sources": "^1.4.3" + } }, - "node_modules/body-parser": { - "version": "1.19.0", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", - "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", + "node_modules/@slorber/static-site-generator-webpack-plugin/node_modules/cheerio": { + "version": "0.22.0", + "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-0.22.0.tgz", + "integrity": "sha512-8/MzidM6G/TgRelkzDG13y3Y9LxBjCb+8yOEZ9+wwq5gVF2w2pV0wmHvjfT0RvuxGyR7UEuK36r+yYMbT4uKgA==", "dependencies": { - "bytes": "3.1.0", - "content-type": "~1.0.4", - "debug": "2.6.9", - "depd": "~1.1.2", - "http-errors": "1.7.2", - "iconv-lite": "0.4.24", - "on-finished": "~2.3.0", - "qs": "6.7.0", - "raw-body": "2.4.0", - "type-is": "~1.6.17" + "css-select": "~1.2.0", + "dom-serializer": "~0.1.0", + "entities": "~1.1.1", + "htmlparser2": "^3.9.1", + "lodash.assignin": "^4.0.9", + "lodash.bind": "^4.1.4", + "lodash.defaults": "^4.0.1", + "lodash.filter": "^4.4.0", + "lodash.flatten": "^4.2.0", + "lodash.foreach": "^4.3.0", + "lodash.map": "^4.4.0", + "lodash.merge": "^4.4.0", + "lodash.pick": "^4.2.1", + "lodash.reduce": "^4.4.0", + "lodash.reject": "^4.4.0", + "lodash.some": "^4.4.0" }, "engines": { - "node": ">= 0.8" + "node": ">= 0.6" } }, - "node_modules/body-parser/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "node_modules/@slorber/static-site-generator-webpack-plugin/node_modules/css-select": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz", + "integrity": "sha512-dUQOBoqdR7QwV90WysXPLXG5LO7nhYBgiWVfxF80DKPF8zx1t/pUd2FYy73emg3zrjtM6dzmYgbHKfV2rxiHQA==", "dependencies": { - "ms": "2.0.0" + "boolbase": "~1.0.0", + "css-what": "2.1", + "domutils": "1.5.1", + "nth-check": "~1.0.1" } }, - "node_modules/body-parser/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - }, - "node_modules/bonjour": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/bonjour/-/bonjour-3.5.0.tgz", - "integrity": "sha1-jokKGD2O6aI5OzhExpGkK897yfU=", - "dependencies": { - "array-flatten": "^2.1.0", - "deep-equal": "^1.0.1", - "dns-equal": "^1.0.0", - "dns-txt": "^2.0.2", - "multicast-dns": "^6.0.1", - "multicast-dns-service-types": "^1.1.0" + "node_modules/@slorber/static-site-generator-webpack-plugin/node_modules/css-what": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.3.tgz", + "integrity": "sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg==", + "engines": { + "node": "*" } }, - "node_modules/bonjour/node_modules/array-flatten": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz", - "integrity": "sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==" - }, - "node_modules/boolbase": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", - "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=" - }, - "node_modules/boxen": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/boxen/-/boxen-5.1.2.tgz", - "integrity": "sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ==", + "node_modules/@slorber/static-site-generator-webpack-plugin/node_modules/dom-serializer": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.1.tgz", + "integrity": "sha512-l0IU0pPzLWSHBcieZbpOKgkIn3ts3vAh7ZuFyXNwJxJXk/c4Gwj9xaTJwIDVQCXawWD0qb3IzMGH5rglQaO0XA==", "dependencies": { - "ansi-align": "^3.0.0", - "camelcase": "^6.2.0", - "chalk": "^4.1.0", - "cli-boxes": "^2.2.1", - "string-width": "^4.2.2", - "type-fest": "^0.20.2", - "widest-line": "^3.1.0", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "domelementtype": "^1.3.0", + "entities": "^1.1.1" } }, - "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "node_modules/@slorber/static-site-generator-webpack-plugin/node_modules/domelementtype": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", + "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==" + }, + "node_modules/@slorber/static-site-generator-webpack-plugin/node_modules/domhandler": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz", + "integrity": "sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==", "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "domelementtype": "1" } }, - "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "node_modules/@slorber/static-site-generator-webpack-plugin/node_modules/domutils": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz", + "integrity": "sha512-gSu5Oi/I+3wDENBsOWBiRK1eoGxcywYSqg3rR960/+EfY0CF4EX1VPkgHOZ3WiS/Jg2DtliF6BhWcHlfpYUcGw==", "dependencies": { - "fill-range": "^7.0.1" - }, - "engines": { - "node": ">=8" + "dom-serializer": "0", + "domelementtype": "1" } }, - "node_modules/brorand": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", - "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=" + "node_modules/@slorber/static-site-generator-webpack-plugin/node_modules/entities": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", + "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==" }, - "node_modules/browserify-aes": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", - "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", + "node_modules/@slorber/static-site-generator-webpack-plugin/node_modules/htmlparser2": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.1.tgz", + "integrity": "sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ==", "dependencies": { - "buffer-xor": "^1.0.3", - "cipher-base": "^1.0.0", - "create-hash": "^1.1.0", - "evp_bytestokey": "^1.0.3", + "domelementtype": "^1.3.1", + "domhandler": "^2.3.0", + "domutils": "^1.5.1", + "entities": "^1.1.1", "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" + "readable-stream": "^3.1.1" } }, - "node_modules/browserify-cipher": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", - "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", + "node_modules/@slorber/static-site-generator-webpack-plugin/node_modules/nth-check": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz", + "integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==", "dependencies": { - "browserify-aes": "^1.0.4", - "browserify-des": "^1.0.0", - "evp_bytestokey": "^1.0.0" + "boolbase": "~1.0.0" } }, - "node_modules/browserify-des": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", - "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", - "dependencies": { - "cipher-base": "^1.0.1", - "des.js": "^1.0.0", - "inherits": "^2.0.1", - "safe-buffer": "^5.1.2" + "node_modules/@svgr/babel-plugin-add-jsx-attribute": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-5.4.0.tgz", + "integrity": "sha512-ZFf2gs/8/6B8PnSofI0inYXr2SDNTDScPXhN7k5EqD4aZ3gi6u+rbmZHVB8IM3wDyx8ntKACZbtXSm7oZGRqVg==", + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" } }, - "node_modules/browserify-rsa": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.1.0.tgz", - "integrity": "sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog==", - "dependencies": { - "bn.js": "^5.0.0", - "randombytes": "^2.0.1" + "node_modules/@svgr/babel-plugin-remove-jsx-attribute": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-5.4.0.tgz", + "integrity": "sha512-yaS4o2PgUtwLFGTKbsiAy6D0o3ugcUhWK0Z45umJ66EPWunAz9fuFw2gJuje6wqQvQWOTJvIahUwndOXb7QCPg==", + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" } }, - "node_modules/browserify-sign": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.1.tgz", - "integrity": "sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg==", - "dependencies": { - "bn.js": "^5.1.1", - "browserify-rsa": "^4.0.1", - "create-hash": "^1.2.0", - "create-hmac": "^1.1.7", - "elliptic": "^6.5.3", - "inherits": "^2.0.4", - "parse-asn1": "^5.1.5", - "readable-stream": "^3.6.0", - "safe-buffer": "^5.2.0" + "node_modules/@svgr/babel-plugin-remove-jsx-empty-expression": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-5.0.1.tgz", + "integrity": "sha512-LA72+88A11ND/yFIMzyuLRSMJ+tRKeYKeQ+mR3DcAZ5I4h5CPWN9AHyUzJbWSYp/u2u0xhmgOe0+E41+GjEueA==", + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" } }, - "node_modules/browserify-sign/node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/browserify-zlib": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", - "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", - "dependencies": { - "pako": "~1.0.5" + "node_modules/@svgr/babel-plugin-replace-jsx-attribute-value": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-5.0.1.tgz", + "integrity": "sha512-PoiE6ZD2Eiy5mK+fjHqwGOS+IXX0wq/YDtNyIgOrc6ejFnxN4b13pRpiIPbtPwHEc+NT2KCjteAcq33/F1Y9KQ==", + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" } }, - "node_modules/browserslist": { - "version": "4.17.4", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.17.4.tgz", - "integrity": "sha512-Zg7RpbZpIJRW3am9Lyckue7PLytvVxxhJj1CaJVlCWENsGEAOlnlt8X0ZxGRPp7Bt9o8tIRM5SEXy4BCPMJjLQ==", - "dependencies": { - "caniuse-lite": "^1.0.30001265", - "electron-to-chromium": "^1.3.867", - "escalade": "^3.1.1", - "node-releases": "^2.0.0", - "picocolors": "^1.0.0" - }, - "bin": { - "browserslist": "cli.js" - }, + "node_modules/@svgr/babel-plugin-svg-dynamic-title": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-5.4.0.tgz", + "integrity": "sha512-zSOZH8PdZOpuG1ZVx/cLVePB2ibo3WPpqo7gFIjLV9a0QsuQAzJiwwqmuEdTaW2pegyBE17Uu15mOgOcgabQZg==", "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + "node": ">=10" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" + "type": "github", + "url": "https://github.com/sponsors/gregberge" } }, - "node_modules/buffer": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", - "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" + "node_modules/@svgr/babel-plugin-svg-em-dimensions": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-5.4.0.tgz", + "integrity": "sha512-cPzDbDA5oT/sPXDCUYoVXEmm3VIoAWAPT6mSPTJNbQaBNUuEKVKyGH93oDY4e42PYHRW67N5alJx/eEol20abw==", + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" } }, - "node_modules/buffer-equal": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-0.0.1.tgz", - "integrity": "sha1-kbx0sR6kBbyRa8aqkI+q+ltKrEs=", + "node_modules/@svgr/babel-plugin-transform-react-native-svg": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-5.4.0.tgz", + "integrity": "sha512-3eYP/SaopZ41GHwXma7Rmxcv9uRslRDTY1estspeB1w1ueZWd/tPlMfEOoccYpEMZU3jD4OU7YitnXcF5hLW2Q==", "engines": { - "node": ">=0.4.0" + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" } }, - "node_modules/buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" - }, - "node_modules/buffer-indexof": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/buffer-indexof/-/buffer-indexof-1.1.1.tgz", - "integrity": "sha512-4/rOEg86jivtPTeOUUT61jJO1Ya1TrR/OkqCSZDyq84WJh3LuuiphBYJN+fm5xufIk4XAFcEwte/8WzC8If/1g==" - }, - "node_modules/buffer-xor": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", - "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=" - }, - "node_modules/builtin-status-codes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", - "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=" - }, - "node_modules/bytes": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", - "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", + "node_modules/@svgr/babel-plugin-transform-svg-component": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-5.5.0.tgz", + "integrity": "sha512-q4jSH1UUvbrsOtlo/tKcgSeiCHRSBdXoIoqX1pgcKK/aU3JD27wmMKwGtpB8qRYUYoyXvfGxUVKchLuR5pB3rQ==", "engines": { - "node": ">= 0.8" + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" } }, - "node_modules/cache-base": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", - "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", + "node_modules/@svgr/babel-preset": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-preset/-/babel-preset-5.5.0.tgz", + "integrity": "sha512-4FiXBjvQ+z2j7yASeGPEi8VD/5rrGQk4Xrq3EdJmoZgz/tpqChpo5hgXDvmEauwtvOc52q8ghhZK4Oy7qph4ig==", "dependencies": { - "collection-visit": "^1.0.0", - "component-emitter": "^1.2.1", - "get-value": "^2.0.6", - "has-value": "^1.0.0", - "isobject": "^3.0.1", - "set-value": "^2.0.0", - "to-object-path": "^0.3.0", - "union-value": "^1.0.0", - "unset-value": "^1.0.0" + "@svgr/babel-plugin-add-jsx-attribute": "^5.4.0", + "@svgr/babel-plugin-remove-jsx-attribute": "^5.4.0", + "@svgr/babel-plugin-remove-jsx-empty-expression": "^5.0.1", + "@svgr/babel-plugin-replace-jsx-attribute-value": "^5.0.1", + "@svgr/babel-plugin-svg-dynamic-title": "^5.4.0", + "@svgr/babel-plugin-svg-em-dimensions": "^5.4.0", + "@svgr/babel-plugin-transform-react-native-svg": "^5.4.0", + "@svgr/babel-plugin-transform-svg-component": "^5.5.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" } }, - "node_modules/cacheable-request": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", - "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==", + "node_modules/@svgr/core": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/@svgr/core/-/core-5.5.0.tgz", + "integrity": "sha512-q52VOcsJPvV3jO1wkPtzTuKlvX7Y3xIcWRpCMtBF3MrteZJtBfQw/+u0B1BHy5ColpQc1/YVTrPEtSYIMNZlrQ==", "dependencies": { - "clone-response": "^1.0.2", - "get-stream": "^5.1.0", - "http-cache-semantics": "^4.0.0", - "keyv": "^3.0.0", - "lowercase-keys": "^2.0.0", - "normalize-url": "^4.1.0", - "responselike": "^1.0.2" + "@svgr/plugin-jsx": "^5.5.0", + "camelcase": "^6.2.0", + "cosmiconfig": "^7.0.0" }, "engines": { - "node": ">=8" + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" } }, - "node_modules/cacheable-request/node_modules/get-stream": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "node_modules/@svgr/hast-util-to-babel-ast": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-5.5.0.tgz", + "integrity": "sha512-cAaR/CAiZRB8GP32N+1jocovUtvlj0+e65TB50/6Lcime+EA49m/8l+P2ko+XPJ4dw3xaPS3jOL4F2X4KWxoeQ==", "dependencies": { - "pump": "^3.0.0" + "@babel/types": "^7.12.6" }, "engines": { - "node": ">=8" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "type": "github", + "url": "https://github.com/sponsors/gregberge" } }, - "node_modules/cacheable-request/node_modules/lowercase-keys": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", - "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", + "node_modules/@svgr/plugin-jsx": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/@svgr/plugin-jsx/-/plugin-jsx-5.5.0.tgz", + "integrity": "sha512-V/wVh33j12hGh05IDg8GpIUXbjAPnTdPTKuP4VNLggnwaHMPNQNae2pRnyTAILWCQdz5GyMqtO488g7CKM8CBA==", + "dependencies": { + "@babel/core": "^7.12.3", + "@svgr/babel-preset": "^5.5.0", + "@svgr/hast-util-to-babel-ast": "^5.5.0", + "svg-parser": "^2.0.2" + }, "engines": { - "node": ">=8" - } - }, - "node_modules/cacheable-request/node_modules/normalize-url": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.1.tgz", - "integrity": "sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==", + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@svgr/plugin-svgo": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/@svgr/plugin-svgo/-/plugin-svgo-5.5.0.tgz", + "integrity": "sha512-r5swKk46GuQl4RrVejVwpeeJaydoxkdwkM1mBKOgJLBUJPGaLci6ylg/IjhrRsREKDkr4kbMWdgOtbXEh0fyLQ==", + "dependencies": { + "cosmiconfig": "^7.0.0", + "deepmerge": "^4.2.2", + "svgo": "^1.2.2" + }, "engines": { - "node": ">=8" + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" } }, - "node_modules/call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "node_modules/@svgr/webpack": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/@svgr/webpack/-/webpack-5.5.0.tgz", + "integrity": "sha512-DOBOK255wfQxguUta2INKkzPj6AIS6iafZYiYmHn6W3pHlycSRRlvWKCfLDG10fXfLWqE3DJHgRUOyJYmARa7g==", "dependencies": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" + "@babel/core": "^7.12.3", + "@babel/plugin-transform-react-constant-elements": "^7.12.1", + "@babel/preset-env": "^7.12.1", + "@babel/preset-react": "^7.12.5", + "@svgr/core": "^5.5.0", + "@svgr/plugin-jsx": "^5.5.0", + "@svgr/plugin-svgo": "^5.5.0", + "loader-utils": "^2.0.0" + }, + "engines": { + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "type": "github", + "url": "https://github.com/sponsors/gregberge" } }, - "node_modules/call-me-maybe": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.1.tgz", - "integrity": "sha1-JtII6onje1y95gJQoV8DHBak1ms=" + "node_modules/@swc/core": { + "version": "1.2.174", + "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.2.174.tgz", + "integrity": "sha512-PbBwwaqrBCyOae+hZV9QK+QeR1azqb+MGKvuk6SVxsk3Rvh1HSX4CieMnuhcmX+Sm4L58eQv9l37ZLCu2hBZcA==", + "dev": true, + "bin": { + "swcx": "run_swcx.js" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/swc" + }, + "optionalDependencies": { + "@swc/core-android-arm-eabi": "1.2.174", + "@swc/core-android-arm64": "1.2.174", + "@swc/core-darwin-arm64": "1.2.174", + "@swc/core-darwin-x64": "1.2.174", + "@swc/core-freebsd-x64": "1.2.174", + "@swc/core-linux-arm-gnueabihf": "1.2.174", + "@swc/core-linux-arm64-gnu": "1.2.174", + "@swc/core-linux-arm64-musl": "1.2.174", + "@swc/core-linux-x64-gnu": "1.2.174", + "@swc/core-linux-x64-musl": "1.2.174", + "@swc/core-win32-arm64-msvc": "1.2.174", + "@swc/core-win32-ia32-msvc": "1.2.174", + "@swc/core-win32-x64-msvc": "1.2.174" + } + }, + "node_modules/@swc/core-android-arm-eabi": { + "version": "1.2.174", + "resolved": "https://registry.npmjs.org/@swc/core-android-arm-eabi/-/core-android-arm-eabi-1.2.174.tgz", + "integrity": "sha512-sxH6jIq57wnZ8LyLKN8SXM4DhMo4aTq0mClo+zBMPTyHzNO5AEAwh5nqs+d51Dycs3epur/8iv/J6xDv+cKkfw==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=10" + } }, - "node_modules/callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "node_modules/@swc/core-android-arm64": { + "version": "1.2.174", + "resolved": "https://registry.npmjs.org/@swc/core-android-arm64/-/core-android-arm64-1.2.174.tgz", + "integrity": "sha512-gGXBuY8Zs93eNduyrhm+rB+K/smF535uwmamHB1+7BrkuUtt/Lrk3vDTc4D61GMA/vBOqus9IXKHBc+EFmBbog==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], "engines": { - "node": ">=6" + "node": ">=10" } }, - "node_modules/camel-case": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz", - "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==", - "dependencies": { - "pascal-case": "^3.1.2", - "tslib": "^2.0.3" + "node_modules/@swc/core-darwin-arm64": { + "version": "1.2.174", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.2.174.tgz", + "integrity": "sha512-dFxu2o8dR55A+d0Qf/Ai0yKnGjon/UT1hWnBY9tcyvgo7XsiFRB/P83tlbVohqq9N+SDVxdBg9bMAR2i8rDTHg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=10" } }, - "node_modules/camelcase": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.2.0.tgz", - "integrity": "sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg==", + "node_modules/@swc/core-darwin-x64": { + "version": "1.2.174", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.2.174.tgz", + "integrity": "sha512-LsANlfBkqfJobPvfojTbUY9xw0ZwTxTicdwaK6BC5TLmYXVfvxvMpmhsvIe3bNlx4jV1z0IrFaJ0YxDSc1s6vw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], "engines": { "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/camelcase-css": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", - "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", + "node_modules/@swc/core-freebsd-x64": { + "version": "1.2.174", + "resolved": "https://registry.npmjs.org/@swc/core-freebsd-x64/-/core-freebsd-x64-1.2.174.tgz", + "integrity": "sha512-IG0qc9/qUHmiqC6fqT3yq4iBwNRHN1zYbGpzQm4DU/d7DTwsV7D2A+1McFUKmnUOvBG7zdgg5ee91QxUVOCZTQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], "engines": { - "node": ">= 6" + "node": ">=10" } }, - "node_modules/camelize": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/camelize/-/camelize-1.0.0.tgz", - "integrity": "sha1-FkpUg+Yw+kMh5a8HAg5TGDGyYJs=" + "node_modules/@swc/core-linux-arm-gnueabihf": { + "version": "1.2.174", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.2.174.tgz", + "integrity": "sha512-nK4U8s9++e5AVEhWz3W6V0tUsPPjYJlMsb4ZzZR2qhYe53YBURCznFIhUDwe0ib/f6T773Tn7sr52uemcQBu8A==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } }, - "node_modules/caniuse-api": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz", - "integrity": "sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==", - "dependencies": { - "browserslist": "^4.0.0", - "caniuse-lite": "^1.0.0", - "lodash.memoize": "^4.1.2", - "lodash.uniq": "^4.5.0" + "node_modules/@swc/core-linux-arm64-gnu": { + "version": "1.2.174", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.2.174.tgz", + "integrity": "sha512-Tf6Ths472ul9Z4p8uFP7vMJXLmBS2h4PQL/zDj3g3N+9D8hs6+tnnBNrkEm6jXs09gO4bvaN+706QxmZUEgyPg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" } }, - "node_modules/caniuse-lite": { - "version": "1.0.30001265", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001265.tgz", - "integrity": "sha512-YzBnspggWV5hep1m9Z6sZVLOt7vrju8xWooFAgN6BA5qvy98qPAPb7vNUzypFaoh2pb3vlfzbDO8tB57UPGbtw==", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" + "node_modules/@swc/core-linux-arm64-musl": { + "version": "1.2.174", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.2.174.tgz", + "integrity": "sha512-vsQjxyCe3+qRMQSuDlYwmFxbRILIycRC8OB/tBhTJXYuwIh4zvpxc+zvSuERbd4cmMWwM/JtXIlP5grSNjgH6A==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" } }, - "node_modules/ccount": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/ccount/-/ccount-1.1.0.tgz", - "integrity": "sha512-vlNK021QdI7PNeiUh/lKkC/mNHHfV0m/Ad5JoI0TYtlBnJAslM/JIkm/tGC88bkLIwO6OQ5uV6ztS6kVAtCDlg==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "node_modules/@swc/core-linux-x64-gnu": { + "version": "1.2.174", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.2.174.tgz", + "integrity": "sha512-CFEL2WMIQ1mZvvDguaVGgwan9X7Ah7ctHG8SOa+mFaWXdAyVXOWp8sdNMJbqvwYAv980CENfYioI8yL0z1heWA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" } }, - "node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "node_modules/@swc/core-linux-x64-musl": { + "version": "1.2.174", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.2.174.tgz", + "integrity": "sha512-qulTJ3GYE8gUR0yfIOJVfo8SSl/AgLKAplskIHJu/cP0JtRpHL8B598mfny6SuD+ZabBjUvAz6d8ACL9JdhYTw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-win32-arm64-msvc": { + "version": "1.2.174", + "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.2.174.tgz", + "integrity": "sha512-ZogvH4sOVk3pLguYLlc+3lBlGwJ4WOi375VUqDSb92TirBFPjhX98xDn/Xus1fyRKofSGp1zoAs4w80F6hkX6g==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-win32-ia32-msvc": { + "version": "1.2.174", + "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.2.174.tgz", + "integrity": "sha512-QcnXBs2L0O5BiV61orDxJqZsmk2wPUscTTY4upfW5++eCI6IpDYVyfQmtQ9OdVCXWfVEPrhQKuUxLZEjoKxdNQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-win32-x64-msvc": { + "version": "1.2.174", + "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.2.174.tgz", + "integrity": "sha512-9aFcbPTFA5jtiTQbOsq+/QN29F/YNpOrhcwsUa2Haqq0+2h71rMiBn7oluUERFQ+/se9J0C00iSC0QXif4pfuQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/jest": { + "version": "0.2.20", + "resolved": "https://registry.npmjs.org/@swc/jest/-/jest-0.2.20.tgz", + "integrity": "sha512-5qSUBYY1wyIMn7p0Vl9qqV4hMI69oJwZCIPUpBsTFWN2wlwn6RDugzdgCn+bLXVYh+Cxi8bJcZ1uumDgsoL+FA==", + "dev": true, "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "@jest/create-cache-key-function": "^27.4.2" }, "engines": { - "node": ">=10" + "npm": ">= 7.0.0" }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "peerDependencies": { + "@swc/core": "*" + } + }, + "node_modules/@szmarczak/http-timer": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz", + "integrity": "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==", + "dependencies": { + "defer-to-connect": "^1.0.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@testing-library/dom": { + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-8.13.0.tgz", + "integrity": "sha512-9VHgfIatKNXQNaZTtLnalIy0jNZzY35a4S3oi08YAt9Hv1VsfZ/DfA45lM8D/UhtHBGJ4/lGwp0PZkVndRkoOQ==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.10.4", + "@babel/runtime": "^7.12.5", + "@types/aria-query": "^4.2.0", + "aria-query": "^5.0.0", + "chalk": "^4.1.0", + "dom-accessibility-api": "^0.5.9", + "lz-string": "^1.4.4", + "pretty-format": "^27.0.2" + }, + "engines": { + "node": ">=12" } }, - "node_modules/chalk/node_modules/ansi-styles": { + "node_modules/@testing-library/dom/node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, "dependencies": { "color-convert": "^2.0.1" }, @@ -4912,34 +5165,54 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/chalk/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "node_modules/@testing-library/dom/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "dependencies": { - "color-name": "~1.1.4" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">=7.0.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/chalk/node_modules/color-name": { + "node_modules/@testing-library/dom/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@testing-library/dom/node_modules/color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true }, - "node_modules/chalk/node_modules/has-flag": { + "node_modules/@testing-library/dom/node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, "engines": { "node": ">=8" } }, - "node_modules/chalk/node_modules/supports-color": { + "node_modules/@testing-library/dom/node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, "dependencies": { "has-flag": "^4.0.0" }, @@ -4947,3904 +5220,3641 @@ "node": ">=8" } }, - "node_modules/character-entities": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-1.2.4.tgz", - "integrity": "sha512-iBMyeEHxfVnIakwOuDXpVkc54HijNgCyQB2w0VfGQThle6NXn50zU6V/u+LDhxHcDUPojn6Kpga3PTAD8W1bQw==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/character-entities-legacy": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-1.1.4.tgz", - "integrity": "sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/character-reference-invalid": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-1.1.4.tgz", - "integrity": "sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/cheerio": { - "version": "0.22.0", - "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-0.22.0.tgz", - "integrity": "sha1-qbqoYKP5tZWmuBsahocxIe06Jp4=", + "node_modules/@testing-library/jest-dom": { + "version": "5.16.4", + "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-5.16.4.tgz", + "integrity": "sha512-Gy+IoFutbMQcky0k+bqqumXZ1cTGswLsFqmNLzNdSKkU9KGV2u9oXhukCbbJ9/LRPKiqwxEE8VpV/+YZlfkPUA==", + "dev": true, "dependencies": { - "css-select": "~1.2.0", - "dom-serializer": "~0.1.0", - "entities": "~1.1.1", - "htmlparser2": "^3.9.1", - "lodash.assignin": "^4.0.9", - "lodash.bind": "^4.1.4", - "lodash.defaults": "^4.0.1", - "lodash.filter": "^4.4.0", - "lodash.flatten": "^4.2.0", - "lodash.foreach": "^4.3.0", - "lodash.map": "^4.4.0", - "lodash.merge": "^4.4.0", - "lodash.pick": "^4.2.1", - "lodash.reduce": "^4.4.0", - "lodash.reject": "^4.4.0", - "lodash.some": "^4.4.0" + "@babel/runtime": "^7.9.2", + "@types/testing-library__jest-dom": "^5.9.1", + "aria-query": "^5.0.0", + "chalk": "^3.0.0", + "css": "^3.0.0", + "css.escape": "^1.5.1", + "dom-accessibility-api": "^0.5.6", + "lodash": "^4.17.15", + "redent": "^3.0.0" }, "engines": { - "node": ">= 0.6" + "node": ">=8", + "npm": ">=6", + "yarn": ">=1" } }, - "node_modules/cheerio/node_modules/css-select": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz", - "integrity": "sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg=", + "node_modules/@testing-library/jest-dom/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, "dependencies": { - "boolbase": "~1.0.0", - "css-what": "2.1", - "domutils": "1.5.1", - "nth-check": "~1.0.1" - } - }, - "node_modules/cheerio/node_modules/css-what": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.3.tgz", - "integrity": "sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg==", + "color-convert": "^2.0.1" + }, "engines": { - "node": "*" - } - }, - "node_modules/cheerio/node_modules/dom-serializer": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.1.tgz", - "integrity": "sha512-l0IU0pPzLWSHBcieZbpOKgkIn3ts3vAh7ZuFyXNwJxJXk/c4Gwj9xaTJwIDVQCXawWD0qb3IzMGH5rglQaO0XA==", - "dependencies": { - "domelementtype": "^1.3.0", - "entities": "^1.1.1" - } - }, - "node_modules/cheerio/node_modules/domelementtype": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", - "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==" - }, - "node_modules/cheerio/node_modules/domutils": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz", - "integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=", - "dependencies": { - "dom-serializer": "0", - "domelementtype": "1" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/cheerio/node_modules/entities": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", - "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==" - }, - "node_modules/cheerio/node_modules/nth-check": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz", - "integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==", + "node_modules/@testing-library/jest-dom/node_modules/chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "dev": true, "dependencies": { - "boolbase": "~1.0.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=8" } }, - "node_modules/chokidar": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.2.tgz", - "integrity": "sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ==", + "node_modules/@testing-library/jest-dom/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, "dependencies": { - "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" + "color-name": "~1.1.4" }, "engines": { - "node": ">= 8.10.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" + "node": ">=7.0.0" } }, - "node_modules/chownr": { + "node_modules/@testing-library/jest-dom/node_modules/color-name": { "version": "1.1.4", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", - "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true }, - "node_modules/chrome-trace-event": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", - "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==", + "node_modules/@testing-library/jest-dom/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, "engines": { - "node": ">=6.0" - } - }, - "node_modules/ci-info": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.2.0.tgz", - "integrity": "sha512-dVqRX7fLUm8J6FgHJ418XuIgDLZDkYcDFTeL6TA2gt5WlIZUQrrH6EZrNClwT/H0FateUsZkGIOPRrLbP+PR9A==" - }, - "node_modules/cipher-base": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", - "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", - "dependencies": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" + "node": ">=8" } }, - "node_modules/class-utils": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", - "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", + "node_modules/@testing-library/jest-dom/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, "dependencies": { - "arr-union": "^3.1.0", - "define-property": "^0.2.5", - "isobject": "^3.0.0", - "static-extend": "^0.1.1" + "has-flag": "^4.0.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, - "node_modules/class-utils/node_modules/define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "node_modules/@testing-library/react": { + "version": "12.1.5", + "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-12.1.5.tgz", + "integrity": "sha512-OfTXCJUFgjd/digLUuPxa0+/3ZxsQmE7ub9kcbW/wi96Bh3o/p5vrETcBGfP17NWPGqeYYl5LTRpwyGoMC4ysg==", + "dev": true, "dependencies": { - "is-descriptor": "^0.1.0" + "@babel/runtime": "^7.12.5", + "@testing-library/dom": "^8.0.0", + "@types/react-dom": "<18.0.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=12" + }, + "peerDependencies": { + "react": "<18.0.0", + "react-dom": "<18.0.0" } }, - "node_modules/classnames": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.1.tgz", - "integrity": "sha512-OlQdbZ7gLfGarSqxesMesDa5uz7KFbID8Kpq/SxIoNGDqY8lSYs0D+hhtBXhcdB3rcbXArFr7vlHheLk1voeNA==" - }, - "node_modules/clean-css": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.2.1.tgz", - "integrity": "sha512-ooQCa1/70oRfVdUUGjKpbHuxgMgm8BsDT5EBqBGvPxMoRoGXf4PNx5mMnkjzJ9Ptx4vvmDdha0QVh86QtYIk1g==", + "node_modules/@testing-library/user-event": { + "version": "13.5.0", + "resolved": "https://registry.npmjs.org/@testing-library/user-event/-/user-event-13.5.0.tgz", + "integrity": "sha512-5Kwtbo3Y/NowpkbRuSepbyMFkZmHgD+vPzYB/RJ4oxt5Gj/avFFBYjhw27cqSVPVw/3a67NK1PbiIr9k4Gwmdg==", + "dev": true, "dependencies": { - "source-map": "~0.6.0" + "@babel/runtime": "^7.12.5" }, "engines": { - "node": ">= 10.0" + "node": ">=10", + "npm": ">=6" + }, + "peerDependencies": { + "@testing-library/dom": ">=7.21.4" } }, - "node_modules/clean-css/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "node_modules/@tootallnate/once": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", + "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", + "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">= 6" } }, - "node_modules/clean-stack": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", - "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "node_modules/@trysound/sax": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", + "integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==", "engines": { - "node": ">=6" + "node": ">=10.13.0" } }, - "node_modules/cli-boxes": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz", - "integrity": "sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==", - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } + "node_modules/@types/aria-query": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-4.2.2.tgz", + "integrity": "sha512-HnYpAE1Y6kRyKM/XkEuiRQhTHvkzMBurTHnpFLYLBGPIylZNPs9jJcuOOYWxPLJCSEtmZT0Y8rHDokKN7rRTig==", + "dev": true }, - "node_modules/cliui": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", - "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "node_modules/@types/babel__core": { + "version": "7.1.19", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.19.tgz", + "integrity": "sha512-WEOTgRsbYkvA/KCsDwVEGkd7WAr1e3g31VHQ8zy5gul/V1qKullU/BU5I68X5v7V3GnB9eotmom4v5a5gjxorw==", + "dev": true, "dependencies": { - "string-width": "^3.1.0", - "strip-ansi": "^5.2.0", - "wrap-ansi": "^5.1.0" + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" } }, - "node_modules/cliui/node_modules/ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "engines": { - "node": ">=6" + "node_modules/@types/babel__generator": { + "version": "7.6.4", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.4.tgz", + "integrity": "sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg==", + "dev": true, + "dependencies": { + "@babel/types": "^7.0.0" } }, - "node_modules/cliui/node_modules/emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==" - }, - "node_modules/cliui/node_modules/is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "engines": { - "node": ">=4" + "node_modules/@types/babel__template": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.1.tgz", + "integrity": "sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" } }, - "node_modules/cliui/node_modules/string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "node_modules/@types/babel__traverse": { + "version": "7.17.1", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.17.1.tgz", + "integrity": "sha512-kVzjari1s2YVi77D3w1yuvohV2idweYXMCDzqBiVNN63TcDWrIlTVOYpqVrvbbyOE/IyzBoTKF0fdnLPEORFxA==", + "dev": true, "dependencies": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - }, - "engines": { - "node": ">=6" + "@babel/types": "^7.3.0" } }, - "node_modules/cliui/node_modules/strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "node_modules/@types/body-parser": { + "version": "1.19.2", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz", + "integrity": "sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==", "dependencies": { - "ansi-regex": "^4.1.0" - }, - "engines": { - "node": ">=6" + "@types/connect": "*", + "@types/node": "*" } }, - "node_modules/cliui/node_modules/wrap-ansi": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", - "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "node_modules/@types/bonjour": { + "version": "3.5.10", + "resolved": "https://registry.npmjs.org/@types/bonjour/-/bonjour-3.5.10.tgz", + "integrity": "sha512-p7ienRMiS41Nu2/igbJxxLDWrSZ0WxM8UQgCeO9KhoVF7cOVFkrKsiDr1EsJIla8vV3oEEjGcz11jc5yimhzZw==", "dependencies": { - "ansi-styles": "^3.2.0", - "string-width": "^3.0.0", - "strip-ansi": "^5.0.0" - }, - "engines": { - "node": ">=6" + "@types/node": "*" } }, - "node_modules/clone-deep": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", - "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", + "node_modules/@types/connect": { + "version": "3.4.35", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", + "integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==", "dependencies": { - "is-plain-object": "^2.0.4", - "kind-of": "^6.0.2", - "shallow-clone": "^3.0.0" - }, - "engines": { - "node": ">=6" + "@types/node": "*" } }, - "node_modules/clone-response": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", - "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=", + "node_modules/@types/connect-history-api-fallback": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.3.5.tgz", + "integrity": "sha512-h8QJa8xSb1WD4fpKBDcATDNGXghFj6/3GRWG6dhmRcu0RX1Ubasur2Uvx5aeEwlf0MwblEC2bMzzMQntxnw/Cw==", "dependencies": { - "mimic-response": "^1.0.0" + "@types/express-serve-static-core": "*", + "@types/node": "*" } }, - "node_modules/clsx": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.1.1.tgz", - "integrity": "sha512-6/bPho624p3S2pMyvP5kKBPXnI3ufHLObBFCfgx+LkeR5lg2XYy2hqZqUf45ypD8COn2bhgGJSUE+l5dhNBieA==", - "engines": { - "node": ">=6" + "node_modules/@types/eslint": { + "version": "8.4.1", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.4.1.tgz", + "integrity": "sha512-GE44+DNEyxxh2Kc6ro/VkIj+9ma0pO0bwv9+uHSyBrikYOHr8zYcdPvnBOp1aw8s+CjRvuSx7CyWqRrNFQ59mA==", + "dependencies": { + "@types/estree": "*", + "@types/json-schema": "*" } }, - "node_modules/coa": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/coa/-/coa-2.0.2.tgz", - "integrity": "sha512-q5/jG+YQnSy4nRTV4F7lPepBJZ8qBNJJDBuJdoejDyLXgmL7IEo+Le2JDZudFTFt7mrCqIRaSjws4ygRCTCAXA==", + "node_modules/@types/eslint-scope": { + "version": "3.7.3", + "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.3.tgz", + "integrity": "sha512-PB3ldyrcnAicT35TWPs5IcwKD8S333HMaa2VVv4+wdvebJkjWuW/xESoB8IwRcog8HYVYamb1g/R31Qv5Bx03g==", "dependencies": { - "@types/q": "^1.5.1", - "chalk": "^2.4.1", - "q": "^1.1.2" - }, - "engines": { - "node": ">= 4.0" + "@types/eslint": "*", + "@types/estree": "*" } }, - "node_modules/coa/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "node_modules/@types/estree": { + "version": "0.0.51", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.51.tgz", + "integrity": "sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ==" + }, + "node_modules/@types/express": { + "version": "4.17.13", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.13.tgz", + "integrity": "sha512-6bSZTPaTIACxn48l50SR+axgrqm6qXFIxrdAKaG6PaJk3+zuUr35hBlgT7vOmJcum+OEaIBLtHV/qloEAFITeA==", "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.18", + "@types/qs": "*", + "@types/serve-static": "*" } }, - "node_modules/code-point-at": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", - "engines": { - "node": ">=0.10.0" + "node_modules/@types/express-serve-static-core": { + "version": "4.17.28", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.28.tgz", + "integrity": "sha512-P1BJAEAW3E2DJUlkgq4tOL3RyMunoWXqbSCygWo5ZIWTjUgN1YnaXWW4VWl/oc8vs/XoYibEGBKP0uZyF4AHig==", + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*" } }, - "node_modules/collapse-white-space": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/collapse-white-space/-/collapse-white-space-1.0.6.tgz", - "integrity": "sha512-jEovNnrhMuqyCcjfEJA56v0Xq8SkIoPKDyaHahwo3POf4qcSXqMYuwNcOTzp74vTsR9Tn08z4MxWqAhcekogkQ==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "node_modules/@types/graceful-fs": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.5.tgz", + "integrity": "sha512-anKkLmZZ+xm4p8JWBf4hElkM4XR+EZeA2M9BAkkTldmcyDY4mbdIJnRghDJH3Ov5ooY7/UAoENtmdMSkaAd7Cw==", + "dev": true, + "dependencies": { + "@types/node": "*" } }, - "node_modules/collection-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", - "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", + "node_modules/@types/hast": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/@types/hast/-/hast-2.3.4.tgz", + "integrity": "sha512-wLEm0QvaoawEDoTRwzTXp4b4jpwiJDvR5KMnFnVodm3scufTlBOWRD6N1OBf9TZMhjlNsSfcO5V+7AF4+Vy+9g==", "dependencies": { - "map-visit": "^1.0.0", - "object-visit": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" + "@types/unist": "*" } }, - "node_modules/color": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/color/-/color-3.2.1.tgz", - "integrity": "sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA==", + "node_modules/@types/history": { + "version": "4.7.11", + "resolved": "https://registry.npmjs.org/@types/history/-/history-4.7.11.tgz", + "integrity": "sha512-qjDJRrmvBMiTx+jyLxvLfJU7UznFuokDv4f3WRuriHKERccVpFU+8XMQUAbDzoiJCsmexxRExQeMwwCdamSKDA==" + }, + "node_modules/@types/html-minifier-terser": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", + "integrity": "sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg==" + }, + "node_modules/@types/http-proxy": { + "version": "1.17.8", + "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.8.tgz", + "integrity": "sha512-5kPLG5BKpWYkw/LVOGWpiq3nEVqxiN32rTgI53Sk12/xHFQ2rG3ehI9IO+O3W2QoKeyB92dJkoka8SUm6BX1pA==", "dependencies": { - "color-convert": "^1.9.3", - "color-string": "^1.6.0" + "@types/node": "*" } }, - "node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "node_modules/@types/istanbul-lib-coverage": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", + "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==", + "dev": true + }, + "node_modules/@types/istanbul-lib-report": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", + "integrity": "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==", + "dev": true, "dependencies": { - "color-name": "1.1.3" + "@types/istanbul-lib-coverage": "*" } }, - "node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" + "node_modules/@types/istanbul-reports": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", + "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", + "dev": true, + "dependencies": { + "@types/istanbul-lib-report": "*" + } }, - "node_modules/color-string": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.6.0.tgz", - "integrity": "sha512-c/hGS+kRWJutUBEngKKmk4iH3sD59MBkoxVapS/0wgpCz2u7XsNloxknyvBhzwEs1IbV36D9PwqLPJ2DTu3vMA==", + "node_modules/@types/jest": { + "version": "27.4.1", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-27.4.1.tgz", + "integrity": "sha512-23iPJADSmicDVrWk+HT58LMJtzLAnB2AgIzplQuq/bSrGaxCrlvRFjGbXmamnnk/mAmCdLStiGqggu28ocUyiw==", + "dev": true, "dependencies": { - "color-name": "^1.0.0", - "simple-swizzle": "^0.2.2" + "jest-matcher-utils": "^27.0.0", + "pretty-format": "^27.0.0" } }, - "node_modules/colord": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/colord/-/colord-2.8.0.tgz", - "integrity": "sha512-kNkVV4KFta3TYQv0bzs4xNwLaeag261pxgzGQSh4cQ1rEhYjcTJfFRP0SDlbhLONg0eSoLzrDd79PosjbltufA==" + "node_modules/@types/json-schema": { + "version": "7.0.11", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", + "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==" }, - "node_modules/colorette": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.4.0.tgz", - "integrity": "sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g==" + "node_modules/@types/katex": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/@types/katex/-/katex-0.11.1.tgz", + "integrity": "sha512-DUlIj2nk0YnJdlWgsFuVKcX27MLW0KbKmGVoUHmFr+74FYYNUDAaj9ZqTADvsbE8rfxuVmSFc7KczYn5Y09ozg==" }, - "node_modules/combine-promises": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/combine-promises/-/combine-promises-1.1.0.tgz", - "integrity": "sha512-ZI9jvcLDxqwaXEixOhArm3r7ReIivsXkpbyEWyeOhzz1QS0iSgBPnWvEqvIQtYyamGCYA88gFhmUrs9hrrQ0pg==", - "engines": { - "node": ">=10" - } + "node_modules/@types/lodash": { + "version": "4.14.182", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.182.tgz", + "integrity": "sha512-/THyiqyQAP9AfARo4pF+aCGcyiQ94tX/Is2I7HofNRqoYLgN1PBoOWu2/zTA5zMxzP5EFutMtWtGAFRKUe961Q==" }, - "node_modules/comma-separated-tokens": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-1.0.8.tgz", - "integrity": "sha512-GHuDRO12Sypu2cV70d1dkA2EUmXHgntrzbpvOB+Qy+49ypNfGgFQIC2fhhXbnyrJRynDCAARsT7Ou0M6hirpfw==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "node_modules/@types/mdast": { + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.10.tgz", + "integrity": "sha512-W864tg/Osz1+9f4lrGTZpCSO5/z4608eUp19tbozkq2HJK6i3z1kT0H9tlADXuYIb1YYOBByU4Jsqkk75q48qA==", + "dependencies": { + "@types/unist": "*" } }, - "node_modules/commander": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz", - "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==", - "engines": { - "node": ">= 6" - } + "node_modules/@types/mime": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", + "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==" }, - "node_modules/commondir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", - "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=" + "node_modules/@types/node": { + "version": "17.0.31", + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.31.tgz", + "integrity": "sha512-AR0x5HbXGqkEx9CadRH3EBYx/VkiUgZIhP4wvPn/+5KIsgpNoyFaRlVe0Zlx9gRtg8fA06a9tskE2MSN7TcG4Q==" }, - "node_modules/component-emitter": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", - "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==" + "node_modules/@types/parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==" }, - "node_modules/compressible": { - "version": "2.0.18", - "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", - "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", + "node_modules/@types/parse5": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/@types/parse5/-/parse5-5.0.3.tgz", + "integrity": "sha512-kUNnecmtkunAoQ3CnjmMkzNU/gtxG8guhi+Fk2U/kOpIKjIMKnXGp4IJCgQJrXSgMsWYimYG4TGjz/UzbGEBTw==" + }, + "node_modules/@types/prettier": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.6.0.tgz", + "integrity": "sha512-G/AdOadiZhnJp0jXCaBQU449W2h716OW/EoXeYkCytxKL06X1WCXB4DZpp8TpZ8eyIJVS1cw4lrlkkSYU21cDw==", + "dev": true + }, + "node_modules/@types/prop-types": { + "version": "15.7.5", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz", + "integrity": "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==" + }, + "node_modules/@types/q": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@types/q/-/q-1.5.5.tgz", + "integrity": "sha512-L28j2FcJfSZOnL1WBjDYp2vUHCeIFlyYI/53EwD/rKUBQ7MtUUfbQWiyKJGpcnv4/WgrhWsFKrcPstcAt/J0tQ==" + }, + "node_modules/@types/qs": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz", + "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==" + }, + "node_modules/@types/range-parser": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", + "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==" + }, + "node_modules/@types/react": { + "version": "17.0.44", + "resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.44.tgz", + "integrity": "sha512-Ye0nlw09GeMp2Suh8qoOv0odfgCoowfM/9MG6WeRD60Gq9wS90bdkdRtYbRkNhXOpG4H+YXGvj4wOWhAC0LJ1g==", "dependencies": { - "mime-db": ">= 1.43.0 < 2" - }, - "engines": { - "node": ">= 0.6" + "@types/prop-types": "*", + "@types/scheduler": "*", + "csstype": "^3.0.2" } }, - "node_modules/compression": { - "version": "1.7.4", - "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", - "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", + "node_modules/@types/react-dom": { + "version": "17.0.16", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-17.0.16.tgz", + "integrity": "sha512-DWcXf8EbMrO/gWnQU7Z88Ws/p16qxGpPyjTKTpmBSFKeE+HveVubqGO1CVK7FrwlWD5MuOcvh8gtd0/XO38NdQ==", + "dev": true, "dependencies": { - "accepts": "~1.3.5", - "bytes": "3.0.0", - "compressible": "~2.0.16", - "debug": "2.6.9", - "on-headers": "~1.0.2", - "safe-buffer": "5.1.2", - "vary": "~1.1.2" - }, - "engines": { - "node": ">= 0.8.0" + "@types/react": "^17" } }, - "node_modules/compression/node_modules/bytes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", - "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=", - "engines": { - "node": ">= 0.8" + "node_modules/@types/react-router": { + "version": "5.1.18", + "resolved": "https://registry.npmjs.org/@types/react-router/-/react-router-5.1.18.tgz", + "integrity": "sha512-YYknwy0D0iOwKQgz9v8nOzt2J6l4gouBmDnWqUUznltOTaon+r8US8ky8HvN0tXvc38U9m6z/t2RsVsnd1zM0g==", + "dependencies": { + "@types/history": "^4.7.11", + "@types/react": "*" } }, - "node_modules/compression/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "node_modules/@types/react-router-config": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/@types/react-router-config/-/react-router-config-5.0.6.tgz", + "integrity": "sha512-db1mx37a1EJDf1XeX8jJN7R3PZABmJQXR8r28yUjVMFSjkmnQo6X6pOEEmNl+Tp2gYQOGPdYbFIipBtdElZ3Yg==", "dependencies": { - "ms": "2.0.0" + "@types/history": "^4.7.11", + "@types/react": "*", + "@types/react-router": "*" } }, - "node_modules/compression/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + "node_modules/@types/react-router-dom": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/@types/react-router-dom/-/react-router-dom-5.3.3.tgz", + "integrity": "sha512-kpqnYK4wcdm5UaWI3fLcELopqLrHgLqNsdpHauzlQktfkHL3npOSwtj1Uz9oKBAzs7lFtVkV8j83voAz2D8fhw==", + "dependencies": { + "@types/history": "^4.7.11", + "@types/react": "*", + "@types/react-router": "*" + } }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + "node_modules/@types/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==" }, - "node_modules/configstore": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/configstore/-/configstore-5.0.1.tgz", - "integrity": "sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA==", + "node_modules/@types/sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@types/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-pSAff4IAxJjfAXUG6tFkO7dsSbTmf8CtUpfhhZ5VhkRpC4628tJhh3+V6H1E+/Gs9piSzYKT5yzHO5M4GG9jkw==", "dependencies": { - "dot-prop": "^5.2.0", - "graceful-fs": "^4.1.2", - "make-dir": "^3.0.0", - "unique-string": "^2.0.0", - "write-file-atomic": "^3.0.0", - "xdg-basedir": "^4.0.0" - }, - "engines": { - "node": ">=8" + "@types/node": "*" } }, - "node_modules/connect-history-api-fallback": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz", - "integrity": "sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg==", - "engines": { - "node": ">=0.8" + "node_modules/@types/scheduler": { + "version": "0.16.2", + "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz", + "integrity": "sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==" + }, + "node_modules/@types/serve-index": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.1.tgz", + "integrity": "sha512-d/Hs3nWDxNL2xAczmOVZNj92YZCS6RGxfBPjKzuu/XirCgXdpKEb88dYNbrYGint6IVWLNP+yonwVAuRC0T2Dg==", + "dependencies": { + "@types/express": "*" } }, - "node_modules/consola": { - "version": "2.15.3", - "resolved": "https://registry.npmjs.org/consola/-/consola-2.15.3.tgz", - "integrity": "sha512-9vAdYbHj6x2fLKC4+oPH0kFzY/orMZyG2Aj+kNylHxKGJ/Ed4dpNyAQYwJOdqO4zdM7XpVHmyejQDcQHrnuXbw==" + "node_modules/@types/serve-static": { + "version": "1.13.10", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.10.tgz", + "integrity": "sha512-nCkHGI4w7ZgAdNkrEu0bv+4xNV/XDqW+DydknebMOQwkpDGx8G+HTlj7R7ABI8i8nKxVw0wtKPi1D+lPOkh4YQ==", + "dependencies": { + "@types/mime": "^1", + "@types/node": "*" + } }, - "node_modules/console-browserify": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.2.0.tgz", - "integrity": "sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==" + "node_modules/@types/sinonjs__fake-timers": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.1.tgz", + "integrity": "sha512-0kSuKjAS0TrGLJ0M/+8MaFkGsQhZpB6pxOmvS3K8FYI72K//YmdfoW9X2qPsAKh1mkwxGD5zib9s1FIFed6E8g==", + "dev": true }, - "node_modules/console-control-strings": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" - }, - "node_modules/consolidated-events": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/consolidated-events/-/consolidated-events-2.0.2.tgz", - "integrity": "sha512-2/uRVMdRypf5z/TW/ncD/66l75P5hH2vM/GR8Jf8HLc2xnfJtmina6F6du8+v4Z2vTrMo7jC+W1tmEEuuELgkQ==" - }, - "node_modules/constants-browserify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", - "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=" + "node_modules/@types/sizzle": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.3.tgz", + "integrity": "sha512-JYM8x9EGF163bEyhdJBpR2QX1R5naCJHC8ucJylJ3w9/CVBaskdQ8WqBf8MmQrd1kRvp/a4TS8HJ+bxzR7ZJYQ==", + "dev": true }, - "node_modules/content-disposition": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", - "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", + "node_modules/@types/sockjs": { + "version": "0.3.33", + "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.33.tgz", + "integrity": "sha512-f0KEEe05NvUnat+boPTZ0dgaLZ4SfSouXUgv5noUiefG2ajgKjmETo9ZJyuqsl7dfl2aHlLJUiki6B4ZYldiiw==", "dependencies": { - "safe-buffer": "5.1.2" - }, - "engines": { - "node": ">= 0.6" + "@types/node": "*" } }, - "node_modules/content-type": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", - "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", - "engines": { - "node": ">= 0.6" - } + "node_modules/@types/stack-utils": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", + "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==", + "dev": true }, - "node_modules/convert-source-map": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz", - "integrity": "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==", + "node_modules/@types/testing-library__jest-dom": { + "version": "5.14.3", + "resolved": "https://registry.npmjs.org/@types/testing-library__jest-dom/-/testing-library__jest-dom-5.14.3.tgz", + "integrity": "sha512-oKZe+Mf4ioWlMuzVBaXQ9WDnEm1+umLx0InILg+yvZVBBDmzV5KfZyLrCvadtWcx8+916jLmHafcmqqffl+iIw==", + "dev": true, "dependencies": { - "safe-buffer": "~5.1.1" - } - }, - "node_modules/cookie": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", - "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==", - "engines": { - "node": ">= 0.6" + "@types/jest": "*" } }, - "node_modules/cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" + "node_modules/@types/unist": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.6.tgz", + "integrity": "sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ==" }, - "node_modules/copy-descriptor": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", - "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", - "engines": { - "node": ">=0.10.0" + "node_modules/@types/ws": { + "version": "8.5.3", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.3.tgz", + "integrity": "sha512-6YOoWjruKj1uLf3INHH7D3qTXwFfEsg1kf3c0uDdSBJwfa/llkwIjrAGV7j7mVgGNbzTQ3HiHKKDXl6bJPD97w==", + "dependencies": { + "@types/node": "*" } }, - "node_modules/copy-text-to-clipboard": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/copy-text-to-clipboard/-/copy-text-to-clipboard-3.0.1.tgz", - "integrity": "sha512-rvVsHrpFcL4F2P8ihsoLdFHmd404+CMg71S756oRSeQgqk51U3kicGdnvfkrxva0xXH92SjGS62B0XIJsbh+9Q==", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node_modules/@types/yargs": { + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", + "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", + "dev": true, + "dependencies": { + "@types/yargs-parser": "*" } }, - "node_modules/copy-webpack-plugin": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-9.0.1.tgz", - "integrity": "sha512-14gHKKdYIxF84jCEgPgYXCPpldbwpxxLbCmA7LReY7gvbaT555DgeBWBgBZM116tv/fO6RRJrsivBqRyRlukhw==", + "node_modules/@types/yargs-parser": { + "version": "21.0.0", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz", + "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==", + "dev": true + }, + "node_modules/@types/yauzl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.0.tgz", + "integrity": "sha512-Cn6WYCm0tXv8p6k+A8PvbDG763EDpBoTzHdA+Q/MF6H3sapGjCm9NzoaJncJS9tUKSuCoDs9XHxYYsQDgxR6kw==", + "dev": true, + "optional": true, "dependencies": { - "fast-glob": "^3.2.5", - "glob-parent": "^6.0.0", - "globby": "^11.0.3", - "normalize-path": "^3.0.0", - "p-limit": "^3.1.0", - "schema-utils": "^3.0.0", - "serialize-javascript": "^6.0.0" - }, - "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.1.0" + "@types/node": "*" } }, - "node_modules/copy-webpack-plugin/node_modules/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "node_modules/@webassemblyjs/ast": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.1.tgz", + "integrity": "sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw==", "dependencies": { - "is-glob": "^4.0.3" - }, - "engines": { - "node": ">=10.13.0" + "@webassemblyjs/helper-numbers": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1" } }, - "node_modules/core-js": { - "version": "3.18.3", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.18.3.tgz", - "integrity": "sha512-tReEhtMReZaPFVw7dajMx0vlsz3oOb8ajgPoHVYGxr8ErnZ6PcYEvvmjGmXlfpnxpkYSdOQttjB+MvVbCGfvLw==", - "hasInstallScript": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/core-js" - } + "node_modules/@webassemblyjs/floating-point-hex-parser": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz", + "integrity": "sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ==" }, - "node_modules/core-js-compat": { - "version": "3.18.3", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.18.3.tgz", - "integrity": "sha512-4zP6/y0a2RTHN5bRGT7PTq9lVt3WzvffTNjqnTKsXhkAYNDTkdCLOIfAdOLcQ/7TDdyRj3c+NeHe1NmF1eDScw==", + "node_modules/@webassemblyjs/helper-api-error": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz", + "integrity": "sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg==" + }, + "node_modules/@webassemblyjs/helper-buffer": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz", + "integrity": "sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA==" + }, + "node_modules/@webassemblyjs/helper-numbers": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz", + "integrity": "sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ==", "dependencies": { - "browserslist": "^4.17.3", - "semver": "7.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/core-js" + "@webassemblyjs/floating-point-hex-parser": "1.11.1", + "@webassemblyjs/helper-api-error": "1.11.1", + "@xtuc/long": "4.2.2" } }, - "node_modules/core-js-compat/node_modules/semver": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz", - "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==", - "bin": { - "semver": "bin/semver.js" - } + "node_modules/@webassemblyjs/helper-wasm-bytecode": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz", + "integrity": "sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q==" }, - "node_modules/core-js-pure": { - "version": "3.18.3", - "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.18.3.tgz", - "integrity": "sha512-qfskyO/KjtbYn09bn1IPkuhHl5PlJ6IzJ9s9sraJ1EqcuGyLGKzhSM1cY0zgyL9hx42eulQLZ6WaeK5ycJCkqw==", - "hasInstallScript": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/core-js" + "node_modules/@webassemblyjs/helper-wasm-section": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz", + "integrity": "sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg==", + "dependencies": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-buffer": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/wasm-gen": "1.11.1" } }, - "node_modules/core-util-is": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" - }, - "node_modules/cosmiconfig": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.1.tgz", - "integrity": "sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ==", + "node_modules/@webassemblyjs/ieee754": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz", + "integrity": "sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ==", "dependencies": { - "@types/parse-json": "^4.0.0", - "import-fresh": "^3.2.1", - "parse-json": "^5.0.0", - "path-type": "^4.0.0", - "yaml": "^1.10.0" - }, - "engines": { - "node": ">=10" + "@xtuc/ieee754": "^1.2.0" } }, - "node_modules/create-ecdh": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz", - "integrity": "sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==", + "node_modules/@webassemblyjs/leb128": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.1.tgz", + "integrity": "sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw==", "dependencies": { - "bn.js": "^4.1.0", - "elliptic": "^6.5.3" + "@xtuc/long": "4.2.2" } }, - "node_modules/create-ecdh/node_modules/bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + "node_modules/@webassemblyjs/utf8": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.1.tgz", + "integrity": "sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ==" }, - "node_modules/create-hash": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", - "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", + "node_modules/@webassemblyjs/wasm-edit": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz", + "integrity": "sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA==", "dependencies": { - "cipher-base": "^1.0.1", - "inherits": "^2.0.1", - "md5.js": "^1.3.4", - "ripemd160": "^2.0.1", - "sha.js": "^2.4.0" + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-buffer": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/helper-wasm-section": "1.11.1", + "@webassemblyjs/wasm-gen": "1.11.1", + "@webassemblyjs/wasm-opt": "1.11.1", + "@webassemblyjs/wasm-parser": "1.11.1", + "@webassemblyjs/wast-printer": "1.11.1" } }, - "node_modules/create-hmac": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", - "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", + "node_modules/@webassemblyjs/wasm-gen": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz", + "integrity": "sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA==", "dependencies": { - "cipher-base": "^1.0.3", - "create-hash": "^1.1.0", - "inherits": "^2.0.1", - "ripemd160": "^2.0.0", - "safe-buffer": "^5.0.1", - "sha.js": "^2.4.8" + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/ieee754": "1.11.1", + "@webassemblyjs/leb128": "1.11.1", + "@webassemblyjs/utf8": "1.11.1" } }, - "node_modules/cross-fetch": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.4.tgz", - "integrity": "sha512-1eAtFWdIubi6T4XPy6ei9iUFoKpUkIF971QLN8lIvvvwueI65+Nw5haMNKUwfJxabqlIIDODJKGrQ66gxC0PbQ==", + "node_modules/@webassemblyjs/wasm-opt": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz", + "integrity": "sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw==", "dependencies": { - "node-fetch": "2.6.1" + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-buffer": "1.11.1", + "@webassemblyjs/wasm-gen": "1.11.1", + "@webassemblyjs/wasm-parser": "1.11.1" } }, - "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" + "node_modules/@webassemblyjs/wasm-parser": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz", + "integrity": "sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA==", + "dependencies": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-api-error": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/ieee754": "1.11.1", + "@webassemblyjs/leb128": "1.11.1", + "@webassemblyjs/utf8": "1.11.1" } }, - "node_modules/crypto-browserify": { - "version": "3.12.0", - "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", - "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", + "node_modules/@webassemblyjs/wast-printer": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz", + "integrity": "sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg==", "dependencies": { - "browserify-cipher": "^1.0.0", - "browserify-sign": "^4.0.0", - "create-ecdh": "^4.0.0", - "create-hash": "^1.1.0", - "create-hmac": "^1.1.0", - "diffie-hellman": "^5.0.0", - "inherits": "^2.0.1", - "pbkdf2": "^3.0.3", - "public-encrypt": "^4.0.0", - "randombytes": "^2.0.0", - "randomfill": "^1.0.3" - }, - "engines": { - "node": "*" + "@webassemblyjs/ast": "1.11.1", + "@xtuc/long": "4.2.2" } }, - "node_modules/crypto-random-string": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", - "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==", - "engines": { - "node": ">=8" - } + "node_modules/@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==" }, - "node_modules/css-color-keywords": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/css-color-keywords/-/css-color-keywords-1.0.0.tgz", - "integrity": "sha1-/qJhbcZ2spYmhrOvjb2+GAskTgU=", - "engines": { - "node": ">=4" - } + "node_modules/@xtuc/long": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==" }, - "node_modules/css-color-names": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/css-color-names/-/css-color-names-1.0.1.tgz", - "integrity": "sha512-/loXYOch1qU1biStIFsHH8SxTmOseh1IJqFvy8IujXOm1h+QjUdDhkzOrR5HG8K8mlxREj0yfi8ewCHx0eMxzA==", - "engines": { - "node": "*" - } + "node_modules/abab": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz", + "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==", + "dev": true }, - "node_modules/css-declaration-sorter": { - "version": "6.1.3", - "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-6.1.3.tgz", - "integrity": "sha512-SvjQjNRZgh4ULK1LDJ2AduPKUKxIqmtU7ZAyi47BTV+M90Qvxr9AB6lKlLbDUfXqI9IQeYA8LbAsCZPpJEV3aA==", + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", "dependencies": { - "timsort": "^0.3.0" + "mime-types": "~2.1.34", + "negotiator": "0.6.3" }, "engines": { - "node": ">= 10" - }, - "peerDependencies": { - "postcss": "^8.0.9" + "node": ">= 0.6" } }, - "node_modules/css-loader": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-3.6.0.tgz", - "integrity": "sha512-M5lSukoWi1If8dhQAUCvj4H8vUt3vOnwbQBH9DdTm/s4Ym2B/3dPMtYZeJmq7Q3S3Pa+I94DcZ7pc9bP14cWIQ==", - "dev": true, - "dependencies": { - "camelcase": "^5.3.1", - "cssesc": "^3.0.0", - "icss-utils": "^4.1.1", - "loader-utils": "^1.2.3", - "normalize-path": "^3.0.0", - "postcss": "^7.0.32", - "postcss-modules-extract-imports": "^2.0.0", - "postcss-modules-local-by-default": "^3.0.2", - "postcss-modules-scope": "^2.2.0", - "postcss-modules-values": "^3.0.0", - "postcss-value-parser": "^4.1.0", - "schema-utils": "^2.7.0", - "semver": "^6.3.0" + "node_modules/acorn": { + "version": "8.7.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.1.tgz", + "integrity": "sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A==", + "bin": { + "acorn": "bin/acorn" }, "engines": { - "node": ">= 8.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^4.0.0 || ^5.0.0" + "node": ">=0.4.0" } }, - "node_modules/css-loader/node_modules/camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "node_modules/acorn-globals": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-6.0.0.tgz", + "integrity": "sha512-ZQl7LOWaF5ePqqcX4hLuv/bLXYQNfNWw2c0/yX/TsPRKamzHcTGQnlCjHT3TsmkOUVEPS3crCxiPfdzE/Trlhg==", "dev": true, - "engines": { - "node": ">=6" + "dependencies": { + "acorn": "^7.1.1", + "acorn-walk": "^7.1.1" } }, - "node_modules/css-loader/node_modules/icss-utils": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-4.1.1.tgz", - "integrity": "sha512-4aFq7wvWyMHKgxsH8QQtGpvbASCf+eM3wPRLI6R+MgAnTCZ6STYsRvttLvRWK0Nfif5piF394St3HeJDaljGPA==", + "node_modules/acorn-globals/node_modules/acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", "dev": true, - "dependencies": { - "postcss": "^7.0.14" + "bin": { + "acorn": "bin/acorn" }, "engines": { - "node": ">= 6" + "node": ">=0.4.0" } }, - "node_modules/css-loader/node_modules/json5": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", - "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", - "dev": true, - "dependencies": { - "minimist": "^1.2.0" - }, - "bin": { - "json5": "lib/cli.js" + "node_modules/acorn-import-assertions": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz", + "integrity": "sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==", + "peerDependencies": { + "acorn": "^8" } }, - "node_modules/css-loader/node_modules/loader-utils": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", - "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", + "node_modules/acorn-walk": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", + "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==", "dev": true, - "dependencies": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^1.0.1" - }, "engines": { - "node": ">=4.0.0" + "node": ">=0.4.0" } }, - "node_modules/css-loader/node_modules/picocolors": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", - "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", - "dev": true - }, - "node_modules/css-loader/node_modules/postcss": { - "version": "7.0.39", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", - "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", - "dev": true, - "dependencies": { - "picocolors": "^0.2.1", - "source-map": "^0.6.1" - }, + "node_modules/address": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/address/-/address-1.2.0.tgz", + "integrity": "sha512-tNEZYz5G/zYunxFm7sfhAxkXEuLj3K6BKwv6ZURlsF6yiUQ65z0Q2wZW9L5cPUl9ocofGvXOdFYbFHp0+6MOig==", "engines": { - "node": ">=6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" + "node": ">= 10.0.0" } }, - "node_modules/css-loader/node_modules/postcss-modules-extract-imports": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-2.0.0.tgz", - "integrity": "sha512-LaYLDNS4SG8Q5WAWqIJgdHPJrDDr/Lv775rMBFUbgjTz6j34lUznACHcdRWroPvXANP2Vj7yNK57vp9eFqzLWQ==", + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", "dev": true, "dependencies": { - "postcss": "^7.0.5" + "debug": "4" }, "engines": { - "node": ">= 6" + "node": ">= 6.0.0" } }, - "node_modules/css-loader/node_modules/postcss-modules-local-by-default": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-3.0.3.tgz", - "integrity": "sha512-e3xDq+LotiGesympRlKNgaJ0PCzoUIdpH0dj47iWAui/kyTgh3CiAr1qP54uodmJhl6p9rN6BoNcdEDVJx9RDw==", - "dev": true, + "node_modules/aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", "dependencies": { - "icss-utils": "^4.1.1", - "postcss": "^7.0.32", - "postcss-selector-parser": "^6.0.2", - "postcss-value-parser": "^4.1.0" + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" }, "engines": { - "node": ">= 6" + "node": ">=8" } }, - "node_modules/css-loader/node_modules/postcss-modules-scope": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-2.2.0.tgz", - "integrity": "sha512-YyEgsTMRpNd+HmyC7H/mh3y+MeFWevy7V1evVhJWewmMbjDHIbZbOXICC2y+m1xI1UVfIT1HMW/O04Hxyu9oXQ==", - "dev": true, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dependencies": { - "postcss": "^7.0.6", - "postcss-selector-parser": "^6.0.0" + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" }, - "engines": { - "node": ">= 6" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/css-loader/node_modules/postcss-modules-values": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-3.0.0.tgz", - "integrity": "sha512-1//E5jCBrZ9DmRX+zCtmQtRSV6PV42Ix7Bzj9GbwJceduuf7IqP8MgeTXuRDHOWj2m0VzZD5+roFWDuU8RQjcg==", - "dev": true, + "node_modules/ajv-formats": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", + "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", "dependencies": { - "icss-utils": "^4.0.0", - "postcss": "^7.0.6" + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } } }, - "node_modules/css-loader/node_modules/schema-utils": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz", - "integrity": "sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==", - "dev": true, + "node_modules/ajv-formats/node_modules/ajv": { + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz", + "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==", "dependencies": { - "@types/json-schema": "^7.0.5", - "ajv": "^6.12.4", - "ajv-keywords": "^3.5.2" - }, - "engines": { - "node": ">= 8.9.0" + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/css-loader/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true, - "bin": { - "semver": "bin/semver.js" + "node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "peerDependencies": { + "ajv": "^6.9.1" } }, - "node_modules/css-loader/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "engines": { - "node": ">=0.10.0" + "node_modules/ajv/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + }, + "node_modules/algoliasearch": { + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-4.13.0.tgz", + "integrity": "sha512-oHv4faI1Vl2s+YC0YquwkK/TsaJs79g2JFg5FDm2rKN12VItPTAeQ7hyJMHarOPPYuCnNC5kixbtcqvb21wchw==", + "dependencies": { + "@algolia/cache-browser-local-storage": "4.13.0", + "@algolia/cache-common": "4.13.0", + "@algolia/cache-in-memory": "4.13.0", + "@algolia/client-account": "4.13.0", + "@algolia/client-analytics": "4.13.0", + "@algolia/client-common": "4.13.0", + "@algolia/client-personalization": "4.13.0", + "@algolia/client-search": "4.13.0", + "@algolia/logger-common": "4.13.0", + "@algolia/logger-console": "4.13.0", + "@algolia/requester-browser-xhr": "4.13.0", + "@algolia/requester-common": "4.13.0", + "@algolia/requester-node-http": "4.13.0", + "@algolia/transporter": "4.13.0" } }, - "node_modules/css-minimizer-webpack-plugin": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/css-minimizer-webpack-plugin/-/css-minimizer-webpack-plugin-3.1.1.tgz", - "integrity": "sha512-KlB8l5uoNcf9F7i5kXnkxoqJGd2BXH4f0+Lj2vSWSmuvMLYO1kNsJ1KHSzeDW8e45/whgSOPcKVT/3JopkT8dg==", + "node_modules/algoliasearch-helper": { + "version": "3.8.2", + "resolved": "https://registry.npmjs.org/algoliasearch-helper/-/algoliasearch-helper-3.8.2.tgz", + "integrity": "sha512-AXxiF0zT9oYwl8ZBgU/eRXvfYhz7cBA5YrLPlw9inZHdaYF0QEya/f1Zp1mPYMXc1v6VkHwBq4pk6/vayBLICg==", "dependencies": { - "cssnano": "^5.0.6", - "jest-worker": "^27.0.2", - "p-limit": "^3.0.2", - "postcss": "^8.3.5", - "schema-utils": "^3.1.0", - "serialize-javascript": "^6.0.0", - "source-map": "^0.6.1" - }, - "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" + "@algolia/events": "^4.0.1" }, "peerDependencies": { - "webpack": "^5.0.0" - }, - "peerDependenciesMeta": { - "clean-css": { - "optional": true - }, - "csso": { - "optional": true - }, - "esbuild": { - "optional": true - } - } - }, - "node_modules/css-minimizer-webpack-plugin/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "engines": { - "node": ">=0.10.0" + "algoliasearch": ">= 3.1 < 5" } }, - "node_modules/css-select": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.1.3.tgz", - "integrity": "sha512-gT3wBNd9Nj49rAbmtFHj1cljIAOLYSX1nZ8CB7TBO3INYckygm5B7LISU/szY//YmdiSLbJvDLOx9VnMVpMBxA==", + "node_modules/ansi-align": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", + "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", "dependencies": { - "boolbase": "^1.0.0", - "css-what": "^5.0.0", - "domhandler": "^4.2.0", - "domutils": "^2.6.0", - "nth-check": "^2.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" + "string-width": "^4.1.0" } }, - "node_modules/css-select-base-adapter": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/css-select-base-adapter/-/css-select-base-adapter-0.1.1.tgz", - "integrity": "sha512-jQVeeRG70QI08vSTwf1jHxp74JoZsr2XSgETae8/xC8ovSnL2WF87GTLO86Sbwdt2lK4Umg4HnnwMO4YF3Ce7w==" - }, - "node_modules/css-to-react-native": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/css-to-react-native/-/css-to-react-native-3.0.0.tgz", - "integrity": "sha512-Ro1yETZA813eoyUp2GDBhG2j+YggidUmzO1/v9eYBKR2EHVEniE2MI/NqpTQ954BMpTPZFsGNPm46qFB9dpaPQ==", - "dependencies": { - "camelize": "^1.0.0", - "css-color-keywords": "^1.0.0", - "postcss-value-parser": "^4.0.2" - } + "node_modules/ansi-align/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, - "node_modules/css-tree": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz", - "integrity": "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==", + "node_modules/ansi-align/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dependencies": { - "mdn-data": "2.0.14", - "source-map": "^0.6.1" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" }, "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/css-tree/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/css-what": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-5.1.0.tgz", - "integrity": "sha512-arSMRWIIFY0hV8pIxZMEfmMI47Wj3R/aWpZDDxWYCPEiOMv6tfOrnpDtgxBYPEQD4V0Y/958+1TdC3iWTFcUPw==", - "engines": { - "node": ">= 6" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" + "node": ">=8" } }, - "node_modules/cssesc": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", - "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", - "bin": { - "cssesc": "bin/cssesc" - }, + "node_modules/ansi-colors": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", + "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", + "dev": true, "engines": { - "node": ">=4" + "node": ">=6" } }, - "node_modules/cssnano": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-5.0.8.tgz", - "integrity": "sha512-Lda7geZU0Yu+RZi2SGpjYuQz4HI4/1Y+BhdD0jL7NXAQ5larCzVn+PUGuZbDMYz904AXXCOgO5L1teSvgu7aFg==", + "node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, "dependencies": { - "cssnano-preset-default": "^5.1.4", - "is-resolvable": "^1.1.0", - "lilconfig": "^2.0.3", - "yaml": "^1.10.2" + "type-fest": "^0.21.3" }, "engines": { - "node": "^10 || ^12 || >=14.0" + "node": ">=8" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/cssnano" - }, - "peerDependencies": { - "postcss": "^8.2.15" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/cssnano-preset-advanced": { - "version": "5.1.4", - "resolved": "https://registry.npmjs.org/cssnano-preset-advanced/-/cssnano-preset-advanced-5.1.4.tgz", - "integrity": "sha512-pFtIM15OzryDk09RcK+bBBtwSl80+g/POTAf/sVPqPmnOAleK6vBkY5wTmPjqGyV5/UTPjEzWMtbOQ3Z0kCBXA==", - "dependencies": { - "autoprefixer": "^10.2.0", - "cssnano-preset-default": "^5.1.4", - "postcss-discard-unused": "^5.0.1", - "postcss-merge-idents": "^5.0.1", - "postcss-reduce-idents": "^5.0.1", - "postcss-zindex": "^5.0.1" - }, + "node_modules/ansi-escapes/node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true, "engines": { - "node": "^10 || ^12 || >=14.0" + "node": ">=10" }, - "peerDependencies": { - "postcss": "^8.2.15" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/cssnano-preset-default": { - "version": "5.1.4", - "resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-5.1.4.tgz", - "integrity": "sha512-sPpQNDQBI3R/QsYxQvfB4mXeEcWuw0wGtKtmS5eg8wudyStYMgKOQT39G07EbW1LB56AOYrinRS9f0ig4Y3MhQ==", - "dependencies": { - "css-declaration-sorter": "^6.0.3", - "cssnano-utils": "^2.0.1", - "postcss-calc": "^8.0.0", - "postcss-colormin": "^5.2.0", - "postcss-convert-values": "^5.0.1", - "postcss-discard-comments": "^5.0.1", - "postcss-discard-duplicates": "^5.0.1", - "postcss-discard-empty": "^5.0.1", - "postcss-discard-overridden": "^5.0.1", - "postcss-merge-longhand": "^5.0.2", - "postcss-merge-rules": "^5.0.2", - "postcss-minify-font-values": "^5.0.1", - "postcss-minify-gradients": "^5.0.2", - "postcss-minify-params": "^5.0.1", - "postcss-minify-selectors": "^5.1.0", - "postcss-normalize-charset": "^5.0.1", - "postcss-normalize-display-values": "^5.0.1", - "postcss-normalize-positions": "^5.0.1", - "postcss-normalize-repeat-style": "^5.0.1", - "postcss-normalize-string": "^5.0.1", - "postcss-normalize-timing-functions": "^5.0.1", - "postcss-normalize-unicode": "^5.0.1", - "postcss-normalize-url": "^5.0.2", - "postcss-normalize-whitespace": "^5.0.1", - "postcss-ordered-values": "^5.0.2", - "postcss-reduce-initial": "^5.0.1", - "postcss-reduce-transforms": "^5.0.1", - "postcss-svgo": "^5.0.2", - "postcss-unique-selectors": "^5.0.1" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" + "node_modules/ansi-html-community": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz", + "integrity": "sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==", + "engines": [ + "node >= 0.8.0" + ], + "bin": { + "ansi-html": "bin/ansi-html" } }, - "node_modules/cssnano-utils": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/cssnano-utils/-/cssnano-utils-2.0.1.tgz", - "integrity": "sha512-i8vLRZTnEH9ubIyfdZCAdIdgnHAUeQeByEeQ2I7oTilvP9oHO6RScpeq3GsFUVqeB8uZgOQ9pw8utofNn32hhQ==", + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" + "node": ">=8" } }, - "node_modules/csso": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/csso/-/csso-4.2.0.tgz", - "integrity": "sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA==", + "node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dependencies": { - "css-tree": "^1.1.2" + "color-convert": "^1.9.0" }, "engines": { - "node": ">=8.0.0" + "node": ">=4" } }, - "node_modules/debug": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", - "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "node_modules/any-base": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/any-base/-/any-base-1.1.0.tgz", + "integrity": "sha512-uMgjozySS8adZZYePpaWs8cxB9/kdzmpX6SgJZ+wbz1K5eYk5QMYDVJaZKhxyIHUdnnJkfR7SVgStgH7LkGUyg==" + }, + "node_modules/anymatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", + "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", "dependencies": { - "ms": "2.1.2" + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" }, "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } + "node": ">= 8" } }, - "node_modules/decamelize": { + "node_modules/aproba": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", - "engines": { - "node": ">=0.10.0" - } + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" }, - "node_modules/decko": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decko/-/decko-1.2.0.tgz", - "integrity": "sha1-/UPHNelnuAEzBohKVvvmZZlraBc=" + "node_modules/arch": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/arch/-/arch-2.2.0.tgz", + "integrity": "sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] }, - "node_modules/decode-uri-component": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", - "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", - "engines": { - "node": ">=0.10" + "node_modules/are-we-there-yet": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz", + "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==", + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" } }, - "node_modules/decompress-response": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", - "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", + "node_modules/are-we-there-yet/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "node_modules/are-we-there-yet/node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", "dependencies": { - "mimic-response": "^1.0.0" - }, - "engines": { - "node": ">=4" + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" } }, - "node_modules/deep-equal": { + "node_modules/are-we-there-yet/node_modules/string_decoder": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.1.tgz", - "integrity": "sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g==", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dependencies": { - "is-arguments": "^1.0.4", - "is-date-object": "^1.0.1", - "is-regex": "^1.0.4", - "object-is": "^1.0.1", - "object-keys": "^1.1.1", - "regexp.prototype.flags": "^1.2.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "safe-buffer": "~5.1.0" } }, - "node_modules/deep-extend": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", - "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "node_modules/arg": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.1.tgz", + "integrity": "sha512-e0hDa9H2Z9AwFkk2qDlwhoMYE4eToKarchkQHovNdLTCYMHZHeRjI71crOh+dio4K6u1IcwubQqo79Ga4CyAQA==" + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + }, + "node_modules/aria-query": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.0.0.tgz", + "integrity": "sha512-V+SM7AbUwJ+EBnB8+DXs0hPZHO0W6pqBcc0dW90OwtVG02PswOu/teuARoLQjdDOH+t9pJgGnW5/Qmouf3gPJg==", + "dev": true, "engines": { - "node": ">=4.0.0" + "node": ">=6.0" } }, - "node_modules/deepmerge": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", - "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==", + "node_modules/array-flatten": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz", + "integrity": "sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==" + }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, - "node_modules/default-gateway": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-4.2.0.tgz", - "integrity": "sha512-h6sMrVB1VMWVrW13mSc6ia/DwYYw5MN6+exNu1OaJeFac5aSAvwM7lZ0NVfTABuSkQelr4h5oebg3KB1XPdjgA==", + "node_modules/asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=" + }, + "node_modules/asn1": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", + "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", + "dev": true, "dependencies": { - "execa": "^1.0.0", - "ip-regex": "^2.1.0" - }, - "engines": { - "node": ">=6" + "safer-buffer": "~2.1.0" } }, - "node_modules/defer-to-connect": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz", - "integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==" + "node_modules/asn1.js": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", + "integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==", + "dependencies": { + "bn.js": "^4.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0", + "safer-buffer": "^2.1.0" + } }, - "node_modules/define-properties": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", - "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "node_modules/asn1.js/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + }, + "node_modules/assert": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/assert/-/assert-2.0.0.tgz", + "integrity": "sha512-se5Cd+js9dXJnu6Ag2JFc00t+HmHOen+8Q+L7O9zI0PqQXr20uk2J0XQqMxZEeo5U50o8Nvmmx7dZrl+Ufr35A==", "dependencies": { - "object-keys": "^1.0.12" - }, + "es6-object-assign": "^1.1.0", + "is-nan": "^1.2.1", + "object-is": "^1.0.1", + "util": "^0.12.0" + } + }, + "node_modules/assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", + "dev": true, "engines": { - "node": ">= 0.4" + "node": ">=0.8" } }, - "node_modules/define-property": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", - "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", - "dependencies": { - "is-descriptor": "^1.0.2", - "isobject": "^3.0.1" - }, + "node_modules/astral-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, - "node_modules/define-property/node_modules/is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "node_modules/async": { + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", + "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", "dependencies": { - "kind-of": "^6.0.0" - }, - "engines": { - "node": ">=0.10.0" + "lodash": "^4.17.14" } }, - "node_modules/define-property/node_modules/is-data-descriptor": { + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, + "node_modules/at-least-node": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dependencies": { - "kind-of": "^6.0.0" - }, + "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", + "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", "engines": { - "node": ">=0.10.0" + "node": ">= 4.0.0" } }, - "node_modules/define-property/node_modules/is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dependencies": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" + "node_modules/atob": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", + "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", + "dev": true, + "bin": { + "atob": "bin/atob.js" }, "engines": { - "node": ">=0.10.0" + "node": ">= 4.5.0" } }, - "node_modules/del": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/del/-/del-6.0.0.tgz", - "integrity": "sha512-1shh9DQ23L16oXSZKB2JxpL7iMy2E0S9d517ptA1P8iw0alkPtQcrKH7ru31rYtKwF499HkTu+DRzq3TCKDFRQ==", + "node_modules/autoprefixer": { + "version": "10.4.7", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.7.tgz", + "integrity": "sha512-ypHju4Y2Oav95SipEcCcI5J7CGPuvz8oat7sUtYj3ClK44bldfvtvcxK6IEK++7rqB7YchDGzweZIBG+SD0ZAA==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/autoprefixer" + } + ], "dependencies": { - "globby": "^11.0.1", - "graceful-fs": "^4.2.4", - "is-glob": "^4.0.1", - "is-path-cwd": "^2.2.0", - "is-path-inside": "^3.0.2", - "p-map": "^4.0.0", - "rimraf": "^3.0.2", - "slash": "^3.0.0" + "browserslist": "^4.20.3", + "caniuse-lite": "^1.0.30001335", + "fraction.js": "^4.2.0", + "normalize-range": "^0.1.2", + "picocolors": "^1.0.0", + "postcss-value-parser": "^4.2.0" + }, + "bin": { + "autoprefixer": "bin/autoprefixer" }, "engines": { - "node": ">=10" + "node": "^10 || ^12 || >=14" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "peerDependencies": { + "postcss": "^8.1.0" } }, - "node_modules/delegates": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=" + "node_modules/available-typed-arrays": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", + "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, - "node_modules/depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "node_modules/aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==", + "dev": true, "engines": { - "node": ">= 0.6" + "node": "*" } }, - "node_modules/des.js": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.1.tgz", - "integrity": "sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA==", + "node_modules/aws4": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz", + "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==", + "dev": true + }, + "node_modules/axios": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz", + "integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==", "dependencies": { - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0" + "follow-redirects": "^1.14.9", + "form-data": "^4.0.0" } }, - "node_modules/destroy": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", - "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" - }, - "node_modules/detab": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/detab/-/detab-2.0.4.tgz", - "integrity": "sha512-8zdsQA5bIkoRECvCrNKPla84lyoR7DSAyf7p0YgXzBO9PDJx8KntPUay7NS6yp+KdxdVtiE5SpHKtbp2ZQyA9g==", + "node_modules/axios/node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", "dependencies": { - "repeat-string": "^1.5.4" + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "engines": { + "node": ">= 6" } }, - "node_modules/detect-libc": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", - "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=", - "bin": { - "detect-libc": "bin/detect-libc.js" + "node_modules/babel-jest": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-27.5.1.tgz", + "integrity": "sha512-cdQ5dXjGRd0IBRATiQ4mZGlGlRE8kJpjPOixdNRdT+m3UcNqmYWN6rK6nvtXYfY3D76cb8s/O1Ss8ea24PIwcg==", + "dev": true, + "dependencies": { + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/babel__core": "^7.1.14", + "babel-plugin-istanbul": "^6.1.1", + "babel-preset-jest": "^27.5.1", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "slash": "^3.0.0" }, "engines": { - "node": ">=0.10" + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.8.0" } }, - "node_modules/detect-node": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", - "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==" - }, - "node_modules/detect-port": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/detect-port/-/detect-port-1.3.0.tgz", - "integrity": "sha512-E+B1gzkl2gqxt1IhUzwjrxBKRqx1UzC3WLONHinn8S3T6lwV/agVCyitiFOsGJ/eYuEUBvD71MZHy3Pv1G9doQ==", + "node_modules/babel-jest/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, "dependencies": { - "address": "^1.0.1", - "debug": "^2.6.0" - }, - "bin": { - "detect": "bin/detect-port", - "detect-port": "bin/detect-port" + "color-convert": "^2.0.1" }, "engines": { - "node": ">= 4.2.1" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/detect-port/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "node_modules/babel-jest/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "dependencies": { - "ms": "2.0.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/detect-port/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - }, - "node_modules/diffie-hellman": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", - "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", + "node_modules/babel-jest/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, "dependencies": { - "bn.js": "^4.1.0", - "miller-rabin": "^4.0.0", - "randombytes": "^2.0.0" + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" } }, - "node_modules/diffie-hellman/node_modules/bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + "node_modules/babel-jest/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true }, - "node_modules/dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "node_modules/babel-jest/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-jest/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, "dependencies": { - "path-type": "^4.0.0" + "has-flag": "^4.0.0" }, "engines": { "node": ">=8" } }, - "node_modules/dns-equal": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz", - "integrity": "sha1-s55/HabrCnW6nBcySzR1PEfgZU0=" - }, - "node_modules/dns-packet": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-1.3.4.tgz", - "integrity": "sha512-BQ6F4vycLXBvdrJZ6S3gZewt6rcrks9KBgM9vrhW+knGRqc8uEdT7fuCwloc7nny5xNoMJ17HGH0R/6fpo8ECA==", + "node_modules/babel-loader": { + "version": "8.2.5", + "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.2.5.tgz", + "integrity": "sha512-OSiFfH89LrEMiWd4pLNqGz4CwJDtbs2ZVc+iGu2HrkRfPxId9F2anQj38IxWpmRfsUY0aBZYi1EFcd3mhtRMLQ==", "dependencies": { - "ip": "^1.1.0", - "safe-buffer": "^5.0.1" + "find-cache-dir": "^3.3.1", + "loader-utils": "^2.0.0", + "make-dir": "^3.1.0", + "schema-utils": "^2.6.5" + }, + "engines": { + "node": ">= 8.9" + }, + "peerDependencies": { + "@babel/core": "^7.0.0", + "webpack": ">=2" } }, - "node_modules/dns-txt": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/dns-txt/-/dns-txt-2.0.2.tgz", - "integrity": "sha1-uR2Ab10nGI5Ks+fRB9iBocxGQrY=", + "node_modules/babel-plugin-apply-mdx-type-prop": { + "version": "1.6.22", + "resolved": "https://registry.npmjs.org/babel-plugin-apply-mdx-type-prop/-/babel-plugin-apply-mdx-type-prop-1.6.22.tgz", + "integrity": "sha512-VefL+8o+F/DfK24lPZMtJctrCVOfgbqLAGZSkxwhazQv4VxPg3Za/i40fu22KR2m8eEda+IfSOlPLUSIiLcnCQ==", "dependencies": { - "buffer-indexof": "^1.0.0" + "@babel/helper-plugin-utils": "7.10.4", + "@mdx-js/util": "1.6.22" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + }, + "peerDependencies": { + "@babel/core": "^7.11.6" } }, - "node_modules/dom-converter": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz", - "integrity": "sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==", + "node_modules/babel-plugin-apply-mdx-type-prop/node_modules/@babel/helper-plugin-utils": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz", + "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==" + }, + "node_modules/babel-plugin-dynamic-import-node": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.0.tgz", + "integrity": "sha512-o6qFkpeQEBxcqt0XYlWzAVxNCSCZdUgcR8IRlhD/8DylxjjO4foPcvTW0GGKa/cVt3rvxZ7o5ippJ+/0nvLhlQ==", "dependencies": { - "utila": "~0.4" + "object.assign": "^4.1.0" } }, - "node_modules/dom-serializer": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.3.2.tgz", - "integrity": "sha512-5c54Bk5Dw4qAxNOI1pFEizPSjVsx5+bpJKmL2kPn8JhBUq2q09tTCa3mjijun2NfK78NMouDYNMBkOrPZiS+ig==", + "node_modules/babel-plugin-extract-import-names": { + "version": "1.6.22", + "resolved": "https://registry.npmjs.org/babel-plugin-extract-import-names/-/babel-plugin-extract-import-names-1.6.22.tgz", + "integrity": "sha512-yJ9BsJaISua7d8zNT7oRG1ZLBJCIdZ4PZqmH8qa9N5AK01ifk3fnkc98AXhtzE7UkfCsEumvoQWgoYLhOnJ7jQ==", "dependencies": { - "domelementtype": "^2.0.1", - "domhandler": "^4.2.0", - "entities": "^2.0.0" + "@babel/helper-plugin-utils": "7.10.4" }, "funding": { - "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/dom-walk": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.2.tgz", - "integrity": "sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w==" + "node_modules/babel-plugin-extract-import-names/node_modules/@babel/helper-plugin-utils": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz", + "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==" }, - "node_modules/domain-browser": { - "version": "4.22.0", - "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-4.22.0.tgz", - "integrity": "sha512-IGBwjF7tNk3cwypFNH/7bfzBcgSCbaMOD3GsaY1AU/JRrnHnYgEM0+9kQt52iZxjNsjBtJYtao146V+f8jFZNw==", - "engines": { - "node": ">=10" + "node_modules/babel-plugin-istanbul": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", + "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^5.0.4", + "test-exclude": "^6.0.0" }, - "funding": { - "url": "https://bevry.me/fund" + "engines": { + "node": ">=8" } }, - "node_modules/domelementtype": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz", - "integrity": "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ] - }, - "node_modules/domhandler": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.2.2.tgz", - "integrity": "sha512-PzE9aBMsdZO8TK4BnuJwH0QT41wgMbRzuZrHUcpYncEjmQazq8QEaBWgLG7ZyC/DAZKEgglpIA6j4Qn/HmxS3w==", + "node_modules/babel-plugin-jest-hoist": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-27.5.1.tgz", + "integrity": "sha512-50wCwD5EMNW4aRpOwtqzyZHIewTYNxLA4nhB+09d8BIssfNfzBRhkBIHiaPv1Si226TQSvp8gxAJm2iY2qs2hQ==", + "dev": true, "dependencies": { - "domelementtype": "^2.2.0" + "@babel/template": "^7.3.3", + "@babel/types": "^7.3.3", + "@types/babel__core": "^7.0.0", + "@types/babel__traverse": "^7.0.6" }, "engines": { - "node": ">= 4" + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/babel-plugin-polyfill-corejs2": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.1.tgz", + "integrity": "sha512-v7/T6EQcNfVLfcN2X8Lulb7DjprieyLWJK/zOWH5DUYcAgex9sP3h25Q+DLsX9TloXe3y1O8l2q2Jv9q8UVB9w==", + "dependencies": { + "@babel/compat-data": "^7.13.11", + "@babel/helper-define-polyfill-provider": "^0.3.1", + "semver": "^6.1.1" }, - "funding": { - "url": "https://github.com/fb55/domhandler?sponsor=1" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/dompurify": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-2.3.3.tgz", - "integrity": "sha512-dqnqRkPMAjOZE0FogZ+ceJNM2dZ3V/yNOuFB7+39qpO93hHhfRpHw3heYQC7DPK9FqbQTfBKUJhiSfz4MvXYwg==" + "node_modules/babel-plugin-polyfill-corejs2/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "bin": { + "semver": "bin/semver.js" + } }, - "node_modules/domutils": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", - "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", + "node_modules/babel-plugin-polyfill-corejs3": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.5.2.tgz", + "integrity": "sha512-G3uJih0XWiID451fpeFaYGVuxHEjzKTHtc9uGFEjR6hHrvNzeS/PX+LLLcetJcytsB5m4j+K3o/EpXJNb/5IEQ==", "dependencies": { - "dom-serializer": "^1.0.1", - "domelementtype": "^2.2.0", - "domhandler": "^4.2.0" + "@babel/helper-define-polyfill-provider": "^0.3.1", + "core-js-compat": "^3.21.0" }, - "funding": { - "url": "https://github.com/fb55/domutils?sponsor=1" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/dot-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", - "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", + "node_modules/babel-plugin-polyfill-regenerator": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.3.1.tgz", + "integrity": "sha512-Y2B06tvgHYt1x0yz17jGkGeeMr5FeKUu+ASJ+N6nB5lQ8Dapfg42i0OVrf8PNGJ3zKL4A23snMi1IRwrqqND7A==", "dependencies": { - "no-case": "^3.0.4", - "tslib": "^2.0.3" + "@babel/helper-define-polyfill-provider": "^0.3.1" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/dot-prop": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", - "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", + "node_modules/babel-plugin-styled-components": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/babel-plugin-styled-components/-/babel-plugin-styled-components-2.0.7.tgz", + "integrity": "sha512-i7YhvPgVqRKfoQ66toiZ06jPNA3p6ierpfUuEWxNF+fV27Uv5gxBkf8KZLHUCc1nFA9j6+80pYoIpqCeyW3/bA==", "dependencies": { - "is-obj": "^2.0.0" + "@babel/helper-annotate-as-pure": "^7.16.0", + "@babel/helper-module-imports": "^7.16.0", + "babel-plugin-syntax-jsx": "^6.18.0", + "lodash": "^4.17.11", + "picomatch": "^2.3.0" }, - "engines": { - "node": ">=8" + "peerDependencies": { + "styled-components": ">= 2" } }, - "node_modules/duplexer": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", - "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==" - }, - "node_modules/duplexer3": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", - "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=" - }, - "node_modules/ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" + "node_modules/babel-plugin-syntax-jsx": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz", + "integrity": "sha1-CvMqmm4Tyno/1QaeYtew9Y0NiUY=" }, - "node_modules/electron-to-chromium": { - "version": "1.3.867", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.867.tgz", - "integrity": "sha512-WbTXOv7hsLhjJyl7jBfDkioaY++iVVZomZ4dU6TMe/SzucV6mUAs2VZn/AehBwuZMiNEQDaPuTGn22YK5o+aDw==" + "node_modules/babel-preset-current-node-syntax": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz", + "integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==", + "dev": true, + "dependencies": { + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-bigint": "^7.8.3", + "@babel/plugin-syntax-class-properties": "^7.8.3", + "@babel/plugin-syntax-import-meta": "^7.8.3", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.8.3", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.8.3", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-top-level-await": "^7.8.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } }, - "node_modules/elliptic": { - "version": "6.5.4", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", - "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==", + "node_modules/babel-preset-jest": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-27.5.1.tgz", + "integrity": "sha512-Nptf2FzlPCWYuJg41HBqXVT8ym6bXOevuCTbhxlUpjwtysGaIWFvDEjp4y+G7fl13FgOdjs7P/DmErqH7da0Ag==", + "dev": true, "dependencies": { - "bn.js": "^4.11.9", - "brorand": "^1.1.0", - "hash.js": "^1.0.0", - "hmac-drbg": "^1.0.1", - "inherits": "^2.0.4", - "minimalistic-assert": "^1.0.1", - "minimalistic-crypto-utils": "^1.0.1" - } - }, - "node_modules/elliptic/node_modules/bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" - }, - "node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" - }, - "node_modules/emojis-list": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", - "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", + "babel-plugin-jest-hoist": "^27.5.1", + "babel-preset-current-node-syntax": "^1.0.0" + }, "engines": { - "node": ">= 4" + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "node_modules/emoticon": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/emoticon/-/emoticon-3.2.0.tgz", - "integrity": "sha512-SNujglcLTTg+lDAcApPNgEdudaqQFiAbJCqzjNxJkvN9vAwCGi0uu8IUVvx+f16h+V44KCY6Y2yboroc9pilHg==", + "node_modules/bail": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/bail/-/bail-1.0.5.tgz", + "integrity": "sha512-xFbRxM1tahm08yHBP16MMjVUAvDaBMD38zsM9EMAUN61omwLmKlOpB/Zku5QkjZ8TZ4vn53pj+t518cH0S03RQ==", "funding": { "type": "github", "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/encodeurl": { + "node_modules/balanced-match": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", - "engines": { - "node": ">= 0.8" - } + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, - "node_modules/end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "node_modules/base16": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/base16/-/base16-1.0.0.tgz", + "integrity": "sha1-4pf2DX7BAUp6lxo568ipjAtoHnA=" + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/batch": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", + "integrity": "sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY=" + }, + "node_modules/bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", + "dev": true, "dependencies": { - "once": "^1.4.0" + "tweetnacl": "^0.14.3" } }, - "node_modules/enhanced-resolve": { - "version": "5.8.3", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.8.3.tgz", - "integrity": "sha512-EGAbGvH7j7Xt2nc0E7D99La1OiEs8LnyimkRgwExpUMScN6O+3x9tIWs7PLQZVNx4YD+00skHXPXi1yQHpAmZA==", - "dependencies": { - "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" - }, + "node_modules/big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", "engines": { - "node": ">=10.13.0" + "node": "*" } }, - "node_modules/entities": { + "node_modules/binary-extensions": { "version": "2.2.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", - "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "engines": { + "node": ">=8" } }, - "node_modules/errno": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz", - "integrity": "sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==", + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", "dependencies": { - "prr": "~1.0.1" - }, - "bin": { - "errno": "cli.js" + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" } }, - "node_modules/error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "node_modules/bl/node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], "dependencies": { - "is-arrayish": "^0.2.1" + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" } }, - "node_modules/es-abstract": { - "version": "1.19.1", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.19.1.tgz", - "integrity": "sha512-2vJ6tjA/UfqLm2MPs7jxVybLoB8i1t1Jd9R3kISld20sIxPcTbLuggQOUxeWeAvIUkduv/CfMjuh4WmiXr2v9w==", - "dependencies": { - "call-bind": "^1.0.2", - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "get-intrinsic": "^1.1.1", - "get-symbol-description": "^1.0.0", - "has": "^1.0.3", - "has-symbols": "^1.0.2", - "internal-slot": "^1.0.3", - "is-callable": "^1.2.4", - "is-negative-zero": "^2.0.1", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.1", - "is-string": "^1.0.7", - "is-weakref": "^1.0.1", - "object-inspect": "^1.11.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.2", - "string.prototype.trimend": "^1.0.4", - "string.prototype.trimstart": "^1.0.4", - "unbox-primitive": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } + "node_modules/blob-util": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/blob-util/-/blob-util-2.0.2.tgz", + "integrity": "sha512-T7JQa+zsXXEa6/8ZhHcQEW1UFfVM49Ts65uBkFL6fz2QmrElqmbajIDJvuA0tEhRe5eIjpV9ZF+0RfZR9voJFQ==", + "dev": true }, - "node_modules/es-module-lexer": { - "version": "0.9.3", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.9.3.tgz", - "integrity": "sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ==" + "node_modules/bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" }, - "node_modules/es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "node_modules/bmp-js": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/bmp-js/-/bmp-js-0.1.0.tgz", + "integrity": "sha1-4Fpj95amwf8l9Hcex62twUjAcjM=" + }, + "node_modules/bn.js": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.0.tgz", + "integrity": "sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw==" + }, + "node_modules/body-parser": { + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.0.tgz", + "integrity": "sha512-DfJ+q6EPcGKZD1QWUjSpqp+Q7bDQTsQIF4zfUAtZ6qk+H/3/QRhg9CEp39ss+/T2vw0+HaidC0ecJj/DRLIaKg==", "dependencies": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" + "bytes": "3.1.2", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.10.3", + "raw-body": "2.5.1", + "type-is": "~1.6.18", + "unpipe": "1.0.0" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" } }, - "node_modules/es6-object-assign": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/es6-object-assign/-/es6-object-assign-1.1.0.tgz", - "integrity": "sha1-wsNYJlYkfDnqEHyx5mUrb58kUjw=" - }, - "node_modules/es6-promise": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.3.1.tgz", - "integrity": "sha1-oIzd6EzNvzTQJ6FFG8kdS80ophM=" - }, - "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "node_modules/body-parser/node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", "engines": { - "node": ">=6" + "node": ">= 0.8" } }, - "node_modules/escape-goat": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-2.1.1.tgz", - "integrity": "sha512-8/uIhbG12Csjy2JEW7D9pHbreaVaS/OpN3ycnyvElTdwM5n6GY6W6e2IPemfvGZeUMqZ9A/3GqIZMgKnBhAw/Q==", - "engines": { - "node": ">=8" + "node_modules/body-parser/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" } }, - "node_modules/escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" + "node_modules/body-parser/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, - "node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "engines": { - "node": ">=0.8.0" + "node_modules/bonjour-service": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.0.12.tgz", + "integrity": "sha512-pMmguXYCu63Ug37DluMKEHdxc+aaIf/ay4YbF8Gxtba+9d3u+rmEWy61VK3Z3hp8Rskok3BunHYnG0dUHAsblw==", + "dependencies": { + "array-flatten": "^2.1.2", + "dns-equal": "^1.0.0", + "fast-deep-equal": "^3.1.3", + "multicast-dns": "^7.2.4" } }, - "node_modules/eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=" + }, + "node_modules/boxen": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-6.2.1.tgz", + "integrity": "sha512-H4PEsJXfFI/Pt8sjDWbHlQPx4zL/bvSQjcilJmaulGt5mLDorHOHpmdXAJcBcmru7PhYSp/cDMWRko4ZUMFkSw==", "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" + "ansi-align": "^3.0.1", + "camelcase": "^6.2.0", + "chalk": "^4.1.2", + "cli-boxes": "^3.0.0", + "string-width": "^5.0.1", + "type-fest": "^2.5.0", + "widest-line": "^4.0.1", + "wrap-ansi": "^8.0.1" }, "engines": { - "node": ">=8.0.0" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/esrecurse": { + "node_modules/boxen/node_modules/ansi-styles": { "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dependencies": { - "estraverse": "^5.2.0" + "color-convert": "^2.0.1" }, "engines": { - "node": ">=4.0" - } - }, - "node_modules/esrecurse/node_modules/estraverse": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", - "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/eta": { - "version": "1.12.3", - "resolved": "https://registry.npmjs.org/eta/-/eta-1.12.3.tgz", - "integrity": "sha512-qHixwbDLtekO/d51Yr4glcaUJCIjGVJyTzuqV4GPlgZo1YpgOKG+avQynErZIYrfM6JIJdtiG2Kox8tbb+DoGg==", - "engines": { - "node": ">=6.0.0" + "node": ">=8" }, "funding": { - "url": "https://github.com/eta-dev/eta?sponsor=1" + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", + "node_modules/boxen/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, "engines": { - "node": ">= 0.6" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/eval": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/eval/-/eval-0.1.6.tgz", - "integrity": "sha512-o0XUw+5OGkXw4pJZzQoXUk+H87DHuC+7ZE//oSrRGtatTmr12oTnLfg6QOq9DyTt0c/p4TwzgmkKrBzWTSizyQ==", + "node_modules/boxen/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dependencies": { - "require-like": ">= 0.1.1" + "color-name": "~1.1.4" }, "engines": { - "node": ">= 0.8" + "node": ">=7.0.0" } }, - "node_modules/eventemitter3": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", - "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==" + "node_modules/boxen/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, - "node_modules/events": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "node_modules/boxen/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "engines": { - "node": ">=0.8.x" + "node": ">=8" } }, - "node_modules/eventsource": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-1.1.0.tgz", - "integrity": "sha512-VSJjT5oCNrFvCS6igjzPAt5hBzQ2qPBFIbJ03zLI9SE0mxwZpMw6BfJrbFHm1a141AavMEB8JHmBhWAd66PfCg==", + "node_modules/boxen/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dependencies": { - "original": "^1.0.0" + "has-flag": "^4.0.0" }, "engines": { - "node": ">=0.12.0" + "node": ">=8" } }, - "node_modules/evp_bytestokey": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", - "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dependencies": { - "md5.js": "^1.3.4", - "safe-buffer": "^5.1.1" - } - }, - "node_modules/execa": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", - "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", - "dependencies": { - "cross-spawn": "^6.0.0", - "get-stream": "^4.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" - }, - "engines": { - "node": ">=6" + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "node_modules/execa/node_modules/cross-spawn": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", - "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", "dependencies": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" + "fill-range": "^7.0.1" }, "engines": { - "node": ">=4.8" + "node": ">=8" } }, - "node_modules/execa/node_modules/path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", - "engines": { - "node": ">=4" - } + "node_modules/brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=" }, - "node_modules/execa/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "bin": { - "semver": "bin/semver" - } + "node_modules/browser-process-hrtime": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz", + "integrity": "sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==", + "dev": true }, - "node_modules/execa/node_modules/shebang-command": { + "node_modules/browserify-aes": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", + "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", "dependencies": { - "shebang-regex": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" + "buffer-xor": "^1.0.3", + "cipher-base": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.3", + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" } }, - "node_modules/execa/node_modules/shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", - "engines": { - "node": ">=0.10.0" + "node_modules/browserify-cipher": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", + "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", + "dependencies": { + "browserify-aes": "^1.0.4", + "browserify-des": "^1.0.0", + "evp_bytestokey": "^1.0.0" } }, - "node_modules/execa/node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "node_modules/browserify-des": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", + "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "which": "bin/which" + "cipher-base": "^1.0.1", + "des.js": "^1.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" } }, - "node_modules/exif-parser": { - "version": "0.1.12", - "resolved": "https://registry.npmjs.org/exif-parser/-/exif-parser-0.1.12.tgz", - "integrity": "sha1-WKnS1ywCwfbwKg70qRZicrd2CSI=" + "node_modules/browserify-rsa": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.1.0.tgz", + "integrity": "sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog==", + "dependencies": { + "bn.js": "^5.0.0", + "randombytes": "^2.0.1" + } }, - "node_modules/expand-brackets": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", - "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "node_modules/browserify-sign": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.1.tgz", + "integrity": "sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg==", "dependencies": { - "debug": "^2.3.3", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "posix-character-classes": "^0.1.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" + "bn.js": "^5.1.1", + "browserify-rsa": "^4.0.1", + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "elliptic": "^6.5.3", + "inherits": "^2.0.4", + "parse-asn1": "^5.1.5", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" } }, - "node_modules/expand-brackets/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "node_modules/browserify-sign/node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/browserify-zlib": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", + "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", "dependencies": { - "ms": "2.0.0" + "pako": "~1.0.5" } }, - "node_modules/expand-brackets/node_modules/define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "node_modules/browserslist": { + "version": "4.20.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.20.3.tgz", + "integrity": "sha512-NBhymBQl1zM0Y5dQT/O+xiLP9/rzOIQdKM/eMJBAq7yBgaB6krIYLGejrwVYnSHZdqjscB1SPuAjHwxjvN6Wdg==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + } + ], "dependencies": { - "is-descriptor": "^0.1.0" + "caniuse-lite": "^1.0.30001332", + "electron-to-chromium": "^1.4.118", + "escalade": "^3.1.1", + "node-releases": "^2.0.3", + "picocolors": "^1.0.0" + }, + "bin": { + "browserslist": "cli.js" }, "engines": { - "node": ">=0.10.0" + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" } }, - "node_modules/expand-brackets/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - }, - "node_modules/expand-template": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", - "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", - "engines": { - "node": ">=6" + "node_modules/bser": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", + "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", + "dev": true, + "dependencies": { + "node-int64": "^0.4.0" } }, - "node_modules/express": { - "version": "4.17.1", - "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", - "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", + "node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], "dependencies": { - "accepts": "~1.3.7", - "array-flatten": "1.1.1", - "body-parser": "1.19.0", - "content-disposition": "0.5.3", - "content-type": "~1.0.4", - "cookie": "0.4.0", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "~1.1.2", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "~1.1.2", - "fresh": "0.5.2", - "merge-descriptors": "1.0.1", - "methods": "~1.1.2", - "on-finished": "~2.3.0", - "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", - "proxy-addr": "~2.0.5", - "qs": "6.7.0", - "range-parser": "~1.2.1", - "safe-buffer": "5.1.2", - "send": "0.17.1", - "serve-static": "1.14.1", - "setprototypeof": "1.1.1", - "statuses": "~1.5.0", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" - }, + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", + "dev": true, "engines": { - "node": ">= 0.10.0" + "node": "*" } }, - "node_modules/express/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dependencies": { - "ms": "2.0.0" + "node_modules/buffer-equal": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-0.0.1.tgz", + "integrity": "sha1-kbx0sR6kBbyRa8aqkI+q+ltKrEs=", + "engines": { + "node": ">=0.4.0" } }, - "node_modules/express/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" }, - "node_modules/extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + "node_modules/buffer-xor": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", + "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=" }, - "node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dependencies": { - "is-extendable": "^0.1.0" - }, + "node_modules/builtin-status-codes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", + "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=" + }, + "node_modules/bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=", "engines": { - "node": ">=0.10.0" + "node": ">= 0.8" } }, - "node_modules/extglob": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "node_modules/cacheable-request": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", + "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==", "dependencies": { - "array-unique": "^0.3.2", - "define-property": "^1.0.0", - "expand-brackets": "^2.1.4", - "extend-shallow": "^2.0.1", - "fragment-cache": "^0.2.1", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^3.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^4.1.0", + "responselike": "^1.0.2" }, "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, - "node_modules/extglob/node_modules/define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "node_modules/cacheable-request/node_modules/get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", "dependencies": { - "is-descriptor": "^1.0.0" + "pump": "^3.0.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/extglob/node_modules/is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dependencies": { - "kind-of": "^6.0.0" - }, + "node_modules/cacheable-request/node_modules/lowercase-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, - "node_modules/extglob/node_modules/is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dependencies": { - "kind-of": "^6.0.0" - }, + "node_modules/cacheable-request/node_modules/normalize-url": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.1.tgz", + "integrity": "sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==", "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, - "node_modules/extglob/node_modules/is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dependencies": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - }, + "node_modules/cachedir": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/cachedir/-/cachedir-2.3.0.tgz", + "integrity": "sha512-A+Fezp4zxnit6FanDmv9EqXNAi3vt9DWp51/71UEhXukb7QUuvtv9344h91dyAxuTLoSYJFU299qzR3tzwPAhw==", + "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">=6" } }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" - }, - "node_modules/fast-glob": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.7.tgz", - "integrity": "sha512-rYGMRwip6lUMvYD3BTScMwT1HtAs2d71SMv66Vrxs0IekGZEjhM0pcMfjQPnknBt2zeCwQMEupiN02ZP4DiT1Q==", + "node_modules/call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" }, - "engines": { - "node": ">=8" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" - }, - "node_modules/fast-safe-stringify": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", - "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==" + "node_modules/call-me-maybe": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.1.tgz", + "integrity": "sha1-JtII6onje1y95gJQoV8DHBak1ms=" }, - "node_modules/fast-url-parser": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/fast-url-parser/-/fast-url-parser-1.1.3.tgz", - "integrity": "sha1-9K8+qfNNiicc9YrSs3WfQx8LMY0=", - "dependencies": { - "punycode": "^1.3.2" + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "engines": { + "node": ">=6" } }, - "node_modules/fast-url-parser/node_modules/punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" - }, - "node_modules/fastq": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", - "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", + "node_modules/camel-case": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz", + "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==", "dependencies": { - "reusify": "^1.0.4" + "pascal-case": "^3.1.2", + "tslib": "^2.0.3" } }, - "node_modules/faye-websocket": { - "version": "0.11.4", - "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz", - "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==", - "dependencies": { - "websocket-driver": ">=0.5.1" + "node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "engines": { + "node": ">=10" }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/camelcase-css": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", + "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", "engines": { - "node": ">=0.8.0" + "node": ">= 6" } }, - "node_modules/fbemitter": { + "node_modules/camelize": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/camelize/-/camelize-1.0.0.tgz", + "integrity": "sha1-FkpUg+Yw+kMh5a8HAg5TGDGyYJs=" + }, + "node_modules/caniuse-api": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/fbemitter/-/fbemitter-3.0.0.tgz", - "integrity": "sha512-KWKaceCwKQU0+HPoop6gn4eOHk50bBv/VxjJtGMfwmJt3D29JpN4H4eisCtIPA+a8GVBam+ldMMpMjJUvpDyHw==", + "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz", + "integrity": "sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==", "dependencies": { - "fbjs": "^3.0.0" + "browserslist": "^4.0.0", + "caniuse-lite": "^1.0.0", + "lodash.memoize": "^4.1.2", + "lodash.uniq": "^4.5.0" } }, - "node_modules/fbjs": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/fbjs/-/fbjs-3.0.0.tgz", - "integrity": "sha512-dJd4PiDOFuhe7vk4F80Mba83Vr2QuK86FoxtgPmzBqEJahncp+13YCmfoa53KHCo6OnlXLG7eeMWPfB5CrpVKg==", - "dependencies": { - "cross-fetch": "^3.0.4", - "fbjs-css-vars": "^1.0.0", - "loose-envify": "^1.0.0", - "object-assign": "^4.1.0", - "promise": "^7.1.1", - "setimmediate": "^1.0.5", - "ua-parser-js": "^0.7.18" - } - }, - "node_modules/fbjs-css-vars": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/fbjs-css-vars/-/fbjs-css-vars-1.0.2.tgz", - "integrity": "sha512-b2XGFAFdWZWg0phtAWLHCk836A1Xann+I+Dgd3Gk64MHKZO44FfoD1KxyvbSh0qZsIoXQGGlVztIY+oitJPpRQ==" + "node_modules/caniuse-lite": { + "version": "1.0.30001335", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001335.tgz", + "integrity": "sha512-ddP1Tgm7z2iIxu6QTtbZUv6HJxSaV/PZeSrWFZtbY4JZ69tOeNhBCl3HyRQgeNZKE5AOn1kpV7fhljigy0Ty3w==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + } + ] }, - "node_modules/feed": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/feed/-/feed-4.2.2.tgz", - "integrity": "sha512-u5/sxGfiMfZNtJ3OvQpXcvotFpYkL0n9u9mM2vkui2nGo8b4wvDkJ8gAkYqbA8QpGyFCv3RK0Z+Iv+9veCS9bQ==", - "dependencies": { - "xml-js": "^1.6.11" - }, - "engines": { - "node": ">=0.4.0" - } + "node_modules/caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==", + "dev": true }, - "node_modules/figures": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", - "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", - "dependencies": { - "escape-string-regexp": "^1.0.5" - }, - "engines": { - "node": ">=8" - }, + "node_modules/ccount": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/ccount/-/ccount-1.1.0.tgz", + "integrity": "sha512-vlNK021QdI7PNeiUh/lKkC/mNHHfV0m/Ad5JoI0TYtlBnJAslM/JIkm/tGC88bkLIwO6OQ5uV6ztS6kVAtCDlg==", "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "type": "github", + "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/file-loader": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-6.2.0.tgz", - "integrity": "sha512-qo3glqyTa61Ytg4u73GultjHGjdRyig3tG6lPtyX/jOEJvHif9uB0/OCI2Kif6ctF3caQTW2G5gym21oAsI4pw==", + "node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dependencies": { - "loader-utils": "^2.0.0", - "schema-utils": "^3.0.0" + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" }, "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^4.0.0 || ^5.0.0" + "node": ">=4" } }, - "node_modules/file-type": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/file-type/-/file-type-9.0.0.tgz", - "integrity": "sha512-Qe/5NJrgIOlwijpq3B7BEpzPFcgzggOTagZmkXQY4LA6bsXKTUstK7Wp12lEJ/mLKTpvIZxmIuRcLYWT6ov9lw==", + "node_modules/char-regex": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", + "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", + "dev": true, "engines": { - "node": ">=6" + "node": ">=10" } }, - "node_modules/file-uri-to-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", - "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", - "optional": true - }, - "node_modules/filesize": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/filesize/-/filesize-6.1.0.tgz", - "integrity": "sha512-LpCHtPQ3sFx67z+uh2HnSyWSLLu5Jxo21795uRDuar/EOuYWXib5EmPaGIBuSnRqH2IODiKA2k5re/K9OnN/Yg==", - "engines": { - "node": ">= 0.4.0" + "node_modules/character-entities": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-1.2.4.tgz", + "integrity": "sha512-iBMyeEHxfVnIakwOuDXpVkc54HijNgCyQB2w0VfGQThle6NXn50zU6V/u+LDhxHcDUPojn6Kpga3PTAD8W1bQw==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" + "node_modules/character-entities-legacy": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-1.1.4.tgz", + "integrity": "sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/filter-obj": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/filter-obj/-/filter-obj-2.0.2.tgz", - "integrity": "sha512-lO3ttPjHZRfjMcxWKb1j1eDhTFsu4meeR3lnMcnBFhk6RuLhvEiuALu2TlfL310ph4lCYYwgF/ElIjdP739tdg==", - "engines": { - "node": ">=8" + "node_modules/character-reference-invalid": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-1.1.4.tgz", + "integrity": "sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/finalhandler": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", - "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", - "dependencies": { - "debug": "2.6.9", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "on-finished": "~2.3.0", - "parseurl": "~1.3.3", - "statuses": "~1.5.0", - "unpipe": "~1.0.0" - }, + "node_modules/check-more-types": { + "version": "2.24.0", + "resolved": "https://registry.npmjs.org/check-more-types/-/check-more-types-2.24.0.tgz", + "integrity": "sha512-Pj779qHxV2tuapviy1bSZNEL1maXr13bPYpsvSDB68HlYcYuhlDrmGd63i0JHMCLKzc7rUSNIrpdJlhVlNwrxA==", + "dev": true, "engines": { - "node": ">= 0.8" - } - }, - "node_modules/finalhandler/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dependencies": { - "ms": "2.0.0" + "node": ">= 0.8.0" } }, - "node_modules/finalhandler/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - }, - "node_modules/find-cache-dir": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", - "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", + "node_modules/cheerio": { + "version": "1.0.0-rc.10", + "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.10.tgz", + "integrity": "sha512-g0J0q/O6mW8z5zxQ3A8E8J1hUgp4SMOvEoW/x84OwyHKe/Zccz83PVT4y5Crcr530FV6NgmKI1qvGTKVl9XXVw==", "dependencies": { - "commondir": "^1.0.1", - "make-dir": "^3.0.2", - "pkg-dir": "^4.1.0" + "cheerio-select": "^1.5.0", + "dom-serializer": "^1.3.2", + "domhandler": "^4.2.0", + "htmlparser2": "^6.1.0", + "parse5": "^6.0.1", + "parse5-htmlparser2-tree-adapter": "^6.0.1", + "tslib": "^2.2.0" }, "engines": { - "node": ">=8" + "node": ">= 6" }, "funding": { - "url": "https://github.com/avajs/find-cache-dir?sponsor=1" - } - }, - "node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" + "url": "https://github.com/cheeriojs/cheerio?sponsor=1" } }, - "node_modules/flux": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/flux/-/flux-4.0.2.tgz", - "integrity": "sha512-u/ucO5ezm3nBvdaSGkWpDlzCePoV+a9x3KHmy13TV/5MzOaCZDN8Mfd94jmf0nOi8ZZay+nOKbBUkOe2VNaupQ==", + "node_modules/cheerio-select": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-1.6.0.tgz", + "integrity": "sha512-eq0GdBvxVFbqWgmCm7M3XGs1I8oLy/nExUnh6oLqmBditPO9AqQJrkslDpMun/hZ0yyTs8L0m85OHp4ho6Qm9g==", "dependencies": { - "fbemitter": "^3.0.0", - "fbjs": "^3.0.0" + "css-select": "^4.3.0", + "css-what": "^6.0.1", + "domelementtype": "^2.2.0", + "domhandler": "^4.3.1", + "domutils": "^2.8.0" }, - "peerDependencies": { - "react": "^15.0.2 || ^16.0.0 || ^17.0.0" + "funding": { + "url": "https://github.com/sponsors/fb55" } }, - "node_modules/follow-redirects": { - "version": "1.14.4", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.4.tgz", - "integrity": "sha512-zwGkiSXC1MUJG/qmeIFH2HBJx9u0V46QGUe3YR1fXG8bXQxq7fLj0RjLZQ5nubr9qNJUZrH+xUcwXEoXNpfS+g==", + "node_modules/chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", "funding": [ { "type": "individual", - "url": "https://github.com/sponsors/RubenVerborgh" + "url": "https://paulmillr.com/funding/" } ], + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, "engines": { - "node": ">=4.0" + "node": ">= 8.10.0" }, - "peerDependenciesMeta": { - "debug": { - "optional": true - } + "optionalDependencies": { + "fsevents": "~2.3.2" } }, - "node_modules/for-in": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", - "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", + "node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + }, + "node_modules/chrome-trace-event": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", + "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==", "engines": { - "node": ">=0.10.0" + "node": ">=6.0" } }, - "node_modules/foreach": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz", - "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=" + "node_modules/ci-info": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.3.0.tgz", + "integrity": "sha512-riT/3vI5YpVH6/qomlDnJow6TBee2PBKSEpx3O32EGPYbWGIRsIlGRms3Sm74wYE1JMo8RnO04Hb12+v1J5ICw==", + "dev": true }, - "node_modules/fork-ts-checker-webpack-plugin": { - "version": "4.1.6", - "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-4.1.6.tgz", - "integrity": "sha512-DUxuQaKoqfNne8iikd14SAkh5uw4+8vNifp6gmA73yYNS6ywLIWSLD/n/mBzHQRpW3J7rbATEakmiA8JvkTyZw==", + "node_modules/cipher-base": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", + "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", "dependencies": { - "@babel/code-frame": "^7.5.5", - "chalk": "^2.4.1", - "micromatch": "^3.1.10", - "minimatch": "^3.0.4", - "semver": "^5.6.0", - "tapable": "^1.0.0", - "worker-rpc": "^0.1.0" - }, - "engines": { - "node": ">=6.11.5", - "yarn": ">=1.0.0" + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" } }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "dependencies": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } + "node_modules/cjs-module-lexer": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz", + "integrity": "sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA==", + "dev": true }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/braces/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "node_modules/classnames": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.1.tgz", + "integrity": "sha512-OlQdbZ7gLfGarSqxesMesDa5uz7KFbID8Kpq/SxIoNGDqY8lSYs0D+hhtBXhcdB3rcbXArFr7vlHheLk1voeNA==" + }, + "node_modules/clean-css": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.0.tgz", + "integrity": "sha512-YYuuxv4H/iNb1Z/5IbMRoxgrzjWGhOEFfd+groZ5dMCVkpENiMZmwspdrzBo9286JjM1gZJPAyL7ZIdzuvu2AQ==", "dependencies": { - "is-extendable": "^0.1.0" + "source-map": "~0.6.0" }, "engines": { - "node": ">=0.10.0" + "node": ">= 10.0" } }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, + "node_modules/clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", "engines": { - "node": ">=4" + "node": ">=6" } }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "dependencies": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - }, + "node_modules/cli-boxes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-3.0.0.tgz", + "integrity": "sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==", "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/extend-shallow/node_modules/is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dependencies": { - "is-plain-object": "^2.0.4" + "node": ">=10" }, - "engines": { - "node": ">=0.10.0" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "node_modules/cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "dev": true, "dependencies": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" + "restore-cursor": "^3.1.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/fill-range/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "node_modules/cli-table3": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.2.tgz", + "integrity": "sha512-QyavHCaIC80cMivimWu4aWHilIpiDpfm3hGmqAmXVL1UsnbLuBSMd21hTX6VY4ZSDSM73ESLeF8TOYId3rBTbw==", "dependencies": { - "is-extendable": "^0.1.0" + "string-width": "^4.2.0" }, "engines": { - "node": ">=0.10.0" + "node": "10.* || >= 12.*" + }, + "optionalDependencies": { + "@colors/colors": "1.5.0" } }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "node_modules/cli-table3/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/cli-table3/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dependencies": { - "kind-of": "^3.0.2" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" }, "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/is-number/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "node_modules/cli-truncate": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-2.1.0.tgz", + "integrity": "sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==", + "dev": true, "dependencies": { - "is-buffer": "^1.1.5" + "slice-ansi": "^3.0.0", + "string-width": "^4.2.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "node_modules/cli-truncate/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/cli-truncate/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, "dependencies": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" }, "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "bin": { - "semver": "bin/semver" + "node_modules/cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" } }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/tapable": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", - "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==", + "node_modules/cliui/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, "engines": { - "node": ">=6" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "node_modules/cliui/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dependencies": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" + "color-name": "~1.1.4" }, "engines": { - "node": ">=0.10.0" + "node": ">=7.0.0" } }, - "node_modules/forwarded": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", - "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", - "engines": { - "node": ">= 0.6" - } + "node_modules/cliui/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, - "node_modules/fraction.js": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.1.1.tgz", - "integrity": "sha512-MHOhvvxHTfRFpF1geTK9czMIZ6xclsEor2wkIGYYq+PxcQqT7vStJqjhe6S1TenZrMZzo+wlqOufBDVepUEgPg==", - "engines": { - "node": "*" - }, - "funding": { - "type": "patreon", - "url": "https://www.patreon.com/infusion" - } + "node_modules/cliui/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, - "node_modules/fragment-cache": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", - "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", + "node_modules/cliui/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dependencies": { - "map-cache": "^0.2.2" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" }, "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, - "node_modules/fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", + "node_modules/cliui/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, "engines": { - "node": ">= 0.6" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/fs-constants": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", - "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" - }, - "node_modules/fs-extra": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.0.0.tgz", - "integrity": "sha512-C5owb14u9eJwizKGdchcDUQeFtlSHHthBk8pbX9Vc1PFZrLombudjDnNns88aYslCyF6IY5SUw3Roz6xShcEIQ==", + "node_modules/clone-deep": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", + "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" + "is-plain-object": "^2.0.4", + "kind-of": "^6.0.2", + "shallow-clone": "^3.0.0" }, "engines": { - "node": ">=12" + "node": ">=6" } }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + "node_modules/clone-response": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", + "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=", + "dependencies": { + "mimic-response": "^1.0.0" + } }, - "node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], + "node_modules/clone-response/node_modules/mimic-response": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + "node": ">=4" } }, - "node_modules/function-bind": { + "node_modules/clsx": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" - }, - "node_modules/gauge": { - "version": "2.7.4", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", - "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", - "dependencies": { - "aproba": "^1.0.3", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.0", - "object-assign": "^4.1.0", - "signal-exit": "^3.0.0", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wide-align": "^1.1.0" + "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.1.1.tgz", + "integrity": "sha512-6/bPho624p3S2pMyvP5kKBPXnI3ufHLObBFCfgx+LkeR5lg2XYy2hqZqUf45ypD8COn2bhgGJSUE+l5dhNBieA==", + "engines": { + "node": ">=6" } }, - "node_modules/gauge/node_modules/ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "node_modules/co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", + "dev": true, "engines": { - "node": ">=0.10.0" + "iojs": ">= 1.0.0", + "node": ">= 0.12.0" } }, - "node_modules/gauge/node_modules/is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "node_modules/coa": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/coa/-/coa-2.0.2.tgz", + "integrity": "sha512-q5/jG+YQnSy4nRTV4F7lPepBJZ8qBNJJDBuJdoejDyLXgmL7IEo+Le2JDZudFTFt7mrCqIRaSjws4ygRCTCAXA==", "dependencies": { - "number-is-nan": "^1.0.0" + "@types/q": "^1.5.1", + "chalk": "^2.4.1", + "q": "^1.1.2" }, "engines": { - "node": ">=0.10.0" + "node": ">= 4.0" } }, - "node_modules/gauge/node_modules/string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dependencies": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/gauge/node_modules/strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dependencies": { - "ansi-regex": "^2.0.0" - }, + "node_modules/code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", "engines": { "node": ">=0.10.0" } }, - "node_modules/gensync": { - "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/get-intrinsic": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", - "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", - "dependencies": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1" - }, + "node_modules/collapse-white-space": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/collapse-white-space/-/collapse-white-space-1.0.6.tgz", + "integrity": "sha512-jEovNnrhMuqyCcjfEJA56v0Xq8SkIoPKDyaHahwo3POf4qcSXqMYuwNcOTzp74vTsR9Tn08z4MxWqAhcekogkQ==", "funding": { - "url": "https://github.com/sponsors/ljharb" + "type": "github", + "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/get-own-enumerable-property-symbols": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz", - "integrity": "sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g==" + "node_modules/collect-v8-coverage": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz", + "integrity": "sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg==", + "dev": true }, - "node_modules/get-stream": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", - "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "node_modules/color": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/color/-/color-3.2.1.tgz", + "integrity": "sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA==", "dependencies": { - "pump": "^3.0.0" - }, - "engines": { - "node": ">=6" + "color-convert": "^1.9.3", + "color-string": "^1.6.0" } }, - "node_modules/get-symbol-description": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", - "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", + "node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "color-name": "1.1.3" } }, - "node_modules/get-value": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", - "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", - "engines": { - "node": ">=0.10.0" - } + "node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" }, - "node_modules/gifwrap": { - "version": "0.9.2", - "resolved": "https://registry.npmjs.org/gifwrap/-/gifwrap-0.9.2.tgz", - "integrity": "sha512-fcIswrPaiCDAyO8xnWvHSZdWChjKXUanKKpAiWWJ/UTkEi/aYKn5+90e7DE820zbEaVR9CE2y4z9bzhQijZ0BA==", + "node_modules/color-string": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", + "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", "dependencies": { - "image-q": "^1.1.1", - "omggif": "^1.0.10" + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" } }, - "node_modules/github-from-package": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", - "integrity": "sha1-l/tdlr/eiXMxPyDoKI75oWf6ZM4=" + "node_modules/colord": { + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.2.tgz", + "integrity": "sha512-Uqbg+J445nc1TKn4FoDPS6ZZqAvEDnwrH42yo8B40JSOgSLxMZ/gt3h4nmCtPLQeXhjJJkqBx7SCY35WnIixaQ==" }, - "node_modules/github-slugger": { + "node_modules/colorette": { "version": "1.4.0", - "resolved": "https://registry.npmjs.org/github-slugger/-/github-slugger-1.4.0.tgz", - "integrity": "sha512-w0dzqw/nt51xMVmlaV1+JRzN+oCa1KfcgGEWhxUG16wbdA+Xnt/yoFO8Z8x/V82ZcZ0wy6ln9QDup5avbhiDhQ==" + "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.4.0.tgz", + "integrity": "sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g==" }, - "node_modules/glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, + "node_modules/combine-promises": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/combine-promises/-/combine-promises-1.1.0.tgz", + "integrity": "sha512-ZI9jvcLDxqwaXEixOhArm3r7ReIivsXkpbyEWyeOhzz1QS0iSgBPnWvEqvIQtYyamGCYA88gFhmUrs9hrrQ0pg==", "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": ">=10" } }, - "node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", "dependencies": { - "is-glob": "^4.0.1" + "delayed-stream": "~1.0.0" }, "engines": { - "node": ">= 6" + "node": ">= 0.8" } }, - "node_modules/glob-to-regexp": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", - "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==" - }, - "node_modules/global": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/global/-/global-4.4.0.tgz", - "integrity": "sha512-wv/LAoHdRE3BeTGz53FAamhGlPLhlssK45usmGFThIi4XqnBmjKQ16u+RNbP7WvigRZDxUsM0J3gcQ5yicaL0w==", - "dependencies": { - "min-document": "^2.19.0", - "process": "^0.11.10" + "node_modules/comma-separated-tokens": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-1.0.8.tgz", + "integrity": "sha512-GHuDRO12Sypu2cV70d1dkA2EUmXHgntrzbpvOB+Qy+49ypNfGgFQIC2fhhXbnyrJRynDCAARsT7Ou0M6hirpfw==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/global-dirs": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-3.0.0.tgz", - "integrity": "sha512-v8ho2DS5RiCjftj1nD9NmnfaOzTdud7RRnVd9kFNOjqZbISlx5DQ+OrTkywgd0dIt7oFCvKetZSHoHcP3sDdiA==", - "dependencies": { - "ini": "2.0.0" - }, + "node_modules/commander": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz", + "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==", "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">= 6" } }, - "node_modules/global-dirs/node_modules/ini": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz", - "integrity": "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==", + "node_modules/common-tags": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.2.tgz", + "integrity": "sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==", + "dev": true, "engines": { - "node": ">=10" + "node": ">=4.0.0" } }, - "node_modules/global-modules": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz", - "integrity": "sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==", + "node_modules/commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=" + }, + "node_modules/compressible": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", + "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", "dependencies": { - "global-prefix": "^3.0.0" + "mime-db": ">= 1.43.0 < 2" }, "engines": { - "node": ">=6" + "node": ">= 0.6" } }, - "node_modules/global-prefix": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz", - "integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==", + "node_modules/compression": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", + "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", "dependencies": { - "ini": "^1.3.5", - "kind-of": "^6.0.2", - "which": "^1.3.1" + "accepts": "~1.3.5", + "bytes": "3.0.0", + "compressible": "~2.0.16", + "debug": "2.6.9", + "on-headers": "~1.0.2", + "safe-buffer": "5.1.2", + "vary": "~1.1.2" }, "engines": { - "node": ">=6" + "node": ">= 0.8.0" } }, - "node_modules/global-prefix/node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "node_modules/compression/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "which": "bin/which" + "ms": "2.0.0" } }, - "node_modules/globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "engines": { - "node": ">=4" - } + "node_modules/compression/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" }, - "node_modules/globby": { - "version": "11.0.4", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.4.tgz", - "integrity": "sha512-9O4MVG9ioZJ08ffbcyVYyLOJLk5JQ688pJ4eMGLpdWLHq/Wr1D9BlriLQyL0E+jbkuePVZXYFj47QM/v093wHg==", + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "node_modules/configstore": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/configstore/-/configstore-5.0.1.tgz", + "integrity": "sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA==", "dependencies": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.1.1", - "ignore": "^5.1.4", - "merge2": "^1.3.0", - "slash": "^3.0.0" + "dot-prop": "^5.2.0", + "graceful-fs": "^4.1.2", + "make-dir": "^3.0.0", + "unique-string": "^2.0.0", + "write-file-atomic": "^3.0.0", + "xdg-basedir": "^4.0.0" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=8" } }, - "node_modules/got": { - "version": "9.6.0", - "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", - "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==", - "dependencies": { - "@sindresorhus/is": "^0.14.0", - "@szmarczak/http-timer": "^1.1.2", - "cacheable-request": "^6.0.0", - "decompress-response": "^3.3.0", - "duplexer3": "^0.1.4", - "get-stream": "^4.1.0", - "lowercase-keys": "^1.0.1", - "mimic-response": "^1.0.1", - "p-cancelable": "^1.0.0", - "to-readable-stream": "^1.0.0", - "url-parse-lax": "^3.0.0" - }, + "node_modules/connect-history-api-fallback": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz", + "integrity": "sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg==", "engines": { - "node": ">=8.6" + "node": ">=0.8" } }, - "node_modules/graceful-fs": { - "version": "4.2.8", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz", - "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==" + "node_modules/consola": { + "version": "2.15.3", + "resolved": "https://registry.npmjs.org/consola/-/consola-2.15.3.tgz", + "integrity": "sha512-9vAdYbHj6x2fLKC4+oPH0kFzY/orMZyG2Aj+kNylHxKGJ/Ed4dpNyAQYwJOdqO4zdM7XpVHmyejQDcQHrnuXbw==" }, - "node_modules/gray-matter": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/gray-matter/-/gray-matter-4.0.3.tgz", - "integrity": "sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q==", - "dependencies": { - "js-yaml": "^3.13.1", - "kind-of": "^6.0.2", - "section-matter": "^1.0.0", - "strip-bom-string": "^1.0.0" - }, - "engines": { - "node": ">=6.0" - } + "node_modules/console-browserify": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.2.0.tgz", + "integrity": "sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==" }, - "node_modules/gzip-size": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-5.1.1.tgz", - "integrity": "sha512-FNHi6mmoHvs1mxZAds4PpdCS6QG8B4C1krxJsMutgxl5t3+GlRTzzI3NEkifXx2pVsOvJdOGSmIgDhQ55FwdPA==", - "dependencies": { - "duplexer": "^0.1.1", - "pify": "^4.0.1" - }, + "node_modules/console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" + }, + "node_modules/consolidated-events": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/consolidated-events/-/consolidated-events-2.0.2.tgz", + "integrity": "sha512-2/uRVMdRypf5z/TW/ncD/66l75P5hH2vM/GR8Jf8HLc2xnfJtmina6F6du8+v4Z2vTrMo7jC+W1tmEEuuELgkQ==" + }, + "node_modules/constants-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", + "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=" + }, + "node_modules/content-disposition": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", + "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ=", "engines": { - "node": ">=6" + "node": ">= 0.6" } }, - "node_modules/handle-thing": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", - "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==" - }, - "node_modules/has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dependencies": { - "function-bind": "^1.1.1" - }, + "node_modules/content-type": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", "engines": { - "node": ">= 0.4.0" + "node": ">= 0.6" } }, - "node_modules/has-bigints": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz", - "integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==", - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node_modules/convert-source-map": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz", + "integrity": "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==", + "dependencies": { + "safe-buffer": "~5.1.1" } }, - "node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "node_modules/cookie": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", + "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", "engines": { - "node": ">=4" + "node": ">= 0.6" } }, - "node_modules/has-symbols": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", - "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" + }, + "node_modules/copy-text-to-clipboard": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/copy-text-to-clipboard/-/copy-text-to-clipboard-3.0.1.tgz", + "integrity": "sha512-rvVsHrpFcL4F2P8ihsoLdFHmd404+CMg71S756oRSeQgqk51U3kicGdnvfkrxva0xXH92SjGS62B0XIJsbh+9Q==", "engines": { - "node": ">= 0.4" + "node": ">=12" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/has-tostringtag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", - "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "node_modules/copy-webpack-plugin": { + "version": "10.2.4", + "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-10.2.4.tgz", + "integrity": "sha512-xFVltahqlsRcyyJqQbDY6EYTtyQZF9rf+JPjwHObLdPFMEISqkFkr7mFoVOC6BfYS/dNThyoQKvziugm+OnwBg==", "dependencies": { - "has-symbols": "^1.0.2" + "fast-glob": "^3.2.7", + "glob-parent": "^6.0.1", + "globby": "^12.0.2", + "normalize-path": "^3.0.0", + "schema-utils": "^4.0.0", + "serialize-javascript": "^6.0.0" }, "engines": { - "node": ">= 0.4" + "node": ">= 12.20.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.1.0" } }, - "node_modules/has-unicode": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=" - }, - "node_modules/has-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", - "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", + "node_modules/copy-webpack-plugin/node_modules/ajv": { + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz", + "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==", "dependencies": { - "get-value": "^2.0.6", - "has-values": "^1.0.0", - "isobject": "^3.0.0" + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" }, - "engines": { - "node": ">=0.10.0" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/has-values": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", - "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", + "node_modules/copy-webpack-plugin/node_modules/ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", "dependencies": { - "is-number": "^3.0.0", - "kind-of": "^4.0.0" + "fast-deep-equal": "^3.1.3" }, + "peerDependencies": { + "ajv": "^8.8.2" + } + }, + "node_modules/copy-webpack-plugin/node_modules/array-union": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-3.0.1.tgz", + "integrity": "sha512-1OvF9IbWwaeiM9VhzYXVQacMibxpXOMYVNIvMtKRyX9SImBXpKcFr8XvFDeEslCyuH/t6KRt7HEO94AlP8Iatw==", "engines": { - "node": ">=0.10.0" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/has-values/node_modules/is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "node_modules/copy-webpack-plugin/node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", "dependencies": { - "kind-of": "^3.0.2" + "is-glob": "^4.0.3" }, "engines": { - "node": ">=0.10.0" + "node": ">=10.13.0" } }, - "node_modules/has-values/node_modules/is-number/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "node_modules/copy-webpack-plugin/node_modules/globby": { + "version": "12.2.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-12.2.0.tgz", + "integrity": "sha512-wiSuFQLZ+urS9x2gGPl1H5drc5twabmm4m2gTR27XDFyjUHJUNsS8o/2aKyIF6IoBaR630atdher0XJ5g6OMmA==", "dependencies": { - "is-buffer": "^1.1.5" + "array-union": "^3.0.1", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.7", + "ignore": "^5.1.9", + "merge2": "^1.4.1", + "slash": "^4.0.0" }, "engines": { - "node": ">=0.10.0" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/has-values/node_modules/kind-of": { + "node_modules/copy-webpack-plugin/node_modules/schema-utils": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", - "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.0.0.tgz", + "integrity": "sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg==", "dependencies": { - "is-buffer": "^1.1.5" + "@types/json-schema": "^7.0.9", + "ajv": "^8.8.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.0.0" }, "engines": { - "node": ">=0.10.0" + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" } }, - "node_modules/has-yarn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/has-yarn/-/has-yarn-2.1.0.tgz", - "integrity": "sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw==", + "node_modules/copy-webpack-plugin/node_modules/slash": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz", + "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==", "engines": { - "node": ">=8" - } - }, - "node_modules/hash-base": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", - "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", - "dependencies": { - "inherits": "^2.0.4", - "readable-stream": "^3.6.0", - "safe-buffer": "^5.2.0" + "node": ">=12" }, - "engines": { - "node": ">=4" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/hash-base/node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] + "node_modules/core-js": { + "version": "3.22.4", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.22.4.tgz", + "integrity": "sha512-1uLykR+iOfYja+6Jn/57743gc9n73EWiOnSJJ4ba3B4fOEYDBv25MagmEZBxTp5cWq4b/KPx/l77zgsp28ju4w==", + "deprecated": "core-js@<3.23.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Some versions have web compatibility issues. Please, upgrade your dependencies to the actual version of core-js.", + "hasInstallScript": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } }, - "node_modules/hash.js": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", - "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", + "node_modules/core-js-compat": { + "version": "3.22.4", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.22.4.tgz", + "integrity": "sha512-dIWcsszDezkFZrfm1cnB4f/J85gyhiCpxbgBdohWCDtSVuAaChTSpPV7ldOQf/Xds2U5xCIJZOK82G4ZPAIswA==", "dependencies": { - "inherits": "^2.0.3", - "minimalistic-assert": "^1.0.1" + "browserslist": "^4.20.3", + "semver": "7.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" } }, - "node_modules/hast-to-hyperscript": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/hast-to-hyperscript/-/hast-to-hyperscript-9.0.1.tgz", - "integrity": "sha512-zQgLKqF+O2F72S1aa4y2ivxzSlko3MAvxkwG8ehGmNiqd98BIN3JM1rAJPmplEyLmGLO2QZYJtIneOSZ2YbJuA==", - "dependencies": { - "@types/unist": "^2.0.3", - "comma-separated-tokens": "^1.0.0", - "property-information": "^5.3.0", - "space-separated-tokens": "^1.0.0", - "style-to-object": "^0.3.0", - "unist-util-is": "^4.0.0", - "web-namespaces": "^1.0.0" - }, + "node_modules/core-js-compat/node_modules/semver": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz", + "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/core-js-pure": { + "version": "3.22.4", + "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.22.4.tgz", + "integrity": "sha512-4iF+QZkpzIz0prAFuepmxwJ2h5t4agvE8WPYqs2mjLJMNNwJOnpch76w2Q7bUfCPEv/V7wpvOfog0w273M+ZSw==", + "deprecated": "core-js-pure@<3.23.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Some versions have web compatibility issues. Please, upgrade your dependencies to the actual version of core-js-pure.", + "hasInstallScript": true, "funding": { "type": "opencollective", - "url": "https://opencollective.com/unified" + "url": "https://opencollective.com/core-js" } }, - "node_modules/hast-util-from-parse5": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-5.0.3.tgz", - "integrity": "sha512-gOc8UB99F6eWVWFtM9jUikjN7QkWxB3nY0df5Z0Zq1/Nkwl5V4hAAsl0tmwlgWl/1shlTF8DnNYLO8X6wRV9pA==", + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" + }, + "node_modules/cosmiconfig": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.1.tgz", + "integrity": "sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ==", "dependencies": { - "ccount": "^1.0.3", - "hastscript": "^5.0.0", - "property-information": "^5.0.0", - "web-namespaces": "^1.1.2", - "xtend": "^4.0.1" + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.2.1", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.10.0" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "engines": { + "node": ">=10" } }, - "node_modules/hast-util-parse-selector": { - "version": "2.2.5", - "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-2.2.5.tgz", - "integrity": "sha512-7j6mrk/qqkSehsM92wQjdIgWM2/BW61u/53G6xmC8i1OmEdKLHbk419QKQUjz6LglWsfqoiHmyMRkP1BGjecNQ==", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "node_modules/create-ecdh": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz", + "integrity": "sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==", + "dependencies": { + "bn.js": "^4.1.0", + "elliptic": "^6.5.3" } }, - "node_modules/hast-util-raw": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/hast-util-raw/-/hast-util-raw-6.0.1.tgz", - "integrity": "sha512-ZMuiYA+UF7BXBtsTBNcLBF5HzXzkyE6MLzJnL605LKE8GJylNjGc4jjxazAHUtcwT5/CEt6afRKViYB4X66dig==", + "node_modules/create-ecdh/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + }, + "node_modules/create-hash": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", + "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", "dependencies": { - "@types/hast": "^2.0.0", - "hast-util-from-parse5": "^6.0.0", - "hast-util-to-parse5": "^6.0.0", - "html-void-elements": "^1.0.0", - "parse5": "^6.0.0", - "unist-util-position": "^3.0.0", - "vfile": "^4.0.0", - "web-namespaces": "^1.0.0", - "xtend": "^4.0.0", - "zwitch": "^1.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "cipher-base": "^1.0.1", + "inherits": "^2.0.1", + "md5.js": "^1.3.4", + "ripemd160": "^2.0.1", + "sha.js": "^2.4.0" } }, - "node_modules/hast-util-raw/node_modules/hast-util-from-parse5": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-6.0.1.tgz", - "integrity": "sha512-jeJUWiN5pSxW12Rh01smtVkZgZr33wBokLzKLwinYOUfSzm1Nl/c3GUGebDyOKjdsRgMvoVbV0VpAcpjF4NrJA==", + "node_modules/create-hmac": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", + "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", "dependencies": { - "@types/parse5": "^5.0.0", - "hastscript": "^6.0.0", - "property-information": "^5.0.0", - "vfile": "^4.0.0", - "vfile-location": "^3.2.0", - "web-namespaces": "^1.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "cipher-base": "^1.0.3", + "create-hash": "^1.1.0", + "inherits": "^2.0.1", + "ripemd160": "^2.0.0", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" } }, - "node_modules/hast-util-raw/node_modules/hastscript": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/hastscript/-/hastscript-6.0.0.tgz", - "integrity": "sha512-nDM6bvd7lIqDUiYEiu5Sl/+6ReP0BMk/2f4U/Rooccxkj0P5nm+acM5PrGJ/t5I8qPGiqZSE6hVAwZEdZIvP4w==", + "node_modules/cross-fetch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.5.tgz", + "integrity": "sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw==", "dependencies": { - "@types/hast": "^2.0.0", - "comma-separated-tokens": "^1.0.0", - "hast-util-parse-selector": "^2.0.0", - "property-information": "^5.0.0", - "space-separated-tokens": "^1.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "node-fetch": "2.6.7" } }, - "node_modules/hast-util-raw/node_modules/parse5": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", - "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==" - }, - "node_modules/hast-util-to-parse5": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/hast-util-to-parse5/-/hast-util-to-parse5-6.0.0.tgz", - "integrity": "sha512-Lu5m6Lgm/fWuz8eWnrKezHtVY83JeRGaNQ2kn9aJgqaxvVkFCZQBEhgodZUDUvoodgyROHDb3r5IxAEdl6suJQ==", + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", "dependencies": { - "hast-to-hyperscript": "^9.0.0", - "property-information": "^5.0.0", - "web-namespaces": "^1.0.0", - "xtend": "^4.0.0", - "zwitch": "^1.0.0" + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "engines": { + "node": ">= 8" } }, - "node_modules/hastscript": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/hastscript/-/hastscript-5.1.2.tgz", - "integrity": "sha512-WlztFuK+Lrvi3EggsqOkQ52rKbxkXL3RwB6t5lwoa8QLMemoWfBuL43eDrwOamJyR7uKQKdmKYaBH1NZBiIRrQ==", + "node_modules/crypto-browserify": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", + "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", "dependencies": { - "comma-separated-tokens": "^1.0.0", - "hast-util-parse-selector": "^2.0.0", - "property-information": "^5.0.0", - "space-separated-tokens": "^1.0.0" + "browserify-cipher": "^1.0.0", + "browserify-sign": "^4.0.0", + "create-ecdh": "^4.0.0", + "create-hash": "^1.1.0", + "create-hmac": "^1.1.0", + "diffie-hellman": "^5.0.0", + "inherits": "^2.0.1", + "pbkdf2": "^3.0.3", + "public-encrypt": "^4.0.0", + "randombytes": "^2.0.0", + "randomfill": "^1.0.3" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "engines": { + "node": "*" } }, - "node_modules/he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", - "bin": { - "he": "bin/he" + "node_modules/crypto-random-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", + "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==", + "engines": { + "node": ">=8" } }, - "node_modules/history": { - "version": "4.10.1", - "resolved": "https://registry.npmjs.org/history/-/history-4.10.1.tgz", - "integrity": "sha512-36nwAD620w12kuzPAsyINPWJqlNbij+hpK1k9XRloDtym8mxzGYl2c17LnV6IAGB2Dmg4tEa7G7DlawS0+qjew==", + "node_modules/css": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/css/-/css-3.0.0.tgz", + "integrity": "sha512-DG9pFfwOrzc+hawpmqX/dHYHJG+Bsdb0klhyi1sDneOgGOXy9wQIC8hzyVp1e4NRYDBdxcylvywPkkXCHAzTyQ==", + "dev": true, "dependencies": { - "@babel/runtime": "^7.1.2", - "loose-envify": "^1.2.0", - "resolve-pathname": "^3.0.0", - "tiny-invariant": "^1.0.2", - "tiny-warning": "^1.0.0", - "value-equal": "^1.0.1" + "inherits": "^2.0.4", + "source-map": "^0.6.1", + "source-map-resolve": "^0.6.0" } }, - "node_modules/hmac-drbg": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", - "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", - "dependencies": { - "hash.js": "^1.0.3", - "minimalistic-assert": "^1.0.0", - "minimalistic-crypto-utils": "^1.0.1" + "node_modules/css-color-keywords": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/css-color-keywords/-/css-color-keywords-1.0.0.tgz", + "integrity": "sha1-/qJhbcZ2spYmhrOvjb2+GAskTgU=", + "engines": { + "node": ">=4" } }, - "node_modules/hoist-non-react-statics": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", - "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", - "dependencies": { - "react-is": "^16.7.0" + "node_modules/css-declaration-sorter": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-6.2.2.tgz", + "integrity": "sha512-Ufadglr88ZLsrvS11gjeu/40Lw74D9Am/Jpr3LlYm5Q4ZP5KdlUhG+6u2EjyXeZcxmZ2h1ebCKngDjolpeLHpg==", + "engines": { + "node": "^10 || ^12 || >=14" + }, + "peerDependencies": { + "postcss": "^8.0.9" } }, - "node_modules/hpack.js": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", - "integrity": "sha1-h3dMCUnlE/QuhFdbPEVoH63ioLI=", + "node_modules/css-loader": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-3.6.0.tgz", + "integrity": "sha512-M5lSukoWi1If8dhQAUCvj4H8vUt3vOnwbQBH9DdTm/s4Ym2B/3dPMtYZeJmq7Q3S3Pa+I94DcZ7pc9bP14cWIQ==", + "dev": true, "dependencies": { - "inherits": "^2.0.1", - "obuf": "^1.0.0", - "readable-stream": "^2.0.1", - "wbuf": "^1.1.0" - } - }, - "node_modules/hpack.js/node_modules/readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" + "camelcase": "^5.3.1", + "cssesc": "^3.0.0", + "icss-utils": "^4.1.1", + "loader-utils": "^1.2.3", + "normalize-path": "^3.0.0", + "postcss": "^7.0.32", + "postcss-modules-extract-imports": "^2.0.0", + "postcss-modules-local-by-default": "^3.0.2", + "postcss-modules-scope": "^2.2.0", + "postcss-modules-values": "^3.0.0", + "postcss-value-parser": "^4.1.0", + "schema-utils": "^2.7.0", + "semver": "^6.3.0" + }, + "engines": { + "node": ">= 8.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.0.0 || ^5.0.0" } }, - "node_modules/hpack.js/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dependencies": { - "safe-buffer": "~5.1.0" + "node_modules/css-loader/node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true, + "engines": { + "node": ">=6" } }, - "node_modules/html-entities": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-1.4.0.tgz", - "integrity": "sha512-8nxjcBcd8wovbeKx7h3wTji4e6+rhaVuPNpMqwWgnHh+N9ToqsCs6XztWRBPQ+UtzsoMAdKZtUENoVzU/EMtZA==" - }, - "node_modules/html-minifier-terser": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-5.1.1.tgz", - "integrity": "sha512-ZPr5MNObqnV/T9akshPKbVgyOqLmy+Bxo7juKCfTfnjNniTAMdy4hz21YQqoofMBJD2kdREaqPPdThoR78Tgxg==", + "node_modules/css-loader/node_modules/json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dev": true, "dependencies": { - "camel-case": "^4.1.1", - "clean-css": "^4.2.3", - "commander": "^4.1.1", - "he": "^1.2.0", - "param-case": "^3.0.3", - "relateurl": "^0.2.7", - "terser": "^4.6.3" + "minimist": "^1.2.0" }, "bin": { - "html-minifier-terser": "cli.js" - }, - "engines": { - "node": ">=6" + "json5": "lib/cli.js" } }, - "node_modules/html-minifier-terser/node_modules/clean-css": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.3.tgz", - "integrity": "sha512-VcMWDN54ZN/DS+g58HYL5/n4Zrqe8vHJpGA8KdgUXFU4fuP/aHNw8eld9SyEIyabIMJX/0RaY/fplOo5hYLSFA==", + "node_modules/css-loader/node_modules/loader-utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", + "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", + "dev": true, "dependencies": { - "source-map": "~0.6.0" + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" }, "engines": { - "node": ">= 4.0" - } - }, - "node_modules/html-minifier-terser/node_modules/commander": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", - "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", - "engines": { - "node": ">= 6" + "node": ">=4.0.0" } }, - "node_modules/html-minifier-terser/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "engines": { - "node": ">=0.10.0" - } + "node_modules/css-loader/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true }, - "node_modules/html-minifier-terser/node_modules/terser": { - "version": "4.8.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-4.8.0.tgz", - "integrity": "sha512-EAPipTNeWsb/3wLPeup1tVPaXfIaU68xMnVdPafIL1TV05OhASArYyIfFvnvJCNrR2NIOvDVNNTFRa+Re2MWyw==", + "node_modules/css-loader/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, "dependencies": { - "commander": "^2.20.0", - "source-map": "~0.6.1", - "source-map-support": "~0.5.12" - }, - "bin": { - "terser": "bin/terser" + "picocolors": "^0.2.1", + "source-map": "^0.6.1" }, "engines": { "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" } }, - "node_modules/html-minifier-terser/node_modules/terser/node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" - }, - "node_modules/html-tags": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.1.0.tgz", - "integrity": "sha512-1qYz89hW3lFDEazhjW0yVAV87lw8lVkrJocr72XmBkMKsoSVJCQx3W8BXsC7hO2qAt8BoVjYjtAcZ9perqGnNg==", - "engines": { - "node": ">=8" - } - }, - "node_modules/html-void-elements": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-1.0.5.tgz", - "integrity": "sha512-uE/TxKuyNIcx44cIWnjr/rfIATDH7ZaOMmstu0CwhFG1Dunhlp4OC6/NMbhiwoq5BpW0ubi303qnEk/PZj614w==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "node_modules/css-loader/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" } }, - "node_modules/html-webpack-plugin": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.3.2.tgz", - "integrity": "sha512-HvB33boVNCz2lTyBsSiMffsJ+m0YLIQ+pskblXgN9fnjS1BgEcuAfdInfXfGrkdXV406k9FiDi86eVCDBgJOyQ==", + "node_modules/css-minimizer-webpack-plugin": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/css-minimizer-webpack-plugin/-/css-minimizer-webpack-plugin-3.4.1.tgz", + "integrity": "sha512-1u6D71zeIfgngN2XNRJefc/hY7Ybsxd74Jm4qngIXyUEk7fss3VUzuHxLAq/R8NAba4QU9OUSaMZlbpRc7bM4Q==", "dependencies": { - "@types/html-minifier-terser": "^5.0.0", - "html-minifier-terser": "^5.0.1", - "lodash": "^4.17.21", - "pretty-error": "^3.0.4", - "tapable": "^2.0.0" + "cssnano": "^5.0.6", + "jest-worker": "^27.0.2", + "postcss": "^8.3.5", + "schema-utils": "^4.0.0", + "serialize-javascript": "^6.0.0", + "source-map": "^0.6.1" }, "engines": { - "node": ">=10.13.0" + "node": ">= 12.13.0" }, "funding": { "type": "opencollective", - "url": "https://opencollective.com/html-webpack-plugin" + "url": "https://opencollective.com/webpack" }, "peerDependencies": { - "webpack": "^5.20.0" + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "@parcel/css": { + "optional": true + }, + "clean-css": { + "optional": true + }, + "csso": { + "optional": true + }, + "esbuild": { + "optional": true + } } }, - "node_modules/htmlparser2": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.1.tgz", - "integrity": "sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ==", + "node_modules/css-minimizer-webpack-plugin/node_modules/ajv": { + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz", + "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==", "dependencies": { - "domelementtype": "^1.3.1", - "domhandler": "^2.3.0", - "domutils": "^1.5.1", - "entities": "^1.1.1", - "inherits": "^2.0.1", - "readable-stream": "^3.1.1" + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/htmlparser2/node_modules/dom-serializer": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz", - "integrity": "sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==", + "node_modules/css-minimizer-webpack-plugin/node_modules/ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", "dependencies": { - "domelementtype": "^2.0.1", - "entities": "^2.0.0" + "fast-deep-equal": "^3.1.3" + }, + "peerDependencies": { + "ajv": "^8.8.2" } }, - "node_modules/htmlparser2/node_modules/dom-serializer/node_modules/domelementtype": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz", - "integrity": "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ] + "node_modules/css-minimizer-webpack-plugin/node_modules/schema-utils": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.0.0.tgz", + "integrity": "sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg==", + "dependencies": { + "@types/json-schema": "^7.0.9", + "ajv": "^8.8.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.0.0" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } }, - "node_modules/htmlparser2/node_modules/dom-serializer/node_modules/entities": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", - "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", + "node_modules/css-select": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", + "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==", + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.0.1", + "domhandler": "^4.3.1", + "domutils": "^2.8.0", + "nth-check": "^2.0.1" + }, "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" + "url": "https://github.com/sponsors/fb55" } }, - "node_modules/htmlparser2/node_modules/domelementtype": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", - "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==" + "node_modules/css-select-base-adapter": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/css-select-base-adapter/-/css-select-base-adapter-0.1.1.tgz", + "integrity": "sha512-jQVeeRG70QI08vSTwf1jHxp74JoZsr2XSgETae8/xC8ovSnL2WF87GTLO86Sbwdt2lK4Umg4HnnwMO4YF3Ce7w==" }, - "node_modules/htmlparser2/node_modules/domhandler": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz", - "integrity": "sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==", + "node_modules/css-to-react-native": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/css-to-react-native/-/css-to-react-native-3.0.0.tgz", + "integrity": "sha512-Ro1yETZA813eoyUp2GDBhG2j+YggidUmzO1/v9eYBKR2EHVEniE2MI/NqpTQ954BMpTPZFsGNPm46qFB9dpaPQ==", "dependencies": { - "domelementtype": "1" + "camelize": "^1.0.0", + "css-color-keywords": "^1.0.0", + "postcss-value-parser": "^4.0.2" } }, - "node_modules/htmlparser2/node_modules/domutils": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz", - "integrity": "sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==", + "node_modules/css-tree": { + "version": "1.0.0-alpha.37", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.37.tgz", + "integrity": "sha512-DMxWJg0rnz7UgxKT0Q1HU/L9BeJI0M6ksor0OgqOnF+aRCDWg/N2641HmVyU9KVIu0OVVWOb2IpC9A+BJRnejg==", "dependencies": { - "dom-serializer": "0", - "domelementtype": "1" + "mdn-data": "2.0.4", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=8.0.0" } }, - "node_modules/htmlparser2/node_modules/entities": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", - "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==" + "node_modules/css-what": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", + "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } }, - "node_modules/http-cache-semantics": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", - "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==" - }, - "node_modules/http-deceiver": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", - "integrity": "sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc=" + "node_modules/css.escape": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/css.escape/-/css.escape-1.5.1.tgz", + "integrity": "sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==", + "dev": true }, - "node_modules/http-errors": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", - "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", - "dependencies": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.1", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.0" + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "bin": { + "cssesc": "bin/cssesc" }, "engines": { - "node": ">= 0.6" + "node": ">=4" } }, - "node_modules/http-errors/node_modules/inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" - }, - "node_modules/http-parser-js": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.3.tgz", - "integrity": "sha512-t7hjvef/5HEK7RWTdUzVUhl8zkEu+LlaE0IYzdMuvbSDipxBRpOn4Uhw8ZyECEa808iVT8XCjzo6xmYt4CiLZg==" - }, - "node_modules/http-proxy": { - "version": "1.18.1", - "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", - "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", + "node_modules/cssnano": { + "version": "5.1.7", + "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-5.1.7.tgz", + "integrity": "sha512-pVsUV6LcTXif7lvKKW9ZrmX+rGRzxkEdJuVJcp5ftUjWITgwam5LMZOgaTvUrWPkcORBey6he7JKb4XAJvrpKg==", "dependencies": { - "eventemitter3": "^4.0.0", - "follow-redirects": "^1.0.0", - "requires-port": "^1.0.0" + "cssnano-preset-default": "^5.2.7", + "lilconfig": "^2.0.3", + "yaml": "^1.10.2" }, "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/http-proxy-middleware": { - "version": "0.19.1", - "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-0.19.1.tgz", - "integrity": "sha512-yHYTgWMQO8VvwNS22eLLloAkvungsKdKTLO8AJlftYIKNfJr3GK3zK0ZCfzDDGUBttdGc8xFy1mCitvNKQtC3Q==", - "dependencies": { - "http-proxy": "^1.17.0", - "is-glob": "^4.0.0", - "lodash": "^4.17.11", - "micromatch": "^3.1.10" + "node": "^10 || ^12 || >=14.0" }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/http-proxy-middleware/node_modules/braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "dependencies": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/cssnano" }, - "engines": { - "node": ">=0.10.0" + "peerDependencies": { + "postcss": "^8.2.15" } }, - "node_modules/http-proxy-middleware/node_modules/braces/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "node_modules/cssnano-preset-advanced": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/cssnano-preset-advanced/-/cssnano-preset-advanced-5.3.3.tgz", + "integrity": "sha512-AB9SmTSC2Gd8T7PpKUsXFJ3eNsg7dc4CTZ0+XAJ29MNxyJsrCEk7N1lw31bpHrsQH2PVJr21bbWgGAfA9j0dIA==", "dependencies": { - "is-extendable": "^0.1.0" + "autoprefixer": "^10.3.7", + "cssnano-preset-default": "^5.2.7", + "postcss-discard-unused": "^5.1.0", + "postcss-merge-idents": "^5.1.1", + "postcss-reduce-idents": "^5.2.0", + "postcss-zindex": "^5.1.0" }, "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/http-proxy-middleware/node_modules/extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "dependencies": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" + "node": "^10 || ^12 || >=14.0" }, - "engines": { - "node": ">=0.10.0" + "peerDependencies": { + "postcss": "^8.2.15" } }, - "node_modules/http-proxy-middleware/node_modules/extend-shallow/node_modules/is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dependencies": { - "is-plain-object": "^2.0.4" + "node_modules/cssnano-preset-default": { + "version": "5.2.7", + "resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-5.2.7.tgz", + "integrity": "sha512-JiKP38ymZQK+zVKevphPzNSGHSlTI+AOwlasoSRtSVMUU285O7/6uZyd5NbW92ZHp41m0sSHe6JoZosakj63uA==", + "dependencies": { + "css-declaration-sorter": "^6.2.2", + "cssnano-utils": "^3.1.0", + "postcss-calc": "^8.2.3", + "postcss-colormin": "^5.3.0", + "postcss-convert-values": "^5.1.0", + "postcss-discard-comments": "^5.1.1", + "postcss-discard-duplicates": "^5.1.0", + "postcss-discard-empty": "^5.1.1", + "postcss-discard-overridden": "^5.1.0", + "postcss-merge-longhand": "^5.1.4", + "postcss-merge-rules": "^5.1.1", + "postcss-minify-font-values": "^5.1.0", + "postcss-minify-gradients": "^5.1.1", + "postcss-minify-params": "^5.1.2", + "postcss-minify-selectors": "^5.2.0", + "postcss-normalize-charset": "^5.1.0", + "postcss-normalize-display-values": "^5.1.0", + "postcss-normalize-positions": "^5.1.0", + "postcss-normalize-repeat-style": "^5.1.0", + "postcss-normalize-string": "^5.1.0", + "postcss-normalize-timing-functions": "^5.1.0", + "postcss-normalize-unicode": "^5.1.0", + "postcss-normalize-url": "^5.1.0", + "postcss-normalize-whitespace": "^5.1.1", + "postcss-ordered-values": "^5.1.1", + "postcss-reduce-initial": "^5.1.0", + "postcss-reduce-transforms": "^5.1.0", + "postcss-svgo": "^5.1.0", + "postcss-unique-selectors": "^5.1.1" }, "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/http-proxy-middleware/node_modules/fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "dependencies": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" + "node": "^10 || ^12 || >=14.0" }, - "engines": { - "node": ">=0.10.0" + "peerDependencies": { + "postcss": "^8.2.15" } }, - "node_modules/http-proxy-middleware/node_modules/fill-range/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dependencies": { - "is-extendable": "^0.1.0" - }, + "node_modules/cssnano-utils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cssnano-utils/-/cssnano-utils-3.1.0.tgz", + "integrity": "sha512-JQNR19/YZhz4psLX/rQ9M83e3z2Wf/HdJbryzte4a3NSuafyp9w/I4U+hx5C2S9g41qlstH7DEWnZaaj83OuEA==", "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/http-proxy-middleware/node_modules/is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dependencies": { - "kind-of": "^3.0.2" + "node": "^10 || ^12 || >=14.0" }, - "engines": { - "node": ">=0.10.0" + "peerDependencies": { + "postcss": "^8.2.15" } }, - "node_modules/http-proxy-middleware/node_modules/is-number/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "node_modules/csso": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/csso/-/csso-4.2.0.tgz", + "integrity": "sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA==", "dependencies": { - "is-buffer": "^1.1.5" + "css-tree": "^1.1.2" }, "engines": { - "node": ">=0.10.0" + "node": ">=8.0.0" } }, - "node_modules/http-proxy-middleware/node_modules/micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "node_modules/csso/node_modules/css-tree": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz", + "integrity": "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==", "dependencies": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" + "mdn-data": "2.0.14", + "source-map": "^0.6.1" }, "engines": { - "node": ">=0.10.0" + "node": ">=8.0.0" } }, - "node_modules/http-proxy-middleware/node_modules/to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "node_modules/csso/node_modules/mdn-data": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz", + "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==" + }, + "node_modules/cssom": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.4.4.tgz", + "integrity": "sha512-p3pvU7r1MyyqbTk+WbNJIgJjG2VmTIaB10rI93LzVPrmDJKkzKYMtxxyAvQXR/NS6otuzveI7+7BBq3SjBS2mw==", + "dev": true + }, + "node_modules/cssstyle": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-2.3.0.tgz", + "integrity": "sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==", + "dev": true, "dependencies": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" + "cssom": "~0.3.6" }, "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, - "node_modules/http2-client": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/http2-client/-/http2-client-1.3.5.tgz", - "integrity": "sha512-EC2utToWl4RKfs5zd36Mxq7nzHHBuomZboI0yYL6Y0RmBgT7Sgkq4rQ0ezFTYoIsSs7Tm9SJe+o2FcAg6GBhGA==" - }, - "node_modules/https-browserify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", - "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=" + "node_modules/cssstyle/node_modules/cssom": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", + "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", + "dev": true }, - "node_modules/human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "engines": { - "node": ">=10.17.0" - } + "node_modules/csstype": { + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.11.tgz", + "integrity": "sha512-sa6P2wJ+CAbgyy4KFssIb/JNMLxFvKF1pCYCSXS8ZMuqZnMsrxqI2E5sPyoTpxoPU/gVZMzr2zjOfg8GIZOMsw==" }, - "node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "node_modules/cypress": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/cypress/-/cypress-10.3.0.tgz", + "integrity": "sha512-txkQWKzvBVnWdCuKs5Xc08gjpO89W2Dom2wpZgT9zWZT5jXxqPIxqP/NC1YArtkpmp3fN5HW8aDjYBizHLUFvg==", + "dev": true, + "hasInstallScript": true, "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" + "@cypress/request": "^2.88.10", + "@cypress/xvfb": "^1.2.4", + "@types/node": "^14.14.31", + "@types/sinonjs__fake-timers": "8.1.1", + "@types/sizzle": "^2.3.2", + "arch": "^2.2.0", + "blob-util": "^2.0.2", + "bluebird": "^3.7.2", + "buffer": "^5.6.0", + "cachedir": "^2.3.0", + "chalk": "^4.1.0", + "check-more-types": "^2.24.0", + "cli-cursor": "^3.1.0", + "cli-table3": "~0.6.1", + "commander": "^5.1.0", + "common-tags": "^1.8.0", + "dayjs": "^1.10.4", + "debug": "^4.3.2", + "enquirer": "^2.3.6", + "eventemitter2": "^6.4.3", + "execa": "4.1.0", + "executable": "^4.1.1", + "extract-zip": "2.0.1", + "figures": "^3.2.0", + "fs-extra": "^9.1.0", + "getos": "^3.2.1", + "is-ci": "^3.0.0", + "is-installed-globally": "~0.4.0", + "lazy-ass": "^1.6.0", + "listr2": "^3.8.3", + "lodash": "^4.17.21", + "log-symbols": "^4.0.0", + "minimist": "^1.2.6", + "ospath": "^1.2.2", + "pretty-bytes": "^5.6.0", + "proxy-from-env": "1.0.0", + "request-progress": "^3.0.0", + "semver": "^7.3.2", + "supports-color": "^8.1.1", + "tmp": "~0.2.1", + "untildify": "^4.0.0", + "yauzl": "^2.10.0" + }, + "bin": { + "cypress": "bin/cypress" }, "engines": { - "node": ">=0.10.0" + "node": ">=12.0.0" } }, - "node_modules/icss-utils": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", - "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", + "node_modules/cypress/node_modules/@types/node": { + "version": "14.18.21", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.21.tgz", + "integrity": "sha512-x5W9s+8P4XteaxT/jKF0PSb7XEvo5VmqEWgsMlyeY4ZlLK8I6aH6g5TPPyDlLAep+GYf4kefb7HFyc7PAO3m+Q==", + "dev": true + }, + "node_modules/cypress/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, "engines": { - "node": "^10 || ^12 || >= 14" + "node": ">=8" }, - "peerDependencies": { - "postcss": "^8.1.0" + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "node_modules/cypress/node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "dev": true, "funding": [ { "type": "github", @@ -8858,299 +8868,297 @@ "type": "consulting", "url": "https://feross.org/support" } - ] - }, - "node_modules/ignore": { - "version": "5.1.8", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", - "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", - "engines": { - "node": ">= 4" - } - }, - "node_modules/image-q": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/image-q/-/image-q-1.1.1.tgz", - "integrity": "sha1-/IQJlmRGC5DKhi2TALa/u7+/gFY=", - "engines": { - "node": ">=0.9.0" - } - }, - "node_modules/immer": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/immer/-/immer-8.0.1.tgz", - "integrity": "sha512-aqXhGP7//Gui2+UrEtvxZxSquQVXTpZ7KDxfCcKAF3Vysvw0CViVaW9RZ1j1xlIYqaaaipBoqdqeibkc18PNvA==", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/immer" + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" } }, - "node_modules/import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "node_modules/cypress/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">=6" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/import-lazy": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz", - "integrity": "sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM=", + "node_modules/cypress/node_modules/chalk/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, "engines": { - "node": ">=4" + "node": ">=8" } }, - "node_modules/import-local": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-2.0.0.tgz", - "integrity": "sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ==", + "node_modules/cypress/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, "dependencies": { - "pkg-dir": "^3.0.0", - "resolve-cwd": "^2.0.0" - }, - "bin": { - "import-local-fixture": "fixtures/cli.js" + "color-name": "~1.1.4" }, "engines": { - "node": ">=6" + "node": ">=7.0.0" } }, - "node_modules/import-local/node_modules/find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "node_modules/cypress/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/cypress/node_modules/execa": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-4.1.0.tgz", + "integrity": "sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==", + "dev": true, "dependencies": { - "locate-path": "^3.0.0" + "cross-spawn": "^7.0.0", + "get-stream": "^5.0.0", + "human-signals": "^1.1.1", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.0", + "onetime": "^5.1.0", + "signal-exit": "^3.0.2", + "strip-final-newline": "^2.0.0" }, "engines": { - "node": ">=6" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" } }, - "node_modules/import-local/node_modules/locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "node_modules/cypress/node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, "dependencies": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" }, "engines": { - "node": ">=6" + "node": ">=10" } }, - "node_modules/import-local/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "node_modules/cypress/node_modules/get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, "dependencies": { - "p-try": "^2.0.0" + "pump": "^3.0.0" }, "engines": { - "node": ">=6" + "node": ">=8" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/import-local/node_modules/p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dependencies": { - "p-limit": "^2.0.0" - }, + "node_modules/cypress/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, "engines": { - "node": ">=6" + "node": ">=8" } }, - "node_modules/import-local/node_modules/path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "node_modules/cypress/node_modules/human-signals": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz", + "integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==", + "dev": true, "engines": { - "node": ">=4" + "node": ">=8.12.0" } }, - "node_modules/import-local/node_modules/pkg-dir": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", - "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "node_modules/cypress/node_modules/is-ci": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-3.0.1.tgz", + "integrity": "sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==", + "dev": true, "dependencies": { - "find-up": "^3.0.0" + "ci-info": "^3.2.0" }, - "engines": { - "node": ">=6" - } - }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", - "engines": { - "node": ">=0.8.19" - } - }, - "node_modules/indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "engines": { - "node": ">=8" + "bin": { + "is-ci": "bin.js" } }, - "node_modules/infima": { - "version": "0.2.0-alpha.33", - "resolved": "https://registry.npmjs.org/infima/-/infima-0.2.0-alpha.33.tgz", - "integrity": "sha512-iLZI8/vGTbbhbeFhlWv1zwvrqfNDLAayuEdqZqNqCyGuh0IW469dRIRm0FLZ98YyLikt2njzuKfy6xUrBWRXcg==", + "node_modules/cypress/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, "engines": { - "node": ">=12" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "node_modules/dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==", + "dev": true, "dependencies": { - "once": "^1.3.0", - "wrappy": "1" + "assert-plus": "^1.0.0" + }, + "engines": { + "node": ">=0.10" } }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "node_modules/ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" - }, - "node_modules/inline-style-parser": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.1.1.tgz", - "integrity": "sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q==" - }, - "node_modules/internal-ip": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/internal-ip/-/internal-ip-4.3.0.tgz", - "integrity": "sha512-S1zBo1D6zcsyuC6PMmY5+55YMILQ9av8lotMx447Bq6SAgo/sDK6y6uUKmuYhW7eacnIhFfsPmCNYdDzsnnDCg==", + "node_modules/data-urls": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-2.0.0.tgz", + "integrity": "sha512-X5eWTSXO/BJmpdIKCRuKUgSCgAN0OwliVK3yPKbwIWU1Tdw5BRajxlzMidvh+gwko9AfQ9zIj52pzF91Q3YAvQ==", + "dev": true, "dependencies": { - "default-gateway": "^4.2.0", - "ipaddr.js": "^1.9.0" + "abab": "^2.0.3", + "whatwg-mimetype": "^2.3.0", + "whatwg-url": "^8.0.0" }, "engines": { - "node": ">=6" + "node": ">=10" } }, - "node_modules/internal-slot": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz", - "integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==", + "node_modules/dayjs": { + "version": "1.11.3", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.3.tgz", + "integrity": "sha512-xxwlswWOlGhzgQ4TKzASQkUhqERI3egRNqgV4ScR8wlANA/A9tZ7miXa44vTTKEq5l7vWoL5G57bG3zA+Kow0A==", + "dev": true + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "dependencies": { - "get-intrinsic": "^1.1.0", - "has": "^1.0.3", - "side-channel": "^1.0.4" + "ms": "2.1.2" }, "engines": { - "node": ">= 0.4" + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, - "node_modules/interpret": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", - "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", - "engines": { - "node": ">= 0.10" - } + "node_modules/decimal.js": { + "version": "10.3.1", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.3.1.tgz", + "integrity": "sha512-V0pfhfr8suzyPGOx3nmq4aHqabehUZn6Ch9kyFpV79TGDTWFmHqUqXdabR7QHqxzrYolF4+tVmJhUG4OURg5dQ==", + "dev": true }, - "node_modules/ip": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", - "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=" + "node_modules/decko": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decko/-/decko-1.2.0.tgz", + "integrity": "sha1-/UPHNelnuAEzBohKVvvmZZlraBc=" }, - "node_modules/ip-regex": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-2.1.0.tgz", - "integrity": "sha1-+ni/XS5pE8kRzp+BnuUUa7bYROk=", + "node_modules/decode-uri-component": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", + "integrity": "sha512-hjf+xovcEn31w/EUYdTXQh/8smFL/dzYjohQGEIgjyNavaJfBY2p5F527Bo1VPATxv0VYTUC2bOcXvqFwk78Og==", + "dev": true, "engines": { - "node": ">=4" + "node": ">=0.10" } }, - "node_modules/ipaddr.js": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", - "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "dependencies": { + "mimic-response": "^3.1.0" + }, "engines": { - "node": ">= 0.10" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/is-absolute-url": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-3.0.3.tgz", - "integrity": "sha512-opmNIX7uFnS96NtPmhWQgQx6/NYFgsUXYMllcfzwWKUMwfo8kku1TvE6hkNcH+Q1ts5cMVrsY7j0bxXQDciu9Q==", + "node_modules/dedent": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", + "integrity": "sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==", + "dev": true + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", "engines": { - "node": ">=8" + "node": ">=4.0.0" } }, - "node_modules/is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dependencies": { - "kind-of": "^3.0.2" - }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, + "node_modules/deepmerge": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", + "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==", "engines": { "node": ">=0.10.0" } }, - "node_modules/is-accessor-descriptor/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "node_modules/default-gateway": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-6.0.3.tgz", + "integrity": "sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg==", "dependencies": { - "is-buffer": "^1.1.5" + "execa": "^5.0.0" }, "engines": { - "node": ">=0.10.0" + "node": ">= 10" } }, - "node_modules/is-alphabetical": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-1.0.4.tgz", - "integrity": "sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } + "node_modules/defer-to-connect": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz", + "integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==" }, - "node_modules/is-alphanumerical": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-1.0.4.tgz", - "integrity": "sha512-UzoZUr+XfVz3t3v4KyGEniVL9BDRoQtY7tOyrRybkVNjDFWyo1yhXNGrrBTQxp3ib9BLAWs7k2YKBQsFRkZG9A==", - "dependencies": { - "is-alphabetical": "^1.0.0", - "is-decimal": "^1.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "node_modules/define-lazy-prop": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", + "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", + "engines": { + "node": ">=8" } }, - "node_modules/is-arguments": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", - "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", + "node_modules/define-properties": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz", + "integrity": "sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==", "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" }, "engines": { "node": ">= 0.4" @@ -9159,463 +9167,522 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=" - }, - "node_modules/is-bigint": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", - "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "node_modules/del": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/del/-/del-6.0.0.tgz", + "integrity": "sha512-1shh9DQ23L16oXSZKB2JxpL7iMy2E0S9d517ptA1P8iw0alkPtQcrKH7ru31rYtKwF499HkTu+DRzq3TCKDFRQ==", "dependencies": { - "has-bigints": "^1.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dependencies": { - "binary-extensions": "^2.0.0" + "globby": "^11.0.1", + "graceful-fs": "^4.2.4", + "is-glob": "^4.0.1", + "is-path-cwd": "^2.2.0", + "is-path-inside": "^3.0.2", + "p-map": "^4.0.0", + "rimraf": "^3.0.2", + "slash": "^3.0.0" }, "engines": { - "node": ">=8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/is-boolean-object": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", - "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=0.4.0" } }, - "node_modules/is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" + "node_modules/delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=" }, - "node_modules/is-callable": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz", - "integrity": "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==", + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">= 0.8" } }, - "node_modules/is-ci": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", - "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", + "node_modules/des.js": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.1.tgz", + "integrity": "sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA==", "dependencies": { - "ci-info": "^2.0.0" - }, - "bin": { - "is-ci": "bin.js" + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" } }, - "node_modules/is-ci/node_modules/ci-info": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", - "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==" + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } }, - "node_modules/is-core-module": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.7.0.tgz", - "integrity": "sha512-ByY+tjCciCr+9nLryBYcSD50EOGWt95c7tIsKTG1J2ixKKXPvF7Ej3AVd+UfDydAJom3biBGDBALaO79ktwgEQ==", + "node_modules/detab": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/detab/-/detab-2.0.4.tgz", + "integrity": "sha512-8zdsQA5bIkoRECvCrNKPla84lyoR7DSAyf7p0YgXzBO9PDJx8KntPUay7NS6yp+KdxdVtiE5SpHKtbp2ZQyA9g==", "dependencies": { - "has": "^1.0.3" + "repeat-string": "^1.5.4" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "type": "github", + "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dependencies": { - "kind-of": "^3.0.2" - }, + "node_modules/detect-libc": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz", + "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==", "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, - "node_modules/is-data-descriptor/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dependencies": { - "is-buffer": "^1.1.5" - }, + "node_modules/detect-newline": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", + "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", + "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, - "node_modules/is-date-object": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", - "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "node_modules/detect-node": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", + "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==" + }, + "node_modules/detect-port": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/detect-port/-/detect-port-1.3.0.tgz", + "integrity": "sha512-E+B1gzkl2gqxt1IhUzwjrxBKRqx1UzC3WLONHinn8S3T6lwV/agVCyitiFOsGJ/eYuEUBvD71MZHy3Pv1G9doQ==", "dependencies": { - "has-tostringtag": "^1.0.0" + "address": "^1.0.1", + "debug": "^2.6.0" }, - "engines": { - "node": ">= 0.4" + "bin": { + "detect": "bin/detect-port", + "detect-port": "bin/detect-port" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-decimal": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-1.0.4.tgz", - "integrity": "sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "engines": { + "node": ">= 4.2.1" } }, - "node_modules/is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "node_modules/detect-port-alt": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/detect-port-alt/-/detect-port-alt-1.1.6.tgz", + "integrity": "sha512-5tQykt+LqfJFBEYaDITx7S7cR7mJ/zQmLXZ2qt5w04ainYZw6tBf9dBunMjVeVOdYVRUzUOE4HkY5J7+uttb5Q==", "dependencies": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" + "address": "^1.0.1", + "debug": "^2.6.0" + }, + "bin": { + "detect": "bin/detect-port", + "detect-port": "bin/detect-port" }, "engines": { - "node": ">=0.10.0" + "node": ">= 4.2.1" } }, - "node_modules/is-descriptor/node_modules/kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "engines": { - "node": ">=0.10.0" + "node_modules/detect-port-alt/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" } }, - "node_modules/is-docker": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", - "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", - "bin": { - "is-docker": "cli.js" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } + "node_modules/detect-port-alt/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" }, - "node_modules/is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "engines": { - "node": ">=0.10.0" + "node_modules/detect-port/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" } }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "node_modules/detect-port/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "node_modules/diff-sequences": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.5.1.tgz", + "integrity": "sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ==", + "dev": true, "engines": { - "node": ">=0.10.0" + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "engines": { - "node": ">=8" + "node_modules/diffie-hellman": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", + "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", + "dependencies": { + "bn.js": "^4.1.0", + "miller-rabin": "^4.0.0", + "randombytes": "^2.0.0" } }, - "node_modules/is-function": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-function/-/is-function-1.0.2.tgz", - "integrity": "sha512-lw7DUp0aWXYg+CBCN+JKkcE0Q2RayZnSvnZBlwgxHBQhqt5pZNVy4Ri7H9GmmXkdu7LUthszM+Tor1u/2iBcpQ==" + "node_modules/diffie-hellman/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" }, - "node_modules/is-generator-function": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", - "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", "dependencies": { - "has-tostringtag": "^1.0.0" + "path-type": "^4.0.0" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=8" } }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "node_modules/dns-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz", + "integrity": "sha1-s55/HabrCnW6nBcySzR1PEfgZU0=" + }, + "node_modules/dns-packet": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.3.1.tgz", + "integrity": "sha512-spBwIj0TK0Ey3666GwIdWVfUpLyubpU53BTCu8iPn4r4oXd9O14Hjg3EHw3ts2oed77/SeckunUYCyRlSngqHw==", "dependencies": { - "is-extglob": "^2.1.1" + "@leichtgewicht/ip-codec": "^2.0.1" }, "engines": { - "node": ">=0.10.0" + "node": ">=6" } }, - "node_modules/is-hexadecimal": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-1.0.4.tgz", - "integrity": "sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } + "node_modules/dom-accessibility-api": { + "version": "0.5.14", + "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.14.tgz", + "integrity": "sha512-NMt+m9zFMPZe0JcY9gN224Qvk6qLIdqex29clBvc/y75ZBX9YA9wNK3frsYvu2DI1xcCIwxwnX+TlsJ2DSOADg==", + "dev": true }, - "node_modules/is-installed-globally": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.4.0.tgz", - "integrity": "sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ==", + "node_modules/dom-converter": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz", + "integrity": "sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==", "dependencies": { - "global-dirs": "^3.0.0", - "is-path-inside": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "utila": "~0.4" } }, - "node_modules/is-nan": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/is-nan/-/is-nan-1.3.2.tgz", - "integrity": "sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==", + "node_modules/dom-serializer": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", + "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", "dependencies": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3" - }, - "engines": { - "node": ">= 0.4" + "domelementtype": "^2.0.1", + "domhandler": "^4.2.0", + "entities": "^2.0.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" } }, - "node_modules/is-negative-zero": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.1.tgz", - "integrity": "sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } + "node_modules/dom-walk": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.2.tgz", + "integrity": "sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w==" }, - "node_modules/is-npm": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-5.0.0.tgz", - "integrity": "sha512-WW/rQLOazUq+ST/bCAVBp/2oMERWLsR7OrKyt052dNDk4DHcDE0/7QSXITlmi+VBcV13DfIbysG3tZJm5RfdBA==", + "node_modules/domain-browser": { + "version": "4.22.0", + "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-4.22.0.tgz", + "integrity": "sha512-IGBwjF7tNk3cwypFNH/7bfzBcgSCbaMOD3GsaY1AU/JRrnHnYgEM0+9kQt52iZxjNsjBtJYtao146V+f8jFZNw==", "engines": { "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://bevry.me/fund" } }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "engines": { - "node": ">=0.12.0" - } + "node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ] }, - "node_modules/is-number-object": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.6.tgz", - "integrity": "sha512-bEVOqiRcvo3zO1+G2lVMy+gkkEm9Yh7cDMRusKKu5ZJKPUYSJwICTKZrNKHA2EbSP0Tu0+6B/emsYNHZyn6K8g==", + "node_modules/domexception": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/domexception/-/domexception-2.0.1.tgz", + "integrity": "sha512-yxJ2mFy/sibVQlu5qHjOkf9J3K6zgmCxgJ94u2EdvDOV09H+32LtRswEcUsmUWN72pVLOEnTSRaIVVzVQgS0dg==", + "dev": true, "dependencies": { - "has-tostringtag": "^1.0.0" + "webidl-conversions": "^5.0.0" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=8" } }, - "node_modules/is-obj": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", - "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", + "node_modules/domexception/node_modules/webidl-conversions": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-5.0.0.tgz", + "integrity": "sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA==", + "dev": true, "engines": { "node": ">=8" } }, - "node_modules/is-path-cwd": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz", - "integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==", + "node_modules/domhandler": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", + "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", + "dependencies": { + "domelementtype": "^2.2.0" + }, "engines": { - "node": ">=6" + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" } }, - "node_modules/is-path-in-cwd": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-2.1.0.tgz", - "integrity": "sha512-rNocXHgipO+rvnP6dk3zI20RpOtrAM/kzbB258Uw5BWr3TpXi861yzjo16Dn4hUox07iw5AyeMLHWsujkjzvRQ==", + "node_modules/dompurify": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-2.3.6.tgz", + "integrity": "sha512-OFP2u/3T1R5CEgWCEONuJ1a5+MFKnOYpkywpUSxv/dj1LeBT1erK+JwM7zK0ROy2BRhqVCf0LRw/kHqKuMkVGg==" + }, + "node_modules/domutils": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", + "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", "dependencies": { - "is-path-inside": "^2.1.0" + "dom-serializer": "^1.0.1", + "domelementtype": "^2.2.0", + "domhandler": "^4.2.0" }, - "engines": { - "node": ">=6" + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" } }, - "node_modules/is-path-in-cwd/node_modules/is-path-inside": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-2.1.0.tgz", - "integrity": "sha512-wiyhTzfDWsvwAW53OBWF5zuvaOGlZ6PwYxAbPVDhpm+gM09xKQGjBq/8uYN12aDvMxnAnq3dxTyoSoRNmg5YFg==", + "node_modules/dot-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", + "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/dot-prop": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", + "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", "dependencies": { - "path-is-inside": "^1.0.2" + "is-obj": "^2.0.0" }, "engines": { - "node": ">=6" + "node": ">=8" } }, - "node_modules/is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "node_modules/dot-prop/node_modules/is-obj": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", + "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", "engines": { "node": ">=8" } }, - "node_modules/is-plain-obj": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", - "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", + "node_modules/dotenv": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-10.0.0.tgz", + "integrity": "sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q==", + "dev": true, "engines": { - "node": ">=8" + "node": ">=10" } }, - "node_modules/is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "node_modules/duplexer": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", + "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==" + }, + "node_modules/duplexer3": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", + "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=" + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" + }, + "node_modules/ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==", + "dev": true, "dependencies": { - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" } }, - "node_modules/is-regex": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", - "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" + }, + "node_modules/electron-to-chromium": { + "version": "1.4.129", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.129.tgz", + "integrity": "sha512-GgtN6bsDtHdtXJtlMYZWGB/uOyjZWjmRDumXTas7dGBaB9zUyCjzHet1DY2KhyHN8R0GLbzZWqm4efeddqqyRQ==" + }, + "node_modules/elliptic": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", + "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==", "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "bn.js": "^4.11.9", + "brorand": "^1.1.0", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.1", + "inherits": "^2.0.4", + "minimalistic-assert": "^1.0.1", + "minimalistic-crypto-utils": "^1.0.1" } }, - "node_modules/is-regexp": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz", - "integrity": "sha1-/S2INUXEa6xaYz57mgnof6LLUGk=", + "node_modules/elliptic/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + }, + "node_modules/emittery": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.8.1.tgz", + "integrity": "sha512-uDfvUjVrfGJJhymx/kz6prltenw1u7WrCg1oa94zYY8xxVpLLUu045LAT0dhDZdXG58/EpPL/5kA180fQ/qudg==", + "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/emittery?sponsor=1" } }, - "node_modules/is-resolvable": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz", - "integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==" + "node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" }, - "node_modules/is-root": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-root/-/is-root-2.1.0.tgz", - "integrity": "sha512-AGOriNp96vNBd3HtU+RzFEc75FfR5ymiYv8E553I71SCeXBiMsVDUtdio1OEFvrPyLIQ9tVR5RxXIFe5PUFjMg==", + "node_modules/emojis-list": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", + "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", "engines": { - "node": ">=6" + "node": ">= 4" } }, - "node_modules/is-shared-array-buffer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.1.tgz", - "integrity": "sha512-IU0NmyknYZN0rChcKhRO1X8LYz5Isj/Fsqh8NJOSf+N/hCOTwy29F32Ik7a+QszE63IdvmwdTPDd6cZ5pg4cwA==", + "node_modules/emoticon": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/emoticon/-/emoticon-3.2.0.tgz", + "integrity": "sha512-SNujglcLTTg+lDAcApPNgEdudaqQFiAbJCqzjNxJkvN9vAwCGi0uu8IUVvx+f16h+V44KCY6Y2yboroc9pilHg==", "funding": { - "url": "https://github.com/sponsors/ljharb" + "type": "github", + "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/is-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", + "node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", "engines": { - "node": ">=0.10.0" + "node": ">= 0.8" } }, - "node_modules/is-string": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", - "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "once": "^1.4.0" } }, - "node_modules/is-symbol": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", - "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "node_modules/enhanced-resolve": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.9.3.tgz", + "integrity": "sha512-Bq9VSor+kjvW3f9/MiiR4eE3XYgOl7/rS8lnSxbRbF3kS0B2r+Y9w5krBWxZgDxASVZbdYrn5wT4j/Wb0J9qow==", "dependencies": { - "has-symbols": "^1.0.2" + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" }, "engines": { - "node": ">= 0.4" + "node": ">=10.13.0" + } + }, + "node_modules/enquirer": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", + "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", + "dev": true, + "dependencies": { + "ansi-colors": "^4.1.1" }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/entities": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/fb55/entities?sponsor=1" } }, - "node_modules/is-typed-array": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.8.tgz", - "integrity": "sha512-HqH41TNZq2fgtGT8WHVFVJhBVGuY3AnP3Q36K8JKXUxSxRgk/d+7NjmwG2vo2mYmXK8UYZKu0qH8bVP5gEisjA==", + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/es-abstract": { + "version": "1.19.5", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.19.5.tgz", + "integrity": "sha512-Aa2G2+Rd3b6kxEUKTF4TaW67czBLyAv3z7VOhYRU50YBx+bbsYZ9xQP4lMNazePuFlybXI0V4MruPos7qUo5fA==", "dependencies": { - "available-typed-arrays": "^1.0.5", "call-bind": "^1.0.2", - "es-abstract": "^1.18.5", - "foreach": "^2.0.5", - "has-tostringtag": "^1.0.0" + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "get-intrinsic": "^1.1.1", + "get-symbol-description": "^1.0.0", + "has": "^1.0.3", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.3", + "is-callable": "^1.2.4", + "is-negative-zero": "^2.0.2", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.2", + "is-string": "^1.0.7", + "is-weakref": "^1.0.2", + "object-inspect": "^1.12.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.2", + "string.prototype.trimend": "^1.0.4", + "string.prototype.trimstart": "^1.0.4", + "unbox-primitive": "^1.0.1" }, "engines": { "node": ">= 0.4" @@ -9624,500 +9691,570 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" + "node_modules/es-module-lexer": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.9.3.tgz", + "integrity": "sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ==" }, - "node_modules/is-weakref": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.1.tgz", - "integrity": "sha512-b2jKc2pQZjaeFYWEf7ScFj+Be1I+PXmlu572Q8coTXZ+LD/QQZ7ShPMst8h16riVgyXTQwUsFEl74mDvc/3MHQ==", + "node_modules/es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", "dependencies": { - "call-bind": "^1.0.0" + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-whitespace-character": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-whitespace-character/-/is-whitespace-character-1.0.4.tgz", - "integrity": "sha512-SDweEzfIZM0SJV0EUga669UTKlmL0Pq8Lno0QDQsPnvECB3IM2aP0gdx5TrU0A01MAPfViaZiI2V1QMZLaKK5w==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } + "node_modules/es6-object-assign": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/es6-object-assign/-/es6-object-assign-1.1.0.tgz", + "integrity": "sha1-wsNYJlYkfDnqEHyx5mUrb58kUjw=" }, - "node_modules/is-windows": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", - "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", - "engines": { - "node": ">=0.10.0" - } + "node_modules/es6-promise": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.3.1.tgz", + "integrity": "sha1-oIzd6EzNvzTQJ6FFG8kdS80ophM=" }, - "node_modules/is-word-character": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-word-character/-/is-word-character-1.0.4.tgz", - "integrity": "sha512-5SMO8RVennx3nZrqtKwCGyyetPE9VDba5ugvKLaD4KopPG5kR4mQ7tNt/r7feL5yt5h3lpuBbIUmCOG2eSzXHA==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "node_modules/escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "engines": { + "node": ">=6" } }, - "node_modules/is-wsl": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", - "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", - "dependencies": { - "is-docker": "^2.0.0" - }, + "node_modules/escape-goat": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-2.1.1.tgz", + "integrity": "sha512-8/uIhbG12Csjy2JEW7D9pHbreaVaS/OpN3ycnyvElTdwM5n6GY6W6e2IPemfvGZeUMqZ9A/3GqIZMgKnBhAw/Q==", "engines": { "node": ">=8" } }, - "node_modules/is-yarn-global": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/is-yarn-global/-/is-yarn-global-0.3.0.tgz", - "integrity": "sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw==" + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" }, - "node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "engines": { + "node": ">=0.8.0" + } }, - "node_modules/isexe": { + "node_modules/escodegen": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" - }, - "node_modules/isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.0.0.tgz", + "integrity": "sha512-mmHKys/C8BFUGI+MAWNcSYoORYLMdPzjrknd2Vc+bUsjN5bXcr8EhrNB+UTqfL1y3I9c4fw2ihgtMPQLBRiQxw==", + "dev": true, + "dependencies": { + "esprima": "^4.0.1", + "estraverse": "^5.2.0", + "esutils": "^2.0.2", + "optionator": "^0.8.1" + }, + "bin": { + "escodegen": "bin/escodegen.js", + "esgenerate": "bin/esgenerate.js" + }, "engines": { - "node": ">=0.10.0" + "node": ">=6.0" + }, + "optionalDependencies": { + "source-map": "~0.6.1" } }, - "node_modules/jest-worker": { - "version": "27.2.5", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.2.5.tgz", - "integrity": "sha512-HTjEPZtcNKZ4LnhSp02NEH4vE+5OpJ0EsOWYvGQpHgUMLngydESAAMH5Wd/asPf29+XUDQZszxpLg1BkIIA2aw==", + "node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", "dependencies": { - "@types/node": "*", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" }, "engines": { - "node": ">= 10.13.0" + "node": ">=8.0.0" } }, - "node_modules/jest-worker/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "node_modules/eslint-scope/node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", "engines": { - "node": ">=8" + "node": ">=4.0" } }, - "node_modules/jest-worker/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dependencies": { - "has-flag": "^4.0.0" + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" + "node": ">=4" } }, - "node_modules/joi": { - "version": "17.4.2", - "resolved": "https://registry.npmjs.org/joi/-/joi-17.4.2.tgz", - "integrity": "sha512-Lm56PP+n0+Z2A2rfRvsfWVDXGEWjXxatPopkQ8qQ5mxCEhwHG+Ettgg5o98FFaxilOxozoa14cFhrE/hOzh/Nw==", + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", "dependencies": { - "@hapi/hoek": "^9.0.0", - "@hapi/topo": "^5.0.0", - "@sideway/address": "^4.1.0", - "@sideway/formula": "^3.0.0", - "@sideway/pinpoint": "^2.0.0" + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" } }, - "node_modules/jpeg-js": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/jpeg-js/-/jpeg-js-0.4.2.tgz", - "integrity": "sha512-+az2gi/hvex7eLTMTlbRLOhH6P6WFdk2ITI8HJsaH2VqYO0I594zXSYEP+tf4FW+8Cy68ScDXoAsQdyQanv3sw==" + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "engines": { + "node": ">=4.0" + } }, - "node_modules/js-levenshtein": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/js-levenshtein/-/js-levenshtein-1.1.6.tgz", - "integrity": "sha512-X2BB11YZtrRqY4EnQcLX5Rh373zbK4alC1FW7D7MBhL2gtcC17cTnr6DmfHZeS0s2rTHjUTMMHfG7gO8SSdw+g==", + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "engines": { "node": ">=0.10.0" } }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" - }, - "node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" + "node_modules/eta": { + "version": "1.12.3", + "resolved": "https://registry.npmjs.org/eta/-/eta-1.12.3.tgz", + "integrity": "sha512-qHixwbDLtekO/d51Yr4glcaUJCIjGVJyTzuqV4GPlgZo1YpgOKG+avQynErZIYrfM6JIJdtiG2Kox8tbb+DoGg==", + "engines": { + "node": ">=6.0.0" }, - "bin": { - "js-yaml": "bin/js-yaml.js" + "funding": { + "url": "https://github.com/eta-dev/eta?sponsor=1" } }, - "node_modules/jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "bin": { - "jsesc": "bin/jsesc" - }, - "engines": { - "node": ">=4" + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", + "engines": { + "node": ">= 0.6" } }, - "node_modules/json-buffer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", - "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=" - }, - "node_modules/json-parse-better-errors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", - "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==" - }, - "node_modules/json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" - }, - "node_modules/json-pointer": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/json-pointer/-/json-pointer-0.6.1.tgz", - "integrity": "sha512-3OvjqKdCBvH41DLpV4iSt6v2XhZXV1bPB4OROuknvUXI7ZQNofieCPkmE26stEJ9zdQuvIxDHCuYhfgxFAAs+Q==", + "node_modules/eval": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/eval/-/eval-0.1.8.tgz", + "integrity": "sha512-EzV94NYKoO09GLXGjXj9JIlXijVck4ONSr5wiCWDvhsvj5jxSrzTmRU/9C1DyB6uToszLs8aifA6NQ7lEQdvFw==", "dependencies": { - "foreach": "^2.0.4" + "@types/node": "*", + "require-like": ">= 0.1.1" + }, + "engines": { + "node": ">= 0.8" } }, - "node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + "node_modules/eventemitter2": { + "version": "6.4.6", + "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-6.4.6.tgz", + "integrity": "sha512-OHqo4wbHX5VbvlbB6o6eDwhYmiTjrpWACjF8Pmof/GTD6rdBNdZFNck3xlhqOiQFGCOoq3uzHvA0cQpFHIGVAQ==", + "dev": true }, - "node_modules/json3": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/json3/-/json3-3.3.3.tgz", - "integrity": "sha512-c7/8mbUsKigAbLkD5B010BK4D9LZm7A1pNItkEwiUZRpIN66exu/e7YQWysGun+TRKaJp8MhemM+VkfWv42aCA==" + "node_modules/eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==" }, - "node_modules/json5": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz", - "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==", - "dependencies": { - "minimist": "^1.2.5" - }, - "bin": { - "json5": "lib/cli.js" - }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", "engines": { - "node": ">=6" + "node": ">=0.8.x" } }, - "node_modules/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "node_modules/evp_bytestokey": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", + "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", "dependencies": { - "universalify": "^2.0.0" + "md5.js": "^1.3.4", + "safe-buffer": "^5.1.1" + } + }, + "node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" } }, - "node_modules/keyv": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", - "integrity": "sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==", + "node_modules/executable": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/executable/-/executable-4.1.1.tgz", + "integrity": "sha512-8iA79xD3uAch729dUG8xaaBBFGaEa0wdD2VkYLFHwlqosEj/jT66AzcreRDSgV7ehnNLBW2WR5jIXwGKjVdTLg==", + "dev": true, "dependencies": { - "json-buffer": "3.0.0" + "pify": "^2.2.0" + }, + "engines": { + "node": ">=4" } }, - "node_modules/killable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/killable/-/killable-1.0.1.tgz", - "integrity": "sha512-LzqtLKlUwirEUyl/nicirVmNiPvYs7l5n8wOPP7fyJVpUPkvCnW/vuiXGpylGUlnPDnB7311rARzAt3Mhswpjg==" + "node_modules/exif-parser": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/exif-parser/-/exif-parser-0.1.12.tgz", + "integrity": "sha1-WKnS1ywCwfbwKg70qRZicrd2CSI=" }, - "node_modules/kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "node_modules/exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", + "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">= 0.8.0" } }, - "node_modules/kleur": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", - "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "node_modules/expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", "engines": { "node": ">=6" } }, - "node_modules/klona": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/klona/-/klona-2.0.4.tgz", - "integrity": "sha512-ZRbnvdg/NxqzC7L9Uyqzf4psi1OM4Cuc+sJAkQPjO6XkQIJTNbfK2Rsmbw8fx1p2mkZdp2FZYo2+LwXYY/uwIA==", + "node_modules/expect": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/expect/-/expect-27.5.1.tgz", + "integrity": "sha512-E1q5hSUG2AmYQwQJ041nvgpkODHQvB+RKlB4IYdru6uJsyFTRyZAP463M+1lINorwbqAmUggi6+WwkD8lCS/Dw==", + "dev": true, + "dependencies": { + "@jest/types": "^27.5.1", + "jest-get-type": "^27.5.1", + "jest-matcher-utils": "^27.5.1", + "jest-message-util": "^27.5.1" + }, "engines": { - "node": ">= 8" + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "node_modules/latest-version": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-5.1.0.tgz", - "integrity": "sha512-weT+r0kTkRQdCdYCNtkMwWXQTMEswKrFBkm4ckQOMVhhqhIMI1UT2hMj+1iigIhgSZm5gTmrRXBNoGUgaTY1xA==", + "node_modules/express": { + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.18.1.tgz", + "integrity": "sha512-zZBcOX9TfehHQhtupq57OF8lFZ3UZi08Y97dwFCkD8p9d/d2Y3M+ykKcwaMDEL+4qyUolgBDX6AblpR3fL212Q==", "dependencies": { - "package-json": "^6.3.0" + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.0", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.5.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.2.0", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.7", + "qs": "6.10.3", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.18.0", + "serve-static": "1.15.0", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" }, "engines": { - "node": ">=8" + "node": ">= 0.10.0" } }, - "node_modules/leven": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", - "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", - "engines": { - "node": ">=6" - } + "node_modules/express/node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" }, - "node_modules/lilconfig": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.0.3.tgz", - "integrity": "sha512-EHKqr/+ZvdKCifpNrJCKxBTgk5XupZA3y/aCPY9mxfgBzmgh93Mt/WqjjQ38oMxXuvDokaKiM3lAgvSH2sjtHg==", + "node_modules/express/node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "dependencies": { + "safe-buffer": "5.2.1" + }, "engines": { - "node": ">=10" + "node": ">= 0.6" } }, - "node_modules/lines-and-columns": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.1.6.tgz", - "integrity": "sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=" - }, - "node_modules/load-bmfont": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/load-bmfont/-/load-bmfont-1.4.1.tgz", - "integrity": "sha512-8UyQoYmdRDy81Brz6aLAUhfZLwr5zV0L3taTQ4hju7m6biuwiWiJXjPhBJxbUQJA8PrkvJ/7Enqmwk2sM14soA==", + "node_modules/express/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dependencies": { - "buffer-equal": "0.0.1", - "mime": "^1.3.4", - "parse-bmfont-ascii": "^1.0.3", - "parse-bmfont-binary": "^1.0.5", - "parse-bmfont-xml": "^1.1.4", - "phin": "^2.9.1", - "xhr": "^2.0.1", - "xtend": "^4.0.0" + "ms": "2.0.0" } }, - "node_modules/loader-runner": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.2.0.tgz", - "integrity": "sha512-92+huvxMvYlMzMt0iIOukcwYBFpkYJdpl2xsZ7LrlayO7E8SOv+JJUEK17B/dJIHAOLMfh2dZZ/Y18WgmGtYNw==", + "node_modules/express/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/express/node_modules/path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" + }, + "node_modules/express/node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", "engines": { - "node": ">=6.11.5" + "node": ">= 0.6" } }, - "node_modules/loader-utils": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz", - "integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==", + "node_modules/express/node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + }, + "node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dependencies": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^2.1.2" + "is-extendable": "^0.1.0" }, "engines": { - "node": ">=8.9.0" + "node": ">=0.10.0" } }, - "node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "node_modules/extract-zip": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", + "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", + "dev": true, "dependencies": { - "p-locate": "^4.1.0" + "debug": "^4.1.1", + "get-stream": "^5.1.0", + "yauzl": "^2.10.0" + }, + "bin": { + "extract-zip": "cli.js" }, "engines": { - "node": ">=8" + "node": ">= 10.17.0" + }, + "optionalDependencies": { + "@types/yauzl": "^2.9.1" } }, - "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" - }, - "node_modules/lodash.assignin": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.assignin/-/lodash.assignin-4.2.0.tgz", - "integrity": "sha1-uo31+4QesKPoBEIysOJjqNxqKKI=" - }, - "node_modules/lodash.bind": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/lodash.bind/-/lodash.bind-4.2.1.tgz", - "integrity": "sha1-euMBfpOWIqwxt9fX3LGzTbFpDTU=" - }, - "node_modules/lodash.curry": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lodash.curry/-/lodash.curry-4.1.1.tgz", - "integrity": "sha1-JI42By7ekGUB11lmIAqG2riyMXA=" - }, - "node_modules/lodash.debounce": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", - "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=" - }, - "node_modules/lodash.defaults": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", - "integrity": "sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw=" - }, - "node_modules/lodash.filter": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.filter/-/lodash.filter-4.6.0.tgz", - "integrity": "sha1-ZosdSYFgOuHMWm+nYBQ+SAtMSs4=" - }, - "node_modules/lodash.flatten": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", - "integrity": "sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=" - }, - "node_modules/lodash.flow": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/lodash.flow/-/lodash.flow-3.5.0.tgz", - "integrity": "sha1-h79AKSuM+D5OjOGjrkIJ4gBxZ1o=" - }, - "node_modules/lodash.foreach": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.foreach/-/lodash.foreach-4.5.0.tgz", - "integrity": "sha1-Gmo16s5AEoDH8G3d7DUWWrJ+PlM=" + "node_modules/extract-zip/node_modules/get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, - "node_modules/lodash.isequal": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", - "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA=" + "node_modules/extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==", + "dev": true, + "engines": [ + "node >=0.6.0" + ] }, - "node_modules/lodash.map": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.map/-/lodash.map-4.6.0.tgz", - "integrity": "sha1-dx7Hg540c9nEzeKLGTlMNWL09tM=" + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" }, - "node_modules/lodash.memoize": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", - "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=" + "node_modules/fast-glob": { + "version": "3.2.11", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz", + "integrity": "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } }, - "node_modules/lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==" + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" }, - "node_modules/lodash.pick": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.pick/-/lodash.pick-4.4.0.tgz", - "integrity": "sha1-UvBWEP/53tQiYRRB7R/BI6AwAbM=" + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true }, - "node_modules/lodash.reduce": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.reduce/-/lodash.reduce-4.6.0.tgz", - "integrity": "sha1-8atrg5KZrUj3hKu/R2WW8DuRTTs=" + "node_modules/fast-safe-stringify": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", + "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==" }, - "node_modules/lodash.reject": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.reject/-/lodash.reject-4.6.0.tgz", - "integrity": "sha1-gNZJLcFHCGS79YNTO2UfQqn1JBU=" + "node_modules/fast-url-parser": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/fast-url-parser/-/fast-url-parser-1.1.3.tgz", + "integrity": "sha1-9K8+qfNNiicc9YrSs3WfQx8LMY0=", + "dependencies": { + "punycode": "^1.3.2" + } }, - "node_modules/lodash.some": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.some/-/lodash.some-4.6.0.tgz", - "integrity": "sha1-G7nzFO9ri63tE7VJFpsqlF62jk0=" + "node_modules/fast-url-parser/node_modules/punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" }, - "node_modules/lodash.uniq": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", - "integrity": "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=" + "node_modules/fastq": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", + "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", + "dependencies": { + "reusify": "^1.0.4" + } }, - "node_modules/loglevel": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.7.1.tgz", - "integrity": "sha512-Hesni4s5UkWkwCGJMQGAh71PaLUmKFM60dHvq0zi/vDhhrzuk+4GgNbTXJ12YYQJn6ZKBDNIjYcuQGKudvqrIw==", - "engines": { - "node": ">= 0.6.0" + "node_modules/faye-websocket": { + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz", + "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==", + "dependencies": { + "websocket-driver": ">=0.5.1" }, - "funding": { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/loglevel" + "engines": { + "node": ">=0.8.0" } }, - "node_modules/loose-envify": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", - "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "node_modules/fb-watchman": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.1.tgz", + "integrity": "sha512-DkPJKQeY6kKwmuMretBhr7G6Vodr7bFwDYTXIkfG1gjvNpaxBTQV3PbXg6bR1c1UP4jPOX0jHUbbHANL9vRjVg==", + "dev": true, "dependencies": { - "js-tokens": "^3.0.0 || ^4.0.0" - }, - "bin": { - "loose-envify": "cli.js" + "bser": "2.1.1" } }, - "node_modules/lower-case": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", - "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", + "node_modules/fbemitter": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/fbemitter/-/fbemitter-3.0.0.tgz", + "integrity": "sha512-KWKaceCwKQU0+HPoop6gn4eOHk50bBv/VxjJtGMfwmJt3D29JpN4H4eisCtIPA+a8GVBam+ldMMpMjJUvpDyHw==", "dependencies": { - "tslib": "^2.0.3" + "fbjs": "^3.0.0" } }, - "node_modules/lowercase-keys": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", - "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", - "engines": { - "node": ">=0.10.0" + "node_modules/fbjs": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/fbjs/-/fbjs-3.0.4.tgz", + "integrity": "sha512-ucV0tDODnGV3JCnnkmoszb5lf4bNpzjv80K41wd4k798Etq+UYD0y0TIfalLjZoKgjive6/adkRnszwapiDgBQ==", + "dependencies": { + "cross-fetch": "^3.1.5", + "fbjs-css-vars": "^1.0.0", + "loose-envify": "^1.0.0", + "object-assign": "^4.1.0", + "promise": "^7.1.1", + "setimmediate": "^1.0.5", + "ua-parser-js": "^0.7.30" } }, - "node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "node_modules/fbjs-css-vars": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/fbjs-css-vars/-/fbjs-css-vars-1.0.2.tgz", + "integrity": "sha512-b2XGFAFdWZWg0phtAWLHCk836A1Xann+I+Dgd3Gk64MHKZO44FfoD1KxyvbSh0qZsIoXQGGlVztIY+oitJPpRQ==" + }, + "node_modules/fd-slicer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", + "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", + "dev": true, "dependencies": { - "yallist": "^4.0.0" + "pend": "~1.2.0" + } + }, + "node_modules/feed": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/feed/-/feed-4.2.2.tgz", + "integrity": "sha512-u5/sxGfiMfZNtJ3OvQpXcvotFpYkL0n9u9mM2vkui2nGo8b4wvDkJ8gAkYqbA8QpGyFCv3RK0Z+Iv+9veCS9bQ==", + "dependencies": { + "xml-js": "^1.6.11" }, "engines": { - "node": ">=10" + "node": ">=0.4.0" } }, - "node_modules/lunr": { - "version": "2.3.9", - "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz", - "integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==" - }, - "node_modules/make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "node_modules/figures": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", + "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", + "dev": true, "dependencies": { - "semver": "^6.0.0" + "escape-string-regexp": "^1.0.5" }, "engines": { "node": ">=8" @@ -10126,1123 +10263,1210 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/make-dir/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/map-cache": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", - "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", + "node_modules/file-loader": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-6.2.0.tgz", + "integrity": "sha512-qo3glqyTa61Ytg4u73GultjHGjdRyig3tG6lPtyX/jOEJvHif9uB0/OCI2Kif6ctF3caQTW2G5gym21oAsI4pw==", + "dependencies": { + "loader-utils": "^2.0.0", + "schema-utils": "^3.0.0" + }, "engines": { - "node": ">=0.10.0" + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.0.0 || ^5.0.0" } }, - "node_modules/map-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", - "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", + "node_modules/file-loader/node_modules/schema-utils": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", + "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", "dependencies": { - "object-visit": "^1.0.0" + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" }, "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/mark.js": { - "version": "8.11.1", - "resolved": "https://registry.npmjs.org/mark.js/-/mark.js-8.11.1.tgz", - "integrity": "sha1-GA8fnr74sOY45BZq1S24eb6y/8U=" - }, - "node_modules/markdown-escapes": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/markdown-escapes/-/markdown-escapes-1.0.4.tgz", - "integrity": "sha512-8z4efJYk43E0upd0NbVXwgSTQs6cT3T06etieCMEg7dRbzCbxUCK/GHlX8mhHRDcp+OLlHkPKsvqQTCvsRl2cg==", + "node": ">= 10.13.0" + }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "type": "opencollective", + "url": "https://opencollective.com/webpack" } }, - "node_modules/marked": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/marked/-/marked-0.7.0.tgz", - "integrity": "sha512-c+yYdCZJQrsRjTPhUx7VKkApw9bwDkNbHUKo1ovgcfDjb2kc8rLuRbIFyXL5WOEUwzSSKo3IXpph2K6DqB/KZg==", - "bin": { - "marked": "bin/marked" - }, + "node_modules/file-type": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-9.0.0.tgz", + "integrity": "sha512-Qe/5NJrgIOlwijpq3B7BEpzPFcgzggOTagZmkXQY4LA6bsXKTUstK7Wp12lEJ/mLKTpvIZxmIuRcLYWT6ov9lw==", "engines": { - "node": ">=0.10.0" + "node": ">=6" } }, - "node_modules/md5.js": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", - "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", - "dependencies": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1", - "safe-buffer": "^5.1.2" + "node_modules/filesize": { + "version": "8.0.7", + "resolved": "https://registry.npmjs.org/filesize/-/filesize-8.0.7.tgz", + "integrity": "sha512-pjmC+bkIF8XI7fWaH8KxHcZL3DPybs1roSKP4rKDvy20tAWwIObE4+JIseG2byfGKhud5ZnM4YSGKBz7Sh0ndQ==", + "engines": { + "node": ">= 0.4.0" } }, - "node_modules/mdast-squeeze-paragraphs": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mdast-squeeze-paragraphs/-/mdast-squeeze-paragraphs-4.0.0.tgz", - "integrity": "sha512-zxdPn69hkQ1rm4J+2Cs2j6wDEv7O17TfXTJ33tl/+JPIoEmtV9t2ZzBM5LPHE8QlHsmVD8t3vPKCyY3oH+H8MQ==", + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", "dependencies": { - "unist-util-remove": "^2.0.0" + "to-regex-range": "^5.0.1" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "engines": { + "node": ">=8" } }, - "node_modules/mdast-util-definitions": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mdast-util-definitions/-/mdast-util-definitions-4.0.0.tgz", - "integrity": "sha512-k8AJ6aNnUkB7IE+5azR9h81O5EQ/cTDXtWdMq9Kk5KcEW/8ritU5CeLg/9HhOC++nALHBlaogJ5jz0Ybk3kPMQ==", - "dependencies": { - "unist-util-visit": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "node_modules/filter-obj": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/filter-obj/-/filter-obj-2.0.2.tgz", + "integrity": "sha512-lO3ttPjHZRfjMcxWKb1j1eDhTFsu4meeR3lnMcnBFhk6RuLhvEiuALu2TlfL310ph4lCYYwgF/ElIjdP739tdg==", + "engines": { + "node": ">=8" } }, - "node_modules/mdast-util-to-hast": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-10.0.1.tgz", - "integrity": "sha512-BW3LM9SEMnjf4HXXVApZMt8gLQWVNXc3jryK0nJu/rOXPOnlkUjmdkDlmxMirpbU9ILncGFIwLH/ubnWBbcdgA==", + "node_modules/finalhandler": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", + "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", "dependencies": { - "@types/mdast": "^3.0.0", - "@types/unist": "^2.0.0", - "mdast-util-definitions": "^4.0.0", - "mdurl": "^1.0.0", - "unist-builder": "^2.0.0", - "unist-util-generated": "^1.0.0", - "unist-util-position": "^3.0.0", - "unist-util-visit": "^2.0.0" + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "engines": { + "node": ">= 0.8" } }, - "node_modules/mdast-util-to-string": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-2.0.0.tgz", - "integrity": "sha512-AW4DRS3QbBayY/jJmD8437V1Gombjf8RSOUCMFBuo5iHi58AGEgVCKQ+ezHkZZDpAQS75hcBMpLqjpJTjtUL7w==", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "node_modules/finalhandler/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" } }, - "node_modules/mdn-data": { - "version": "2.0.14", - "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz", - "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==" - }, - "node_modules/mdurl": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", - "integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=" + "node_modules/finalhandler/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, - "node_modules/media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", + "node_modules/find-cache-dir": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", + "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", + "dependencies": { + "commondir": "^1.0.1", + "make-dir": "^3.0.2", + "pkg-dir": "^4.1.0" + }, "engines": { - "node": ">= 0.6" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/avajs/find-cache-dir?sponsor=1" } }, - "node_modules/memoize-one": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.2.1.tgz", - "integrity": "sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q==" - }, - "node_modules/memory-fs": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", - "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=", + "node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dependencies": { - "errno": "^0.1.3", - "readable-stream": "^2.0.1" + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" } }, - "node_modules/memory-fs/node_modules/readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "node_modules/flux": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/flux/-/flux-4.0.3.tgz", + "integrity": "sha512-yKAbrp7JhZhj6uiT1FTuVMlIAT1J4jqEyBpFApi1kxpGZCvacMVc/t1pMQyotqHhAgvoE3bNvAykhCo2CLjnYw==", "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" + "fbemitter": "^3.0.0", + "fbjs": "^3.0.1" + }, + "peerDependencies": { + "react": "^15.0.2 || ^16.0.0 || ^17.0.0" } }, - "node_modules/memory-fs/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dependencies": { - "safe-buffer": "~5.1.0" + "node_modules/follow-redirects": { + "version": "1.14.9", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.9.tgz", + "integrity": "sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } } }, - "node_modules/merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" - }, - "node_modules/merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==" + "node_modules/foreach": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz", + "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=" }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "node_modules/forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==", + "dev": true, "engines": { - "node": ">= 8" + "node": "*" } }, - "node_modules/methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", + "node_modules/fork-ts-checker-webpack-plugin": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-6.5.2.tgz", + "integrity": "sha512-m5cUmF30xkZ7h4tWUgTAcEaKmUW7tfyUyTqNNOz7OxWJ0v1VWKTcOvH8FWHUwSjlW/356Ijc9vi3XfcPstpQKA==", + "dependencies": { + "@babel/code-frame": "^7.8.3", + "@types/json-schema": "^7.0.5", + "chalk": "^4.1.0", + "chokidar": "^3.4.2", + "cosmiconfig": "^6.0.0", + "deepmerge": "^4.2.2", + "fs-extra": "^9.0.0", + "glob": "^7.1.6", + "memfs": "^3.1.2", + "minimatch": "^3.0.4", + "schema-utils": "2.7.0", + "semver": "^7.3.2", + "tapable": "^1.0.0" + }, "engines": { - "node": ">= 0.6" + "node": ">=10", + "yarn": ">=1.0.0" + }, + "peerDependencies": { + "eslint": ">= 6", + "typescript": ">= 2.7", + "vue-template-compiler": "*", + "webpack": ">= 4" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + }, + "vue-template-compiler": { + "optional": true + } } }, - "node_modules/microevent.ts": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/microevent.ts/-/microevent.ts-0.1.1.tgz", - "integrity": "sha512-jo1OfR4TaEwd5HOrt5+tAZ9mqT4jmpNAusXtyfNzqVm9uiSYFZlKM1wYL4oU7azZW/PxQW53wM0S6OR1JHNa2g==" - }, - "node_modules/micromatch": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", - "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", + "node_modules/fork-ts-checker-webpack-plugin/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dependencies": { - "braces": "^3.0.1", - "picomatch": "^2.2.3" + "color-convert": "^2.0.1" }, "engines": { - "node": ">=8.6" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/miller-rabin": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", - "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", + "node_modules/fork-ts-checker-webpack-plugin/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dependencies": { - "bn.js": "^4.0.0", - "brorand": "^1.0.1" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, - "bin": { - "miller-rabin": "bin/miller-rabin" + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/miller-rabin/node_modules/bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" - }, - "node_modules/mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "bin": { - "mime": "cli.js" + "node_modules/fork-ts-checker-webpack-plugin/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" }, "engines": { - "node": ">=4" + "node": ">=7.0.0" } }, - "node_modules/mime-db": { - "version": "1.50.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.50.0.tgz", - "integrity": "sha512-9tMZCDlYHqeERXEHO9f/hKfNXhre5dK2eE/krIvUjZbS2KPcqGDfNShIWS1uW9XOTKQKqK6qbeOci18rbfW77A==", - "engines": { - "node": ">= 0.6" - } + "node_modules/fork-ts-checker-webpack-plugin/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, - "node_modules/mime-types": { - "version": "2.1.33", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.33.tgz", - "integrity": "sha512-plLElXp7pRDd0bNZHw+nMd52vRYjLwQjygaNg7ddJ2uJtTlmnTCjWuPKxVu6//AdaRuME84SvLW91sIkBqGT0g==", + "node_modules/fork-ts-checker-webpack-plugin/node_modules/cosmiconfig": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-6.0.0.tgz", + "integrity": "sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg==", "dependencies": { - "mime-db": "1.50.0" + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.1.0", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.7.2" }, "engines": { - "node": ">= 0.6" + "node": ">=8" } }, - "node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "node_modules/fork-ts-checker-webpack-plugin/node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, "engines": { - "node": ">=6" + "node": ">=10" } }, - "node_modules/mimic-response": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", - "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", + "node_modules/fork-ts-checker-webpack-plugin/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "engines": { - "node": ">=4" + "node": ">=8" } }, - "node_modules/min-document": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/min-document/-/min-document-2.19.0.tgz", - "integrity": "sha1-e9KC4/WELtKVu3SM3Z8f+iyCRoU=", + "node_modules/fork-ts-checker-webpack-plugin/node_modules/schema-utils": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.0.tgz", + "integrity": "sha512-0ilKFI6QQF5nxDZLFn2dMjvc4hjg/Wkg7rHd3jK6/A4a1Hl9VFdQWvgB1UMGoU94pad1P/8N7fMcEnLnSiju8A==", "dependencies": { - "dom-walk": "^0.1.0" + "@types/json-schema": "^7.0.4", + "ajv": "^6.12.2", + "ajv-keywords": "^3.4.1" + }, + "engines": { + "node": ">= 8.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" } }, - "node_modules/mini-create-react-context": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/mini-create-react-context/-/mini-create-react-context-0.4.1.tgz", - "integrity": "sha512-YWCYEmd5CQeHGSAKrYvXgmzzkrvssZcuuQDDeqkT+PziKGMgE+0MCCtcKbROzocGBG1meBLl2FotlRwf4gAzbQ==", + "node_modules/fork-ts-checker-webpack-plugin/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dependencies": { - "@babel/runtime": "^7.12.1", - "tiny-warning": "^1.0.3" + "has-flag": "^4.0.0" }, - "peerDependencies": { - "prop-types": "^15.0.0", - "react": "^0.14.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" + "engines": { + "node": ">=8" } }, - "node_modules/mini-css-extract-plugin": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-1.6.2.tgz", - "integrity": "sha512-WhDvO3SjGm40oV5y26GjMJYjd2UMqrLAGKy5YS2/3QKJy2F7jgynuHTir/tgUUOiNQu5saXHdc8reo7YuhhT4Q==", + "node_modules/fork-ts-checker-webpack-plugin/node_modules/tapable": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", + "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/form-data": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", + "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==", + "dev": true, "dependencies": { - "loader-utils": "^2.0.0", - "schema-utils": "^3.0.0", - "webpack-sources": "^1.1.0" + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" }, "engines": { - "node": ">= 10.13.0" + "node": ">= 6" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fraction.js": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.2.0.tgz", + "integrity": "sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA==", + "engines": { + "node": "*" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^4.4.0 || ^5.0.0" + "type": "patreon", + "url": "https://www.patreon.com/infusion" } }, - "node_modules/mini-css-extract-plugin/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", "engines": { - "node": ">=0.10.0" + "node": ">= 0.6" } }, - "node_modules/mini-css-extract-plugin/node_modules/webpack-sources": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", - "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", + "node_modules/fs": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/fs/-/fs-0.0.2.tgz", + "integrity": "sha1-4fJE7zkzwbKmS9R5kTYGDQ9ZFPg=" + }, + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, + "node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", "dependencies": { - "source-list-map": "^2.0.0", - "source-map": "~0.6.1" + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" } }, - "node_modules/minimalistic-assert": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", - "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" + "node_modules/fs-monkey": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.3.tgz", + "integrity": "sha512-cybjIfiiE+pTWicSCLFHSrXZ6EilF30oh91FDP9S2B051prEa7QWfrVTQm10/dDpswBDXZugPa1Ogu8Yh+HV0Q==" }, - "node_modules/minimalistic-crypto-utils": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", - "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=" + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" }, - "node_modules/minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dependencies": { - "brace-expansion": "^1.1.7" - }, + "node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": "*" + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, - "node_modules/minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" }, - "node_modules/mixin-deep": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", - "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", + "node_modules/gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", + "dependencies": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "node_modules/gauge/node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/gauge/node_modules/is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", "dependencies": { - "for-in": "^1.0.2", - "is-extendable": "^1.0.1" + "number-is-nan": "^1.0.0" }, "engines": { "node": ">=0.10.0" } }, - "node_modules/mixin-deep/node_modules/is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "node_modules/gauge/node_modules/string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", "dependencies": { - "is-plain-object": "^2.0.4" + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" }, "engines": { "node": ">=0.10.0" } }, - "node_modules/mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "node_modules/gauge/node_modules/strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "dependencies": { - "minimist": "^1.2.5" + "ansi-regex": "^2.0.0" }, - "bin": { - "mkdirp": "bin/cmd.js" + "engines": { + "node": ">=0.10.0" } }, - "node_modules/mkdirp-classic": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", - "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "engines": { + "node": ">=6.9.0" + } }, - "node_modules/mobx": { - "version": "6.3.3", - "resolved": "https://registry.npmjs.org/mobx/-/mobx-6.3.3.tgz", - "integrity": "sha512-JoNU50rO6d1wHwKPJqKq4rmUMbYnI9CsJmBo+Cu4exBYenFvIN77LWrZENpzW6reZPADtXMmB1DicbDSfy8Clw==", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mobx" + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "engines": { + "node": "6.* || 8.* || >= 10.*" } }, - "node_modules/mobx-react": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/mobx-react/-/mobx-react-7.2.0.tgz", - "integrity": "sha512-KHUjZ3HBmZlNnPd1M82jcdVsQRDlfym38zJhZEs33VxyVQTvL77hODCArq6+C1P1k/6erEeo2R7rpE7ZeOL7dg==", + "node_modules/get-intrinsic": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", + "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", "dependencies": { - "mobx-react-lite": "^3.2.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mobx" - }, - "peerDependencies": { - "mobx": "^6.1.0", - "react": "^16.8.0 || ^17" + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1" }, - "peerDependenciesMeta": { - "react-dom": { - "optional": true - }, - "react-native": { - "optional": true - } + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/mobx-react-lite": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/mobx-react-lite/-/mobx-react-lite-3.2.1.tgz", - "integrity": "sha512-hwURgfmP2apX3HQrB55V9DN47kuN3C6KlQvI5UIfJRibXma72C/JudcNt2r9dWjAdFMrcZoz1ivvtXMCkJ2aQA==", + "node_modules/get-own-enumerable-property-symbols": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz", + "integrity": "sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g==" + }, + "node_modules/get-package-type": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", + "dev": true, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "engines": { + "node": ">=10" + }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mobx" + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-symbol-description": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", + "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" }, - "peerDependencies": { - "mobx": "^6.1.0", - "react": "^16.8.0 || ^17" + "engines": { + "node": ">= 0.4" }, - "peerDependenciesMeta": { - "react-dom": { - "optional": true - }, - "react-native": { - "optional": true - } + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/module-alias": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/module-alias/-/module-alias-2.2.2.tgz", - "integrity": "sha512-A/78XjoX2EmNvppVWEhM2oGk3x4lLxnkEA4jTbaK97QKSDjkIoOsKQlfylt/d3kKKi596Qy3NP5XrXJ6fZIC9Q==" + "node_modules/getos": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/getos/-/getos-3.2.1.tgz", + "integrity": "sha512-U56CfOK17OKgTVqozZjUKNdkfEv6jk5WISBJ8SHoagjE6L69zOwl3Z+O8myjY9MEW3i2HPWQBt/LTbCgcC973Q==", + "dev": true, + "dependencies": { + "async": "^3.2.0" + } }, - "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + "node_modules/getos/node_modules/async": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", + "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==", + "dev": true }, - "node_modules/multicast-dns": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-6.2.3.tgz", - "integrity": "sha512-ji6J5enbMyGRHIAkAOu3WdV8nggqviKCEKtXcOqfphZZtQrmHKycfynJ2V7eVPUA4NhJ6V7Wf4TmGbTwKE9B6g==", + "node_modules/getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==", + "dev": true, "dependencies": { - "dns-packet": "^1.3.1", - "thunky": "^1.0.2" - }, - "bin": { - "multicast-dns": "cli.js" + "assert-plus": "^1.0.0" } }, - "node_modules/multicast-dns-service-types": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz", - "integrity": "sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE=" + "node_modules/gifwrap": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/gifwrap/-/gifwrap-0.9.4.tgz", + "integrity": "sha512-MDMwbhASQuVeD4JKd1fKgNgCRL3fGqMM4WaqpNhWO0JiMOAjbQdumbs4BbBZEy9/M00EHEjKN3HieVhCUlwjeQ==", + "dependencies": { + "image-q": "^4.0.0", + "omggif": "^1.0.10" + } }, - "node_modules/nan": { - "version": "2.15.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.15.0.tgz", - "integrity": "sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ==", - "optional": true + "node_modules/github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha1-l/tdlr/eiXMxPyDoKI75oWf6ZM4=" }, - "node_modules/nanocolors": { - "version": "0.1.12", - "resolved": "https://registry.npmjs.org/nanocolors/-/nanocolors-0.1.12.tgz", - "integrity": "sha512-2nMHqg1x5PU+unxX7PGY7AuYxl2qDx7PSrTRjizr8sxdd3l/3hBuWWaki62qmtYm2U5i4Z5E7GbjlyDFhs9/EQ==" + "node_modules/github-slugger": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/github-slugger/-/github-slugger-1.4.0.tgz", + "integrity": "sha512-w0dzqw/nt51xMVmlaV1+JRzN+oCa1KfcgGEWhxUG16wbdA+Xnt/yoFO8Z8x/V82ZcZ0wy6ln9QDup5avbhiDhQ==" }, - "node_modules/nanoid": { - "version": "3.1.29", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.29.tgz", - "integrity": "sha512-dW2pUSGZ8ZnCFIlBIA31SV8huOGCHb6OwzVCc7A69rb/a+SgPBwfmLvK5TKQ3INPbRkcI8a/Owo0XbiTNH19wg==", - "bin": { - "nanoid": "bin/nanoid.cjs" + "node_modules/glob": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" }, "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/nanomatch": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", - "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dependencies": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "fragment-cache": "^0.2.1", - "is-windows": "^1.0.2", - "kind-of": "^6.0.2", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" + "is-glob": "^4.0.1" }, "engines": { - "node": ">=0.10.0" + "node": ">= 6" } }, - "node_modules/nanomatch/node_modules/extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "node_modules/glob-to-regexp": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==" + }, + "node_modules/global": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/global/-/global-4.4.0.tgz", + "integrity": "sha512-wv/LAoHdRE3BeTGz53FAamhGlPLhlssK45usmGFThIi4XqnBmjKQ16u+RNbP7WvigRZDxUsM0J3gcQ5yicaL0w==", "dependencies": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" + "min-document": "^2.19.0", + "process": "^0.11.10" } }, - "node_modules/nanomatch/node_modules/is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "node_modules/global-dirs": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-3.0.0.tgz", + "integrity": "sha512-v8ho2DS5RiCjftj1nD9NmnfaOzTdud7RRnVd9kFNOjqZbISlx5DQ+OrTkywgd0dIt7oFCvKetZSHoHcP3sDdiA==", "dependencies": { - "is-plain-object": "^2.0.4" + "ini": "2.0.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/napi-build-utils": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", - "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==" - }, - "node_modules/negotiator": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", - "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==", + "node_modules/global-dirs/node_modules/ini": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz", + "integrity": "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==", "engines": { - "node": ">= 0.6" + "node": ">=10" } }, - "node_modules/neo-async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" - }, - "node_modules/nice-try": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", - "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==" - }, - "node_modules/no-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", - "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", + "node_modules/global-modules": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz", + "integrity": "sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==", "dependencies": { - "lower-case": "^2.0.2", - "tslib": "^2.0.3" + "global-prefix": "^3.0.0" + }, + "engines": { + "node": ">=6" } }, - "node_modules/node-abi": { - "version": "2.30.1", - "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.30.1.tgz", - "integrity": "sha512-/2D0wOQPgaUWzVSVgRMx+trKJRC2UG4SUc4oCJoXx9Uxjtp0Vy3/kt7zcbxHF8+Z/pK3UloLWzBISg72brfy1w==", + "node_modules/global-prefix": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz", + "integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==", "dependencies": { - "semver": "^5.4.1" - } - }, - "node_modules/node-abi/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "bin": { - "semver": "bin/semver" + "ini": "^1.3.5", + "kind-of": "^6.0.2", + "which": "^1.3.1" + }, + "engines": { + "node": ">=6" } }, - "node_modules/node-addon-api": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.2.1.tgz", - "integrity": "sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A==" - }, - "node_modules/node-emoji": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-1.11.0.tgz", - "integrity": "sha512-wo2DpQkQp7Sjm2A0cq+sN7EHKO6Sl0ctXeBdFZrL9T9+UywORbufTcTZxom8YqpLQt/FqNMUkOpkZrJVYSKD3A==", + "node_modules/global-prefix/node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", "dependencies": { - "lodash": "^4.17.21" + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" } }, - "node_modules/node-fetch": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz", - "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==", + "node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", "engines": { - "node": "4.x || >=6.0.0" + "node": ">=4" } }, - "node_modules/node-fetch-h2": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/node-fetch-h2/-/node-fetch-h2-2.3.0.tgz", - "integrity": "sha512-ofRW94Ab0T4AOh5Fk8t0h8OBWrmjb0SSB20xh1H8YnPV9EJ+f5AMoYSUQ2zgJ4Iq2HAK0I2l5/Nequ8YzFS3Hg==", + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", "dependencies": { - "http2-client": "^1.2.5" + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" }, "engines": { - "node": "4.x || >=6.0.0" - } - }, - "node_modules/node-forge": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.10.0.tgz", - "integrity": "sha512-PPmu8eEeG9saEUvI97fm4OYxXVB6bFvyNTyiUOBichBpFG8A1Ljw3bY62+5oOjDEMHRnd0Y7HQ+x7uzxOzC6JA==", - "engines": { - "node": ">= 6.0.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/node-polyfill-webpack-plugin": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/node-polyfill-webpack-plugin/-/node-polyfill-webpack-plugin-1.1.4.tgz", - "integrity": "sha512-Z0XTKj1wRWO8o/Vjobsw5iOJCN+Sua3EZEUc2Ziy9CyVvmHKu6o+t4gUH9GOE0czyPR94LI6ZCV/PpcM8b5yow==", + "node_modules/got": { + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", + "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==", "dependencies": { - "assert": "^2.0.0", - "browserify-zlib": "^0.2.0", - "buffer": "^6.0.3", - "console-browserify": "^1.2.0", - "constants-browserify": "^1.0.0", - "crypto-browserify": "^3.12.0", - "domain-browser": "^4.19.0", - "events": "^3.3.0", - "filter-obj": "^2.0.2", - "https-browserify": "^1.0.0", - "os-browserify": "^0.3.0", - "path-browserify": "^1.0.1", - "process": "^0.11.10", - "punycode": "^2.1.1", - "querystring-es3": "^0.2.1", - "readable-stream": "^3.6.0", - "stream-browserify": "^3.0.0", - "stream-http": "^3.2.0", - "string_decoder": "^1.3.0", - "timers-browserify": "^2.0.12", - "tty-browserify": "^0.0.1", - "url": "^0.11.0", - "util": "^0.12.4", - "vm-browserify": "^1.1.2" + "@sindresorhus/is": "^0.14.0", + "@szmarczak/http-timer": "^1.1.2", + "cacheable-request": "^6.0.0", + "decompress-response": "^3.3.0", + "duplexer3": "^0.1.4", + "get-stream": "^4.1.0", + "lowercase-keys": "^1.0.1", + "mimic-response": "^1.0.1", + "p-cancelable": "^1.0.0", + "to-readable-stream": "^1.0.0", + "url-parse-lax": "^3.0.0" }, "engines": { - "node": ">=10" - }, - "peerDependencies": { - "webpack": ">=5" + "node": ">=8.6" } }, - "node_modules/node-polyfill-webpack-plugin/node_modules/buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], + "node_modules/got/node_modules/decompress-response": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", + "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" + "mimic-response": "^1.0.0" + }, + "engines": { + "node": ">=4" } }, - "node_modules/node-readfiles": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/node-readfiles/-/node-readfiles-0.2.0.tgz", - "integrity": "sha1-271K8SE04uY1wkXvk//Pb2BnOl0=", + "node_modules/got/node_modules/get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", "dependencies": { - "es6-promise": "^3.2.1" + "pump": "^3.0.0" + }, + "engines": { + "node": ">=6" } }, - "node_modules/node-releases": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.0.tgz", - "integrity": "sha512-aA87l0flFYMzCHpTM3DERFSYxc6lv/BltdbRTOMZuxZ0cwZCD3mejE5n9vLhSJCN++/eOqr77G1IO5uXxlQYWA==" - }, - "node_modules/node-vibrant": { - "version": "3.1.6", - "resolved": "https://registry.npmjs.org/node-vibrant/-/node-vibrant-3.1.6.tgz", - "integrity": "sha512-Wlc/hQmBMOu6xon12ZJHS2N3M+I6J8DhrD3Yo6m5175v8sFkVIN+UjhKVRcO+fqvre89ASTpmiFEP3nPO13SwA==", - "dependencies": { - "@jimp/custom": "^0.16.1", - "@jimp/plugin-resize": "^0.16.1", - "@jimp/types": "^0.16.1", - "@types/lodash": "^4.14.53", - "@types/node": "^10.11.7", - "lodash": "^4.17.20", - "url": "^0.11.0" + "node_modules/got/node_modules/mimic-response": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", + "engines": { + "node": ">=4" } }, - "node_modules/node-vibrant/node_modules/@types/node": { - "version": "10.17.60", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.60.tgz", - "integrity": "sha512-F0KIgDJfy2nA3zMLmWGKxcH2ZVEtCZXHHdOQs2gSaQ27+lNeEfGxzkIw90aXswATX7AZ33tahPbzy6KAfUreVw==" + "node_modules/graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "node_modules/gray-matter": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/gray-matter/-/gray-matter-4.0.3.tgz", + "integrity": "sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q==", + "dependencies": { + "js-yaml": "^3.13.1", + "kind-of": "^6.0.2", + "section-matter": "^1.0.0", + "strip-bom-string": "^1.0.0" + }, "engines": { - "node": ">=0.10.0" + "node": ">=6.0" } }, - "node_modules/normalize-range": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", - "integrity": "sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=", - "engines": { - "node": ">=0.10.0" + "node_modules/gray-matter/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dependencies": { + "sprintf-js": "~1.0.2" } }, - "node_modules/normalize-url": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", - "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", - "engines": { - "node": ">=10" + "node_modules/gray-matter/node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "bin": { + "js-yaml": "bin/js-yaml.js" } }, - "node_modules/npm-run-path": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", - "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "node_modules/gzip-size": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-6.0.0.tgz", + "integrity": "sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q==", "dependencies": { - "path-key": "^2.0.0" + "duplexer": "^0.1.2" }, "engines": { - "node": ">=4" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/npm-run-path/node_modules/path-key": { + "node_modules/handle-thing": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", - "engines": { - "node": ">=4" - } + "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", + "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==" }, - "node_modules/npmlog": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", - "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", "dependencies": { - "are-we-there-yet": "~1.1.2", - "console-control-strings": "~1.1.0", - "gauge": "~2.7.3", - "set-blocking": "~2.0.0" + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" } }, - "node_modules/nprogress": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/nprogress/-/nprogress-0.2.0.tgz", - "integrity": "sha1-y480xTIT2JVyP8urkH6UIq28r7E=" - }, - "node_modules/nth-check": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.0.1.tgz", - "integrity": "sha512-it1vE95zF6dTT9lBsYbxvqh0Soy4SPowchj0UBGj/V6cTPnXXtQOPUbhZ6CmGzAD/rW22LQK6E96pcdJXk4A4w==", - "dependencies": { - "boolbase": "^1.0.0" - }, + "node_modules/has-bigints": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", + "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", "funding": { - "url": "https://github.com/fb55/nth-check?sponsor=1" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/number-is-nan": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", "engines": { - "node": ">=0.10.0" + "node": ">=4" } }, - "node_modules/oas-kit-common": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/oas-kit-common/-/oas-kit-common-1.0.8.tgz", - "integrity": "sha512-pJTS2+T0oGIwgjGpw7sIRU8RQMcUoKCDWFLdBqKB2BNmGpbBMH2sdqAaOXUg8OzonZHU0L7vfJu1mJFEiYDWOQ==", + "node_modules/has-property-descriptors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", + "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", "dependencies": { - "fast-safe-stringify": "^2.0.7" + "get-intrinsic": "^1.1.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/oas-linter": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/oas-linter/-/oas-linter-3.2.2.tgz", - "integrity": "sha512-KEGjPDVoU5K6swgo9hJVA/qYGlwfbFx+Kg2QB/kd7rzV5N8N5Mg6PlsoCMohVnQmo+pzJap/F610qTodKzecGQ==", - "dependencies": { - "@exodus/schemasafe": "^1.0.0-rc.2", - "should": "^13.2.1", - "yaml": "^1.10.0" + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "engines": { + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/Mermade/oas-kit?sponsor=1" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/oas-resolver": { - "version": "2.5.6", - "resolved": "https://registry.npmjs.org/oas-resolver/-/oas-resolver-2.5.6.tgz", - "integrity": "sha512-Yx5PWQNZomfEhPPOphFbZKi9W93CocQj18NlD2Pa4GWZzdZpSJvYwoiuurRI7m3SpcChrnO08hkuQDL3FGsVFQ==", + "node_modules/has-tostringtag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", + "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", "dependencies": { - "node-fetch-h2": "^2.3.0", - "oas-kit-common": "^1.0.8", - "reftools": "^1.1.9", - "yaml": "^1.10.0", - "yargs": "^17.0.1" + "has-symbols": "^1.0.2" }, - "bin": { - "resolve": "resolve.js" + "engines": { + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/Mermade/oas-kit?sponsor=1" - } - }, - "node_modules/oas-resolver/node_modules/cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/oas-resolver/node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "node_modules/has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=" + }, + "node_modules/has-yarn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/has-yarn/-/has-yarn-2.1.0.tgz", + "integrity": "sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw==", "engines": { - "node": ">=10" + "node": ">=8" } }, - "node_modules/oas-resolver/node_modules/yargs": { - "version": "17.2.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.2.1.tgz", - "integrity": "sha512-XfR8du6ua4K6uLGm5S6fA+FIJom/MdJcFNVY8geLlp2v8GYbOXD4EB1tPNZsRn4vBzKGMgb5DRZMeWuFc2GO8Q==", + "node_modules/hash-base": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", + "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", "dependencies": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" + "inherits": "^2.0.4", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" }, "engines": { - "node": ">=12" - } - }, - "node_modules/oas-resolver/node_modules/yargs-parser": { - "version": "20.2.9", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", - "engines": { - "node": ">=10" + "node": ">=4" } }, - "node_modules/oas-schema-walker": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/oas-schema-walker/-/oas-schema-walker-1.1.5.tgz", - "integrity": "sha512-2yucenq1a9YPmeNExoUa9Qwrt9RFkjqaMAA1X+U7sbb0AqBeTIdMHky9SQQ6iN94bO5NW0W4TRYXerG+BdAvAQ==", - "funding": { - "url": "https://github.com/Mermade/oas-kit?sponsor=1" - } + "node_modules/hash-base/node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] }, - "node_modules/oas-validator": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/oas-validator/-/oas-validator-5.0.8.tgz", - "integrity": "sha512-cu20/HE5N5HKqVygs3dt94eYJfBi0TsZvPVXDhbXQHiEityDN+RROTleefoKRKKJ9dFAF2JBkDHgvWj0sjKGmw==", + "node_modules/hash.js": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", + "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", "dependencies": { - "call-me-maybe": "^1.0.1", - "oas-kit-common": "^1.0.8", - "oas-linter": "^3.2.2", - "oas-resolver": "^2.5.6", - "oas-schema-walker": "^1.1.5", - "reftools": "^1.1.9", - "should": "^13.2.1", - "yaml": "^1.10.0" - }, - "funding": { - "url": "https://github.com/Mermade/oas-kit?sponsor=1" - } - }, - "node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "engines": { - "node": ">=0.10.0" + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" } }, - "node_modules/object-copy": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", - "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", + "node_modules/hast-to-hyperscript": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/hast-to-hyperscript/-/hast-to-hyperscript-9.0.1.tgz", + "integrity": "sha512-zQgLKqF+O2F72S1aa4y2ivxzSlko3MAvxkwG8ehGmNiqd98BIN3JM1rAJPmplEyLmGLO2QZYJtIneOSZ2YbJuA==", "dependencies": { - "copy-descriptor": "^0.1.0", - "define-property": "^0.2.5", - "kind-of": "^3.0.3" + "@types/unist": "^2.0.3", + "comma-separated-tokens": "^1.0.0", + "property-information": "^5.3.0", + "space-separated-tokens": "^1.0.0", + "style-to-object": "^0.3.0", + "unist-util-is": "^4.0.0", + "web-namespaces": "^1.0.0" }, - "engines": { - "node": ">=0.10.0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/object-copy/node_modules/define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "node_modules/hast-util-from-parse5": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-6.0.1.tgz", + "integrity": "sha512-jeJUWiN5pSxW12Rh01smtVkZgZr33wBokLzKLwinYOUfSzm1Nl/c3GUGebDyOKjdsRgMvoVbV0VpAcpjF4NrJA==", "dependencies": { - "is-descriptor": "^0.1.0" + "@types/parse5": "^5.0.0", + "hastscript": "^6.0.0", + "property-information": "^5.0.0", + "vfile": "^4.0.0", + "vfile-location": "^3.2.0", + "web-namespaces": "^1.0.0" }, - "engines": { - "node": ">=0.10.0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/object-copy/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" + "node_modules/hast-util-is-element": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/hast-util-is-element/-/hast-util-is-element-1.1.0.tgz", + "integrity": "sha512-oUmNua0bFbdrD/ELDSSEadRVtWZOf3iF6Lbv81naqsIV99RnSCieTbWuWCY8BAeEfKJTKl0gRdokv+dELutHGQ==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/object-inspect": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.11.0.tgz", - "integrity": "sha512-jp7ikS6Sd3GxQfZJPyH3cjcbJF6GZPClgdV+EFygjFLQ5FmW/dRUnTd9PQ9k0JhoNDabWFbpF1yCdSWCC6gexg==", + "node_modules/hast-util-parse-selector": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-2.2.5.tgz", + "integrity": "sha512-7j6mrk/qqkSehsM92wQjdIgWM2/BW61u/53G6xmC8i1OmEdKLHbk419QKQUjz6LglWsfqoiHmyMRkP1BGjecNQ==", "funding": { - "url": "https://github.com/sponsors/ljharb" + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/object-is": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz", - "integrity": "sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==", + "node_modules/hast-util-raw": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/hast-util-raw/-/hast-util-raw-6.0.1.tgz", + "integrity": "sha512-ZMuiYA+UF7BXBtsTBNcLBF5HzXzkyE6MLzJnL605LKE8GJylNjGc4jjxazAHUtcwT5/CEt6afRKViYB4X66dig==", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" - }, - "engines": { - "node": ">= 0.4" + "@types/hast": "^2.0.0", + "hast-util-from-parse5": "^6.0.0", + "hast-util-to-parse5": "^6.0.0", + "html-void-elements": "^1.0.0", + "parse5": "^6.0.0", + "unist-util-position": "^3.0.0", + "vfile": "^4.0.0", + "web-namespaces": "^1.0.0", + "xtend": "^4.0.0", + "zwitch": "^1.0.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "engines": { - "node": ">= 0.4" + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/object-visit": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", - "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", + "node_modules/hast-util-to-parse5": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/hast-util-to-parse5/-/hast-util-to-parse5-6.0.0.tgz", + "integrity": "sha512-Lu5m6Lgm/fWuz8eWnrKezHtVY83JeRGaNQ2kn9aJgqaxvVkFCZQBEhgodZUDUvoodgyROHDb3r5IxAEdl6suJQ==", "dependencies": { - "isobject": "^3.0.0" + "hast-to-hyperscript": "^9.0.0", + "property-information": "^5.0.0", + "web-namespaces": "^1.0.0", + "xtend": "^4.0.0", + "zwitch": "^1.0.0" }, - "engines": { - "node": ">=0.10.0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/object.assign": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", - "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", + "node_modules/hast-util-to-text": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/hast-util-to-text/-/hast-util-to-text-2.0.1.tgz", + "integrity": "sha512-8nsgCARfs6VkwH2jJU9b8LNTuR4700na+0h3PqCaEk4MAnMDeu5P0tP8mjk9LLNGxIeQRLbiDbZVw6rku+pYsQ==", "dependencies": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3", - "has-symbols": "^1.0.1", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" + "hast-util-is-element": "^1.0.0", + "repeat-string": "^1.0.0", + "unist-util-find-after": "^3.0.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/object.getownpropertydescriptors": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.3.tgz", - "integrity": "sha512-VdDoCwvJI4QdC6ndjpqFmoL3/+HxffFBbcJzKi5hwLLqqx3mdbedRpfZDdK0SrOSauj8X4GzBvnDZl4vTN7dOw==", + "node_modules/hastscript": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/hastscript/-/hastscript-6.0.0.tgz", + "integrity": "sha512-nDM6bvd7lIqDUiYEiu5Sl/+6ReP0BMk/2f4U/Rooccxkj0P5nm+acM5PrGJ/t5I8qPGiqZSE6hVAwZEdZIvP4w==", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.1" - }, - "engines": { - "node": ">= 0.8" + "@types/hast": "^2.0.0", + "comma-separated-tokens": "^1.0.0", + "hast-util-parse-selector": "^2.0.0", + "property-information": "^5.0.0", + "space-separated-tokens": "^1.0.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/object.pick": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", - "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", - "dependencies": { - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "bin": { + "he": "bin/he" } }, - "node_modules/object.values": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.5.tgz", - "integrity": "sha512-QUZRW0ilQ3PnPpbNtgdNV1PDbEqLIiSFB3l+EnGtBQ/8SUTLj1PZwtQHABZtLgwpJZTSZhuGLOGk57Drx2IvYg==", + "node_modules/history": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/history/-/history-4.10.1.tgz", + "integrity": "sha512-36nwAD620w12kuzPAsyINPWJqlNbij+hpK1k9XRloDtym8mxzGYl2c17LnV6IAGB2Dmg4tEa7G7DlawS0+qjew==", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "@babel/runtime": "^7.1.2", + "loose-envify": "^1.2.0", + "resolve-pathname": "^3.0.0", + "tiny-invariant": "^1.0.2", + "tiny-warning": "^1.0.0", + "value-equal": "^1.0.1" } }, - "node_modules/obuf": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", - "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==" + "node_modules/hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", + "dependencies": { + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" + } }, - "node_modules/omggif": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/omggif/-/omggif-1.0.10.tgz", - "integrity": "sha512-LMJTtvgc/nugXj0Vcrrs68Mn2D1r0zf630VNtqtpI1FEO7e+O9FP4gqs9AcnBaSEeoHIPm28u6qgPR0oyEpGSw==" + "node_modules/hoist-non-react-statics": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", + "dependencies": { + "react-is": "^16.7.0" + } }, - "node_modules/on-finished": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "node_modules/hoist-non-react-statics/node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + }, + "node_modules/hpack.js": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", + "integrity": "sha1-h3dMCUnlE/QuhFdbPEVoH63ioLI=", "dependencies": { - "ee-first": "1.1.1" - }, - "engines": { - "node": ">= 0.8" + "inherits": "^2.0.1", + "obuf": "^1.0.0", + "readable-stream": "^2.0.1", + "wbuf": "^1.1.0" } }, - "node_modules/on-headers": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", - "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", - "engines": { - "node": ">= 0.8" + "node_modules/hpack.js/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "node_modules/hpack.js/node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" } }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "node_modules/hpack.js/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dependencies": { - "wrappy": "1" + "safe-buffer": "~5.1.0" } }, - "node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "node_modules/html-encoding-sniffer": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz", + "integrity": "sha512-D5JbOMBIR/TVZkubHT+OyT2705QvogUW4IBn6nHd756OwieSF9aDYFj4dv6HHEVGYbHaLETa3WggZYWWMyy3ZQ==", + "dev": true, "dependencies": { - "mimic-fn": "^2.1.0" + "whatwg-encoding": "^1.0.5" }, "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=10" } }, - "node_modules/open": { - "version": "7.4.2", - "resolved": "https://registry.npmjs.org/open/-/open-7.4.2.tgz", - "integrity": "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==", + "node_modules/html-entities": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.3.3.tgz", + "integrity": "sha512-DV5Ln36z34NNTDgnz0EWGBLZENelNAtkiFA4kyNOG2tDI6Mz1uSWiq1wAKdyjnJwyDiDO7Fa2SO1CTxPXL8VxA==" + }, + "node_modules/html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true + }, + "node_modules/html-minifier-terser": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", + "integrity": "sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw==", "dependencies": { - "is-docker": "^2.0.0", - "is-wsl": "^2.1.1" + "camel-case": "^4.1.2", + "clean-css": "^5.2.2", + "commander": "^8.3.0", + "he": "^1.2.0", + "param-case": "^3.0.4", + "relateurl": "^0.2.7", + "terser": "^5.10.0" + }, + "bin": { + "html-minifier-terser": "cli.js" }, + "engines": { + "node": ">=12" + } + }, + "node_modules/html-minifier-terser/node_modules/commander": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", + "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", + "engines": { + "node": ">= 12" + } + }, + "node_modules/html-tags": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.2.0.tgz", + "integrity": "sha512-vy7ClnArOZwCnqZgvv+ddgHgJiAFXe3Ge9ML5/mBctVJoUoYPCdxVucOywjDARn6CVoh3dRSFdPHy2sX80L0Wg==", "engines": { "node": ">=8" }, @@ -11250,117 +11474,139 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/openapi-sampler": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/openapi-sampler/-/openapi-sampler-1.1.0.tgz", - "integrity": "sha512-/LhZYKNBWphLEpbAG5BdpBZbIbmLgC4vTiTj8N/MV0LF9ptmKOiJ2nETVlacNjXHt7iqDgZDELJCIoZ3q5ZG6A==", - "dependencies": { - "@types/json-schema": "^7.0.7", - "json-pointer": "^0.6.1" - } - }, - "node_modules/opener": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz", - "integrity": "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==", - "bin": { - "opener": "bin/opener-bin.js" + "node_modules/html-void-elements": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-1.0.5.tgz", + "integrity": "sha512-uE/TxKuyNIcx44cIWnjr/rfIATDH7ZaOMmstu0CwhFG1Dunhlp4OC6/NMbhiwoq5BpW0ubi303qnEk/PZj614w==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/opn": { + "node_modules/html-webpack-plugin": { "version": "5.5.0", - "resolved": "https://registry.npmjs.org/opn/-/opn-5.5.0.tgz", - "integrity": "sha512-PqHpggC9bLV0VeWcdKhkpxY+3JTzetLSqTCWL/z/tFIbI6G8JCjondXklT1JinczLz2Xib62sSp0T/gKT4KksA==", + "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.5.0.tgz", + "integrity": "sha512-sy88PC2cRTVxvETRgUHFrL4No3UxvcH8G1NepGhqaTT+GXN2kTamqasot0inS5hXeg1cMbFDt27zzo9p35lZVw==", "dependencies": { - "is-wsl": "^1.1.0" + "@types/html-minifier-terser": "^6.0.0", + "html-minifier-terser": "^6.0.2", + "lodash": "^4.17.21", + "pretty-error": "^4.0.0", + "tapable": "^2.0.0" }, "engines": { - "node": ">=4" - } - }, - "node_modules/opn/node_modules/is-wsl": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", - "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=", - "engines": { - "node": ">=4" + "node": ">=10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/html-webpack-plugin" + }, + "peerDependencies": { + "webpack": "^5.20.0" } }, - "node_modules/original": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/original/-/original-1.0.2.tgz", - "integrity": "sha512-hyBVl6iqqUOJ8FqRe+l/gS8H+kKYjrEndd5Pm1MfBtsEKA038HkkdbAl/72EAXGyonD/PFsvmVG+EvcIpliMBg==", + "node_modules/htmlparser2": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", + "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], "dependencies": { - "url-parse": "^1.4.3" + "domelementtype": "^2.0.1", + "domhandler": "^4.0.0", + "domutils": "^2.5.2", + "entities": "^2.0.0" } }, - "node_modules/os-browserify": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", - "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=" + "node_modules/http-cache-semantics": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", + "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==" }, - "node_modules/p-cancelable": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", - "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==", - "engines": { - "node": ">=6" - } + "node_modules/http-deceiver": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", + "integrity": "sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc=" }, - "node_modules/p-finally": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", - "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, "engines": { - "node": ">=4" + "node": ">= 0.8" } }, - "node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "node_modules/http-parser-js": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.6.tgz", + "integrity": "sha512-vDlkRPDJn93swjcjqMSaGSPABbIarsr1TLAui/gLDXzV5VsJNdXNzMYDyNBLQkjWQCJ1uizu8T2oDMhmGt0PRA==" + }, + "node_modules/http-proxy": { + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", + "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", "dependencies": { - "yocto-queue": "^0.1.0" + "eventemitter3": "^4.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=8.0.0" } }, - "node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "node_modules/http-proxy-agent": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", + "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", + "dev": true, "dependencies": { - "p-limit": "^2.2.0" + "@tootallnate/once": "1", + "agent-base": "6", + "debug": "4" }, "engines": { - "node": ">=8" + "node": ">= 6" } }, - "node_modules/p-locate/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "node_modules/http-proxy-middleware": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.6.tgz", + "integrity": "sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw==", "dependencies": { - "p-try": "^2.0.0" + "@types/http-proxy": "^1.17.8", + "http-proxy": "^1.18.1", + "is-glob": "^4.0.1", + "is-plain-obj": "^3.0.0", + "micromatch": "^4.0.2" }, "engines": { - "node": ">=6" + "node": ">=12.0.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "peerDependencies": { + "@types/express": "^4.17.13" + }, + "peerDependenciesMeta": { + "@types/express": { + "optional": true + } } }, - "node_modules/p-map": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", - "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", - "dependencies": { - "aggregate-error": "^3.0.0" - }, + "node_modules/http-proxy-middleware/node_modules/is-plain-obj": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz", + "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==", "engines": { "node": ">=10" }, @@ -11368,13240 +11614,21134 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/p-retry": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-3.0.1.tgz", - "integrity": "sha512-XE6G4+YTTkT2a0UWb2kjZe8xNwf8bIbnqpc/IS/idOBVhyves0mK5OJgeocjx7q5pvX/6m23xuzVPYT1uGM73w==", + "node_modules/http-signature": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.3.6.tgz", + "integrity": "sha512-3adrsD6zqo4GsTqtO7FyrejHNv+NgiIfAfv68+jVlFmSr9OGy7zrxONceFRLKvnnZA5jbxQBX1u9PpB6Wi32Gw==", + "dev": true, "dependencies": { - "retry": "^0.12.0" + "assert-plus": "^1.0.0", + "jsprim": "^2.0.2", + "sshpk": "^1.14.1" }, "engines": { - "node": ">=6" + "node": ">=0.10" } }, - "node_modules/p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "engines": { - "node": ">=6" - } + "node_modules/http2-client": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/http2-client/-/http2-client-1.3.5.tgz", + "integrity": "sha512-EC2utToWl4RKfs5zd36Mxq7nzHHBuomZboI0yYL6Y0RmBgT7Sgkq4rQ0ezFTYoIsSs7Tm9SJe+o2FcAg6GBhGA==" }, - "node_modules/package-json": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/package-json/-/package-json-6.5.0.tgz", - "integrity": "sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ==", + "node_modules/https-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", + "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=" + }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dev": true, "dependencies": { - "got": "^9.6.0", - "registry-auth-token": "^4.0.0", - "registry-url": "^5.0.0", - "semver": "^6.2.0" + "agent-base": "6", + "debug": "4" }, "engines": { - "node": ">=8" + "node": ">= 6" } }, - "node_modules/package-json/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "bin": { - "semver": "bin/semver.js" + "node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "engines": { + "node": ">=10.17.0" } }, - "node_modules/pako": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", - "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==" - }, - "node_modules/param-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", - "integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==", + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", "dependencies": { - "dot-case": "^3.0.4", - "tslib": "^2.0.3" + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" } }, - "node_modules/parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "node_modules/icss-utils": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-4.1.1.tgz", + "integrity": "sha512-4aFq7wvWyMHKgxsH8QQtGpvbASCf+eM3wPRLI6R+MgAnTCZ6STYsRvttLvRWK0Nfif5piF394St3HeJDaljGPA==", + "dev": true, "dependencies": { - "callsites": "^3.0.0" + "postcss": "^7.0.14" }, "engines": { - "node": ">=6" + "node": ">= 6" } }, - "node_modules/parse-asn1": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.6.tgz", - "integrity": "sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw==", + "node_modules/icss-utils/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "node_modules/icss-utils/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, "dependencies": { - "asn1.js": "^5.2.0", - "browserify-aes": "^1.0.0", - "evp_bytestokey": "^1.0.0", - "pbkdf2": "^3.0.3", - "safe-buffer": "^5.1.1" + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" } }, - "node_modules/parse-bmfont-ascii": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/parse-bmfont-ascii/-/parse-bmfont-ascii-1.0.6.tgz", - "integrity": "sha1-Eaw8P/WPfCAgqyJ2kHkQjU36AoU=" + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] }, - "node_modules/parse-bmfont-binary": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/parse-bmfont-binary/-/parse-bmfont-binary-1.0.6.tgz", - "integrity": "sha1-0Di0dtPp3Z2x4RoLDlOiJ5K2kAY=" + "node_modules/ignore": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", + "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", + "engines": { + "node": ">= 4" + } }, - "node_modules/parse-bmfont-xml": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/parse-bmfont-xml/-/parse-bmfont-xml-1.1.4.tgz", - "integrity": "sha512-bjnliEOmGv3y1aMEfREMBJ9tfL3WR0i0CKPj61DnSLaoxWR3nLrsQrEbCId/8rF4NyRF0cCqisSVXyQYWM+mCQ==", + "node_modules/image-q": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/image-q/-/image-q-4.0.0.tgz", + "integrity": "sha512-PfJGVgIfKQJuq3s0tTDOKtztksibuUEbJQIYT3by6wctQo+Rdlh7ef4evJ5NCdxY4CfMbvFkocEwbl4BF8RlJw==", "dependencies": { - "xml-parse-from-string": "^1.0.0", - "xml2js": "^0.4.5" + "@types/node": "16.9.1" } }, - "node_modules/parse-entities": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-2.0.0.tgz", - "integrity": "sha512-kkywGpCcRYhqQIchaWqZ875wzpS/bMKhz5HnN3p7wveJTkTtyAB/AlnS0f8DFSqYW1T82t6yEAkEcB+A1I3MbQ==", + "node_modules/image-q/node_modules/@types/node": { + "version": "16.9.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.9.1.tgz", + "integrity": "sha512-QpLcX9ZSsq3YYUUnD3nFDY8H7wctAhQj/TFKL8Ya8v5fMm3CFXxo8zStsLAl780ltoYoo1WvKUVGBQK+1ifr7g==" + }, + "node_modules/image-size": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/image-size/-/image-size-1.0.1.tgz", + "integrity": "sha512-VAwkvNSNGClRw9mDHhc5Efax8PLlsOGcUTh0T/LIriC8vPA3U5PdqXWqkz406MoYHMKW8Uf9gWr05T/rYB44kQ==", "dependencies": { - "character-entities": "^1.0.0", - "character-entities-legacy": "^1.0.0", - "character-reference-invalid": "^1.0.0", - "is-alphanumerical": "^1.0.0", - "is-decimal": "^1.0.0", - "is-hexadecimal": "^1.0.0" + "queue": "6.0.2" }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "bin": { + "image-size": "bin/image-size.js" + }, + "engines": { + "node": ">=12.0.0" } }, - "node_modules/parse-headers": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/parse-headers/-/parse-headers-2.0.4.tgz", - "integrity": "sha512-psZ9iZoCNFLrgRjZ1d8mn0h9WRqJwFxM9q3x7iUjN/YT2OksthDJ5TiPCu2F38kS4zutqfW+YdVVkBZZx3/1aw==" + "node_modules/immer": { + "version": "9.0.12", + "resolved": "https://registry.npmjs.org/immer/-/immer-9.0.12.tgz", + "integrity": "sha512-lk7UNmSbAukB5B6dh9fnh5D0bJTOFKxVg2cyJWTYrWRfhLrLMBquONcUs3aFq507hNoIZEDDh8lb8UtOizSMhA==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/immer" + } }, - "node_modules/parse-json": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", "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" + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" }, "engines": { - "node": ">=8" + "node": ">=6" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/parse-numeric-range": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/parse-numeric-range/-/parse-numeric-range-1.3.0.tgz", - "integrity": "sha512-twN+njEipszzlMJd4ONUYgSfZPDxgHhT9Ahed5uTigpQn90FggW4SA/AIPq/6a149fTbE9qBEcSwE3FAEp6wQQ==" - }, - "node_modules/parse5": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.1.tgz", - "integrity": "sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug==" - }, - "node_modules/parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "node_modules/import-lazy": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz", + "integrity": "sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM=", "engines": { - "node": ">= 0.8" + "node": ">=4" } }, - "node_modules/pascal-case": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz", - "integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==", + "node_modules/import-local": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", + "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", + "dev": true, "dependencies": { - "no-case": "^3.0.4", - "tslib": "^2.0.3" + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + }, + "bin": { + "import-local-fixture": "fixtures/cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/pascalcase": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", - "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", "engines": { - "node": ">=0.10.0" + "node": ">=0.8.19" } }, - "node_modules/path-browserify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", - "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==" - }, - "node_modules/path-dirname": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", - "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=" - }, - "node_modules/path-exists": { + "node_modules/indent-string": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", "engines": { "node": ">=8" } }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "node_modules/infima": { + "version": "0.2.0-alpha.37", + "resolved": "https://registry.npmjs.org/infima/-/infima-0.2.0-alpha.37.tgz", + "integrity": "sha512-4GX7Baw+/lwS4PPW/UJNY89tWSvYG1DL6baKVdpK6mC593iRgMssxNtORMTFArLPJ/A/lzsGhRmx+z6MaMxj0Q==", "engines": { - "node": ">=0.10.0" + "node": ">=12" } }, - "node_modules/path-is-inside": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", - "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=" + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "engines": { - "node": ">=8" - } - }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, - "node_modules/path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" }, - "node_modules/path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "engines": { - "node": ">=8" - } + "node_modules/inline-style-parser": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.1.1.tgz", + "integrity": "sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q==" }, - "node_modules/pbkdf2": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.2.tgz", - "integrity": "sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==", + "node_modules/internal-slot": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz", + "integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==", "dependencies": { - "create-hash": "^1.1.2", - "create-hmac": "^1.1.4", - "ripemd160": "^2.0.1", - "safe-buffer": "^5.0.1", - "sha.js": "^2.4.8" + "get-intrinsic": "^1.1.0", + "has": "^1.0.3", + "side-channel": "^1.0.4" }, "engines": { - "node": ">=0.12" - } - }, - "node_modules/perfect-scrollbar": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/perfect-scrollbar/-/perfect-scrollbar-1.5.2.tgz", - "integrity": "sha512-McHAinFkyzKbBZrFtb4MT2mxkehp15KvOX/UrjB8C5EZZXHTHgyETo5IGFYtHRTI2Pb2bsV0OE0YnkjT9Cw3aw==" - }, - "node_modules/phin": { - "version": "2.9.3", - "resolved": "https://registry.npmjs.org/phin/-/phin-2.9.3.tgz", - "integrity": "sha512-CzFr90qM24ju5f88quFC/6qohjC144rehe5n6DH900lgXmUe86+xCKc10ev56gRKC4/BkHUoG4uSiQgBiIXwDA==" - }, - "node_modules/picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" - }, - "node_modules/picomatch": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", - "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==", - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" + "node": ">= 0.4" } }, - "node_modules/pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "node_modules/interpret": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", + "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", "engines": { - "node": ">=6" + "node": ">= 0.10" } }, - "node_modules/pinkie": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", - "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", - "engines": { - "node": ">=0.10.0" + "node_modules/invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "dependencies": { + "loose-envify": "^1.0.0" } }, - "node_modules/pinkie-promise": { + "node_modules/ipaddr.js": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", - "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", - "dependencies": { - "pinkie": "^2.0.0" - }, + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.0.1.tgz", + "integrity": "sha512-1qTgH9NG+IIJ4yfKs2e6Pp1bZg8wbDbKHT21HrLIeYBTRLgMYKnMTPAuI3Lcs61nfx5h1xlXnbJtH1kX5/d/ng==", "engines": { - "node": ">=0.10.0" + "node": ">= 10" } }, - "node_modules/pixelmatch": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/pixelmatch/-/pixelmatch-4.0.2.tgz", - "integrity": "sha1-j0fc7FARtHe2fbA8JDvB8wheiFQ=", - "dependencies": { - "pngjs": "^3.0.0" - }, - "bin": { - "pixelmatch": "bin/pixelmatch" + "node_modules/is-alphabetical": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-1.0.4.tgz", + "integrity": "sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/pkg-dir": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", - "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "node_modules/is-alphanumerical": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-1.0.4.tgz", + "integrity": "sha512-UzoZUr+XfVz3t3v4KyGEniVL9BDRoQtY7tOyrRybkVNjDFWyo1yhXNGrrBTQxp3ib9BLAWs7k2YKBQsFRkZG9A==", "dependencies": { - "find-up": "^4.0.0" + "is-alphabetical": "^1.0.0", + "is-decimal": "^1.0.0" }, - "engines": { - "node": ">=8" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/pkg-up": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-3.1.0.tgz", - "integrity": "sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA==", + "node_modules/is-arguments": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", + "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", "dependencies": { - "find-up": "^3.0.0" + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" }, "engines": { - "node": ">=8" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/pkg-up/node_modules/find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=" + }, + "node_modules/is-bigint": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", "dependencies": { - "locate-path": "^3.0.0" + "has-bigints": "^1.0.1" }, - "engines": { - "node": ">=6" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/pkg-up/node_modules/locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", "dependencies": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" + "binary-extensions": "^2.0.0" }, "engines": { - "node": ">=6" + "node": ">=8" } }, - "node_modules/pkg-up/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "node_modules/is-boolean-object": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", "dependencies": { - "p-try": "^2.0.0" + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" }, "engines": { - "node": ">=6" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/pkg-up/node_modules/p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dependencies": { - "p-limit": "^2.0.0" - }, - "engines": { - "node": ">=6" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/pkg-up/node_modules/path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "node_modules/is-buffer": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz", + "integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], "engines": { "node": ">=4" } }, - "node_modules/pngjs": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-3.4.0.tgz", - "integrity": "sha512-NCrCHhWmnQklfH4MtJMRjZ2a8c80qXeMlQMv2uVp9ISJMTt562SbGd6n2oq0PaPgKm7Z6pL9E2UlLIhC+SHL3w==", + "node_modules/is-callable": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz", + "integrity": "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==", "engines": { - "node": ">=4.0.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/polished": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/polished/-/polished-4.1.3.tgz", - "integrity": "sha512-ocPAcVBUOryJEKe0z2KLd1l9EBa1r5mSwlKpExmrLzsnIzJo4axsoU9O2BjOTkDGDT4mZ0WFE5XKTlR3nLnZOA==", + "node_modules/is-ci": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", + "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", "dependencies": { - "@babel/runtime": "^7.14.0" + "ci-info": "^2.0.0" }, - "engines": { - "node": ">=10" + "bin": { + "is-ci": "bin.js" } }, - "node_modules/portfinder": { - "version": "1.0.28", - "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.28.tgz", - "integrity": "sha512-Se+2isanIcEqf2XMHjyUKskczxbPH7dQnlMjXX6+dybayyHvAf/TCgyMRlzf/B6QDhAEFOGes0pzRo3by4AbMA==", + "node_modules/is-ci/node_modules/ci-info": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", + "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==" + }, + "node_modules/is-core-module": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.9.0.tgz", + "integrity": "sha512-+5FPy5PnwmO3lvfMb0AsoPaBG+5KHUI0wYFXOtYPnVVVspTFUuMZNfNaNVRt3FZadstu2c8x23vykRW/NBoU6A==", "dependencies": { - "async": "^2.6.2", - "debug": "^3.1.1", - "mkdirp": "^0.5.5" + "has": "^1.0.3" }, - "engines": { - "node": ">= 0.12.0" - } - }, - "node_modules/portfinder/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/posix-character-classes": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", - "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", - "engines": { - "node": ">=0.10.0" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/postcss": { - "version": "8.3.9", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.3.9.tgz", - "integrity": "sha512-f/ZFyAKh9Dnqytx5X62jgjhhzttjZS7hMsohcI7HEI5tjELX/HxCy3EFhsRxyzGvrzFF+82XPvCS8T9TFleVJw==", + "node_modules/is-date-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", "dependencies": { - "nanoid": "^3.1.28", - "picocolors": "^0.2.1", - "source-map-js": "^0.6.2" + "has-tostringtag": "^1.0.0" }, "engines": { - "node": "^10 || ^12 || >=14" + "node": ">= 0.4" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/postcss-calc": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-8.0.0.tgz", - "integrity": "sha512-5NglwDrcbiy8XXfPM11F3HeC6hoT9W7GUH/Zi5U/p7u3Irv4rHhdDcIZwG0llHXV4ftsBjpfWMXAnXNl4lnt8g==", - "dependencies": { - "postcss-selector-parser": "^6.0.2", - "postcss-value-parser": "^4.0.2" - }, - "peerDependencies": { - "postcss": "^8.2.2" + "node_modules/is-decimal": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-1.0.4.tgz", + "integrity": "sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/postcss-colormin": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-5.2.0.tgz", - "integrity": "sha512-+HC6GfWU3upe5/mqmxuqYZ9B2Wl4lcoUUNkoaX59nEWV4EtADCMiBqui111Bu8R8IvaZTmqmxrqOAqjbHIwXPw==", - "dependencies": { - "browserslist": "^4.16.6", - "caniuse-api": "^3.0.0", - "colord": "^2.0.1", - "postcss-value-parser": "^4.1.0" + "node_modules/is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "bin": { + "is-docker": "cli.js" }, "engines": { - "node": "^10 || ^12 || >=14.0" + "node": ">=8" }, - "peerDependencies": { - "postcss": "^8.2.15" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/postcss-convert-values": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-5.0.1.tgz", - "integrity": "sha512-C3zR1Do2BkKkCgC0g3sF8TS0koF2G+mN8xxayZx3f10cIRmTaAnpgpRQZjNekTZxM2ciSPoh2IWJm0VZx8NoQg==", - "dependencies": { - "postcss-value-parser": "^4.1.0" - }, + "node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" + "node": ">=0.10.0" } }, - "node_modules/postcss-discard-comments": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-5.0.1.tgz", - "integrity": "sha512-lgZBPTDvWrbAYY1v5GYEv8fEO/WhKOu/hmZqmCYfrpD6eyDWWzAOsl2rF29lpvziKO02Gc5GJQtlpkTmakwOWg==", + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" + "node": ">=0.10.0" } }, - "node_modules/postcss-discard-duplicates": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-5.0.1.tgz", - "integrity": "sha512-svx747PWHKOGpAXXQkCc4k/DsWo+6bc5LsVrAsw+OU+Ibi7klFZCyX54gjYzX4TH+f2uzXjRviLARxkMurA2bA==", + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" + "node": ">=8" } }, - "node_modules/postcss-discard-empty": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-5.0.1.tgz", - "integrity": "sha512-vfU8CxAQ6YpMxV2SvMcMIyF2LX1ZzWpy0lqHDsOdaKKLQVQGVP1pzhrI9JlsO65s66uQTfkQBKBD/A5gp9STFw==", - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } + "node_modules/is-function": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-function/-/is-function-1.0.2.tgz", + "integrity": "sha512-lw7DUp0aWXYg+CBCN+JKkcE0Q2RayZnSvnZBlwgxHBQhqt5pZNVy4Ri7H9GmmXkdu7LUthszM+Tor1u/2iBcpQ==" }, - "node_modules/postcss-discard-overridden": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-5.0.1.tgz", - "integrity": "sha512-Y28H7y93L2BpJhrdUR2SR2fnSsT+3TVx1NmVQLbcnZWwIUpJ7mfcTC6Za9M2PG6w8j7UQRfzxqn8jU2VwFxo3Q==", + "node_modules/is-generator-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", + "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", + "dev": true, "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" + "node": ">=6" } }, - "node_modules/postcss-discard-unused": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/postcss-discard-unused/-/postcss-discard-unused-5.0.1.tgz", - "integrity": "sha512-tD6xR/xyZTwfhKYRw0ylfCY8wbfhrjpKAMnDKRTLMy2fNW5hl0hoV6ap5vo2JdCkuHkP3CHw72beO4Y8pzFdww==", + "node_modules/is-generator-function": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", + "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", "dependencies": { - "postcss-selector-parser": "^6.0.5" + "has-tostringtag": "^1.0.0" }, "engines": { - "node": "^10 || ^12 || >=14.0" + "node": ">= 0.4" }, - "peerDependencies": { - "postcss": "^8.2.15" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/postcss-loader": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-5.3.0.tgz", - "integrity": "sha512-/+Z1RAmssdiSLgIZwnJHwBMnlABPgF7giYzTN2NOfr9D21IJZ4mQC1R2miwp80zno9M4zMD/umGI8cR+2EL5zw==", + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", "dependencies": { - "cosmiconfig": "^7.0.0", - "klona": "^2.0.4", - "semver": "^7.3.4" + "is-extglob": "^2.1.1" }, "engines": { - "node": ">= 10.13.0" - }, + "node": ">=0.10.0" + } + }, + "node_modules/is-hexadecimal": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-1.0.4.tgz", + "integrity": "sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw==", "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "postcss": "^7.0.0 || ^8.0.1", - "webpack": "^5.0.0" + "type": "github", + "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/postcss-merge-idents": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/postcss-merge-idents/-/postcss-merge-idents-5.0.1.tgz", - "integrity": "sha512-xu8ueVU0RszbI2gKkxR6mluupsOSSLvt8q4gA2fcKFkA+x6SlH3cb4cFHpDvcRCNFbUmCR/VUub+Y6zPOjPx+Q==", + "node_modules/is-installed-globally": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.4.0.tgz", + "integrity": "sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ==", "dependencies": { - "cssnano-utils": "^2.0.1", - "postcss-value-parser": "^4.1.0" + "global-dirs": "^3.0.0", + "is-path-inside": "^3.0.2" }, "engines": { - "node": "^10 || ^12 || >=14.0" + "node": ">=10" }, - "peerDependencies": { - "postcss": "^8.2.15" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/postcss-merge-longhand": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-5.0.2.tgz", - "integrity": "sha512-BMlg9AXSI5G9TBT0Lo/H3PfUy63P84rVz3BjCFE9e9Y9RXQZD3+h3YO1kgTNsNJy7bBc1YQp8DmSnwLIW5VPcw==", + "node_modules/is-nan": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/is-nan/-/is-nan-1.3.2.tgz", + "integrity": "sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==", "dependencies": { - "css-color-names": "^1.0.1", - "postcss-value-parser": "^4.1.0", - "stylehacks": "^5.0.1" + "call-bind": "^1.0.0", + "define-properties": "^1.1.3" }, "engines": { - "node": "^10 || ^12 || >=14.0" + "node": ">= 0.4" }, - "peerDependencies": { - "postcss": "^8.2.15" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/postcss-merge-rules": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-5.0.2.tgz", - "integrity": "sha512-5K+Md7S3GwBewfB4rjDeol6V/RZ8S+v4B66Zk2gChRqLTCC8yjnHQ601omj9TKftS19OPGqZ/XzoqpzNQQLwbg==", - "dependencies": { - "browserslist": "^4.16.6", - "caniuse-api": "^3.0.0", - "cssnano-utils": "^2.0.1", - "postcss-selector-parser": "^6.0.5", - "vendors": "^1.0.3" - }, + "node_modules/is-negative-zero": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", + "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", "engines": { - "node": "^10 || ^12 || >=14.0" + "node": ">= 0.4" }, - "peerDependencies": { - "postcss": "^8.2.15" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/postcss-minify-font-values": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-5.0.1.tgz", - "integrity": "sha512-7JS4qIsnqaxk+FXY1E8dHBDmraYFWmuL6cgt0T1SWGRO5bzJf8sUoelwa4P88LEWJZweHevAiDKxHlofuvtIoA==", - "dependencies": { - "postcss-value-parser": "^4.1.0" - }, + "node_modules/is-npm": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-5.0.0.tgz", + "integrity": "sha512-WW/rQLOazUq+ST/bCAVBp/2oMERWLsR7OrKyt052dNDk4DHcDE0/7QSXITlmi+VBcV13DfIbysG3tZJm5RfdBA==", "engines": { - "node": "^10 || ^12 || >=14.0" + "node": ">=10" }, - "peerDependencies": { - "postcss": "^8.2.15" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/postcss-minify-gradients": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-5.0.2.tgz", - "integrity": "sha512-7Do9JP+wqSD6Prittitt2zDLrfzP9pqKs2EcLX7HJYxsxCOwrrcLt4x/ctQTsiOw+/8HYotAoqNkrzItL19SdQ==", - "dependencies": { - "colord": "^2.6", - "cssnano-utils": "^2.0.1", - "postcss-value-parser": "^4.1.0" - }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" + "node": ">=0.12.0" } }, - "node_modules/postcss-minify-params": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-5.0.1.tgz", - "integrity": "sha512-4RUC4k2A/Q9mGco1Z8ODc7h+A0z7L7X2ypO1B6V8057eVK6mZ6xwz6QN64nHuHLbqbclkX1wyzRnIrdZehTEHw==", + "node_modules/is-number-object": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", + "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", "dependencies": { - "alphanum-sort": "^1.0.2", - "browserslist": "^4.16.0", - "cssnano-utils": "^2.0.1", - "postcss-value-parser": "^4.1.0", - "uniqs": "^2.0.0" + "has-tostringtag": "^1.0.0" }, "engines": { - "node": "^10 || ^12 || >=14.0" + "node": ">= 0.4" }, - "peerDependencies": { - "postcss": "^8.2.15" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/postcss-minify-selectors": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-5.1.0.tgz", - "integrity": "sha512-NzGBXDa7aPsAcijXZeagnJBKBPMYLaJJzB8CQh6ncvyl2sIndLVWfbcDi0SBjRWk5VqEjXvf8tYwzoKf4Z07og==", - "dependencies": { - "alphanum-sort": "^1.0.2", - "postcss-selector-parser": "^6.0.5" - }, + "node_modules/is-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", + "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=", "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" + "node": ">=0.10.0" } }, - "node_modules/postcss-modules-extract-imports": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz", - "integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==", + "node_modules/is-path-cwd": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz", + "integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==", "engines": { - "node": "^10 || ^12 || >= 14" - }, - "peerDependencies": { - "postcss": "^8.1.0" + "node": ">=6" } }, - "node_modules/postcss-modules-local-by-default": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.0.tgz", - "integrity": "sha512-sT7ihtmGSF9yhm6ggikHdV0hlziDTX7oFoXtuVWeDd3hHObNkcHRo9V3yg7vCAY7cONyxJC/XXCmmiHHcvX7bQ==", - "dependencies": { - "icss-utils": "^5.0.0", - "postcss-selector-parser": "^6.0.2", - "postcss-value-parser": "^4.1.0" - }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", "engines": { - "node": "^10 || ^12 || >= 14" - }, - "peerDependencies": { - "postcss": "^8.1.0" + "node": ">=8" } }, - "node_modules/postcss-modules-scope": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.0.0.tgz", - "integrity": "sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg==", - "dependencies": { - "postcss-selector-parser": "^6.0.4" - }, + "node_modules/is-plain-obj": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", + "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", "engines": { - "node": "^10 || ^12 || >= 14" - }, - "peerDependencies": { - "postcss": "^8.1.0" + "node": ">=8" } }, - "node_modules/postcss-modules-values": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", - "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", + "node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", "dependencies": { - "icss-utils": "^5.0.0" + "isobject": "^3.0.1" }, "engines": { - "node": "^10 || ^12 || >= 14" - }, - "peerDependencies": { - "postcss": "^8.1.0" + "node": ">=0.10.0" } }, - "node_modules/postcss-normalize-charset": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-5.0.1.tgz", - "integrity": "sha512-6J40l6LNYnBdPSk+BHZ8SF+HAkS4q2twe5jnocgd+xWpz/mx/5Sa32m3W1AA8uE8XaXN+eg8trIlfu8V9x61eg==", - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } + "node_modules/is-potential-custom-element-name": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", + "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", + "dev": true }, - "node_modules/postcss-normalize-display-values": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/postcss-normalize-display-values/-/postcss-normalize-display-values-5.0.1.tgz", - "integrity": "sha512-uupdvWk88kLDXi5HEyI9IaAJTE3/Djbcrqq8YgjvAVuzgVuqIk3SuJWUisT2gaJbZm1H9g5k2w1xXilM3x8DjQ==", + "node_modules/is-regex": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", "dependencies": { - "cssnano-utils": "^2.0.1", - "postcss-value-parser": "^4.1.0" + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" }, "engines": { - "node": "^10 || ^12 || >=14.0" + "node": ">= 0.4" }, - "peerDependencies": { - "postcss": "^8.2.15" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/postcss-normalize-positions": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/postcss-normalize-positions/-/postcss-normalize-positions-5.0.1.tgz", - "integrity": "sha512-rvzWAJai5xej9yWqlCb1OWLd9JjW2Ex2BCPzUJrbaXmtKtgfL8dBMOOMTX6TnvQMtjk3ei1Lswcs78qKO1Skrg==", - "dependencies": { - "postcss-value-parser": "^4.1.0" - }, + "node_modules/is-regexp": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz", + "integrity": "sha1-/S2INUXEa6xaYz57mgnof6LLUGk=", "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" + "node": ">=0.10.0" } }, - "node_modules/postcss-normalize-repeat-style": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-5.0.1.tgz", - "integrity": "sha512-syZ2itq0HTQjj4QtXZOeefomckiV5TaUO6ReIEabCh3wgDs4Mr01pkif0MeVwKyU/LHEkPJnpwFKRxqWA/7O3w==", - "dependencies": { - "cssnano-utils": "^2.0.1", - "postcss-value-parser": "^4.1.0" - }, + "node_modules/is-root": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-root/-/is-root-2.1.0.tgz", + "integrity": "sha512-AGOriNp96vNBd3HtU+RzFEc75FfR5ymiYv8E553I71SCeXBiMsVDUtdio1OEFvrPyLIQ9tVR5RxXIFe5PUFjMg==", "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" + "node": ">=6" } }, - "node_modules/postcss-normalize-string": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/postcss-normalize-string/-/postcss-normalize-string-5.0.1.tgz", - "integrity": "sha512-Ic8GaQ3jPMVl1OEn2U//2pm93AXUcF3wz+OriskdZ1AOuYV25OdgS7w9Xu2LO5cGyhHCgn8dMXh9bO7vi3i9pA==", + "node_modules/is-shared-array-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", + "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", "dependencies": { - "postcss-value-parser": "^4.1.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" + "call-bind": "^1.0.2" }, - "peerDependencies": { - "postcss": "^8.2.15" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/postcss-normalize-timing-functions": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-5.0.1.tgz", - "integrity": "sha512-cPcBdVN5OsWCNEo5hiXfLUnXfTGtSFiBU9SK8k7ii8UD7OLuznzgNRYkLZow11BkQiiqMcgPyh4ZqXEEUrtQ1Q==", - "dependencies": { - "cssnano-utils": "^2.0.1", - "postcss-value-parser": "^4.1.0" - }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", "engines": { - "node": "^10 || ^12 || >=14.0" + "node": ">=8" }, - "peerDependencies": { - "postcss": "^8.2.15" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/postcss-normalize-unicode": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/postcss-normalize-unicode/-/postcss-normalize-unicode-5.0.1.tgz", - "integrity": "sha512-kAtYD6V3pK0beqrU90gpCQB7g6AOfP/2KIPCVBKJM2EheVsBQmx/Iof+9zR9NFKLAx4Pr9mDhogB27pmn354nA==", + "node_modules/is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", "dependencies": { - "browserslist": "^4.16.0", - "postcss-value-parser": "^4.1.0" + "has-tostringtag": "^1.0.0" }, "engines": { - "node": "^10 || ^12 || >=14.0" + "node": ">= 0.4" }, - "peerDependencies": { - "postcss": "^8.2.15" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/postcss-normalize-url": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-5.0.2.tgz", - "integrity": "sha512-k4jLTPUxREQ5bpajFQZpx8bCF2UrlqOTzP9kEqcEnOfwsRshWs2+oAFIHfDQB8GO2PaUaSE0NlTAYtbluZTlHQ==", + "node_modules/is-symbol": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", "dependencies": { - "is-absolute-url": "^3.0.3", - "normalize-url": "^6.0.1", - "postcss-value-parser": "^4.1.0" + "has-symbols": "^1.0.2" }, "engines": { - "node": "^10 || ^12 || >=14.0" + "node": ">= 0.4" }, - "peerDependencies": { - "postcss": "^8.2.15" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/postcss-normalize-whitespace": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/postcss-normalize-whitespace/-/postcss-normalize-whitespace-5.0.1.tgz", - "integrity": "sha512-iPklmI5SBnRvwceb/XH568yyzK0qRVuAG+a1HFUsFRf11lEJTiQQa03a4RSCQvLKdcpX7XsI1Gen9LuLoqwiqA==", + "node_modules/is-typed-array": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.8.tgz", + "integrity": "sha512-HqH41TNZq2fgtGT8WHVFVJhBVGuY3AnP3Q36K8JKXUxSxRgk/d+7NjmwG2vo2mYmXK8UYZKu0qH8bVP5gEisjA==", "dependencies": { - "postcss-value-parser": "^4.1.0" + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "es-abstract": "^1.18.5", + "foreach": "^2.0.5", + "has-tostringtag": "^1.0.0" }, "engines": { - "node": "^10 || ^12 || >=14.0" + "node": ">= 0.4" }, - "peerDependencies": { - "postcss": "^8.2.15" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/postcss-ordered-values": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-5.0.2.tgz", - "integrity": "sha512-8AFYDSOYWebJYLyJi3fyjl6CqMEG/UVworjiyK1r573I56kb3e879sCJLGvR3merj+fAdPpVplXKQZv+ey6CgQ==", - "dependencies": { - "cssnano-utils": "^2.0.1", - "postcss-value-parser": "^4.1.0" - }, + "node_modules/is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" + }, + "node_modules/is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "dev": true, "engines": { - "node": "^10 || ^12 || >=14.0" + "node": ">=10" }, - "peerDependencies": { - "postcss": "^8.2.15" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/postcss-reduce-idents": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/postcss-reduce-idents/-/postcss-reduce-idents-5.0.1.tgz", - "integrity": "sha512-6Rw8iIVFbqtaZExgWK1rpVgP7DPFRPh0DDFZxJ/ADNqPiH10sPCoq5tgo6kLiTyfh9sxjKYjXdc8udLEcPOezg==", + "node_modules/is-weakref": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", + "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", "dependencies": { - "postcss-value-parser": "^4.1.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" + "call-bind": "^1.0.2" }, - "peerDependencies": { - "postcss": "^8.2.15" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/postcss-reduce-initial": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-5.0.1.tgz", - "integrity": "sha512-zlCZPKLLTMAqA3ZWH57HlbCjkD55LX9dsRyxlls+wfuRfqCi5mSlZVan0heX5cHr154Dq9AfbH70LyhrSAezJw==", - "dependencies": { - "browserslist": "^4.16.0", - "caniuse-api": "^3.0.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" + "node_modules/is-whitespace-character": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-whitespace-character/-/is-whitespace-character-1.0.4.tgz", + "integrity": "sha512-SDweEzfIZM0SJV0EUga669UTKlmL0Pq8Lno0QDQsPnvECB3IM2aP0gdx5TrU0A01MAPfViaZiI2V1QMZLaKK5w==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/postcss-reduce-transforms": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-5.0.1.tgz", - "integrity": "sha512-a//FjoPeFkRuAguPscTVmRQUODP+f3ke2HqFNgGPwdYnpeC29RZdCBvGRGTsKpMURb/I3p6jdKoBQ2zI+9Q7kA==", + "node_modules/is-word-character": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-word-character/-/is-word-character-1.0.4.tgz", + "integrity": "sha512-5SMO8RVennx3nZrqtKwCGyyetPE9VDba5ugvKLaD4KopPG5kR4mQ7tNt/r7feL5yt5h3lpuBbIUmCOG2eSzXHA==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", "dependencies": { - "cssnano-utils": "^2.0.1", - "postcss-value-parser": "^4.1.0" + "is-docker": "^2.0.0" }, "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" + "node": ">=8" } }, - "node_modules/postcss-selector-parser": { - "version": "6.0.6", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.6.tgz", - "integrity": "sha512-9LXrvaaX3+mcv5xkg5kFwqSzSH1JIObIx51PrndZwlmznwXRfxMddDvo9gve3gVR8ZTKgoFDdWkbRFmEhT4PMg==", + "node_modules/is-yarn-global": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/is-yarn-global/-/is-yarn-global-0.3.0.tgz", + "integrity": "sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw==" + }, + "node_modules/isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" + }, + "node_modules/isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==", + "dev": true + }, + "node_modules/istanbul-lib-coverage": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", + "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-instrument": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.0.tgz", + "integrity": "sha512-6Lthe1hqXHBNsqvgDzGO6l03XNeu3CrG4RqQ1KM9+l5+jNGpEJfIELx1NS3SEHmJQA8np/u+E4EPRKRiu6m19A==", + "dev": true, "dependencies": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" }, "engines": { - "node": ">=4" + "node": ">=8" } }, - "node_modules/postcss-sort-media-queries": { - "version": "3.12.13", - "resolved": "https://registry.npmjs.org/postcss-sort-media-queries/-/postcss-sort-media-queries-3.12.13.tgz", - "integrity": "sha512-bFbR1+P6HhZWXcT5DVV2pBH5Y2U5daKbFd0j+kcwKdzrxkbmgFu0GhI2JfFUyy5KQIeW+YJGP+vwNDOS5hIn2g==", + "node_modules/istanbul-lib-instrument/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/istanbul-lib-report": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", + "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==", + "dev": true, "dependencies": { - "sort-css-media-queries": "2.0.4" + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^3.0.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "postcss": "^8.3.6" + "node": ">=8" } }, - "node_modules/postcss-svgo": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-5.0.2.tgz", - "integrity": "sha512-YzQuFLZu3U3aheizD+B1joQ94vzPfE6BNUcSYuceNxlVnKKsOtdo6hL9/zyC168Q8EwfLSgaDSalsUGa9f2C0A==", + "node_modules/istanbul-lib-report/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-report/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, "dependencies": { - "postcss-value-parser": "^4.1.0", - "svgo": "^2.3.0" + "has-flag": "^4.0.0" }, "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" + "node": ">=8" } }, - "node_modules/postcss-unique-selectors": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-5.0.1.tgz", - "integrity": "sha512-gwi1NhHV4FMmPn+qwBNuot1sG1t2OmacLQ/AX29lzyggnjd+MnVD5uqQmpXO3J17KGL2WAxQruj1qTd3H0gG/w==", + "node_modules/istanbul-lib-source-maps": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", + "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", + "dev": true, "dependencies": { - "alphanum-sort": "^1.0.2", - "postcss-selector-parser": "^6.0.5", - "uniqs": "^2.0.0" + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0", + "source-map": "^0.6.1" }, "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" + "node": ">=10" } }, - "node_modules/postcss-value-parser": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.1.0.tgz", - "integrity": "sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ==" - }, - "node_modules/postcss-zindex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/postcss-zindex/-/postcss-zindex-5.0.1.tgz", - "integrity": "sha512-nwgtJJys+XmmSGoYCcgkf/VczP8Mp/0OfSv3v0+fw0uABY4yxw+eFs0Xp9nAZHIKnS5j+e9ywQ+RD+ONyvl5pA==", - "engines": { - "node": "^10 || ^12 || >=14.0" + "node_modules/istanbul-reports": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.4.tgz", + "integrity": "sha512-r1/DshN4KSE7xWEknZLLLLDn5CJybV3nw01VTkp6D5jzLuELlcbudfj/eSQFvrKsJuTVCGnePO7ho82Nw9zzfw==", + "dev": true, + "dependencies": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" }, - "peerDependencies": { - "postcss": "^8.2.15" + "engines": { + "node": ">=8" } }, - "node_modules/postcss/node_modules/picocolors": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", - "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" - }, - "node_modules/prebuild-install": { - "version": "6.1.4", - "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-6.1.4.tgz", - "integrity": "sha512-Z4vpywnK1lBg+zdPCVCsKq0xO66eEV9rWo2zrROGGiRS4JtueBOdlB1FnY8lcy7JsUud/Q3ijUxyWN26Ika0vQ==", + "node_modules/jest": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest/-/jest-27.5.1.tgz", + "integrity": "sha512-Yn0mADZB89zTtjkPJEXwrac3LHudkQMR+Paqa8uxJHCBr9agxztUifWCyiYrjhMPBoUVBjyny0I7XH6ozDr7QQ==", + "dev": true, "dependencies": { - "detect-libc": "^1.0.3", - "expand-template": "^2.0.3", - "github-from-package": "0.0.0", - "minimist": "^1.2.3", - "mkdirp-classic": "^0.5.3", - "napi-build-utils": "^1.0.1", - "node-abi": "^2.21.0", - "npmlog": "^4.0.1", - "pump": "^3.0.0", - "rc": "^1.2.7", - "simple-get": "^3.0.3", - "tar-fs": "^2.0.0", - "tunnel-agent": "^0.6.0" + "@jest/core": "^27.5.1", + "import-local": "^3.0.2", + "jest-cli": "^27.5.1" }, "bin": { - "prebuild-install": "bin.js" + "jest": "bin/jest.js" }, "engines": { - "node": ">=6" + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } } }, - "node_modules/prepend-http": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", - "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=", + "node_modules/jest-changed-files": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-27.5.1.tgz", + "integrity": "sha512-buBLMiByfWGCoMsLLzGUUSpAmIAGnbR2KJoMN10ziLhOLvP4e0SlypHnAel8iqQXTrcbmfEY9sSqae5sgUsTvw==", + "dev": true, + "dependencies": { + "@jest/types": "^27.5.1", + "execa": "^5.0.0", + "throat": "^6.0.1" + }, "engines": { - "node": ">=4" + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "node_modules/pretty-error": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-3.0.4.tgz", - "integrity": "sha512-ytLFLfv1So4AO1UkoBF6GXQgJRaKbiSiGFICaOPNwQ3CMvBvXpLRubeQWyPGnsbV/t9ml9qto6IeCsho0aEvwQ==", + "node_modules/jest-circus": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-27.5.1.tgz", + "integrity": "sha512-D95R7x5UtlMA5iBYsOHFFbMD/GVA4R/Kdq15f7xYWUfWHBto9NYRsOvnSauTgdF+ogCpJ4tyKOXhUifxS65gdw==", + "dev": true, "dependencies": { - "lodash": "^4.17.20", - "renderkid": "^2.0.6" - } - }, - "node_modules/pretty-time": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/pretty-time/-/pretty-time-1.1.0.tgz", - "integrity": "sha512-28iF6xPQrP8Oa6uxE6a1biz+lWeTOAPKggvjB8HAs6nVMKZwf5bG++632Dx614hIWgUPkgivRfG+a8uAXGTIbA==", + "@jest/environment": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "co": "^4.6.0", + "dedent": "^0.7.0", + "expect": "^27.5.1", + "is-generator-fn": "^2.0.0", + "jest-each": "^27.5.1", + "jest-matcher-utils": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-runtime": "^27.5.1", + "jest-snapshot": "^27.5.1", + "jest-util": "^27.5.1", + "pretty-format": "^27.5.1", + "slash": "^3.0.0", + "stack-utils": "^2.0.3", + "throat": "^6.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-circus/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, "engines": { - "node": ">=4" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/prism-react-renderer": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prism-react-renderer/-/prism-react-renderer-1.2.1.tgz", - "integrity": "sha512-w23ch4f75V1Tnz8DajsYKvY5lF7H1+WvzvLUcF0paFxkTHSp42RS0H5CttdN2Q8RR3DRGZ9v5xD/h3n8C8kGmg==", - "peerDependencies": { - "react": ">=0.14.9" + "node_modules/jest-circus/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/prismjs": { - "version": "1.25.0", - "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.25.0.tgz", - "integrity": "sha512-WCjJHl1KEWbnkQom1+SzftbtXMKQoezOCYs5rECqMN+jP+apI7ftoflyqigqzopSO3hMhTEb0mFClA8lkolgEg==" - }, - "node_modules/process": { - "version": "0.11.10", - "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", - "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=", + "node_modules/jest-circus/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, "engines": { - "node": ">= 0.6.0" + "node": ">=7.0.0" } }, - "node_modules/process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + "node_modules/jest-circus/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true }, - "node_modules/promise": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", - "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==", - "dependencies": { - "asap": "~2.0.3" + "node_modules/jest-circus/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" } }, - "node_modules/prompts": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", - "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "node_modules/jest-circus/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, "dependencies": { - "kleur": "^3.0.3", - "sisteransi": "^1.0.5" + "has-flag": "^4.0.0" }, "engines": { - "node": ">= 6" + "node": ">=8" } }, - "node_modules/prop-types": { - "version": "15.7.2", - "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz", - "integrity": "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==", + "node_modules/jest-cli": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-27.5.1.tgz", + "integrity": "sha512-Hc6HOOwYq4/74/c62dEE3r5elx8wjYqxY0r0G/nFrLDPMFRu6RA/u8qINOIkvhxG7mMQ5EJsOGfRpI8L6eFUVw==", + "dev": true, "dependencies": { - "loose-envify": "^1.4.0", - "object-assign": "^4.1.1", - "react-is": "^16.8.1" + "@jest/core": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/types": "^27.5.1", + "chalk": "^4.0.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "import-local": "^3.0.2", + "jest-config": "^27.5.1", + "jest-util": "^27.5.1", + "jest-validate": "^27.5.1", + "prompts": "^2.0.1", + "yargs": "^16.2.0" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } } }, - "node_modules/property-information": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/property-information/-/property-information-5.6.0.tgz", - "integrity": "sha512-YUHSPk+A30YPv+0Qf8i9Mbfe/C0hdPXk1s1jPVToV8pk8BQtpw10ct89Eo7OWkutrwqvT0eicAxlOg3dOAu8JA==", + "node_modules/jest-cli/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, "dependencies": { - "xtend": "^4.0.0" + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/proxy-addr": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", - "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "node_modules/jest-cli/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "dependencies": { - "forwarded": "0.2.0", - "ipaddr.js": "1.9.1" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">= 0.10" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/prr": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", - "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=" - }, - "node_modules/public-encrypt": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", - "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", + "node_modules/jest-cli/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, "dependencies": { - "bn.js": "^4.1.0", - "browserify-rsa": "^4.0.0", - "create-hash": "^1.1.0", - "parse-asn1": "^5.0.0", - "randombytes": "^2.0.1", - "safe-buffer": "^5.1.2" + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" } }, - "node_modules/public-encrypt/node_modules/bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" - }, - "node_modules/pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } + "node_modules/jest-cli/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true }, - "node_modules/punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "node_modules/jest-cli/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, "engines": { - "node": ">=6" + "node": ">=8" } }, - "node_modules/pupa": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/pupa/-/pupa-2.1.1.tgz", - "integrity": "sha512-l1jNAspIBSFqbT+y+5FosojNpVpF94nlI+wDUpqP9enwOTfHx9f0gh5nB96vl+6yTpsJsypeNrwfzPrKuHB41A==", + "node_modules/jest-cli/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, "dependencies": { - "escape-goat": "^2.0.0" + "has-flag": "^4.0.0" }, "engines": { "node": ">=8" } }, - "node_modules/pure-color": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/pure-color/-/pure-color-1.3.0.tgz", - "integrity": "sha1-H+Bk+wrIUfDeYTIKi/eWg2Qi8z4=" - }, - "node_modules/q": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", - "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=", + "node_modules/jest-config": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-27.5.1.tgz", + "integrity": "sha512-5sAsjm6tGdsVbW9ahcChPAFCk4IlkQUknH5AvKjuLTSlcO/wCZKyFdn7Rg0EkC+OGgWODEy2hDpWB1PgzH0JNA==", + "dev": true, + "dependencies": { + "@babel/core": "^7.8.0", + "@jest/test-sequencer": "^27.5.1", + "@jest/types": "^27.5.1", + "babel-jest": "^27.5.1", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "deepmerge": "^4.2.2", + "glob": "^7.1.1", + "graceful-fs": "^4.2.9", + "jest-circus": "^27.5.1", + "jest-environment-jsdom": "^27.5.1", + "jest-environment-node": "^27.5.1", + "jest-get-type": "^27.5.1", + "jest-jasmine2": "^27.5.1", + "jest-regex-util": "^27.5.1", + "jest-resolve": "^27.5.1", + "jest-runner": "^27.5.1", + "jest-util": "^27.5.1", + "jest-validate": "^27.5.1", + "micromatch": "^4.0.4", + "parse-json": "^5.2.0", + "pretty-format": "^27.5.1", + "slash": "^3.0.0", + "strip-json-comments": "^3.1.1" + }, "engines": { - "node": ">=0.6.0", - "teleport": ">=0.2.0" + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + }, + "peerDependencies": { + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "ts-node": { + "optional": true + } } }, - "node_modules/qs": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", - "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==", + "node_modules/jest-config/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, "engines": { - "node": ">=0.6" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/querystring": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", - "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", - "deprecated": "The querystring API is considered Legacy. new code should use the URLSearchParams API instead.", + "node_modules/jest-config/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, "engines": { - "node": ">=0.4.x" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/querystring-es3": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", - "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=", + "node_modules/jest-config/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, "engines": { - "node": ">=0.4.x" + "node": ">=7.0.0" } }, - "node_modules/querystringify": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", - "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==" - }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] + "node_modules/jest-config/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true }, - "node_modules/randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dependencies": { - "safe-buffer": "^5.1.0" + "node_modules/jest-config/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" } }, - "node_modules/randomfill": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", - "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", + "node_modules/jest-config/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, "dependencies": { - "randombytes": "^2.0.5", - "safe-buffer": "^5.1.0" - } - }, - "node_modules/range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "has-flag": "^4.0.0" + }, "engines": { - "node": ">= 0.6" + "node": ">=8" } }, - "node_modules/raw-body": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", - "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", + "node_modules/jest-diff": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-27.5.1.tgz", + "integrity": "sha512-m0NvkX55LDt9T4mctTEgnZk3fmEg3NRYutvMPWM/0iPnkFj2wIeF45O1718cMSOFO1vINkqmxqD8vE37uTEbqw==", + "dev": true, "dependencies": { - "bytes": "3.1.0", - "http-errors": "1.7.2", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" + "chalk": "^4.0.0", + "diff-sequences": "^27.5.1", + "jest-get-type": "^27.5.1", + "pretty-format": "^27.5.1" }, "engines": { - "node": ">= 0.8" + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "node_modules/rc": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", - "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "node_modules/jest-diff/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, "dependencies": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" + "color-convert": "^2.0.1" }, - "bin": { - "rc": "cli.js" + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/react": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/react/-/react-17.0.2.tgz", - "integrity": "sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA==", + "node_modules/jest-diff/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "dependencies": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/react-base16-styling": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/react-base16-styling/-/react-base16-styling-0.6.0.tgz", - "integrity": "sha1-7yFW1mz0E5aVyKFniGy2nqZgeSw=", + "node_modules/jest-diff/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, "dependencies": { - "base16": "^1.0.0", - "lodash.curry": "^4.0.1", - "lodash.flow": "^3.3.0", - "pure-color": "^1.2.0" - } - }, - "node_modules/react-dev-utils": { - "version": "11.0.4", - "resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-11.0.4.tgz", - "integrity": "sha512-dx0LvIGHcOPtKbeiSUM4jqpBl3TcY7CDjZdfOIcKeznE7BWr9dg0iPG90G5yfVQ+p/rGNMXdbfStvzQZEVEi4A==", - "dependencies": { - "@babel/code-frame": "7.10.4", - "address": "1.1.2", - "browserslist": "4.14.2", - "chalk": "2.4.2", - "cross-spawn": "7.0.3", - "detect-port-alt": "1.1.6", - "escape-string-regexp": "2.0.0", - "filesize": "6.1.0", - "find-up": "4.1.0", - "fork-ts-checker-webpack-plugin": "4.1.6", - "global-modules": "2.0.0", - "globby": "11.0.1", - "gzip-size": "5.1.1", - "immer": "8.0.1", - "is-root": "2.1.0", - "loader-utils": "2.0.0", - "open": "^7.0.2", - "pkg-up": "3.1.0", - "prompts": "2.4.0", - "react-error-overlay": "^6.0.9", - "recursive-readdir": "2.2.2", - "shell-quote": "1.7.2", - "strip-ansi": "6.0.0", - "text-table": "0.2.0" + "color-name": "~1.1.4" }, "engines": { - "node": ">=10" + "node": ">=7.0.0" } }, - "node_modules/react-dev-utils/node_modules/@babel/code-frame": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", - "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", - "dependencies": { - "@babel/highlight": "^7.10.4" - } + "node_modules/jest-diff/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true }, - "node_modules/react-dev-utils/node_modules/browserslist": { - "version": "4.14.2", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.14.2.tgz", - "integrity": "sha512-HI4lPveGKUR0x2StIz+2FXfDk9SfVMrxn6PLh1JeGUwcuoDkdKZebWiyLRJ68iIPDpMI4JLVDf7S7XzslgWOhw==", - "dependencies": { - "caniuse-lite": "^1.0.30001125", - "electron-to-chromium": "^1.3.564", - "escalade": "^3.0.2", - "node-releases": "^1.1.61" - }, - "bin": { - "browserslist": "cli.js" - }, + "node_modules/jest-diff/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" - }, - "funding": { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" + "node": ">=8" } }, - "node_modules/react-dev-utils/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "node_modules/jest-diff/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" + "has-flag": "^4.0.0" }, "engines": { - "node": ">=4" - } - }, - "node_modules/react-dev-utils/node_modules/chalk/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "engines": { - "node": ">=0.8.0" + "node": ">=8" } }, - "node_modules/react-dev-utils/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "node_modules/jest-docblock": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-27.5.1.tgz", + "integrity": "sha512-rl7hlABeTsRYxKiUfpHrQrG4e2obOiTQWfMEH3PxPjOtdsfLQO4ReWSZaQ7DETm4xu07rl4q/h4zcKXyU0/OzQ==", + "dev": true, "dependencies": { - "ms": "2.0.0" + "detect-newline": "^3.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "node_modules/react-dev-utils/node_modules/detect-port-alt": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/detect-port-alt/-/detect-port-alt-1.1.6.tgz", - "integrity": "sha512-5tQykt+LqfJFBEYaDITx7S7cR7mJ/zQmLXZ2qt5w04ainYZw6tBf9dBunMjVeVOdYVRUzUOE4HkY5J7+uttb5Q==", + "node_modules/jest-each": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-27.5.1.tgz", + "integrity": "sha512-1Ff6p+FbhT/bXQnEouYy00bkNSY7OUpfIcmdl8vZ31A1UUaurOLPA8a8BbJOF2RDUElwJhmeaV7LnagI+5UwNQ==", + "dev": true, "dependencies": { - "address": "^1.0.1", - "debug": "^2.6.0" - }, - "bin": { - "detect": "bin/detect-port", - "detect-port": "bin/detect-port" + "@jest/types": "^27.5.1", + "chalk": "^4.0.0", + "jest-get-type": "^27.5.1", + "jest-util": "^27.5.1", + "pretty-format": "^27.5.1" }, "engines": { - "node": ">= 4.2.1" + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "node_modules/react-dev-utils/node_modules/escape-string-regexp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", - "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "node_modules/jest-each/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, "engines": { "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/react-dev-utils/node_modules/globby": { - "version": "11.0.1", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.1.tgz", - "integrity": "sha512-iH9RmgwCmUJHi2z5o2l3eTtGBtXek1OYlHrbcxOYugyHLmAsZrPj43OtHThd62Buh/Vv6VyCBD2bdyWcGNQqoQ==", + "node_modules/jest-each/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "dependencies": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.1.1", - "ignore": "^5.1.4", - "merge2": "^1.3.0", - "slash": "^3.0.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/react-dev-utils/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - }, - "node_modules/react-dev-utils/node_modules/node-releases": { - "version": "1.1.77", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.77.tgz", - "integrity": "sha512-rB1DUFUNAN4Gn9keO2K1efO35IDK7yKHCdCaIMvFO7yUYmmZYeDjnGKle26G4rwj+LKRQpjyUUvMkPglwGCYNQ==" - }, - "node_modules/react-dev-utils/node_modules/prompts": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.0.tgz", - "integrity": "sha512-awZAKrk3vN6CroQukBL+R9051a4R3zCZBlJm/HBfrSZ8iTpYix3VX1vU4mveiLpiwmOJT4wokTF9m6HUk4KqWQ==", + "node_modules/jest-each/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, "dependencies": { - "kleur": "^3.0.3", - "sisteransi": "^1.0.5" + "color-name": "~1.1.4" }, "engines": { - "node": ">= 6" + "node": ">=7.0.0" } }, - "node_modules/react-dev-utils/node_modules/strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", - "dependencies": { - "ansi-regex": "^5.0.0" - }, + "node_modules/jest-each/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jest-each/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, "engines": { "node": ">=8" } }, - "node_modules/react-dom": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-17.0.2.tgz", - "integrity": "sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA==", + "node_modules/jest-each/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, "dependencies": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1", - "scheduler": "^0.20.2" + "has-flag": "^4.0.0" }, - "peerDependencies": { - "react": "17.0.2" + "engines": { + "node": ">=8" } }, - "node_modules/react-error-overlay": { - "version": "6.0.9", - "resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.9.tgz", - "integrity": "sha512-nQTTcUu+ATDbrSD1BZHr5kgSD4oF8OFjxun8uAaL8RwPBacGBNPf/yAuVVdx17N8XNzRDMrZ9XcKZHCjPW+9ew==" - }, - "node_modules/react-fast-compare": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.0.tgz", - "integrity": "sha512-rtGImPZ0YyLrscKI9xTpV8psd6I8VAtjKCzQDlzyDvqJA8XOW78TXYQwNRNd8g8JZnDu8q9Fu/1v4HPAVwVdHA==" - }, - "node_modules/react-helmet": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/react-helmet/-/react-helmet-6.1.0.tgz", - "integrity": "sha512-4uMzEY9nlDlgxr61NL3XbKRy1hEkXmKNXhjbAIOVw5vcFrsdYbH2FEwcNyWvWinl103nXgzYNlns9ca+8kFiWw==", + "node_modules/jest-environment-jsdom": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-27.5.1.tgz", + "integrity": "sha512-TFBvkTC1Hnnnrka/fUb56atfDtJ9VMZ94JkjTbggl1PEpwrYtUBKMezB3inLmWqQsXYLcMwNoDQwoBTAvFfsfw==", + "dev": true, "dependencies": { - "object-assign": "^4.1.1", - "prop-types": "^15.7.2", - "react-fast-compare": "^3.1.1", - "react-side-effect": "^2.1.0" + "@jest/environment": "^27.5.1", + "@jest/fake-timers": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "jest-mock": "^27.5.1", + "jest-util": "^27.5.1", + "jsdom": "^16.6.0" }, - "peerDependencies": { - "react": ">=16.3.0" + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "node_modules/react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" - }, - "node_modules/react-json-view": { - "version": "1.21.3", - "resolved": "https://registry.npmjs.org/react-json-view/-/react-json-view-1.21.3.tgz", - "integrity": "sha512-13p8IREj9/x/Ye4WI/JpjhoIwuzEgUAtgJZNBJckfzJt1qyh24BdTm6UQNGnyTq9dapQdrqvquZTo3dz1X6Cjw==", + "node_modules/jest-environment-node": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-27.5.1.tgz", + "integrity": "sha512-Jt4ZUnxdOsTGwSRAfKEnE6BcwsSPNOijjwifq5sDFSA2kesnXTvNqKHYgM0hDq3549Uf/KzdXNYn4wMZJPlFLw==", + "dev": true, "dependencies": { - "flux": "^4.0.1", - "react-base16-styling": "^0.6.0", - "react-lifecycles-compat": "^3.0.4", - "react-textarea-autosize": "^8.3.2" + "@jest/environment": "^27.5.1", + "@jest/fake-timers": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "jest-mock": "^27.5.1", + "jest-util": "^27.5.1" }, - "peerDependencies": { - "react": "^17.0.0 || ^16.3.0 || ^15.5.4", - "react-dom": "^17.0.0 || ^16.3.0 || ^15.5.4" + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "node_modules/react-lifecycles-compat": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz", - "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==" + "node_modules/jest-get-type": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-27.5.1.tgz", + "integrity": "sha512-2KY95ksYSaK7DMBWQn6dQz3kqAf3BB64y2udeG+hv4KfSOb9qwcYQstTJc1KCbsix+wLZWZYN8t7nwX3GOBLRw==", + "dev": true, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } }, - "node_modules/react-loadable": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/react-loadable/-/react-loadable-5.5.0.tgz", - "integrity": "sha512-C8Aui0ZpMd4KokxRdVAm2bQtI03k2RMRNzOB+IipV3yxFTSVICv7WoUr5L9ALB5BmKO1iHgZtWM8EvYG83otdg==", + "node_modules/jest-haste-map": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-27.5.1.tgz", + "integrity": "sha512-7GgkZ4Fw4NFbMSDSpZwXeBiIbx+t/46nJ2QitkOjvwPYyZmqttu2TDSimMHP1EkPOi4xUZAN1doE5Vd25H4Jng==", + "dev": true, "dependencies": { - "prop-types": "^15.5.0" + "@jest/types": "^27.5.1", + "@types/graceful-fs": "^4.1.2", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^27.5.1", + "jest-serializer": "^27.5.1", + "jest-util": "^27.5.1", + "jest-worker": "^27.5.1", + "micromatch": "^4.0.4", + "walker": "^1.0.7" }, - "peerDependencies": { - "react": "*" + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + }, + "optionalDependencies": { + "fsevents": "^2.3.2" } }, - "node_modules/react-loadable-ssr-addon-v5-slorber": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/react-loadable-ssr-addon-v5-slorber/-/react-loadable-ssr-addon-v5-slorber-1.0.1.tgz", - "integrity": "sha512-lq3Lyw1lGku8zUEJPDxsNm1AfYHBrO9Y1+olAYwpUJ2IGFBskM0DMKok97A6LWUpHm+o7IvQBOWu9MLenp9Z+A==", + "node_modules/jest-jasmine2": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-27.5.1.tgz", + "integrity": "sha512-jtq7VVyG8SqAorDpApwiJJImd0V2wv1xzdheGHRGyuT7gZm6gG47QEskOlzsN1PG/6WNaCo5pmwMHDf3AkG2pQ==", + "dev": true, "dependencies": { - "@babel/runtime": "^7.10.3" + "@jest/environment": "^27.5.1", + "@jest/source-map": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "co": "^4.6.0", + "expect": "^27.5.1", + "is-generator-fn": "^2.0.0", + "jest-each": "^27.5.1", + "jest-matcher-utils": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-runtime": "^27.5.1", + "jest-snapshot": "^27.5.1", + "jest-util": "^27.5.1", + "pretty-format": "^27.5.1", + "throat": "^6.0.1" }, "engines": { - "node": ">=10.13.0" - }, - "peerDependencies": { - "react-loadable": "*", - "webpack": ">=4.41.1 || 5.x" + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "node_modules/react-router": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/react-router/-/react-router-5.2.1.tgz", - "integrity": "sha512-lIboRiOtDLFdg1VTemMwud9vRVuOCZmUIT/7lUoZiSpPODiiH1UQlfXy+vPLC/7IWdFYnhRwAyNqA/+I7wnvKQ==", + "node_modules/jest-jasmine2/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, "dependencies": { - "@babel/runtime": "^7.12.13", - "history": "^4.9.0", - "hoist-non-react-statics": "^3.1.0", - "loose-envify": "^1.3.1", - "mini-create-react-context": "^0.4.0", - "path-to-regexp": "^1.7.0", - "prop-types": "^15.6.2", - "react-is": "^16.6.0", - "tiny-invariant": "^1.0.2", - "tiny-warning": "^1.0.0" + "color-convert": "^2.0.1" }, - "peerDependencies": { - "react": ">=15" + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/react-router-config": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/react-router-config/-/react-router-config-5.1.1.tgz", - "integrity": "sha512-DuanZjaD8mQp1ppHjgnnUnyOlqYXZVjnov/JzFhjLEwd3Z4dYjMSnqrEzzGThH47vpCOqPPwJM2FtthLeJ8Pbg==", + "node_modules/jest-jasmine2/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "dependencies": { - "@babel/runtime": "^7.1.2" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, - "peerDependencies": { - "react": ">=15", - "react-router": ">=5" + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/react-router-dom": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-5.3.0.tgz", - "integrity": "sha512-ObVBLjUZsphUUMVycibxgMdh5jJ1e3o+KpAZBVeHcNQZ4W+uUGGWsokurzlF4YOldQYRQL4y6yFRWM4m3svmuQ==", + "node_modules/jest-jasmine2/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, "dependencies": { - "@babel/runtime": "^7.12.13", - "history": "^4.9.0", - "loose-envify": "^1.3.1", - "prop-types": "^15.6.2", - "react-router": "5.2.1", - "tiny-invariant": "^1.0.2", - "tiny-warning": "^1.0.0" + "color-name": "~1.1.4" }, - "peerDependencies": { - "react": ">=15" + "engines": { + "node": ">=7.0.0" } }, - "node_modules/react-router/node_modules/isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + "node_modules/jest-jasmine2/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true }, - "node_modules/react-router/node_modules/path-to-regexp": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", - "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", - "dependencies": { - "isarray": "0.0.1" + "node_modules/jest-jasmine2/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" } }, - "node_modules/react-side-effect": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/react-side-effect/-/react-side-effect-2.1.1.tgz", - "integrity": "sha512-2FoTQzRNTncBVtnzxFOk2mCpcfxQpenBMbk5kSVBg5UcPqV9fRbgY2zhb7GTWWOlpFmAxhClBDlIq8Rsubz1yQ==", - "peerDependencies": { - "react": "^16.3.0 || ^17.0.0" + "node_modules/jest-jasmine2/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" } }, - "node_modules/react-tabs": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/react-tabs/-/react-tabs-3.2.2.tgz", - "integrity": "sha512-/o52eGKxFHRa+ssuTEgSM8qORnV4+k7ibW+aNQzKe+5gifeVz8nLxCrsI9xdRhfb0wCLdgIambIpb1qCxaMN+A==", + "node_modules/jest-leak-detector": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-27.5.1.tgz", + "integrity": "sha512-POXfWAMvfU6WMUXftV4HolnJfnPOGEu10fscNCA76KBpRRhcMN2c8d3iT2pxQS3HLbA+5X4sOUPzYO2NUyIlHQ==", + "dev": true, "dependencies": { - "clsx": "^1.1.0", - "prop-types": "^15.5.0" + "jest-get-type": "^27.5.1", + "pretty-format": "^27.5.1" }, - "peerDependencies": { - "react": "^16.3.0 || ^17.0.0-0" + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "node_modules/react-textarea-autosize": { - "version": "8.3.3", - "resolved": "https://registry.npmjs.org/react-textarea-autosize/-/react-textarea-autosize-8.3.3.tgz", - "integrity": "sha512-2XlHXK2TDxS6vbQaoPbMOfQ8GK7+irc2fVK6QFIcC8GOnH3zI/v481n+j1L0WaPVvKxwesnY93fEfH++sus2rQ==", + "node_modules/jest-matcher-utils": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-27.5.1.tgz", + "integrity": "sha512-z2uTx/T6LBaCoNWNFWwChLBKYxTMcGBRjAt+2SbP929/Fflb9aa5LGma654Rz8z9HLxsrUaYzxE9T/EFIL/PAw==", + "dev": true, "dependencies": { - "@babel/runtime": "^7.10.2", - "use-composed-ref": "^1.0.0", - "use-latest": "^1.0.0" + "chalk": "^4.0.0", + "jest-diff": "^27.5.1", + "jest-get-type": "^27.5.1", + "pretty-format": "^27.5.1" }, "engines": { - "node": ">=10" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0" + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "node_modules/react-waypoint": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/react-waypoint/-/react-waypoint-10.1.0.tgz", - "integrity": "sha512-wiVF0lTslVm27xHbnvUUADUrcDjrQxAp9lEYGExvcoEBScYbXu3Kt++pLrfj6CqOeeRAL4HcX8aANVLSn6bK0Q==", + "node_modules/jest-matcher-utils/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, "dependencies": { - "@babel/runtime": "^7.12.5", - "consolidated-events": "^1.1.0 || ^2.0.0", - "prop-types": "^15.0.0", - "react-is": "^17.0.1" + "color-convert": "^2.0.1" }, - "peerDependencies": { - "react": "^15.3.0 || ^16.0.0 || ^17.0.0" + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/react-waypoint/node_modules/react-is": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", - "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" - }, - "node_modules/readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "node_modules/jest-matcher-utils/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">= 6" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "node_modules/jest-matcher-utils/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, "dependencies": { - "picomatch": "^2.2.1" + "color-name": "~1.1.4" }, "engines": { - "node": ">=8.10.0" + "node": ">=7.0.0" } }, - "node_modules/reading-time": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/reading-time/-/reading-time-1.5.0.tgz", - "integrity": "sha512-onYyVhBNr4CmAxFsKS7bz+uTLRakypIe4R+5A824vBSkQy/hB3fZepoVEf8OVAxzLvK+H/jm9TzpI3ETSm64Kg==" + "node_modules/jest-matcher-utils/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true }, - "node_modules/rechoir": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", - "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", + "node_modules/jest-matcher-utils/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-matcher-utils/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, "dependencies": { - "resolve": "^1.1.6" + "has-flag": "^4.0.0" }, "engines": { - "node": ">= 0.10" + "node": ">=8" } }, - "node_modules/recursive-readdir": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/recursive-readdir/-/recursive-readdir-2.2.2.tgz", - "integrity": "sha512-nRCcW9Sj7NuZwa2XvH9co8NPeXUBhZP7CRKJtU+cS6PW9FpCIFoI5ib0NT1ZrbNuPoRy0ylyCaUL8Gih4LSyFg==", + "node_modules/jest-message-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-27.5.1.tgz", + "integrity": "sha512-rMyFe1+jnyAAf+NHwTclDz0eAaLkVDdKVHHBFWsBWHnnh5YeJMNWWsv7AbFYXfK3oTqvL7VTWkhNLu1jX24D+g==", + "dev": true, "dependencies": { - "minimatch": "3.0.4" + "@babel/code-frame": "^7.12.13", + "@jest/types": "^27.5.1", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^27.5.1", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" }, "engines": { - "node": ">=0.10.0" + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "node_modules/redoc": { - "version": "2.0.0-rc.57", - "resolved": "https://registry.npmjs.org/redoc/-/redoc-2.0.0-rc.57.tgz", - "integrity": "sha512-f8XIqvZF1agphq6xmOU9jTDVNDFHJt3MzDq1lUgZojb/7YY4eqLyDi6er/yCWYkY9DuB+v2jHCOn5UUbMuKAfg==", + "node_modules/jest-message-util/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, "dependencies": { - "@babel/runtime": "^7.14.0", - "@redocly/openapi-core": "^1.0.0-beta.54", - "@redocly/react-dropdown-aria": "^2.0.11", - "classnames": "^2.3.1", - "decko": "^1.2.0", - "dompurify": "^2.2.8", - "eventemitter3": "^4.0.7", - "json-pointer": "^0.6.1", - "lunr": "^2.3.9", - "mark.js": "^8.11.1", - "marked": "^0.7.0", - "memoize-one": "^5.2.1", - "mobx-react": "^7.2.0", - "openapi-sampler": "^1.0.1", - "path-browserify": "^1.0.1", - "perfect-scrollbar": "^1.5.1", - "polished": "^4.1.3", - "prismjs": "^1.24.1", - "prop-types": "^15.7.2", - "react-tabs": "^3.2.2", - "slugify": "~1.4.7", - "stickyfill": "^1.1.1", - "swagger2openapi": "^7.0.6", - "url-template": "^2.0.8" + "color-convert": "^2.0.1" }, "engines": { - "node": ">=6.9", - "npm": ">=3.0.0" + "node": ">=8" }, - "peerDependencies": { - "core-js": "^3.1.4", - "mobx": "^6.0.4", - "react": "^16.8.4 || ^17.0.0", - "react-dom": "^16.8.4 || ^17.0.0", - "styled-components": "^4.1.1 || ^5.1.1" + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/reftools": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/reftools/-/reftools-1.1.9.tgz", - "integrity": "sha512-OVede/NQE13xBQ+ob5CKd5KyeJYU2YInb1bmV4nRoOfquZPkAkxuOXicSe1PvqIuZZ4kD13sPKBbR7UFDmli6w==", + "node_modules/jest-message-util/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, "funding": { - "url": "https://github.com/Mermade/oas-kit?sponsor=1" + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/regenerate": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", - "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==" - }, - "node_modules/regenerate-unicode-properties": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-9.0.0.tgz", - "integrity": "sha512-3E12UeNSPfjrgwjkR81m5J7Aw/T55Tu7nUyZVQYCKEOs+2dkxEY+DpPtZzO4YruuiPb7NkYLVcyJC4+zCbk5pA==", + "node_modules/jest-message-util/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, "dependencies": { - "regenerate": "^1.4.2" + "color-name": "~1.1.4" }, "engines": { - "node": ">=4" + "node": ">=7.0.0" } }, - "node_modules/regenerator-runtime": { - "version": "0.13.9", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz", - "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==" + "node_modules/jest-message-util/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true }, - "node_modules/regenerator-transform": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.5.tgz", - "integrity": "sha512-eOf6vka5IO151Jfsw2NO9WpGX58W6wWmefK3I1zEGr0lOD0u8rwPaNqQL1aRxUaxLeKO3ArNh3VYg1KbaD+FFw==", - "dependencies": { - "@babel/runtime": "^7.8.4" + "node_modules/jest-message-util/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" } }, - "node_modules/regex-not": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", - "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", + "node_modules/jest-message-util/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, "dependencies": { - "extend-shallow": "^3.0.2", - "safe-regex": "^1.1.0" + "has-flag": "^4.0.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, - "node_modules/regex-not/node_modules/extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "node_modules/jest-mock": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-27.5.1.tgz", + "integrity": "sha512-K4jKbY1d4ENhbrG2zuPWaQBvDly+iZ2yAW+T1fATN78hc0sInwn7wZB8XtlNnvHug5RMwV897Xm4LqmPM4e2Og==", + "dev": true, "dependencies": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" + "@jest/types": "^27.5.1", + "@types/node": "*" }, "engines": { - "node": ">=0.10.0" + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "node_modules/regex-not/node_modules/is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dependencies": { - "is-plain-object": "^2.0.4" + "node_modules/jest-pnp-resolver": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.2.tgz", + "integrity": "sha512-olV41bKSMm8BdnuMsewT4jqlZ8+3TCARAXjZGT9jcoSnrfUnRCqnMoF9XEeoWjbzObpqF9dRhHQj0Xb9QdF6/w==", + "dev": true, + "engines": { + "node": ">=6" }, + "peerDependencies": { + "jest-resolve": "*" + }, + "peerDependenciesMeta": { + "jest-resolve": { + "optional": true + } + } + }, + "node_modules/jest-regex-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-27.5.1.tgz", + "integrity": "sha512-4bfKq2zie+x16okqDXjXn9ql2B0dScQu+vcwe4TvFVhkVyuWLqpZrZtXxLLWoXYgn0E87I6r6GRYHF7wFZBUvg==", + "dev": true, "engines": { - "node": ">=0.10.0" + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "node_modules/regexp.prototype.flags": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.3.1.tgz", - "integrity": "sha512-JiBdRBq91WlY7uRJ0ds7R+dU02i6LKi8r3BuQhNXn+kmeLN+EfHhfjqMRis1zJxnlu88hq/4dx0P2OP3APRTOA==", + "node_modules/jest-resolve": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-27.5.1.tgz", + "integrity": "sha512-FFDy8/9E6CV83IMbDpcjOhumAQPDyETnU2KZ1O98DwTnz8AOBsW/Xv3GySr1mOZdItLR+zDZ7I/UdTFbgSOVCw==", + "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" + "@jest/types": "^27.5.1", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^27.5.1", + "jest-pnp-resolver": "^1.2.2", + "jest-util": "^27.5.1", + "jest-validate": "^27.5.1", + "resolve": "^1.20.0", + "resolve.exports": "^1.1.0", + "slash": "^3.0.0" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "node_modules/regexpu-core": { - "version": "4.8.0", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.8.0.tgz", - "integrity": "sha512-1F6bYsoYiz6is+oz70NWur2Vlh9KWtswuRuzJOfeYUrfPX2o8n74AnUVaOGDbUqVGO9fNHu48/pjJO4sNVwsOg==", + "node_modules/jest-resolve-dependencies": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-27.5.1.tgz", + "integrity": "sha512-QQOOdY4PE39iawDn5rzbIePNigfe5B9Z91GDD1ae/xNDlu9kaat8QQ5EKnNmVWPV54hUdxCVwwj6YMgR2O7IOg==", + "dev": true, "dependencies": { - "regenerate": "^1.4.2", - "regenerate-unicode-properties": "^9.0.0", - "regjsgen": "^0.5.2", - "regjsparser": "^0.7.0", - "unicode-match-property-ecmascript": "^2.0.0", - "unicode-match-property-value-ecmascript": "^2.0.0" + "@jest/types": "^27.5.1", + "jest-regex-util": "^27.5.1", + "jest-snapshot": "^27.5.1" }, "engines": { - "node": ">=4" + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "node_modules/registry-auth-token": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.2.1.tgz", - "integrity": "sha512-6gkSb4U6aWJB4SF2ZvLb76yCBjcvufXBqvvEx1HbmKPkutswjW1xNVRY0+daljIYRbogN7O0etYSlbiaEQyMyw==", + "node_modules/jest-resolve/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, "dependencies": { - "rc": "^1.2.8" + "color-convert": "^2.0.1" }, "engines": { - "node": ">=6.0.0" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/registry-url": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-5.1.0.tgz", - "integrity": "sha512-8acYXXTI0AkQv6RAOjE3vOaIXZkT9wo4LOFbBKYQEEnnMNBpKqdUrI6S4NT0KPIo/WVvJ5tE/X5LF/TQUf0ekw==", + "node_modules/jest-resolve/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "dependencies": { - "rc": "^1.2.8" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">=8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/regjsgen": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.2.tgz", - "integrity": "sha512-OFFT3MfrH90xIW8OOSyUrk6QHD5E9JOTeGodiJeBS3J6IwlgzJMNE/1bZklWz5oTg+9dCMyEetclvCVXOPoN3A==" - }, - "node_modules/regjsparser": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.7.0.tgz", - "integrity": "sha512-A4pcaORqmNMDVwUjWoTzuhwMGpP+NykpfqAsEgI1FSH/EzC7lrN5TMd+kN8YCovX+jMpu8eaqXgXPCa0g8FQNQ==", + "node_modules/jest-resolve/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, "dependencies": { - "jsesc": "~0.5.0" + "color-name": "~1.1.4" }, - "bin": { - "regjsparser": "bin/parser" + "engines": { + "node": ">=7.0.0" } }, - "node_modules/regjsparser/node_modules/jsesc": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", - "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", - "bin": { - "jsesc": "bin/jsesc" + "node_modules/jest-resolve/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jest-resolve/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" } }, - "node_modules/rehype-parse": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/rehype-parse/-/rehype-parse-6.0.2.tgz", - "integrity": "sha512-0S3CpvpTAgGmnz8kiCyFLGuW5yA4OQhyNTm/nwPopZ7+PI11WnGl1TTWTGv/2hPEe/g2jRLlhVVSsoDH8waRug==", + "node_modules/jest-resolve/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, "dependencies": { - "hast-util-from-parse5": "^5.0.0", - "parse5": "^5.0.0", - "xtend": "^4.0.0" + "has-flag": "^4.0.0" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "engines": { + "node": ">=8" } }, - "node_modules/relateurl": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", - "integrity": "sha1-VNvzd+UUQKypCkzSdGANP/LYiKk=", + "node_modules/jest-runner": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-27.5.1.tgz", + "integrity": "sha512-g4NPsM4mFCOwFKXO4p/H/kWGdJp9V8kURY2lX8Me2drgXqG7rrZAx5kv+5H7wtt/cdFIjhqYx1HrlqWHaOvDaQ==", + "dev": true, + "dependencies": { + "@jest/console": "^27.5.1", + "@jest/environment": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "emittery": "^0.8.1", + "graceful-fs": "^4.2.9", + "jest-docblock": "^27.5.1", + "jest-environment-jsdom": "^27.5.1", + "jest-environment-node": "^27.5.1", + "jest-haste-map": "^27.5.1", + "jest-leak-detector": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-resolve": "^27.5.1", + "jest-runtime": "^27.5.1", + "jest-util": "^27.5.1", + "jest-worker": "^27.5.1", + "source-map-support": "^0.5.6", + "throat": "^6.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-runner/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, "engines": { - "node": ">= 0.10" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/remark-admonitions": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/remark-admonitions/-/remark-admonitions-1.2.1.tgz", - "integrity": "sha512-Ji6p68VDvD+H1oS95Fdx9Ar5WA2wcDA4kwrrhVU7fGctC6+d3uiMICu7w7/2Xld+lnU7/gi+432+rRbup5S8ow==", + "node_modules/jest-runner/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "dependencies": { - "rehype-parse": "^6.0.2", - "unified": "^8.4.2", - "unist-util-visit": "^2.0.1" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/remark-emoji": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/remark-emoji/-/remark-emoji-2.2.0.tgz", - "integrity": "sha512-P3cj9s5ggsUvWw5fS2uzCHJMGuXYRb0NnZqYlNecewXt8QBU9n5vW3DUUKOhepS8F9CwdMx9B8a3i7pqFWAI5w==", + "node_modules/jest-runner/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, "dependencies": { - "emoticon": "^3.2.0", - "node-emoji": "^1.10.0", - "unist-util-visit": "^2.0.3" + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" } }, - "node_modules/remark-footnotes": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/remark-footnotes/-/remark-footnotes-2.0.0.tgz", - "integrity": "sha512-3Clt8ZMH75Ayjp9q4CorNeyjwIxHFcTkaektplKGl2A1jNGEUey8cKL0ZC5vJwfcD5GFGsNLImLG/NGzWIzoMQ==", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "node_modules/jest-runner/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jest-runner/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" } }, - "node_modules/remark-mdx": { - "version": "1.6.22", - "resolved": "https://registry.npmjs.org/remark-mdx/-/remark-mdx-1.6.22.tgz", - "integrity": "sha512-phMHBJgeV76uyFkH4rvzCftLfKCr2RZuF+/gmVcaKrpsihyzmhXjA0BEMDaPTXG5y8qZOKPVo83NAOX01LPnOQ==", + "node_modules/jest-runner/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, "dependencies": { - "@babel/core": "7.12.9", - "@babel/helper-plugin-utils": "7.10.4", - "@babel/plugin-proposal-object-rest-spread": "7.12.1", - "@babel/plugin-syntax-jsx": "7.12.1", - "@mdx-js/util": "1.6.22", - "is-alphabetical": "1.0.4", - "remark-parse": "8.0.3", - "unified": "9.2.0" + "has-flag": "^4.0.0" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "engines": { + "node": ">=8" } }, - "node_modules/remark-mdx/node_modules/@babel/core": { - "version": "7.12.9", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.12.9.tgz", - "integrity": "sha512-gTXYh3M5wb7FRXQy+FErKFAv90BnlOuNn1QkCK2lREoPAjrQCO49+HVSrFoe5uakFAF5eenS75KbO2vQiLrTMQ==", + "node_modules/jest-runtime": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-27.5.1.tgz", + "integrity": "sha512-o7gxw3Gf+H2IGt8fv0RiyE1+r83FJBRruoA+FXrlHw6xEyBsU8ugA6IPfTdVyA0w8HClpbK+DGJxH59UrNMx8A==", + "dev": true, "dependencies": { - "@babel/code-frame": "^7.10.4", - "@babel/generator": "^7.12.5", - "@babel/helper-module-transforms": "^7.12.1", - "@babel/helpers": "^7.12.5", - "@babel/parser": "^7.12.7", - "@babel/template": "^7.12.7", - "@babel/traverse": "^7.12.9", - "@babel/types": "^7.12.7", - "convert-source-map": "^1.7.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.1", - "json5": "^2.1.2", - "lodash": "^4.17.19", - "resolve": "^1.3.2", - "semver": "^5.4.1", - "source-map": "^0.5.0" + "@jest/environment": "^27.5.1", + "@jest/fake-timers": "^27.5.1", + "@jest/globals": "^27.5.1", + "@jest/source-map": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", + "chalk": "^4.0.0", + "cjs-module-lexer": "^1.0.0", + "collect-v8-coverage": "^1.0.0", + "execa": "^5.0.0", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-mock": "^27.5.1", + "jest-regex-util": "^27.5.1", + "jest-resolve": "^27.5.1", + "jest-snapshot": "^27.5.1", + "jest-util": "^27.5.1", + "slash": "^3.0.0", + "strip-bom": "^4.0.0" }, "engines": { - "node": ">=6.9.0" + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-runtime/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/babel" + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/remark-mdx/node_modules/@babel/helper-plugin-utils": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz", - "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==" - }, - "node_modules/remark-mdx/node_modules/@babel/plugin-proposal-object-rest-spread": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.12.1.tgz", - "integrity": "sha512-s6SowJIjzlhx8o7lsFx5zmY4At6CTtDvgNQDdPzkBQucle58A6b/TTeEBYtyDgmcXjUTM+vE8YOGHZzzbc/ioA==", + "node_modules/jest-runtime/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4", - "@babel/plugin-syntax-object-rest-spread": "^7.8.0", - "@babel/plugin-transform-parameters": "^7.12.1" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/remark-mdx/node_modules/@babel/plugin-syntax-jsx": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.12.1.tgz", - "integrity": "sha512-1yRi7yAtB0ETgxdY9ti/p2TivUxJkTdhu/ZbF9MshVGqOx1TdB3b7xCXs49Fupgg50N45KcAsRP/ZqWjs9SRjg==", + "node_modules/jest-runtime/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" + "color-name": "~1.1.4" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "engines": { + "node": ">=7.0.0" } }, - "node_modules/remark-mdx/node_modules/is-buffer": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz", - "integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], + "node_modules/jest-runtime/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jest-runtime/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, "engines": { - "node": ">=4" + "node": ">=8" } }, - "node_modules/remark-mdx/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "bin": { - "semver": "bin/semver" + "node_modules/jest-runtime/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" } }, - "node_modules/remark-mdx/node_modules/unified": { - "version": "9.2.0", - "resolved": "https://registry.npmjs.org/unified/-/unified-9.2.0.tgz", - "integrity": "sha512-vx2Z0vY+a3YoTj8+pttM3tiJHCwY5UFbYdiWrwBEbHmK8pvsPj2rtAX2BFfgXen8T39CJWblWRDT4L5WGXtDdg==", + "node_modules/jest-serializer": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-27.5.1.tgz", + "integrity": "sha512-jZCyo6iIxO1aqUxpuBlwTDMkzOAJS4a3eYz3YzgxxVQFwLeSA7Jfq5cbqCY+JLvTDrWirgusI/0KwxKMgrdf7w==", + "dev": true, "dependencies": { - "bail": "^1.0.0", - "extend": "^3.0.0", - "is-buffer": "^2.0.0", - "is-plain-obj": "^2.0.0", - "trough": "^1.0.0", - "vfile": "^4.0.0" + "@types/node": "*", + "graceful-fs": "^4.2.9" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "node_modules/remark-parse": { - "version": "8.0.3", - "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-8.0.3.tgz", - "integrity": "sha512-E1K9+QLGgggHxCQtLt++uXltxEprmWzNfg+MxpfHsZlrddKzZ/hZyWHDbK3/Ap8HJQqYJRXP+jHczdL6q6i85Q==", + "node_modules/jest-snapshot": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-27.5.1.tgz", + "integrity": "sha512-yYykXI5a0I31xX67mgeLw1DZ0bJB+gpq5IpSuCAoyDi0+BhgU/RIrL+RTzDmkNTchvDFWKP8lp+w/42Z3us5sA==", + "dev": true, "dependencies": { - "ccount": "^1.0.0", - "collapse-white-space": "^1.0.2", - "is-alphabetical": "^1.0.0", - "is-decimal": "^1.0.0", - "is-whitespace-character": "^1.0.0", - "is-word-character": "^1.0.0", - "markdown-escapes": "^1.0.0", - "parse-entities": "^2.0.0", - "repeat-string": "^1.5.4", - "state-toggle": "^1.0.0", - "trim": "0.0.1", - "trim-trailing-lines": "^1.0.0", - "unherit": "^1.0.4", - "unist-util-remove-position": "^2.0.0", - "vfile-location": "^3.0.0", - "xtend": "^4.0.1" + "@babel/core": "^7.7.2", + "@babel/generator": "^7.7.2", + "@babel/plugin-syntax-typescript": "^7.7.2", + "@babel/traverse": "^7.7.2", + "@babel/types": "^7.0.0", + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/babel__traverse": "^7.0.4", + "@types/prettier": "^2.1.5", + "babel-preset-current-node-syntax": "^1.0.0", + "chalk": "^4.0.0", + "expect": "^27.5.1", + "graceful-fs": "^4.2.9", + "jest-diff": "^27.5.1", + "jest-get-type": "^27.5.1", + "jest-haste-map": "^27.5.1", + "jest-matcher-utils": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-util": "^27.5.1", + "natural-compare": "^1.4.0", + "pretty-format": "^27.5.1", + "semver": "^7.3.2" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-snapshot/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/remark-squeeze-paragraphs": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/remark-squeeze-paragraphs/-/remark-squeeze-paragraphs-4.0.0.tgz", - "integrity": "sha512-8qRqmL9F4nuLPIgl92XUuxI3pFxize+F1H0e/W3llTk0UsjJaj01+RrirkMw7P21RKe4X6goQhYRSvNWX+70Rw==", + "node_modules/jest-snapshot/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "dependencies": { - "mdast-squeeze-paragraphs": "^4.0.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/remove-trailing-separator": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", - "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=" - }, - "node_modules/renderkid": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-2.0.7.tgz", - "integrity": "sha512-oCcFyxaMrKsKcTY59qnCAtmDVSLfPbrv6A3tVbPdFMMrv5jaK10V6m40cKsoPNhAqN6rmHW9sswW4o3ruSrwUQ==", + "node_modules/jest-snapshot/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, "dependencies": { - "css-select": "^4.1.3", - "dom-converter": "^0.2.0", - "htmlparser2": "^6.1.0", - "lodash": "^4.17.21", - "strip-ansi": "^3.0.1" + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" } }, - "node_modules/renderkid/node_modules/ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "node_modules/jest-snapshot/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jest-snapshot/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, - "node_modules/renderkid/node_modules/htmlparser2": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", - "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", - "funding": [ - "https://github.com/fb55/htmlparser2?sponsor=1", - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ], + "node_modules/jest-snapshot/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, "dependencies": { - "domelementtype": "^2.0.1", - "domhandler": "^4.0.0", - "domutils": "^2.5.2", - "entities": "^2.0.0" + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" } }, - "node_modules/renderkid/node_modules/strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "node_modules/jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "dev": true, "dependencies": { - "ansi-regex": "^2.0.0" + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" }, "engines": { - "node": ">=0.10.0" + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "node_modules/repeat-element": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.4.tgz", - "integrity": "sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ==", + "node_modules/jest-util/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, "engines": { - "node": ">=0.10.0" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/repeat-string": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", + "node_modules/jest-util/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, "engines": { - "node": ">=0.10" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "node_modules/jest-util/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, "engines": { - "node": ">=0.10.0" + "node": ">=7.0.0" } }, - "node_modules/require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "node_modules/jest-util/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jest-util/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, - "node_modules/require-like": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/require-like/-/require-like-0.1.2.tgz", - "integrity": "sha1-rW8wwTvs15cBDEaK+ndcDAprR/o=", + "node_modules/jest-util/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, "engines": { - "node": "*" + "node": ">=8" } }, - "node_modules/require-main-filename": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==" - }, - "node_modules/requires-port": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=" - }, - "node_modules/resolve": { - "version": "1.20.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", - "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", + "node_modules/jest-validate": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-27.5.1.tgz", + "integrity": "sha512-thkNli0LYTmOI1tDB3FI1S1RTp/Bqyd9pTarJwL87OIBFuqEb5Apv5EaApEudYg4g86e3CT6kM0RowkhtEnCBQ==", + "dev": true, "dependencies": { - "is-core-module": "^2.2.0", - "path-parse": "^1.0.6" + "@jest/types": "^27.5.1", + "camelcase": "^6.2.0", + "chalk": "^4.0.0", + "jest-get-type": "^27.5.1", + "leven": "^3.1.0", + "pretty-format": "^27.5.1" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "node_modules/resolve-cwd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-2.0.0.tgz", - "integrity": "sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=", + "node_modules/jest-validate/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, "dependencies": { - "resolve-from": "^3.0.0" + "color-convert": "^2.0.1" }, "engines": { - "node": ">=4" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/resolve-cwd/node_modules/resolve-from": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", - "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", + "node_modules/jest-validate/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, "engines": { - "node": ">=4" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "node_modules/jest-validate/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, "engines": { - "node": ">=4" + "node": ">=7.0.0" } }, - "node_modules/resolve-pathname": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-pathname/-/resolve-pathname-3.0.0.tgz", - "integrity": "sha512-C7rARubxI8bXFNB/hqcp/4iUeIXJhJZvFPFPiSPRnhU5UPxzMFIl+2E6yY6c4k9giDJAhtV+enfA+G89N6Csng==" - }, - "node_modules/resolve-url": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", - "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", - "deprecated": "https://github.com/lydell/resolve-url#deprecated" + "node_modules/jest-validate/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true }, - "node_modules/responselike": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", - "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=", - "dependencies": { - "lowercase-keys": "^1.0.0" + "node_modules/jest-validate/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" } }, - "node_modules/ret": { - "version": "0.1.15", - "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", - "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", + "node_modules/jest-validate/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, "engines": { - "node": ">=0.12" + "node": ">=8" } }, - "node_modules/retry": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", - "integrity": "sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs=", + "node_modules/jest-watcher": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-27.5.1.tgz", + "integrity": "sha512-z676SuD6Z8o8qbmEGhoEUFOM1+jfEiL3DXHK/xgEiG2EyNYfFG60jluWcupY6dATjfEsKQuibReS1djInQnoVw==", + "dev": true, + "dependencies": { + "@jest/test-result": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "jest-util": "^27.5.1", + "string-length": "^4.0.1" + }, "engines": { - "node": ">= 4" + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "node_modules/reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "node_modules/jest-watcher/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "node_modules/jest-watcher/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "dependencies": { - "glob": "^7.1.3" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, - "bin": { - "rimraf": "bin.js" + "engines": { + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/ripemd160": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", - "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", + "node_modules/jest-watcher/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, "dependencies": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1" + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" } }, - "node_modules/rtl-detect": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/rtl-detect/-/rtl-detect-1.0.4.tgz", - "integrity": "sha512-EBR4I2VDSSYr7PkBmFy04uhycIpDKp+21p/jARYXlCSjQksTBQcJ0HFUPOO79EPPH5JS6VAhiIQbycf0O3JAxQ==" + "node_modules/jest-watcher/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true }, - "node_modules/rtlcss": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/rtlcss/-/rtlcss-3.3.0.tgz", - "integrity": "sha512-XZ2KEatH2nU5yPlts1Wu8SGIuZ3ndN025HQX5MqtUCUiOn5WkCDbcpJ2VJWjpuFmM2cUTQ1xtH21fhMCSseI5A==", - "dependencies": { - "chalk": "^4.1.0", - "find-up": "^5.0.0", - "mkdirp": "^1.0.4", - "postcss": "^8.2.4", - "strip-json-comments": "^3.1.1" - }, - "bin": { - "rtlcss": "bin/rtlcss.js" - }, - "peerDependencies": { - "postcss": "^8.2.4" + "node_modules/jest-watcher/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" } }, - "node_modules/rtlcss/node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "node_modules/jest-watcher/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" + "has-flag": "^4.0.0" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=8" } }, - "node_modules/rtlcss/node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "node_modules/jest-worker": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", + "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", "dependencies": { - "p-locate": "^5.0.0" + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">= 10.13.0" } }, - "node_modules/rtlcss/node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "bin": { - "mkdirp": "bin/cmd.js" - }, + "node_modules/jest-worker/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "engines": { - "node": ">=10" + "node": ">=8" } }, - "node_modules/rtlcss/node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dependencies": { - "p-limit": "^3.0.2" + "has-flag": "^4.0.0" }, "engines": { "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "node_modules/rtlcss/node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "node_modules/joi": { + "version": "17.6.0", + "resolved": "https://registry.npmjs.org/joi/-/joi-17.6.0.tgz", + "integrity": "sha512-OX5dG6DTbcr/kbMFj0KGYxuew69HPcAE3K/sZpEV2nP6e/j/C0HV+HNiBPCASxdx5T7DMoa0s8UeHWMnb6n2zw==", + "dependencies": { + "@hapi/hoek": "^9.0.0", + "@hapi/topo": "^5.0.0", + "@sideway/address": "^4.1.3", + "@sideway/formula": "^3.0.0", + "@sideway/pinpoint": "^2.0.0" + } + }, + "node_modules/jpeg-js": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/jpeg-js/-/jpeg-js-0.4.2.tgz", + "integrity": "sha512-+az2gi/hvex7eLTMTlbRLOhH6P6WFdk2ITI8HJsaH2VqYO0I594zXSYEP+tf4FW+8Cy68ScDXoAsQdyQanv3sw==" + }, + "node_modules/js-levenshtein": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/js-levenshtein/-/js-levenshtein-1.1.6.tgz", + "integrity": "sha512-X2BB11YZtrRqY4EnQcLX5Rh373zbK4alC1FW7D7MBhL2gtcC17cTnr6DmfHZeS0s2rTHjUTMMHfG7gO8SSdw+g==", "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=0.10.0" } }, - "node_modules/run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "dependencies": { - "queue-microtask": "^1.2.2" + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" } }, - "node_modules/rxjs": { - "version": "6.6.7", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", - "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", + "node_modules/jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==", + "dev": true + }, + "node_modules/jsdom": { + "version": "16.7.0", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-16.7.0.tgz", + "integrity": "sha512-u9Smc2G1USStM+s/x1ru5Sxrl6mPYCbByG1U/hUmqaVsm4tbNyS7CicOSRyuGQYZhTu0h84qkZZQ/I+dzizSVw==", + "dev": true, "dependencies": { - "tslib": "^1.9.0" + "abab": "^2.0.5", + "acorn": "^8.2.4", + "acorn-globals": "^6.0.0", + "cssom": "^0.4.4", + "cssstyle": "^2.3.0", + "data-urls": "^2.0.0", + "decimal.js": "^10.2.1", + "domexception": "^2.0.1", + "escodegen": "^2.0.0", + "form-data": "^3.0.0", + "html-encoding-sniffer": "^2.0.1", + "http-proxy-agent": "^4.0.1", + "https-proxy-agent": "^5.0.0", + "is-potential-custom-element-name": "^1.0.1", + "nwsapi": "^2.2.0", + "parse5": "6.0.1", + "saxes": "^5.0.1", + "symbol-tree": "^3.2.4", + "tough-cookie": "^4.0.0", + "w3c-hr-time": "^1.0.2", + "w3c-xmlserializer": "^2.0.0", + "webidl-conversions": "^6.1.0", + "whatwg-encoding": "^1.0.5", + "whatwg-mimetype": "^2.3.0", + "whatwg-url": "^8.5.0", + "ws": "^7.4.6", + "xml-name-validator": "^3.0.0" }, "engines": { - "npm": ">=2.0.0" + "node": ">=10" + }, + "peerDependencies": { + "canvas": "^2.5.0" + }, + "peerDependenciesMeta": { + "canvas": { + "optional": true + } } }, - "node_modules/rxjs/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" - }, - "node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "node_modules/safe-regex": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", - "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", - "dependencies": { - "ret": "~0.1.10" + "node_modules/jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=4" } }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + "node_modules/json-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", + "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=" }, - "node_modules/sax": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", - "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" + "node_modules/json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==" }, - "node_modules/scheduler": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.20.2.tgz", - "integrity": "sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ==", - "dependencies": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1" - } + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" }, - "node_modules/schema-utils": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", - "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", + "node_modules/json-pointer": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/json-pointer/-/json-pointer-0.6.2.tgz", + "integrity": "sha512-vLWcKbOaXlO+jvRy4qNd+TI1QUPZzfJj1tpJ3vAXDych5XJf93ftpUKe5pKCrzyIIwgBJcOcCVRUfqQP25afBw==", "dependencies": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" + "foreach": "^2.0.4" } }, - "node_modules/section-matter": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/section-matter/-/section-matter-1.0.0.tgz", - "integrity": "sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA==", - "dependencies": { - "extend-shallow": "^2.0.1", - "kind-of": "^6.0.0" - }, - "engines": { - "node": ">=4" - } + "node_modules/json-schema": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", + "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", + "dev": true }, - "node_modules/select-hose": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", - "integrity": "sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo=" + "node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" }, - "node_modules/selfsigned": { - "version": "1.10.11", - "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-1.10.11.tgz", - "integrity": "sha512-aVmbPOfViZqOZPgRBT0+3u4yZFHpmnIghLMlAcb5/xhp5ZtB/RVnKhz5vl2M32CLXAqR4kha9zfhNg0Lf/sxKA==", - "dependencies": { - "node-forge": "^0.10.0" - } + "node_modules/json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", + "dev": true }, - "node_modules/semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", - "dependencies": { - "lru-cache": "^6.0.0" - }, + "node_modules/json5": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz", + "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==", "bin": { - "semver": "bin/semver.js" + "json5": "lib/cli.js" }, "engines": { - "node": ">=10" + "node": ">=6" } }, - "node_modules/semver-diff": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-3.1.1.tgz", - "integrity": "sha512-GX0Ix/CJcHyB8c4ykpHGIAvLyOwOobtM/8d+TQkAd81/bEjgPHrfba41Vpesr7jX/t8Uh+R3EX9eAS5be+jQYg==", + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", "dependencies": { - "semver": "^6.3.0" + "universalify": "^2.0.0" }, - "engines": { - "node": ">=8" - } - }, - "node_modules/semver-diff/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "bin": { - "semver": "bin/semver.js" + "optionalDependencies": { + "graceful-fs": "^4.1.6" } }, - "node_modules/send": { - "version": "0.17.1", - "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", - "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", + "node_modules/jsprim": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-2.0.2.tgz", + "integrity": "sha512-gqXddjPqQ6G40VdnI6T6yObEC+pDNvyP95wdQhkWkg7crHH3km5qP1FsOXEkzEQwnz6gz5qGTn1c2Y52wP3OyQ==", + "dev": true, + "engines": [ + "node >=0.6.0" + ], "dependencies": { - "debug": "2.6.9", - "depd": "~1.1.2", - "destroy": "~1.0.4", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "~1.7.2", - "mime": "1.6.0", - "ms": "2.1.1", - "on-finished": "~2.3.0", - "range-parser": "~1.2.1", - "statuses": "~1.5.0" - }, - "engines": { - "node": ">= 0.8.0" + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.4.0", + "verror": "1.10.0" } }, - "node_modules/send/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "node_modules/katex": { + "version": "0.13.24", + "resolved": "https://registry.npmjs.org/katex/-/katex-0.13.24.tgz", + "integrity": "sha512-jZxYuKCma3VS5UuxOx/rFV1QyGSl3Uy/i0kTJF3HgQ5xMinCQVF8Zd4bMY/9aI9b9A2pjIBOsjSSm68ykTAr8w==", + "funding": [ + "https://opencollective.com/katex", + "https://github.com/sponsors/katex" + ], "dependencies": { - "ms": "2.0.0" + "commander": "^8.0.0" + }, + "bin": { + "katex": "cli.js" } }, - "node_modules/send/node_modules/debug/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - }, - "node_modules/send/node_modules/ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" - }, - "node_modules/serialize-javascript": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", - "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", - "dependencies": { - "randombytes": "^2.1.0" + "node_modules/katex/node_modules/commander": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", + "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", + "engines": { + "node": ">= 12" } }, - "node_modules/serve-handler": { - "version": "6.1.3", - "resolved": "https://registry.npmjs.org/serve-handler/-/serve-handler-6.1.3.tgz", - "integrity": "sha512-FosMqFBNrLyeiIDvP1zgO6YoTzFYHxLDEIavhlmQ+knB2Z7l1t+kGLHkZIDN7UVWqQAmKI3D20A6F6jo3nDd4w==", + "node_modules/keyv": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", + "integrity": "sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==", "dependencies": { - "bytes": "3.0.0", - "content-disposition": "0.5.2", - "fast-url-parser": "1.1.3", - "mime-types": "2.1.18", - "minimatch": "3.0.4", - "path-is-inside": "1.0.2", - "path-to-regexp": "2.2.1", - "range-parser": "1.2.0" + "json-buffer": "3.0.0" } }, - "node_modules/serve-handler/node_modules/bytes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", - "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=", + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", "engines": { - "node": ">= 0.8" + "node": ">=0.10.0" } }, - "node_modules/serve-handler/node_modules/content-disposition": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", - "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ=", + "node_modules/kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", "engines": { - "node": ">= 0.6" + "node": ">=6" } }, - "node_modules/serve-handler/node_modules/mime-db": { - "version": "1.33.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz", - "integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==", + "node_modules/klona": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/klona/-/klona-2.0.5.tgz", + "integrity": "sha512-pJiBpiXMbt7dkzXe8Ghj/u4FfXOOa98fPW+bihOJ4SjnoijweJrNThJfd3ifXpXhREjpoF2mZVH1GfS9LV3kHQ==", "engines": { - "node": ">= 0.6" + "node": ">= 8" } }, - "node_modules/serve-handler/node_modules/mime-types": { - "version": "2.1.18", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz", - "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==", + "node_modules/latest-version": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-5.1.0.tgz", + "integrity": "sha512-weT+r0kTkRQdCdYCNtkMwWXQTMEswKrFBkm4ckQOMVhhqhIMI1UT2hMj+1iigIhgSZm5gTmrRXBNoGUgaTY1xA==", "dependencies": { - "mime-db": "~1.33.0" + "package-json": "^6.3.0" }, "engines": { - "node": ">= 0.6" + "node": ">=8" } }, - "node_modules/serve-handler/node_modules/path-to-regexp": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-2.2.1.tgz", - "integrity": "sha512-gu9bD6Ta5bwGrrU8muHzVOBFFREpp2iRkVfhBJahwJ6p6Xw20SjT0MxLnwkjOibQmGSYhiUnf2FLe7k+jcFmGQ==" + "node_modules/lazy-ass": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/lazy-ass/-/lazy-ass-1.6.0.tgz", + "integrity": "sha512-cc8oEVoctTvsFZ/Oje/kGnHbpWHYBe8IAJe4C0QNc3t8uM/0Y8+erSz/7Y1ALuXTEZTMvxXwO6YbX1ey3ujiZw==", + "dev": true, + "engines": { + "node": "> 0.8" + } }, - "node_modules/serve-handler/node_modules/range-parser": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", - "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=", + "node_modules/leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", "engines": { - "node": ">= 0.6" + "node": ">=6" } }, - "node_modules/serve-index": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", - "integrity": "sha1-03aNabHn2C5c4FD/9bRTvqEqkjk=", + "node_modules/levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==", + "dev": true, "dependencies": { - "accepts": "~1.3.4", - "batch": "0.6.1", - "debug": "2.6.9", - "escape-html": "~1.0.3", - "http-errors": "~1.6.2", - "mime-types": "~2.1.17", - "parseurl": "~1.3.2" + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" }, "engines": { "node": ">= 0.8.0" } }, - "node_modules/serve-index/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dependencies": { - "ms": "2.0.0" + "node_modules/lilconfig": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.0.5.tgz", + "integrity": "sha512-xaYmXZtTHPAw5m+xLN8ab9C+3a8YmV3asNSPOATITbtwrfbwaLJj8h66H1WMIpALCkqsIzK3h7oQ+PdX+LQ9Eg==", + "engines": { + "node": ">=10" } }, - "node_modules/serve-index/node_modules/http-errors": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", - "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==" + }, + "node_modules/listr2": { + "version": "3.14.0", + "resolved": "https://registry.npmjs.org/listr2/-/listr2-3.14.0.tgz", + "integrity": "sha512-TyWI8G99GX9GjE54cJ+RrNMcIFBfwMPxc3XTFiAYGN4s10hWROGtOg7+O6u6LE3mNkyld7RSLE6nrKBvTfcs3g==", + "dev": true, "dependencies": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.0", - "statuses": ">= 1.4.0 < 2" + "cli-truncate": "^2.1.0", + "colorette": "^2.0.16", + "log-update": "^4.0.0", + "p-map": "^4.0.0", + "rfdc": "^1.3.0", + "rxjs": "^7.5.1", + "through": "^2.3.8", + "wrap-ansi": "^7.0.0" }, "engines": { - "node": ">= 0.6" + "node": ">=10.0.0" + }, + "peerDependencies": { + "enquirer": ">= 2.3.0 < 3" + }, + "peerDependenciesMeta": { + "enquirer": { + "optional": true + } } }, - "node_modules/serve-index/node_modules/inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" - }, - "node_modules/serve-index/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - }, - "node_modules/serve-index/node_modules/setprototypeof": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", - "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==" - }, - "node_modules/serve-static": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", - "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", + "node_modules/listr2/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, "dependencies": { - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.17.1" + "color-convert": "^2.0.1" }, "engines": { - "node": ">= 0.8.0" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" - }, - "node_modules/set-value": { + "node_modules/listr2/node_modules/color-convert": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", - "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, "dependencies": { - "extend-shallow": "^2.0.1", - "is-extendable": "^0.1.1", - "is-plain-object": "^2.0.3", - "split-string": "^3.0.1" + "color-name": "~1.1.4" }, "engines": { - "node": ">=0.10.0" + "node": ">=7.0.0" } }, - "node_modules/setimmediate": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", - "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=" + "node_modules/listr2/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true }, - "node_modules/setprototypeof": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", - "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" + "node_modules/listr2/node_modules/colorette": { + "version": "2.0.19", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.19.tgz", + "integrity": "sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ==", + "dev": true }, - "node_modules/sha.js": { - "version": "2.4.11", - "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", - "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", - "dependencies": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - }, - "bin": { - "sha.js": "bin.js" - } + "node_modules/listr2/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true }, - "node_modules/shallow-clone": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", - "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", + "node_modules/listr2/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, "dependencies": { - "kind-of": "^6.0.2" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" }, "engines": { "node": ">=8" } }, - "node_modules/shallowequal": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz", - "integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==" - }, - "node_modules/sharp": { - "version": "0.28.3", - "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.28.3.tgz", - "integrity": "sha512-21GEP45Rmr7q2qcmdnjDkNP04Ooh5v0laGS5FDpojOO84D1DJwUijLiSq8XNNM6e8aGXYtoYRh3sVNdm8NodMA==", - "hasInstallScript": true, + "node_modules/listr2/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, "dependencies": { - "color": "^3.1.3", - "detect-libc": "^1.0.3", - "node-addon-api": "^3.2.0", - "prebuild-install": "^6.1.2", - "semver": "^7.3.5", - "simple-get": "^3.1.0", - "tar-fs": "^2.1.1", - "tunnel-agent": "^0.6.0" + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" }, "engines": { "node": ">=10" }, "funding": { - "url": "https://opencollective.com/libvips" + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "node_modules/load-bmfont": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/load-bmfont/-/load-bmfont-1.4.1.tgz", + "integrity": "sha512-8UyQoYmdRDy81Brz6aLAUhfZLwr5zV0L3taTQ4hju7m6biuwiWiJXjPhBJxbUQJA8PrkvJ/7Enqmwk2sM14soA==", "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" + "buffer-equal": "0.0.1", + "mime": "^1.3.4", + "parse-bmfont-ascii": "^1.0.3", + "parse-bmfont-binary": "^1.0.5", + "parse-bmfont-xml": "^1.1.4", + "phin": "^2.9.1", + "xhr": "^2.0.1", + "xtend": "^4.0.0" } }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "node_modules/loader-runner": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", + "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", "engines": { - "node": ">=8" + "node": ">=6.11.5" } }, - "node_modules/shell-quote": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.2.tgz", - "integrity": "sha512-mRz/m/JVscCrkMyPqHc/bczi3OQHkLTqXHEFu0zDhK/qfv3UcOA4SVmRCLmos4bhjr9ekVQubj/R7waKapmiQg==" - }, - "node_modules/shelljs": { - "version": "0.8.4", - "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.4.tgz", - "integrity": "sha512-7gk3UZ9kOfPLIAbslLzyWeGiEqx9e3rxwZM0KE6EL8GlGwjym9Mrlx5/p33bWTu9YG6vcS4MBxYZDHYr5lr8BQ==", + "node_modules/loader-utils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.2.tgz", + "integrity": "sha512-TM57VeHptv569d/GKh6TAYdzKblwDNiumOdkFnejjD0XwTH87K90w3O7AiJRqdQoXygvi1VQTJTLGhJl7WqA7A==", "dependencies": { - "glob": "^7.0.0", - "interpret": "^1.0.0", - "rechoir": "^0.6.2" - }, - "bin": { - "shjs": "bin/shjs" + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" }, "engines": { - "node": ">=4" + "node": ">=8.9.0" } }, - "node_modules/should": { - "version": "13.2.3", - "resolved": "https://registry.npmjs.org/should/-/should-13.2.3.tgz", - "integrity": "sha512-ggLesLtu2xp+ZxI+ysJTmNjh2U0TsC+rQ/pfED9bUZZ4DKefP27D+7YJVVTvKsmjLpIi9jAa7itwDGkDDmt1GQ==", + "node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "dependencies": { - "should-equal": "^2.0.0", - "should-format": "^3.0.3", - "should-type": "^1.4.0", - "should-type-adaptors": "^1.0.1", - "should-util": "^1.0.0" + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" } }, - "node_modules/should-equal": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/should-equal/-/should-equal-2.0.0.tgz", - "integrity": "sha512-ZP36TMrK9euEuWQYBig9W55WPC7uo37qzAEmbjHz4gfyuXrEUgF8cUvQVO+w+d3OMfPvSRQJ22lSm8MQJ43LTA==", - "dependencies": { - "should-type": "^1.4.0" - } + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, - "node_modules/should-format": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/should-format/-/should-format-3.0.3.tgz", - "integrity": "sha1-m/yPdPo5IFxT04w01xcwPidxJPE=", - "dependencies": { - "should-type": "^1.3.0", - "should-type-adaptors": "^1.0.1" - } + "node_modules/lodash.assignin": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.assignin/-/lodash.assignin-4.2.0.tgz", + "integrity": "sha1-uo31+4QesKPoBEIysOJjqNxqKKI=" }, - "node_modules/should-type": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/should-type/-/should-type-1.4.0.tgz", - "integrity": "sha1-B1bYzoRt/QmEOmlHcZ36DUz/XPM=" + "node_modules/lodash.bind": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/lodash.bind/-/lodash.bind-4.2.1.tgz", + "integrity": "sha1-euMBfpOWIqwxt9fX3LGzTbFpDTU=" }, - "node_modules/should-type-adaptors": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/should-type-adaptors/-/should-type-adaptors-1.1.0.tgz", - "integrity": "sha512-JA4hdoLnN+kebEp2Vs8eBe9g7uy0zbRo+RMcU0EsNy+R+k049Ki+N5tT5Jagst2g7EAja+euFuoXFCa8vIklfA==", - "dependencies": { - "should-type": "^1.3.0", - "should-util": "^1.0.0" - } + "node_modules/lodash.curry": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.curry/-/lodash.curry-4.1.1.tgz", + "integrity": "sha1-JI42By7ekGUB11lmIAqG2riyMXA=" }, - "node_modules/should-util": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/should-util/-/should-util-1.0.1.tgz", - "integrity": "sha512-oXF8tfxx5cDk8r2kYqlkUJzZpDBqVY/II2WhvU0n9Y3XYvAYRmeaf1PvvIvTgPnv4KJ+ES5M0PyDq5Jp+Ygy2g==" + "node_modules/lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=" }, - "node_modules/side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", - "dependencies": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } + "node_modules/lodash.defaults": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", + "integrity": "sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw=" }, - "node_modules/signal-exit": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.5.tgz", - "integrity": "sha512-KWcOiKeQj6ZyXx7zq4YxSMgHRlod4czeBQZrPb8OKcohcqAXShm7E20kEMle9WBt26hFcAf0qLOcp5zmY7kOqQ==" + "node_modules/lodash.filter": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.filter/-/lodash.filter-4.6.0.tgz", + "integrity": "sha1-ZosdSYFgOuHMWm+nYBQ+SAtMSs4=" }, - "node_modules/simple-concat": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", - "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] + "node_modules/lodash.flatten": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", + "integrity": "sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=" }, - "node_modules/simple-get": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-3.1.0.tgz", - "integrity": "sha512-bCR6cP+aTdScaQCnQKbPKtJOKDp/hj9EDLJo3Nw4y1QksqaovlW/bnptB6/c1e+qmNIDHRK+oXFDdEqBT8WzUA==", - "dependencies": { - "decompress-response": "^4.2.0", - "once": "^1.3.1", - "simple-concat": "^1.0.0" - } + "node_modules/lodash.flow": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/lodash.flow/-/lodash.flow-3.5.0.tgz", + "integrity": "sha1-h79AKSuM+D5OjOGjrkIJ4gBxZ1o=" }, - "node_modules/simple-get/node_modules/decompress-response": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-4.2.1.tgz", - "integrity": "sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw==", + "node_modules/lodash.foreach": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.foreach/-/lodash.foreach-4.5.0.tgz", + "integrity": "sha1-Gmo16s5AEoDH8G3d7DUWWrJ+PlM=" + }, + "node_modules/lodash.isequal": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", + "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA=" + }, + "node_modules/lodash.map": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.map/-/lodash.map-4.6.0.tgz", + "integrity": "sha1-dx7Hg540c9nEzeKLGTlMNWL09tM=" + }, + "node_modules/lodash.memoize": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", + "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=" + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==" + }, + "node_modules/lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==", + "dev": true + }, + "node_modules/lodash.pick": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.pick/-/lodash.pick-4.4.0.tgz", + "integrity": "sha1-UvBWEP/53tQiYRRB7R/BI6AwAbM=" + }, + "node_modules/lodash.reduce": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.reduce/-/lodash.reduce-4.6.0.tgz", + "integrity": "sha1-8atrg5KZrUj3hKu/R2WW8DuRTTs=" + }, + "node_modules/lodash.reject": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.reject/-/lodash.reject-4.6.0.tgz", + "integrity": "sha1-gNZJLcFHCGS79YNTO2UfQqn1JBU=" + }, + "node_modules/lodash.some": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.some/-/lodash.some-4.6.0.tgz", + "integrity": "sha1-G7nzFO9ri63tE7VJFpsqlF62jk0=" + }, + "node_modules/lodash.sortby": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", + "integrity": "sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==" + }, + "node_modules/lodash.uniq": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", + "integrity": "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=" + }, + "node_modules/log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "dev": true, "dependencies": { - "mimic-response": "^2.0.0" + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" }, "engines": { - "node": ">=8" - } - }, - "node_modules/simple-get/node_modules/mimic-response": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-2.1.0.tgz", - "integrity": "sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==", - "engines": { - "node": ">=8" + "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/simple-html-tokenizer": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/simple-html-tokenizer/-/simple-html-tokenizer-0.1.1.tgz", - "integrity": "sha1-BcLuxXn//+FFoDCsJs/qYbmA+r4=", - "dev": true - }, - "node_modules/simple-swizzle": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", - "integrity": "sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=", - "dependencies": { - "is-arrayish": "^0.3.1" - } - }, - "node_modules/simple-swizzle/node_modules/is-arrayish": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", - "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==" - }, - "node_modules/sirv": { - "version": "1.0.17", - "resolved": "https://registry.npmjs.org/sirv/-/sirv-1.0.17.tgz", - "integrity": "sha512-qx9go5yraB7ekT7bCMqUHJ5jEaOC/GXBxUWv+jeWnb7WzHUFdcQPGWk7YmAwFBaQBrogpuSqd/azbC2lZRqqmw==", + "node_modules/log-symbols/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, "dependencies": { - "@polka/url": "^1.0.0-next.20", - "mime": "^2.3.1", - "totalist": "^1.0.0" + "color-convert": "^2.0.1" }, "engines": { - "node": ">= 10" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/sirv/node_modules/mime": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.5.2.tgz", - "integrity": "sha512-tqkh47FzKeCPD2PUiPB6pkbMzsCasjxAfC62/Wap5qrUWcb+sFasXUC5I3gYM5iBM8v/Qpn4UK0x+j0iHyFPDg==", - "bin": { - "mime": "cli.js" + "node_modules/log-symbols/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">=4.0.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/sisteransi": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", - "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==" - }, - "node_modules/sitemap": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/sitemap/-/sitemap-7.0.0.tgz", - "integrity": "sha512-Ud0jrRQO2k7fEtPAM+cQkBKoMvxQyPKNXKDLn8tRVHxRCsdDQ2JZvw+aZ5IRYYQVAV9iGxEar6boTwZzev+x3g==", + "node_modules/log-symbols/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, "dependencies": { - "@types/node": "^15.0.1", - "@types/sax": "^1.2.1", - "arg": "^5.0.0", - "sax": "^1.2.4" - }, - "bin": { - "sitemap": "dist/cli.js" + "color-name": "~1.1.4" }, "engines": { - "node": ">=12.0.0", - "npm": ">=5.6.0" + "node": ">=7.0.0" } }, - "node_modules/sitemap/node_modules/@types/node": { - "version": "15.14.9", - "resolved": "https://registry.npmjs.org/@types/node/-/node-15.14.9.tgz", - "integrity": "sha512-qjd88DrCxupx/kJD5yQgZdcYKZKSIGBVDIBE1/LTGcNm3d2Np/jxojkdePDdfnBHJc5W7vSMpbJ1aB7p/Py69A==" + "node_modules/log-symbols/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true }, - "node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "node_modules/log-symbols/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, "engines": { "node": ">=8" } }, - "node_modules/slugify": { - "version": "1.4.7", - "resolved": "https://registry.npmjs.org/slugify/-/slugify-1.4.7.tgz", - "integrity": "sha512-tf+h5W1IrjNm/9rKKj0JU2MDMruiopx0jjVA5zCdBtcGjfp0+c5rHw/zADLC3IeKlGHtVbHtpfzvYA0OYT+HKg==", - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/snapdragon": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", - "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", + "node_modules/log-symbols/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, "dependencies": { - "base": "^0.11.1", - "debug": "^2.2.0", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "map-cache": "^0.2.2", - "source-map": "^0.5.6", - "source-map-resolve": "^0.5.0", - "use": "^3.1.0" + "has-flag": "^4.0.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, - "node_modules/snapdragon-node": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", - "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", + "node_modules/log-update": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-4.0.0.tgz", + "integrity": "sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==", + "dev": true, "dependencies": { - "define-property": "^1.0.0", - "isobject": "^3.0.0", - "snapdragon-util": "^3.0.1" + "ansi-escapes": "^4.3.0", + "cli-cursor": "^3.1.0", + "slice-ansi": "^4.0.0", + "wrap-ansi": "^6.2.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/snapdragon-node/node_modules/define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "node_modules/log-update/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, "dependencies": { - "is-descriptor": "^1.0.0" + "color-convert": "^2.0.1" }, "engines": { - "node": ">=0.10.0" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/snapdragon-node/node_modules/is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "node_modules/log-update/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, "dependencies": { - "kind-of": "^6.0.0" + "color-name": "~1.1.4" }, "engines": { - "node": ">=0.10.0" + "node": ">=7.0.0" } }, - "node_modules/snapdragon-node/node_modules/is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "node_modules/log-update/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/log-update/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/log-update/node_modules/slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", + "dev": true, "dependencies": { - "kind-of": "^6.0.0" + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" } }, - "node_modules/snapdragon-node/node_modules/is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "node_modules/log-update/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, "dependencies": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" }, "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, - "node_modules/snapdragon-util": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", - "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", + "node_modules/log-update/node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dev": true, "dependencies": { - "kind-of": "^3.2.0" + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, - "node_modules/snapdragon-util/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/snapdragon/node_modules/define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", "dependencies": { - "is-descriptor": "^0.1.0" + "js-tokens": "^3.0.0 || ^4.0.0" }, - "engines": { - "node": ">=0.10.0" + "bin": { + "loose-envify": "cli.js" } }, - "node_modules/snapdragon/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - }, - "node_modules/sockjs": { - "version": "0.3.21", - "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.21.tgz", - "integrity": "sha512-DhbPFGpxjc6Z3I+uX07Id5ZO2XwYsWOrYjaSeieES78cq+JaJvVe5q/m1uvjIQhXinhIeCFRH6JgXe+mvVMyXw==", + "node_modules/lower-case": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", + "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", "dependencies": { - "faye-websocket": "^0.11.3", - "uuid": "^3.4.0", - "websocket-driver": "^0.7.4" + "tslib": "^2.0.3" } }, - "node_modules/sockjs-client": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/sockjs-client/-/sockjs-client-1.5.2.tgz", - "integrity": "sha512-ZzRxPBISQE7RpzlH4tKJMQbHM9pabHluk0WBaxAQ+wm/UieeBVBou0p4wVnSQGN9QmpAZygQ0cDIypWuqOFmFQ==", - "dependencies": { - "debug": "^3.2.6", - "eventsource": "^1.0.7", - "faye-websocket": "^0.11.3", - "inherits": "^2.0.4", - "json3": "^3.3.3", - "url-parse": "^1.5.3" + "node_modules/lowercase-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", + "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", + "engines": { + "node": ">=0.10.0" } }, - "node_modules/sockjs-client/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/sort-css-media-queries": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/sort-css-media-queries/-/sort-css-media-queries-2.0.4.tgz", - "integrity": "sha512-PAIsEK/XupCQwitjv7XxoMvYhT7EAfyzI3hsy/MyDgTvc+Ft55ctdkctJLOy6cQejaIC+zjpUL4djFVm2ivOOw==", + "yallist": "^4.0.0" + }, "engines": { - "node": ">= 6.3.0" + "node": ">=10" } }, - "node_modules/source-list-map": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz", - "integrity": "sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==" + "node_modules/lunr": { + "version": "2.3.9", + "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz", + "integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==" }, - "node_modules/source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "engines": { - "node": ">=0.10.0" + "node_modules/lz-string": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.4.4.tgz", + "integrity": "sha512-0ckx7ZHRPqb0oUm8zNr+90mtf9DQB60H1wMCjBtfi62Kl3a7JbHob6gA2bC+xRvZoOL+1hzUK8jeuEIQE8svEQ==", + "dev": true, + "bin": { + "lz-string": "bin/bin.js" } }, - "node_modules/source-map-js": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-0.6.2.tgz", - "integrity": "sha512-/3GptzWzu0+0MBQFrDKzw/DvvMTUORvgY6k6jd/VS6iCR4RDTKWH6v6WPwQoUO8667uQEf9Oe38DxAYWY5F/Ug==", + "node_modules/make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dependencies": { + "semver": "^6.0.0" + }, "engines": { - "node": ">=0.10.0" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/source-map-resolve": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", - "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", - "dependencies": { - "atob": "^2.1.2", - "decode-uri-component": "^0.2.0", - "resolve-url": "^0.2.1", - "source-map-url": "^0.4.0", - "urix": "^0.1.0" + "node_modules/make-dir/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "bin": { + "semver": "bin/semver.js" } }, - "node_modules/source-map-support": { - "version": "0.5.20", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.20.tgz", - "integrity": "sha512-n1lZZ8Ve4ksRqizaBQgxXDgKwttHDhyfQjA6YZZn8+AroHbsIz+JjwxQDxbp+7y5OYCI8t1Yk7etjD9CRd2hIw==", + "node_modules/makeerror": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", + "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", + "dev": true, "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "node_modules/source-map-support/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "engines": { - "node": ">=0.10.0" + "tmpl": "1.0.5" } }, - "node_modules/source-map-url": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.1.tgz", - "integrity": "sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==" + "node_modules/mark.js": { + "version": "8.11.1", + "resolved": "https://registry.npmjs.org/mark.js/-/mark.js-8.11.1.tgz", + "integrity": "sha1-GA8fnr74sOY45BZq1S24eb6y/8U=" }, - "node_modules/space-separated-tokens": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-1.1.5.tgz", - "integrity": "sha512-q/JSVd1Lptzhf5bkYm4ob4iWPjx0KiRe3sRFBNrVqbJkFaBm5vbbowy1mymoPNLRa52+oadOhJ+K49wsSeSjTA==", + "node_modules/markdown-escapes": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/markdown-escapes/-/markdown-escapes-1.0.4.tgz", + "integrity": "sha512-8z4efJYk43E0upd0NbVXwgSTQs6cT3T06etieCMEg7dRbzCbxUCK/GHlX8mhHRDcp+OLlHkPKsvqQTCvsRl2cg==", "funding": { "type": "github", "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/spdy": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz", - "integrity": "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==", - "dependencies": { - "debug": "^4.1.0", - "handle-thing": "^2.0.0", - "http-deceiver": "^1.2.7", - "select-hose": "^2.0.0", - "spdy-transport": "^3.0.0" + "node_modules/marked": { + "version": "4.0.15", + "resolved": "https://registry.npmjs.org/marked/-/marked-4.0.15.tgz", + "integrity": "sha512-esX5lPdTfG4p8LDkv+obbRCyOKzB+820ZZyMOXJZygZBHrH9b3xXR64X4kT3sPe9Nx8qQXbmcz6kFSMt4Nfk6Q==", + "bin": { + "marked": "bin/marked.js" }, "engines": { - "node": ">=6.0.0" + "node": ">= 12" } }, - "node_modules/spdy-transport": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz", - "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==", + "node_modules/md5.js": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", + "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", "dependencies": { - "debug": "^4.1.0", - "detect-node": "^2.0.4", - "hpack.js": "^2.1.6", - "obuf": "^1.1.2", - "readable-stream": "^3.0.6", - "wbuf": "^1.7.3" + "hash-base": "^3.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" } }, - "node_modules/split-string": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", - "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", + "node_modules/mdast-squeeze-paragraphs": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mdast-squeeze-paragraphs/-/mdast-squeeze-paragraphs-4.0.0.tgz", + "integrity": "sha512-zxdPn69hkQ1rm4J+2Cs2j6wDEv7O17TfXTJ33tl/+JPIoEmtV9t2ZzBM5LPHE8QlHsmVD8t3vPKCyY3oH+H8MQ==", "dependencies": { - "extend-shallow": "^3.0.0" + "unist-util-remove": "^2.0.0" }, - "engines": { - "node": ">=0.10.0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/split-string/node_modules/extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "node_modules/mdast-util-definitions": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-definitions/-/mdast-util-definitions-4.0.0.tgz", + "integrity": "sha512-k8AJ6aNnUkB7IE+5azR9h81O5EQ/cTDXtWdMq9Kk5KcEW/8ritU5CeLg/9HhOC++nALHBlaogJ5jz0Ybk3kPMQ==", "dependencies": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" + "unist-util-visit": "^2.0.0" }, - "engines": { - "node": ">=0.10.0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/split-string/node_modules/is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "node_modules/mdast-util-to-hast": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-10.0.1.tgz", + "integrity": "sha512-BW3LM9SEMnjf4HXXVApZMt8gLQWVNXc3jryK0nJu/rOXPOnlkUjmdkDlmxMirpbU9ILncGFIwLH/ubnWBbcdgA==", "dependencies": { - "is-plain-object": "^2.0.4" + "@types/mdast": "^3.0.0", + "@types/unist": "^2.0.0", + "mdast-util-definitions": "^4.0.0", + "mdurl": "^1.0.0", + "unist-builder": "^2.0.0", + "unist-util-generated": "^1.0.0", + "unist-util-position": "^3.0.0", + "unist-util-visit": "^2.0.0" }, - "engines": { - "node": ">=0.10.0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" - }, - "node_modules/stable": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz", - "integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==" - }, - "node_modules/state-toggle": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/state-toggle/-/state-toggle-1.0.3.tgz", - "integrity": "sha512-d/5Z4/2iiCnHw6Xzghyhb+GcmF89bxwgXG60wjIiZaxnymbyOmI8Hk4VqHXiVVp6u2ysaskFfXg3ekCj4WNftQ==", + "node_modules/mdast-util-to-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-2.0.0.tgz", + "integrity": "sha512-AW4DRS3QbBayY/jJmD8437V1Gombjf8RSOUCMFBuo5iHi58AGEgVCKQ+ezHkZZDpAQS75hcBMpLqjpJTjtUL7w==", "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/static-extend": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", - "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", - "dependencies": { - "define-property": "^0.2.5", - "object-copy": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } + "node_modules/mdn-data": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.4.tgz", + "integrity": "sha512-iV3XNKw06j5Q7mi6h+9vbx23Tv7JkjEVgKHW4pimwyDGWm0OIQntJJ+u1C6mg6mK1EaTv42XQ7w76yuzH7M2cA==" }, - "node_modules/static-extend/node_modules/define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dependencies": { - "is-descriptor": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } + "node_modules/mdurl": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", + "integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=" }, - "node_modules/statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", "engines": { "node": ">= 0.6" } }, - "node_modules/std-env": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/std-env/-/std-env-2.3.1.tgz", - "integrity": "sha512-eOsoKTWnr6C8aWrqJJ2KAReXoa7Vn5Ywyw6uCXgA/xDhxPoaIsBa5aNJmISY04dLwXPBnDHW4diGM7Sn5K4R/g==", + "node_modules/memfs": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.4.1.tgz", + "integrity": "sha512-1c9VPVvW5P7I85c35zAdEr1TD5+F11IToIHIlrVIcflfnzPkJa0ZoYEoEdYDP8KgPFoSZ/opDrUsAoZWym3mtw==", "dependencies": { - "ci-info": "^3.1.1" + "fs-monkey": "1.0.3" + }, + "engines": { + "node": ">= 4.0.0" } }, - "node_modules/stickyfill": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/stickyfill/-/stickyfill-1.1.1.tgz", - "integrity": "sha1-OUE/7p0CXHSn5ZzuyyN4TMDxfwI=" - }, - "node_modules/stream-browserify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-3.0.0.tgz", - "integrity": "sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA==", - "dependencies": { - "inherits": "~2.0.4", - "readable-stream": "^3.5.0" - } + "node_modules/merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" }, - "node_modules/stream-http": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-3.2.0.tgz", - "integrity": "sha512-Oq1bLqisTyK3TSCXpPbT4sdeYNdmyZJv1LxpEm2vu1ZhK89kSE5YXwZc3cWk0MagGaKriBh9mCFbVGtO+vY29A==", - "dependencies": { - "builtin-status-codes": "^3.0.0", - "inherits": "^2.0.4", - "readable-stream": "^3.6.0", - "xtend": "^4.0.2" - } + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==" }, - "node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dependencies": { - "safe-buffer": "~5.2.0" + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "engines": { + "node": ">= 8" } }, - "node_modules/string_decoder/node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", "engines": { - "node": ">=8" + "node": ">= 0.6" } }, - "node_modules/string.prototype.trimend": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz", - "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==", + "node_modules/micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" + "braces": "^3.0.2", + "picomatch": "^2.3.1" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": ">=8.6" } }, - "node_modules/string.prototype.trimstart": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz", - "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==", + "node_modules/miller-rabin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", + "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" + "bn.js": "^4.0.0", + "brorand": "^1.0.1" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "bin": { + "miller-rabin": "bin/miller-rabin" } }, - "node_modules/stringify-object": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/stringify-object/-/stringify-object-3.3.0.tgz", - "integrity": "sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw==", - "dependencies": { - "get-own-enumerable-property-symbols": "^3.0.0", - "is-obj": "^1.0.1", - "is-regexp": "^1.0.0" + "node_modules/miller-rabin/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "bin": { + "mime": "cli.js" }, "engines": { "node": ">=4" } }, - "node_modules/stringify-object/node_modules/is-obj": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", - "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=", + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", "engines": { - "node": ">=0.10.0" + "node": ">= 0.6" } }, - "node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", "dependencies": { - "ansi-regex": "^5.0.1" + "mime-db": "1.52.0" }, "engines": { - "node": ">=8" + "node": ">= 0.6" } }, - "node_modules/strip-bom-string": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-bom-string/-/strip-bom-string-1.0.0.tgz", - "integrity": "sha1-5SEekiQ2n7uB1jOi8ABE3IztrZI=", + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", "engines": { - "node": ">=0.10.0" + "node": ">=6" } }, - "node_modules/strip-eof": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", - "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", + "node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", "engines": { - "node": ">=0.10.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "engines": { - "node": ">=6" + "node_modules/min-document": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/min-document/-/min-document-2.19.0.tgz", + "integrity": "sha1-e9KC4/WELtKVu3SM3Z8f+iyCRoU=", + "dependencies": { + "dom-walk": "^0.1.0" } }, - "node_modules/strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "node_modules/min-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", + "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", + "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">=4" } }, - "node_modules/style-loader": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-1.3.0.tgz", - "integrity": "sha512-V7TCORko8rs9rIqkSrlMfkqA63DfoGBBJmK1kKGCcSi+BWb4cqz0SRsnp4l6rU5iwOEd0/2ePv68SV22VXon4Q==", - "dev": true, + "node_modules/mini-create-react-context": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/mini-create-react-context/-/mini-create-react-context-0.4.1.tgz", + "integrity": "sha512-YWCYEmd5CQeHGSAKrYvXgmzzkrvssZcuuQDDeqkT+PziKGMgE+0MCCtcKbROzocGBG1meBLl2FotlRwf4gAzbQ==", "dependencies": { - "loader-utils": "^2.0.0", - "schema-utils": "^2.7.0" - }, - "engines": { - "node": ">= 8.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" + "@babel/runtime": "^7.12.1", + "tiny-warning": "^1.0.3" }, "peerDependencies": { - "webpack": "^4.0.0 || ^5.0.0" + "prop-types": "^15.0.0", + "react": "^0.14.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, - "node_modules/style-loader/node_modules/schema-utils": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz", - "integrity": "sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==", - "dev": true, + "node_modules/mini-css-extract-plugin": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.6.0.tgz", + "integrity": "sha512-ndG8nxCEnAemsg4FSgS+yNyHKgkTB4nPKqCOgh65j3/30qqC5RaSQQXMm++Y6sb6E1zRSxPkztj9fqxhS1Eo6w==", "dependencies": { - "@types/json-schema": "^7.0.5", - "ajv": "^6.12.4", - "ajv-keywords": "^3.5.2" + "schema-utils": "^4.0.0" }, "engines": { - "node": ">= 8.9.0" + "node": ">= 12.13.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" } }, - "node_modules/style-to-object": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-0.3.0.tgz", - "integrity": "sha512-CzFnRRXhzWIdItT3OmF8SQfWyahHhjq3HwcMNCNLn+N7klOOqPjMeG/4JSu77D7ypZdGvSzvkrbyeTMizz2VrA==", + "node_modules/mini-css-extract-plugin/node_modules/ajv": { + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz", + "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==", "dependencies": { - "inline-style-parser": "0.1.1" + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/styled-components": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/styled-components/-/styled-components-5.3.1.tgz", - "integrity": "sha512-JThv2JRzyH0NOIURrk9iskdxMSAAtCfj/b2Sf1WJaCUsloQkblepy1jaCLX/bYE+mhYo3unmwVSI9I5d9ncSiQ==", + "node_modules/mini-css-extract-plugin/node_modules/ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", "dependencies": { - "@babel/helper-module-imports": "^7.0.0", - "@babel/traverse": "^7.4.5", - "@emotion/is-prop-valid": "^0.8.8", - "@emotion/stylis": "^0.8.4", - "@emotion/unitless": "^0.7.4", - "babel-plugin-styled-components": ">= 1.12.0", - "css-to-react-native": "^3.0.0", - "hoist-non-react-statics": "^3.0.0", - "shallowequal": "^1.1.0", - "supports-color": "^5.5.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/styled-components" + "fast-deep-equal": "^3.1.3" }, "peerDependencies": { - "react": ">= 16.8.0", - "react-dom": ">= 16.8.0", - "react-is": ">= 16.8.0" + "ajv": "^8.8.2" } }, - "node_modules/stylehacks": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-5.0.1.tgz", - "integrity": "sha512-Es0rVnHIqbWzveU1b24kbw92HsebBepxfcqe5iix7t9j0PQqhs0IxXVXv0pY2Bxa08CgMkzD6OWql7kbGOuEdA==", + "node_modules/mini-css-extract-plugin/node_modules/schema-utils": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.0.0.tgz", + "integrity": "sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg==", "dependencies": { - "browserslist": "^4.16.0", - "postcss-selector-parser": "^6.0.4" + "@types/json-schema": "^7.0.9", + "ajv": "^8.8.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.0.0" }, "engines": { - "node": "^10 || ^12 || >=14.0" + "node": ">= 12.13.0" }, - "peerDependencies": { - "postcss": "^8.2.15" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" } }, - "node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/svg-inline-loader": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/svg-inline-loader/-/svg-inline-loader-0.8.2.tgz", - "integrity": "sha512-kbrcEh5n5JkypaSC152eGfGcnT4lkR0eSfvefaUJkLqgGjRQJyKDvvEE/CCv5aTSdfXuc+N98w16iAojhShI3g==", - "dev": true, - "dependencies": { - "loader-utils": "^1.1.0", - "object-assign": "^4.0.1", - "simple-html-tokenizer": "^0.1.1" - } + "node_modules/minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" }, - "node_modules/svg-inline-loader/node_modules/json5": { + "node_modules/minimalistic-crypto-utils": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", - "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", - "dev": true, - "dependencies": { - "minimist": "^1.2.0" - }, - "bin": { - "json5": "lib/cli.js" - } + "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=" }, - "node_modules/svg-inline-loader/node_modules/loader-utils": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", - "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", - "dev": true, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dependencies": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^1.0.1" + "brace-expansion": "^1.1.7" }, "engines": { - "node": ">=4.0.0" + "node": "*" } }, - "node_modules/svg-parser": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/svg-parser/-/svg-parser-2.0.4.tgz", - "integrity": "sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ==" + "node_modules/minimist": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", + "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" }, - "node_modules/svgo": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/svgo/-/svgo-2.7.0.tgz", - "integrity": "sha512-aDLsGkre4fTDCWvolyW+fs8ZJFABpzLXbtdK1y71CKnHzAnpDxKXPj2mNKj+pyOXUCzFHzuxRJ94XOFygOWV3w==", + "node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", "dependencies": { - "@trysound/sax": "0.2.0", - "commander": "^7.2.0", - "css-select": "^4.1.3", - "css-tree": "^1.1.3", - "csso": "^4.2.0", - "nanocolors": "^0.1.12", - "stable": "^0.1.8" + "minimist": "^1.2.6" }, "bin": { - "svgo": "bin/svgo" - }, - "engines": { - "node": ">=10.13.0" + "mkdirp": "bin/cmd.js" } }, - "node_modules/svgo/node_modules/commander": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", - "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", - "engines": { - "node": ">= 10" + "node_modules/mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" + }, + "node_modules/mobx": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/mobx/-/mobx-6.5.0.tgz", + "integrity": "sha512-pHZ/cySF00FVENDWIDzJyoObFahK6Eg4d0papqm6d7yMkxWTZ/S/csqJX1A3PsYy4t5k3z2QnlwuCfMW5lSEwA==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mobx" } }, - "node_modules/swagger2openapi": { - "version": "7.0.8", - "resolved": "https://registry.npmjs.org/swagger2openapi/-/swagger2openapi-7.0.8.tgz", - "integrity": "sha512-upi/0ZGkYgEcLeGieoz8gT74oWHA0E7JivX7aN9mAf+Tc7BQoRBvnIGHoPDw+f9TXTW4s6kGYCZJtauP6OYp7g==", + "node_modules/mobx-react": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/mobx-react/-/mobx-react-7.3.0.tgz", + "integrity": "sha512-RGEcwZokopqyJE5JPwXKB9FWMSqFM9NJVO2QPI+z6laJTJeBHqvPicjnKgY5mvihxTeXB1+72TnooqUePeGV1g==", "dependencies": { - "call-me-maybe": "^1.0.1", - "node-fetch": "^2.6.1", - "node-fetch-h2": "^2.3.0", - "node-readfiles": "^0.2.0", - "oas-kit-common": "^1.0.8", - "oas-resolver": "^2.5.6", - "oas-schema-walker": "^1.1.5", - "oas-validator": "^5.0.8", - "reftools": "^1.1.9", - "yaml": "^1.10.0", - "yargs": "^17.0.1" - }, - "bin": { - "boast": "boast.js", - "oas-validate": "oas-validate.js", - "swagger2openapi": "swagger2openapi.js" + "mobx-react-lite": "^3.3.0" }, "funding": { - "url": "https://github.com/Mermade/oas-kit?sponsor=1" + "type": "opencollective", + "url": "https://opencollective.com/mobx" + }, + "peerDependencies": { + "mobx": "^6.1.0", + "react": "^16.8.0 || ^17" + }, + "peerDependenciesMeta": { + "react-dom": { + "optional": true + }, + "react-native": { + "optional": true + } } }, - "node_modules/swagger2openapi/node_modules/cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" + "node_modules/mobx-react-lite": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/mobx-react-lite/-/mobx-react-lite-3.3.0.tgz", + "integrity": "sha512-U/kMSFtV/bNVgY01FuiGWpRkaQVHozBq5CEBZltFvPt4FcV111hEWkgwqVg9GPPZSEuEdV438PEz8mk8mKpYlA==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mobx" + }, + "peerDependencies": { + "mobx": "^6.1.0", + "react": "^16.8.0 || ^17" + }, + "peerDependenciesMeta": { + "react-dom": { + "optional": true + }, + "react-native": { + "optional": true + } } }, - "node_modules/swagger2openapi/node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "node_modules/mrmime": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-1.0.0.tgz", + "integrity": "sha512-a70zx7zFfVO7XpnQ2IX1Myh9yY4UYvfld/dikWRnsXxbyvMcfz+u6UfgNAtH+k2QqtJuzVpv6eLTx1G2+WKZbQ==", "engines": { "node": ">=10" } }, - "node_modules/swagger2openapi/node_modules/yargs": { - "version": "17.2.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.2.1.tgz", - "integrity": "sha512-XfR8du6ua4K6uLGm5S6fA+FIJom/MdJcFNVY8geLlp2v8GYbOXD4EB1tPNZsRn4vBzKGMgb5DRZMeWuFc2GO8Q==", + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/multicast-dns": { + "version": "7.2.4", + "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-7.2.4.tgz", + "integrity": "sha512-XkCYOU+rr2Ft3LI6w4ye51M3VK31qJXFIxu0XLw169PtKG0Zx47OrXeVW/GCYOfpC9s1yyyf1S+L8/4LY0J9Zw==", "dependencies": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" + "dns-packet": "^5.2.2", + "thunky": "^1.0.2" }, - "engines": { - "node": ">=12" + "bin": { + "multicast-dns": "cli.js" } }, - "node_modules/swagger2openapi/node_modules/yargs-parser": { - "version": "20.2.9", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "node_modules/nanoid": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.3.tgz", + "integrity": "sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, "engines": { - "node": ">=10" + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, - "node_modules/tapable": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", - "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "node_modules/napi-build-utils": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", + "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==" + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", "engines": { - "node": ">=6" + "node": ">= 0.6" } }, - "node_modules/tar-fs": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", - "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" + }, + "node_modules/no-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", + "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", "dependencies": { - "chownr": "^1.1.1", - "mkdirp-classic": "^0.5.2", - "pump": "^3.0.0", - "tar-stream": "^2.1.4" + "lower-case": "^2.0.2", + "tslib": "^2.0.3" } }, - "node_modules/tar-stream": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", - "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "node_modules/node-abi": { + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.15.0.tgz", + "integrity": "sha512-Ic6z/j6I9RLm4ov7npo1I48UQr2BEyFCqh6p7S1dhEx9jPO0GPGq/e2Rb7x7DroQrmiVMz/Bw1vJm9sPAl2nxA==", "dependencies": { - "bl": "^4.0.3", - "end-of-stream": "^1.4.1", - "fs-constants": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^3.1.1" + "semver": "^7.3.5" }, "engines": { - "node": ">=6" + "node": ">=10" } }, - "node_modules/terser": { - "version": "5.9.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.9.0.tgz", - "integrity": "sha512-h5hxa23sCdpzcye/7b8YqbE5OwKca/ni0RQz1uRX3tGh8haaGHqcuSqbGRybuAKNdntZ0mDgFNXPJ48xQ2RXKQ==", + "node_modules/node-addon-api": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-4.3.0.tgz", + "integrity": "sha512-73sE9+3UaLYYFmDsFZnqCInzPyh3MqIwZO9cw58yIqAZhONrrabrYyYe3TuIqtIiOuTXVhsGau8hcrhhwSsDIQ==" + }, + "node_modules/node-emoji": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-1.11.0.tgz", + "integrity": "sha512-wo2DpQkQp7Sjm2A0cq+sN7EHKO6Sl0ctXeBdFZrL9T9+UywORbufTcTZxom8YqpLQt/FqNMUkOpkZrJVYSKD3A==", "dependencies": { - "commander": "^2.20.0", - "source-map": "~0.7.2", - "source-map-support": "~0.5.20" - }, - "bin": { - "terser": "bin/terser" - }, - "engines": { - "node": ">=10" + "lodash": "^4.17.21" } }, - "node_modules/terser-webpack-plugin": { - "version": "5.2.4", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.2.4.tgz", - "integrity": "sha512-E2CkNMN+1cho04YpdANyRrn8CyN4yMy+WdFKZIySFZrGXZxJwJP6PMNGGc/Mcr6qygQHUUqRxnAPmi0M9f00XA==", + "node_modules/node-fetch": { + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", + "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", "dependencies": { - "jest-worker": "^27.0.6", - "p-limit": "^3.1.0", - "schema-utils": "^3.1.1", - "serialize-javascript": "^6.0.0", - "source-map": "^0.6.1", - "terser": "^5.7.2" + "whatwg-url": "^5.0.0" }, "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" + "node": "4.x || >=6.0.0" }, "peerDependencies": { - "webpack": "^5.1.0" + "encoding": "^0.1.0" }, "peerDependenciesMeta": { - "@swc/core": { - "optional": true - }, - "esbuild": { - "optional": true - }, - "uglify-js": { + "encoding": { "optional": true } } }, - "node_modules/terser-webpack-plugin/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "node_modules/node-fetch-h2": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/node-fetch-h2/-/node-fetch-h2-2.3.0.tgz", + "integrity": "sha512-ofRW94Ab0T4AOh5Fk8t0h8OBWrmjb0SSB20xh1H8YnPV9EJ+f5AMoYSUQ2zgJ4Iq2HAK0I2l5/Nequ8YzFS3Hg==", + "dependencies": { + "http2-client": "^1.2.5" + }, "engines": { - "node": ">=0.10.0" + "node": "4.x || >=6.0.0" } }, - "node_modules/terser/node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" + "node_modules/node-fetch/node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=" }, - "node_modules/terser/node_modules/source-map": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", - "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", - "engines": { - "node": ">= 8" + "node_modules/node-fetch/node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=" + }, + "node_modules/node-fetch/node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" } }, - "node_modules/text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=" + "node_modules/node-forge": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", + "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", + "engines": { + "node": ">= 6.13.0" + } }, - "node_modules/thunky": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", - "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==" + "node_modules/node-int64": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", + "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", + "dev": true }, - "node_modules/timers-browserify": { - "version": "2.0.12", - "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.12.tgz", - "integrity": "sha512-9phl76Cqm6FhSX9Xe1ZUAMLtm1BLkKj2Qd5ApyWkXzsMRaA7dgr81kf4wJmQf/hAvg8EEyJxDo3du/0KlhPiKQ==", + "node_modules/node-polyfill-webpack-plugin": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/node-polyfill-webpack-plugin/-/node-polyfill-webpack-plugin-1.1.4.tgz", + "integrity": "sha512-Z0XTKj1wRWO8o/Vjobsw5iOJCN+Sua3EZEUc2Ziy9CyVvmHKu6o+t4gUH9GOE0czyPR94LI6ZCV/PpcM8b5yow==", "dependencies": { - "setimmediate": "^1.0.4" + "assert": "^2.0.0", + "browserify-zlib": "^0.2.0", + "buffer": "^6.0.3", + "console-browserify": "^1.2.0", + "constants-browserify": "^1.0.0", + "crypto-browserify": "^3.12.0", + "domain-browser": "^4.19.0", + "events": "^3.3.0", + "filter-obj": "^2.0.2", + "https-browserify": "^1.0.0", + "os-browserify": "^0.3.0", + "path-browserify": "^1.0.1", + "process": "^0.11.10", + "punycode": "^2.1.1", + "querystring-es3": "^0.2.1", + "readable-stream": "^3.6.0", + "stream-browserify": "^3.0.0", + "stream-http": "^3.2.0", + "string_decoder": "^1.3.0", + "timers-browserify": "^2.0.12", + "tty-browserify": "^0.0.1", + "url": "^0.11.0", + "util": "^0.12.4", + "vm-browserify": "^1.1.2" }, "engines": { - "node": ">=0.6.0" + "node": ">=10" + }, + "peerDependencies": { + "webpack": ">=5" } }, - "node_modules/timm": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/timm/-/timm-1.7.1.tgz", - "integrity": "sha512-IjZc9KIotudix8bMaBW6QvMuq64BrJWFs1+4V0lXwWGQZwH+LnX87doAYhem4caOEusRP9/g6jVDQmZ8XOk1nw==" + "node_modules/node-readfiles": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/node-readfiles/-/node-readfiles-0.2.0.tgz", + "integrity": "sha1-271K8SE04uY1wkXvk//Pb2BnOl0=", + "dependencies": { + "es6-promise": "^3.2.1" + } }, - "node_modules/timsort": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/timsort/-/timsort-0.3.0.tgz", - "integrity": "sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q=" + "node_modules/node-releases": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.4.tgz", + "integrity": "sha512-gbMzqQtTtDz/00jQzZ21PQzdI9PyLYqUSvD0p3naOhX4odFji0ZxYdnVwPTxmSwkmxhcFImpozceidSG+AgoPQ==" }, - "node_modules/tiny-invariant": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.1.0.tgz", - "integrity": "sha512-ytxQvrb1cPc9WBEI/HSeYYoGD0kWnGEOR8RY6KomWLBVhqz0RgTwVO9dLrGz7dC+nN9llyI7OKAgRq8Vq4ZBSw==" + "node_modules/node-vibrant": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/node-vibrant/-/node-vibrant-3.1.6.tgz", + "integrity": "sha512-Wlc/hQmBMOu6xon12ZJHS2N3M+I6J8DhrD3Yo6m5175v8sFkVIN+UjhKVRcO+fqvre89ASTpmiFEP3nPO13SwA==", + "dependencies": { + "@jimp/custom": "^0.16.1", + "@jimp/plugin-resize": "^0.16.1", + "@jimp/types": "^0.16.1", + "@types/lodash": "^4.14.53", + "@types/node": "^10.11.7", + "lodash": "^4.17.20", + "url": "^0.11.0" + } }, - "node_modules/tiny-warning": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz", - "integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==" + "node_modules/node-vibrant/node_modules/@types/node": { + "version": "10.17.60", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.60.tgz", + "integrity": "sha512-F0KIgDJfy2nA3zMLmWGKxcH2ZVEtCZXHHdOQs2gSaQ27+lNeEfGxzkIw90aXswATX7AZ33tahPbzy6KAfUreVw==" }, - "node_modules/tinycolor2": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.4.2.tgz", - "integrity": "sha512-vJhccZPs965sV/L2sU4oRQVAos0pQXwsvTLkWYdqJ+a8Q5kPFzJTuOFwy7UniPli44NKQGAglksjvOcpo95aZA==", + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", "engines": { - "node": "*" + "node": ">=0.10.0" } }, - "node_modules/to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "node_modules/normalize-range": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", + "integrity": "sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=", "engines": { - "node": ">=4" + "node": ">=0.10.0" } }, - "node_modules/to-object-path": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", - "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", - "dependencies": { - "kind-of": "^3.0.2" - }, + "node_modules/normalize-url": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", + "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", "engines": { - "node": ">=0.10.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/to-object-path/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", "dependencies": { - "is-buffer": "^1.1.5" + "path-key": "^3.0.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, - "node_modules/to-readable-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz", - "integrity": "sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==", - "engines": { - "node": ">=6" + "node_modules/npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "dependencies": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" } }, - "node_modules/to-regex": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", - "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", + "node_modules/nprogress": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/nprogress/-/nprogress-0.2.0.tgz", + "integrity": "sha1-y480xTIT2JVyP8urkH6UIq28r7E=" + }, + "node_modules/nth-check": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.0.1.tgz", + "integrity": "sha512-it1vE95zF6dTT9lBsYbxvqh0Soy4SPowchj0UBGj/V6cTPnXXtQOPUbhZ6CmGzAD/rW22LQK6E96pcdJXk4A4w==", "dependencies": { - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "regex-not": "^1.0.2", - "safe-regex": "^1.1.0" + "boolbase": "^1.0.0" }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, + "node_modules/number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", "engines": { "node": ">=0.10.0" } }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "node_modules/nwsapi": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.0.tgz", + "integrity": "sha512-h2AatdwYH+JHiZpv7pt/gSX1XoRGb7L/qSIeuqA6GwYoF9w1vP1cw42TO0aI2pNyshRK5893hNSl+1//vHK7hQ==", + "dev": true + }, + "node_modules/oas-kit-common": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/oas-kit-common/-/oas-kit-common-1.0.8.tgz", + "integrity": "sha512-pJTS2+T0oGIwgjGpw7sIRU8RQMcUoKCDWFLdBqKB2BNmGpbBMH2sdqAaOXUg8OzonZHU0L7vfJu1mJFEiYDWOQ==", "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" + "fast-safe-stringify": "^2.0.7" } }, - "node_modules/to-regex/node_modules/extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "node_modules/oas-linter": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/oas-linter/-/oas-linter-3.2.2.tgz", + "integrity": "sha512-KEGjPDVoU5K6swgo9hJVA/qYGlwfbFx+Kg2QB/kd7rzV5N8N5Mg6PlsoCMohVnQmo+pzJap/F610qTodKzecGQ==", "dependencies": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" + "@exodus/schemasafe": "^1.0.0-rc.2", + "should": "^13.2.1", + "yaml": "^1.10.0" }, - "engines": { - "node": ">=0.10.0" + "funding": { + "url": "https://github.com/Mermade/oas-kit?sponsor=1" } }, - "node_modules/to-regex/node_modules/is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "node_modules/oas-resolver": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/oas-resolver/-/oas-resolver-2.5.6.tgz", + "integrity": "sha512-Yx5PWQNZomfEhPPOphFbZKi9W93CocQj18NlD2Pa4GWZzdZpSJvYwoiuurRI7m3SpcChrnO08hkuQDL3FGsVFQ==", "dependencies": { - "is-plain-object": "^2.0.4" + "node-fetch-h2": "^2.3.0", + "oas-kit-common": "^1.0.8", + "reftools": "^1.1.9", + "yaml": "^1.10.0", + "yargs": "^17.0.1" }, - "engines": { - "node": ">=0.10.0" + "bin": { + "resolve": "resolve.js" + }, + "funding": { + "url": "https://github.com/Mermade/oas-kit?sponsor=1" } }, - "node_modules/toidentifier": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", - "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", + "node_modules/oas-resolver/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/oas-resolver/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, "engines": { - "node": ">=0.6" + "node": ">=8" } }, - "node_modules/totalist": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/totalist/-/totalist-1.1.0.tgz", - "integrity": "sha512-gduQwd1rOdDMGxFG1gEvhV88Oirdo2p+KjoYFU7k2g+i7n6AFFbDQ5kMPUsW0pNbfQsB/cwXvT1i4Bue0s9g5g==", + "node_modules/oas-resolver/node_modules/yargs": { + "version": "17.4.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.4.1.tgz", + "integrity": "sha512-WSZD9jgobAg3ZKuCQZSa3g9QOJeCCqLoLAykiWgmXnDo9EPnn4RPf5qVTtzgOx66o6/oqhcA5tHtJXpG8pMt3g==", + "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" + }, "engines": { - "node": ">=6" + "node": ">=12" } }, - "node_modules/trim": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/trim/-/trim-0.0.1.tgz", - "integrity": "sha1-WFhUf2spB1fulczMZm+1AITEYN0=" - }, - "node_modules/trim-trailing-lines": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/trim-trailing-lines/-/trim-trailing-lines-1.1.4.tgz", - "integrity": "sha512-rjUWSqnfTNrjbB9NQWfPMH/xRK1deHeGsHoVfpxJ++XeYXE0d6B1En37AHfw3jtfTU7dzMzZL2jjpe8Qb5gLIQ==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "node_modules/oas-resolver/node_modules/yargs-parser": { + "version": "21.0.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.0.1.tgz", + "integrity": "sha512-9BK1jFpLzJROCI5TzwZL/TU4gqjK5xiHV/RfWLOahrjAko/e4DJkRDZQXfvqAsiZzzYhgAzbgz6lg48jcm4GLg==", + "engines": { + "node": ">=12" } }, - "node_modules/trough": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/trough/-/trough-1.0.5.tgz", - "integrity": "sha512-rvuRbTarPXmMb79SmzEp8aqXNKcK+y0XaB298IXueQ8I2PsrATcPBCSPyK/dDNa2iWOhKlfNnOjdAOTBU/nkFA==", + "node_modules/oas-schema-walker": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/oas-schema-walker/-/oas-schema-walker-1.1.5.tgz", + "integrity": "sha512-2yucenq1a9YPmeNExoUa9Qwrt9RFkjqaMAA1X+U7sbb0AqBeTIdMHky9SQQ6iN94bO5NW0W4TRYXerG+BdAvAQ==", "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "url": "https://github.com/Mermade/oas-kit?sponsor=1" } }, - "node_modules/ts-essentials": { - "version": "2.0.12", - "resolved": "https://registry.npmjs.org/ts-essentials/-/ts-essentials-2.0.12.tgz", - "integrity": "sha512-3IVX4nI6B5cc31/GFFE+i8ey/N2eA0CZDbo6n0yrz0zDX8ZJ8djmU1p+XRz7G3is0F3bB3pu2pAroFdAWQKU3w==" - }, - "node_modules/tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - }, - "node_modules/tty-browserify": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.1.tgz", - "integrity": "sha512-C3TaO7K81YvjCgQH9Q1S3R3P3BtN3RIM8n+OvX4il1K1zgE8ZhI0op7kClgkxtutIE8hQrcrHBXvIheqKUUCxw==" - }, - "node_modules/tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "node_modules/oas-validator": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/oas-validator/-/oas-validator-5.0.8.tgz", + "integrity": "sha512-cu20/HE5N5HKqVygs3dt94eYJfBi0TsZvPVXDhbXQHiEityDN+RROTleefoKRKKJ9dFAF2JBkDHgvWj0sjKGmw==", "dependencies": { - "safe-buffer": "^5.0.1" + "call-me-maybe": "^1.0.1", + "oas-kit-common": "^1.0.8", + "oas-linter": "^3.2.2", + "oas-resolver": "^2.5.6", + "oas-schema-walker": "^1.1.5", + "reftools": "^1.1.9", + "should": "^13.2.1", + "yaml": "^1.10.0" }, - "engines": { - "node": "*" + "funding": { + "url": "https://github.com/Mermade/oas-kit?sponsor=1" } }, - "node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", "engines": { - "node": ">=10" - }, + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.0.tgz", + "integrity": "sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g==", "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "node_modules/object-is": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz", + "integrity": "sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==", "dependencies": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" }, "engines": { - "node": ">= 0.6" - } - }, - "node_modules/typedarray-to-buffer": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", - "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", - "dependencies": { - "is-typedarray": "^1.0.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/ua-parser-js": { - "version": "0.7.28", - "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.28.tgz", - "integrity": "sha512-6Gurc1n//gjp9eQNXjD9O3M/sMwVtN5S8Lv9bvOYBfKfDNiIIhqiyi01vMBO45u4zkDE420w/e0se7Vs+sIg+g==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/ua-parser-js" - }, - { - "type": "paypal", - "url": "https://paypal.me/faisalman" - } - ], + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", "engines": { - "node": "*" + "node": ">= 0.4" } }, - "node_modules/unbox-primitive": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz", - "integrity": "sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==", + "node_modules/object.assign": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", + "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", "dependencies": { - "function-bind": "^1.1.1", - "has-bigints": "^1.0.1", - "has-symbols": "^1.0.2", - "which-boxed-primitive": "^1.0.2" + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "has-symbols": "^1.0.1", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/unherit": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/unherit/-/unherit-1.1.3.tgz", - "integrity": "sha512-Ft16BJcnapDKp0+J/rqFC3Rrk6Y/Ng4nzsC028k2jdDII/rdZ7Wd3pPT/6+vIIxRagwRc9K0IUX0Ra4fKvw+WQ==", + "node_modules/object.getownpropertydescriptors": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.3.tgz", + "integrity": "sha512-VdDoCwvJI4QdC6ndjpqFmoL3/+HxffFBbcJzKi5hwLLqqx3mdbedRpfZDdK0SrOSauj8X4GzBvnDZl4vTN7dOw==", "dependencies": { - "inherits": "^2.0.0", - "xtend": "^4.0.0" + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.1" + }, + "engines": { + "node": ">= 0.8" }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/unicode-canonical-property-names-ecmascript": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", - "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==", + "node_modules/object.values": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.5.tgz", + "integrity": "sha512-QUZRW0ilQ3PnPpbNtgdNV1PDbEqLIiSFB3l+EnGtBQ/8SUTLj1PZwtQHABZtLgwpJZTSZhuGLOGk57Drx2IvYg==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.1" + }, "engines": { - "node": ">=4" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/unicode-match-property-ecmascript": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", - "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", + "node_modules/obuf": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", + "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==" + }, + "node_modules/omggif": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/omggif/-/omggif-1.0.10.tgz", + "integrity": "sha512-LMJTtvgc/nugXj0Vcrrs68Mn2D1r0zf630VNtqtpI1FEO7e+O9FP4gqs9AcnBaSEeoHIPm28u6qgPR0oyEpGSw==" + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", "dependencies": { - "unicode-canonical-property-names-ecmascript": "^2.0.0", - "unicode-property-aliases-ecmascript": "^2.0.0" + "ee-first": "1.1.1" }, "engines": { - "node": ">=4" + "node": ">= 0.8" } }, - "node_modules/unicode-match-property-value-ecmascript": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.0.0.tgz", - "integrity": "sha512-7Yhkc0Ye+t4PNYzOGKedDhXbYIBe1XEQYQxOPyhcXNMJ0WCABqqj6ckydd6pWRZTHV4GuCPKdBAUiMc60tsKVw==", + "node_modules/on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", "engines": { - "node": ">=4" + "node": ">= 0.8" } }, - "node_modules/unicode-property-aliases-ecmascript": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.0.0.tgz", - "integrity": "sha512-5Zfuy9q/DFr4tfO7ZPeVXb1aPoeQSdeFMLpYuFebehDAhbuevLs5yxSZmIFN1tP5F9Wl4IpJrYojg85/zgyZHQ==", - "engines": { - "node": ">=4" + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dependencies": { + "wrappy": "1" } }, - "node_modules/unified": { - "version": "8.4.2", - "resolved": "https://registry.npmjs.org/unified/-/unified-8.4.2.tgz", - "integrity": "sha512-JCrmN13jI4+h9UAyKEoGcDZV+i1E7BLFuG7OsaDvTXI5P0qhHX+vZO/kOhz9jn8HGENDKbwSeB0nVOg4gVStGA==", + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", "dependencies": { - "bail": "^1.0.0", - "extend": "^3.0.0", - "is-plain-obj": "^2.0.0", - "trough": "^1.0.0", - "vfile": "^4.0.0" + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/union-value": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", - "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", + "node_modules/open": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/open/-/open-8.4.0.tgz", + "integrity": "sha512-XgFPPM+B28FtCCgSb9I+s9szOC1vZRSwgWsRUA5ylIxRTgKozqjOCrVOqGsYABPYK5qnfqClxZTFBa8PKt2v6Q==", "dependencies": { - "arr-union": "^3.1.0", - "get-value": "^2.0.6", - "is-extendable": "^0.1.1", - "set-value": "^2.0.1" + "define-lazy-prop": "^2.0.0", + "is-docker": "^2.1.1", + "is-wsl": "^2.2.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/uniqs": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/uniqs/-/uniqs-2.0.0.tgz", - "integrity": "sha1-/+3ks2slKQaW5uFl1KWe25mOawI=" - }, - "node_modules/unique-string": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", - "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==", + "node_modules/openapi-sampler": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/openapi-sampler/-/openapi-sampler-1.2.3.tgz", + "integrity": "sha512-dH2QYXqakorV5dxkP/f1BV3Ku4yNn21YmBsqJunnyrHLw7mnCNZZldftgrEpv/66b1m5oaUAmiJoJN+FqBEkJg==", "dependencies": { - "crypto-random-string": "^2.0.0" - }, - "engines": { - "node": ">=8" + "@types/json-schema": "^7.0.7", + "json-pointer": "0.6.2" } }, - "node_modules/unist-builder": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/unist-builder/-/unist-builder-2.0.3.tgz", - "integrity": "sha512-f98yt5pnlMWlzP539tPc4grGMsFaQQlP/vM396b00jngsiINumNmsY8rkXjfoi1c6QaM8nQ3vaGDuoKWbe/1Uw==", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "node_modules/opener": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz", + "integrity": "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==", + "bin": { + "opener": "bin/opener-bin.js" } }, - "node_modules/unist-util-generated": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/unist-util-generated/-/unist-util-generated-1.1.6.tgz", - "integrity": "sha512-cln2Mm1/CZzN5ttGK7vkoGw+RZ8VcUH6BtGbq98DDtRGquAAOXig1mrBQYelOwMXYS8rK+vZDyyojSjp7JX+Lg==", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "node_modules/optionator": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", + "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", + "dev": true, + "dependencies": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.6", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "word-wrap": "~1.2.3" + }, + "engines": { + "node": ">= 0.8.0" } }, - "node_modules/unist-util-is": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-4.1.0.tgz", - "integrity": "sha512-ZOQSsnce92GrxSqlnEEseX0gi7GH9zTJZ0p9dtu87WRb/37mMPO2Ilx1s/t9vBHrFhbgweUwb+t7cIn5dxPhZg==", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } + "node_modules/os-browserify": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", + "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=" }, - "node_modules/unist-util-position": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-3.1.0.tgz", - "integrity": "sha512-w+PkwCbYSFw8vpgWD0v7zRCl1FpY3fjDSQ3/N/wNd9Ffa4gPi8+4keqt99N3XW6F99t/mUzp2xAhNmfKWp95QA==", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } + "node_modules/ospath": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/ospath/-/ospath-1.2.2.tgz", + "integrity": "sha512-o6E5qJV5zkAbIDNhGSIlyOhScKXgQrSRMilfph0clDfM0nEnBOlKlH4sWDmG95BW/CvwNz0vmm7dJVtU2KlMiA==", + "dev": true }, - "node_modules/unist-util-remove": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/unist-util-remove/-/unist-util-remove-2.1.0.tgz", - "integrity": "sha512-J8NYPyBm4baYLdCbjmf1bhPu45Cr1MWTm77qd9istEkzWpnN6O9tMsEbB2JhNnBCqGENRqEWomQ+He6au0B27Q==", - "dependencies": { - "unist-util-is": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "node_modules/p-cancelable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", + "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==", + "engines": { + "node": ">=6" } }, - "node_modules/unist-util-remove-position": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/unist-util-remove-position/-/unist-util-remove-position-2.0.1.tgz", - "integrity": "sha512-fDZsLYIe2uT+oGFnuZmy73K6ZxOPG/Qcm+w7jbEjaFcJgbQ6cqjs/eSPzXhsmGpAsWPkqZM9pYjww5QTn3LHMA==", + "node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dependencies": { - "unist-util-visit": "^2.0.0" + "p-try": "^2.0.0" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unist-util-stringify-position": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-2.0.3.tgz", - "integrity": "sha512-3faScn5I+hy9VleOq/qNbAd6pAx7iH5jYBMS9I1HgQVijz/4mv5Bvw5iw1sC/90CODiKo81G/ps8AJrISn687g==", - "dependencies": { - "@types/unist": "^2.0.2" + "engines": { + "node": ">=6" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/unist-util-visit": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-2.0.3.tgz", - "integrity": "sha512-iJ4/RczbJMkD0712mGktuGpm/U4By4FfDonL7N/9tATGIF4imikjOuagyMY53tnZq3NP6BcmlrHhEKAfGWjh7Q==", + "node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", "dependencies": { - "@types/unist": "^2.0.0", - "unist-util-is": "^4.0.0", - "unist-util-visit-parents": "^3.0.0" + "p-limit": "^2.2.0" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "engines": { + "node": ">=8" } }, - "node_modules/unist-util-visit-parents": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-3.1.1.tgz", - "integrity": "sha512-1KROIZWo6bcMrZEwiH2UrXDyalAa0uqzWCxCJj6lPOvTve2WkfgCytoDTPaMnodXh1WrXOq0haVYHj99ynJlsg==", + "node_modules/p-map": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", "dependencies": { - "@types/unist": "^2.0.0", - "unist-util-is": "^4.0.0" + "aggregate-error": "^3.0.0" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", "engines": { - "node": ">= 0.8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/unquote": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/unquote/-/unquote-1.1.1.tgz", - "integrity": "sha1-j97XMk7G6IoP+LkF58CYzcCG1UQ=" - }, - "node_modules/unset-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", - "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", + "node_modules/p-retry": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-4.6.2.tgz", + "integrity": "sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==", "dependencies": { - "has-value": "^0.3.1", - "isobject": "^3.0.0" + "@types/retry": "0.12.0", + "retry": "^0.13.1" }, "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, - "node_modules/unset-value/node_modules/has-value": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", - "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", - "dependencies": { - "get-value": "^2.0.3", - "has-values": "^0.1.4", - "isobject": "^2.0.0" - }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", "engines": { - "node": ">=0.10.0" + "node": ">=6" } }, - "node_modules/unset-value/node_modules/has-value/node_modules/isobject": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", - "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "node_modules/package-json": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/package-json/-/package-json-6.5.0.tgz", + "integrity": "sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ==", "dependencies": { - "isarray": "1.0.0" + "got": "^9.6.0", + "registry-auth-token": "^4.0.0", + "registry-url": "^5.0.0", + "semver": "^6.2.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, - "node_modules/unset-value/node_modules/has-values": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", - "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", - "engines": { - "node": ">=0.10.0" + "node_modules/package-json/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "bin": { + "semver": "bin/semver.js" } }, - "node_modules/upath": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", - "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==", - "engines": { - "node": ">=4", - "yarn": "*" + "node_modules/pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==" + }, + "node_modules/param-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", + "integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==", + "dependencies": { + "dot-case": "^3.0.4", + "tslib": "^2.0.3" } }, - "node_modules/update-notifier": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-5.1.0.tgz", - "integrity": "sha512-ItnICHbeMh9GqUy31hFPrD1kcuZ3rpxDZbf4KUDavXwS0bW5m7SLbDQpGX3UYr072cbrF5hFUs3r5tUsPwjfHw==", + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", "dependencies": { - "boxen": "^5.0.0", - "chalk": "^4.1.0", - "configstore": "^5.0.1", - "has-yarn": "^2.1.0", - "import-lazy": "^2.1.0", - "is-ci": "^2.0.0", - "is-installed-globally": "^0.4.0", - "is-npm": "^5.0.0", - "is-yarn-global": "^0.3.0", - "latest-version": "^5.1.0", - "pupa": "^2.1.1", - "semver": "^7.3.4", - "semver-diff": "^3.1.1", - "xdg-basedir": "^4.0.0" + "callsites": "^3.0.0" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/yeoman/update-notifier?sponsor=1" + "node": ">=6" } }, - "node_modules/uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "node_modules/parse-asn1": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.6.tgz", + "integrity": "sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw==", "dependencies": { - "punycode": "^2.1.0" + "asn1.js": "^5.2.0", + "browserify-aes": "^1.0.0", + "evp_bytestokey": "^1.0.0", + "pbkdf2": "^3.0.3", + "safe-buffer": "^5.1.1" } }, - "node_modules/urix": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", - "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", - "deprecated": "Please see https://github.com/lydell/urix#deprecated" + "node_modules/parse-bmfont-ascii": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/parse-bmfont-ascii/-/parse-bmfont-ascii-1.0.6.tgz", + "integrity": "sha1-Eaw8P/WPfCAgqyJ2kHkQjU36AoU=" }, - "node_modules/url": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", - "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", - "dependencies": { - "punycode": "1.3.2", - "querystring": "0.2.0" - } + "node_modules/parse-bmfont-binary": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/parse-bmfont-binary/-/parse-bmfont-binary-1.0.6.tgz", + "integrity": "sha1-0Di0dtPp3Z2x4RoLDlOiJ5K2kAY=" }, - "node_modules/url-loader": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/url-loader/-/url-loader-4.1.1.tgz", - "integrity": "sha512-3BTV812+AVHHOJQO8O5MkWgZ5aosP7GnROJwvzLS9hWDj00lZ6Z0wNak423Lp9PBZN05N+Jk/N5Si8jRAlGyWA==", + "node_modules/parse-bmfont-xml": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/parse-bmfont-xml/-/parse-bmfont-xml-1.1.4.tgz", + "integrity": "sha512-bjnliEOmGv3y1aMEfREMBJ9tfL3WR0i0CKPj61DnSLaoxWR3nLrsQrEbCId/8rF4NyRF0cCqisSVXyQYWM+mCQ==", "dependencies": { - "loader-utils": "^2.0.0", - "mime-types": "^2.1.27", - "schema-utils": "^3.0.0" - }, - "engines": { - "node": ">= 10.13.0" + "xml-parse-from-string": "^1.0.0", + "xml2js": "^0.4.5" + } + }, + "node_modules/parse-entities": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-2.0.0.tgz", + "integrity": "sha512-kkywGpCcRYhqQIchaWqZ875wzpS/bMKhz5HnN3p7wveJTkTtyAB/AlnS0f8DFSqYW1T82t6yEAkEcB+A1I3MbQ==", + "dependencies": { + "character-entities": "^1.0.0", + "character-entities-legacy": "^1.0.0", + "character-reference-invalid": "^1.0.0", + "is-alphanumerical": "^1.0.0", + "is-decimal": "^1.0.0", + "is-hexadecimal": "^1.0.0" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/parse-headers": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/parse-headers/-/parse-headers-2.0.5.tgz", + "integrity": "sha512-ft3iAoLOB/MlwbNXgzy43SWGP6sQki2jQvAyBg/zDFAgr9bfNWZIUj42Kw2eJIl8kEi4PbgE6U1Zau/HwI75HA==" + }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "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" }, - "peerDependencies": { - "file-loader": "*", - "webpack": "^4.0.0 || ^5.0.0" + "engines": { + "node": ">=8" }, - "peerDependenciesMeta": { - "file-loader": { - "optional": true - } + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/url-parse": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.3.tgz", - "integrity": "sha512-IIORyIQD9rvj0A4CLWsHkBBJuNqWpFQe224b6j9t/ABmquIS0qDU2pY6kl6AuOrL5OkCXHMCFNe1jBcuAggjvQ==", + "node_modules/parse-numeric-range": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/parse-numeric-range/-/parse-numeric-range-1.3.0.tgz", + "integrity": "sha512-twN+njEipszzlMJd4ONUYgSfZPDxgHhT9Ahed5uTigpQn90FggW4SA/AIPq/6a149fTbE9qBEcSwE3FAEp6wQQ==" + }, + "node_modules/parse5": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", + "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==" + }, + "node_modules/parse5-htmlparser2-tree-adapter": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz", + "integrity": "sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==", "dependencies": { - "querystringify": "^2.1.1", - "requires-port": "^1.0.0" + "parse5": "^6.0.1" } }, - "node_modules/url-parse-lax": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", - "integrity": "sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=", + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/pascal-case": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz", + "integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==", "dependencies": { - "prepend-http": "^2.0.0" - }, + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/path-browserify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", + "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==" + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", "engines": { - "node": ">=4" + "node": ">=8" } }, - "node_modules/url-template": { - "version": "2.0.8", - "resolved": "https://registry.npmjs.org/url-template/-/url-template-2.0.8.tgz", - "integrity": "sha1-/FZaPMy/93MMd19WQflVV5FDnyE=" + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "engines": { + "node": ">=0.10.0" + } }, - "node_modules/url/node_modules/punycode": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", - "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=" + "node_modules/path-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=" }, - "node_modules/use": { + "node_modules/path-key": { "version": "3.1.1", - "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", - "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, - "node_modules/use-composed-ref": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/use-composed-ref/-/use-composed-ref-1.1.0.tgz", - "integrity": "sha512-my1lNHGWsSDAhhVAT4MKs6IjBUtG6ZG11uUqexPH9PptiIZDQOzaF4f5tEbJ2+7qvNbtXNBbU3SfmN+fXlWDhg==", + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" + }, + "node_modules/path-to-regexp": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", + "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", "dependencies": { - "ts-essentials": "^2.0.3" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0" + "isarray": "0.0.1" } }, - "node_modules/use-isomorphic-layout-effect": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.1.1.tgz", - "integrity": "sha512-L7Evj8FGcwo/wpbv/qvSfrkHFtOpCzvM5yl2KVyDJoylVuSvzphiiasmjgQPttIGBAy2WKiBNR98q8w7PiNgKQ==", - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "engines": { + "node": ">=8" } }, - "node_modules/use-latest": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/use-latest/-/use-latest-1.2.0.tgz", - "integrity": "sha512-d2TEuG6nSLKQLAfW3By8mKr8HurOlTkul0sOpxbClIv4SQ4iOd7BYr7VIzdbktUCnv7dua/60xzd8igMU6jmyw==", + "node_modules/pbkdf2": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.2.tgz", + "integrity": "sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==", "dependencies": { - "use-isomorphic-layout-effect": "^1.0.0" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0" + "create-hash": "^1.1.2", + "create-hmac": "^1.1.4", + "ripemd160": "^2.0.1", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "engines": { + "node": ">=0.12" } }, - "node_modules/utif": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/utif/-/utif-2.0.1.tgz", - "integrity": "sha512-Z/S1fNKCicQTf375lIP9G8Sa1H/phcysstNrrSdZKj1f9g58J4NMgb5IgiEZN9/nLMPDwF0W7hdOe9Qq2IYoLg==", - "dependencies": { - "pako": "^1.0.5" - } + "node_modules/pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", + "dev": true }, - "node_modules/util": { - "version": "0.12.4", - "resolved": "https://registry.npmjs.org/util/-/util-0.12.4.tgz", - "integrity": "sha512-bxZ9qtSlGUWSOy9Qa9Xgk11kSslpuZwaxCg4sNIDj6FLucDab2JxnHwyNTCpHMtK1MjoQiWQ6DiUMZYbSrO+Sw==", - "dependencies": { - "inherits": "^2.0.3", - "is-arguments": "^1.0.4", - "is-generator-function": "^1.0.7", - "is-typed-array": "^1.1.3", - "safe-buffer": "^5.1.2", - "which-typed-array": "^1.1.2" - } + "node_modules/perfect-scrollbar": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/perfect-scrollbar/-/perfect-scrollbar-1.5.5.tgz", + "integrity": "sha512-dzalfutyP3e/FOpdlhVryN4AJ5XDVauVWxybSkLZmakFE2sS3y3pc4JnSprw8tGmHvkaG5Edr5T7LBTZ+WWU2g==" }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + "node_modules/performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==", + "dev": true }, - "node_modules/util.promisify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.1.tgz", - "integrity": "sha512-g9JpC/3He3bm38zsLupWryXHoEcS22YHthuPQSJdMy6KNrzIRzWqcsHzD/WUnqe45whVou4VIsPew37DoXWNrA==", - "dependencies": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.2", - "has-symbols": "^1.0.1", - "object.getownpropertydescriptors": "^2.1.0" + "node_modules/phin": { + "version": "2.9.3", + "resolved": "https://registry.npmjs.org/phin/-/phin-2.9.3.tgz", + "integrity": "sha512-CzFr90qM24ju5f88quFC/6qohjC144rehe5n6DH900lgXmUe86+xCKc10ev56gRKC4/BkHUoG4uSiQgBiIXwDA==" + }, + "node_modules/picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "engines": { + "node": ">=8.6" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/utila": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/utila/-/utila-0.4.0.tgz", - "integrity": "sha1-ihagXURWV6Oupe7MWxKk+lN5dyw=" - }, - "node_modules/utility-types": { - "version": "3.10.0", - "resolved": "https://registry.npmjs.org/utility-types/-/utility-types-3.10.0.tgz", - "integrity": "sha512-O11mqxmi7wMKCo6HKFt5AhO4BwY3VV68YU07tgxfz8zJTIxr4BpsezN49Ffwy9j3ZpwwJp4fkRwjRzq3uWE6Rg==", + "node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "dev": true, "engines": { - "node": ">= 4" + "node": ">=0.10.0" } }, - "node_modules/utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", + "node_modules/pirates": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.5.tgz", + "integrity": "sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ==", + "dev": true, "engines": { - "node": ">= 0.4.0" + "node": ">= 6" } }, - "node_modules/uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", - "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", - "bin": { - "uuid": "bin/uuid" - } - }, - "node_modules/value-equal": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/value-equal/-/value-equal-1.0.1.tgz", - "integrity": "sha512-NOJ6JZCAWr0zlxZt+xqCHNTEKOsrks2HQd4MqhP1qy4z1SkbEP467eNx6TgDKXMvUOb+OENfJCZwM+16n7fRfw==" + "node_modules/pixelmatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/pixelmatch/-/pixelmatch-4.0.2.tgz", + "integrity": "sha1-j0fc7FARtHe2fbA8JDvB8wheiFQ=", + "dependencies": { + "pngjs": "^3.0.0" + }, + "bin": { + "pixelmatch": "bin/pixelmatch" + } }, - "node_modules/vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", + "node_modules/pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dependencies": { + "find-up": "^4.0.0" + }, "engines": { - "node": ">= 0.8" + "node": ">=8" } }, - "node_modules/vendors": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/vendors/-/vendors-1.0.4.tgz", - "integrity": "sha512-/juG65kTL4Cy2su4P8HjtkTxk6VmJDiOPBufWniqQ6wknac6jNiXS9vU+hO3wgusiyqWlzTbVHi0dyJqRONg3w==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "node_modules/pkg-up": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-3.1.0.tgz", + "integrity": "sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA==", + "dependencies": { + "find-up": "^3.0.0" + }, + "engines": { + "node": ">=8" } }, - "node_modules/vfile": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/vfile/-/vfile-4.2.1.tgz", - "integrity": "sha512-O6AE4OskCG5S1emQ/4gl8zK586RqA3srz3nfK/Viy0UPToBc5Trp9BVFb1u0CjsKrAWwnpr4ifM/KBXPWwJbCA==", + "node_modules/pkg-up/node_modules/find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", "dependencies": { - "@types/unist": "^2.0.0", - "is-buffer": "^2.0.0", - "unist-util-stringify-position": "^2.0.0", - "vfile-message": "^2.0.0" + "locate-path": "^3.0.0" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "engines": { + "node": ">=6" } }, - "node_modules/vfile-location": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-3.2.0.tgz", - "integrity": "sha512-aLEIZKv/oxuCDZ8lkJGhuhztf/BW4M+iHdCwglA/eWc+vtuRFJj8EtgceYFX4LRjOhCAAiNHsKGssC6onJ+jbA==", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "node_modules/pkg-up/node_modules/locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" } }, - "node_modules/vfile-message": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-2.0.4.tgz", - "integrity": "sha512-DjssxRGkMvifUOJre00juHoP9DPWuzjxKuMDrhNbk2TdaYYBNMStsNhEOt3idrtI12VQYM/1+iM0KOzXi4pxwQ==", + "node_modules/pkg-up/node_modules/p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", "dependencies": { - "@types/unist": "^2.0.0", - "unist-util-stringify-position": "^2.0.0" + "p-limit": "^2.0.0" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "engines": { + "node": ">=6" } }, - "node_modules/vfile/node_modules/is-buffer": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz", - "integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], + "node_modules/pkg-up/node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", "engines": { "node": ">=4" } }, - "node_modules/vm-browserify": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz", - "integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==" + "node_modules/pluralize": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", + "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==", + "engines": { + "node": ">=4" + } }, - "node_modules/wait-on": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/wait-on/-/wait-on-5.3.0.tgz", - "integrity": "sha512-DwrHrnTK+/0QFaB9a8Ol5Lna3k7WvUR4jzSKmz0YaPBpuN2sACyiPVKVfj6ejnjcajAcvn3wlbTyMIn9AZouOg==", - "dependencies": { - "axios": "^0.21.1", - "joi": "^17.3.0", - "lodash": "^4.17.21", - "minimist": "^1.2.5", - "rxjs": "^6.6.3" - }, - "bin": { - "wait-on": "bin/wait-on" - }, + "node_modules/pngjs": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-3.4.0.tgz", + "integrity": "sha512-NCrCHhWmnQklfH4MtJMRjZ2a8c80qXeMlQMv2uVp9ISJMTt562SbGd6n2oq0PaPgKm7Z6pL9E2UlLIhC+SHL3w==", "engines": { - "node": ">=8.9.0" + "node": ">=4.0.0" } }, - "node_modules/watchpack": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.2.0.tgz", - "integrity": "sha512-up4YAn/XHgZHIxFBVCdlMiWDj6WaLKpwVeGQk2I5thdYxF/KmF0aaz6TfJZ/hfl1h/XlcDr7k1KH7ThDagpFaA==", + "node_modules/polished": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/polished/-/polished-4.2.2.tgz", + "integrity": "sha512-Sz2Lkdxz6F2Pgnpi9U5Ng/WdWAUZxmHrNPoVlm3aAemxoy2Qy7LGjQg4uf8qKelDAUW94F4np3iH2YPf2qefcQ==", "dependencies": { - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.1.2" + "@babel/runtime": "^7.17.8" }, "engines": { - "node": ">=10.13.0" + "node": ">=10" } }, - "node_modules/wbuf": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz", - "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==", + "node_modules/portfinder": { + "version": "1.0.28", + "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.28.tgz", + "integrity": "sha512-Se+2isanIcEqf2XMHjyUKskczxbPH7dQnlMjXX6+dybayyHvAf/TCgyMRlzf/B6QDhAEFOGes0pzRo3by4AbMA==", "dependencies": { - "minimalistic-assert": "^1.0.0" + "async": "^2.6.2", + "debug": "^3.1.1", + "mkdirp": "^0.5.5" + }, + "engines": { + "node": ">= 0.12.0" } }, - "node_modules/web-namespaces": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/web-namespaces/-/web-namespaces-1.1.4.tgz", - "integrity": "sha512-wYxSGajtmoP4WxfejAPIr4l0fVh+jeMXZb08wNc0tMg6xsfZXj3cECqIK0G7ZAqUq0PP8WlMDtaOGVBTAWztNw==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "node_modules/portfinder/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dependencies": { + "ms": "^2.1.1" } }, - "node_modules/webpack": { - "version": "5.58.2", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.58.2.tgz", - "integrity": "sha512-3S6e9Vo1W2ijk4F4PPWRIu6D/uGgqaPmqw+av3W3jLDujuNkdxX5h5c+RQ6GkjVR+WwIPOfgY8av+j5j4tMqJw==", + "node_modules/postcss": { + "version": "8.4.13", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.13.tgz", + "integrity": "sha512-jtL6eTBrza5MPzy8oJLFuUscHDXTV5KcLlqAWHl5q5WYRfnNRGSmOZmOZ1T6Gy7A99mOZfqungmZMpMmCVJ8ZA==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + } + ], "dependencies": { - "@types/eslint-scope": "^3.7.0", - "@types/estree": "^0.0.50", - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/wasm-edit": "1.11.1", - "@webassemblyjs/wasm-parser": "1.11.1", - "acorn": "^8.4.1", - "acorn-import-assertions": "^1.7.6", - "browserslist": "^4.14.5", - "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.8.3", - "es-module-lexer": "^0.9.0", - "eslint-scope": "5.1.1", - "events": "^3.2.0", - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.2.4", - "json-parse-better-errors": "^1.0.2", - "loader-runner": "^4.2.0", - "mime-types": "^2.1.27", - "neo-async": "^2.6.2", - "schema-utils": "^3.1.0", - "tapable": "^2.1.1", - "terser-webpack-plugin": "^5.1.3", - "watchpack": "^2.2.0", - "webpack-sources": "^3.2.0" - }, - "bin": { - "webpack": "bin/webpack.js" + "nanoid": "^3.3.3", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" }, "engines": { - "node": ">=10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependenciesMeta": { - "webpack-cli": { - "optional": true - } + "node": "^10 || ^12 || >=14" } }, - "node_modules/webpack-bundle-analyzer": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/webpack-bundle-analyzer/-/webpack-bundle-analyzer-4.5.0.tgz", - "integrity": "sha512-GUMZlM3SKwS8Z+CKeIFx7CVoHn3dXFcUAjT/dcZQQmfSZGvitPfMob2ipjai7ovFFqPvTqkEZ/leL4O0YOdAYQ==", + "node_modules/postcss-calc": { + "version": "8.2.4", + "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-8.2.4.tgz", + "integrity": "sha512-SmWMSJmB8MRnnULldx0lQIyhSNvuDl9HfrZkaqqE/WHAhToYsAvDq+yAsA/kIyINDszOp3Rh0GFoNuH5Ypsm3Q==", "dependencies": { - "acorn": "^8.0.4", - "acorn-walk": "^8.0.0", - "chalk": "^4.1.0", - "commander": "^7.2.0", - "gzip-size": "^6.0.0", - "lodash": "^4.17.20", - "opener": "^1.5.2", - "sirv": "^1.0.7", - "ws": "^7.3.1" + "postcss-selector-parser": "^6.0.9", + "postcss-value-parser": "^4.2.0" }, - "bin": { - "webpack-bundle-analyzer": "lib/bin/analyzer.js" - }, - "engines": { - "node": ">= 10.13.0" + "peerDependencies": { + "postcss": "^8.2.2" } }, - "node_modules/webpack-bundle-analyzer/node_modules/commander": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", - "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "node_modules/postcss-colormin": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-5.3.0.tgz", + "integrity": "sha512-WdDO4gOFG2Z8n4P8TWBpshnL3JpmNmJwdnfP2gbk2qBA8PWwOYcmjmI/t3CmMeL72a7Hkd+x/Mg9O2/0rD54Pg==", + "dependencies": { + "browserslist": "^4.16.6", + "caniuse-api": "^3.0.0", + "colord": "^2.9.1", + "postcss-value-parser": "^4.2.0" + }, "engines": { - "node": ">= 10" + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" } }, - "node_modules/webpack-bundle-analyzer/node_modules/gzip-size": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-6.0.0.tgz", - "integrity": "sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q==", + "node_modules/postcss-convert-values": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-5.1.0.tgz", + "integrity": "sha512-GkyPbZEYJiWtQB0KZ0X6qusqFHUepguBCNFi9t5JJc7I2OTXG7C0twbTLvCfaKOLl3rSXmpAwV7W5txd91V84g==", "dependencies": { - "duplexer": "^0.1.2" + "postcss-value-parser": "^4.2.0" }, "engines": { - "node": ">=10" + "node": "^10 || ^12 || >=14.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "peerDependencies": { + "postcss": "^8.2.15" } }, - "node_modules/webpack-dev-middleware": { - "version": "3.7.3", - "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-3.7.3.tgz", - "integrity": "sha512-djelc/zGiz9nZj/U7PTBi2ViorGJXEWo/3ltkPbDyxCXhhEXkW0ce99falaok4TPj+AsxLiXJR0EBOb0zh9fKQ==", - "dependencies": { - "memory-fs": "^0.4.1", - "mime": "^2.4.4", - "mkdirp": "^0.5.1", - "range-parser": "^1.2.1", - "webpack-log": "^2.0.0" - }, + "node_modules/postcss-discard-comments": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-5.1.1.tgz", + "integrity": "sha512-5JscyFmvkUxz/5/+TB3QTTT9Gi9jHkcn8dcmmuN68JQcv3aQg4y88yEHHhwFB52l/NkaJ43O0dbksGMAo49nfQ==", "engines": { - "node": ">= 6" + "node": "^10 || ^12 || >=14.0" }, "peerDependencies": { - "webpack": "^4.0.0 || ^5.0.0" + "postcss": "^8.2.15" } }, - "node_modules/webpack-dev-middleware/node_modules/mime": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.5.2.tgz", - "integrity": "sha512-tqkh47FzKeCPD2PUiPB6pkbMzsCasjxAfC62/Wap5qrUWcb+sFasXUC5I3gYM5iBM8v/Qpn4UK0x+j0iHyFPDg==", - "bin": { - "mime": "cli.js" - }, + "node_modules/postcss-discard-duplicates": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-5.1.0.tgz", + "integrity": "sha512-zmX3IoSI2aoenxHV6C7plngHWWhUOV3sP1T8y2ifzxzbtnuhk1EdPwm0S1bIUNaJ2eNbWeGLEwzw8huPD67aQw==", "engines": { - "node": ">=4.0.0" + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" } }, - "node_modules/webpack-dev-server": { - "version": "3.11.2", - "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-3.11.2.tgz", - "integrity": "sha512-A80BkuHRQfCiNtGBS1EMf2ChTUs0x+B3wGDFmOeT4rmJOHhHTCH2naNxIHhmkr0/UillP4U3yeIyv1pNp+QDLQ==", - "dependencies": { - "ansi-html": "0.0.7", - "bonjour": "^3.5.0", - "chokidar": "^2.1.8", - "compression": "^1.7.4", - "connect-history-api-fallback": "^1.6.0", - "debug": "^4.1.1", - "del": "^4.1.1", - "express": "^4.17.1", - "html-entities": "^1.3.1", - "http-proxy-middleware": "0.19.1", - "import-local": "^2.0.0", - "internal-ip": "^4.3.0", - "ip": "^1.1.5", - "is-absolute-url": "^3.0.3", - "killable": "^1.0.1", - "loglevel": "^1.6.8", - "opn": "^5.5.0", - "p-retry": "^3.0.1", - "portfinder": "^1.0.26", - "schema-utils": "^1.0.0", - "selfsigned": "^1.10.8", - "semver": "^6.3.0", - "serve-index": "^1.9.1", - "sockjs": "^0.3.21", - "sockjs-client": "^1.5.0", - "spdy": "^4.0.2", - "strip-ansi": "^3.0.1", - "supports-color": "^6.1.0", - "url": "^0.11.0", - "webpack-dev-middleware": "^3.7.2", - "webpack-log": "^2.0.0", - "ws": "^6.2.1", - "yargs": "^13.3.2" - }, - "bin": { - "webpack-dev-server": "bin/webpack-dev-server.js" - }, + "node_modules/postcss-discard-empty": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-5.1.1.tgz", + "integrity": "sha512-zPz4WljiSuLWsI0ir4Mcnr4qQQ5e1Ukc3i7UfE2XcrwKK2LIPIqE5jxMRxO6GbI3cv//ztXDsXwEWT3BHOGh3A==", "engines": { - "node": ">= 6.11.5" + "node": "^10 || ^12 || >=14.0" }, "peerDependencies": { - "webpack": "^4.0.0 || ^5.0.0" - }, - "peerDependenciesMeta": { - "webpack-cli": { - "optional": true - } + "postcss": "^8.2.15" } }, - "node_modules/webpack-dev-server/node_modules/ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "node_modules/postcss-discard-overridden": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-5.1.0.tgz", + "integrity": "sha512-21nOL7RqWR1kasIVdKs8HNqQJhFxLsyRfAnUDm4Fe4t4mCWL9OJiHvlHPjcd8zc5Myu89b/7wZDnOSjFgeWRtw==", "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/webpack-dev-server/node_modules/anymatch": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", - "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", - "dependencies": { - "micromatch": "^3.1.4", - "normalize-path": "^2.1.1" + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" } }, - "node_modules/webpack-dev-server/node_modules/anymatch/node_modules/normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "node_modules/postcss-discard-unused": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-discard-unused/-/postcss-discard-unused-5.1.0.tgz", + "integrity": "sha512-KwLWymI9hbwXmJa0dkrzpRbSJEh0vVUd7r8t0yOGPcfKzyJJxFM8kLyC5Ev9avji6nY95pOp1W6HqIrfT+0VGw==", "dependencies": { - "remove-trailing-separator": "^1.0.1" + "postcss-selector-parser": "^6.0.5" }, "engines": { - "node": ">=0.10.0" + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" } }, - "node_modules/webpack-dev-server/node_modules/array-union": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", - "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", + "node_modules/postcss-loader": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-6.2.1.tgz", + "integrity": "sha512-WbbYpmAaKcux/P66bZ40bpWsBucjx/TTgVVzRZ9yUO8yQfVBlameJ0ZGVaPfH64hNSBh63a+ICP5nqOpBA0w+Q==", "dependencies": { - "array-uniq": "^1.0.1" + "cosmiconfig": "^7.0.0", + "klona": "^2.0.5", + "semver": "^7.3.5" }, "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/webpack-dev-server/node_modules/binary-extensions": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", - "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", - "engines": { - "node": ">=0.10.0" + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "postcss": "^7.0.0 || ^8.0.1", + "webpack": "^5.0.0" } }, - "node_modules/webpack-dev-server/node_modules/braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "node_modules/postcss-merge-idents": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-merge-idents/-/postcss-merge-idents-5.1.1.tgz", + "integrity": "sha512-pCijL1TREiCoog5nQp7wUe+TUonA2tC2sQ54UGeMmryK3UFGIYKqDyjnqd6RcuI4znFn9hWSLNN8xKE/vWcUQw==", "dependencies": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" + "cssnano-utils": "^3.1.0", + "postcss-value-parser": "^4.2.0" }, "engines": { - "node": ">=0.10.0" + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" } }, - "node_modules/webpack-dev-server/node_modules/braces/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "node_modules/postcss-merge-longhand": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-5.1.4.tgz", + "integrity": "sha512-hbqRRqYfmXoGpzYKeW0/NCZhvNyQIlQeWVSao5iKWdyx7skLvCfQFGIUsP9NUs3dSbPac2IC4Go85/zG+7MlmA==", "dependencies": { - "is-extendable": "^0.1.0" + "postcss-value-parser": "^4.2.0", + "stylehacks": "^5.1.0" }, "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/webpack-dev-server/node_modules/chokidar": { - "version": "2.1.8", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", - "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", - "deprecated": "Chokidar 2 will break on node v14+. Upgrade to chokidar 3 with 15x less dependencies.", - "dependencies": { - "anymatch": "^2.0.0", - "async-each": "^1.0.1", - "braces": "^2.3.2", - "glob-parent": "^3.1.0", - "inherits": "^2.0.3", - "is-binary-path": "^1.0.0", - "is-glob": "^4.0.0", - "normalize-path": "^3.0.0", - "path-is-absolute": "^1.0.0", - "readdirp": "^2.2.1", - "upath": "^1.1.1" + "node": "^10 || ^12 || >=14.0" }, - "optionalDependencies": { - "fsevents": "^1.2.7" + "peerDependencies": { + "postcss": "^8.2.15" } }, - "node_modules/webpack-dev-server/node_modules/del": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/del/-/del-4.1.1.tgz", - "integrity": "sha512-QwGuEUouP2kVwQenAsOof5Fv8K9t3D8Ca8NxcXKrIpEHjTXK5J2nXLdP+ALI1cgv8wj7KuwBhTwBkOZSJKM5XQ==", + "node_modules/postcss-merge-rules": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-5.1.1.tgz", + "integrity": "sha512-8wv8q2cXjEuCcgpIB1Xx1pIy8/rhMPIQqYKNzEdyx37m6gpq83mQQdCxgIkFgliyEnKvdwJf/C61vN4tQDq4Ww==", "dependencies": { - "@types/glob": "^7.1.1", - "globby": "^6.1.0", - "is-path-cwd": "^2.0.0", - "is-path-in-cwd": "^2.0.0", - "p-map": "^2.0.0", - "pify": "^4.0.1", - "rimraf": "^2.6.3" + "browserslist": "^4.16.6", + "caniuse-api": "^3.0.0", + "cssnano-utils": "^3.1.0", + "postcss-selector-parser": "^6.0.5" }, "engines": { - "node": ">=6" + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" } }, - "node_modules/webpack-dev-server/node_modules/extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "node_modules/postcss-minify-font-values": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-5.1.0.tgz", + "integrity": "sha512-el3mYTgx13ZAPPirSVsHqFzl+BBBDrXvbySvPGFnQcTI4iNslrPaFq4muTkLZmKlGk4gyFAYUBMH30+HurREyA==", "dependencies": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" + "postcss-value-parser": "^4.2.0" }, "engines": { - "node": ">=0.10.0" + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" } }, - "node_modules/webpack-dev-server/node_modules/extend-shallow/node_modules/is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "node_modules/postcss-minify-gradients": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-5.1.1.tgz", + "integrity": "sha512-VGvXMTpCEo4qHTNSa9A0a3D+dxGFZCYwR6Jokk+/3oB6flu2/PnPXAh2x7x52EkY5xlIHLm+Le8tJxe/7TNhzw==", "dependencies": { - "is-plain-object": "^2.0.4" + "colord": "^2.9.1", + "cssnano-utils": "^3.1.0", + "postcss-value-parser": "^4.2.0" }, "engines": { - "node": ">=0.10.0" + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" } }, - "node_modules/webpack-dev-server/node_modules/fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "node_modules/postcss-minify-params": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-5.1.2.tgz", + "integrity": "sha512-aEP+p71S/urY48HWaRHasyx4WHQJyOYaKpQ6eXl8k0kxg66Wt/30VR6/woh8THgcpRbonJD5IeD+CzNhPi1L8g==", "dependencies": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" + "browserslist": "^4.16.6", + "cssnano-utils": "^3.1.0", + "postcss-value-parser": "^4.2.0" }, "engines": { - "node": ">=0.10.0" + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" } }, - "node_modules/webpack-dev-server/node_modules/fill-range/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "node_modules/postcss-minify-selectors": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-5.2.0.tgz", + "integrity": "sha512-vYxvHkW+iULstA+ctVNx0VoRAR4THQQRkG77o0oa4/mBS0OzGvvzLIvHDv/nNEM0crzN2WIyFU5X7wZhaUK3RA==", "dependencies": { - "is-extendable": "^0.1.0" + "postcss-selector-parser": "^6.0.5" }, "engines": { - "node": ">=0.10.0" + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" } }, - "node_modules/webpack-dev-server/node_modules/fsevents": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", - "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", - "deprecated": "fsevents 1 will break on node v14+ and could be using insecure binaries. Upgrade to fsevents 2.", - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], + "node_modules/postcss-modules-extract-imports": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-2.0.0.tgz", + "integrity": "sha512-LaYLDNS4SG8Q5WAWqIJgdHPJrDDr/Lv775rMBFUbgjTz6j34lUznACHcdRWroPvXANP2Vj7yNK57vp9eFqzLWQ==", + "dev": true, "dependencies": { - "bindings": "^1.5.0", - "nan": "^2.12.1" + "postcss": "^7.0.5" }, "engines": { - "node": ">= 4.0" + "node": ">= 6" } }, - "node_modules/webpack-dev-server/node_modules/glob-parent": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", - "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", - "dependencies": { - "is-glob": "^3.1.0", - "path-dirname": "^1.0.0" - } + "node_modules/postcss-modules-extract-imports/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true }, - "node_modules/webpack-dev-server/node_modules/glob-parent/node_modules/is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "node_modules/postcss-modules-extract-imports/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, "dependencies": { - "is-extglob": "^2.1.0" + "picocolors": "^0.2.1", + "source-map": "^0.6.1" }, "engines": { - "node": ">=0.10.0" + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" } }, - "node_modules/webpack-dev-server/node_modules/globby": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", - "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=", + "node_modules/postcss-modules-local-by-default": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-3.0.3.tgz", + "integrity": "sha512-e3xDq+LotiGesympRlKNgaJ0PCzoUIdpH0dj47iWAui/kyTgh3CiAr1qP54uodmJhl6p9rN6BoNcdEDVJx9RDw==", + "dev": true, "dependencies": { - "array-union": "^1.0.1", - "glob": "^7.0.3", - "object-assign": "^4.0.1", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" + "icss-utils": "^4.1.1", + "postcss": "^7.0.32", + "postcss-selector-parser": "^6.0.2", + "postcss-value-parser": "^4.1.0" }, "engines": { - "node": ">=0.10.0" + "node": ">= 6" } }, - "node_modules/webpack-dev-server/node_modules/globby/node_modules/pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "engines": { - "node": ">=0.10.0" - } + "node_modules/postcss-modules-local-by-default/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true }, - "node_modules/webpack-dev-server/node_modules/is-binary-path": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", - "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", + "node_modules/postcss-modules-local-by-default/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, "dependencies": { - "binary-extensions": "^1.0.0" + "picocolors": "^0.2.1", + "source-map": "^0.6.1" }, "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/webpack-dev-server/node_modules/is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dependencies": { - "kind-of": "^3.0.2" + "node": ">=6.0.0" }, - "engines": { - "node": ">=0.10.0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" } }, - "node_modules/webpack-dev-server/node_modules/is-number/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "node_modules/postcss-modules-scope": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-2.2.0.tgz", + "integrity": "sha512-YyEgsTMRpNd+HmyC7H/mh3y+MeFWevy7V1evVhJWewmMbjDHIbZbOXICC2y+m1xI1UVfIT1HMW/O04Hxyu9oXQ==", + "dev": true, "dependencies": { - "is-buffer": "^1.1.5" + "postcss": "^7.0.6", + "postcss-selector-parser": "^6.0.0" }, "engines": { - "node": ">=0.10.0" + "node": ">= 6" } }, - "node_modules/webpack-dev-server/node_modules/micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "dependencies": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } + "node_modules/postcss-modules-scope/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true }, - "node_modules/webpack-dev-server/node_modules/p-map": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", - "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==", + "node_modules/postcss-modules-scope/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, "engines": { - "node": ">=6" + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" } }, - "node_modules/webpack-dev-server/node_modules/readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "node_modules/postcss-modules-values": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-3.0.0.tgz", + "integrity": "sha512-1//E5jCBrZ9DmRX+zCtmQtRSV6PV42Ix7Bzj9GbwJceduuf7IqP8MgeTXuRDHOWj2m0VzZD5+roFWDuU8RQjcg==", + "dev": true, "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" + "icss-utils": "^4.0.0", + "postcss": "^7.0.6" } }, - "node_modules/webpack-dev-server/node_modules/readdirp": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", - "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", + "node_modules/postcss-modules-values/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "node_modules/postcss-modules-values/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, "dependencies": { - "graceful-fs": "^4.1.11", - "micromatch": "^3.1.10", - "readable-stream": "^2.0.2" + "picocolors": "^0.2.1", + "source-map": "^0.6.1" }, "engines": { - "node": ">=0.10" + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" } }, - "node_modules/webpack-dev-server/node_modules/rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "dependencies": { - "glob": "^7.1.3" + "node_modules/postcss-normalize-charset": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-5.1.0.tgz", + "integrity": "sha512-mSgUJ+pd/ldRGVx26p2wz9dNZ7ji6Pn8VWBajMXFf8jk7vUoSrZ2lt/wZR7DtlZYKesmZI680qjr2CeFF2fbUg==", + "engines": { + "node": "^10 || ^12 || >=14.0" }, - "bin": { - "rimraf": "bin.js" + "peerDependencies": { + "postcss": "^8.2.15" } }, - "node_modules/webpack-dev-server/node_modules/schema-utils": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", - "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "node_modules/postcss-normalize-display-values": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-display-values/-/postcss-normalize-display-values-5.1.0.tgz", + "integrity": "sha512-WP4KIM4o2dazQXWmFaqMmcvsKmhdINFblgSeRgn8BJ6vxaMyaJkwAzpPpuvSIoG/rmX3M+IrRZEz2H0glrQNEA==", "dependencies": { - "ajv": "^6.1.0", - "ajv-errors": "^1.0.0", - "ajv-keywords": "^3.1.0" + "postcss-value-parser": "^4.2.0" }, "engines": { - "node": ">= 4" - } - }, - "node_modules/webpack-dev-server/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/webpack-dev-server/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dependencies": { - "safe-buffer": "~5.1.0" + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" } }, - "node_modules/webpack-dev-server/node_modules/strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "node_modules/postcss-normalize-positions": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-positions/-/postcss-normalize-positions-5.1.0.tgz", + "integrity": "sha512-8gmItgA4H5xiUxgN/3TVvXRoJxkAWLW6f/KKhdsH03atg0cB8ilXnrB5PpSshwVu/dD2ZsRFQcR1OEmSBDAgcQ==", "dependencies": { - "ansi-regex": "^2.0.0" + "postcss-value-parser": "^4.2.0" }, "engines": { - "node": ">=0.10.0" + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" } }, - "node_modules/webpack-dev-server/node_modules/supports-color": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", - "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "node_modules/postcss-normalize-repeat-style": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-5.1.0.tgz", + "integrity": "sha512-IR3uBjc+7mcWGL6CtniKNQ4Rr5fTxwkaDHwMBDGGs1x9IVRkYIT/M4NelZWkAOBdV6v3Z9S46zqaKGlyzHSchw==", "dependencies": { - "has-flag": "^3.0.0" + "postcss-value-parser": "^4.2.0" }, "engines": { - "node": ">=6" + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" } }, - "node_modules/webpack-dev-server/node_modules/to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "node_modules/postcss-normalize-string": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-string/-/postcss-normalize-string-5.1.0.tgz", + "integrity": "sha512-oYiIJOf4T9T1N4i+abeIc7Vgm/xPCGih4bZz5Nm0/ARVJ7K6xrDlLwvwqOydvyL3RHNf8qZk6vo3aatiw/go3w==", "dependencies": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" + "postcss-value-parser": "^4.2.0" }, "engines": { - "node": ">=0.10.0" + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" } }, - "node_modules/webpack-dev-server/node_modules/ws": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.2.tgz", - "integrity": "sha512-zmhltoSR8u1cnDsD43TX59mzoMZsLKqUweyYBAIvTngR3shc0W6aOZylZmq/7hqyVxPdi+5Ud2QInblgyE72fw==", + "node_modules/postcss-normalize-timing-functions": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-5.1.0.tgz", + "integrity": "sha512-DOEkzJ4SAXv5xkHl0Wa9cZLF3WCBhF3o1SKVxKQAa+0pYKlueTpCgvkFAHfk+Y64ezX9+nITGrDZeVGgITJXjg==", "dependencies": { - "async-limiter": "~1.0.0" + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" } }, - "node_modules/webpack-log": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/webpack-log/-/webpack-log-2.0.0.tgz", - "integrity": "sha512-cX8G2vR/85UYG59FgkoMamwHUIkSSlV3bBMRsbxVXVUk2j6NleCKjQ/WE9eYg9WY4w25O9w8wKP4rzNZFmUcUg==", + "node_modules/postcss-normalize-unicode": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-unicode/-/postcss-normalize-unicode-5.1.0.tgz", + "integrity": "sha512-J6M3MizAAZ2dOdSjy2caayJLQT8E8K9XjLce8AUQMwOrCvjCHv24aLC/Lps1R1ylOfol5VIDMaM/Lo9NGlk1SQ==", "dependencies": { - "ansi-colors": "^3.0.0", - "uuid": "^3.3.2" + "browserslist": "^4.16.6", + "postcss-value-parser": "^4.2.0" }, "engines": { - "node": ">= 6" + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" } }, - "node_modules/webpack-merge": { - "version": "5.8.0", - "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.8.0.tgz", - "integrity": "sha512-/SaI7xY0831XwP6kzuwhKWVKDP9t1QY1h65lAFLbZqMPIuYcD9QAW4u9STIbU9kaJbPBB/geU/gLr1wDjOhQ+Q==", + "node_modules/postcss-normalize-url": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-5.1.0.tgz", + "integrity": "sha512-5upGeDO+PVthOxSmds43ZeMeZfKH+/DKgGRD7TElkkyS46JXAUhMzIKiCa7BabPeIy3AQcTkXwVVN7DbqsiCew==", "dependencies": { - "clone-deep": "^4.0.1", - "wildcard": "^2.0.0" + "normalize-url": "^6.0.1", + "postcss-value-parser": "^4.2.0" }, "engines": { - "node": ">=10.0.0" + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" } }, - "node_modules/webpack-sources": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.1.tgz", - "integrity": "sha512-t6BMVLQ0AkjBOoRTZgqrWm7xbXMBzD+XDq2EZ96+vMfn3qKgsvdXZhbPZ4ElUOpdv4u+iiGe+w3+J75iy/bYGA==", + "node_modules/postcss-normalize-whitespace": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-whitespace/-/postcss-normalize-whitespace-5.1.1.tgz", + "integrity": "sha512-83ZJ4t3NUDETIHTa3uEg6asWjSBYL5EdkVB0sDncx9ERzOKBVJIUeDO9RyA9Zwtig8El1d79HBp0JEi8wvGQnA==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, "engines": { - "node": ">=10.13.0" + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" } }, - "node_modules/webpackbar": { - "version": "5.0.0-3", - "resolved": "https://registry.npmjs.org/webpackbar/-/webpackbar-5.0.0-3.tgz", - "integrity": "sha512-viW6KCYjMb0NPoDrw2jAmLXU2dEOhRrtku28KmOfeE1vxbfwCYuTbTaMhnkrCZLFAFyY9Q49Z/jzYO80Dw5b8g==", + "node_modules/postcss-ordered-values": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-5.1.1.tgz", + "integrity": "sha512-7lxgXF0NaoMIgyihL/2boNAEZKiW0+HkMhdKMTD93CjW8TdCy2hSdj8lsAo+uwm7EDG16Da2Jdmtqpedl0cMfw==", "dependencies": { - "ansi-escapes": "^4.3.1", - "chalk": "^4.1.0", - "consola": "^2.15.0", - "figures": "^3.2.0", - "pretty-time": "^1.1.0", - "std-env": "^2.2.1", - "text-table": "^0.2.0", - "wrap-ansi": "^7.0.0" + "cssnano-utils": "^3.1.0", + "postcss-value-parser": "^4.2.0" }, "engines": { - "node": ">=10" + "node": "^10 || ^12 || >=14.0" }, "peerDependencies": { - "webpack": "3 || 4 || 5" + "postcss": "^8.2.15" } }, - "node_modules/websocket-driver": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", - "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", + "node_modules/postcss-reduce-idents": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/postcss-reduce-idents/-/postcss-reduce-idents-5.2.0.tgz", + "integrity": "sha512-BTrLjICoSB6gxbc58D5mdBK8OhXRDqud/zodYfdSi52qvDHdMwk+9kB9xsM8yJThH/sZU5A6QVSmMmaN001gIg==", "dependencies": { - "http-parser-js": ">=0.5.1", - "safe-buffer": ">=5.1.0", - "websocket-extensions": ">=0.1.1" + "postcss-value-parser": "^4.2.0" }, "engines": { - "node": ">=0.8.0" + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" } }, - "node_modules/websocket-extensions": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", - "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", + "node_modules/postcss-reduce-initial": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-5.1.0.tgz", + "integrity": "sha512-5OgTUviz0aeH6MtBjHfbr57tml13PuedK/Ecg8szzd4XRMbYxH4572JFG067z+FqBIf6Zp/d+0581glkvvWMFw==", + "dependencies": { + "browserslist": "^4.16.6", + "caniuse-api": "^3.0.0" + }, "engines": { - "node": ">=0.8.0" + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" } }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "node_modules/postcss-reduce-transforms": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-5.1.0.tgz", + "integrity": "sha512-2fbdbmgir5AvpW9RLtdONx1QoYG2/EtqpNQbFASDlixBbAYuTcJ0dECwlqNqH7VbaUnEnh8SrxOe2sRIn24XyQ==", "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" + "postcss-value-parser": "^4.2.0" }, "engines": { - "node": ">= 8" + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" } }, - "node_modules/which-boxed-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", - "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "node_modules/postcss-selector-parser": { + "version": "6.0.10", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz", + "integrity": "sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==", "dependencies": { - "is-bigint": "^1.0.1", - "is-boolean-object": "^1.1.0", - "is-number-object": "^1.0.4", - "is-string": "^1.0.5", - "is-symbol": "^1.0.3" + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": ">=4" } }, - "node_modules/which-module": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=" - }, - "node_modules/which-typed-array": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.7.tgz", - "integrity": "sha512-vjxaB4nfDqwKI0ws7wZpxIlde1XrLX5uB0ZjpfshgmapJMD7jJWhZI+yToJTqaFByF0eNBcYxbjmCzoRP7CfEw==", + "node_modules/postcss-sort-media-queries": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/postcss-sort-media-queries/-/postcss-sort-media-queries-4.2.1.tgz", + "integrity": "sha512-9VYekQalFZ3sdgcTjXMa0dDjsfBVHXlraYJEMiOJ/2iMmI2JGCMavP16z3kWOaRu8NSaJCTgVpB/IVpH5yT9YQ==", "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "es-abstract": "^1.18.5", - "foreach": "^2.0.5", - "has-tostringtag": "^1.0.0", - "is-typed-array": "^1.1.7" + "sort-css-media-queries": "2.0.4" }, "engines": { - "node": ">= 0.4" + "node": ">=10.0.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "peerDependencies": { + "postcss": "^8.4.4" } }, - "node_modules/wide-align": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", - "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", + "node_modules/postcss-svgo": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-5.1.0.tgz", + "integrity": "sha512-D75KsH1zm5ZrHyxPakAxJWtkyXew5qwS70v56exwvw542d9CRtTo78K0WeFxZB4G7JXKKMbEZtZayTGdIky/eA==", "dependencies": { - "string-width": "^1.0.2 || 2" - } - }, - "node_modules/wide-align/node_modules/ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "postcss-value-parser": "^4.2.0", + "svgo": "^2.7.0" + }, "engines": { - "node": ">=4" + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" } }, - "node_modules/wide-align/node_modules/is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "node_modules/postcss-svgo/node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", "engines": { - "node": ">=4" + "node": ">= 10" } }, - "node_modules/wide-align/node_modules/string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "node_modules/postcss-svgo/node_modules/css-tree": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz", + "integrity": "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==", "dependencies": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" + "mdn-data": "2.0.14", + "source-map": "^0.6.1" }, "engines": { - "node": ">=4" + "node": ">=8.0.0" } }, - "node_modules/wide-align/node_modules/strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "node_modules/postcss-svgo/node_modules/mdn-data": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz", + "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==" + }, + "node_modules/postcss-svgo/node_modules/svgo": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-2.8.0.tgz", + "integrity": "sha512-+N/Q9kV1+F+UeWYoSiULYo4xYSDQlTgb+ayMobAXPwMnLvop7oxKMo9OzIrX5x3eS4L4f2UHhc9axXwY8DpChg==", "dependencies": { - "ansi-regex": "^3.0.0" + "@trysound/sax": "0.2.0", + "commander": "^7.2.0", + "css-select": "^4.1.3", + "css-tree": "^1.1.3", + "csso": "^4.2.0", + "picocolors": "^1.0.0", + "stable": "^0.1.8" + }, + "bin": { + "svgo": "bin/svgo" }, "engines": { - "node": ">=4" + "node": ">=10.13.0" } }, - "node_modules/widest-line": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", - "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==", + "node_modules/postcss-unique-selectors": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-5.1.1.tgz", + "integrity": "sha512-5JiODlELrz8L2HwxfPnhOWZYWDxVHWL83ufOv84NrcgipI7TaeRsatAhK4Tr2/ZiYldpK/wBvw5BD3qfaK96GA==", "dependencies": { - "string-width": "^4.0.0" + "postcss-selector-parser": "^6.0.5" }, "engines": { - "node": ">=8" + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" } }, - "node_modules/wildcard": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.0.tgz", - "integrity": "sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw==" - }, - "node_modules/worker-rpc": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/worker-rpc/-/worker-rpc-0.1.1.tgz", - "integrity": "sha512-P1WjMrUB3qgJNI9jfmpZ/htmBEjFh//6l/5y8SD9hg1Ef5zTTVVoRjTrTEzPrNBQvmhMxkoTsjOXN10GWU7aCg==", - "dependencies": { - "microevent.ts": "~0.1.1" - } + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" }, - "node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, + "node_modules/postcss-zindex": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-zindex/-/postcss-zindex-5.1.0.tgz", + "integrity": "sha512-fgFMf0OtVSBR1va1JNHYgMxYk73yhn/qb4uQDq1DLGYolz8gHCyr/sesEuGUaYs58E3ZJRcpoGuPVoB7Meiq9A==", "engines": { - "node": ">=10" + "node": "^10 || ^12 || >=14.0" }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + "peerDependencies": { + "postcss": "^8.2.15" } }, - "node_modules/wrap-ansi/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/prebuild-install": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.0.tgz", + "integrity": "sha512-CNcMgI1xBypOyGqjp3wOc8AAo1nMhZS3Cwd3iHIxOdAUbb+YxdNuM4Z5iIrZ8RLvOsf3F3bl7b7xGq6DjQoNYA==", "dependencies": { - "color-convert": "^2.0.1" + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^1.0.1", + "node-abi": "^3.3.0", + "npmlog": "^4.0.1", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" }, - "engines": { - "node": ">=8" + "bin": { + "prebuild-install": "bin.js" }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "engines": { + "node": ">=10" } }, - "node_modules/wrap-ansi/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dependencies": { - "color-name": "~1.1.4" - }, + "node_modules/prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==", + "dev": true, "engines": { - "node": ">=7.0.0" + "node": ">= 0.8.0" } }, - "node_modules/wrap-ansi/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" - }, - "node_modules/write-file-atomic": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", - "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", - "dependencies": { - "imurmurhash": "^0.1.4", - "is-typedarray": "^1.0.0", - "signal-exit": "^3.0.2", - "typedarray-to-buffer": "^3.1.5" + "node_modules/prepend-http": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", + "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=", + "engines": { + "node": ">=4" } }, - "node_modules/ws": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.5.tgz", - "integrity": "sha512-BAkMFcAzl8as1G/hArkxOxq3G7pjUqQ3gzYbLL0/5zNkph70e+lCoxBGnm6AW1+/aiNeV4fnKqZ8m4GZewmH2w==", + "node_modules/pretty-bytes": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz", + "integrity": "sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==", + "dev": true, "engines": { - "node": ">=8.3.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" + "node": ">=6" }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/xdg-basedir": { + "node_modules/pretty-error": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz", - "integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==", - "engines": { - "node": ">=8" + "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-4.0.0.tgz", + "integrity": "sha512-AoJ5YMAcXKYxKhuJGdcvse+Voc6v1RgnsR3nWcYU7q4t6z0Q6T86sv5Zq8VIRbOWWFpvdGE83LtdSMNd+6Y0xw==", + "dependencies": { + "lodash": "^4.17.20", + "renderkid": "^3.0.0" } }, - "node_modules/xhr": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/xhr/-/xhr-2.6.0.tgz", - "integrity": "sha512-/eCGLb5rxjx5e3mF1A7s+pLlR6CGyqWN91fv1JgER5mVWg1MZmlhBvy9kjcsOdRk8RrIujotWyJamfyrp+WIcA==", + "node_modules/pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "dev": true, "dependencies": { - "global": "~4.4.0", - "is-function": "^1.0.1", - "parse-headers": "^2.0.0", - "xtend": "^4.0.0" + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "node_modules/xml-js": { - "version": "1.6.11", - "resolved": "https://registry.npmjs.org/xml-js/-/xml-js-1.6.11.tgz", - "integrity": "sha512-7rVi2KMfwfWFl+GpPg6m80IVMWXLRjO+PxTq7V2CDhoGak0wzYzFgUY2m4XJ47OGdXd8eLE8EmwfAmdjw7lC1g==", - "dependencies": { - "sax": "^1.2.4" + "node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "engines": { + "node": ">=10" }, - "bin": { - "xml-js": "bin/cli.js" + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/xml-parse-from-string": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/xml-parse-from-string/-/xml-parse-from-string-1.0.1.tgz", - "integrity": "sha1-qQKekp09vN7RafPG4oI42VpdWig=" + "node_modules/pretty-format/node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "dev": true }, - "node_modules/xml2js": { - "version": "0.4.23", - "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.23.tgz", - "integrity": "sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug==", - "dependencies": { - "sax": ">=0.6.0", - "xmlbuilder": "~11.0.0" - }, + "node_modules/pretty-time": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/pretty-time/-/pretty-time-1.1.0.tgz", + "integrity": "sha512-28iF6xPQrP8Oa6uxE6a1biz+lWeTOAPKggvjB8HAs6nVMKZwf5bG++632Dx614hIWgUPkgivRfG+a8uAXGTIbA==", "engines": { - "node": ">=4.0.0" + "node": ">=4" } }, - "node_modules/xmlbuilder": { - "version": "11.0.1", - "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", - "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", - "engines": { - "node": ">=4.0" + "node_modules/prism-react-renderer": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/prism-react-renderer/-/prism-react-renderer-1.3.1.tgz", + "integrity": "sha512-xUeDMEz074d0zc5y6rxiMp/dlC7C+5IDDlaEUlcBOFE2wddz7hz5PNupb087mPwTt7T9BrFmewObfCBuf/LKwQ==", + "peerDependencies": { + "react": ">=0.14.9" } }, - "node_modules/xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "node_modules/prismjs": { + "version": "1.28.0", + "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.28.0.tgz", + "integrity": "sha512-8aaXdYvl1F7iC7Xm1spqSaY/OJBpYW3v+KJ+F17iYxvdc8sfjW194COK5wVhMZX45tGteiBQgdvD/nhxcRwylw==", "engines": { - "node": ">=0.4" + "node": ">=6" } }, - "node_modules/y18n": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", - "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==" - }, - "node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - }, - "node_modules/yaml": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", - "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "node_modules/process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=", "engines": { - "node": ">= 6" + "node": ">= 0.6.0" } }, - "node_modules/yaml-ast-parser": { - "version": "0.0.43", - "resolved": "https://registry.npmjs.org/yaml-ast-parser/-/yaml-ast-parser-0.0.43.tgz", - "integrity": "sha512-2PTINUwsRqSd+s8XxKaJWQlUuEMHJQyEuh2edBbW8KNJz0SJPwUSD2zRWqezFEdN7IzAgeuYHFUCF7o8zRdZ0A==" + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" }, - "node_modules/yargs": { - "version": "13.3.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", - "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", + "node_modules/promise": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", + "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==", "dependencies": { - "cliui": "^5.0.0", - "find-up": "^3.0.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^3.0.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^13.1.2" + "asap": "~2.0.3" } }, - "node_modules/yargs-parser": { - "version": "13.1.2", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", - "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", + "node_modules/prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", "dependencies": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } - }, - "node_modules/yargs-parser/node_modules/camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + }, "engines": { - "node": ">=6" + "node": ">= 6" } }, - "node_modules/yargs/node_modules/ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "engines": { - "node": ">=6" + "node_modules/prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "dependencies": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" } }, - "node_modules/yargs/node_modules/emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==" + "node_modules/prop-types/node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" }, - "node_modules/yargs/node_modules/find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "node_modules/property-information": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/property-information/-/property-information-5.6.0.tgz", + "integrity": "sha512-YUHSPk+A30YPv+0Qf8i9Mbfe/C0hdPXk1s1jPVToV8pk8BQtpw10ct89Eo7OWkutrwqvT0eicAxlOg3dOAu8JA==", "dependencies": { - "locate-path": "^3.0.0" + "xtend": "^4.0.0" }, - "engines": { - "node": ">=6" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/yargs/node_modules/is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, "engines": { - "node": ">=4" + "node": ">= 0.10" } }, - "node_modules/yargs/node_modules/locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dependencies": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - }, + "node_modules/proxy-addr/node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", "engines": { - "node": ">=6" + "node": ">= 0.10" } }, - "node_modules/yargs/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "node_modules/proxy-from-env": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.0.0.tgz", + "integrity": "sha512-F2JHgJQ1iqwnHDcQjVBsq3n/uoaFL+iPW/eAeL7kVxy/2RrWaN4WroKjjvbsoRtv0ftelNyC01bjRhn/bhcf4A==", + "dev": true + }, + "node_modules/psl": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", + "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==", + "dev": true + }, + "node_modules/public-encrypt": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", + "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "bn.js": "^4.1.0", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "parse-asn1": "^5.0.0", + "randombytes": "^2.0.1", + "safe-buffer": "^5.1.2" } }, - "node_modules/yargs/node_modules/p-locate": { + "node_modules/public-encrypt/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + }, + "node_modules/pump": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", "dependencies": { - "p-limit": "^2.0.0" - }, - "engines": { - "node": ">=6" + "end-of-stream": "^1.1.0", + "once": "^1.3.1" } }, - "node_modules/yargs/node_modules/path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "node_modules/punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", "engines": { - "node": ">=4" + "node": ">=6" } }, - "node_modules/yargs/node_modules/string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "node_modules/pupa": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/pupa/-/pupa-2.1.1.tgz", + "integrity": "sha512-l1jNAspIBSFqbT+y+5FosojNpVpF94nlI+wDUpqP9enwOTfHx9f0gh5nB96vl+6yTpsJsypeNrwfzPrKuHB41A==", "dependencies": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" + "escape-goat": "^2.0.0" }, "engines": { - "node": ">=6" + "node": ">=8" } }, - "node_modules/yargs/node_modules/strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dependencies": { - "ansi-regex": "^4.1.0" - }, + "node_modules/pure-color": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/pure-color/-/pure-color-1.3.0.tgz", + "integrity": "sha1-H+Bk+wrIUfDeYTIKi/eWg2Qi8z4=" + }, + "node_modules/q": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", + "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=", "engines": { - "node": ">=6" + "node": ">=0.6.0", + "teleport": ">=0.2.0" } }, - "node_modules/yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "node_modules/qs": { + "version": "6.10.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz", + "integrity": "sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==", + "dependencies": { + "side-channel": "^1.0.4" + }, "engines": { - "node": ">=10" + "node": ">=0.6" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/zwitch": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-1.0.5.tgz", - "integrity": "sha512-V50KMwwzqJV0NpZIZFwfOD5/lyny3WlSzRiXgA0G7VUnRlqttta1L6UQIHzd6EuBY/cHGfwTIck7w1yH6Q5zUw==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - } - }, - "dependencies": { - "@algolia/autocomplete-core": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@algolia/autocomplete-core/-/autocomplete-core-1.2.2.tgz", - "integrity": "sha512-JOQaURze45qVa8OOFDh+ozj2a/ObSRsVyz6Zd0aiBeej+RSTqrr1hDVpGNbbXYLW26G5ujuc9QIdH+rBHn95nw==", - "requires": { - "@algolia/autocomplete-shared": "1.2.2" + "node_modules/querystring": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.1.tgz", + "integrity": "sha512-wkvS7mL/JMugcup3/rMitHmd9ecIGd2lhFhK9N3UUQ450h66d1r3Y9nvXzQAW1Lq+wyx61k/1pfKS5KuKiyEbg==", + "deprecated": "The querystring API is considered Legacy. new code should use the URLSearchParams API instead.", + "engines": { + "node": ">=0.4.x" } }, - "@algolia/autocomplete-preset-algolia": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@algolia/autocomplete-preset-algolia/-/autocomplete-preset-algolia-1.2.2.tgz", - "integrity": "sha512-AZkh+bAMaJDzMZTelFOXJTJqkp5VPGH8W3n0B+Ggce7DdozlMRsDLguKTCQAkZ0dJ1EbBPyFL5ztL/JImB137Q==", - "requires": { - "@algolia/autocomplete-shared": "1.2.2" + "node_modules/querystring-es3": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", + "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=", + "engines": { + "node": ">=0.4.x" } }, - "@algolia/autocomplete-shared": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@algolia/autocomplete-shared/-/autocomplete-shared-1.2.2.tgz", - "integrity": "sha512-mLTl7d2C1xVVazHt/bqh9EE/u2lbp5YOxLDdcjILXmUqOs5HH1D4SuySblXaQG1uf28FhTqMGp35qE5wJQnqAw==" - }, - "@algolia/cache-browser-local-storage": { - "version": "4.10.5", - "resolved": "https://registry.npmjs.org/@algolia/cache-browser-local-storage/-/cache-browser-local-storage-4.10.5.tgz", - "integrity": "sha512-cfX2rEKOtuuljcGI5DMDHClwZHdDqd2nT2Ohsc8aHtBiz6bUxKVyIqxr2gaC6tU8AgPtrTVBzcxCA+UavXpKww==", - "requires": { - "@algolia/cache-common": "4.10.5" + "node_modules/queue": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/queue/-/queue-6.0.2.tgz", + "integrity": "sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA==", + "dependencies": { + "inherits": "~2.0.3" } }, - "@algolia/cache-common": { - "version": "4.10.5", - "resolved": "https://registry.npmjs.org/@algolia/cache-common/-/cache-common-4.10.5.tgz", - "integrity": "sha512-1mClwdmTHll+OnHkG+yeRoFM17kSxDs4qXkjf6rNZhoZGXDvfYLy3YcZ1FX4Kyz0DJv8aroq5RYGBDsWkHj6Tw==" - }, - "@algolia/cache-in-memory": { - "version": "4.10.5", - "resolved": "https://registry.npmjs.org/@algolia/cache-in-memory/-/cache-in-memory-4.10.5.tgz", - "integrity": "sha512-+ciQnfIGi5wjMk02XhEY8fmy2pzy+oY1nIIfu8LBOglaSipCRAtjk6WhHc7/KIbXPiYzIwuDbM2K1+YOwSGjwA==", - "requires": { - "@algolia/cache-common": "4.10.5" - } + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] }, - "@algolia/client-account": { - "version": "4.10.5", - "resolved": "https://registry.npmjs.org/@algolia/client-account/-/client-account-4.10.5.tgz", - "integrity": "sha512-I9UkSS2glXm7RBZYZIALjBMmXSQbw/fI/djPcBHxiwXIheNIlqIFl2SNPkvihpPF979BSkzjqdJNRPhE1vku3Q==", - "requires": { - "@algolia/client-common": "4.10.5", - "@algolia/client-search": "4.10.5", - "@algolia/transporter": "4.10.5" + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dependencies": { + "safe-buffer": "^5.1.0" } }, - "@algolia/client-analytics": { - "version": "4.10.5", - "resolved": "https://registry.npmjs.org/@algolia/client-analytics/-/client-analytics-4.10.5.tgz", - "integrity": "sha512-h2owwJSkovPxzc+xIsjY1pMl0gj+jdVwP9rcnGjlaTY2fqHbSLrR9yvGyyr6305LvTppxsQnfAbRdE/5Z3eFxw==", - "requires": { - "@algolia/client-common": "4.10.5", - "@algolia/client-search": "4.10.5", - "@algolia/requester-common": "4.10.5", - "@algolia/transporter": "4.10.5" + "node_modules/randomfill": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", + "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", + "dependencies": { + "randombytes": "^2.0.5", + "safe-buffer": "^5.1.0" } }, - "@algolia/client-common": { - "version": "4.10.5", - "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-4.10.5.tgz", - "integrity": "sha512-21FAvIai5qm8DVmZHm2Gp4LssQ/a0nWwMchAx+1hIRj1TX7OcdW6oZDPyZ8asQdvTtK7rStQrRnD8a95SCUnzA==", - "requires": { - "@algolia/requester-common": "4.10.5", - "@algolia/transporter": "4.10.5" + "node_modules/range-parser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", + "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=", + "engines": { + "node": ">= 0.6" } }, - "@algolia/client-personalization": { - "version": "4.10.5", - "resolved": "https://registry.npmjs.org/@algolia/client-personalization/-/client-personalization-4.10.5.tgz", - "integrity": "sha512-nH+IyFKBi8tCyzGOanJTbXC5t4dspSovX3+ABfmwKWUYllYzmiQNFUadpb3qo+MLA3jFx5IwBesjneN6dD5o3w==", - "requires": { - "@algolia/client-common": "4.10.5", - "@algolia/requester-common": "4.10.5", - "@algolia/transporter": "4.10.5" + "node_modules/raw-body": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", + "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" } }, - "@algolia/client-search": { - "version": "4.10.5", - "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-4.10.5.tgz", - "integrity": "sha512-1eQFMz9uodrc5OM+9HeT+hHcfR1E1AsgFWXwyJ9Q3xejA2c1c4eObGgOgC9ZoshuHHdptaTN1m3rexqAxXRDBg==", - "requires": { - "@algolia/client-common": "4.10.5", - "@algolia/requester-common": "4.10.5", - "@algolia/transporter": "4.10.5" + "node_modules/raw-body/node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "engines": { + "node": ">= 0.8" } }, - "@algolia/logger-common": { - "version": "4.10.5", - "resolved": "https://registry.npmjs.org/@algolia/logger-common/-/logger-common-4.10.5.tgz", - "integrity": "sha512-gRJo9zt1UYP4k3woEmZm4iuEBIQd/FrArIsjzsL/b+ihNoOqIxZKTSuGFU4UUZOEhvmxDReiA4gzvQXG+TMTmA==" - }, - "@algolia/logger-console": { - "version": "4.10.5", - "resolved": "https://registry.npmjs.org/@algolia/logger-console/-/logger-console-4.10.5.tgz", - "integrity": "sha512-4WfIbn4253EDU12u9UiYvz+QTvAXDv39mKNg9xSoMCjKE5szcQxfcSczw2byc6pYhahOJ9PmxPBfs1doqsdTKQ==", - "requires": { - "@algolia/logger-common": "4.10.5" + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" } }, - "@algolia/requester-browser-xhr": { - "version": "4.10.5", - "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-4.10.5.tgz", - "integrity": "sha512-53/MURQEqtK+bGdfq4ITSPwTh5hnADU99qzvpAINGQveUFNSFGERipJxHjTJjIrjFz3vxj5kKwjtxDnU6ygO9g==", - "requires": { - "@algolia/requester-common": "4.10.5" + "node_modules/rc/node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "engines": { + "node": ">=0.10.0" } }, - "@algolia/requester-common": { - "version": "4.10.5", - "resolved": "https://registry.npmjs.org/@algolia/requester-common/-/requester-common-4.10.5.tgz", - "integrity": "sha512-UkVa1Oyuj6NPiAEt5ZvrbVopEv1m/mKqjs40KLB+dvfZnNcj+9Fry4Oxnt15HMy/HLORXsx4UwcthAvBuOXE9Q==" - }, - "@algolia/requester-node-http": { - "version": "4.10.5", - "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-4.10.5.tgz", - "integrity": "sha512-aNEKVKXL4fiiC+bS7yJwAHdxln81ieBwY3tsMCtM4zF9f5KwCzY2OtN4WKEZa5AAADVcghSAUdyjs4AcGUlO5w==", - "requires": { - "@algolia/requester-common": "4.10.5" + "node_modules/react": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react/-/react-17.0.2.tgz", + "integrity": "sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA==", + "dependencies": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1" + }, + "engines": { + "node": ">=0.10.0" } }, - "@algolia/transporter": { - "version": "4.10.5", - "resolved": "https://registry.npmjs.org/@algolia/transporter/-/transporter-4.10.5.tgz", - "integrity": "sha512-F8DLkmIlvCoMwSCZA3FKHtmdjH3o5clbt0pi2ktFStVNpC6ZDmY307HcK619bKP5xW6h8sVJhcvrLB775D2cyA==", - "requires": { - "@algolia/cache-common": "4.10.5", - "@algolia/logger-common": "4.10.5", - "@algolia/requester-common": "4.10.5" + "node_modules/react-base16-styling": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/react-base16-styling/-/react-base16-styling-0.6.0.tgz", + "integrity": "sha1-7yFW1mz0E5aVyKFniGy2nqZgeSw=", + "dependencies": { + "base16": "^1.0.0", + "lodash.curry": "^4.0.1", + "lodash.flow": "^3.3.0", + "pure-color": "^1.2.0" } }, - "@babel/code-frame": { - "version": "7.15.8", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.15.8.tgz", - "integrity": "sha512-2IAnmn8zbvC/jKYhq5Ki9I+DwjlrtMPUCH/CpHvqI4dNnlwHwsxoIhlc8WcYY5LSYknXQtAlFYuHfqAFCvQ4Wg==", - "requires": { - "@babel/highlight": "^7.14.5" + "node_modules/react-dev-utils": { + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-12.0.1.tgz", + "integrity": "sha512-84Ivxmr17KjUupyqzFode6xKhjwuEJDROWKJy/BthkL7Wn6NJ8h4WE6k/exAv6ImS+0oZLRRW5j/aINMHyeGeQ==", + "dependencies": { + "@babel/code-frame": "^7.16.0", + "address": "^1.1.2", + "browserslist": "^4.18.1", + "chalk": "^4.1.2", + "cross-spawn": "^7.0.3", + "detect-port-alt": "^1.1.6", + "escape-string-regexp": "^4.0.0", + "filesize": "^8.0.6", + "find-up": "^5.0.0", + "fork-ts-checker-webpack-plugin": "^6.5.0", + "global-modules": "^2.0.0", + "globby": "^11.0.4", + "gzip-size": "^6.0.0", + "immer": "^9.0.7", + "is-root": "^2.1.0", + "loader-utils": "^3.2.0", + "open": "^8.4.0", + "pkg-up": "^3.1.0", + "prompts": "^2.4.2", + "react-error-overlay": "^6.0.11", + "recursive-readdir": "^2.2.2", + "shell-quote": "^1.7.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "engines": { + "node": ">=14" } }, - "@babel/compat-data": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.15.0.tgz", - "integrity": "sha512-0NqAC1IJE0S0+lL1SWFMxMkz1pKCNCjI4tr2Zx4LJSXxCLAdr6KyArnY+sno5m3yH9g737ygOyPABDsnXkpxiA==" - }, - "@babel/core": { - "version": "7.15.8", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.15.8.tgz", - "integrity": "sha512-3UG9dsxvYBMYwRv+gS41WKHno4K60/9GPy1CJaH6xy3Elq8CTtvtjT5R5jmNhXfCYLX2mTw+7/aq5ak/gOE0og==", - "requires": { - "@babel/code-frame": "^7.15.8", - "@babel/generator": "^7.15.8", - "@babel/helper-compilation-targets": "^7.15.4", - "@babel/helper-module-transforms": "^7.15.8", - "@babel/helpers": "^7.15.4", - "@babel/parser": "^7.15.8", - "@babel/template": "^7.15.4", - "@babel/traverse": "^7.15.4", - "@babel/types": "^7.15.6", - "convert-source-map": "^1.7.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.1.2", - "semver": "^6.3.0", - "source-map": "^0.5.0" - }, + "node_modules/react-dev-utils/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" - } + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "@babel/generator": { - "version": "7.15.8", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.15.8.tgz", - "integrity": "sha512-ECmAKstXbp1cvpTTZciZCgfOt6iN64lR0d+euv3UZisU5awfRawOvg07Utn/qBGuH4bRIEZKrA/4LzZyXhZr8g==", - "requires": { - "@babel/types": "^7.15.6", - "jsesc": "^2.5.1", - "source-map": "^0.5.0" + "node_modules/react-dev-utils/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "@babel/helper-annotate-as-pure": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.15.4.tgz", - "integrity": "sha512-QwrtdNvUNsPCj2lfNQacsGSQvGX8ee1ttrBrcozUP2Sv/jylewBP/8QFe6ZkBsC8T/GYWonNAWJV4aRR9AL2DA==", - "requires": { - "@babel/types": "^7.15.4" + "node_modules/react-dev-utils/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" } }, - "@babel/helper-builder-binary-assignment-operator-visitor": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.15.4.tgz", - "integrity": "sha512-P8o7JP2Mzi0SdC6eWr1zF+AEYvrsZa7GSY1lTayjF5XJhVH0kjLYUZPvTMflP7tBgZoe9gIhTa60QwFpqh/E0Q==", - "requires": { - "@babel/helper-explode-assignable-expression": "^7.15.4", - "@babel/types": "^7.15.4" - } + "node_modules/react-dev-utils/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, - "@babel/helper-compilation-targets": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.15.4.tgz", - "integrity": "sha512-rMWPCirulnPSe4d+gwdWXLfAXTTBj8M3guAf5xFQJ0nvFY7tfNAFnWdqaHegHlgDZOCT4qvhF3BYlSJag8yhqQ==", - "requires": { - "@babel/compat-data": "^7.15.0", - "@babel/helper-validator-option": "^7.14.5", - "browserslist": "^4.16.6", - "semver": "^6.3.0" + "node_modules/react-dev-utils/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "engines": { + "node": ">=10" }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/react-dev-utils/node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" - } + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "@babel/helper-create-class-features-plugin": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.15.4.tgz", - "integrity": "sha512-7ZmzFi+DwJx6A7mHRwbuucEYpyBwmh2Ca0RvI6z2+WLZYCqV0JOaLb+u0zbtmDicebgKBZgqbYfLaKNqSgv5Pw==", - "requires": { - "@babel/helper-annotate-as-pure": "^7.15.4", - "@babel/helper-function-name": "^7.15.4", - "@babel/helper-member-expression-to-functions": "^7.15.4", - "@babel/helper-optimise-call-expression": "^7.15.4", - "@babel/helper-replace-supers": "^7.15.4", - "@babel/helper-split-export-declaration": "^7.15.4" + "node_modules/react-dev-utils/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "engines": { + "node": ">=8" } }, - "@babel/helper-create-regexp-features-plugin": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.14.5.tgz", - "integrity": "sha512-TLawwqpOErY2HhWbGJ2nZT5wSkR192QpN+nBg1THfBfftrlvOh+WbhrxXCH4q4xJ9Gl16BGPR/48JA+Ryiho/A==", - "requires": { - "@babel/helper-annotate-as-pure": "^7.14.5", - "regexpu-core": "^4.7.1" + "node_modules/react-dev-utils/node_modules/loader-utils": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-3.2.0.tgz", + "integrity": "sha512-HVl9ZqccQihZ7JM85dco1MvO9G+ONvxoGa9rkhzFsneGLKSUg1gJf9bWzhRhcvm2qChhWpebQhP44qxjKIUCaQ==", + "engines": { + "node": ">= 12.13.0" } }, - "@babel/helper-define-polyfill-provider": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.2.3.tgz", - "integrity": "sha512-RH3QDAfRMzj7+0Nqu5oqgO5q9mFtQEVvCRsi8qCEfzLR9p2BHfn5FzhSB2oj1fF7I2+DcTORkYaQ6aTR9Cofew==", - "requires": { - "@babel/helper-compilation-targets": "^7.13.0", - "@babel/helper-module-imports": "^7.12.13", - "@babel/helper-plugin-utils": "^7.13.0", - "@babel/traverse": "^7.13.0", - "debug": "^4.1.1", - "lodash.debounce": "^4.0.8", - "resolve": "^1.14.2", - "semver": "^6.1.2" - }, + "node_modules/react-dev-utils/node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" - } + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "@babel/helper-explode-assignable-expression": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.15.4.tgz", - "integrity": "sha512-J14f/vq8+hdC2KoWLIQSsGrC9EFBKE4NFts8pfMpymfApds+fPqR30AOUWc4tyr56h9l/GA1Sxv2q3dLZWbQ/g==", - "requires": { - "@babel/types": "^7.15.4" + "node_modules/react-dev-utils/node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "@babel/helper-function-name": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.15.4.tgz", - "integrity": "sha512-Z91cOMM4DseLIGOnog+Z8OI6YseR9bua+HpvLAQ2XayUGU+neTtX+97caALaLdyu53I/fjhbeCnWnRH1O3jFOw==", - "requires": { - "@babel/helper-get-function-arity": "^7.15.4", - "@babel/template": "^7.15.4", - "@babel/types": "^7.15.4" + "node_modules/react-dev-utils/node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "@babel/helper-get-function-arity": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.15.4.tgz", - "integrity": "sha512-1/AlxSF92CmGZzHnC515hm4SirTxtpDnLEJ0UyEMgTMZN+6bxXKg04dKhiRx5Enel+SUA1G1t5Ed/yQia0efrA==", - "requires": { - "@babel/types": "^7.15.4" + "node_modules/react-dev-utils/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" } }, - "@babel/helper-hoist-variables": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.15.4.tgz", - "integrity": "sha512-VTy085egb3jUGVK9ycIxQiPbquesq0HUQ+tPO0uv5mPEBZipk+5FkRKiWq5apuyTE9FUrjENB0rCf8y+n+UuhA==", - "requires": { - "@babel/types": "^7.15.4" + "node_modules/react-dom": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-17.0.2.tgz", + "integrity": "sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA==", + "dependencies": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1", + "scheduler": "^0.20.2" + }, + "peerDependencies": { + "react": "17.0.2" } }, - "@babel/helper-member-expression-to-functions": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.15.4.tgz", - "integrity": "sha512-cokOMkxC/BTyNP1AlY25HuBWM32iCEsLPI4BHDpJCHHm1FU2E7dKWWIXJgQgSFiu4lp8q3bL1BIKwqkSUviqtA==", - "requires": { - "@babel/types": "^7.15.4" - } + "node_modules/react-error-overlay": { + "version": "6.0.11", + "resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.11.tgz", + "integrity": "sha512-/6UZ2qgEyH2aqzYZgQPxEnz33NJ2gNsnHA2o5+o4wW9bLM/JYQitNP9xPhsXwC08hMMovfGe/8retsdDsczPRg==" }, - "@babel/helper-module-imports": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.15.4.tgz", - "integrity": "sha512-jeAHZbzUwdW/xHgHQ3QmWR4Jg6j15q4w/gCfwZvtqOxoo5DKtLHk8Bsf4c5RZRC7NmLEs+ohkdq8jFefuvIxAA==", - "requires": { - "@babel/types": "^7.15.4" - } + "node_modules/react-fast-compare": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.0.tgz", + "integrity": "sha512-rtGImPZ0YyLrscKI9xTpV8psd6I8VAtjKCzQDlzyDvqJA8XOW78TXYQwNRNd8g8JZnDu8q9Fu/1v4HPAVwVdHA==" }, - "@babel/helper-module-transforms": { - "version": "7.15.8", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.15.8.tgz", - "integrity": "sha512-DfAfA6PfpG8t4S6npwzLvTUpp0sS7JrcuaMiy1Y5645laRJIp/LiLGIBbQKaXSInK8tiGNI7FL7L8UvB8gdUZg==", - "requires": { - "@babel/helper-module-imports": "^7.15.4", - "@babel/helper-replace-supers": "^7.15.4", - "@babel/helper-simple-access": "^7.15.4", - "@babel/helper-split-export-declaration": "^7.15.4", - "@babel/helper-validator-identifier": "^7.15.7", - "@babel/template": "^7.15.4", - "@babel/traverse": "^7.15.4", - "@babel/types": "^7.15.6" + "node_modules/react-helmet-async": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/react-helmet-async/-/react-helmet-async-1.3.0.tgz", + "integrity": "sha512-9jZ57/dAn9t3q6hneQS0wukqC2ENOBgMNVEhb/ZG9ZSxUetzVIw4iAmEU38IaVg3QGYauQPhSeUTuIUtFglWpg==", + "dependencies": { + "@babel/runtime": "^7.12.5", + "invariant": "^2.2.4", + "prop-types": "^15.7.2", + "react-fast-compare": "^3.2.0", + "shallowequal": "^1.1.0" + }, + "peerDependencies": { + "react": "^16.6.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.6.0 || ^17.0.0 || ^18.0.0" } }, - "@babel/helper-optimise-call-expression": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.15.4.tgz", - "integrity": "sha512-E/z9rfbAOt1vDW1DR7k4SzhzotVV5+qMciWV6LaG1g4jeFrkDlJedjtV4h0i4Q/ITnUu+Pk08M7fczsB9GXBDw==", - "requires": { - "@babel/types": "^7.15.4" - } - }, - "@babel/helper-plugin-utils": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.14.5.tgz", - "integrity": "sha512-/37qQCE3K0vvZKwoK4XU/irIJQdIfCJuhU5eKnNxpFDsOkgFaUAwbv+RYw6eYgsC0E4hS7r5KqGULUogqui0fQ==" - }, - "@babel/helper-remap-async-to-generator": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.15.4.tgz", - "integrity": "sha512-v53MxgvMK/HCwckJ1bZrq6dNKlmwlyRNYM6ypaRTdXWGOE2c1/SCa6dL/HimhPulGhZKw9W0QhREM583F/t0vQ==", - "requires": { - "@babel/helper-annotate-as-pure": "^7.15.4", - "@babel/helper-wrap-function": "^7.15.4", - "@babel/types": "^7.15.4" - } + "node_modules/react-is": { + "version": "18.1.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.1.0.tgz", + "integrity": "sha512-Fl7FuabXsJnV5Q1qIOQwx/sagGF18kogb4gpfcG4gjLBWO0WDiiz1ko/ExayuxE7InyQkBLkxRFG5oxY6Uu3Kg==" }, - "@babel/helper-replace-supers": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.15.4.tgz", - "integrity": "sha512-/ztT6khaXF37MS47fufrKvIsiQkx1LBRvSJNzRqmbyeZnTwU9qBxXYLaaT/6KaxfKhjs2Wy8kG8ZdsFUuWBjzw==", - "requires": { - "@babel/helper-member-expression-to-functions": "^7.15.4", - "@babel/helper-optimise-call-expression": "^7.15.4", - "@babel/traverse": "^7.15.4", - "@babel/types": "^7.15.4" + "node_modules/react-json-view": { + "version": "1.21.3", + "resolved": "https://registry.npmjs.org/react-json-view/-/react-json-view-1.21.3.tgz", + "integrity": "sha512-13p8IREj9/x/Ye4WI/JpjhoIwuzEgUAtgJZNBJckfzJt1qyh24BdTm6UQNGnyTq9dapQdrqvquZTo3dz1X6Cjw==", + "dependencies": { + "flux": "^4.0.1", + "react-base16-styling": "^0.6.0", + "react-lifecycles-compat": "^3.0.4", + "react-textarea-autosize": "^8.3.2" + }, + "peerDependencies": { + "react": "^17.0.0 || ^16.3.0 || ^15.5.4", + "react-dom": "^17.0.0 || ^16.3.0 || ^15.5.4" } }, - "@babel/helper-simple-access": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.15.4.tgz", - "integrity": "sha512-UzazrDoIVOZZcTeHHEPYrr1MvTR/K+wgLg6MY6e1CJyaRhbibftF6fR2KU2sFRtI/nERUZR9fBd6aKgBlIBaPg==", - "requires": { - "@babel/types": "^7.15.4" - } + "node_modules/react-lifecycles-compat": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz", + "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==" }, - "@babel/helper-skip-transparent-expression-wrappers": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.15.4.tgz", - "integrity": "sha512-BMRLsdh+D1/aap19TycS4eD1qELGrCBJwzaY9IE8LrpJtJb+H7rQkPIdsfgnMtLBA6DJls7X9z93Z4U8h7xw0A==", - "requires": { - "@babel/types": "^7.15.4" + "node_modules/react-loadable": { + "name": "@docusaurus/react-loadable", + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/@docusaurus/react-loadable/-/react-loadable-5.5.2.tgz", + "integrity": "sha512-A3dYjdBGuy0IGT+wyLIGIKLRE+sAk1iNk0f1HjNDysO7u8lhL4N3VEm+FAubmJbAztn94F7MxBTPmnixbiyFdQ==", + "dependencies": { + "@types/react": "*", + "prop-types": "^15.6.2" } }, - "@babel/helper-split-export-declaration": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.15.4.tgz", - "integrity": "sha512-HsFqhLDZ08DxCpBdEVtKmywj6PQbwnF6HHybur0MAnkAKnlS6uHkwnmRIkElB2Owpfb4xL4NwDmDLFubueDXsw==", - "requires": { - "@babel/types": "^7.15.4" + "node_modules/react-loadable-ssr-addon-v5-slorber": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/react-loadable-ssr-addon-v5-slorber/-/react-loadable-ssr-addon-v5-slorber-1.0.1.tgz", + "integrity": "sha512-lq3Lyw1lGku8zUEJPDxsNm1AfYHBrO9Y1+olAYwpUJ2IGFBskM0DMKok97A6LWUpHm+o7IvQBOWu9MLenp9Z+A==", + "dependencies": { + "@babel/runtime": "^7.10.3" + }, + "engines": { + "node": ">=10.13.0" + }, + "peerDependencies": { + "react-loadable": "*", + "webpack": ">=4.41.1 || 5.x" } }, - "@babel/helper-validator-identifier": { - "version": "7.15.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.15.7.tgz", - "integrity": "sha512-K4JvCtQqad9OY2+yTU8w+E82ywk/fe+ELNlt1G8z3bVGlZfn/hOcQQsUhGhW/N+tb3fxK800wLtKOE/aM0m72w==" - }, - "@babel/helper-validator-option": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.14.5.tgz", - "integrity": "sha512-OX8D5eeX4XwcroVW45NMvoYaIuFI+GQpA2a8Gi+X/U/cDUIRsV37qQfF905F0htTRCREQIB4KqPeaveRJUl3Ow==" - }, - "@babel/helper-wrap-function": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.15.4.tgz", - "integrity": "sha512-Y2o+H/hRV5W8QhIfTpRIBwl57y8PrZt6JM3V8FOo5qarjshHItyH5lXlpMfBfmBefOqSCpKZs/6Dxqp0E/U+uw==", - "requires": { - "@babel/helper-function-name": "^7.15.4", - "@babel/template": "^7.15.4", - "@babel/traverse": "^7.15.4", - "@babel/types": "^7.15.4" + "node_modules/react-router": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-5.3.1.tgz", + "integrity": "sha512-v+zwjqb7bakqgF+wMVKlAPTca/cEmPOvQ9zt7gpSNyPXau1+0qvuYZ5BWzzNDP1y6s15zDwgb9rPN63+SIniRQ==", + "dependencies": { + "@babel/runtime": "^7.12.13", + "history": "^4.9.0", + "hoist-non-react-statics": "^3.1.0", + "loose-envify": "^1.3.1", + "mini-create-react-context": "^0.4.0", + "path-to-regexp": "^1.7.0", + "prop-types": "^15.6.2", + "react-is": "^16.6.0", + "tiny-invariant": "^1.0.2", + "tiny-warning": "^1.0.0" + }, + "peerDependencies": { + "react": ">=15" } }, - "@babel/helpers": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.15.4.tgz", - "integrity": "sha512-V45u6dqEJ3w2rlryYYXf6i9rQ5YMNu4FLS6ngs8ikblhu2VdR1AqAd6aJjBzmf2Qzh6KOLqKHxEN9+TFbAkAVQ==", - "requires": { - "@babel/template": "^7.15.4", - "@babel/traverse": "^7.15.4", - "@babel/types": "^7.15.4" + "node_modules/react-router-config": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/react-router-config/-/react-router-config-5.1.1.tgz", + "integrity": "sha512-DuanZjaD8mQp1ppHjgnnUnyOlqYXZVjnov/JzFhjLEwd3Z4dYjMSnqrEzzGThH47vpCOqPPwJM2FtthLeJ8Pbg==", + "dependencies": { + "@babel/runtime": "^7.1.2" + }, + "peerDependencies": { + "react": ">=15", + "react-router": ">=5" } }, - "@babel/highlight": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.5.tgz", - "integrity": "sha512-qf9u2WFWVV0MppaL877j2dBtQIDgmidgjGk5VIMw3OadXvYaXn66U1BFlH2t4+t3i+8PhedppRv+i40ABzd+gg==", - "requires": { - "@babel/helper-validator-identifier": "^7.14.5", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - }, + "node_modules/react-router-dom": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-5.3.1.tgz", + "integrity": "sha512-f0pj/gMAbv9e8gahTmCEY20oFhxhrmHwYeIwH5EO5xu0qme+wXtsdB8YfUOAZzUz4VaXmb58m3ceiLtjMhqYmQ==", "dependencies": { - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - } + "@babel/runtime": "^7.12.13", + "history": "^4.9.0", + "loose-envify": "^1.3.1", + "prop-types": "^15.6.2", + "react-router": "5.3.1", + "tiny-invariant": "^1.0.2", + "tiny-warning": "^1.0.0" + }, + "peerDependencies": { + "react": ">=15" } }, - "@babel/parser": { - "version": "7.15.8", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.15.8.tgz", - "integrity": "sha512-BRYa3wcQnjS/nqI8Ac94pYYpJfojHVvVXJ97+IDCImX4Jc8W8Xv1+47enbruk+q1etOpsQNwnfFcNGw+gtPGxA==" + "node_modules/react-router/node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" }, - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.15.4.tgz", - "integrity": "sha512-eBnpsl9tlhPhpI10kU06JHnrYXwg3+V6CaP2idsCXNef0aeslpqyITXQ74Vfk5uHgY7IG7XP0yIH8b42KSzHog==", - "requires": { - "@babel/helper-plugin-utils": "^7.14.5", - "@babel/helper-skip-transparent-expression-wrappers": "^7.15.4", - "@babel/plugin-proposal-optional-chaining": "^7.14.5" + "node_modules/react-tabs": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/react-tabs/-/react-tabs-3.2.3.tgz", + "integrity": "sha512-jx325RhRVnS9DdFbeF511z0T0WEqEoMl1uCE3LoZ6VaZZm7ytatxbum0B8bCTmaiV0KsU+4TtLGTGevCic7SWg==", + "dependencies": { + "clsx": "^1.1.0", + "prop-types": "^15.5.0" + }, + "peerDependencies": { + "react": "^16.3.0 || ^17.0.0-0" } }, - "@babel/plugin-proposal-async-generator-functions": { - "version": "7.15.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.15.8.tgz", - "integrity": "sha512-2Z5F2R2ibINTc63mY7FLqGfEbmofrHU9FitJW1Q7aPaKFhiPvSq6QEt/BoWN5oME3GVyjcRuNNSRbb9LC0CSWA==", - "requires": { - "@babel/helper-plugin-utils": "^7.14.5", - "@babel/helper-remap-async-to-generator": "^7.15.4", - "@babel/plugin-syntax-async-generators": "^7.8.4" + "node_modules/react-textarea-autosize": { + "version": "8.3.3", + "resolved": "https://registry.npmjs.org/react-textarea-autosize/-/react-textarea-autosize-8.3.3.tgz", + "integrity": "sha512-2XlHXK2TDxS6vbQaoPbMOfQ8GK7+irc2fVK6QFIcC8GOnH3zI/v481n+j1L0WaPVvKxwesnY93fEfH++sus2rQ==", + "dependencies": { + "@babel/runtime": "^7.10.2", + "use-composed-ref": "^1.0.0", + "use-latest": "^1.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0" } }, - "@babel/plugin-proposal-class-properties": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.14.5.tgz", - "integrity": "sha512-q/PLpv5Ko4dVc1LYMpCY7RVAAO4uk55qPwrIuJ5QJ8c6cVuAmhu7I/49JOppXL6gXf7ZHzpRVEUZdYoPLM04Gg==", - "requires": { - "@babel/helper-create-class-features-plugin": "^7.14.5", - "@babel/helper-plugin-utils": "^7.14.5" + "node_modules/react-tooltip": { + "version": "4.2.21", + "resolved": "https://registry.npmjs.org/react-tooltip/-/react-tooltip-4.2.21.tgz", + "integrity": "sha512-zSLprMymBDowknr0KVDiJ05IjZn9mQhhg4PRsqln0OZtURAJ1snt1xi5daZfagsh6vfsziZrc9pErPTDY1ACig==", + "dependencies": { + "prop-types": "^15.7.2", + "uuid": "^7.0.3" + }, + "engines": { + "npm": ">=6.13" + }, + "peerDependencies": { + "react": ">=16.0.0", + "react-dom": ">=16.0.0" } }, - "@babel/plugin-proposal-class-static-block": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.15.4.tgz", - "integrity": "sha512-M682XWrrLNk3chXCjoPUQWOyYsB93B9z3mRyjtqqYJWDf2mfCdIYgDrA11cgNVhAQieaq6F2fn2f3wI0U4aTjA==", - "requires": { - "@babel/helper-create-class-features-plugin": "^7.15.4", - "@babel/helper-plugin-utils": "^7.14.5", - "@babel/plugin-syntax-class-static-block": "^7.14.5" + "node_modules/react-waypoint": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/react-waypoint/-/react-waypoint-10.1.0.tgz", + "integrity": "sha512-wiVF0lTslVm27xHbnvUUADUrcDjrQxAp9lEYGExvcoEBScYbXu3Kt++pLrfj6CqOeeRAL4HcX8aANVLSn6bK0Q==", + "dependencies": { + "@babel/runtime": "^7.12.5", + "consolidated-events": "^1.1.0 || ^2.0.0", + "prop-types": "^15.0.0", + "react-is": "^17.0.1" + }, + "peerDependencies": { + "react": "^15.3.0 || ^16.0.0 || ^17.0.0" } }, - "@babel/plugin-proposal-dynamic-import": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.14.5.tgz", - "integrity": "sha512-ExjiNYc3HDN5PXJx+bwC50GIx/KKanX2HiggnIUAYedbARdImiCU4RhhHfdf0Kd7JNXGpsBBBCOm+bBVy3Gb0g==", - "requires": { - "@babel/helper-plugin-utils": "^7.14.5", - "@babel/plugin-syntax-dynamic-import": "^7.8.3" - } + "node_modules/react-waypoint/node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" }, - "@babel/plugin-proposal-export-namespace-from": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.14.5.tgz", - "integrity": "sha512-g5POA32bXPMmSBu5Dx/iZGLGnKmKPc5AiY7qfZgurzrCYgIztDlHFbznSNCoQuv57YQLnQfaDi7dxCtLDIdXdA==", - "requires": { - "@babel/helper-plugin-utils": "^7.14.5", - "@babel/plugin-syntax-export-namespace-from": "^7.8.3" + "node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" } }, - "@babel/plugin-proposal-json-strings": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.14.5.tgz", - "integrity": "sha512-NSq2fczJYKVRIsUJyNxrVUMhB27zb7N7pOFGQOhBKJrChbGcgEAqyZrmZswkPk18VMurEeJAaICbfm57vUeTbQ==", - "requires": { - "@babel/helper-plugin-utils": "^7.14.5", - "@babel/plugin-syntax-json-strings": "^7.8.3" + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" } }, - "@babel/plugin-proposal-logical-assignment-operators": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.14.5.tgz", - "integrity": "sha512-YGn2AvZAo9TwyhlLvCCWxD90Xq8xJ4aSgaX3G5D/8DW94L8aaT+dS5cSP+Z06+rCJERGSr9GxMBZ601xoc2taw==", - "requires": { - "@babel/helper-plugin-utils": "^7.14.5", - "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" - } + "node_modules/reading-time": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/reading-time/-/reading-time-1.5.0.tgz", + "integrity": "sha512-onYyVhBNr4CmAxFsKS7bz+uTLRakypIe4R+5A824vBSkQy/hB3fZepoVEf8OVAxzLvK+H/jm9TzpI3ETSm64Kg==" }, - "@babel/plugin-proposal-nullish-coalescing-operator": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.14.5.tgz", - "integrity": "sha512-gun/SOnMqjSb98Nkaq2rTKMwervfdAoz6NphdY0vTfuzMfryj+tDGb2n6UkDKwez+Y8PZDhE3D143v6Gepp4Hg==", - "requires": { - "@babel/helper-plugin-utils": "^7.14.5", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" + "node_modules/rechoir": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", + "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", + "dependencies": { + "resolve": "^1.1.6" + }, + "engines": { + "node": ">= 0.10" } }, - "@babel/plugin-proposal-numeric-separator": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.14.5.tgz", - "integrity": "sha512-yiclALKe0vyZRZE0pS6RXgjUOt87GWv6FYa5zqj15PvhOGFO69R5DusPlgK/1K5dVnCtegTiWu9UaBSrLLJJBg==", - "requires": { - "@babel/helper-plugin-utils": "^7.14.5", - "@babel/plugin-syntax-numeric-separator": "^7.10.4" + "node_modules/recursive-readdir": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/recursive-readdir/-/recursive-readdir-2.2.2.tgz", + "integrity": "sha512-nRCcW9Sj7NuZwa2XvH9co8NPeXUBhZP7CRKJtU+cS6PW9FpCIFoI5ib0NT1ZrbNuPoRy0ylyCaUL8Gih4LSyFg==", + "dependencies": { + "minimatch": "3.0.4" + }, + "engines": { + "node": ">=0.10.0" } }, - "@babel/plugin-proposal-object-rest-spread": { - "version": "7.15.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.15.6.tgz", - "integrity": "sha512-qtOHo7A1Vt+O23qEAX+GdBpqaIuD3i9VRrWgCJeq7WO6H2d14EK3q11urj5Te2MAeK97nMiIdRpwd/ST4JFbNg==", - "requires": { - "@babel/compat-data": "^7.15.0", - "@babel/helper-compilation-targets": "^7.15.4", - "@babel/helper-plugin-utils": "^7.14.5", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-transform-parameters": "^7.15.4" + "node_modules/recursive-readdir/node_modules/minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" } }, - "@babel/plugin-proposal-optional-catch-binding": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.14.5.tgz", - "integrity": "sha512-3Oyiixm0ur7bzO5ybNcZFlmVsygSIQgdOa7cTfOYCMY+wEPAYhZAJxi3mixKFCTCKUhQXuCTtQ1MzrpL3WT8ZQ==", - "requires": { - "@babel/helper-plugin-utils": "^7.14.5", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" + "node_modules/redent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", + "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", + "dev": true, + "dependencies": { + "indent-string": "^4.0.0", + "strip-indent": "^3.0.0" + }, + "engines": { + "node": ">=8" } }, - "@babel/plugin-proposal-optional-chaining": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.14.5.tgz", - "integrity": "sha512-ycz+VOzo2UbWNI1rQXxIuMOzrDdHGrI23fRiz/Si2R4kv2XZQ1BK8ccdHwehMKBlcH/joGW/tzrUmo67gbJHlQ==", - "requires": { - "@babel/helper-plugin-utils": "^7.14.5", - "@babel/helper-skip-transparent-expression-wrappers": "^7.14.5", - "@babel/plugin-syntax-optional-chaining": "^7.8.3" - } - }, - "@babel/plugin-proposal-private-methods": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.14.5.tgz", - "integrity": "sha512-838DkdUA1u+QTCplatfq4B7+1lnDa/+QMI89x5WZHBcnNv+47N8QEj2k9I2MUU9xIv8XJ4XvPCviM/Dj7Uwt9g==", - "requires": { - "@babel/helper-create-class-features-plugin": "^7.14.5", - "@babel/helper-plugin-utils": "^7.14.5" + "node_modules/redoc": { + "version": "2.0.0-rc.67", + "resolved": "https://registry.npmjs.org/redoc/-/redoc-2.0.0-rc.67.tgz", + "integrity": "sha512-u6rEKB0LylSisN+mFa3flj7zf+prXDB+G02foqC9BOlcXkUYXHFDZM4L3BTBL/DstyGTgjhe2dA9csAjIVti/g==", + "dependencies": { + "@redocly/openapi-core": "^1.0.0-beta.88", + "@redocly/react-dropdown-aria": "^2.0.11", + "classnames": "^2.3.1", + "decko": "^1.2.0", + "dompurify": "^2.2.8", + "eventemitter3": "^4.0.7", + "json-pointer": "^0.6.2", + "lunr": "^2.3.9", + "mark.js": "^8.11.1", + "marked": "^4.0.10", + "mobx-react": "^7.2.0", + "openapi-sampler": "^1.2.1", + "path-browserify": "^1.0.1", + "perfect-scrollbar": "^1.5.1", + "polished": "^4.1.3", + "prismjs": "^1.27.0", + "prop-types": "^15.7.2", + "react-tabs": "^3.2.2", + "slugify": "~1.4.7", + "stickyfill": "^1.1.1", + "style-loader": "^3.3.1", + "swagger2openapi": "^7.0.6", + "url-template": "^2.0.8" + }, + "engines": { + "node": ">=6.9", + "npm": ">=3.0.0" + }, + "peerDependencies": { + "core-js": "^3.1.4", + "mobx": "^6.0.4", + "react": "^16.8.4 || ^17.0.0", + "react-dom": "^16.8.4 || ^17.0.0", + "styled-components": "^4.1.1 || ^5.1.1" } }, - "@babel/plugin-proposal-private-property-in-object": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.15.4.tgz", - "integrity": "sha512-X0UTixkLf0PCCffxgu5/1RQyGGbgZuKoI+vXP4iSbJSYwPb7hu06omsFGBvQ9lJEvwgrxHdS8B5nbfcd8GyUNA==", - "requires": { - "@babel/helper-annotate-as-pure": "^7.15.4", - "@babel/helper-create-class-features-plugin": "^7.15.4", - "@babel/helper-plugin-utils": "^7.14.5", - "@babel/plugin-syntax-private-property-in-object": "^7.14.5" + "node_modules/redoc/node_modules/slugify": { + "version": "1.4.7", + "resolved": "https://registry.npmjs.org/slugify/-/slugify-1.4.7.tgz", + "integrity": "sha512-tf+h5W1IrjNm/9rKKj0JU2MDMruiopx0jjVA5zCdBtcGjfp0+c5rHw/zADLC3IeKlGHtVbHtpfzvYA0OYT+HKg==", + "engines": { + "node": ">=8.0.0" } }, - "@babel/plugin-proposal-unicode-property-regex": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.14.5.tgz", - "integrity": "sha512-6axIeOU5LnY471KenAB9vI8I5j7NQ2d652hIYwVyRfgaZT5UpiqFKCuVXCDMSrU+3VFafnu2c5m3lrWIlr6A5Q==", - "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.14.5", - "@babel/helper-plugin-utils": "^7.14.5" + "node_modules/redoc/node_modules/style-loader": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-3.3.1.tgz", + "integrity": "sha512-GPcQ+LDJbrcxHORTRes6Jy2sfvK2kS6hpSfI/fXhPt+spVzxF6LJ1dHLN9zIGmVaaP044YKaIatFaufENRiDoQ==", + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" } }, - "@babel/plugin-syntax-async-generators": { - "version": "7.8.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", - "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" + "node_modules/reftools": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/reftools/-/reftools-1.1.9.tgz", + "integrity": "sha512-OVede/NQE13xBQ+ob5CKd5KyeJYU2YInb1bmV4nRoOfquZPkAkxuOXicSe1PvqIuZZ4kD13sPKBbR7UFDmli6w==", + "funding": { + "url": "https://github.com/Mermade/oas-kit?sponsor=1" } }, - "@babel/plugin-syntax-class-properties": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", - "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", - "requires": { - "@babel/helper-plugin-utils": "^7.12.13" - } + "node_modules/regenerate": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", + "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==" }, - "@babel/plugin-syntax-class-static-block": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", - "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", - "requires": { - "@babel/helper-plugin-utils": "^7.14.5" + "node_modules/regenerate-unicode-properties": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.0.1.tgz", + "integrity": "sha512-vn5DU6yg6h8hP/2OkQo3K7uVILvY4iu0oI4t3HFa81UPkhGJwkRwM10JEc3upjdhHjs/k8GJY1sRBhk5sr69Bw==", + "dependencies": { + "regenerate": "^1.4.2" + }, + "engines": { + "node": ">=4" } }, - "@babel/plugin-syntax-dynamic-import": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", - "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } + "node_modules/regenerator-runtime": { + "version": "0.13.9", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz", + "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==" }, - "@babel/plugin-syntax-export-namespace-from": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", - "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", - "requires": { - "@babel/helper-plugin-utils": "^7.8.3" + "node_modules/regenerator-transform": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.0.tgz", + "integrity": "sha512-LsrGtPmbYg19bcPHwdtmXwbW+TqNvtY4riE3P83foeHRroMbH6/2ddFBfab3t7kbzc7v7p4wbkIecHImqt0QNg==", + "dependencies": { + "@babel/runtime": "^7.8.4" } }, - "@babel/plugin-syntax-json-strings": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", - "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" + "node_modules/regexpu-core": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.0.1.tgz", + "integrity": "sha512-CriEZlrKK9VJw/xQGJpQM5rY88BtuL8DM+AEwvcThHilbxiTAy8vq4iJnd2tqq8wLmjbGZzP7ZcKFjbGkmEFrw==", + "dependencies": { + "regenerate": "^1.4.2", + "regenerate-unicode-properties": "^10.0.1", + "regjsgen": "^0.6.0", + "regjsparser": "^0.8.2", + "unicode-match-property-ecmascript": "^2.0.0", + "unicode-match-property-value-ecmascript": "^2.0.0" + }, + "engines": { + "node": ">=4" } }, - "@babel/plugin-syntax-jsx": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.14.5.tgz", - "integrity": "sha512-ohuFIsOMXJnbOMRfX7/w7LocdR6R7whhuRD4ax8IipLcLPlZGJKkBxgHp++U4N/vKyU16/YDQr2f5seajD3jIw==", - "requires": { - "@babel/helper-plugin-utils": "^7.14.5" + "node_modules/registry-auth-token": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.2.1.tgz", + "integrity": "sha512-6gkSb4U6aWJB4SF2ZvLb76yCBjcvufXBqvvEx1HbmKPkutswjW1xNVRY0+daljIYRbogN7O0etYSlbiaEQyMyw==", + "dependencies": { + "rc": "^1.2.8" + }, + "engines": { + "node": ">=6.0.0" } }, - "@babel/plugin-syntax-logical-assignment-operators": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", - "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" + "node_modules/registry-url": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-5.1.0.tgz", + "integrity": "sha512-8acYXXTI0AkQv6RAOjE3vOaIXZkT9wo4LOFbBKYQEEnnMNBpKqdUrI6S4NT0KPIo/WVvJ5tE/X5LF/TQUf0ekw==", + "dependencies": { + "rc": "^1.2.8" + }, + "engines": { + "node": ">=8" } }, - "@babel/plugin-syntax-nullish-coalescing-operator": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", - "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } + "node_modules/regjsgen": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.6.0.tgz", + "integrity": "sha512-ozE883Uigtqj3bx7OhL1KNbCzGyW2NQZPl6Hs09WTvCuZD5sTI4JY58bkbQWa/Y9hxIsvJ3M8Nbf7j54IqeZbA==" }, - "@babel/plugin-syntax-numeric-separator": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", - "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" + "node_modules/regjsparser": { + "version": "0.8.4", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.8.4.tgz", + "integrity": "sha512-J3LABycON/VNEu3abOviqGHuB/LOtOQj8SKmfP9anY5GfAVw/SPjwzSjxGjbZXIxbGfqTHtJw58C2Li/WkStmA==", + "dependencies": { + "jsesc": "~0.5.0" + }, + "bin": { + "regjsparser": "bin/parser" } }, - "@babel/plugin-syntax-object-rest-spread": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", - "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" + "node_modules/regjsparser/node_modules/jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", + "bin": { + "jsesc": "bin/jsesc" } }, - "@babel/plugin-syntax-optional-catch-binding": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", - "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" + "node_modules/rehype-katex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/rehype-katex/-/rehype-katex-5.0.0.tgz", + "integrity": "sha512-ksSuEKCql/IiIadOHiKRMjypva9BLhuwQNascMqaoGLDVd0k2NlE2wMvgZ3rpItzRKCd6vs8s7MFbb8pcR0AEg==", + "dependencies": { + "@types/katex": "^0.11.0", + "hast-util-to-text": "^2.0.0", + "katex": "^0.13.0", + "rehype-parse": "^7.0.0", + "unified": "^9.0.0", + "unist-util-visit": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "@babel/plugin-syntax-optional-chaining": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", - "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" + "node_modules/rehype-katex/node_modules/rehype-parse": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/rehype-parse/-/rehype-parse-7.0.1.tgz", + "integrity": "sha512-fOiR9a9xH+Le19i4fGzIEowAbwG7idy2Jzs4mOrFWBSJ0sNUgy0ev871dwWnbOo371SjgjG4pwzrbgSVrKxecw==", + "dependencies": { + "hast-util-from-parse5": "^6.0.0", + "parse5": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "@babel/plugin-syntax-private-property-in-object": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", - "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", - "requires": { - "@babel/helper-plugin-utils": "^7.14.5" + "node_modules/rehype-parse": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/rehype-parse/-/rehype-parse-6.0.2.tgz", + "integrity": "sha512-0S3CpvpTAgGmnz8kiCyFLGuW5yA4OQhyNTm/nwPopZ7+PI11WnGl1TTWTGv/2hPEe/g2jRLlhVVSsoDH8waRug==", + "dependencies": { + "hast-util-from-parse5": "^5.0.0", + "parse5": "^5.0.0", + "xtend": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "@babel/plugin-syntax-top-level-await": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", - "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", - "requires": { - "@babel/helper-plugin-utils": "^7.14.5" + "node_modules/rehype-parse/node_modules/hast-util-from-parse5": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-5.0.3.tgz", + "integrity": "sha512-gOc8UB99F6eWVWFtM9jUikjN7QkWxB3nY0df5Z0Zq1/Nkwl5V4hAAsl0tmwlgWl/1shlTF8DnNYLO8X6wRV9pA==", + "dependencies": { + "ccount": "^1.0.3", + "hastscript": "^5.0.0", + "property-information": "^5.0.0", + "web-namespaces": "^1.1.2", + "xtend": "^4.0.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "@babel/plugin-syntax-typescript": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.14.5.tgz", - "integrity": "sha512-u6OXzDaIXjEstBRRoBCQ/uKQKlbuaeE5in0RvWdA4pN6AhqxTIwUsnHPU1CFZA/amYObMsuWhYfRl3Ch90HD0Q==", - "requires": { - "@babel/helper-plugin-utils": "^7.14.5" + "node_modules/rehype-parse/node_modules/hastscript": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/hastscript/-/hastscript-5.1.2.tgz", + "integrity": "sha512-WlztFuK+Lrvi3EggsqOkQ52rKbxkXL3RwB6t5lwoa8QLMemoWfBuL43eDrwOamJyR7uKQKdmKYaBH1NZBiIRrQ==", + "dependencies": { + "comma-separated-tokens": "^1.0.0", + "hast-util-parse-selector": "^2.0.0", + "property-information": "^5.0.0", + "space-separated-tokens": "^1.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "@babel/plugin-transform-arrow-functions": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.14.5.tgz", - "integrity": "sha512-KOnO0l4+tD5IfOdi4x8C1XmEIRWUjNRV8wc6K2vz/3e8yAOoZZvsRXRRIF/yo/MAOFb4QjtAw9xSxMXbSMRy8A==", - "requires": { - "@babel/helper-plugin-utils": "^7.14.5" - } + "node_modules/rehype-parse/node_modules/parse5": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.1.tgz", + "integrity": "sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug==" }, - "@babel/plugin-transform-async-to-generator": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.14.5.tgz", - "integrity": "sha512-szkbzQ0mNk0rpu76fzDdqSyPu0MuvpXgC+6rz5rpMb5OIRxdmHfQxrktL8CYolL2d8luMCZTR0DpIMIdL27IjA==", - "requires": { - "@babel/helper-module-imports": "^7.14.5", - "@babel/helper-plugin-utils": "^7.14.5", - "@babel/helper-remap-async-to-generator": "^7.14.5" + "node_modules/relateurl": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", + "integrity": "sha1-VNvzd+UUQKypCkzSdGANP/LYiKk=", + "engines": { + "node": ">= 0.10" } }, - "@babel/plugin-transform-block-scoped-functions": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.14.5.tgz", - "integrity": "sha512-dtqWqdWZ5NqBX3KzsVCWfQI3A53Ft5pWFCT2eCVUftWZgjc5DpDponbIF1+c+7cSGk2wN0YK7HGL/ezfRbpKBQ==", - "requires": { - "@babel/helper-plugin-utils": "^7.14.5" + "node_modules/remark-admonitions": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/remark-admonitions/-/remark-admonitions-1.2.1.tgz", + "integrity": "sha512-Ji6p68VDvD+H1oS95Fdx9Ar5WA2wcDA4kwrrhVU7fGctC6+d3uiMICu7w7/2Xld+lnU7/gi+432+rRbup5S8ow==", + "dependencies": { + "rehype-parse": "^6.0.2", + "unified": "^8.4.2", + "unist-util-visit": "^2.0.1" } }, - "@babel/plugin-transform-block-scoping": { - "version": "7.15.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.15.3.tgz", - "integrity": "sha512-nBAzfZwZb4DkaGtOes1Up1nOAp9TDRRFw4XBzBBSG9QK7KVFmYzgj9o9sbPv7TX5ofL4Auq4wZnxCoPnI/lz2Q==", - "requires": { - "@babel/helper-plugin-utils": "^7.14.5" + "node_modules/remark-admonitions/node_modules/unified": { + "version": "8.4.2", + "resolved": "https://registry.npmjs.org/unified/-/unified-8.4.2.tgz", + "integrity": "sha512-JCrmN13jI4+h9UAyKEoGcDZV+i1E7BLFuG7OsaDvTXI5P0qhHX+vZO/kOhz9jn8HGENDKbwSeB0nVOg4gVStGA==", + "dependencies": { + "bail": "^1.0.0", + "extend": "^3.0.0", + "is-plain-obj": "^2.0.0", + "trough": "^1.0.0", + "vfile": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "@babel/plugin-transform-classes": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.15.4.tgz", - "integrity": "sha512-Yjvhex8GzBmmPQUvpXRPWQ9WnxXgAFuZSrqOK/eJlOGIXwvv8H3UEdUigl1gb/bnjTrln+e8bkZUYCBt/xYlBg==", - "requires": { - "@babel/helper-annotate-as-pure": "^7.15.4", - "@babel/helper-function-name": "^7.15.4", - "@babel/helper-optimise-call-expression": "^7.15.4", - "@babel/helper-plugin-utils": "^7.14.5", - "@babel/helper-replace-supers": "^7.15.4", - "@babel/helper-split-export-declaration": "^7.15.4", - "globals": "^11.1.0" + "node_modules/remark-emoji": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/remark-emoji/-/remark-emoji-2.2.0.tgz", + "integrity": "sha512-P3cj9s5ggsUvWw5fS2uzCHJMGuXYRb0NnZqYlNecewXt8QBU9n5vW3DUUKOhepS8F9CwdMx9B8a3i7pqFWAI5w==", + "dependencies": { + "emoticon": "^3.2.0", + "node-emoji": "^1.10.0", + "unist-util-visit": "^2.0.3" } }, - "@babel/plugin-transform-computed-properties": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.14.5.tgz", - "integrity": "sha512-pWM+E4283UxaVzLb8UBXv4EIxMovU4zxT1OPnpHJcmnvyY9QbPPTKZfEj31EUvG3/EQRbYAGaYEUZ4yWOBC2xg==", - "requires": { - "@babel/helper-plugin-utils": "^7.14.5" + "node_modules/remark-footnotes": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/remark-footnotes/-/remark-footnotes-2.0.0.tgz", + "integrity": "sha512-3Clt8ZMH75Ayjp9q4CorNeyjwIxHFcTkaektplKGl2A1jNGEUey8cKL0ZC5vJwfcD5GFGsNLImLG/NGzWIzoMQ==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "@babel/plugin-transform-destructuring": { - "version": "7.14.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.14.7.tgz", - "integrity": "sha512-0mDE99nK+kVh3xlc5vKwB6wnP9ecuSj+zQCa/n0voENtP/zymdT4HH6QEb65wjjcbqr1Jb/7z9Qp7TF5FtwYGw==", - "requires": { - "@babel/helper-plugin-utils": "^7.14.5" + "node_modules/remark-math": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/remark-math/-/remark-math-3.0.1.tgz", + "integrity": "sha512-epT77R/HK0x7NqrWHdSV75uNLwn8g9qTyMqCRCDujL0vj/6T6+yhdrR7mjELWtkse+Fw02kijAaBuVcHBor1+Q==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "@babel/plugin-transform-dotall-regex": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.14.5.tgz", - "integrity": "sha512-loGlnBdj02MDsFaHhAIJzh7euK89lBrGIdM9EAtHFo6xKygCUGuuWe07o1oZVk287amtW1n0808sQM99aZt3gw==", - "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.14.5", - "@babel/helper-plugin-utils": "^7.14.5" + "node_modules/remark-mdx": { + "version": "1.6.22", + "resolved": "https://registry.npmjs.org/remark-mdx/-/remark-mdx-1.6.22.tgz", + "integrity": "sha512-phMHBJgeV76uyFkH4rvzCftLfKCr2RZuF+/gmVcaKrpsihyzmhXjA0BEMDaPTXG5y8qZOKPVo83NAOX01LPnOQ==", + "dependencies": { + "@babel/core": "7.12.9", + "@babel/helper-plugin-utils": "7.10.4", + "@babel/plugin-proposal-object-rest-spread": "7.12.1", + "@babel/plugin-syntax-jsx": "7.12.1", + "@mdx-js/util": "1.6.22", + "is-alphabetical": "1.0.4", + "remark-parse": "8.0.3", + "unified": "9.2.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "@babel/plugin-transform-duplicate-keys": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.14.5.tgz", - "integrity": "sha512-iJjbI53huKbPDAsJ8EmVmvCKeeq21bAze4fu9GBQtSLqfvzj2oRuHVx4ZkDwEhg1htQ+5OBZh/Ab0XDf5iBZ7A==", - "requires": { - "@babel/helper-plugin-utils": "^7.14.5" + "node_modules/remark-mdx/node_modules/@babel/core": { + "version": "7.12.9", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.12.9.tgz", + "integrity": "sha512-gTXYh3M5wb7FRXQy+FErKFAv90BnlOuNn1QkCK2lREoPAjrQCO49+HVSrFoe5uakFAF5eenS75KbO2vQiLrTMQ==", + "dependencies": { + "@babel/code-frame": "^7.10.4", + "@babel/generator": "^7.12.5", + "@babel/helper-module-transforms": "^7.12.1", + "@babel/helpers": "^7.12.5", + "@babel/parser": "^7.12.7", + "@babel/template": "^7.12.7", + "@babel/traverse": "^7.12.9", + "@babel/types": "^7.12.7", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.1", + "json5": "^2.1.2", + "lodash": "^4.17.19", + "resolve": "^1.3.2", + "semver": "^5.4.1", + "source-map": "^0.5.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" } }, - "@babel/plugin-transform-exponentiation-operator": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.14.5.tgz", - "integrity": "sha512-jFazJhMBc9D27o9jDnIE5ZErI0R0m7PbKXVq77FFvqFbzvTMuv8jaAwLZ5PviOLSFttqKIW0/wxNSDbjLk0tYA==", - "requires": { - "@babel/helper-builder-binary-assignment-operator-visitor": "^7.14.5", - "@babel/helper-plugin-utils": "^7.14.5" - } + "node_modules/remark-mdx/node_modules/@babel/helper-plugin-utils": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz", + "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==" }, - "@babel/plugin-transform-for-of": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.15.4.tgz", - "integrity": "sha512-DRTY9fA751AFBDh2oxydvVm4SYevs5ILTWLs6xKXps4Re/KG5nfUkr+TdHCrRWB8C69TlzVgA9b3RmGWmgN9LA==", - "requires": { - "@babel/helper-plugin-utils": "^7.14.5" + "node_modules/remark-mdx/node_modules/@babel/plugin-proposal-object-rest-spread": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.12.1.tgz", + "integrity": "sha512-s6SowJIjzlhx8o7lsFx5zmY4At6CTtDvgNQDdPzkBQucle58A6b/TTeEBYtyDgmcXjUTM+vE8YOGHZzzbc/ioA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.0", + "@babel/plugin-transform-parameters": "^7.12.1" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-transform-function-name": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.14.5.tgz", - "integrity": "sha512-vbO6kv0fIzZ1GpmGQuvbwwm+O4Cbm2NrPzwlup9+/3fdkuzo1YqOZcXw26+YUJB84Ja7j9yURWposEHLYwxUfQ==", - "requires": { - "@babel/helper-function-name": "^7.14.5", - "@babel/helper-plugin-utils": "^7.14.5" + "node_modules/remark-mdx/node_modules/@babel/plugin-syntax-jsx": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.12.1.tgz", + "integrity": "sha512-1yRi7yAtB0ETgxdY9ti/p2TivUxJkTdhu/ZbF9MshVGqOx1TdB3b7xCXs49Fupgg50N45KcAsRP/ZqWjs9SRjg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-transform-literals": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.14.5.tgz", - "integrity": "sha512-ql33+epql2F49bi8aHXxvLURHkxJbSmMKl9J5yHqg4PLtdE6Uc48CH1GS6TQvZ86eoB/ApZXwm7jlA+B3kra7A==", - "requires": { - "@babel/helper-plugin-utils": "^7.14.5" + "node_modules/remark-mdx/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "bin": { + "semver": "bin/semver" } }, - "@babel/plugin-transform-member-expression-literals": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.14.5.tgz", - "integrity": "sha512-WkNXxH1VXVTKarWFqmso83xl+2V3Eo28YY5utIkbsmXoItO8Q3aZxN4BTS2k0hz9dGUloHK26mJMyQEYfkn/+Q==", - "requires": { - "@babel/helper-plugin-utils": "^7.14.5" + "node_modules/remark-mdx/node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "engines": { + "node": ">=0.10.0" } }, - "@babel/plugin-transform-modules-amd": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.14.5.tgz", - "integrity": "sha512-3lpOU8Vxmp3roC4vzFpSdEpGUWSMsHFreTWOMMLzel2gNGfHE5UWIh/LN6ghHs2xurUp4jRFYMUIZhuFbody1g==", - "requires": { - "@babel/helper-module-transforms": "^7.14.5", - "@babel/helper-plugin-utils": "^7.14.5", - "babel-plugin-dynamic-import-node": "^2.3.3" - }, + "node_modules/remark-parse": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-8.0.3.tgz", + "integrity": "sha512-E1K9+QLGgggHxCQtLt++uXltxEprmWzNfg+MxpfHsZlrddKzZ/hZyWHDbK3/Ap8HJQqYJRXP+jHczdL6q6i85Q==", "dependencies": { - "babel-plugin-dynamic-import-node": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz", - "integrity": "sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==", - "requires": { - "object.assign": "^4.1.0" - } - } + "ccount": "^1.0.0", + "collapse-white-space": "^1.0.2", + "is-alphabetical": "^1.0.0", + "is-decimal": "^1.0.0", + "is-whitespace-character": "^1.0.0", + "is-word-character": "^1.0.0", + "markdown-escapes": "^1.0.0", + "parse-entities": "^2.0.0", + "repeat-string": "^1.5.4", + "state-toggle": "^1.0.0", + "trim": "0.0.1", + "trim-trailing-lines": "^1.0.0", + "unherit": "^1.0.4", + "unist-util-remove-position": "^2.0.0", + "vfile-location": "^3.0.0", + "xtend": "^4.0.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "@babel/plugin-transform-modules-commonjs": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.15.4.tgz", - "integrity": "sha512-qg4DPhwG8hKp4BbVDvX1s8cohM8a6Bvptu4l6Iingq5rW+yRUAhe/YRup/YcW2zCOlrysEWVhftIcKzrEZv3sA==", - "requires": { - "@babel/helper-module-transforms": "^7.15.4", - "@babel/helper-plugin-utils": "^7.14.5", - "@babel/helper-simple-access": "^7.15.4", - "babel-plugin-dynamic-import-node": "^2.3.3" - }, + "node_modules/remark-squeeze-paragraphs": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/remark-squeeze-paragraphs/-/remark-squeeze-paragraphs-4.0.0.tgz", + "integrity": "sha512-8qRqmL9F4nuLPIgl92XUuxI3pFxize+F1H0e/W3llTk0UsjJaj01+RrirkMw7P21RKe4X6goQhYRSvNWX+70Rw==", "dependencies": { - "babel-plugin-dynamic-import-node": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz", - "integrity": "sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==", - "requires": { - "object.assign": "^4.1.0" - } - } + "mdast-squeeze-paragraphs": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "@babel/plugin-transform-modules-systemjs": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.15.4.tgz", - "integrity": "sha512-fJUnlQrl/mezMneR72CKCgtOoahqGJNVKpompKwzv3BrEXdlPspTcyxrZ1XmDTIr9PpULrgEQo3qNKp6dW7ssw==", - "requires": { - "@babel/helper-hoist-variables": "^7.15.4", - "@babel/helper-module-transforms": "^7.15.4", - "@babel/helper-plugin-utils": "^7.14.5", - "@babel/helper-validator-identifier": "^7.14.9", - "babel-plugin-dynamic-import-node": "^2.3.3" - }, + "node_modules/renderkid": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-3.0.0.tgz", + "integrity": "sha512-q/7VIQA8lmM1hF+jn+sFSPWGlMkSAeNYcPLmDQx2zzuiDfaLrOmumR8iaUKlenFgh0XRPIUeSPlH3A+AW3Z5pg==", "dependencies": { - "babel-plugin-dynamic-import-node": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz", - "integrity": "sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==", - "requires": { - "object.assign": "^4.1.0" - } - } + "css-select": "^4.1.3", + "dom-converter": "^0.2.0", + "htmlparser2": "^6.1.0", + "lodash": "^4.17.21", + "strip-ansi": "^6.0.1" } }, - "@babel/plugin-transform-modules-umd": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.14.5.tgz", - "integrity": "sha512-RfPGoagSngC06LsGUYyM9QWSXZ8MysEjDJTAea1lqRjNECE3y0qIJF/qbvJxc4oA4s99HumIMdXOrd+TdKaAAA==", - "requires": { - "@babel/helper-module-transforms": "^7.14.5", - "@babel/helper-plugin-utils": "^7.14.5" + "node_modules/repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", + "engines": { + "node": ">=0.10" } }, - "@babel/plugin-transform-named-capturing-groups-regex": { - "version": "7.14.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.14.9.tgz", - "integrity": "sha512-l666wCVYO75mlAtGFfyFwnWmIXQm3kSH0C3IRnJqWcZbWkoihyAdDhFm2ZWaxWTqvBvhVFfJjMRQ0ez4oN1yYA==", - "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.14.5" + "node_modules/request-progress": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/request-progress/-/request-progress-3.0.0.tgz", + "integrity": "sha512-MnWzEHHaxHO2iWiQuHrUPBi/1WeBf5PkxQqNyNvLl9VAYSdXkP8tQ3pBSeCPD+yw0v0Aq1zosWLz0BdeXpWwZg==", + "dev": true, + "dependencies": { + "throttleit": "^1.0.0" } }, - "@babel/plugin-transform-new-target": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.14.5.tgz", - "integrity": "sha512-Nx054zovz6IIRWEB49RDRuXGI4Gy0GMgqG0cII9L3MxqgXz/+rgII+RU58qpo4g7tNEx1jG7rRVH4ihZoP4esQ==", - "requires": { - "@babel/helper-plugin-utils": "^7.14.5" + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "engines": { + "node": ">=0.10.0" } }, - "@babel/plugin-transform-object-super": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.14.5.tgz", - "integrity": "sha512-MKfOBWzK0pZIrav9z/hkRqIk/2bTv9qvxHzPQc12RcVkMOzpIKnFCNYJip00ssKWYkd8Sf5g0Wr7pqJ+cmtuFg==", - "requires": { - "@babel/helper-plugin-utils": "^7.14.5", - "@babel/helper-replace-supers": "^7.14.5" + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "engines": { + "node": ">=0.10.0" } }, - "@babel/plugin-transform-parameters": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.15.4.tgz", - "integrity": "sha512-9WB/GUTO6lvJU3XQsSr6J/WKvBC2hcs4Pew8YxZagi6GkTdniyqp8On5kqdK8MN0LMeu0mGbhPN+O049NV/9FQ==", - "requires": { - "@babel/helper-plugin-utils": "^7.14.5" + "node_modules/require-like": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/require-like/-/require-like-0.1.2.tgz", + "integrity": "sha1-rW8wwTvs15cBDEaK+ndcDAprR/o=", + "engines": { + "node": "*" } }, - "@babel/plugin-transform-property-literals": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.14.5.tgz", - "integrity": "sha512-r1uilDthkgXW8Z1vJz2dKYLV1tuw2xsbrp3MrZmD99Wh9vsfKoob+JTgri5VUb/JqyKRXotlOtwgu4stIYCmnw==", - "requires": { - "@babel/helper-plugin-utils": "^7.14.5" - } + "node_modules/requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=" }, - "@babel/plugin-transform-react-constant-elements": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.14.5.tgz", - "integrity": "sha512-NBqLEx1GxllIOXJInJAQbrnwwYJsV3WaMHIcOwD8rhYS0AabTWn7kHdHgPgu5RmHLU0q4DMxhAMu8ue/KampgQ==", - "requires": { - "@babel/helper-plugin-utils": "^7.14.5" + "node_modules/resolve": { + "version": "1.22.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz", + "integrity": "sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==", + "dependencies": { + "is-core-module": "^2.8.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "@babel/plugin-transform-react-display-name": { - "version": "7.15.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.15.1.tgz", - "integrity": "sha512-yQZ/i/pUCJAHI/LbtZr413S3VT26qNrEm0M5RRxQJA947/YNYwbZbBaXGDrq6CG5QsZycI1VIP6d7pQaBfP+8Q==", - "requires": { - "@babel/helper-plugin-utils": "^7.14.5" + "node_modules/resolve-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", + "dev": true, + "dependencies": { + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" } }, - "@babel/plugin-transform-react-jsx": { - "version": "7.14.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.14.9.tgz", - "integrity": "sha512-30PeETvS+AeD1f58i1OVyoDlVYQhap/K20ZrMjLmmzmC2AYR/G43D4sdJAaDAqCD3MYpSWbmrz3kES158QSLjw==", - "requires": { - "@babel/helper-annotate-as-pure": "^7.14.5", - "@babel/helper-module-imports": "^7.14.5", - "@babel/helper-plugin-utils": "^7.14.5", - "@babel/plugin-syntax-jsx": "^7.14.5", - "@babel/types": "^7.14.9" + "node_modules/resolve-cwd/node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "engines": { + "node": ">=8" } }, - "@babel/plugin-transform-react-jsx-development": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.14.5.tgz", - "integrity": "sha512-rdwG/9jC6QybWxVe2UVOa7q6cnTpw8JRRHOxntG/h6g/guAOe6AhtQHJuJh5FwmnXIT1bdm5vC2/5huV8ZOorQ==", - "requires": { - "@babel/plugin-transform-react-jsx": "^7.14.5" + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "engines": { + "node": ">=4" } }, - "@babel/plugin-transform-react-pure-annotations": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.14.5.tgz", - "integrity": "sha512-3X4HpBJimNxW4rhUy/SONPyNQHp5YRr0HhJdT2OH1BRp0of7u3Dkirc7x9FRJMKMqTBI079VZ1hzv7Ouuz///g==", - "requires": { - "@babel/helper-annotate-as-pure": "^7.14.5", - "@babel/helper-plugin-utils": "^7.14.5" - } + "node_modules/resolve-pathname": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-pathname/-/resolve-pathname-3.0.0.tgz", + "integrity": "sha512-C7rARubxI8bXFNB/hqcp/4iUeIXJhJZvFPFPiSPRnhU5UPxzMFIl+2E6yY6c4k9giDJAhtV+enfA+G89N6Csng==" }, - "@babel/plugin-transform-regenerator": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.14.5.tgz", - "integrity": "sha512-NVIY1W3ITDP5xQl50NgTKlZ0GrotKtLna08/uGY6ErQt6VEQZXla86x/CTddm5gZdcr+5GSsvMeTmWA5Ii6pkg==", - "requires": { - "regenerator-transform": "^0.14.2" + "node_modules/resolve.exports": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-1.1.0.tgz", + "integrity": "sha512-J1l+Zxxp4XK3LUDZ9m60LRJF/mAe4z6a4xyabPHk7pvK5t35dACV32iIjJDFeWZFfZlO29w6SZ67knR0tHzJtQ==", + "dev": true, + "engines": { + "node": ">=10" } }, - "@babel/plugin-transform-reserved-words": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.14.5.tgz", - "integrity": "sha512-cv4F2rv1nD4qdexOGsRQXJrOcyb5CrgjUH9PKrrtyhSDBNWGxd0UIitjyJiWagS+EbUGjG++22mGH1Pub8D6Vg==", - "requires": { - "@babel/helper-plugin-utils": "^7.14.5" + "node_modules/responselike": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", + "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=", + "dependencies": { + "lowercase-keys": "^1.0.0" } }, - "@babel/plugin-transform-runtime": { - "version": "7.15.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.15.8.tgz", - "integrity": "sha512-+6zsde91jMzzvkzuEA3k63zCw+tm/GvuuabkpisgbDMTPQsIMHllE3XczJFFtEHLjjhKQFZmGQVRdELetlWpVw==", - "requires": { - "@babel/helper-module-imports": "^7.15.4", - "@babel/helper-plugin-utils": "^7.14.5", - "babel-plugin-polyfill-corejs2": "^0.2.2", - "babel-plugin-polyfill-corejs3": "^0.2.5", - "babel-plugin-polyfill-regenerator": "^0.2.2", - "semver": "^6.3.0" - }, + "node_modules/restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "dev": true, "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" - } + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": ">=8" } }, - "@babel/plugin-transform-shorthand-properties": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.14.5.tgz", - "integrity": "sha512-xLucks6T1VmGsTB+GWK5Pl9Jl5+nRXD1uoFdA5TSO6xtiNjtXTjKkmPdFXVLGlK5A2/or/wQMKfmQ2Y0XJfn5g==", - "requires": { - "@babel/helper-plugin-utils": "^7.14.5" + "node_modules/retry": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", + "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", + "engines": { + "node": ">= 4" } }, - "@babel/plugin-transform-spread": { - "version": "7.15.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.15.8.tgz", - "integrity": "sha512-/daZ8s2tNaRekl9YJa9X4bzjpeRZLt122cpgFnQPLGUe61PH8zMEBmYqKkW5xF5JUEh5buEGXJoQpqBmIbpmEQ==", - "requires": { - "@babel/helper-plugin-utils": "^7.14.5", - "@babel/helper-skip-transparent-expression-wrappers": "^7.15.4" + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" } }, - "@babel/plugin-transform-sticky-regex": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.14.5.tgz", - "integrity": "sha512-Z7F7GyvEMzIIbwnziAZmnSNpdijdr4dWt+FJNBnBLz5mwDFkqIXU9wmBcWWad3QeJF5hMTkRe4dAq2sUZiG+8A==", - "requires": { - "@babel/helper-plugin-utils": "^7.14.5" + "node_modules/rfdc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", + "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==", + "dev": true + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "@babel/plugin-transform-template-literals": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.14.5.tgz", - "integrity": "sha512-22btZeURqiepOfuy/VkFr+zStqlujWaarpMErvay7goJS6BWwdd6BY9zQyDLDa4x2S3VugxFb162IZ4m/S/+Gg==", - "requires": { - "@babel/helper-plugin-utils": "^7.14.5" + "node_modules/ripemd160": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", + "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", + "dependencies": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1" } }, - "@babel/plugin-transform-typeof-symbol": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.14.5.tgz", - "integrity": "sha512-lXzLD30ffCWseTbMQzrvDWqljvZlHkXU+CnseMhkMNqU1sASnCsz3tSzAaH3vCUXb9PHeUb90ZT1BdFTm1xxJw==", - "requires": { - "@babel/helper-plugin-utils": "^7.14.5" + "node_modules/rtl-detect": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/rtl-detect/-/rtl-detect-1.0.4.tgz", + "integrity": "sha512-EBR4I2VDSSYr7PkBmFy04uhycIpDKp+21p/jARYXlCSjQksTBQcJ0HFUPOO79EPPH5JS6VAhiIQbycf0O3JAxQ==" + }, + "node_modules/rtlcss": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/rtlcss/-/rtlcss-3.5.0.tgz", + "integrity": "sha512-wzgMaMFHQTnyi9YOwsx9LjOxYXJPzS8sYnFaKm6R5ysvTkwzHiB0vxnbHwchHQT65PTdBjDG21/kQBWI7q9O7A==", + "dependencies": { + "find-up": "^5.0.0", + "picocolors": "^1.0.0", + "postcss": "^8.3.11", + "strip-json-comments": "^3.1.1" + }, + "bin": { + "rtlcss": "bin/rtlcss.js" } }, - "@babel/plugin-transform-typescript": { - "version": "7.15.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.15.8.tgz", - "integrity": "sha512-ZXIkJpbaf6/EsmjeTbiJN/yMxWPFWvlr7sEG1P95Xb4S4IBcrf2n7s/fItIhsAmOf8oSh3VJPDppO6ExfAfKRQ==", - "requires": { - "@babel/helper-create-class-features-plugin": "^7.15.4", - "@babel/helper-plugin-utils": "^7.14.5", - "@babel/plugin-syntax-typescript": "^7.14.5" + "node_modules/rtlcss/node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "@babel/plugin-transform-unicode-escapes": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.14.5.tgz", - "integrity": "sha512-crTo4jATEOjxj7bt9lbYXcBAM3LZaUrbP2uUdxb6WIorLmjNKSpHfIybgY4B8SRpbf8tEVIWH3Vtm7ayCrKocA==", - "requires": { - "@babel/helper-plugin-utils": "^7.14.5" + "node_modules/rtlcss/node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "@babel/plugin-transform-unicode-regex": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.14.5.tgz", - "integrity": "sha512-UygduJpC5kHeCiRw/xDVzC+wj8VaYSoKl5JNVmbP7MadpNinAm3SvZCxZ42H37KZBKztz46YC73i9yV34d0Tzw==", - "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.14.5", - "@babel/helper-plugin-utils": "^7.14.5" + "node_modules/rtlcss/node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "@babel/preset-env": { - "version": "7.15.8", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.15.8.tgz", - "integrity": "sha512-rCC0wH8husJgY4FPbHsiYyiLxSY8oMDJH7Rl6RQMknbN9oDDHhM9RDFvnGM2MgkbUJzSQB4gtuwygY5mCqGSsA==", - "requires": { - "@babel/compat-data": "^7.15.0", - "@babel/helper-compilation-targets": "^7.15.4", - "@babel/helper-plugin-utils": "^7.14.5", - "@babel/helper-validator-option": "^7.14.5", - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.15.4", - "@babel/plugin-proposal-async-generator-functions": "^7.15.8", - "@babel/plugin-proposal-class-properties": "^7.14.5", - "@babel/plugin-proposal-class-static-block": "^7.15.4", - "@babel/plugin-proposal-dynamic-import": "^7.14.5", - "@babel/plugin-proposal-export-namespace-from": "^7.14.5", - "@babel/plugin-proposal-json-strings": "^7.14.5", - "@babel/plugin-proposal-logical-assignment-operators": "^7.14.5", - "@babel/plugin-proposal-nullish-coalescing-operator": "^7.14.5", - "@babel/plugin-proposal-numeric-separator": "^7.14.5", - "@babel/plugin-proposal-object-rest-spread": "^7.15.6", - "@babel/plugin-proposal-optional-catch-binding": "^7.14.5", - "@babel/plugin-proposal-optional-chaining": "^7.14.5", - "@babel/plugin-proposal-private-methods": "^7.14.5", - "@babel/plugin-proposal-private-property-in-object": "^7.15.4", - "@babel/plugin-proposal-unicode-property-regex": "^7.14.5", - "@babel/plugin-syntax-async-generators": "^7.8.4", - "@babel/plugin-syntax-class-properties": "^7.12.13", - "@babel/plugin-syntax-class-static-block": "^7.14.5", - "@babel/plugin-syntax-dynamic-import": "^7.8.3", - "@babel/plugin-syntax-export-namespace-from": "^7.8.3", - "@babel/plugin-syntax-json-strings": "^7.8.3", - "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", - "@babel/plugin-syntax-numeric-separator": "^7.10.4", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", - "@babel/plugin-syntax-optional-chaining": "^7.8.3", - "@babel/plugin-syntax-private-property-in-object": "^7.14.5", - "@babel/plugin-syntax-top-level-await": "^7.14.5", - "@babel/plugin-transform-arrow-functions": "^7.14.5", - "@babel/plugin-transform-async-to-generator": "^7.14.5", - "@babel/plugin-transform-block-scoped-functions": "^7.14.5", - "@babel/plugin-transform-block-scoping": "^7.15.3", - "@babel/plugin-transform-classes": "^7.15.4", - "@babel/plugin-transform-computed-properties": "^7.14.5", - "@babel/plugin-transform-destructuring": "^7.14.7", - "@babel/plugin-transform-dotall-regex": "^7.14.5", - "@babel/plugin-transform-duplicate-keys": "^7.14.5", - "@babel/plugin-transform-exponentiation-operator": "^7.14.5", - "@babel/plugin-transform-for-of": "^7.15.4", - "@babel/plugin-transform-function-name": "^7.14.5", - "@babel/plugin-transform-literals": "^7.14.5", - "@babel/plugin-transform-member-expression-literals": "^7.14.5", - "@babel/plugin-transform-modules-amd": "^7.14.5", - "@babel/plugin-transform-modules-commonjs": "^7.15.4", - "@babel/plugin-transform-modules-systemjs": "^7.15.4", - "@babel/plugin-transform-modules-umd": "^7.14.5", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.14.9", - "@babel/plugin-transform-new-target": "^7.14.5", - "@babel/plugin-transform-object-super": "^7.14.5", - "@babel/plugin-transform-parameters": "^7.15.4", - "@babel/plugin-transform-property-literals": "^7.14.5", - "@babel/plugin-transform-regenerator": "^7.14.5", - "@babel/plugin-transform-reserved-words": "^7.14.5", - "@babel/plugin-transform-shorthand-properties": "^7.14.5", - "@babel/plugin-transform-spread": "^7.15.8", - "@babel/plugin-transform-sticky-regex": "^7.14.5", - "@babel/plugin-transform-template-literals": "^7.14.5", - "@babel/plugin-transform-typeof-symbol": "^7.14.5", - "@babel/plugin-transform-unicode-escapes": "^7.14.5", - "@babel/plugin-transform-unicode-regex": "^7.14.5", - "@babel/preset-modules": "^0.1.4", - "@babel/types": "^7.15.6", - "babel-plugin-polyfill-corejs2": "^0.2.2", - "babel-plugin-polyfill-corejs3": "^0.2.5", - "babel-plugin-polyfill-regenerator": "^0.2.2", - "core-js-compat": "^3.16.0", - "semver": "^6.3.0" - }, + "node_modules/rtlcss/node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" - } + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "@babel/preset-modules": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.4.tgz", - "integrity": "sha512-J36NhwnfdzpmH41M1DrnkkgAqhZaqr/NBdPfQ677mLzlaXo+oDiv1deyCDtgAhz8p328otdob0Du7+xgHGZbKg==", - "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-proposal-unicode-property-regex": "^7.4.4", - "@babel/plugin-transform-dotall-regex": "^7.4.4", - "@babel/types": "^7.4.4", - "esutils": "^2.0.2" + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" } }, - "@babel/preset-react": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.14.5.tgz", - "integrity": "sha512-XFxBkjyObLvBaAvkx1Ie95Iaq4S/GUEIrejyrntQ/VCMKUYvKLoyKxOBzJ2kjA3b6rC9/KL6KXfDC2GqvLiNqQ==", - "requires": { - "@babel/helper-plugin-utils": "^7.14.5", - "@babel/helper-validator-option": "^7.14.5", - "@babel/plugin-transform-react-display-name": "^7.14.5", - "@babel/plugin-transform-react-jsx": "^7.14.5", - "@babel/plugin-transform-react-jsx-development": "^7.14.5", - "@babel/plugin-transform-react-pure-annotations": "^7.14.5" + "node_modules/rxjs": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.5.5.tgz", + "integrity": "sha512-sy+H0pQofO95VDmFLzyaw9xNJU4KTRSwQIGM6+iG3SypAtCiLDzpeG8sJrNCWn2Up9km+KhkvTdbkrdy+yzZdw==", + "dependencies": { + "tslib": "^2.1.0" } }, - "@babel/preset-typescript": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.15.0.tgz", - "integrity": "sha512-lt0Y/8V3y06Wq/8H/u0WakrqciZ7Fz7mwPDHWUJAXlABL5hiUG42BNlRXiELNjeWjO5rWmnNKlx+yzJvxezHow==", - "requires": { - "@babel/helper-plugin-utils": "^7.14.5", - "@babel/helper-validator-option": "^7.14.5", - "@babel/plugin-transform-typescript": "^7.15.0" - } + "node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" }, - "@babel/runtime": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.15.4.tgz", - "integrity": "sha512-99catp6bHCaxr4sJ/DbTGgHS4+Rs2RVd2g7iOap6SLGPDknRK9ztKNsE/Fg6QhSeh1FGE5f6gHGQmvvn3I3xhw==", - "requires": { - "regenerator-runtime": "^0.13.4" - } + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, - "@babel/runtime-corejs3": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.15.4.tgz", - "integrity": "sha512-lWcAqKeB624/twtTc3w6w/2o9RqJPaNBhPGK6DKLSiwuVWC7WFkypWyNg+CpZoyJH0jVzv1uMtXZ/5/lQOLtCg==", - "requires": { - "core-js-pure": "^3.16.0", - "regenerator-runtime": "^0.13.4" + "node_modules/sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" + }, + "node_modules/saxes": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/saxes/-/saxes-5.0.1.tgz", + "integrity": "sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw==", + "dev": true, + "dependencies": { + "xmlchars": "^2.2.0" + }, + "engines": { + "node": ">=10" } }, - "@babel/template": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.15.4.tgz", - "integrity": "sha512-UgBAfEa1oGuYgDIPM2G+aHa4Nlo9Lh6mGD2bDBGMTbYnc38vulXPuC1MGjYILIEmlwl6Rd+BPR9ee3gm20CBtg==", - "requires": { - "@babel/code-frame": "^7.14.5", - "@babel/parser": "^7.15.4", - "@babel/types": "^7.15.4" + "node_modules/scheduler": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.20.2.tgz", + "integrity": "sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ==", + "dependencies": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1" } }, - "@babel/traverse": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.15.4.tgz", - "integrity": "sha512-W6lQD8l4rUbQR/vYgSuCAE75ADyyQvOpFVsvPPdkhf6lATXAsQIG9YdtOcu8BB1dZ0LKu+Zo3c1wEcbKeuhdlA==", - "requires": { - "@babel/code-frame": "^7.14.5", - "@babel/generator": "^7.15.4", - "@babel/helper-function-name": "^7.15.4", - "@babel/helper-hoist-variables": "^7.15.4", - "@babel/helper-split-export-declaration": "^7.15.4", - "@babel/parser": "^7.15.4", - "@babel/types": "^7.15.4", - "debug": "^4.1.0", - "globals": "^11.1.0" + "node_modules/schema-utils": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz", + "integrity": "sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==", + "dependencies": { + "@types/json-schema": "^7.0.5", + "ajv": "^6.12.4", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 8.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" } }, - "@babel/types": { - "version": "7.15.6", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.15.6.tgz", - "integrity": "sha512-BPU+7QhqNjmWyDO0/vitH/CuhpV8ZmK1wpKva8nuyNF5MJfuRNWMc+hc14+u9xT93kvykMdncrJT19h74uB1Ig==", - "requires": { - "@babel/helper-validator-identifier": "^7.14.9", - "to-fast-properties": "^2.0.0" + "node_modules/section-matter": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/section-matter/-/section-matter-1.0.0.tgz", + "integrity": "sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA==", + "dependencies": { + "extend-shallow": "^2.0.1", + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=4" } }, - "@docsearch/css": { - "version": "3.0.0-alpha.40", - "resolved": "https://registry.npmjs.org/@docsearch/css/-/css-3.0.0-alpha.40.tgz", - "integrity": "sha512-PrOTPgJMl+Iji1zOH0+J0PEDMriJ1teGxbgll7o4h8JrvJW6sJGqQw7/bLW7enWiFaxbJMK76w1yyPNLFHV7Qg==" + "node_modules/select-hose": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", + "integrity": "sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo=" }, - "@docsearch/react": { - "version": "3.0.0-alpha.40", - "resolved": "https://registry.npmjs.org/@docsearch/react/-/react-3.0.0-alpha.40.tgz", - "integrity": "sha512-aKxnu7sgpP1R7jtgOV/pZdJEHXx6Ts+jnS9U/ejSUS2BMUpwQI5SA3oLs1BA5TA9kIViJ5E+rrjh0VsbcsJ6sQ==", - "requires": { - "@algolia/autocomplete-core": "1.2.2", - "@algolia/autocomplete-preset-algolia": "1.2.2", - "@docsearch/css": "3.0.0-alpha.40", - "algoliasearch": "^4.0.0" + "node_modules/selfsigned": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.0.1.tgz", + "integrity": "sha512-LmME957M1zOsUhG+67rAjKfiWFox3SBxE/yymatMZsAx+oMrJ0YQ8AToOnyCm7xbeg2ep37IHLxdu0o2MavQOQ==", + "dependencies": { + "node-forge": "^1" + }, + "engines": { + "node": ">=10" } }, - "@docusaurus/core": { - "version": "2.0.0-beta.6", - "resolved": "https://registry.npmjs.org/@docusaurus/core/-/core-2.0.0-beta.6.tgz", - "integrity": "sha512-XMeI+lJKeJBGYBNOfO/Tc+5FMf21E5p1xZjfe75cgYcfZdERZ+W7aemXquwReno8xxHb4Rnfmi9dxkbOLDjqDA==", - "requires": { - "@babel/core": "^7.12.16", - "@babel/generator": "^7.12.15", - "@babel/plugin-syntax-dynamic-import": "^7.8.3", - "@babel/plugin-transform-runtime": "^7.12.15", - "@babel/preset-env": "^7.12.16", - "@babel/preset-react": "^7.12.13", - "@babel/preset-typescript": "^7.12.16", - "@babel/runtime": "^7.12.5", - "@babel/runtime-corejs3": "^7.12.13", - "@babel/traverse": "^7.12.13", - "@docusaurus/cssnano-preset": "2.0.0-beta.6", - "@docusaurus/react-loadable": "5.5.0", - "@docusaurus/types": "2.0.0-beta.6", - "@docusaurus/utils": "2.0.0-beta.6", - "@docusaurus/utils-common": "2.0.0-beta.6", - "@docusaurus/utils-validation": "2.0.0-beta.6", - "@slorber/static-site-generator-webpack-plugin": "^4.0.0", - "@svgr/webpack": "^5.5.0", - "autoprefixer": "^10.2.5", - "babel-loader": "^8.2.2", - "babel-plugin-dynamic-import-node": "2.3.0", - "boxen": "^5.0.1", - "chalk": "^4.1.1", - "chokidar": "^3.5.1", - "clean-css": "^5.1.5", - "commander": "^5.1.0", - "copy-webpack-plugin": "^9.0.0", - "core-js": "^3.9.1", - "css-loader": "^5.1.1", - "css-minimizer-webpack-plugin": "^3.0.1", - "cssnano": "^5.0.4", - "del": "^6.0.0", - "detect-port": "^1.3.0", - "escape-html": "^1.0.3", - "eta": "^1.12.1", - "express": "^4.17.1", - "file-loader": "^6.2.0", - "fs-extra": "^10.0.0", - "github-slugger": "^1.3.0", - "globby": "^11.0.2", - "html-minifier-terser": "^5.1.1", - "html-tags": "^3.1.0", - "html-webpack-plugin": "^5.3.2", - "import-fresh": "^3.3.0", - "is-root": "^2.1.0", - "leven": "^3.1.0", - "lodash": "^4.17.20", - "mini-css-extract-plugin": "^1.6.0", - "module-alias": "^2.2.2", - "nprogress": "^0.2.0", - "postcss": "^8.2.15", - "postcss-loader": "^5.3.0", - "prompts": "^2.4.1", - "react-dev-utils": "^11.0.1", - "react-error-overlay": "^6.0.9", - "react-helmet": "^6.1.0", - "react-loadable": "^5.5.0", - "react-loadable-ssr-addon-v5-slorber": "^1.0.1", - "react-router": "^5.2.0", - "react-router-config": "^5.1.1", - "react-router-dom": "^5.2.0", - "remark-admonitions": "^1.2.1", - "resolve-pathname": "^3.0.0", - "rtl-detect": "^1.0.3", - "semver": "^7.3.4", - "serve-handler": "^6.1.3", - "shelljs": "^0.8.4", - "std-env": "^2.2.1", - "strip-ansi": "^6.0.0", - "terser-webpack-plugin": "^5.1.3", - "tslib": "^2.2.0", - "update-notifier": "^5.1.0", - "url-loader": "^4.1.1", - "wait-on": "^5.3.0", - "webpack": "^5.40.0", - "webpack-bundle-analyzer": "^4.4.2", - "webpack-dev-server": "^3.11.2", - "webpack-merge": "^5.8.0", - "webpackbar": "^5.0.0-3" - }, + "node_modules/semver": { + "version": "7.3.7", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", + "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", "dependencies": { - "css-loader": { - "version": "5.2.7", - "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-5.2.7.tgz", - "integrity": "sha512-Q7mOvpBNBG7YrVGMxRxcBJZFL75o+cH2abNASdibkj/fffYD8qWbInZrD0S9ccI6vZclF3DsHE7njGlLtaHbhg==", - "requires": { - "icss-utils": "^5.1.0", - "loader-utils": "^2.0.0", - "postcss": "^8.2.15", - "postcss-modules-extract-imports": "^3.0.0", - "postcss-modules-local-by-default": "^4.0.0", - "postcss-modules-scope": "^3.0.0", - "postcss-modules-values": "^4.0.0", - "postcss-value-parser": "^4.1.0", - "schema-utils": "^3.0.0", - "semver": "^7.3.5" - } - } + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" } }, - "@docusaurus/cssnano-preset": { - "version": "2.0.0-beta.6", - "resolved": "https://registry.npmjs.org/@docusaurus/cssnano-preset/-/cssnano-preset-2.0.0-beta.6.tgz", - "integrity": "sha512-RCizp2NAbADopkX5nUz1xrAbU6hGZzziQk9RdSDGJLzMgVCN6RDotq9odS8VgzNa9x2Lx3WN527UxeEbzc2GVQ==", - "requires": { - "cssnano-preset-advanced": "^5.1.1", - "postcss": "^8.2.15", - "postcss-sort-media-queries": "^3.10.11" + "node_modules/semver-diff": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-3.1.1.tgz", + "integrity": "sha512-GX0Ix/CJcHyB8c4ykpHGIAvLyOwOobtM/8d+TQkAd81/bEjgPHrfba41Vpesr7jX/t8Uh+R3EX9eAS5be+jQYg==", + "dependencies": { + "semver": "^6.3.0" + }, + "engines": { + "node": ">=8" } }, - "@docusaurus/lqip-loader": { - "version": "2.0.0-beta.6", - "resolved": "https://registry.npmjs.org/@docusaurus/lqip-loader/-/lqip-loader-2.0.0-beta.6.tgz", - "integrity": "sha512-8kXfqWiv1XY+EeWzpKGhiwcftj6Kd4wZ+ThxbmiSWU7LTUcEkvX25wGiK1mHLHDGzrTZYrCRSs8DvXY/PiYIAw==", - "requires": { - "file-loader": "^6.2.0", - "lodash": "^4.17.20", - "node-vibrant": "^3.1.5", - "sharp": "^0.28.2" + "node_modules/semver-diff/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "bin": { + "semver": "bin/semver.js" } }, - "@docusaurus/mdx-loader": { - "version": "2.0.0-beta.6", - "resolved": "https://registry.npmjs.org/@docusaurus/mdx-loader/-/mdx-loader-2.0.0-beta.6.tgz", - "integrity": "sha512-yO6N+OESR77WZ/pXz7muOJGLletYYksx7s7wrwrr0x+A8tzdSwiHZ9op0NyjjpW5AnItU/WQQfcjv37qv4K6HA==", - "requires": { - "@babel/parser": "^7.12.16", - "@babel/traverse": "^7.12.13", - "@docusaurus/core": "2.0.0-beta.6", - "@docusaurus/utils": "2.0.0-beta.6", - "@mdx-js/mdx": "^1.6.21", - "@mdx-js/react": "^1.6.21", - "chalk": "^4.1.1", - "escape-html": "^1.0.3", - "file-loader": "^6.2.0", - "fs-extra": "^10.0.0", - "github-slugger": "^1.3.0", - "gray-matter": "^4.0.3", - "mdast-util-to-string": "^2.0.0", - "remark-emoji": "^2.1.0", - "stringify-object": "^3.3.0", - "unist-util-visit": "^2.0.2", - "url-loader": "^4.1.1", - "webpack": "^5.40.0" + "node_modules/send": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", + "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "engines": { + "node": ">= 0.8.0" } }, - "@docusaurus/plugin-content-blog": { - "version": "2.0.0-beta.6", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-blog/-/plugin-content-blog-2.0.0-beta.6.tgz", - "integrity": "sha512-ohfMt7+rPiFQImc4Clpvc9m/1yWUQAjpG3e/coJywlJYbDXvi1pmH0VKkDUMBSe/35Wtz9457DYgNFG81lhV7Q==", - "requires": { - "@docusaurus/core": "2.0.0-beta.6", - "@docusaurus/mdx-loader": "2.0.0-beta.6", - "@docusaurus/types": "2.0.0-beta.6", - "@docusaurus/utils": "2.0.0-beta.6", - "@docusaurus/utils-validation": "2.0.0-beta.6", - "chalk": "^4.1.1", - "escape-string-regexp": "^4.0.0", - "feed": "^4.2.2", - "fs-extra": "^10.0.0", - "globby": "^11.0.2", - "js-yaml": "^4.0.0", - "loader-utils": "^2.0.0", - "lodash": "^4.17.20", - "reading-time": "^1.3.0", - "remark-admonitions": "^1.2.1", - "tslib": "^2.2.0", - "webpack": "^5.40.0" - }, + "node_modules/send/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dependencies": { - "argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" - }, - "escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==" - }, - "js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "requires": { - "argparse": "^2.0.1" - } - } + "ms": "2.0.0" } }, - "@docusaurus/plugin-content-docs": { - "version": "2.0.0-beta.6", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-docs/-/plugin-content-docs-2.0.0-beta.6.tgz", - "integrity": "sha512-cM5WWogWmX+qKPKv332eDWGRVVT5OjskbmFKe2QimwoaON3Cv6XY8Fo2xdYopqGIU0r0z8dVtRmoGS0ji7zB7w==", - "requires": { - "@docusaurus/core": "2.0.0-beta.6", - "@docusaurus/mdx-loader": "2.0.0-beta.6", - "@docusaurus/types": "2.0.0-beta.6", - "@docusaurus/utils": "2.0.0-beta.6", - "@docusaurus/utils-validation": "2.0.0-beta.6", - "chalk": "^4.1.1", - "combine-promises": "^1.1.0", - "escape-string-regexp": "^4.0.0", - "execa": "^5.0.0", - "fs-extra": "^10.0.0", - "globby": "^11.0.2", - "import-fresh": "^3.2.2", - "js-yaml": "^4.0.0", - "loader-utils": "^1.2.3", - "lodash": "^4.17.20", - "remark-admonitions": "^1.2.1", - "shelljs": "^0.8.4", - "tslib": "^2.2.0", - "utility-types": "^3.10.0", - "webpack": "^5.40.0" - }, - "dependencies": { - "argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" - }, - "escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==" - }, - "execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", - "requires": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - } - }, - "get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==" - }, - "is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==" - }, - "js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "requires": { - "argparse": "^2.0.1" - } - }, - "json5": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", - "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", - "requires": { - "minimist": "^1.2.0" - } - }, - "loader-utils": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", - "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", - "requires": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^1.0.1" - } - }, - "npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "requires": { - "path-key": "^3.0.0" - } - } - } + "node_modules/send/node_modules/debug/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, - "@docusaurus/plugin-content-pages": { - "version": "2.0.0-beta.6", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-pages/-/plugin-content-pages-2.0.0-beta.6.tgz", - "integrity": "sha512-N6wARzOA8gTFeBXZSKbAN5s1Ej6R/pVg+J946E8GCYefXTFikTNRQ8+OPhax4MRzgzoOvhTQbLbRCSoAzSmjig==", - "requires": { - "@docusaurus/core": "2.0.0-beta.6", - "@docusaurus/mdx-loader": "2.0.0-beta.6", - "@docusaurus/types": "2.0.0-beta.6", - "@docusaurus/utils": "2.0.0-beta.6", - "@docusaurus/utils-validation": "2.0.0-beta.6", - "globby": "^11.0.2", - "lodash": "^4.17.20", - "remark-admonitions": "^1.2.1", - "tslib": "^2.1.0", - "webpack": "^5.40.0" + "node_modules/send/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/send/node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "engines": { + "node": ">= 0.6" } }, - "@docusaurus/plugin-debug": { - "version": "2.0.0-beta.6", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-debug/-/plugin-debug-2.0.0-beta.6.tgz", - "integrity": "sha512-TJXDBR2Gr/mhBrcj+/4+rTShSm/Qg56Jfezbm/2fFvuPgVlUwy6oj08s2/kYSTmkfG7G+c4iX1GBHjtyo1KxZA==", - "requires": { - "@docusaurus/core": "2.0.0-beta.6", - "@docusaurus/types": "2.0.0-beta.6", - "@docusaurus/utils": "2.0.0-beta.6", - "fs-extra": "^9.1.0", - "react-json-view": "^1.21.3", - "tslib": "^2.1.0" - }, + "node_modules/serialize-javascript": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", + "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", "dependencies": { - "fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", - "requires": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - } - } + "randombytes": "^2.1.0" } }, - "@docusaurus/plugin-google-analytics": { - "version": "2.0.0-beta.6", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-analytics/-/plugin-google-analytics-2.0.0-beta.6.tgz", - "integrity": "sha512-AHbMNPN3gkWXYFnmHL9MBcRODByAgzHZoH/5v3xwbSV2FOZo6kx4Hp94I6oFM0o5mp+i6X7slDncgGTWSGxCMg==", - "requires": { - "@docusaurus/core": "2.0.0-beta.6" + "node_modules/serve-handler": { + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/serve-handler/-/serve-handler-6.1.3.tgz", + "integrity": "sha512-FosMqFBNrLyeiIDvP1zgO6YoTzFYHxLDEIavhlmQ+knB2Z7l1t+kGLHkZIDN7UVWqQAmKI3D20A6F6jo3nDd4w==", + "dependencies": { + "bytes": "3.0.0", + "content-disposition": "0.5.2", + "fast-url-parser": "1.1.3", + "mime-types": "2.1.18", + "minimatch": "3.0.4", + "path-is-inside": "1.0.2", + "path-to-regexp": "2.2.1", + "range-parser": "1.2.0" } }, - "@docusaurus/plugin-google-gtag": { - "version": "2.0.0-beta.6", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-gtag/-/plugin-google-gtag-2.0.0-beta.6.tgz", - "integrity": "sha512-uJyQ30sXbVRS3TGtVJFA0s1ozrluuREu6NK2Z3TLtKpeT2NTe5iaqXN0Xp749hr3bjbgpEe6gMixVh//jg503w==", - "requires": { - "@docusaurus/core": "2.0.0-beta.6" + "node_modules/serve-handler/node_modules/mime-db": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz", + "integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==", + "engines": { + "node": ">= 0.6" } }, - "@docusaurus/plugin-ideal-image": { - "version": "2.0.0-beta.6", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-ideal-image/-/plugin-ideal-image-2.0.0-beta.6.tgz", - "integrity": "sha512-v8IkaELNHGG90Z0KbtpCPsxcNFwlzZF37LoqyHTzAvvIVmctUWkWUgysIwccbrN3qiYVydPUZA4HZ8X+cTB7Zw==", - "requires": { - "@docusaurus/core": "2.0.0-beta.6", - "@docusaurus/lqip-loader": "2.0.0-beta.6", - "@docusaurus/responsive-loader": "1.4.0", - "@docusaurus/types": "2.0.0-beta.6", - "@endiliey/react-ideal-image": "^0.0.11", - "react-waypoint": "^10.1.0", - "sharp": "^0.28.2", - "tslib": "^2.1.0", - "webpack": "^5.40.0" + "node_modules/serve-handler/node_modules/mime-types": { + "version": "2.1.18", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz", + "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==", + "dependencies": { + "mime-db": "~1.33.0" + }, + "engines": { + "node": ">= 0.6" } }, - "@docusaurus/plugin-sitemap": { - "version": "2.0.0-beta.6", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-sitemap/-/plugin-sitemap-2.0.0-beta.6.tgz", - "integrity": "sha512-jpTaODqyCgg+20RtMw8gSvCKQOvH18FpKhIu6FG+z4zgHP33qaJouVM7/1ZKPrfNt4z7xDOyBNUzzdmpssHA8A==", - "requires": { - "@docusaurus/core": "2.0.0-beta.6", - "@docusaurus/types": "2.0.0-beta.6", - "@docusaurus/utils": "2.0.0-beta.6", - "@docusaurus/utils-common": "2.0.0-beta.6", - "@docusaurus/utils-validation": "2.0.0-beta.6", - "fs-extra": "^10.0.0", - "sitemap": "^7.0.0", - "tslib": "^2.2.0" + "node_modules/serve-handler/node_modules/minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" } }, - "@docusaurus/preset-classic": { - "version": "2.0.0-beta.6", - "resolved": "https://registry.npmjs.org/@docusaurus/preset-classic/-/preset-classic-2.0.0-beta.6.tgz", - "integrity": "sha512-riqQRcNssNH7oto8nAjYIO79/ZucidexHTDlgD+trP56ploHLJp4kIlxb44IGOmx3es8/z4egWtM+acY/39N2Q==", - "requires": { - "@docusaurus/core": "2.0.0-beta.6", - "@docusaurus/plugin-content-blog": "2.0.0-beta.6", - "@docusaurus/plugin-content-docs": "2.0.0-beta.6", - "@docusaurus/plugin-content-pages": "2.0.0-beta.6", - "@docusaurus/plugin-debug": "2.0.0-beta.6", - "@docusaurus/plugin-google-analytics": "2.0.0-beta.6", - "@docusaurus/plugin-google-gtag": "2.0.0-beta.6", - "@docusaurus/plugin-sitemap": "2.0.0-beta.6", - "@docusaurus/theme-classic": "2.0.0-beta.6", - "@docusaurus/theme-search-algolia": "2.0.0-beta.6" - } + "node_modules/serve-handler/node_modules/path-to-regexp": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-2.2.1.tgz", + "integrity": "sha512-gu9bD6Ta5bwGrrU8muHzVOBFFREpp2iRkVfhBJahwJ6p6Xw20SjT0MxLnwkjOibQmGSYhiUnf2FLe7k+jcFmGQ==" }, - "@docusaurus/react-loadable": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@docusaurus/react-loadable/-/react-loadable-5.5.0.tgz", - "integrity": "sha512-Ld/kwUE6yATIOTLq3JCsWiTa/drisajwKqBQ2Rw6IcT+sFsKfYek8F2jSH8f68AT73xX97UehduZeCSlnuCBIg==", - "requires": { - "prop-types": "^15.6.2" + "node_modules/serve-index": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", + "integrity": "sha1-03aNabHn2C5c4FD/9bRTvqEqkjk=", + "dependencies": { + "accepts": "~1.3.4", + "batch": "0.6.1", + "debug": "2.6.9", + "escape-html": "~1.0.3", + "http-errors": "~1.6.2", + "mime-types": "~2.1.17", + "parseurl": "~1.3.2" + }, + "engines": { + "node": ">= 0.8.0" } }, - "@docusaurus/responsive-loader": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/responsive-loader/-/responsive-loader-1.4.0.tgz", - "integrity": "sha512-qkVjSEUM4dVNmgOWkjbuRetZegOiCnzGPOzS1FPmxMrc9jCI70Rusx67EYdYPyAu47F2cvUf8PwX0o6AUzfNTQ==", - "requires": { - "loader-utils": "^2.0.0" + "node_modules/serve-index/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" } }, - "@docusaurus/theme-classic": { - "version": "2.0.0-beta.6", - "resolved": "https://registry.npmjs.org/@docusaurus/theme-classic/-/theme-classic-2.0.0-beta.6.tgz", - "integrity": "sha512-fMb6gAKUdaojInZabimIJE+yPWs8dQfmZII7v/LHmgxafh/FylmrBkKhyJfa2ix4QRibo9E01LGX44/aKzemxw==", - "requires": { - "@docusaurus/core": "2.0.0-beta.6", - "@docusaurus/plugin-content-blog": "2.0.0-beta.6", - "@docusaurus/plugin-content-docs": "2.0.0-beta.6", - "@docusaurus/plugin-content-pages": "2.0.0-beta.6", - "@docusaurus/theme-common": "2.0.0-beta.6", - "@docusaurus/types": "2.0.0-beta.6", - "@docusaurus/utils": "2.0.0-beta.6", - "@docusaurus/utils-common": "2.0.0-beta.6", - "@docusaurus/utils-validation": "2.0.0-beta.6", - "@mdx-js/mdx": "^1.6.21", - "@mdx-js/react": "^1.6.21", - "chalk": "^4.1.1", - "clsx": "^1.1.1", - "copy-text-to-clipboard": "^3.0.1", - "fs-extra": "^10.0.0", - "globby": "^11.0.2", - "infima": "0.2.0-alpha.33", - "lodash": "^4.17.20", - "parse-numeric-range": "^1.2.0", - "postcss": "^8.2.15", - "prism-react-renderer": "^1.2.1", - "prismjs": "^1.23.0", - "prop-types": "^15.7.2", - "react-router-dom": "^5.2.0", - "rtlcss": "^3.1.2" + "node_modules/serve-index/node_modules/depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", + "engines": { + "node": ">= 0.6" } }, - "@docusaurus/theme-common": { - "version": "2.0.0-beta.6", - "resolved": "https://registry.npmjs.org/@docusaurus/theme-common/-/theme-common-2.0.0-beta.6.tgz", - "integrity": "sha512-53nFWMjpFdyHEvBfQQQoDm9rNKgGangy7vSp1B/F3+uRyYAItE7O4l8MdOALXFALlddiiPYvCtI1qGx2dnzndA==", - "requires": { - "@docusaurus/core": "2.0.0-beta.6", - "@docusaurus/plugin-content-blog": "2.0.0-beta.6", - "@docusaurus/plugin-content-docs": "2.0.0-beta.6", - "@docusaurus/plugin-content-pages": "2.0.0-beta.6", - "@docusaurus/types": "2.0.0-beta.6", - "clsx": "^1.1.1", - "fs-extra": "^10.0.0", - "tslib": "^2.1.0" + "node_modules/serve-index/node_modules/http-errors": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": ">= 1.4.0 < 2" + }, + "engines": { + "node": ">= 0.6" } }, - "@docusaurus/theme-search-algolia": { - "version": "2.0.0-beta.6", - "resolved": "https://registry.npmjs.org/@docusaurus/theme-search-algolia/-/theme-search-algolia-2.0.0-beta.6.tgz", - "integrity": "sha512-GaaYdf6EEKL3jwmt9LRyiMtNvobOhw4vGuYJKbJcgba/M75kOJSbZPRrhALBAe6o4gOYbV44afzFC/jUUp7dsA==", - "requires": { - "@docsearch/react": "^3.0.0-alpha.39", - "@docusaurus/core": "2.0.0-beta.6", - "@docusaurus/theme-common": "2.0.0-beta.6", - "@docusaurus/utils": "2.0.0-beta.6", - "@docusaurus/utils-validation": "2.0.0-beta.6", - "algoliasearch": "^4.8.4", - "algoliasearch-helper": "^3.3.4", - "clsx": "^1.1.1", - "eta": "^1.12.1", - "lodash": "^4.17.20" - } + "node_modules/serve-index/node_modules/inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" }, - "@docusaurus/types": { - "version": "2.0.0-beta.6", - "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-2.0.0-beta.6.tgz", - "integrity": "sha512-TrwxyI93XTZEhOmdEI8FPKDbGV61zE9PzXCdE1alwz1NOV+YXwcv+9sRTZEVLqBpr+TIja+IeeS6mxnyen/Ptg==", - "requires": { - "commander": "^5.1.0", - "joi": "^17.4.0", - "querystring": "0.2.0", - "webpack": "^5.40.0", - "webpack-merge": "^5.8.0" - } + "node_modules/serve-index/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" }, - "@docusaurus/utils": { - "version": "2.0.0-beta.6", - "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-2.0.0-beta.6.tgz", - "integrity": "sha512-S72/o7VDaTvrXJy+NpfuctghGGoMW30m94PMkrL3I6V+o5eE2Uzax7dbM++moclmHvi0/Khv+TXmRIQs6ZvwgQ==", - "requires": { - "@docusaurus/types": "2.0.0-beta.6", - "@types/github-slugger": "^1.3.0", - "chalk": "^4.1.1", - "escape-string-regexp": "^4.0.0", - "fs-extra": "^10.0.0", - "globby": "^11.0.4", - "gray-matter": "^4.0.3", - "lodash": "^4.17.20", - "micromatch": "^4.0.4", - "resolve-pathname": "^3.0.0", - "tslib": "^2.2.0" - }, - "dependencies": { - "escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==" - } + "node_modules/serve-index/node_modules/setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==" + }, + "node_modules/serve-index/node_modules/statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", + "engines": { + "node": ">= 0.6" } }, - "@docusaurus/utils-common": { - "version": "2.0.0-beta.6", - "resolved": "https://registry.npmjs.org/@docusaurus/utils-common/-/utils-common-2.0.0-beta.6.tgz", - "integrity": "sha512-MKm6bJxvsYWRl072jLR60z+71tTWSxoERh2eTmCYlegFnu3Tby3HOC8I3jDcC6VpVuoDGsBGNoQbOgy2LqQbXQ==", - "requires": { - "@docusaurus/types": "2.0.0-beta.6", - "tslib": "^2.2.0" - } - }, - "@docusaurus/utils-validation": { - "version": "2.0.0-beta.6", - "resolved": "https://registry.npmjs.org/@docusaurus/utils-validation/-/utils-validation-2.0.0-beta.6.tgz", - "integrity": "sha512-v0nk9bpawUd2JFDFyiHDmZuMG+/O1UvxtxvcRbvrxrul+rlzD7Q9CGxMgW3Grp2OCKQ4yFXRidBIccwqON5AVw==", - "requires": { - "@docusaurus/utils": "2.0.0-beta.6", - "chalk": "^4.1.1", - "joi": "^17.4.0", - "tslib": "^2.1.0" - } - }, - "@emotion/is-prop-valid": { - "version": "0.8.8", - "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-0.8.8.tgz", - "integrity": "sha512-u5WtneEAr5IDG2Wv65yhunPSMLIpuKsbuOktRojfrEiEvRyC85LgPMZI63cr7NUqT8ZIGdSVg8ZKGxIug4lXcA==", - "requires": { - "@emotion/memoize": "0.7.4" + "node_modules/serve-static": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "dependencies": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.18.0" + }, + "engines": { + "node": ">= 0.8.0" } }, - "@emotion/memoize": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.7.4.tgz", - "integrity": "sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw==" + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" }, - "@emotion/stylis": { - "version": "0.8.5", - "resolved": "https://registry.npmjs.org/@emotion/stylis/-/stylis-0.8.5.tgz", - "integrity": "sha512-h6KtPihKFn3T9fuIrwvXXUOwlx3rfUvfZIcP5a6rh8Y7zjE3O06hT5Ss4S/YI1AYhuZ1kjaE/5EaOOI2NqSylQ==" + "node_modules/setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=" }, - "@emotion/unitless": { - "version": "0.7.5", - "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.7.5.tgz", - "integrity": "sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg==" + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" }, - "@endiliey/react-ideal-image": { - "version": "0.0.11", - "resolved": "https://registry.npmjs.org/@endiliey/react-ideal-image/-/react-ideal-image-0.0.11.tgz", - "integrity": "sha512-QxMjt/Gvur/gLxSoCy7VIyGGGrGmDN+VHcXkN3R2ApoWX0EYUE+hMgPHSW/PV6VVebZ1Nd4t2UnGRBDihu16JQ==", - "requires": {} + "node_modules/sha.js": { + "version": "2.4.11", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "dependencies": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + }, + "bin": { + "sha.js": "bin.js" + } }, - "@exodus/schemasafe": { - "version": "1.0.0-rc.6", - "resolved": "https://registry.npmjs.org/@exodus/schemasafe/-/schemasafe-1.0.0-rc.6.tgz", - "integrity": "sha512-dDnQizD94EdBwEj/fh3zPRa/HWCS9O5au2PuHhZBbuM3xWHxuaKzPBOEWze7Nn0xW68MIpZ7Xdyn1CoCpjKCuQ==" + "node_modules/shallow-clone": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", + "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", + "dependencies": { + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=8" + } }, - "@hapi/hoek": { - "version": "9.2.1", - "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.2.1.tgz", - "integrity": "sha512-gfta+H8aziZsm8pZa0vj04KO6biEiisppNgA1kbJvFrrWu9Vm7eaUEy76DIxsuTaWvti5fkJVhllWc6ZTE+Mdw==" + "node_modules/shallowequal": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz", + "integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==" }, - "@hapi/topo": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-5.1.0.tgz", - "integrity": "sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==", - "requires": { - "@hapi/hoek": "^9.0.0" + "node_modules/sharp": { + "version": "0.30.4", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.30.4.tgz", + "integrity": "sha512-3Onig53Y6lji4NIZo69s14mERXXY/GV++6CzOYx/Rd8bnTwbhFbL09WZd7Ag/CCnA0WxFID8tkY0QReyfL6v0Q==", + "hasInstallScript": true, + "dependencies": { + "color": "^4.2.3", + "detect-libc": "^2.0.1", + "node-addon-api": "^4.3.0", + "prebuild-install": "^7.0.1", + "semver": "^7.3.7", + "simple-get": "^4.0.1", + "tar-fs": "^2.1.1", + "tunnel-agent": "^0.6.0" + }, + "engines": { + "node": ">=12.13.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" } }, - "@jimp/bmp": { - "version": "0.16.1", - "resolved": "https://registry.npmjs.org/@jimp/bmp/-/bmp-0.16.1.tgz", - "integrity": "sha512-iwyNYQeBawrdg/f24x3pQ5rEx+/GwjZcCXd3Kgc+ZUd+Ivia7sIqBsOnDaMZdKCBPlfW364ekexnlOqyVa0NWg==", - "requires": { - "@babel/runtime": "^7.7.2", - "@jimp/utils": "^0.16.1", - "bmp-js": "^0.1.0" + "node_modules/sharp/node_modules/color": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz", + "integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==", + "dependencies": { + "color-convert": "^2.0.1", + "color-string": "^1.9.0" + }, + "engines": { + "node": ">=12.5.0" } }, - "@jimp/core": { - "version": "0.16.1", - "resolved": "https://registry.npmjs.org/@jimp/core/-/core-0.16.1.tgz", - "integrity": "sha512-la7kQia31V6kQ4q1kI/uLimu8FXx7imWVajDGtwUG8fzePLWDFJyZl0fdIXVCL1JW2nBcRHidUot6jvlRDi2+g==", - "requires": { - "@babel/runtime": "^7.7.2", - "@jimp/utils": "^0.16.1", - "any-base": "^1.1.0", - "buffer": "^5.2.0", - "exif-parser": "^0.1.12", - "file-type": "^9.0.0", - "load-bmfont": "^1.3.1", - "mkdirp": "^0.5.1", - "phin": "^2.9.1", - "pixelmatch": "^4.0.2", - "tinycolor2": "^1.4.1" + "node_modules/sharp/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" } }, - "@jimp/custom": { - "version": "0.16.1", - "resolved": "https://registry.npmjs.org/@jimp/custom/-/custom-0.16.1.tgz", - "integrity": "sha512-DNUAHNSiUI/j9hmbatD6WN/EBIyeq4AO0frl5ETtt51VN1SvE4t4v83ZA/V6ikxEf3hxLju4tQ5Pc3zmZkN/3A==", - "requires": { - "@babel/runtime": "^7.7.2", - "@jimp/core": "^0.16.1" - } + "node_modules/sharp/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, - "@jimp/gif": { - "version": "0.16.1", - "resolved": "https://registry.npmjs.org/@jimp/gif/-/gif-0.16.1.tgz", - "integrity": "sha512-r/1+GzIW1D5zrP4tNrfW+3y4vqD935WBXSc8X/wm23QTY9aJO9Lw6PEdzpYCEY+SOklIFKaJYUAq/Nvgm/9ryw==", - "requires": { - "@babel/runtime": "^7.7.2", - "@jimp/utils": "^0.16.1", - "gifwrap": "^0.9.2", - "omggif": "^1.0.9" + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" } }, - "@jimp/jpeg": { - "version": "0.16.1", - "resolved": "https://registry.npmjs.org/@jimp/jpeg/-/jpeg-0.16.1.tgz", - "integrity": "sha512-8352zrdlCCLFdZ/J+JjBslDvml+fS3Z8gttdml0We759PnnZGqrnPRhkOEOJbNUlE+dD4ckLeIe6NPxlS/7U+w==", - "requires": { - "@babel/runtime": "^7.7.2", - "@jimp/utils": "^0.16.1", - "jpeg-js": "0.4.2" + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "engines": { + "node": ">=8" } }, - "@jimp/plugin-resize": { - "version": "0.16.1", - "resolved": "https://registry.npmjs.org/@jimp/plugin-resize/-/plugin-resize-0.16.1.tgz", - "integrity": "sha512-u4JBLdRI7dargC04p2Ha24kofQBk3vhaf0q8FwSYgnCRwxfvh2RxvhJZk9H7Q91JZp6wgjz/SjvEAYjGCEgAwQ==", - "requires": { - "@babel/runtime": "^7.7.2", - "@jimp/utils": "^0.16.1" - } + "node_modules/shell-quote": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.3.tgz", + "integrity": "sha512-Vpfqwm4EnqGdlsBFNmHhxhElJYrdfcxPThu+ryKS5J8L/fhAwLazFZtq+S+TWZ9ANj2piSQLGj6NQg+lKPmxrw==" }, - "@jimp/png": { - "version": "0.16.1", - "resolved": "https://registry.npmjs.org/@jimp/png/-/png-0.16.1.tgz", - "integrity": "sha512-iyWoCxEBTW0OUWWn6SveD4LePW89kO7ZOy5sCfYeDM/oTPLpR8iMIGvZpZUz1b8kvzFr27vPst4E5rJhGjwsdw==", - "requires": { - "@babel/runtime": "^7.7.2", - "@jimp/utils": "^0.16.1", - "pngjs": "^3.3.3" + "node_modules/shelljs": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.5.tgz", + "integrity": "sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==", + "dependencies": { + "glob": "^7.0.0", + "interpret": "^1.0.0", + "rechoir": "^0.6.2" + }, + "bin": { + "shjs": "bin/shjs" + }, + "engines": { + "node": ">=4" } }, - "@jimp/tiff": { - "version": "0.16.1", - "resolved": "https://registry.npmjs.org/@jimp/tiff/-/tiff-0.16.1.tgz", - "integrity": "sha512-3K3+xpJS79RmSkAvFMgqY5dhSB+/sxhwTFA9f4AVHUK0oKW+u6r52Z1L0tMXHnpbAdR9EJ+xaAl2D4x19XShkQ==", - "requires": { - "@babel/runtime": "^7.7.2", - "utif": "^2.0.1" + "node_modules/should": { + "version": "13.2.3", + "resolved": "https://registry.npmjs.org/should/-/should-13.2.3.tgz", + "integrity": "sha512-ggLesLtu2xp+ZxI+ysJTmNjh2U0TsC+rQ/pfED9bUZZ4DKefP27D+7YJVVTvKsmjLpIi9jAa7itwDGkDDmt1GQ==", + "dependencies": { + "should-equal": "^2.0.0", + "should-format": "^3.0.3", + "should-type": "^1.4.0", + "should-type-adaptors": "^1.0.1", + "should-util": "^1.0.0" } }, - "@jimp/types": { - "version": "0.16.1", - "resolved": "https://registry.npmjs.org/@jimp/types/-/types-0.16.1.tgz", - "integrity": "sha512-g1w/+NfWqiVW4CaXSJyD28JQqZtm2eyKMWPhBBDCJN9nLCN12/Az0WFF3JUAktzdsEC2KRN2AqB1a2oMZBNgSQ==", - "requires": { - "@babel/runtime": "^7.7.2", - "@jimp/bmp": "^0.16.1", - "@jimp/gif": "^0.16.1", - "@jimp/jpeg": "^0.16.1", - "@jimp/png": "^0.16.1", - "@jimp/tiff": "^0.16.1", - "timm": "^1.6.1" + "node_modules/should-equal": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/should-equal/-/should-equal-2.0.0.tgz", + "integrity": "sha512-ZP36TMrK9euEuWQYBig9W55WPC7uo37qzAEmbjHz4gfyuXrEUgF8cUvQVO+w+d3OMfPvSRQJ22lSm8MQJ43LTA==", + "dependencies": { + "should-type": "^1.4.0" } }, - "@jimp/utils": { - "version": "0.16.1", - "resolved": "https://registry.npmjs.org/@jimp/utils/-/utils-0.16.1.tgz", - "integrity": "sha512-8fULQjB0x4LzUSiSYG6ZtQl355sZjxbv8r9PPAuYHzS9sGiSHJQavNqK/nKnpDsVkU88/vRGcE7t3nMU0dEnVw==", - "requires": { - "@babel/runtime": "^7.7.2", - "regenerator-runtime": "^0.13.3" + "node_modules/should-format": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/should-format/-/should-format-3.0.3.tgz", + "integrity": "sha1-m/yPdPo5IFxT04w01xcwPidxJPE=", + "dependencies": { + "should-type": "^1.3.0", + "should-type-adaptors": "^1.0.1" } }, - "@mdx-js/mdx": { - "version": "1.6.22", - "resolved": "https://registry.npmjs.org/@mdx-js/mdx/-/mdx-1.6.22.tgz", - "integrity": "sha512-AMxuLxPz2j5/6TpF/XSdKpQP1NlG0z11dFOlq+2IP/lSgl11GY8ji6S/rgsViN/L0BDvHvUMruRb7ub+24LUYA==", - "requires": { - "@babel/core": "7.12.9", - "@babel/plugin-syntax-jsx": "7.12.1", - "@babel/plugin-syntax-object-rest-spread": "7.8.3", - "@mdx-js/util": "1.6.22", - "babel-plugin-apply-mdx-type-prop": "1.6.22", - "babel-plugin-extract-import-names": "1.6.22", - "camelcase-css": "2.0.1", - "detab": "2.0.4", - "hast-util-raw": "6.0.1", - "lodash.uniq": "4.5.0", - "mdast-util-to-hast": "10.0.1", - "remark-footnotes": "2.0.0", - "remark-mdx": "1.6.22", - "remark-parse": "8.0.3", - "remark-squeeze-paragraphs": "4.0.0", - "style-to-object": "0.3.0", - "unified": "9.2.0", - "unist-builder": "2.0.3", - "unist-util-visit": "2.0.3" - }, + "node_modules/should-type": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/should-type/-/should-type-1.4.0.tgz", + "integrity": "sha1-B1bYzoRt/QmEOmlHcZ36DUz/XPM=" + }, + "node_modules/should-type-adaptors": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/should-type-adaptors/-/should-type-adaptors-1.1.0.tgz", + "integrity": "sha512-JA4hdoLnN+kebEp2Vs8eBe9g7uy0zbRo+RMcU0EsNy+R+k049Ki+N5tT5Jagst2g7EAja+euFuoXFCa8vIklfA==", "dependencies": { - "@babel/core": { - "version": "7.12.9", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.12.9.tgz", - "integrity": "sha512-gTXYh3M5wb7FRXQy+FErKFAv90BnlOuNn1QkCK2lREoPAjrQCO49+HVSrFoe5uakFAF5eenS75KbO2vQiLrTMQ==", - "requires": { - "@babel/code-frame": "^7.10.4", - "@babel/generator": "^7.12.5", - "@babel/helper-module-transforms": "^7.12.1", - "@babel/helpers": "^7.12.5", - "@babel/parser": "^7.12.7", - "@babel/template": "^7.12.7", - "@babel/traverse": "^7.12.9", - "@babel/types": "^7.12.7", - "convert-source-map": "^1.7.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.1", - "json5": "^2.1.2", - "lodash": "^4.17.19", - "resolve": "^1.3.2", - "semver": "^5.4.1", - "source-map": "^0.5.0" - } + "should-type": "^1.3.0", + "should-util": "^1.0.0" + } + }, + "node_modules/should-util": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/should-util/-/should-util-1.0.1.tgz", + "integrity": "sha512-oXF8tfxx5cDk8r2kYqlkUJzZpDBqVY/II2WhvU0n9Y3XYvAYRmeaf1PvvIvTgPnv4KJ+ES5M0PyDq5Jp+Ygy2g==" + }, + "node_modules/side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "dependencies": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "node_modules/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" }, - "@babel/plugin-syntax-jsx": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.12.1.tgz", - "integrity": "sha512-1yRi7yAtB0ETgxdY9ti/p2TivUxJkTdhu/ZbF9MshVGqOx1TdB3b7xCXs49Fupgg50N45KcAsRP/ZqWjs9SRjg==", - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } + { + "type": "patreon", + "url": "https://www.patreon.com/feross" }, - "is-buffer": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz", - "integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==" + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" }, - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + { + "type": "patreon", + "url": "https://www.patreon.com/feross" }, - "unified": { - "version": "9.2.0", - "resolved": "https://registry.npmjs.org/unified/-/unified-9.2.0.tgz", - "integrity": "sha512-vx2Z0vY+a3YoTj8+pttM3tiJHCwY5UFbYdiWrwBEbHmK8pvsPj2rtAX2BFfgXen8T39CJWblWRDT4L5WGXtDdg==", - "requires": { - "bail": "^1.0.0", - "extend": "^3.0.0", - "is-buffer": "^2.0.0", - "is-plain-obj": "^2.0.0", - "trough": "^1.0.0", - "vfile": "^4.0.0" - } + { + "type": "consulting", + "url": "https://feross.org/support" } + ], + "dependencies": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" } }, - "@mdx-js/react": { - "version": "1.6.22", - "resolved": "https://registry.npmjs.org/@mdx-js/react/-/react-1.6.22.tgz", - "integrity": "sha512-TDoPum4SHdfPiGSAaRBw7ECyI8VaHpK8GJugbJIJuqyh6kzw9ZLJZW3HGL3NNrJGxcAixUvqROm+YuQOo5eXtg==", - "requires": {} - }, - "@mdx-js/util": { - "version": "1.6.22", - "resolved": "https://registry.npmjs.org/@mdx-js/util/-/util-1.6.22.tgz", - "integrity": "sha512-H1rQc1ZOHANWBvPcW+JpGwr+juXSxM8Q8YCkm3GhZd8REu1fHR3z99CErO1p9pkcfcxZnMdIZdIsXkOHY0NilA==" + "node_modules/simple-html-tokenizer": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/simple-html-tokenizer/-/simple-html-tokenizer-0.1.1.tgz", + "integrity": "sha1-BcLuxXn//+FFoDCsJs/qYbmA+r4=", + "dev": true }, - "@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "requires": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" + "node_modules/simple-swizzle": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", + "integrity": "sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=", + "dependencies": { + "is-arrayish": "^0.3.1" } }, - "@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==" + "node_modules/simple-swizzle/node_modules/is-arrayish": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", + "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==" }, - "@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "requires": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" + "node_modules/sirv": { + "version": "1.0.19", + "resolved": "https://registry.npmjs.org/sirv/-/sirv-1.0.19.tgz", + "integrity": "sha512-JuLThK3TnZG1TAKDwNIqNq6QA2afLOCcm+iE8D1Kj3GA40pSPsxQjjJl0J8X3tsR7T+CP1GavpzLwYkgVLWrZQ==", + "dependencies": { + "@polka/url": "^1.0.0-next.20", + "mrmime": "^1.0.0", + "totalist": "^1.0.0" + }, + "engines": { + "node": ">= 10" } }, - "@polka/url": { - "version": "1.0.0-next.21", - "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.21.tgz", - "integrity": "sha512-a5Sab1C4/icpTZVzZc5Ghpz88yQtGOyNqYXcZgOssB2uuAr+wF/MvN6bgtW32q7HHrvBki+BsZ0OuNv6EV3K9g==" + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==" }, - "@redocly/ajv": { - "version": "8.6.2", - "resolved": "https://registry.npmjs.org/@redocly/ajv/-/ajv-8.6.2.tgz", - "integrity": "sha512-tU8fQs0D76ZKhJ2cWtnfQthWqiZgGBx0gH0+5D8JvaBEBaqA8foPPBt3Nonwr3ygyv5xrw2IzKWgIY86BlGs+w==", - "requires": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - }, + "node_modules/sitemap": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/sitemap/-/sitemap-7.1.1.tgz", + "integrity": "sha512-mK3aFtjz4VdJN0igpIJrinf3EO8U8mxOPsTBzSsy06UtjZQJ3YY3o3Xa7zSc5nMqcMrRwlChHZ18Kxg0caiPBg==", "dependencies": { - "json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" - } - } - }, - "@redocly/openapi-core": { - "version": "1.0.0-beta.63", - "resolved": "https://registry.npmjs.org/@redocly/openapi-core/-/openapi-core-1.0.0-beta.63.tgz", - "integrity": "sha512-ZnIoUyZ6BJZ4wnkGM9YAHe8MqHNcgEHVTjM1IsZkvwoDQ6TTV/B7P7gHOKCcgkyBb/sQNShgSAO5Y+lIfKU2+g==", - "requires": { - "@redocly/ajv": "^8.6.2", - "@types/node": "^14.11.8", - "colorette": "^1.2.0", - "js-levenshtein": "^1.1.6", - "js-yaml": "^4.1.0", - "lodash.isequal": "^4.5.0", - "minimatch": "^3.0.4", - "node-fetch": "^2.6.1", - "yaml-ast-parser": "0.0.43" + "@types/node": "^17.0.5", + "@types/sax": "^1.2.1", + "arg": "^5.0.0", + "sax": "^1.2.4" }, - "dependencies": { - "@types/node": { - "version": "14.17.25", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.17.25.tgz", - "integrity": "sha512-85DGKK4X9h+JEbs69xggu9j6y/aAExbfZzTrUMSqSwATwYXywbxRLaNQyJ7WibJjsC4OcxJWJwtuANUzDqMc7A==" - }, - "argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" - }, - "js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "requires": { - "argparse": "^2.0.1" - } - } + "bin": { + "sitemap": "dist/cli.js" + }, + "engines": { + "node": ">=12.0.0", + "npm": ">=5.6.0" } }, - "@redocly/react-dropdown-aria": { - "version": "2.0.12", - "resolved": "https://registry.npmjs.org/@redocly/react-dropdown-aria/-/react-dropdown-aria-2.0.12.tgz", - "integrity": "sha512-feQEZlyBvQsbT/fvpJ4jJ5OLGaUPpnskHYDsY8DGpPymN+HUeDQrqkBEbbKRwMKidFTI2cxk2kJNNTnvdS9jyw==", - "requires": {} - }, - "@sideway/address": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.2.tgz", - "integrity": "sha512-idTz8ibqWFrPU8kMirL0CoPH/A29XOzzAzpyN3zQ4kAWnzmNfFmRaoMNN6VI8ske5M73HZyhIaW4OuSFIdM4oA==", - "requires": { - "@hapi/hoek": "^9.0.0" + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "engines": { + "node": ">=8" } }, - "@sideway/formula": { + "node_modules/slice-ansi": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.0.tgz", - "integrity": "sha512-vHe7wZ4NOXVfkoRb8T5otiENVlT7a3IAiw7H5M2+GO+9CDgcVUUsX1zalAztCmwyOr2RUTGJdgB+ZvSVqmdHmg==" - }, - "@sideway/pinpoint": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@sideway/pinpoint/-/pinpoint-2.0.0.tgz", - "integrity": "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==" - }, - "@sindresorhus/is": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", - "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==" - }, - "@slorber/static-site-generator-webpack-plugin": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@slorber/static-site-generator-webpack-plugin/-/static-site-generator-webpack-plugin-4.0.1.tgz", - "integrity": "sha512-PSv4RIVO1Y3kvHxjvqeVisk3E9XFoO04uwYBDWe217MFqKspplYswTuKLiJu0aLORQWzuQjfVsSlLPojwfYsLw==", - "requires": { - "bluebird": "^3.7.1", - "cheerio": "^0.22.0", - "eval": "^0.1.4", - "url": "^0.11.0", - "webpack-sources": "^1.4.3" + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz", + "integrity": "sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" }, + "engines": { + "node": ">=8" + } + }, + "node_modules/slice-ansi/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" - }, - "webpack-sources": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", - "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", - "requires": { - "source-list-map": "^2.0.0", - "source-map": "~0.6.1" - } - } + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "@svgr/babel-plugin-add-jsx-attribute": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-5.4.0.tgz", - "integrity": "sha512-ZFf2gs/8/6B8PnSofI0inYXr2SDNTDScPXhN7k5EqD4aZ3gi6u+rbmZHVB8IM3wDyx8ntKACZbtXSm7oZGRqVg==" + "node_modules/slice-ansi/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } }, - "@svgr/babel-plugin-remove-jsx-attribute": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-5.4.0.tgz", - "integrity": "sha512-yaS4o2PgUtwLFGTKbsiAy6D0o3ugcUhWK0Z45umJ66EPWunAz9fuFw2gJuje6wqQvQWOTJvIahUwndOXb7QCPg==" + "node_modules/slice-ansi/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true }, - "@svgr/babel-plugin-remove-jsx-empty-expression": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-5.0.1.tgz", - "integrity": "sha512-LA72+88A11ND/yFIMzyuLRSMJ+tRKeYKeQ+mR3DcAZ5I4h5CPWN9AHyUzJbWSYp/u2u0xhmgOe0+E41+GjEueA==" + "node_modules/slugify": { + "version": "1.6.5", + "resolved": "https://registry.npmjs.org/slugify/-/slugify-1.6.5.tgz", + "integrity": "sha512-8mo9bslnBO3tr5PEVFzMPIWwWnipGS0xVbYf65zxDqfNwmzYn1LpiKNrR6DlClusuvo+hDHd1zKpmfAe83NQSQ==", + "engines": { + "node": ">=8.0.0" + } }, - "@svgr/babel-plugin-replace-jsx-attribute-value": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-5.0.1.tgz", - "integrity": "sha512-PoiE6ZD2Eiy5mK+fjHqwGOS+IXX0wq/YDtNyIgOrc6ejFnxN4b13pRpiIPbtPwHEc+NT2KCjteAcq33/F1Y9KQ==" + "node_modules/sockjs": { + "version": "0.3.24", + "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz", + "integrity": "sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==", + "dependencies": { + "faye-websocket": "^0.11.3", + "uuid": "^8.3.2", + "websocket-driver": "^0.7.4" + } }, - "@svgr/babel-plugin-svg-dynamic-title": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-5.4.0.tgz", - "integrity": "sha512-zSOZH8PdZOpuG1ZVx/cLVePB2ibo3WPpqo7gFIjLV9a0QsuQAzJiwwqmuEdTaW2pegyBE17Uu15mOgOcgabQZg==" + "node_modules/sockjs/node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "bin": { + "uuid": "dist/bin/uuid" + } }, - "@svgr/babel-plugin-svg-em-dimensions": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-5.4.0.tgz", - "integrity": "sha512-cPzDbDA5oT/sPXDCUYoVXEmm3VIoAWAPT6mSPTJNbQaBNUuEKVKyGH93oDY4e42PYHRW67N5alJx/eEol20abw==" + "node_modules/sort-css-media-queries": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/sort-css-media-queries/-/sort-css-media-queries-2.0.4.tgz", + "integrity": "sha512-PAIsEK/XupCQwitjv7XxoMvYhT7EAfyzI3hsy/MyDgTvc+Ft55ctdkctJLOy6cQejaIC+zjpUL4djFVm2ivOOw==", + "engines": { + "node": ">= 6.3.0" + } }, - "@svgr/babel-plugin-transform-react-native-svg": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-5.4.0.tgz", - "integrity": "sha512-3eYP/SaopZ41GHwXma7Rmxcv9uRslRDTY1estspeB1w1ueZWd/tPlMfEOoccYpEMZU3jD4OU7YitnXcF5hLW2Q==" + "node_modules/source-list-map": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz", + "integrity": "sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==" }, - "@svgr/babel-plugin-transform-svg-component": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-5.5.0.tgz", - "integrity": "sha512-q4jSH1UUvbrsOtlo/tKcgSeiCHRSBdXoIoqX1pgcKK/aU3JD27wmMKwGtpB8qRYUYoyXvfGxUVKchLuR5pB3rQ==" + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "engines": { + "node": ">=0.10.0" + } }, - "@svgr/babel-preset": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-preset/-/babel-preset-5.5.0.tgz", - "integrity": "sha512-4FiXBjvQ+z2j7yASeGPEi8VD/5rrGQk4Xrq3EdJmoZgz/tpqChpo5hgXDvmEauwtvOc52q8ghhZK4Oy7qph4ig==", - "requires": { - "@svgr/babel-plugin-add-jsx-attribute": "^5.4.0", - "@svgr/babel-plugin-remove-jsx-attribute": "^5.4.0", - "@svgr/babel-plugin-remove-jsx-empty-expression": "^5.0.1", - "@svgr/babel-plugin-replace-jsx-attribute-value": "^5.0.1", - "@svgr/babel-plugin-svg-dynamic-title": "^5.4.0", - "@svgr/babel-plugin-svg-em-dimensions": "^5.4.0", - "@svgr/babel-plugin-transform-react-native-svg": "^5.4.0", - "@svgr/babel-plugin-transform-svg-component": "^5.5.0" + "node_modules/source-map-js": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", + "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", + "engines": { + "node": ">=0.10.0" } }, - "@svgr/core": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@svgr/core/-/core-5.5.0.tgz", - "integrity": "sha512-q52VOcsJPvV3jO1wkPtzTuKlvX7Y3xIcWRpCMtBF3MrteZJtBfQw/+u0B1BHy5ColpQc1/YVTrPEtSYIMNZlrQ==", - "requires": { - "@svgr/plugin-jsx": "^5.5.0", - "camelcase": "^6.2.0", - "cosmiconfig": "^7.0.0" + "node_modules/source-map-resolve": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.6.0.tgz", + "integrity": "sha512-KXBr9d/fO/bWo97NXsPIAW1bFSBOuCnjbNTBMO7N59hsv5i9yzRDfcYwwt0l04+VqnKC+EwzvJZIP/qkuMgR/w==", + "deprecated": "See https://github.com/lydell/source-map-resolve#deprecated", + "dev": true, + "dependencies": { + "atob": "^2.1.2", + "decode-uri-component": "^0.2.0" } }, - "@svgr/hast-util-to-babel-ast": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-5.5.0.tgz", - "integrity": "sha512-cAaR/CAiZRB8GP32N+1jocovUtvlj0+e65TB50/6Lcime+EA49m/8l+P2ko+XPJ4dw3xaPS3jOL4F2X4KWxoeQ==", - "requires": { - "@babel/types": "^7.12.6" + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" } }, - "@svgr/plugin-jsx": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@svgr/plugin-jsx/-/plugin-jsx-5.5.0.tgz", - "integrity": "sha512-V/wVh33j12hGh05IDg8GpIUXbjAPnTdPTKuP4VNLggnwaHMPNQNae2pRnyTAILWCQdz5GyMqtO488g7CKM8CBA==", - "requires": { - "@babel/core": "^7.12.3", - "@svgr/babel-preset": "^5.5.0", - "@svgr/hast-util-to-babel-ast": "^5.5.0", - "svg-parser": "^2.0.2" + "node_modules/space-separated-tokens": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-1.1.5.tgz", + "integrity": "sha512-q/JSVd1Lptzhf5bkYm4ob4iWPjx0KiRe3sRFBNrVqbJkFaBm5vbbowy1mymoPNLRa52+oadOhJ+K49wsSeSjTA==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" } }, - "@svgr/plugin-svgo": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@svgr/plugin-svgo/-/plugin-svgo-5.5.0.tgz", - "integrity": "sha512-r5swKk46GuQl4RrVejVwpeeJaydoxkdwkM1mBKOgJLBUJPGaLci6ylg/IjhrRsREKDkr4kbMWdgOtbXEh0fyLQ==", - "requires": { - "cosmiconfig": "^7.0.0", - "deepmerge": "^4.2.2", - "svgo": "^1.2.2" - }, + "node_modules/spdy": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz", + "integrity": "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==", "dependencies": { - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "css-select": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-2.1.0.tgz", - "integrity": "sha512-Dqk7LQKpwLoH3VovzZnkzegqNSuAziQyNZUcrdDM401iY+R5NkGBXGmtO05/yaXQziALuPogeG0b7UAgjnTJTQ==", - "requires": { - "boolbase": "^1.0.0", - "css-what": "^3.2.1", - "domutils": "^1.7.0", - "nth-check": "^1.0.2" - } - }, - "css-tree": { - "version": "1.0.0-alpha.37", - "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.37.tgz", - "integrity": "sha512-DMxWJg0rnz7UgxKT0Q1HU/L9BeJI0M6ksor0OgqOnF+aRCDWg/N2641HmVyU9KVIu0OVVWOb2IpC9A+BJRnejg==", - "requires": { - "mdn-data": "2.0.4", - "source-map": "^0.6.1" - } - }, - "css-what": { - "version": "3.4.2", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-3.4.2.tgz", - "integrity": "sha512-ACUm3L0/jiZTqfzRM3Hi9Q8eZqd6IK37mMWPLz9PJxkLWllYeRf+EHUSHYEtFop2Eqytaq1FizFVh7XfBnXCDQ==" - }, - "dom-serializer": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz", - "integrity": "sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==", - "requires": { - "domelementtype": "^2.0.1", - "entities": "^2.0.0" - }, - "dependencies": { - "domelementtype": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz", - "integrity": "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A==" - } - } - }, - "domelementtype": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", - "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==" - }, - "domutils": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz", - "integrity": "sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==", - "requires": { - "dom-serializer": "0", - "domelementtype": "1" - } - }, - "mdn-data": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.4.tgz", - "integrity": "sha512-iV3XNKw06j5Q7mi6h+9vbx23Tv7JkjEVgKHW4pimwyDGWm0OIQntJJ+u1C6mg6mK1EaTv42XQ7w76yuzH7M2cA==" - }, - "nth-check": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz", - "integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==", - "requires": { - "boolbase": "~1.0.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" - }, - "svgo": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/svgo/-/svgo-1.3.2.tgz", - "integrity": "sha512-yhy/sQYxR5BkC98CY7o31VGsg014AKLEPxdfhora76l36hD9Rdy5NZA/Ocn6yayNPgSamYdtX2rFJdcv07AYVw==", - "requires": { - "chalk": "^2.4.1", - "coa": "^2.0.2", - "css-select": "^2.0.0", - "css-select-base-adapter": "^0.1.1", - "css-tree": "1.0.0-alpha.37", - "csso": "^4.0.2", - "js-yaml": "^3.13.1", - "mkdirp": "~0.5.1", - "object.values": "^1.1.0", - "sax": "~1.2.4", - "stable": "^0.1.8", - "unquote": "~1.1.1", - "util.promisify": "~1.0.0" - } - } + "debug": "^4.1.0", + "handle-thing": "^2.0.0", + "http-deceiver": "^1.2.7", + "select-hose": "^2.0.0", + "spdy-transport": "^3.0.0" + }, + "engines": { + "node": ">=6.0.0" } }, - "@svgr/webpack": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@svgr/webpack/-/webpack-5.5.0.tgz", - "integrity": "sha512-DOBOK255wfQxguUta2INKkzPj6AIS6iafZYiYmHn6W3pHlycSRRlvWKCfLDG10fXfLWqE3DJHgRUOyJYmARa7g==", - "requires": { - "@babel/core": "^7.12.3", - "@babel/plugin-transform-react-constant-elements": "^7.12.1", - "@babel/preset-env": "^7.12.1", - "@babel/preset-react": "^7.12.5", - "@svgr/core": "^5.5.0", - "@svgr/plugin-jsx": "^5.5.0", - "@svgr/plugin-svgo": "^5.5.0", - "loader-utils": "^2.0.0" + "node_modules/spdy-transport": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz", + "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==", + "dependencies": { + "debug": "^4.1.0", + "detect-node": "^2.0.4", + "hpack.js": "^2.1.6", + "obuf": "^1.1.2", + "readable-stream": "^3.0.6", + "wbuf": "^1.7.3" } }, - "@szmarczak/http-timer": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz", - "integrity": "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==", - "requires": { - "defer-to-connect": "^1.0.1" + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" + }, + "node_modules/sshpk": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.17.0.tgz", + "integrity": "sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ==", + "dev": true, + "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" + }, + "bin": { + "sshpk-conv": "bin/sshpk-conv", + "sshpk-sign": "bin/sshpk-sign", + "sshpk-verify": "bin/sshpk-verify" + }, + "engines": { + "node": ">=0.10.0" } }, - "@trysound/sax": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", - "integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==" + "node_modules/stable": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz", + "integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==", + "deprecated": "Modern JS already guarantees Array#sort() is a stable sort, so this library is deprecated. See the compatibility table on MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#browser_compatibility" }, - "@types/eslint": { - "version": "7.28.1", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-7.28.1.tgz", - "integrity": "sha512-XhZKznR3i/W5dXqUhgU9fFdJekufbeBd5DALmkuXoeFcjbQcPk+2cL+WLHf6Q81HWAnM2vrslIHpGVyCAviRwg==", - "requires": { - "@types/estree": "*", - "@types/json-schema": "*" + "node_modules/stack-utils": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.5.tgz", + "integrity": "sha512-xrQcmYhOsn/1kX+Vraq+7j4oE2j/6BFscZ0etmYg81xuM8Gq0022Pxb8+IqgOFUIaxHs0KaSb7T1+OegiNrNFA==", + "dev": true, + "dependencies": { + "escape-string-regexp": "^2.0.0" + }, + "engines": { + "node": ">=10" } }, - "@types/eslint-scope": { - "version": "3.7.1", - "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.1.tgz", - "integrity": "sha512-SCFeogqiptms4Fg29WpOTk5nHIzfpKCemSN63ksBQYKTcXoJEmJagV+DhVmbapZzY4/5YaOV1nZwrsU79fFm1g==", - "requires": { - "@types/eslint": "*", - "@types/estree": "*" + "node_modules/stack-utils/node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true, + "engines": { + "node": ">=8" } }, - "@types/estree": { - "version": "0.0.50", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.50.tgz", - "integrity": "sha512-C6N5s2ZFtuZRj54k2/zyRhNDjJwwcViAM3Nbm8zjBpbqAdZ00mr0CFxvSKeO8Y/e03WVFLpQMdHYVfUd6SB+Hw==" - }, - "@types/github-slugger": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@types/github-slugger/-/github-slugger-1.3.0.tgz", - "integrity": "sha512-J/rMZa7RqiH/rT29TEVZO4nBoDP9XJOjnbbIofg7GQKs4JIduEO3WLpte+6WeUz/TcrXKlY+bM7FYrp8yFB+3g==" - }, - "@types/glob": { - "version": "7.1.4", - "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.4.tgz", - "integrity": "sha512-w+LsMxKyYQm347Otw+IfBXOv9UWVjpHpCDdbBMt8Kz/xbvCYNjP+0qPh91Km3iKfSRLBB0P7fAMf0KHrPu+MyA==", - "requires": { - "@types/minimatch": "*", - "@types/node": "*" + "node_modules/state-toggle": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/state-toggle/-/state-toggle-1.0.3.tgz", + "integrity": "sha512-d/5Z4/2iiCnHw6Xzghyhb+GcmF89bxwgXG60wjIiZaxnymbyOmI8Hk4VqHXiVVp6u2ysaskFfXg3ekCj4WNftQ==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" } }, - "@types/hast": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/@types/hast/-/hast-2.3.4.tgz", - "integrity": "sha512-wLEm0QvaoawEDoTRwzTXp4b4jpwiJDvR5KMnFnVodm3scufTlBOWRD6N1OBf9TZMhjlNsSfcO5V+7AF4+Vy+9g==", - "requires": { - "@types/unist": "*" + "node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "engines": { + "node": ">= 0.8" } }, - "@types/html-minifier-terser": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-5.1.2.tgz", - "integrity": "sha512-h4lTMgMJctJybDp8CQrxTUiiYmedihHWkjnF/8Pxseu2S6Nlfcy8kwboQ8yejh456rP2yWoEVm1sS/FVsfM48w==" - }, - "@types/json-schema": { - "version": "7.0.9", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.9.tgz", - "integrity": "sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==" + "node_modules/std-env": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.1.1.tgz", + "integrity": "sha512-/c645XdExBypL01TpFKiG/3RAa/Qmu+zRi0MwAmrdEkwHNuN0ebo8ccAXBBDa5Z0QOJgBskUIbuCK91x0sCVEw==" }, - "@types/lodash": { - "version": "4.14.175", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.175.tgz", - "integrity": "sha512-XmdEOrKQ8a1Y/yxQFOMbC47G/V2VDO1GvMRnl4O75M4GW/abC5tnfzadQYkqEveqRM1dEJGFFegfPNA2vvx2iw==" + "node_modules/stickyfill": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/stickyfill/-/stickyfill-1.1.1.tgz", + "integrity": "sha1-OUE/7p0CXHSn5ZzuyyN4TMDxfwI=" }, - "@types/mdast": { - "version": "3.0.10", - "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.10.tgz", - "integrity": "sha512-W864tg/Osz1+9f4lrGTZpCSO5/z4608eUp19tbozkq2HJK6i3z1kT0H9tlADXuYIb1YYOBByU4Jsqkk75q48qA==", - "requires": { - "@types/unist": "*" + "node_modules/stream-browserify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-3.0.0.tgz", + "integrity": "sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA==", + "dependencies": { + "inherits": "~2.0.4", + "readable-stream": "^3.5.0" } }, - "@types/minimatch": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.5.tgz", - "integrity": "sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==" - }, - "@types/node": { - "version": "16.10.8", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.10.8.tgz", - "integrity": "sha512-atlRPM4gM/BABQ2MiXm38veMVL+kz6vFAj1hvqC1wDxWNrnr3t58PozLSecgLBrKNGISunQl2SxxIJcYV3tO2w==" - }, - "@types/parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==" - }, - "@types/parse5": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/@types/parse5/-/parse5-5.0.3.tgz", - "integrity": "sha512-kUNnecmtkunAoQ3CnjmMkzNU/gtxG8guhi+Fk2U/kOpIKjIMKnXGp4IJCgQJrXSgMsWYimYG4TGjz/UzbGEBTw==" - }, - "@types/q": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/@types/q/-/q-1.5.5.tgz", - "integrity": "sha512-L28j2FcJfSZOnL1WBjDYp2vUHCeIFlyYI/53EwD/rKUBQ7MtUUfbQWiyKJGpcnv4/WgrhWsFKrcPstcAt/J0tQ==" - }, - "@types/sax": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@types/sax/-/sax-1.2.3.tgz", - "integrity": "sha512-+QSw6Tqvs/KQpZX8DvIl3hZSjNFLW/OqE5nlyHXtTwODaJvioN2rOWpBNEWZp2HZUFhOh+VohmJku/WxEXU2XA==", - "requires": { - "@types/node": "*" + "node_modules/stream-http": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-3.2.0.tgz", + "integrity": "sha512-Oq1bLqisTyK3TSCXpPbT4sdeYNdmyZJv1LxpEm2vu1ZhK89kSE5YXwZc3cWk0MagGaKriBh9mCFbVGtO+vY29A==", + "dependencies": { + "builtin-status-codes": "^3.0.0", + "inherits": "^2.0.4", + "readable-stream": "^3.6.0", + "xtend": "^4.0.2" } }, - "@types/unist": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.6.tgz", - "integrity": "sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ==" - }, - "@webassemblyjs/ast": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.1.tgz", - "integrity": "sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw==", - "requires": { - "@webassemblyjs/helper-numbers": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1" + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dependencies": { + "safe-buffer": "~5.2.0" } }, - "@webassemblyjs/floating-point-hex-parser": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz", - "integrity": "sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ==" - }, - "@webassemblyjs/helper-api-error": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz", - "integrity": "sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg==" - }, - "@webassemblyjs/helper-buffer": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz", - "integrity": "sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA==" + "node_modules/string_decoder/node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] }, - "@webassemblyjs/helper-numbers": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz", - "integrity": "sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ==", - "requires": { - "@webassemblyjs/floating-point-hex-parser": "1.11.1", - "@webassemblyjs/helper-api-error": "1.11.1", - "@xtuc/long": "4.2.2" + "node_modules/string-length": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", + "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", + "dev": true, + "dependencies": { + "char-regex": "^1.0.2", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" } }, - "@webassemblyjs/helper-wasm-bytecode": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz", - "integrity": "sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q==" + "node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, - "@webassemblyjs/helper-wasm-section": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz", - "integrity": "sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg==", - "requires": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-buffer": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/wasm-gen": "1.11.1" + "node_modules/string-width/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, - "@webassemblyjs/ieee754": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz", - "integrity": "sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ==", - "requires": { - "@xtuc/ieee754": "^1.2.0" + "node_modules/string-width/node_modules/strip-ansi": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.1.tgz", + "integrity": "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, - "@webassemblyjs/leb128": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.1.tgz", - "integrity": "sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw==", - "requires": { - "@xtuc/long": "4.2.2" + "node_modules/string.prototype.trimend": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz", + "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "@webassemblyjs/utf8": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.1.tgz", - "integrity": "sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ==" - }, - "@webassemblyjs/wasm-edit": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz", - "integrity": "sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA==", - "requires": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-buffer": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/helper-wasm-section": "1.11.1", - "@webassemblyjs/wasm-gen": "1.11.1", - "@webassemblyjs/wasm-opt": "1.11.1", - "@webassemblyjs/wasm-parser": "1.11.1", - "@webassemblyjs/wast-printer": "1.11.1" + "node_modules/string.prototype.trimstart": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz", + "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "@webassemblyjs/wasm-gen": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz", - "integrity": "sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA==", - "requires": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/ieee754": "1.11.1", - "@webassemblyjs/leb128": "1.11.1", - "@webassemblyjs/utf8": "1.11.1" + "node_modules/stringify-object": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/stringify-object/-/stringify-object-3.3.0.tgz", + "integrity": "sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw==", + "dependencies": { + "get-own-enumerable-property-symbols": "^3.0.0", + "is-obj": "^1.0.1", + "is-regexp": "^1.0.0" + }, + "engines": { + "node": ">=4" } }, - "@webassemblyjs/wasm-opt": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz", - "integrity": "sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw==", - "requires": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-buffer": "1.11.1", - "@webassemblyjs/wasm-gen": "1.11.1", - "@webassemblyjs/wasm-parser": "1.11.1" + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" } }, - "@webassemblyjs/wasm-parser": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz", - "integrity": "sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA==", - "requires": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-api-error": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/ieee754": "1.11.1", - "@webassemblyjs/leb128": "1.11.1", - "@webassemblyjs/utf8": "1.11.1" + "node_modules/strip-bom": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "dev": true, + "engines": { + "node": ">=8" } }, - "@webassemblyjs/wast-printer": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz", - "integrity": "sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg==", - "requires": { - "@webassemblyjs/ast": "1.11.1", - "@xtuc/long": "4.2.2" + "node_modules/strip-bom-string": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-bom-string/-/strip-bom-string-1.0.0.tgz", + "integrity": "sha1-5SEekiQ2n7uB1jOi8ABE3IztrZI=", + "engines": { + "node": ">=0.10.0" } }, - "@xtuc/ieee754": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", - "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==" - }, - "@xtuc/long": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", - "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==" - }, - "accepts": { - "version": "1.3.7", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", - "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", - "requires": { - "mime-types": "~2.1.24", - "negotiator": "0.6.2" + "node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "engines": { + "node": ">=6" } }, - "acorn": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.5.0.tgz", - "integrity": "sha512-yXbYeFy+jUuYd3/CDcg2NkIYE991XYX/bje7LmjJigUciaeO1JR4XxXgCIV1/Zc/dRuFEyw1L0pbA+qynJkW5Q==" - }, - "acorn-import-assertions": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz", - "integrity": "sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==", - "requires": {} - }, - "acorn-walk": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", - "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==" - }, - "address": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/address/-/address-1.1.2.tgz", - "integrity": "sha512-aT6camzM4xEA54YVJYSqxz1kv4IHnQZRtThJJHhUMRExaU5spC7jX5ugSwTaTgJliIgs4VhZOk7htClvQ/LmRA==" - }, - "aggregate-error": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", - "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", - "requires": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" + "node_modules/strip-indent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", + "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", + "dev": true, + "dependencies": { + "min-indent": "^1.0.0" + }, + "engines": { + "node": ">=8" } }, - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "ajv-errors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-1.0.1.tgz", - "integrity": "sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ==", - "requires": {} - }, - "ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "requires": {} - }, - "algoliasearch": { - "version": "4.10.5", - "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-4.10.5.tgz", - "integrity": "sha512-KmH2XkiN+8FxhND4nWFbQDkIoU6g2OjfeU9kIv4Lb+EiOOs3Gpp7jvd+JnatsCisAZsnWQdjd7zVlW7I/85QvQ==", - "requires": { - "@algolia/cache-browser-local-storage": "4.10.5", - "@algolia/cache-common": "4.10.5", - "@algolia/cache-in-memory": "4.10.5", - "@algolia/client-account": "4.10.5", - "@algolia/client-analytics": "4.10.5", - "@algolia/client-common": "4.10.5", - "@algolia/client-personalization": "4.10.5", - "@algolia/client-search": "4.10.5", - "@algolia/logger-common": "4.10.5", - "@algolia/logger-console": "4.10.5", - "@algolia/requester-browser-xhr": "4.10.5", - "@algolia/requester-common": "4.10.5", - "@algolia/requester-node-http": "4.10.5", - "@algolia/transporter": "4.10.5" + "node_modules/style-loader": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-1.3.0.tgz", + "integrity": "sha512-V7TCORko8rs9rIqkSrlMfkqA63DfoGBBJmK1kKGCcSi+BWb4cqz0SRsnp4l6rU5iwOEd0/2ePv68SV22VXon4Q==", + "dev": true, + "dependencies": { + "loader-utils": "^2.0.0", + "schema-utils": "^2.7.0" + }, + "engines": { + "node": ">= 8.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.0.0 || ^5.0.0" } }, - "algoliasearch-helper": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/algoliasearch-helper/-/algoliasearch-helper-3.6.0.tgz", - "integrity": "sha512-F4Smiq+Vyv/JJytuKNFuzXndPSb4pjtiHZSkEztQCcB+SORu71A8grgt2NSJhbB5VhqHW19QDtlPKbdYdcNrLg==", - "requires": { - "events": "^1.1.1" - }, + "node_modules/style-to-object": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-0.3.0.tgz", + "integrity": "sha512-CzFnRRXhzWIdItT3OmF8SQfWyahHhjq3HwcMNCNLn+N7klOOqPjMeG/4JSu77D7ypZdGvSzvkrbyeTMizz2VrA==", "dependencies": { - "events": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", - "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=" - } + "inline-style-parser": "0.1.1" } }, - "alphanum-sort": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/alphanum-sort/-/alphanum-sort-1.0.2.tgz", - "integrity": "sha1-l6ERlkmyEa0zaR2fn0hqjsn74KM=" - }, - "ansi-align": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", - "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", - "requires": { - "string-width": "^4.1.0" + "node_modules/styled-components": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/styled-components/-/styled-components-5.3.3.tgz", + "integrity": "sha512-++4iHwBM7ZN+x6DtPPWkCI4vdtwumQ+inA/DdAsqYd4SVgUKJie5vXyzotA00ttcFdQkCng7zc6grwlfIfw+lw==", + "dependencies": { + "@babel/helper-module-imports": "^7.0.0", + "@babel/traverse": "^7.4.5", + "@emotion/is-prop-valid": "^0.8.8", + "@emotion/stylis": "^0.8.4", + "@emotion/unitless": "^0.7.4", + "babel-plugin-styled-components": ">= 1.12.0", + "css-to-react-native": "^3.0.0", + "hoist-non-react-statics": "^3.0.0", + "shallowequal": "^1.1.0", + "supports-color": "^5.5.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/styled-components" + }, + "peerDependencies": { + "react": ">= 16.8.0", + "react-dom": ">= 16.8.0", + "react-is": ">= 16.8.0" } }, - "ansi-colors": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.4.tgz", - "integrity": "sha512-hHUXGagefjN2iRrID63xckIvotOXOojhQKWIPUZ4mNUZ9nLZW+7FMNoE1lOkEhNWYsx/7ysGIuJYCiMAA9FnrA==" - }, - "ansi-escapes": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", - "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", - "requires": { - "type-fest": "^0.21.3" - }, + "node_modules/stylehacks": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-5.1.0.tgz", + "integrity": "sha512-SzLmvHQTrIWfSgljkQCw2++C9+Ne91d/6Sp92I8c5uHTcy/PgeHamwITIbBW9wnFTY/3ZfSXR9HIL6Ikqmcu6Q==", "dependencies": { - "type-fest": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", - "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==" - } + "browserslist": "^4.16.6", + "postcss-selector-parser": "^6.0.4" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" } }, - "ansi-html": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/ansi-html/-/ansi-html-0.0.7.tgz", - "integrity": "sha1-gTWEAhliqenm/QOflA0S9WynhZ4=" + "node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } }, - "ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + "node_modules/supports-hyperlinks": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.2.0.tgz", + "integrity": "sha512-6sXEzV5+I5j8Bmq9/vUphGRM/RJNT9SCURJLjwfOg51heRtguGWDzcaBlgAzKhQa0EVNpPEKzQuBwZ8S8WaCeQ==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0", + "supports-color": "^7.0.0" + }, + "engines": { + "node": ">=8" + } }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "requires": { - "color-convert": "^1.9.0" + "node_modules/supports-hyperlinks/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" } }, - "any-base": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/any-base/-/any-base-1.1.0.tgz", - "integrity": "sha512-uMgjozySS8adZZYePpaWs8cxB9/kdzmpX6SgJZ+wbz1K5eYk5QMYDVJaZKhxyIHUdnnJkfR7SVgStgH7LkGUyg==" + "node_modules/supports-hyperlinks/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } }, - "anymatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", - "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", - "requires": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "aproba": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", - "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + "node_modules/svg-inline-loader": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/svg-inline-loader/-/svg-inline-loader-0.8.2.tgz", + "integrity": "sha512-kbrcEh5n5JkypaSC152eGfGcnT4lkR0eSfvefaUJkLqgGjRQJyKDvvEE/CCv5aTSdfXuc+N98w16iAojhShI3g==", + "dev": true, + "dependencies": { + "loader-utils": "^1.1.0", + "object-assign": "^4.0.1", + "simple-html-tokenizer": "^0.1.1" + } }, - "are-we-there-yet": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz", - "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==", - "requires": { - "delegates": "^1.0.0", - "readable-stream": "^2.0.6" + "node_modules/svg-inline-loader/node_modules/json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dev": true, + "dependencies": { + "minimist": "^1.2.0" }, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/svg-inline-loader/node_modules/loader-utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", + "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", + "dev": true, "dependencies": { - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } - } + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + }, + "engines": { + "node": ">=4.0.0" } }, - "arg": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.1.tgz", - "integrity": "sha512-e0hDa9H2Z9AwFkk2qDlwhoMYE4eToKarchkQHovNdLTCYMHZHeRjI71crOh+dio4K6u1IcwubQqo79Ga4CyAQA==" + "node_modules/svg-parser": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/svg-parser/-/svg-parser-2.0.4.tgz", + "integrity": "sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ==" }, - "argparse": { + "node_modules/svgo": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-1.3.2.tgz", + "integrity": "sha512-yhy/sQYxR5BkC98CY7o31VGsg014AKLEPxdfhora76l36hD9Rdy5NZA/Ocn6yayNPgSamYdtX2rFJdcv07AYVw==", + "deprecated": "This SVGO version is no longer supported. Upgrade to v2.x.x.", + "dependencies": { + "chalk": "^2.4.1", + "coa": "^2.0.2", + "css-select": "^2.0.0", + "css-select-base-adapter": "^0.1.1", + "css-tree": "1.0.0-alpha.37", + "csso": "^4.0.2", + "js-yaml": "^3.13.1", + "mkdirp": "~0.5.1", + "object.values": "^1.1.0", + "sax": "~1.2.4", + "stable": "^0.1.8", + "unquote": "~1.1.1", + "util.promisify": "~1.0.0" + }, + "bin": { + "svgo": "bin/svgo" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/svgo/node_modules/argparse": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "requires": { + "dependencies": { "sprintf-js": "~1.0.2" } }, - "arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=" - }, - "arr-flatten": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", - "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==" - }, - "arr-union": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", - "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=" - }, - "array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" - }, - "array-union": { + "node_modules/svgo/node_modules/css-select": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==" - }, - "array-uniq": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", - "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=" - }, - "array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=" - }, - "asap": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", - "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=" - }, - "asn1.js": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", - "integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==", - "requires": { - "bn.js": "^4.0.0", - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0", - "safer-buffer": "^2.1.0" - }, + "resolved": "https://registry.npmjs.org/css-select/-/css-select-2.1.0.tgz", + "integrity": "sha512-Dqk7LQKpwLoH3VovzZnkzegqNSuAziQyNZUcrdDM401iY+R5NkGBXGmtO05/yaXQziALuPogeG0b7UAgjnTJTQ==", "dependencies": { - "bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" - } + "boolbase": "^1.0.0", + "css-what": "^3.2.1", + "domutils": "^1.7.0", + "nth-check": "^1.0.2" } }, - "assert": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/assert/-/assert-2.0.0.tgz", - "integrity": "sha512-se5Cd+js9dXJnu6Ag2JFc00t+HmHOen+8Q+L7O9zI0PqQXr20uk2J0XQqMxZEeo5U50o8Nvmmx7dZrl+Ufr35A==", - "requires": { - "es6-object-assign": "^1.1.0", - "is-nan": "^1.2.1", - "object-is": "^1.0.1", - "util": "^0.12.0" + "node_modules/svgo/node_modules/css-what": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-3.4.2.tgz", + "integrity": "sha512-ACUm3L0/jiZTqfzRM3Hi9Q8eZqd6IK37mMWPLz9PJxkLWllYeRf+EHUSHYEtFop2Eqytaq1FizFVh7XfBnXCDQ==", + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" } }, - "assign-symbols": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", - "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=" + "node_modules/svgo/node_modules/dom-serializer": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz", + "integrity": "sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==", + "dependencies": { + "domelementtype": "^2.0.1", + "entities": "^2.0.0" + } }, - "async": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", - "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", - "requires": { - "lodash": "^4.17.14" + "node_modules/svgo/node_modules/domutils": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz", + "integrity": "sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==", + "dependencies": { + "dom-serializer": "0", + "domelementtype": "1" } }, - "async-each": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz", - "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==" + "node_modules/svgo/node_modules/domutils/node_modules/domelementtype": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", + "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==" }, - "async-limiter": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", - "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==" - }, - "at-least-node": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", - "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==" - }, - "atob": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", - "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==" - }, - "autoprefixer": { - "version": "10.3.7", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.3.7.tgz", - "integrity": "sha512-EmGpu0nnQVmMhX8ROoJ7Mx8mKYPlcUHuxkwrRYEYMz85lu7H09v8w6R1P0JPdn/hKU32GjpLBFEOuIlDWCRWvg==", - "requires": { - "browserslist": "^4.17.3", - "caniuse-lite": "^1.0.30001264", - "fraction.js": "^4.1.1", - "normalize-range": "^0.1.2", - "picocolors": "^0.2.1", - "postcss-value-parser": "^4.1.0" - }, + "node_modules/svgo/node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", "dependencies": { - "picocolors": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", - "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" - } - } - }, - "available-typed-arrays": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", - "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==" - }, - "axios": { - "version": "0.21.4", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz", - "integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==", - "requires": { - "follow-redirects": "^1.14.0" + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" } }, - "babel-loader": { - "version": "8.2.2", - "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.2.2.tgz", - "integrity": "sha512-JvTd0/D889PQBtUXJ2PXaKU/pjZDMtHA9V2ecm+eNRmmBCMR09a+fmpGTNwnJtFmFl5Ei7Vy47LjBb+L0wQ99g==", - "requires": { - "find-cache-dir": "^3.3.1", - "loader-utils": "^1.4.0", - "make-dir": "^3.1.0", - "schema-utils": "^2.6.5" - }, + "node_modules/svgo/node_modules/nth-check": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz", + "integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==", "dependencies": { - "json5": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", - "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", - "requires": { - "minimist": "^1.2.0" - } - }, - "loader-utils": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", - "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", - "requires": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^1.0.1" - } - }, - "schema-utils": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz", - "integrity": "sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==", - "requires": { - "@types/json-schema": "^7.0.5", - "ajv": "^6.12.4", - "ajv-keywords": "^3.5.2" - } - } + "boolbase": "~1.0.0" } }, - "babel-plugin-apply-mdx-type-prop": { - "version": "1.6.22", - "resolved": "https://registry.npmjs.org/babel-plugin-apply-mdx-type-prop/-/babel-plugin-apply-mdx-type-prop-1.6.22.tgz", - "integrity": "sha512-VefL+8o+F/DfK24lPZMtJctrCVOfgbqLAGZSkxwhazQv4VxPg3Za/i40fu22KR2m8eEda+IfSOlPLUSIiLcnCQ==", - "requires": { - "@babel/helper-plugin-utils": "7.10.4", - "@mdx-js/util": "1.6.22" - }, + "node_modules/swagger2openapi": { + "version": "7.0.8", + "resolved": "https://registry.npmjs.org/swagger2openapi/-/swagger2openapi-7.0.8.tgz", + "integrity": "sha512-upi/0ZGkYgEcLeGieoz8gT74oWHA0E7JivX7aN9mAf+Tc7BQoRBvnIGHoPDw+f9TXTW4s6kGYCZJtauP6OYp7g==", "dependencies": { - "@babel/helper-plugin-utils": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz", - "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==" - } + "call-me-maybe": "^1.0.1", + "node-fetch": "^2.6.1", + "node-fetch-h2": "^2.3.0", + "node-readfiles": "^0.2.0", + "oas-kit-common": "^1.0.8", + "oas-resolver": "^2.5.6", + "oas-schema-walker": "^1.1.5", + "oas-validator": "^5.0.8", + "reftools": "^1.1.9", + "yaml": "^1.10.0", + "yargs": "^17.0.1" + }, + "bin": { + "boast": "boast.js", + "oas-validate": "oas-validate.js", + "swagger2openapi": "swagger2openapi.js" + }, + "funding": { + "url": "https://github.com/Mermade/oas-kit?sponsor=1" } }, - "babel-plugin-dynamic-import-node": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.0.tgz", - "integrity": "sha512-o6qFkpeQEBxcqt0XYlWzAVxNCSCZdUgcR8IRlhD/8DylxjjO4foPcvTW0GGKa/cVt3rvxZ7o5ippJ+/0nvLhlQ==", - "requires": { - "object.assign": "^4.1.0" - } + "node_modules/swagger2openapi/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, - "babel-plugin-extract-import-names": { - "version": "1.6.22", - "resolved": "https://registry.npmjs.org/babel-plugin-extract-import-names/-/babel-plugin-extract-import-names-1.6.22.tgz", - "integrity": "sha512-yJ9BsJaISua7d8zNT7oRG1ZLBJCIdZ4PZqmH8qa9N5AK01ifk3fnkc98AXhtzE7UkfCsEumvoQWgoYLhOnJ7jQ==", - "requires": { - "@babel/helper-plugin-utils": "7.10.4" - }, + "node_modules/swagger2openapi/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dependencies": { - "@babel/helper-plugin-utils": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz", - "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==" - } + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" } }, - "babel-plugin-polyfill-corejs2": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.2.2.tgz", - "integrity": "sha512-kISrENsJ0z5dNPq5eRvcctITNHYXWOA4DUZRFYCz3jYCcvTb/A546LIddmoGNMVYg2U38OyFeNosQwI9ENTqIQ==", - "requires": { - "@babel/compat-data": "^7.13.11", - "@babel/helper-define-polyfill-provider": "^0.2.2", - "semver": "^6.1.1" - }, + "node_modules/swagger2openapi/node_modules/yargs": { + "version": "17.4.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.4.1.tgz", + "integrity": "sha512-WSZD9jgobAg3ZKuCQZSa3g9QOJeCCqLoLAykiWgmXnDo9EPnn4RPf5qVTtzgOx66o6/oqhcA5tHtJXpG8pMt3g==", "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" - } + "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" + }, + "engines": { + "node": ">=12" } }, - "babel-plugin-polyfill-corejs3": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.2.5.tgz", - "integrity": "sha512-ninF5MQNwAX9Z7c9ED+H2pGt1mXdP4TqzlHKyPIYmJIYz0N+++uwdM7RnJukklhzJ54Q84vA4ZJkgs7lu5vqcw==", - "requires": { - "@babel/helper-define-polyfill-provider": "^0.2.2", - "core-js-compat": "^3.16.2" + "node_modules/swagger2openapi/node_modules/yargs-parser": { + "version": "21.0.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.0.1.tgz", + "integrity": "sha512-9BK1jFpLzJROCI5TzwZL/TU4gqjK5xiHV/RfWLOahrjAko/e4DJkRDZQXfvqAsiZzzYhgAzbgz6lg48jcm4GLg==", + "engines": { + "node": ">=12" } }, - "babel-plugin-polyfill-regenerator": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.2.2.tgz", - "integrity": "sha512-Goy5ghsc21HgPDFtzRkSirpZVW35meGoTmTOb2bxqdl60ghub4xOidgNTHaZfQ2FaxQsKmwvXtOAkcIS4SMBWg==", - "requires": { - "@babel/helper-define-polyfill-provider": "^0.2.2" - } + "node_modules/symbol-tree": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", + "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", + "dev": true }, - "babel-plugin-styled-components": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/babel-plugin-styled-components/-/babel-plugin-styled-components-1.13.2.tgz", - "integrity": "sha512-Vb1R3d4g+MUfPQPVDMCGjm3cDocJEUTR7Xq7QS95JWWeksN1wdFRYpD2kulDgI3Huuaf1CZd+NK4KQmqUFh5dA==", - "requires": { - "@babel/helper-annotate-as-pure": "^7.0.0", - "@babel/helper-module-imports": "^7.0.0", - "babel-plugin-syntax-jsx": "^6.18.0", - "lodash": "^4.17.11" + "node_modules/tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "engines": { + "node": ">=6" } }, - "babel-plugin-syntax-jsx": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz", - "integrity": "sha1-CvMqmm4Tyno/1QaeYtew9Y0NiUY=" - }, - "bail": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/bail/-/bail-1.0.5.tgz", - "integrity": "sha512-xFbRxM1tahm08yHBP16MMjVUAvDaBMD38zsM9EMAUN61omwLmKlOpB/Zku5QkjZ8TZ4vn53pj+t518cH0S03RQ==" + "node_modules/tar-fs": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", + "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", + "dependencies": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } }, - "balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + "node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } }, - "base": { - "version": "0.11.2", - "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", - "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", - "requires": { - "cache-base": "^1.0.1", - "class-utils": "^0.3.5", - "component-emitter": "^1.2.1", - "define-property": "^1.0.0", - "isobject": "^3.0.1", - "mixin-deep": "^1.2.0", - "pascalcase": "^0.1.1" + "node_modules/terminal-link": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/terminal-link/-/terminal-link-2.1.1.tgz", + "integrity": "sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ==", + "dev": true, + "dependencies": { + "ansi-escapes": "^4.2.1", + "supports-hyperlinks": "^2.0.0" }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/terser": { + "version": "5.13.1", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.13.1.tgz", + "integrity": "sha512-hn4WKOfwnwbYfe48NgrQjqNOH9jzLqRcIfbYytOXCOv46LBfWr9bDS17MQqOi+BWGD0sJK3Sj5NC/gJjiojaoA==", "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } + "acorn": "^8.5.0", + "commander": "^2.20.0", + "source-map": "~0.8.0-beta.0", + "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=10" } }, - "base16": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/base16/-/base16-1.0.0.tgz", - "integrity": "sha1-4pf2DX7BAUp6lxo568ipjAtoHnA=" - }, - "base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" - }, - "batch": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", - "integrity": "sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY=" + "node_modules/terser-webpack-plugin": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.1.tgz", + "integrity": "sha512-GvlZdT6wPQKbDNW/GDQzZFg/j4vKU96yl2q6mcUkzKOgW4gwf1Z8cZToUCrz31XHlPWH8MVb1r2tFtdDtTGJ7g==", + "dependencies": { + "jest-worker": "^27.4.5", + "schema-utils": "^3.1.1", + "serialize-javascript": "^6.0.0", + "source-map": "^0.6.1", + "terser": "^5.7.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.1.0" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "uglify-js": { + "optional": true + } + } }, - "big.js": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", - "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==" + "node_modules/terser-webpack-plugin/node_modules/schema-utils": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", + "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", + "dependencies": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } }, - "binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==" + "node_modules/terser/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" }, - "bindings": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", - "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", - "optional": true, - "requires": { - "file-uri-to-path": "1.0.0" + "node_modules/terser/node_modules/source-map": { + "version": "0.8.0-beta.0", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.8.0-beta.0.tgz", + "integrity": "sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==", + "dependencies": { + "whatwg-url": "^7.0.0" + }, + "engines": { + "node": ">= 8" } }, - "bl": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", - "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", - "requires": { - "buffer": "^5.5.0", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" + "node_modules/terser/node_modules/tr46": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz", + "integrity": "sha1-qLE/1r/SSJUZZ0zN5VujaTtwbQk=", + "dependencies": { + "punycode": "^2.1.0" } }, - "bluebird": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", - "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" - }, - "bmp-js": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/bmp-js/-/bmp-js-0.1.0.tgz", - "integrity": "sha1-4Fpj95amwf8l9Hcex62twUjAcjM=" - }, - "bn.js": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.0.tgz", - "integrity": "sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw==" + "node_modules/terser/node_modules/webidl-conversions": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", + "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==" }, - "body-parser": { - "version": "1.19.0", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", - "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", - "requires": { - "bytes": "3.1.0", - "content-type": "~1.0.4", - "debug": "2.6.9", - "depd": "~1.1.2", - "http-errors": "1.7.2", - "iconv-lite": "0.4.24", - "on-finished": "~2.3.0", - "qs": "6.7.0", - "raw-body": "2.4.0", - "type-is": "~1.6.17" - }, + "node_modules/terser/node_modules/whatwg-url": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz", + "integrity": "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==", "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - } + "lodash.sortby": "^4.7.0", + "tr46": "^1.0.1", + "webidl-conversions": "^4.0.2" } }, - "bonjour": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/bonjour/-/bonjour-3.5.0.tgz", - "integrity": "sha1-jokKGD2O6aI5OzhExpGkK897yfU=", - "requires": { - "array-flatten": "^2.1.0", - "deep-equal": "^1.0.1", - "dns-equal": "^1.0.0", - "dns-txt": "^2.0.2", - "multicast-dns": "^6.0.1", - "multicast-dns-service-types": "^1.1.0" - }, + "node_modules/test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "dev": true, "dependencies": { - "array-flatten": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz", - "integrity": "sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==" - } + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=8" } }, - "boolbase": { + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=" + }, + "node_modules/throat": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/throat/-/throat-6.0.1.tgz", + "integrity": "sha512-8hmiGIJMDlwjg7dlJ4yKGLK8EsYqKgPWbG3b4wjJddKNwc7N7Dpn08Df4szr/sZdMVeOstrdYSsqzX6BYbcB+w==", + "dev": true + }, + "node_modules/throttleit": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", - "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=" + "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-1.0.0.tgz", + "integrity": "sha512-rkTVqu6IjfQ/6+uNuuc3sZek4CEYxTJom3IktzgdSxcZqdARuebbA/f4QmAxMQIxqq9ZLEUkSYqvuk1I6VKq4g==", + "dev": true }, - "boxen": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/boxen/-/boxen-5.1.2.tgz", - "integrity": "sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ==", - "requires": { - "ansi-align": "^3.0.0", - "camelcase": "^6.2.0", - "chalk": "^4.1.0", - "cli-boxes": "^2.2.1", - "string-width": "^4.2.2", - "type-fest": "^0.20.2", - "widest-line": "^3.1.0", - "wrap-ansi": "^7.0.0" - } + "node_modules/through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", + "dev": true }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } + "node_modules/thunky": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", + "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==" }, - "braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "requires": { - "fill-range": "^7.0.1" + "node_modules/timers-browserify": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.12.tgz", + "integrity": "sha512-9phl76Cqm6FhSX9Xe1ZUAMLtm1BLkKj2Qd5ApyWkXzsMRaA7dgr81kf4wJmQf/hAvg8EEyJxDo3du/0KlhPiKQ==", + "dependencies": { + "setimmediate": "^1.0.4" + }, + "engines": { + "node": ">=0.6.0" } }, - "brorand": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", - "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=" + "node_modules/timm": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/timm/-/timm-1.7.1.tgz", + "integrity": "sha512-IjZc9KIotudix8bMaBW6QvMuq64BrJWFs1+4V0lXwWGQZwH+LnX87doAYhem4caOEusRP9/g6jVDQmZ8XOk1nw==" }, - "browserify-aes": { + "node_modules/tiny-invariant": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", - "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", - "requires": { - "buffer-xor": "^1.0.3", - "cipher-base": "^1.0.0", - "create-hash": "^1.1.0", - "evp_bytestokey": "^1.0.3", - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } + "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.2.0.tgz", + "integrity": "sha512-1Uhn/aqw5C6RI4KejVeTg6mIS7IqxnLJ8Mv2tV5rTc0qWobay7pDUz6Wi392Cnc8ak1H0F2cjoRzb2/AW4+Fvg==" }, - "browserify-cipher": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", - "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", - "requires": { - "browserify-aes": "^1.0.4", - "browserify-des": "^1.0.0", - "evp_bytestokey": "^1.0.0" + "node_modules/tiny-warning": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz", + "integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==" + }, + "node_modules/tinycolor2": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.4.2.tgz", + "integrity": "sha512-vJhccZPs965sV/L2sU4oRQVAos0pQXwsvTLkWYdqJ+a8Q5kPFzJTuOFwy7UniPli44NKQGAglksjvOcpo95aZA==", + "engines": { + "node": "*" } }, - "browserify-des": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", - "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", - "requires": { - "cipher-base": "^1.0.1", - "des.js": "^1.0.0", - "inherits": "^2.0.1", - "safe-buffer": "^5.1.2" + "node_modules/tmp": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", + "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", + "dev": true, + "dependencies": { + "rimraf": "^3.0.0" + }, + "engines": { + "node": ">=8.17.0" } }, - "browserify-rsa": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.1.0.tgz", - "integrity": "sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog==", - "requires": { - "bn.js": "^5.0.0", - "randombytes": "^2.0.1" + "node_modules/tmpl": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", + "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", + "dev": true + }, + "node_modules/to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "engines": { + "node": ">=4" } }, - "browserify-sign": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.1.tgz", - "integrity": "sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg==", - "requires": { - "bn.js": "^5.1.1", - "browserify-rsa": "^4.0.1", - "create-hash": "^1.2.0", - "create-hmac": "^1.1.7", - "elliptic": "^6.5.3", - "inherits": "^2.0.4", - "parse-asn1": "^5.1.5", - "readable-stream": "^3.6.0", - "safe-buffer": "^5.2.0" - }, + "node_modules/to-readable-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz", + "integrity": "sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==", + "engines": { + "node": ">=6" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "dependencies": { - "safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" - } + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" } }, - "browserify-zlib": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", - "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", - "requires": { - "pako": "~1.0.5" + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "engines": { + "node": ">=0.6" } }, - "browserslist": { - "version": "4.17.4", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.17.4.tgz", - "integrity": "sha512-Zg7RpbZpIJRW3am9Lyckue7PLytvVxxhJj1CaJVlCWENsGEAOlnlt8X0ZxGRPp7Bt9o8tIRM5SEXy4BCPMJjLQ==", - "requires": { - "caniuse-lite": "^1.0.30001265", - "electron-to-chromium": "^1.3.867", - "escalade": "^3.1.1", - "node-releases": "^2.0.0", - "picocolors": "^1.0.0" + "node_modules/totalist": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/totalist/-/totalist-1.1.0.tgz", + "integrity": "sha512-gduQwd1rOdDMGxFG1gEvhV88Oirdo2p+KjoYFU7k2g+i7n6AFFbDQ5kMPUsW0pNbfQsB/cwXvT1i4Bue0s9g5g==", + "engines": { + "node": ">=6" } }, - "buffer": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", - "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", - "requires": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" + "node_modules/tough-cookie": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.0.0.tgz", + "integrity": "sha512-tHdtEpQCMrc1YLrMaqXXcj6AxhYi/xgit6mZu1+EDWUn+qhUf8wMQoFIy9NXuq23zAwtcB0t/MjACGR18pcRbg==", + "dev": true, + "dependencies": { + "psl": "^1.1.33", + "punycode": "^2.1.1", + "universalify": "^0.1.2" + }, + "engines": { + "node": ">=6" } }, - "buffer-equal": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-0.0.1.tgz", - "integrity": "sha1-kbx0sR6kBbyRa8aqkI+q+ltKrEs=" + "node_modules/tough-cookie/node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true, + "engines": { + "node": ">= 4.0.0" + } }, - "buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" + "node_modules/tr46": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-2.1.0.tgz", + "integrity": "sha512-15Ih7phfcdP5YxqiB+iDtLoaTz4Nd35+IiAv0kQ5FNKHzXgdWqPoTIqEDDJmXceQt4JZk6lVPT8lnDlPpGDppw==", + "dev": true, + "dependencies": { + "punycode": "^2.1.1" + }, + "engines": { + "node": ">=8" + } }, - "buffer-indexof": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/buffer-indexof/-/buffer-indexof-1.1.1.tgz", - "integrity": "sha512-4/rOEg86jivtPTeOUUT61jJO1Ya1TrR/OkqCSZDyq84WJh3LuuiphBYJN+fm5xufIk4XAFcEwte/8WzC8If/1g==" + "node_modules/trim": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/trim/-/trim-0.0.1.tgz", + "integrity": "sha1-WFhUf2spB1fulczMZm+1AITEYN0=" }, - "buffer-xor": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", - "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=" + "node_modules/trim-trailing-lines": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/trim-trailing-lines/-/trim-trailing-lines-1.1.4.tgz", + "integrity": "sha512-rjUWSqnfTNrjbB9NQWfPMH/xRK1deHeGsHoVfpxJ++XeYXE0d6B1En37AHfw3jtfTU7dzMzZL2jjpe8Qb5gLIQ==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } }, - "builtin-status-codes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", - "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=" + "node_modules/trough": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/trough/-/trough-1.0.5.tgz", + "integrity": "sha512-rvuRbTarPXmMb79SmzEp8aqXNKcK+y0XaB298IXueQ8I2PsrATcPBCSPyK/dDNa2iWOhKlfNnOjdAOTBU/nkFA==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } }, - "bytes": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", - "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==" + "node_modules/tslib": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" }, - "cache-base": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", - "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", - "requires": { - "collection-visit": "^1.0.0", - "component-emitter": "^1.2.1", - "get-value": "^2.0.6", - "has-value": "^1.0.0", - "isobject": "^3.0.1", - "set-value": "^2.0.0", - "to-object-path": "^0.3.0", - "union-value": "^1.0.0", - "unset-value": "^1.0.0" - } + "node_modules/tty-browserify": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.1.tgz", + "integrity": "sha512-C3TaO7K81YvjCgQH9Q1S3R3P3BtN3RIM8n+OvX4il1K1zgE8ZhI0op7kClgkxtutIE8hQrcrHBXvIheqKUUCxw==" }, - "cacheable-request": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", - "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==", - "requires": { - "clone-response": "^1.0.2", - "get-stream": "^5.1.0", - "http-cache-semantics": "^4.0.0", - "keyv": "^3.0.0", - "lowercase-keys": "^2.0.0", - "normalize-url": "^4.1.0", - "responselike": "^1.0.2" - }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", "dependencies": { - "get-stream": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", - "requires": { - "pump": "^3.0.0" - } - }, - "lowercase-keys": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", - "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==" - }, - "normalize-url": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.1.tgz", - "integrity": "sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==" - } - } - }, - "call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "requires": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" } }, - "call-me-maybe": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.1.tgz", - "integrity": "sha1-JtII6onje1y95gJQoV8DHBak1ms=" - }, - "callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==" + "node_modules/tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==", + "dev": true }, - "camel-case": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz", - "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==", - "requires": { - "pascal-case": "^3.1.2", - "tslib": "^2.0.3" + "node_modules/type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "dev": true, + "dependencies": { + "prelude-ls": "~1.1.2" + }, + "engines": { + "node": ">= 0.8.0" } }, - "camelcase": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.2.0.tgz", - "integrity": "sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg==" + "node_modules/type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true, + "engines": { + "node": ">=4" + } }, - "camelcase-css": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", - "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==" + "node_modules/type-fest": { + "version": "2.12.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.12.2.tgz", + "integrity": "sha512-qt6ylCGpLjZ7AaODxbpyBZSs9fCI9SkL3Z9q2oxMBQhs/uyY+VD8jHA8ULCGmWQJlBgqvO3EJeAngOHD8zQCrQ==", + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, - "camelize": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/camelize/-/camelize-1.0.0.tgz", - "integrity": "sha1-FkpUg+Yw+kMh5a8HAg5TGDGyYJs=" + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } }, - "caniuse-api": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz", - "integrity": "sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==", - "requires": { - "browserslist": "^4.0.0", - "caniuse-lite": "^1.0.0", - "lodash.memoize": "^4.1.2", - "lodash.uniq": "^4.5.0" + "node_modules/typedarray-to-buffer": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", + "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", + "dependencies": { + "is-typedarray": "^1.0.0" } }, - "caniuse-lite": { - "version": "1.0.30001265", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001265.tgz", - "integrity": "sha512-YzBnspggWV5hep1m9Z6sZVLOt7vrju8xWooFAgN6BA5qvy98qPAPb7vNUzypFaoh2pb3vlfzbDO8tB57UPGbtw==" + "node_modules/typescript": { + "version": "4.7.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.4.tgz", + "integrity": "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==", + "peer": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } }, - "ccount": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/ccount/-/ccount-1.1.0.tgz", - "integrity": "sha512-vlNK021QdI7PNeiUh/lKkC/mNHHfV0m/Ad5JoI0TYtlBnJAslM/JIkm/tGC88bkLIwO6OQ5uV6ztS6kVAtCDlg==" + "node_modules/ua-parser-js": { + "version": "0.7.31", + "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.31.tgz", + "integrity": "sha512-qLK/Xe9E2uzmYI3qLeOmI0tEOt+TBBQyUIAh4aAgU05FVYzeZrKUdkAZfBNVGRaHVgV0TDkdEngJSw/SyQchkQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/ua-parser-js" + }, + { + "type": "paypal", + "url": "https://paypal.me/faisalman" + } + ], + "engines": { + "node": "*" + } + }, + "node_modules/unbox-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", + "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", + "dependencies": { + "call-bind": "^1.0.2", + "has-bigints": "^1.0.2", + "has-symbols": "^1.0.3", + "which-boxed-primitive": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/unherit": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/unherit/-/unherit-1.1.3.tgz", + "integrity": "sha512-Ft16BJcnapDKp0+J/rqFC3Rrk6Y/Ng4nzsC028k2jdDII/rdZ7Wd3pPT/6+vIIxRagwRc9K0IUX0Ra4fKvw+WQ==", + "dependencies": { + "inherits": "^2.0.0", + "xtend": "^4.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/unicode-canonical-property-names-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", + "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==", + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", + "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", + "dependencies": { + "unicode-canonical-property-names-ecmascript": "^2.0.0", + "unicode-property-aliases-ecmascript": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-value-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.0.0.tgz", + "integrity": "sha512-7Yhkc0Ye+t4PNYzOGKedDhXbYIBe1XEQYQxOPyhcXNMJ0WCABqqj6ckydd6pWRZTHV4GuCPKdBAUiMc60tsKVw==", + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-property-aliases-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.0.0.tgz", + "integrity": "sha512-5Zfuy9q/DFr4tfO7ZPeVXb1aPoeQSdeFMLpYuFebehDAhbuevLs5yxSZmIFN1tP5F9Wl4IpJrYojg85/zgyZHQ==", + "engines": { + "node": ">=4" + } + }, + "node_modules/unified": { + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/unified/-/unified-9.2.0.tgz", + "integrity": "sha512-vx2Z0vY+a3YoTj8+pttM3tiJHCwY5UFbYdiWrwBEbHmK8pvsPj2rtAX2BFfgXen8T39CJWblWRDT4L5WGXtDdg==", + "dependencies": { + "bail": "^1.0.0", + "extend": "^3.0.0", + "is-buffer": "^2.0.0", + "is-plain-obj": "^2.0.0", + "trough": "^1.0.0", + "vfile": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unique-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", + "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==", + "dependencies": { + "crypto-random-string": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/unist-builder": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/unist-builder/-/unist-builder-2.0.3.tgz", + "integrity": "sha512-f98yt5pnlMWlzP539tPc4grGMsFaQQlP/vM396b00jngsiINumNmsY8rkXjfoi1c6QaM8nQ3vaGDuoKWbe/1Uw==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-find-after": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/unist-util-find-after/-/unist-util-find-after-3.0.0.tgz", + "integrity": "sha512-ojlBqfsBftYXExNu3+hHLfJQ/X1jYY/9vdm4yZWjIbf0VuWF6CRufci1ZyoD/wV2TYMKxXUoNuoqwy+CkgzAiQ==", + "dependencies": { + "unist-util-is": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-generated": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/unist-util-generated/-/unist-util-generated-1.1.6.tgz", + "integrity": "sha512-cln2Mm1/CZzN5ttGK7vkoGw+RZ8VcUH6BtGbq98DDtRGquAAOXig1mrBQYelOwMXYS8rK+vZDyyojSjp7JX+Lg==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-is": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-4.1.0.tgz", + "integrity": "sha512-ZOQSsnce92GrxSqlnEEseX0gi7GH9zTJZ0p9dtu87WRb/37mMPO2Ilx1s/t9vBHrFhbgweUwb+t7cIn5dxPhZg==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-position": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-3.1.0.tgz", + "integrity": "sha512-w+PkwCbYSFw8vpgWD0v7zRCl1FpY3fjDSQ3/N/wNd9Ffa4gPi8+4keqt99N3XW6F99t/mUzp2xAhNmfKWp95QA==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-remove": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/unist-util-remove/-/unist-util-remove-2.1.0.tgz", + "integrity": "sha512-J8NYPyBm4baYLdCbjmf1bhPu45Cr1MWTm77qd9istEkzWpnN6O9tMsEbB2JhNnBCqGENRqEWomQ+He6au0B27Q==", + "dependencies": { + "unist-util-is": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-remove-position": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/unist-util-remove-position/-/unist-util-remove-position-2.0.1.tgz", + "integrity": "sha512-fDZsLYIe2uT+oGFnuZmy73K6ZxOPG/Qcm+w7jbEjaFcJgbQ6cqjs/eSPzXhsmGpAsWPkqZM9pYjww5QTn3LHMA==", + "dependencies": { + "unist-util-visit": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-stringify-position": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-2.0.3.tgz", + "integrity": "sha512-3faScn5I+hy9VleOq/qNbAd6pAx7iH5jYBMS9I1HgQVijz/4mv5Bvw5iw1sC/90CODiKo81G/ps8AJrISn687g==", + "dependencies": { + "@types/unist": "^2.0.2" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-2.0.3.tgz", + "integrity": "sha512-iJ4/RczbJMkD0712mGktuGpm/U4By4FfDonL7N/9tATGIF4imikjOuagyMY53tnZq3NP6BcmlrHhEKAfGWjh7Q==", + "dependencies": { + "@types/unist": "^2.0.0", + "unist-util-is": "^4.0.0", + "unist-util-visit-parents": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit-parents": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-3.1.1.tgz", + "integrity": "sha512-1KROIZWo6bcMrZEwiH2UrXDyalAa0uqzWCxCJj6lPOvTve2WkfgCytoDTPaMnodXh1WrXOq0haVYHj99ynJlsg==", + "dependencies": { + "@types/unist": "^2.0.0", + "unist-util-is": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/unquote": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unquote/-/unquote-1.1.1.tgz", + "integrity": "sha1-j97XMk7G6IoP+LkF58CYzcCG1UQ=" + }, + "node_modules/untildify": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz", + "integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/update-notifier": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-5.1.0.tgz", + "integrity": "sha512-ItnICHbeMh9GqUy31hFPrD1kcuZ3rpxDZbf4KUDavXwS0bW5m7SLbDQpGX3UYr072cbrF5hFUs3r5tUsPwjfHw==", + "dependencies": { + "boxen": "^5.0.0", + "chalk": "^4.1.0", + "configstore": "^5.0.1", + "has-yarn": "^2.1.0", + "import-lazy": "^2.1.0", + "is-ci": "^2.0.0", + "is-installed-globally": "^0.4.0", + "is-npm": "^5.0.0", + "is-yarn-global": "^0.3.0", + "latest-version": "^5.1.0", + "pupa": "^2.1.1", + "semver": "^7.3.4", + "semver-diff": "^3.1.1", + "xdg-basedir": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/yeoman/update-notifier?sponsor=1" + } + }, + "node_modules/update-notifier/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/update-notifier/node_modules/boxen": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-5.1.2.tgz", + "integrity": "sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ==", + "dependencies": { + "ansi-align": "^3.0.0", + "camelcase": "^6.2.0", + "chalk": "^4.1.0", + "cli-boxes": "^2.2.1", + "string-width": "^4.2.2", + "type-fest": "^0.20.2", + "widest-line": "^3.1.0", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/update-notifier/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/update-notifier/node_modules/cli-boxes": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz", + "integrity": "sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==", + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/update-notifier/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/update-notifier/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/update-notifier/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/update-notifier/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/update-notifier/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/update-notifier/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/update-notifier/node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/update-notifier/node_modules/widest-line": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", + "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==", + "dependencies": { + "string-width": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/update-notifier/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/url": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", + "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", + "dependencies": { + "punycode": "1.3.2", + "querystring": "0.2.0" + } + }, + "node_modules/url-loader": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/url-loader/-/url-loader-4.1.1.tgz", + "integrity": "sha512-3BTV812+AVHHOJQO8O5MkWgZ5aosP7GnROJwvzLS9hWDj00lZ6Z0wNak423Lp9PBZN05N+Jk/N5Si8jRAlGyWA==", + "dependencies": { + "loader-utils": "^2.0.0", + "mime-types": "^2.1.27", + "schema-utils": "^3.0.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "file-loader": "*", + "webpack": "^4.0.0 || ^5.0.0" + }, + "peerDependenciesMeta": { + "file-loader": { + "optional": true + } + } + }, + "node_modules/url-loader/node_modules/schema-utils": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", + "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", + "dependencies": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/url-parse-lax": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", + "integrity": "sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=", + "dependencies": { + "prepend-http": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/url-template": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/url-template/-/url-template-2.0.8.tgz", + "integrity": "sha1-/FZaPMy/93MMd19WQflVV5FDnyE=" + }, + "node_modules/url/node_modules/punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=" + }, + "node_modules/url/node_modules/querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", + "deprecated": "The querystring API is considered Legacy. new code should use the URLSearchParams API instead.", + "engines": { + "node": ">=0.4.x" + } + }, + "node_modules/use-composed-ref": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/use-composed-ref/-/use-composed-ref-1.3.0.tgz", + "integrity": "sha512-GLMG0Jc/jiKov/3Ulid1wbv3r54K9HlMW29IWcDFPEqFkSO2nS0MuefWgMJpeHQ9YJeXDL3ZUF+P3jdXlZX/cQ==", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/use-isomorphic-layout-effect": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.1.2.tgz", + "integrity": "sha512-49L8yCO3iGT/ZF9QttjwLF/ZD9Iwto5LnH5LmEdk/6cFmXddqi2ulF0edxTwjj+7mqvpVVGQWvbXZdn32wRSHA==", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/use-latest": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/use-latest/-/use-latest-1.2.1.tgz", + "integrity": "sha512-xA+AVm/Wlg3e2P/JiItTziwS7FK92LWrDB0p+hgXloIMuVCeJJ8v6f0eeHyPZaJrM+usM1FkFfbNCrJGs8A/zw==", + "dependencies": { + "use-isomorphic-layout-effect": "^1.1.1" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/utif": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/utif/-/utif-2.0.1.tgz", + "integrity": "sha512-Z/S1fNKCicQTf375lIP9G8Sa1H/phcysstNrrSdZKj1f9g58J4NMgb5IgiEZN9/nLMPDwF0W7hdOe9Qq2IYoLg==", + "dependencies": { + "pako": "^1.0.5" + } + }, + "node_modules/util": { + "version": "0.12.4", + "resolved": "https://registry.npmjs.org/util/-/util-0.12.4.tgz", + "integrity": "sha512-bxZ9qtSlGUWSOy9Qa9Xgk11kSslpuZwaxCg4sNIDj6FLucDab2JxnHwyNTCpHMtK1MjoQiWQ6DiUMZYbSrO+Sw==", + "dependencies": { + "inherits": "^2.0.3", + "is-arguments": "^1.0.4", + "is-generator-function": "^1.0.7", + "is-typed-array": "^1.1.3", + "safe-buffer": "^5.1.2", + "which-typed-array": "^1.1.2" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "node_modules/util.promisify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.1.tgz", + "integrity": "sha512-g9JpC/3He3bm38zsLupWryXHoEcS22YHthuPQSJdMy6KNrzIRzWqcsHzD/WUnqe45whVou4VIsPew37DoXWNrA==", + "dependencies": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.2", + "has-symbols": "^1.0.1", + "object.getownpropertydescriptors": "^2.1.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/utila": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/utila/-/utila-0.4.0.tgz", + "integrity": "sha1-ihagXURWV6Oupe7MWxKk+lN5dyw=" + }, + "node_modules/utility-types": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/utility-types/-/utility-types-3.10.0.tgz", + "integrity": "sha512-O11mqxmi7wMKCo6HKFt5AhO4BwY3VV68YU07tgxfz8zJTIxr4BpsezN49Ffwy9j3ZpwwJp4fkRwjRzq3uWE6Rg==", + "engines": { + "node": ">= 4" + } + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/uuid": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-7.0.3.tgz", + "integrity": "sha512-DPSke0pXhTZgoF/d+WSt2QaKMCFSfx7QegxEWT+JOuHF5aWrKEn0G+ztjuJg/gG8/ItK+rbPCD/yNv8yyih6Cg==", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/v8-to-istanbul": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-8.1.1.tgz", + "integrity": "sha512-FGtKtv3xIpR6BYhvgH8MI/y78oT7d8Au3ww4QIxymrCtZEh5b8gCw2siywE+puhEmuWKDtmfrvF5UlB298ut3w==", + "dev": true, + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.1", + "convert-source-map": "^1.6.0", + "source-map": "^0.7.3" + }, + "engines": { + "node": ">=10.12.0" + } + }, + "node_modules/v8-to-istanbul/node_modules/source-map": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", + "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/value-equal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/value-equal/-/value-equal-1.0.1.tgz", + "integrity": "sha512-NOJ6JZCAWr0zlxZt+xqCHNTEKOsrks2HQd4MqhP1qy4z1SkbEP467eNx6TgDKXMvUOb+OENfJCZwM+16n7fRfw==" + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==", + "dev": true, + "engines": [ + "node >=0.6.0" + ], + "dependencies": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "node_modules/verror/node_modules/core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==", + "dev": true + }, + "node_modules/vfile": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/vfile/-/vfile-4.2.1.tgz", + "integrity": "sha512-O6AE4OskCG5S1emQ/4gl8zK586RqA3srz3nfK/Viy0UPToBc5Trp9BVFb1u0CjsKrAWwnpr4ifM/KBXPWwJbCA==", + "dependencies": { + "@types/unist": "^2.0.0", + "is-buffer": "^2.0.0", + "unist-util-stringify-position": "^2.0.0", + "vfile-message": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vfile-location": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-3.2.0.tgz", + "integrity": "sha512-aLEIZKv/oxuCDZ8lkJGhuhztf/BW4M+iHdCwglA/eWc+vtuRFJj8EtgceYFX4LRjOhCAAiNHsKGssC6onJ+jbA==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vfile-message": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-2.0.4.tgz", + "integrity": "sha512-DjssxRGkMvifUOJre00juHoP9DPWuzjxKuMDrhNbk2TdaYYBNMStsNhEOt3idrtI12VQYM/1+iM0KOzXi4pxwQ==", + "dependencies": { + "@types/unist": "^2.0.0", + "unist-util-stringify-position": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vm-browserify": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz", + "integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==" + }, + "node_modules/w3c-hr-time": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz", + "integrity": "sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ==", + "dev": true, + "dependencies": { + "browser-process-hrtime": "^1.0.0" + } + }, + "node_modules/w3c-xmlserializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-2.0.0.tgz", + "integrity": "sha512-4tzD0mF8iSiMiNs30BiLO3EpfGLZUT2MSX/G+o7ZywDzliWQ3OPtTZ0PTC3B3ca1UAf4cJMHB+2Bf56EriJuRA==", + "dev": true, + "dependencies": { + "xml-name-validator": "^3.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/wait-on": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/wait-on/-/wait-on-6.0.1.tgz", + "integrity": "sha512-zht+KASY3usTY5u2LgaNqn/Cd8MukxLGjdcZxT2ns5QzDmTFc4XoWBgC+C/na+sMRZTuVygQoMYwdcVjHnYIVw==", + "dependencies": { + "axios": "^0.25.0", + "joi": "^17.6.0", + "lodash": "^4.17.21", + "minimist": "^1.2.5", + "rxjs": "^7.5.4" + }, + "bin": { + "wait-on": "bin/wait-on" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/wait-on/node_modules/axios": { + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.25.0.tgz", + "integrity": "sha512-cD8FOb0tRH3uuEe6+evtAbgJtfxr7ly3fQjYcMcuPlgkwVS9xboaVIpcDV+cYQe+yGykgwZCs1pzjntcGa6l5g==", + "dependencies": { + "follow-redirects": "^1.14.7" + } + }, + "node_modules/walker": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", + "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", + "dev": true, + "dependencies": { + "makeerror": "1.0.12" + } + }, + "node_modules/watchpack": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.3.1.tgz", + "integrity": "sha512-x0t0JuydIo8qCNctdDrn1OzH/qDzk2+rdCOC3YzumZ42fiMqmQ7T3xQurykYMhYfHaPHTp4ZxAx2NfUo1K6QaA==", + "dependencies": { + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.1.2" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/wbuf": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz", + "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==", + "dependencies": { + "minimalistic-assert": "^1.0.0" + } + }, + "node_modules/web-namespaces": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/web-namespaces/-/web-namespaces-1.1.4.tgz", + "integrity": "sha512-wYxSGajtmoP4WxfejAPIr4l0fVh+jeMXZb08wNc0tMg6xsfZXj3cECqIK0G7ZAqUq0PP8WlMDtaOGVBTAWztNw==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/webidl-conversions": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-6.1.0.tgz", + "integrity": "sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w==", + "dev": true, + "engines": { + "node": ">=10.4" + } + }, + "node_modules/webpack": { + "version": "5.72.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.72.0.tgz", + "integrity": "sha512-qmSmbspI0Qo5ld49htys8GY9XhS9CGqFoHTsOVAnjBdg0Zn79y135R+k4IR4rKK6+eKaabMhJwiVB7xw0SJu5w==", + "dependencies": { + "@types/eslint-scope": "^3.7.3", + "@types/estree": "^0.0.51", + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/wasm-edit": "1.11.1", + "@webassemblyjs/wasm-parser": "1.11.1", + "acorn": "^8.4.1", + "acorn-import-assertions": "^1.7.6", + "browserslist": "^4.14.5", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^5.9.2", + "es-module-lexer": "^0.9.0", + "eslint-scope": "5.1.1", + "events": "^3.2.0", + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.2.9", + "json-parse-better-errors": "^1.0.2", + "loader-runner": "^4.2.0", + "mime-types": "^2.1.27", + "neo-async": "^2.6.2", + "schema-utils": "^3.1.0", + "tapable": "^2.1.1", + "terser-webpack-plugin": "^5.1.3", + "watchpack": "^2.3.1", + "webpack-sources": "^3.2.3" + }, + "bin": { + "webpack": "bin/webpack.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependenciesMeta": { + "webpack-cli": { + "optional": true + } + } + }, + "node_modules/webpack-bundle-analyzer": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/webpack-bundle-analyzer/-/webpack-bundle-analyzer-4.5.0.tgz", + "integrity": "sha512-GUMZlM3SKwS8Z+CKeIFx7CVoHn3dXFcUAjT/dcZQQmfSZGvitPfMob2ipjai7ovFFqPvTqkEZ/leL4O0YOdAYQ==", + "dependencies": { + "acorn": "^8.0.4", + "acorn-walk": "^8.0.0", + "chalk": "^4.1.0", + "commander": "^7.2.0", + "gzip-size": "^6.0.0", + "lodash": "^4.17.20", + "opener": "^1.5.2", + "sirv": "^1.0.7", + "ws": "^7.3.1" + }, + "bin": { + "webpack-bundle-analyzer": "lib/bin/analyzer.js" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/webpack-bundle-analyzer/node_modules/acorn-walk": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", + "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/webpack-bundle-analyzer/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/webpack-bundle-analyzer/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/webpack-bundle-analyzer/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/webpack-bundle-analyzer/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/webpack-bundle-analyzer/node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "engines": { + "node": ">= 10" + } + }, + "node_modules/webpack-bundle-analyzer/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/webpack-bundle-analyzer/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/webpack-dev-middleware": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-5.3.1.tgz", + "integrity": "sha512-81EujCKkyles2wphtdrnPg/QqegC/AtqNH//mQkBYSMqwFVCQrxM6ktB2O/SPlZy7LqeEfTbV3cZARGQz6umhg==", + "dependencies": { + "colorette": "^2.0.10", + "memfs": "^3.4.1", + "mime-types": "^2.1.31", + "range-parser": "^1.2.1", + "schema-utils": "^4.0.0" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.0.0 || ^5.0.0" + } + }, + "node_modules/webpack-dev-middleware/node_modules/ajv": { + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz", + "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/webpack-dev-middleware/node_modules/ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "dependencies": { + "fast-deep-equal": "^3.1.3" + }, + "peerDependencies": { + "ajv": "^8.8.2" + } + }, + "node_modules/webpack-dev-middleware/node_modules/colorette": { + "version": "2.0.16", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.16.tgz", + "integrity": "sha512-hUewv7oMjCp+wkBv5Rm0v87eJhq4woh5rSR+42YSQJKecCqgIqNkZ6lAlQms/BwHPJA5NKMRlpxPRv0n8HQW6g==" + }, + "node_modules/webpack-dev-middleware/node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/webpack-dev-middleware/node_modules/schema-utils": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.0.0.tgz", + "integrity": "sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg==", + "dependencies": { + "@types/json-schema": "^7.0.9", + "ajv": "^8.8.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.0.0" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/webpack-dev-server": { + "version": "4.8.1", + "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.8.1.tgz", + "integrity": "sha512-dwld70gkgNJa33czmcj/PlKY/nOy/BimbrgZRaR9vDATBQAYgLzggR0nxDtPLJiLrMgZwbE6RRfJ5vnBBasTyg==", + "dependencies": { + "@types/bonjour": "^3.5.9", + "@types/connect-history-api-fallback": "^1.3.5", + "@types/express": "^4.17.13", + "@types/serve-index": "^1.9.1", + "@types/sockjs": "^0.3.33", + "@types/ws": "^8.5.1", + "ansi-html-community": "^0.0.8", + "bonjour-service": "^1.0.11", + "chokidar": "^3.5.3", + "colorette": "^2.0.10", + "compression": "^1.7.4", + "connect-history-api-fallback": "^1.6.0", + "default-gateway": "^6.0.3", + "express": "^4.17.3", + "graceful-fs": "^4.2.6", + "html-entities": "^2.3.2", + "http-proxy-middleware": "^2.0.3", + "ipaddr.js": "^2.0.1", + "open": "^8.0.9", + "p-retry": "^4.5.0", + "portfinder": "^1.0.28", + "rimraf": "^3.0.2", + "schema-utils": "^4.0.0", + "selfsigned": "^2.0.1", + "serve-index": "^1.9.1", + "sockjs": "^0.3.21", + "spdy": "^4.0.2", + "webpack-dev-middleware": "^5.3.1", + "ws": "^8.4.2" + }, + "bin": { + "webpack-dev-server": "bin/webpack-dev-server.js" + }, + "engines": { + "node": ">= 12.13.0" + }, + "peerDependencies": { + "webpack": "^4.37.0 || ^5.0.0" + }, + "peerDependenciesMeta": { + "webpack-cli": { + "optional": true + } + } + }, + "node_modules/webpack-dev-server/node_modules/ajv": { + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz", + "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/webpack-dev-server/node_modules/ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "dependencies": { + "fast-deep-equal": "^3.1.3" + }, + "peerDependencies": { + "ajv": "^8.8.2" + } + }, + "node_modules/webpack-dev-server/node_modules/colorette": { + "version": "2.0.16", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.16.tgz", + "integrity": "sha512-hUewv7oMjCp+wkBv5Rm0v87eJhq4woh5rSR+42YSQJKecCqgIqNkZ6lAlQms/BwHPJA5NKMRlpxPRv0n8HQW6g==" + }, + "node_modules/webpack-dev-server/node_modules/schema-utils": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.0.0.tgz", + "integrity": "sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg==", + "dependencies": { + "@types/json-schema": "^7.0.9", + "ajv": "^8.8.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.0.0" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/webpack-dev-server/node_modules/ws": { + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.6.0.tgz", + "integrity": "sha512-AzmM3aH3gk0aX7/rZLYvjdvZooofDu3fFOzGqcSnQ1tOcTWwhM/o+q++E8mAyVVIyUdajrkzWUGftaVSDLn1bw==", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/webpack-merge": { + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.8.0.tgz", + "integrity": "sha512-/SaI7xY0831XwP6kzuwhKWVKDP9t1QY1h65lAFLbZqMPIuYcD9QAW4u9STIbU9kaJbPBB/geU/gLr1wDjOhQ+Q==", + "dependencies": { + "clone-deep": "^4.0.1", + "wildcard": "^2.0.0" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/webpack-sources": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", + "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", + "dependencies": { + "source-list-map": "^2.0.0", + "source-map": "~0.6.1" + } + }, + "node_modules/webpack/node_modules/schema-utils": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", + "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", + "dependencies": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/webpack/node_modules/webpack-sources": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", + "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/webpackbar": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/webpackbar/-/webpackbar-5.0.2.tgz", + "integrity": "sha512-BmFJo7veBDgQzfWXl/wwYXr/VFus0614qZ8i9znqcl9fnEdiVkdbi0TedLQ6xAK92HZHDJ0QmyQ0fmuZPAgCYQ==", + "dependencies": { + "chalk": "^4.1.0", + "consola": "^2.15.3", + "pretty-time": "^1.1.0", + "std-env": "^3.0.1" + }, + "engines": { + "node": ">=12" + }, + "peerDependencies": { + "webpack": "3 || 4 || 5" + } + }, + "node_modules/webpackbar/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/webpackbar/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/webpackbar/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/webpackbar/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/webpackbar/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/webpackbar/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/websocket-driver": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", + "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", + "dependencies": { + "http-parser-js": ">=0.5.1", + "safe-buffer": ">=5.1.0", + "websocket-extensions": ">=0.1.1" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/websocket-extensions": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", + "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/whatwg-encoding": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz", + "integrity": "sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==", + "dev": true, + "dependencies": { + "iconv-lite": "0.4.24" + } + }, + "node_modules/whatwg-mimetype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz", + "integrity": "sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==", + "dev": true + }, + "node_modules/whatwg-url": { + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-8.7.0.tgz", + "integrity": "sha512-gAojqb/m9Q8a5IV96E3fHJM70AzCkgt4uXYX2O7EmuyOnLrViCQlsEBmF9UQIu3/aeAIp2U17rtbpZWNntQqdg==", + "dev": true, + "dependencies": { + "lodash": "^4.7.0", + "tr46": "^2.1.0", + "webidl-conversions": "^6.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dependencies": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-typed-array": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.7.tgz", + "integrity": "sha512-vjxaB4nfDqwKI0ws7wZpxIlde1XrLX5uB0ZjpfshgmapJMD7jJWhZI+yToJTqaFByF0eNBcYxbjmCzoRP7CfEw==", + "dependencies": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "es-abstract": "^1.18.5", + "foreach": "^2.0.5", + "has-tostringtag": "^1.0.0", + "is-typed-array": "^1.1.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "dependencies": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "node_modules/wide-align/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/wide-align/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/widest-line": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-4.0.1.tgz", + "integrity": "sha512-o0cyEG0e8GPzT4iGHphIOh0cJOV8fivsXxddQasHPHfoZf1ZexrfeA21w2NaEN1RHE+fXlfISmOE8R9N3u3Qig==", + "dependencies": { + "string-width": "^5.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/wildcard": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.0.tgz", + "integrity": "sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw==" + }, + "node_modules/word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wrap-ansi": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.0.1.tgz", + "integrity": "sha512-QFF+ufAqhoYHvoHdajT/Po7KoXVBPXS2bgjIam5isfWJPfIOnQZ50JtUiVvCv/sjgacf3yRrt2ZKUZ/V4itN4g==", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.1.0.tgz", + "integrity": "sha512-VbqNsoz55SYGczauuup0MFUyXNQviSpFTj1RQtFzmQLk18qbVSpTFFGMT293rmDaQuKCT6InmbuEyUne4mTuxQ==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.1.tgz", + "integrity": "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "node_modules/write-file-atomic": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", + "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", + "dependencies": { + "imurmurhash": "^0.1.4", + "is-typedarray": "^1.0.0", + "signal-exit": "^3.0.2", + "typedarray-to-buffer": "^3.1.5" + } + }, + "node_modules/ws": { + "version": "7.5.7", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.7.tgz", + "integrity": "sha512-KMvVuFzpKBuiIXW3E4u3mySRO2/mCHSyZDJQM5NQ9Q9KHWHWh0NHgfbRMLLrceUK5qAL4ytALJbpRMjixFZh8A==", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xdg-basedir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz", + "integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==", + "engines": { + "node": ">=8" + } + }, + "node_modules/xhr": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/xhr/-/xhr-2.6.0.tgz", + "integrity": "sha512-/eCGLb5rxjx5e3mF1A7s+pLlR6CGyqWN91fv1JgER5mVWg1MZmlhBvy9kjcsOdRk8RrIujotWyJamfyrp+WIcA==", + "dependencies": { + "global": "~4.4.0", + "is-function": "^1.0.1", + "parse-headers": "^2.0.0", + "xtend": "^4.0.0" + } + }, + "node_modules/xml-js": { + "version": "1.6.11", + "resolved": "https://registry.npmjs.org/xml-js/-/xml-js-1.6.11.tgz", + "integrity": "sha512-7rVi2KMfwfWFl+GpPg6m80IVMWXLRjO+PxTq7V2CDhoGak0wzYzFgUY2m4XJ47OGdXd8eLE8EmwfAmdjw7lC1g==", + "dependencies": { + "sax": "^1.2.4" + }, + "bin": { + "xml-js": "bin/cli.js" + } + }, + "node_modules/xml-name-validator": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz", + "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==", + "dev": true + }, + "node_modules/xml-parse-from-string": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/xml-parse-from-string/-/xml-parse-from-string-1.0.1.tgz", + "integrity": "sha1-qQKekp09vN7RafPG4oI42VpdWig=" + }, + "node_modules/xml2js": { + "version": "0.4.23", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.23.tgz", + "integrity": "sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug==", + "dependencies": { + "sax": ">=0.6.0", + "xmlbuilder": "~11.0.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/xmlbuilder": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", + "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/xmlchars": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", + "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", + "dev": true + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "engines": { + "node": ">=0.4" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "engines": { + "node": ">= 6" + } + }, + "node_modules/yaml-ast-parser": { + "version": "0.0.43", + "resolved": "https://registry.npmjs.org/yaml-ast-parser/-/yaml-ast-parser-0.0.43.tgz", + "integrity": "sha512-2PTINUwsRqSd+s8XxKaJWQlUuEMHJQyEuh2edBbW8KNJz0SJPwUSD2zRWqezFEdN7IzAgeuYHFUCF7o8zRdZ0A==" + }, + "node_modules/yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/yargs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yauzl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", + "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", + "dev": true, + "dependencies": { + "buffer-crc32": "~0.2.3", + "fd-slicer": "~1.1.0" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/zwitch": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-1.0.5.tgz", + "integrity": "sha512-V50KMwwzqJV0NpZIZFwfOD5/lyny3WlSzRiXgA0G7VUnRlqttta1L6UQIHzd6EuBY/cHGfwTIck7w1yH6Q5zUw==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + } + }, + "dependencies": { + "@algolia/autocomplete-core": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-core/-/autocomplete-core-1.5.2.tgz", + "integrity": "sha512-DY0bhyczFSS1b/CqJlTE/nQRtnTAHl6IemIkBy0nEWnhDzRDdtdx4p5Uuk3vwAFxwEEgi1WqKwgSSMx6DpNL4A==", + "requires": { + "@algolia/autocomplete-shared": "1.5.2" + } + }, + "@algolia/autocomplete-preset-algolia": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-preset-algolia/-/autocomplete-preset-algolia-1.5.2.tgz", + "integrity": "sha512-3MRYnYQFJyovANzSX2CToS6/5cfVjbLLqFsZTKcvF3abhQzxbqwwaMBlJtt620uBUOeMzhdfasKhCc40+RHiZw==", + "requires": { + "@algolia/autocomplete-shared": "1.5.2" + } + }, + "@algolia/autocomplete-shared": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-shared/-/autocomplete-shared-1.5.2.tgz", + "integrity": "sha512-ylQAYv5H0YKMfHgVWX0j0NmL8XBcAeeeVQUmppnnMtzDbDnca6CzhKj3Q8eF9cHCgcdTDdb5K+3aKyGWA0obug==" + }, + "@algolia/cache-browser-local-storage": { + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/@algolia/cache-browser-local-storage/-/cache-browser-local-storage-4.13.0.tgz", + "integrity": "sha512-nj1vHRZauTqP/bluwkRIgEADEimqojJgoTRCel5f6q8WCa9Y8QeI4bpDQP28FoeKnDRYa3J5CauDlN466jqRhg==", + "requires": { + "@algolia/cache-common": "4.13.0" + } + }, + "@algolia/cache-common": { + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/@algolia/cache-common/-/cache-common-4.13.0.tgz", + "integrity": "sha512-f9mdZjskCui/dA/fA/5a+6hZ7xnHaaZI5tM/Rw9X8rRB39SUlF/+o3P47onZ33n/AwkpSbi5QOyhs16wHd55kA==" + }, + "@algolia/cache-in-memory": { + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/@algolia/cache-in-memory/-/cache-in-memory-4.13.0.tgz", + "integrity": "sha512-hHdc+ahPiMM92CQMljmObE75laYzNFYLrNOu0Q3/eyvubZZRtY2SUsEEgyUEyzXruNdzrkcDxFYa7YpWBJYHAg==", + "requires": { + "@algolia/cache-common": "4.13.0" + } + }, + "@algolia/client-account": { + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/@algolia/client-account/-/client-account-4.13.0.tgz", + "integrity": "sha512-FzFqFt9b0g/LKszBDoEsW+dVBuUe1K3scp2Yf7q6pgHWM1WqyqUlARwVpLxqyc+LoyJkTxQftOKjyFUqddnPKA==", + "requires": { + "@algolia/client-common": "4.13.0", + "@algolia/client-search": "4.13.0", + "@algolia/transporter": "4.13.0" + } + }, + "@algolia/client-analytics": { + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/@algolia/client-analytics/-/client-analytics-4.13.0.tgz", + "integrity": "sha512-klmnoq2FIiiMHImkzOm+cGxqRLLu9CMHqFhbgSy9wtXZrqb8BBUIUE2VyBe7azzv1wKcxZV2RUyNOMpFqmnRZA==", + "requires": { + "@algolia/client-common": "4.13.0", + "@algolia/client-search": "4.13.0", + "@algolia/requester-common": "4.13.0", + "@algolia/transporter": "4.13.0" + } + }, + "@algolia/client-common": { + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-4.13.0.tgz", + "integrity": "sha512-GoXfTp0kVcbgfSXOjfrxx+slSipMqGO9WnNWgeMmru5Ra09MDjrcdunsiiuzF0wua6INbIpBQFTC2Mi5lUNqGA==", + "requires": { + "@algolia/requester-common": "4.13.0", + "@algolia/transporter": "4.13.0" + } + }, + "@algolia/client-personalization": { + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/@algolia/client-personalization/-/client-personalization-4.13.0.tgz", + "integrity": "sha512-KneLz2WaehJmNfdr5yt2HQETpLaCYagRdWwIwkTqRVFCv4DxRQ2ChPVW9jeTj4YfAAhfzE6F8hn7wkQ/Jfj6ZA==", + "requires": { + "@algolia/client-common": "4.13.0", + "@algolia/requester-common": "4.13.0", + "@algolia/transporter": "4.13.0" + } + }, + "@algolia/client-search": { + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-4.13.0.tgz", + "integrity": "sha512-blgCKYbZh1NgJWzeGf+caKE32mo3j54NprOf0LZVCubQb3Kx37tk1Hc8SDs9bCAE8hUvf3cazMPIg7wscSxspA==", + "requires": { + "@algolia/client-common": "4.13.0", + "@algolia/requester-common": "4.13.0", + "@algolia/transporter": "4.13.0" + } + }, + "@algolia/events": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@algolia/events/-/events-4.0.1.tgz", + "integrity": "sha512-FQzvOCgoFXAbf5Y6mYozw2aj5KCJoA3m4heImceldzPSMbdyS4atVjJzXKMsfX3wnZTFYwkkt8/z8UesLHlSBQ==" + }, + "@algolia/logger-common": { + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/@algolia/logger-common/-/logger-common-4.13.0.tgz", + "integrity": "sha512-8yqXk7rMtmQJ9wZiHOt/6d4/JDEg5VCk83gJ39I+X/pwUPzIsbKy9QiK4uJ3aJELKyoIiDT1hpYVt+5ia+94IA==" + }, + "@algolia/logger-console": { + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/@algolia/logger-console/-/logger-console-4.13.0.tgz", + "integrity": "sha512-YepRg7w2/87L0vSXRfMND6VJ5d6699sFJBRWzZPOlek2p5fLxxK7O0VncYuc/IbVHEgeApvgXx0WgCEa38GVuQ==", + "requires": { + "@algolia/logger-common": "4.13.0" + } + }, + "@algolia/requester-browser-xhr": { + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-4.13.0.tgz", + "integrity": "sha512-Dj+bnoWR5MotrnjblzGKZ2kCdQi2cK/VzPURPnE616NU/il7Ypy6U6DLGZ/ZYz+tnwPa0yypNf21uqt84fOgrg==", + "requires": { + "@algolia/requester-common": "4.13.0" + } + }, + "@algolia/requester-common": { + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/@algolia/requester-common/-/requester-common-4.13.0.tgz", + "integrity": "sha512-BRTDj53ecK+gn7ugukDWOOcBRul59C4NblCHqj4Zm5msd5UnHFjd/sGX+RLOEoFMhetILAnmg6wMrRrQVac9vw==" + }, + "@algolia/requester-node-http": { + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-4.13.0.tgz", + "integrity": "sha512-9b+3O4QFU4azLhGMrZAr/uZPydvzOR4aEZfSL8ZrpLZ7fbbqTO0S/5EVko+QIgglRAtVwxvf8UJ1wzTD2jvKxQ==", + "requires": { + "@algolia/requester-common": "4.13.0" + } + }, + "@algolia/transporter": { + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/@algolia/transporter/-/transporter-4.13.0.tgz", + "integrity": "sha512-8tSQYE+ykQENAdeZdofvtkOr5uJ9VcQSWgRhQ9h01AehtBIPAczk/b2CLrMsw5yQZziLs5cZ3pJ3478yI+urhA==", + "requires": { + "@algolia/cache-common": "4.13.0", + "@algolia/logger-common": "4.13.0", + "@algolia/requester-common": "4.13.0" + } + }, + "@ampproject/remapping": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz", + "integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==", + "requires": { + "@jridgewell/gen-mapping": "^0.1.0", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "@babel/code-frame": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz", + "integrity": "sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==", + "requires": { + "@babel/highlight": "^7.16.7" + } + }, + "@babel/compat-data": { + "version": "7.17.10", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.17.10.tgz", + "integrity": "sha512-GZt/TCsG70Ms19gfZO1tM4CVnXsPgEPBCpJu+Qz3L0LUDsY5nZqFZglIoPC1kIYOtNBZlrnFT+klg12vFGZXrw==" + }, + "@babel/core": { + "version": "7.17.10", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.17.10.tgz", + "integrity": "sha512-liKoppandF3ZcBnIYFjfSDHZLKdLHGJRkoWtG8zQyGJBQfIYobpnVGI5+pLBNtS6psFLDzyq8+h5HiVljW9PNA==", + "requires": { + "@ampproject/remapping": "^2.1.0", + "@babel/code-frame": "^7.16.7", + "@babel/generator": "^7.17.10", + "@babel/helper-compilation-targets": "^7.17.10", + "@babel/helper-module-transforms": "^7.17.7", + "@babel/helpers": "^7.17.9", + "@babel/parser": "^7.17.10", + "@babel/template": "^7.16.7", + "@babel/traverse": "^7.17.10", + "@babel/types": "^7.17.10", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.1", + "semver": "^6.3.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" + } + } + }, + "@babel/generator": { + "version": "7.17.10", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.17.10.tgz", + "integrity": "sha512-46MJZZo9y3o4kmhBVc7zW7i8dtR1oIK/sdO5NcfcZRhTGYi+KKJRtHNgsU6c4VUcJmUNV/LQdebD/9Dlv4K+Tg==", + "requires": { + "@babel/types": "^7.17.10", + "@jridgewell/gen-mapping": "^0.1.0", + "jsesc": "^2.5.1" + } + }, + "@babel/helper-annotate-as-pure": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.16.7.tgz", + "integrity": "sha512-s6t2w/IPQVTAET1HitoowRGXooX8mCgtuP5195wD/QJPV6wYjpujCGF7JuMODVX2ZAJOf1GT6DT9MHEZvLOFSw==", + "requires": { + "@babel/types": "^7.16.7" + } + }, + "@babel/helper-builder-binary-assignment-operator-visitor": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.16.7.tgz", + "integrity": "sha512-C6FdbRaxYjwVu/geKW4ZeQ0Q31AftgRcdSnZ5/jsH6BzCJbtvXvhpfkbkThYSuutZA7nCXpPR6AD9zd1dprMkA==", + "requires": { + "@babel/helper-explode-assignable-expression": "^7.16.7", + "@babel/types": "^7.16.7" + } + }, + "@babel/helper-compilation-targets": { + "version": "7.17.10", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.17.10.tgz", + "integrity": "sha512-gh3RxjWbauw/dFiU/7whjd0qN9K6nPJMqe6+Er7rOavFh0CQUSwhAE3IcTho2rywPJFxej6TUUHDkWcYI6gGqQ==", + "requires": { + "@babel/compat-data": "^7.17.10", + "@babel/helper-validator-option": "^7.16.7", + "browserslist": "^4.20.2", + "semver": "^6.3.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" + } + } + }, + "@babel/helper-create-class-features-plugin": { + "version": "7.17.9", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.17.9.tgz", + "integrity": "sha512-kUjip3gruz6AJKOq5i3nC6CoCEEF/oHH3cp6tOZhB+IyyyPyW0g1Gfsxn3mkk6S08pIA2y8GQh609v9G/5sHVQ==", + "requires": { + "@babel/helper-annotate-as-pure": "^7.16.7", + "@babel/helper-environment-visitor": "^7.16.7", + "@babel/helper-function-name": "^7.17.9", + "@babel/helper-member-expression-to-functions": "^7.17.7", + "@babel/helper-optimise-call-expression": "^7.16.7", + "@babel/helper-replace-supers": "^7.16.7", + "@babel/helper-split-export-declaration": "^7.16.7" + } + }, + "@babel/helper-create-regexp-features-plugin": { + "version": "7.17.0", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.17.0.tgz", + "integrity": "sha512-awO2So99wG6KnlE+TPs6rn83gCz5WlEePJDTnLEqbchMVrBeAujURVphRdigsk094VhvZehFoNOihSlcBjwsXA==", + "requires": { + "@babel/helper-annotate-as-pure": "^7.16.7", + "regexpu-core": "^5.0.1" + } + }, + "@babel/helper-define-polyfill-provider": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.3.1.tgz", + "integrity": "sha512-J9hGMpJQmtWmj46B3kBHmL38UhJGhYX7eqkcq+2gsstyYt341HmPeWspihX43yVRA0mS+8GGk2Gckc7bY/HCmA==", + "requires": { + "@babel/helper-compilation-targets": "^7.13.0", + "@babel/helper-module-imports": "^7.12.13", + "@babel/helper-plugin-utils": "^7.13.0", + "@babel/traverse": "^7.13.0", + "debug": "^4.1.1", + "lodash.debounce": "^4.0.8", + "resolve": "^1.14.2", + "semver": "^6.1.2" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" + } + } + }, + "@babel/helper-environment-visitor": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.16.7.tgz", + "integrity": "sha512-SLLb0AAn6PkUeAfKJCCOl9e1R53pQlGAfc4y4XuMRZfqeMYLE0dM1LMhqbGAlGQY0lfw5/ohoYWAe9V1yibRag==", + "requires": { + "@babel/types": "^7.16.7" + } + }, + "@babel/helper-explode-assignable-expression": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.16.7.tgz", + "integrity": "sha512-KyUenhWMC8VrxzkGP0Jizjo4/Zx+1nNZhgocs+gLzyZyB8SHidhoq9KK/8Ato4anhwsivfkBLftky7gvzbZMtQ==", + "requires": { + "@babel/types": "^7.16.7" + } + }, + "@babel/helper-function-name": { + "version": "7.17.9", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.17.9.tgz", + "integrity": "sha512-7cRisGlVtiVqZ0MW0/yFB4atgpGLWEHUVYnb448hZK4x+vih0YO5UoS11XIYtZYqHd0dIPMdUSv8q5K4LdMnIg==", + "requires": { + "@babel/template": "^7.16.7", + "@babel/types": "^7.17.0" + } + }, + "@babel/helper-hoist-variables": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.7.tgz", + "integrity": "sha512-m04d/0Op34H5v7pbZw6pSKP7weA6lsMvfiIAMeIvkY/R4xQtBSMFEigu9QTZ2qB/9l22vsxtM8a+Q8CzD255fg==", + "requires": { + "@babel/types": "^7.16.7" + } + }, + "@babel/helper-member-expression-to-functions": { + "version": "7.17.7", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.17.7.tgz", + "integrity": "sha512-thxXgnQ8qQ11W2wVUObIqDL4p148VMxkt5T/qpN5k2fboRyzFGFmKsTGViquyM5QHKUy48OZoca8kw4ajaDPyw==", + "requires": { + "@babel/types": "^7.17.0" + } + }, + "@babel/helper-module-imports": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.16.7.tgz", + "integrity": "sha512-LVtS6TqjJHFc+nYeITRo6VLXve70xmq7wPhWTqDJusJEgGmkAACWwMiTNrvfoQo6hEhFwAIixNkvB0jPXDL8Wg==", + "requires": { + "@babel/types": "^7.16.7" + } + }, + "@babel/helper-module-transforms": { + "version": "7.17.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.17.7.tgz", + "integrity": "sha512-VmZD99F3gNTYB7fJRDTi+u6l/zxY0BE6OIxPSU7a50s6ZUQkHwSDmV92FfM+oCG0pZRVojGYhkR8I0OGeCVREw==", + "requires": { + "@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.17.3", + "@babel/types": "^7.17.0" + } + }, + "@babel/helper-optimise-call-expression": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.16.7.tgz", + "integrity": "sha512-EtgBhg7rd/JcnpZFXpBy0ze1YRfdm7BnBX4uKMBd3ixa3RGAE002JZB66FJyNH7g0F38U05pXmA5P8cBh7z+1w==", + "requires": { + "@babel/types": "^7.16.7" + } + }, + "@babel/helper-plugin-utils": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.16.7.tgz", + "integrity": "sha512-Qg3Nk7ZxpgMrsox6HreY1ZNKdBq7K72tDSliA6dCl5f007jR4ne8iD5UzuNnCJH2xBf2BEEVGr+/OL6Gdp7RxA==" + }, + "@babel/helper-remap-async-to-generator": { + "version": "7.16.8", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.16.8.tgz", + "integrity": "sha512-fm0gH7Flb8H51LqJHy3HJ3wnE1+qtYR2A99K06ahwrawLdOFsCEWjZOrYricXJHoPSudNKxrMBUPEIPxiIIvBw==", + "requires": { + "@babel/helper-annotate-as-pure": "^7.16.7", + "@babel/helper-wrap-function": "^7.16.8", + "@babel/types": "^7.16.8" + } + }, + "@babel/helper-replace-supers": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.16.7.tgz", + "integrity": "sha512-y9vsWilTNaVnVh6xiJfABzsNpgDPKev9HnAgz6Gb1p6UUwf9NepdlsV7VXGCftJM+jqD5f7JIEubcpLjZj5dBw==", + "requires": { + "@babel/helper-environment-visitor": "^7.16.7", + "@babel/helper-member-expression-to-functions": "^7.16.7", + "@babel/helper-optimise-call-expression": "^7.16.7", + "@babel/traverse": "^7.16.7", + "@babel/types": "^7.16.7" + } + }, + "@babel/helper-simple-access": { + "version": "7.17.7", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.17.7.tgz", + "integrity": "sha512-txyMCGroZ96i+Pxr3Je3lzEJjqwaRC9buMUgtomcrLe5Nd0+fk1h0LLA+ixUF5OW7AhHuQ7Es1WcQJZmZsz2XA==", + "requires": { + "@babel/types": "^7.17.0" + } + }, + "@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.16.0.tgz", + "integrity": "sha512-+il1gTy0oHwUsBQZyJvukbB4vPMdcYBrFHa0Uc4AizLxbq6BOYC51Rv4tWocX9BLBDLZ4kc6qUFpQ6HRgL+3zw==", + "requires": { + "@babel/types": "^7.16.0" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.7.tgz", + "integrity": "sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw==", + "requires": { + "@babel/types": "^7.16.7" + } + }, + "@babel/helper-validator-identifier": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz", + "integrity": "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==" + }, + "@babel/helper-validator-option": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.16.7.tgz", + "integrity": "sha512-TRtenOuRUVo9oIQGPC5G9DgK4743cdxvtOw0weQNpZXaS16SCBi5MNjZF8vba3ETURjZpTbVn7Vvcf2eAwFozQ==" + }, + "@babel/helper-wrap-function": { + "version": "7.16.8", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.16.8.tgz", + "integrity": "sha512-8RpyRVIAW1RcDDGTA+GpPAwV22wXCfKOoM9bet6TLkGIFTkRQSkH1nMQ5Yet4MpoXe1ZwHPVtNasc2w0uZMqnw==", + "requires": { + "@babel/helper-function-name": "^7.16.7", + "@babel/template": "^7.16.7", + "@babel/traverse": "^7.16.8", + "@babel/types": "^7.16.8" + } + }, + "@babel/helpers": { + "version": "7.17.9", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.17.9.tgz", + "integrity": "sha512-cPCt915ShDWUEzEp3+UNRktO2n6v49l5RSnG9M5pS24hA+2FAc5si+Pn1i4VVbQQ+jh+bIZhPFQOJOzbrOYY1Q==", + "requires": { + "@babel/template": "^7.16.7", + "@babel/traverse": "^7.17.9", + "@babel/types": "^7.17.0" + } + }, + "@babel/highlight": { + "version": "7.17.9", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.17.9.tgz", + "integrity": "sha512-J9PfEKCbFIv2X5bjTMiZu6Vf341N05QIY+d6FvVKynkG1S7G0j3I0QoRtWIrXhZ+/Nlb5Q0MzqL7TokEJ5BNHg==", + "requires": { + "@babel/helper-validator-identifier": "^7.16.7", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + } + }, + "@babel/parser": { + "version": "7.17.10", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.17.10.tgz", + "integrity": "sha512-n2Q6i+fnJqzOaq2VkdXxy2TCPCWQZHiCo0XqmrCvDWcZQKRyZzYi4Z0yxlBuN0w+r2ZHmre+Q087DSrw3pbJDQ==" + }, + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.16.7.tgz", + "integrity": "sha512-anv/DObl7waiGEnC24O9zqL0pSuI9hljihqiDuFHC8d7/bjr/4RLGPWuc8rYOff/QPzbEPSkzG8wGG9aDuhHRg==", + "requires": { + "@babel/helper-plugin-utils": "^7.16.7" + } + }, + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.16.7.tgz", + "integrity": "sha512-di8vUHRdf+4aJ7ltXhaDbPoszdkh59AQtJM5soLsuHpQJdFQZOA4uGj0V2u/CZ8bJ/u8ULDL5yq6FO/bCXnKHw==", + "requires": { + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.16.0", + "@babel/plugin-proposal-optional-chaining": "^7.16.7" + } + }, + "@babel/plugin-proposal-async-generator-functions": { + "version": "7.16.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.16.8.tgz", + "integrity": "sha512-71YHIvMuiuqWJQkebWJtdhQTfd4Q4mF76q2IX37uZPkG9+olBxsX+rH1vkhFto4UeJZ9dPY2s+mDvhDm1u2BGQ==", + "requires": { + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/helper-remap-async-to-generator": "^7.16.8", + "@babel/plugin-syntax-async-generators": "^7.8.4" + } + }, + "@babel/plugin-proposal-class-properties": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.16.7.tgz", + "integrity": "sha512-IobU0Xme31ewjYOShSIqd/ZGM/r/cuOz2z0MDbNrhF5FW+ZVgi0f2lyeoj9KFPDOAqsYxmLWZte1WOwlvY9aww==", + "requires": { + "@babel/helper-create-class-features-plugin": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7" + } + }, + "@babel/plugin-proposal-class-static-block": { + "version": "7.17.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.17.6.tgz", + "integrity": "sha512-X/tididvL2zbs7jZCeeRJ8167U/+Ac135AM6jCAx6gYXDUviZV5Ku9UDvWS2NCuWlFjIRXklYhwo6HhAC7ETnA==", + "requires": { + "@babel/helper-create-class-features-plugin": "^7.17.6", + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/plugin-syntax-class-static-block": "^7.14.5" + } + }, + "@babel/plugin-proposal-dynamic-import": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.16.7.tgz", + "integrity": "sha512-I8SW9Ho3/8DRSdmDdH3gORdyUuYnk1m4cMxUAdu5oy4n3OfN8flDEH+d60iG7dUfi0KkYwSvoalHzzdRzpWHTg==", + "requires": { + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/plugin-syntax-dynamic-import": "^7.8.3" + } + }, + "@babel/plugin-proposal-export-namespace-from": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.16.7.tgz", + "integrity": "sha512-ZxdtqDXLRGBL64ocZcs7ovt71L3jhC1RGSyR996svrCi3PYqHNkb3SwPJCs8RIzD86s+WPpt2S73+EHCGO+NUA==", + "requires": { + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3" + } + }, + "@babel/plugin-proposal-json-strings": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.16.7.tgz", + "integrity": "sha512-lNZ3EEggsGY78JavgbHsK9u5P3pQaW7k4axlgFLYkMd7UBsiNahCITShLjNQschPyjtO6dADrL24757IdhBrsQ==", + "requires": { + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/plugin-syntax-json-strings": "^7.8.3" + } + }, + "@babel/plugin-proposal-logical-assignment-operators": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.16.7.tgz", + "integrity": "sha512-K3XzyZJGQCr00+EtYtrDjmwX7o7PLK6U9bi1nCwkQioRFVUv6dJoxbQjtWVtP+bCPy82bONBKG8NPyQ4+i6yjg==", + "requires": { + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" + } + }, + "@babel/plugin-proposal-nullish-coalescing-operator": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.16.7.tgz", + "integrity": "sha512-aUOrYU3EVtjf62jQrCj63pYZ7k6vns2h/DQvHPWGmsJRYzWXZ6/AsfgpiRy6XiuIDADhJzP2Q9MwSMKauBQ+UQ==", + "requires": { + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" + } + }, + "@babel/plugin-proposal-numeric-separator": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.16.7.tgz", + "integrity": "sha512-vQgPMknOIgiuVqbokToyXbkY/OmmjAzr/0lhSIbG/KmnzXPGwW/AdhdKpi+O4X/VkWiWjnkKOBiqJrTaC98VKw==", + "requires": { + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/plugin-syntax-numeric-separator": "^7.10.4" + } + }, + "@babel/plugin-proposal-object-rest-spread": { + "version": "7.17.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.17.3.tgz", + "integrity": "sha512-yuL5iQA/TbZn+RGAfxQXfi7CNLmKi1f8zInn4IgobuCWcAb7i+zj4TYzQ9l8cEzVyJ89PDGuqxK1xZpUDISesw==", + "requires": { + "@babel/compat-data": "^7.17.0", + "@babel/helper-compilation-targets": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-transform-parameters": "^7.16.7" + } + }, + "@babel/plugin-proposal-optional-catch-binding": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.16.7.tgz", + "integrity": "sha512-eMOH/L4OvWSZAE1VkHbr1vckLG1WUcHGJSLqqQwl2GaUqG6QjddvrOaTUMNYiv77H5IKPMZ9U9P7EaHwvAShfA==", + "requires": { + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" + } + }, + "@babel/plugin-proposal-optional-chaining": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.16.7.tgz", + "integrity": "sha512-eC3xy+ZrUcBtP7x+sq62Q/HYd674pPTb/77XZMb5wbDPGWIdUbSr4Agr052+zaUPSb+gGRnjxXfKFvx5iMJ+DA==", + "requires": { + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.16.0", + "@babel/plugin-syntax-optional-chaining": "^7.8.3" + } + }, + "@babel/plugin-proposal-private-methods": { + "version": "7.16.11", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.16.11.tgz", + "integrity": "sha512-F/2uAkPlXDr8+BHpZvo19w3hLFKge+k75XUprE6jaqKxjGkSYcK+4c+bup5PdW/7W/Rpjwql7FTVEDW+fRAQsw==", + "requires": { + "@babel/helper-create-class-features-plugin": "^7.16.10", + "@babel/helper-plugin-utils": "^7.16.7" + } + }, + "@babel/plugin-proposal-private-property-in-object": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.16.7.tgz", + "integrity": "sha512-rMQkjcOFbm+ufe3bTZLyOfsOUOxyvLXZJCTARhJr+8UMSoZmqTe1K1BgkFcrW37rAchWg57yI69ORxiWvUINuQ==", + "requires": { + "@babel/helper-annotate-as-pure": "^7.16.7", + "@babel/helper-create-class-features-plugin": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5" + } + }, + "@babel/plugin-proposal-unicode-property-regex": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.16.7.tgz", + "integrity": "sha512-QRK0YI/40VLhNVGIjRNAAQkEHws0cswSdFFjpFyt943YmJIU1da9uW63Iu6NFV6CxTZW5eTDCrwZUstBWgp/Rg==", + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7" + } + }, + "@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-bigint": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", + "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "requires": { + "@babel/helper-plugin-utils": "^7.12.13" + } + }, + "@babel/plugin-syntax-class-static-block": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", + "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-syntax-dynamic-import": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", + "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-export-namespace-from": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", + "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + } + }, + "@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-jsx": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.16.7.tgz", + "integrity": "sha512-Esxmk7YjA8QysKeT3VhTXvF6y77f/a91SIs4pWb4H2eWGQkCKFgQaG6hdoEVZtGsrAcb2K5BW66XsOErD4WU3Q==", + "requires": { + "@babel/helper-plugin-utils": "^7.16.7" + } + }, + "@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-private-property-in-object": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", + "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-syntax-typescript": { + "version": "7.17.10", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.17.10.tgz", + "integrity": "sha512-xJefea1DWXW09pW4Tm9bjwVlPDyYA2it3fWlmEjpYz6alPvTUjL0EOzNzI/FEOyI3r4/J7uVH5UqKgl1TQ5hqQ==", + "requires": { + "@babel/helper-plugin-utils": "^7.16.7" + } + }, + "@babel/plugin-transform-arrow-functions": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.16.7.tgz", + "integrity": "sha512-9ffkFFMbvzTvv+7dTp/66xvZAWASuPD5Tl9LK3Z9vhOmANo6j94rik+5YMBt4CwHVMWLWpMsriIc2zsa3WW3xQ==", + "requires": { + "@babel/helper-plugin-utils": "^7.16.7" + } + }, + "@babel/plugin-transform-async-to-generator": { + "version": "7.16.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.16.8.tgz", + "integrity": "sha512-MtmUmTJQHCnyJVrScNzNlofQJ3dLFuobYn3mwOTKHnSCMtbNsqvF71GQmJfFjdrXSsAA7iysFmYWw4bXZ20hOg==", + "requires": { + "@babel/helper-module-imports": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/helper-remap-async-to-generator": "^7.16.8" + } + }, + "@babel/plugin-transform-block-scoped-functions": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.16.7.tgz", + "integrity": "sha512-JUuzlzmF40Z9cXyytcbZEZKckgrQzChbQJw/5PuEHYeqzCsvebDx0K0jWnIIVcmmDOAVctCgnYs0pMcrYj2zJg==", + "requires": { + "@babel/helper-plugin-utils": "^7.16.7" + } + }, + "@babel/plugin-transform-block-scoping": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.16.7.tgz", + "integrity": "sha512-ObZev2nxVAYA4bhyusELdo9hb3H+A56bxH3FZMbEImZFiEDYVHXQSJ1hQKFlDnlt8G9bBrCZ5ZpURZUrV4G5qQ==", + "requires": { + "@babel/helper-plugin-utils": "^7.16.7" + } + }, + "@babel/plugin-transform-classes": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.16.7.tgz", + "integrity": "sha512-WY7og38SFAGYRe64BrjKf8OrE6ulEHtr5jEYaZMwox9KebgqPi67Zqz8K53EKk1fFEJgm96r32rkKZ3qA2nCWQ==", + "requires": { + "@babel/helper-annotate-as-pure": "^7.16.7", + "@babel/helper-environment-visitor": "^7.16.7", + "@babel/helper-function-name": "^7.16.7", + "@babel/helper-optimise-call-expression": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/helper-replace-supers": "^7.16.7", + "@babel/helper-split-export-declaration": "^7.16.7", + "globals": "^11.1.0" + } + }, + "@babel/plugin-transform-computed-properties": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.16.7.tgz", + "integrity": "sha512-gN72G9bcmenVILj//sv1zLNaPyYcOzUho2lIJBMh/iakJ9ygCo/hEF9cpGb61SCMEDxbbyBoVQxrt+bWKu5KGw==", + "requires": { + "@babel/helper-plugin-utils": "^7.16.7" + } + }, + "@babel/plugin-transform-destructuring": { + "version": "7.17.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.17.7.tgz", + "integrity": "sha512-XVh0r5yq9sLR4vZ6eVZe8FKfIcSgaTBxVBRSYokRj2qksf6QerYnTxz9/GTuKTH/n/HwLP7t6gtlybHetJ/6hQ==", + "requires": { + "@babel/helper-plugin-utils": "^7.16.7" + } + }, + "@babel/plugin-transform-dotall-regex": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.16.7.tgz", + "integrity": "sha512-Lyttaao2SjZF6Pf4vk1dVKv8YypMpomAbygW+mU5cYP3S5cWTfCJjG8xV6CFdzGFlfWK81IjL9viiTvpb6G7gQ==", + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7" + } + }, + "@babel/plugin-transform-duplicate-keys": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.16.7.tgz", + "integrity": "sha512-03DvpbRfvWIXyK0/6QiR1KMTWeT6OcQ7tbhjrXyFS02kjuX/mu5Bvnh5SDSWHxyawit2g5aWhKwI86EE7GUnTw==", + "requires": { + "@babel/helper-plugin-utils": "^7.16.7" + } + }, + "@babel/plugin-transform-exponentiation-operator": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.16.7.tgz", + "integrity": "sha512-8UYLSlyLgRixQvlYH3J2ekXFHDFLQutdy7FfFAMm3CPZ6q9wHCwnUyiXpQCe3gVVnQlHc5nsuiEVziteRNTXEA==", + "requires": { + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7" + } + }, + "@babel/plugin-transform-for-of": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.16.7.tgz", + "integrity": "sha512-/QZm9W92Ptpw7sjI9Nx1mbcsWz33+l8kuMIQnDwgQBG5s3fAfQvkRjQ7NqXhtNcKOnPkdICmUHyCaWW06HCsqg==", + "requires": { + "@babel/helper-plugin-utils": "^7.16.7" + } + }, + "@babel/plugin-transform-function-name": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.16.7.tgz", + "integrity": "sha512-SU/C68YVwTRxqWj5kgsbKINakGag0KTgq9f2iZEXdStoAbOzLHEBRYzImmA6yFo8YZhJVflvXmIHUO7GWHmxxA==", + "requires": { + "@babel/helper-compilation-targets": "^7.16.7", + "@babel/helper-function-name": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7" + } + }, + "@babel/plugin-transform-literals": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.16.7.tgz", + "integrity": "sha512-6tH8RTpTWI0s2sV6uq3e/C9wPo4PTqqZps4uF0kzQ9/xPLFQtipynvmT1g/dOfEJ+0EQsHhkQ/zyRId8J2b8zQ==", + "requires": { + "@babel/helper-plugin-utils": "^7.16.7" + } + }, + "@babel/plugin-transform-member-expression-literals": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.16.7.tgz", + "integrity": "sha512-mBruRMbktKQwbxaJof32LT9KLy2f3gH+27a5XSuXo6h7R3vqltl0PgZ80C8ZMKw98Bf8bqt6BEVi3svOh2PzMw==", + "requires": { + "@babel/helper-plugin-utils": "^7.16.7" + } + }, + "@babel/plugin-transform-modules-amd": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.16.7.tgz", + "integrity": "sha512-KaaEtgBL7FKYwjJ/teH63oAmE3lP34N3kshz8mm4VMAw7U3PxjVwwUmxEFksbgsNUaO3wId9R2AVQYSEGRa2+g==", + "requires": { + "@babel/helper-module-transforms": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7", + "babel-plugin-dynamic-import-node": "^2.3.3" + }, + "dependencies": { + "babel-plugin-dynamic-import-node": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz", + "integrity": "sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==", + "requires": { + "object.assign": "^4.1.0" + } + } + } + }, + "@babel/plugin-transform-modules-commonjs": { + "version": "7.17.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.17.9.tgz", + "integrity": "sha512-2TBFd/r2I6VlYn0YRTz2JdazS+FoUuQ2rIFHoAxtyP/0G3D82SBLaRq9rnUkpqlLg03Byfl/+M32mpxjO6KaPw==", + "requires": { + "@babel/helper-module-transforms": "^7.17.7", + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/helper-simple-access": "^7.17.7", + "babel-plugin-dynamic-import-node": "^2.3.3" + }, + "dependencies": { + "babel-plugin-dynamic-import-node": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz", + "integrity": "sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==", + "requires": { + "object.assign": "^4.1.0" + } + } + } + }, + "@babel/plugin-transform-modules-systemjs": { + "version": "7.17.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.17.8.tgz", + "integrity": "sha512-39reIkMTUVagzgA5x88zDYXPCMT6lcaRKs1+S9K6NKBPErbgO/w/kP8GlNQTC87b412ZTlmNgr3k2JrWgHH+Bw==", + "requires": { + "@babel/helper-hoist-variables": "^7.16.7", + "@babel/helper-module-transforms": "^7.17.7", + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/helper-validator-identifier": "^7.16.7", + "babel-plugin-dynamic-import-node": "^2.3.3" + }, + "dependencies": { + "babel-plugin-dynamic-import-node": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz", + "integrity": "sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==", + "requires": { + "object.assign": "^4.1.0" + } + } + } + }, + "@babel/plugin-transform-modules-umd": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.16.7.tgz", + "integrity": "sha512-EMh7uolsC8O4xhudF2F6wedbSHm1HHZ0C6aJ7K67zcDNidMzVcxWdGr+htW9n21klm+bOn+Rx4CBsAntZd3rEQ==", + "requires": { + "@babel/helper-module-transforms": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7" + } + }, + "@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.17.10", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.17.10.tgz", + "integrity": "sha512-v54O6yLaJySCs6mGzaVOUw9T967GnH38T6CQSAtnzdNPwu84l2qAjssKzo/WSO8Yi7NF+7ekm5cVbF/5qiIgNA==", + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.17.0" + } + }, + "@babel/plugin-transform-new-target": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.16.7.tgz", + "integrity": "sha512-xiLDzWNMfKoGOpc6t3U+etCE2yRnn3SM09BXqWPIZOBpL2gvVrBWUKnsJx0K/ADi5F5YC5f8APFfWrz25TdlGg==", + "requires": { + "@babel/helper-plugin-utils": "^7.16.7" + } + }, + "@babel/plugin-transform-object-super": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.16.7.tgz", + "integrity": "sha512-14J1feiQVWaGvRxj2WjyMuXS2jsBkgB3MdSN5HuC2G5nRspa5RK9COcs82Pwy5BuGcjb+fYaUj94mYcOj7rCvw==", + "requires": { + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/helper-replace-supers": "^7.16.7" + } + }, + "@babel/plugin-transform-parameters": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.16.7.tgz", + "integrity": "sha512-AT3MufQ7zZEhU2hwOA11axBnExW0Lszu4RL/tAlUJBuNoRak+wehQW8h6KcXOcgjY42fHtDxswuMhMjFEuv/aw==", + "requires": { + "@babel/helper-plugin-utils": "^7.16.7" + } + }, + "@babel/plugin-transform-property-literals": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.16.7.tgz", + "integrity": "sha512-z4FGr9NMGdoIl1RqavCqGG+ZuYjfZ/hkCIeuH6Do7tXmSm0ls11nYVSJqFEUOSJbDab5wC6lRE/w6YjVcr6Hqw==", + "requires": { + "@babel/helper-plugin-utils": "^7.16.7" + } + }, + "@babel/plugin-transform-react-constant-elements": { + "version": "7.17.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.17.6.tgz", + "integrity": "sha512-OBv9VkyyKtsHZiHLoSfCn+h6yU7YKX8nrs32xUmOa1SRSk+t03FosB6fBZ0Yz4BpD1WV7l73Nsad+2Tz7APpqw==", + "requires": { + "@babel/helper-plugin-utils": "^7.16.7" + } + }, + "@babel/plugin-transform-react-display-name": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.16.7.tgz", + "integrity": "sha512-qgIg8BcZgd0G/Cz916D5+9kqX0c7nPZyXaP8R2tLNN5tkyIZdG5fEwBrxwplzSnjC1jvQmyMNVwUCZPcbGY7Pg==", + "requires": { + "@babel/helper-plugin-utils": "^7.16.7" + } + }, + "@babel/plugin-transform-react-jsx": { + "version": "7.17.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.17.3.tgz", + "integrity": "sha512-9tjBm4O07f7mzKSIlEmPdiE6ub7kfIe6Cd+w+oQebpATfTQMAgW+YOuWxogbKVTulA+MEO7byMeIUtQ1z+z+ZQ==", + "requires": { + "@babel/helper-annotate-as-pure": "^7.16.7", + "@babel/helper-module-imports": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/plugin-syntax-jsx": "^7.16.7", + "@babel/types": "^7.17.0" + } + }, + "@babel/plugin-transform-react-jsx-development": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.16.7.tgz", + "integrity": "sha512-RMvQWvpla+xy6MlBpPlrKZCMRs2AGiHOGHY3xRwl0pEeim348dDyxeH4xBsMPbIMhujeq7ihE702eM2Ew0Wo+A==", + "requires": { + "@babel/plugin-transform-react-jsx": "^7.16.7" + } + }, + "@babel/plugin-transform-react-pure-annotations": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.16.7.tgz", + "integrity": "sha512-hs71ToC97k3QWxswh2ElzMFABXHvGiJ01IB1TbYQDGeWRKWz/MPUTh5jGExdHvosYKpnJW5Pm3S4+TA3FyX+GA==", + "requires": { + "@babel/helper-annotate-as-pure": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7" + } + }, + "@babel/plugin-transform-regenerator": { + "version": "7.17.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.17.9.tgz", + "integrity": "sha512-Lc2TfbxR1HOyn/c6b4Y/b6NHoTb67n/IoWLxTu4kC7h4KQnWlhCq2S8Tx0t2SVvv5Uu87Hs+6JEJ5kt2tYGylQ==", + "requires": { + "regenerator-transform": "^0.15.0" + } + }, + "@babel/plugin-transform-reserved-words": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.16.7.tgz", + "integrity": "sha512-KQzzDnZ9hWQBjwi5lpY5v9shmm6IVG0U9pB18zvMu2i4H90xpT4gmqwPYsn8rObiadYe2M0gmgsiOIF5A/2rtg==", + "requires": { + "@babel/helper-plugin-utils": "^7.16.7" + } + }, + "@babel/plugin-transform-runtime": { + "version": "7.17.10", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.17.10.tgz", + "integrity": "sha512-6jrMilUAJhktTr56kACL8LnWC5hx3Lf27BS0R0DSyW/OoJfb/iTHeE96V3b1dgKG3FSFdd/0culnYWMkjcKCig==", + "requires": { + "@babel/helper-module-imports": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7", + "babel-plugin-polyfill-corejs2": "^0.3.0", + "babel-plugin-polyfill-corejs3": "^0.5.0", + "babel-plugin-polyfill-regenerator": "^0.3.0", + "semver": "^6.3.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" + } + } + }, + "@babel/plugin-transform-shorthand-properties": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.16.7.tgz", + "integrity": "sha512-hah2+FEnoRoATdIb05IOXf+4GzXYTq75TVhIn1PewihbpyrNWUt2JbudKQOETWw6QpLe+AIUpJ5MVLYTQbeeUg==", + "requires": { + "@babel/helper-plugin-utils": "^7.16.7" + } + }, + "@babel/plugin-transform-spread": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.16.7.tgz", + "integrity": "sha512-+pjJpgAngb53L0iaA5gU/1MLXJIfXcYepLgXB3esVRf4fqmj8f2cxM3/FKaHsZms08hFQJkFccEWuIpm429TXg==", + "requires": { + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.16.0" + } + }, + "@babel/plugin-transform-sticky-regex": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.16.7.tgz", + "integrity": "sha512-NJa0Bd/87QV5NZZzTuZG5BPJjLYadeSZ9fO6oOUoL4iQx+9EEuw/eEM92SrsT19Yc2jgB1u1hsjqDtH02c3Drw==", + "requires": { + "@babel/helper-plugin-utils": "^7.16.7" + } + }, + "@babel/plugin-transform-template-literals": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.16.7.tgz", + "integrity": "sha512-VwbkDDUeenlIjmfNeDX/V0aWrQH2QiVyJtwymVQSzItFDTpxfyJh3EVaQiS0rIN/CqbLGr0VcGmuwyTdZtdIsA==", + "requires": { + "@babel/helper-plugin-utils": "^7.16.7" + } + }, + "@babel/plugin-transform-typeof-symbol": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.16.7.tgz", + "integrity": "sha512-p2rOixCKRJzpg9JB4gjnG4gjWkWa89ZoYUnl9snJ1cWIcTH/hvxZqfO+WjG6T8DRBpctEol5jw1O5rA8gkCokQ==", + "requires": { + "@babel/helper-plugin-utils": "^7.16.7" + } + }, + "@babel/plugin-transform-typescript": { + "version": "7.16.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.16.8.tgz", + "integrity": "sha512-bHdQ9k7YpBDO2d0NVfkj51DpQcvwIzIusJ7mEUaMlbZq3Kt/U47j24inXZHQ5MDiYpCs+oZiwnXyKedE8+q7AQ==", + "requires": { + "@babel/helper-create-class-features-plugin": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/plugin-syntax-typescript": "^7.16.7" + } + }, + "@babel/plugin-transform-unicode-escapes": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.16.7.tgz", + "integrity": "sha512-TAV5IGahIz3yZ9/Hfv35TV2xEm+kaBDaZQCn2S/hG9/CZ0DktxJv9eKfPc7yYCvOYR4JGx1h8C+jcSOvgaaI/Q==", + "requires": { + "@babel/helper-plugin-utils": "^7.16.7" + } + }, + "@babel/plugin-transform-unicode-regex": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.16.7.tgz", + "integrity": "sha512-oC5tYYKw56HO75KZVLQ+R/Nl3Hro9kf8iG0hXoaHP7tjAyCpvqBiSNe6vGrZni1Z6MggmUOC6A7VP7AVmw225Q==", + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7" + } + }, + "@babel/preset-env": { + "version": "7.17.10", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.17.10.tgz", + "integrity": "sha512-YNgyBHZQpeoBSRBg0xixsZzfT58Ze1iZrajvv0lJc70qDDGuGfonEnMGfWeSY0mQ3JTuCWFbMkzFRVafOyJx4g==", + "requires": { + "@babel/compat-data": "^7.17.10", + "@babel/helper-compilation-targets": "^7.17.10", + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/helper-validator-option": "^7.16.7", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.16.7", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.16.7", + "@babel/plugin-proposal-async-generator-functions": "^7.16.8", + "@babel/plugin-proposal-class-properties": "^7.16.7", + "@babel/plugin-proposal-class-static-block": "^7.17.6", + "@babel/plugin-proposal-dynamic-import": "^7.16.7", + "@babel/plugin-proposal-export-namespace-from": "^7.16.7", + "@babel/plugin-proposal-json-strings": "^7.16.7", + "@babel/plugin-proposal-logical-assignment-operators": "^7.16.7", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.16.7", + "@babel/plugin-proposal-numeric-separator": "^7.16.7", + "@babel/plugin-proposal-object-rest-spread": "^7.17.3", + "@babel/plugin-proposal-optional-catch-binding": "^7.16.7", + "@babel/plugin-proposal-optional-chaining": "^7.16.7", + "@babel/plugin-proposal-private-methods": "^7.16.11", + "@babel/plugin-proposal-private-property-in-object": "^7.16.7", + "@babel/plugin-proposal-unicode-property-regex": "^7.16.7", + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5", + "@babel/plugin-transform-arrow-functions": "^7.16.7", + "@babel/plugin-transform-async-to-generator": "^7.16.8", + "@babel/plugin-transform-block-scoped-functions": "^7.16.7", + "@babel/plugin-transform-block-scoping": "^7.16.7", + "@babel/plugin-transform-classes": "^7.16.7", + "@babel/plugin-transform-computed-properties": "^7.16.7", + "@babel/plugin-transform-destructuring": "^7.17.7", + "@babel/plugin-transform-dotall-regex": "^7.16.7", + "@babel/plugin-transform-duplicate-keys": "^7.16.7", + "@babel/plugin-transform-exponentiation-operator": "^7.16.7", + "@babel/plugin-transform-for-of": "^7.16.7", + "@babel/plugin-transform-function-name": "^7.16.7", + "@babel/plugin-transform-literals": "^7.16.7", + "@babel/plugin-transform-member-expression-literals": "^7.16.7", + "@babel/plugin-transform-modules-amd": "^7.16.7", + "@babel/plugin-transform-modules-commonjs": "^7.17.9", + "@babel/plugin-transform-modules-systemjs": "^7.17.8", + "@babel/plugin-transform-modules-umd": "^7.16.7", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.17.10", + "@babel/plugin-transform-new-target": "^7.16.7", + "@babel/plugin-transform-object-super": "^7.16.7", + "@babel/plugin-transform-parameters": "^7.16.7", + "@babel/plugin-transform-property-literals": "^7.16.7", + "@babel/plugin-transform-regenerator": "^7.17.9", + "@babel/plugin-transform-reserved-words": "^7.16.7", + "@babel/plugin-transform-shorthand-properties": "^7.16.7", + "@babel/plugin-transform-spread": "^7.16.7", + "@babel/plugin-transform-sticky-regex": "^7.16.7", + "@babel/plugin-transform-template-literals": "^7.16.7", + "@babel/plugin-transform-typeof-symbol": "^7.16.7", + "@babel/plugin-transform-unicode-escapes": "^7.16.7", + "@babel/plugin-transform-unicode-regex": "^7.16.7", + "@babel/preset-modules": "^0.1.5", + "@babel/types": "^7.17.10", + "babel-plugin-polyfill-corejs2": "^0.3.0", + "babel-plugin-polyfill-corejs3": "^0.5.0", + "babel-plugin-polyfill-regenerator": "^0.3.0", + "core-js-compat": "^3.22.1", + "semver": "^6.3.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" + } + } + }, + "@babel/preset-modules": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.5.tgz", + "integrity": "sha512-A57th6YRG7oR3cq/yt/Y84MvGgE0eJG2F1JLhKuyG+jFxEgrd/HAMJatiFtmOiZurz+0DkrvbheCLaV5f2JfjA==", + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-proposal-unicode-property-regex": "^7.4.4", + "@babel/plugin-transform-dotall-regex": "^7.4.4", + "@babel/types": "^7.4.4", + "esutils": "^2.0.2" + } + }, + "@babel/preset-react": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.16.7.tgz", + "integrity": "sha512-fWpyI8UM/HE6DfPBzD8LnhQ/OcH8AgTaqcqP2nGOXEUV+VKBR5JRN9hCk9ai+zQQ57vtm9oWeXguBCPNUjytgA==", + "requires": { + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/helper-validator-option": "^7.16.7", + "@babel/plugin-transform-react-display-name": "^7.16.7", + "@babel/plugin-transform-react-jsx": "^7.16.7", + "@babel/plugin-transform-react-jsx-development": "^7.16.7", + "@babel/plugin-transform-react-pure-annotations": "^7.16.7" + } + }, + "@babel/preset-typescript": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.16.7.tgz", + "integrity": "sha512-WbVEmgXdIyvzB77AQjGBEyYPZx+8tTsO50XtfozQrkW8QB2rLJpH2lgx0TRw5EJrBxOZQ+wCcyPVQvS8tjEHpQ==", + "requires": { + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/helper-validator-option": "^7.16.7", + "@babel/plugin-transform-typescript": "^7.16.7" + } + }, + "@babel/runtime": { + "version": "7.17.9", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.17.9.tgz", + "integrity": "sha512-lSiBBvodq29uShpWGNbgFdKYNiFDo5/HIYsaCEY9ff4sb10x9jizo2+pRrSyF4jKZCXqgzuqBOQKbUm90gQwJg==", + "requires": { + "regenerator-runtime": "^0.13.4" + } + }, + "@babel/runtime-corejs3": { + "version": "7.17.9", + "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.17.9.tgz", + "integrity": "sha512-WxYHHUWF2uZ7Hp1K+D1xQgbgkGUfA+5UPOegEXGt2Y5SMog/rYCVaifLZDbw8UkNXozEqqrZTy6bglL7xTaCOw==", + "requires": { + "core-js-pure": "^3.20.2", + "regenerator-runtime": "^0.13.4" + } + }, + "@babel/template": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.16.7.tgz", + "integrity": "sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w==", + "requires": { + "@babel/code-frame": "^7.16.7", + "@babel/parser": "^7.16.7", + "@babel/types": "^7.16.7" + } + }, + "@babel/traverse": { + "version": "7.17.10", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.17.10.tgz", + "integrity": "sha512-VmbrTHQteIdUUQNTb+zE12SHS/xQVIShmBPhlNP12hD5poF2pbITW1Z4172d03HegaQWhLffdkRJYtAzp0AGcw==", + "requires": { + "@babel/code-frame": "^7.16.7", + "@babel/generator": "^7.17.10", + "@babel/helper-environment-visitor": "^7.16.7", + "@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.17.10", + "@babel/types": "^7.17.10", + "debug": "^4.1.0", + "globals": "^11.1.0" + } + }, + "@babel/types": { + "version": "7.17.10", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.17.10.tgz", + "integrity": "sha512-9O26jG0mBYfGkUYCYZRnBwbVLd1UZOICEr2Em6InB6jVfsAv1GKgwXHmrSg+WFWDmeKTA6vyTZiN8tCSM5Oo3A==", + "requires": { + "@babel/helper-validator-identifier": "^7.16.7", + "to-fast-properties": "^2.0.0" + } + }, + "@bcoe/v8-coverage": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", + "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", + "dev": true + }, + "@colors/colors": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", + "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", + "optional": true + }, + "@cypress/request": { + "version": "2.88.10", + "resolved": "https://registry.npmjs.org/@cypress/request/-/request-2.88.10.tgz", + "integrity": "sha512-Zp7F+R93N0yZyG34GutyTNr+okam7s/Fzc1+i3kcqOP8vk6OuajuE9qZJ6Rs+10/1JFtXFYMdyarnU1rZuJesg==", + "dev": true, + "requires": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "http-signature": "~1.3.6", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "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": "^8.3.2" + }, + "dependencies": { + "form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "dev": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + } + }, + "qs": { + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz", + "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==", + "dev": true + }, + "tough-cookie": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", + "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", + "dev": true, + "requires": { + "psl": "^1.1.28", + "punycode": "^2.1.1" + } + }, + "uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "dev": true + } + } + }, + "@cypress/xvfb": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@cypress/xvfb/-/xvfb-1.2.4.tgz", + "integrity": "sha512-skbBzPggOVYCbnGgV+0dmBdW/s77ZkAOXIC1knS8NagwDjBrNC1LuXtQJeiN6l+m7lzmHtaoUw/ctJKdqkG57Q==", + "dev": true, + "requires": { + "debug": "^3.1.0", + "lodash.once": "^4.1.1" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + } + } + }, + "@docsearch/css": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@docsearch/css/-/css-3.0.0.tgz", + "integrity": "sha512-1kkV7tkAsiuEd0shunYRByKJe3xQDG2q7wYg24SOw1nV9/2lwEd4WrUYRJC/ukGTl2/kHeFxsaUvtiOy0y6fFA==" + }, + "@docsearch/react": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@docsearch/react/-/react-3.0.0.tgz", + "integrity": "sha512-yhMacqS6TVQYoBh/o603zszIb5Bl8MIXuOc6Vy617I74pirisDzzcNh0NEaYQt50fVVR3khUbeEhUEWEWipESg==", + "requires": { + "@algolia/autocomplete-core": "1.5.2", + "@algolia/autocomplete-preset-algolia": "1.5.2", + "@docsearch/css": "3.0.0", + "algoliasearch": "^4.0.0" + } + }, + "@docusaurus/core": { + "version": "2.0.0-beta.17", + "resolved": "https://registry.npmjs.org/@docusaurus/core/-/core-2.0.0-beta.17.tgz", + "integrity": "sha512-iNdW7CsmHNOgc4PxD9BFxa+MD8+i7ln7erOBkF3FSMMPnsKUeVqsR3rr31aLmLZRlTXMITSPLxlXwtBZa3KPCw==", + "requires": { + "@babel/core": "^7.17.5", + "@babel/generator": "^7.17.3", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-transform-runtime": "^7.17.0", + "@babel/preset-env": "^7.16.11", + "@babel/preset-react": "^7.16.7", + "@babel/preset-typescript": "^7.16.7", + "@babel/runtime": "^7.17.2", + "@babel/runtime-corejs3": "^7.17.2", + "@babel/traverse": "^7.17.3", + "@docusaurus/cssnano-preset": "2.0.0-beta.17", + "@docusaurus/logger": "2.0.0-beta.17", + "@docusaurus/mdx-loader": "2.0.0-beta.17", + "@docusaurus/react-loadable": "5.5.2", + "@docusaurus/utils": "2.0.0-beta.17", + "@docusaurus/utils-common": "2.0.0-beta.17", + "@docusaurus/utils-validation": "2.0.0-beta.17", + "@slorber/static-site-generator-webpack-plugin": "^4.0.1", + "@svgr/webpack": "^6.2.1", + "autoprefixer": "^10.4.2", + "babel-loader": "^8.2.3", + "babel-plugin-dynamic-import-node": "2.3.0", + "boxen": "^6.2.1", + "chokidar": "^3.5.3", + "clean-css": "^5.2.4", + "cli-table3": "^0.6.1", + "combine-promises": "^1.1.0", + "commander": "^5.1.0", + "copy-webpack-plugin": "^10.2.4", + "core-js": "^3.21.1", + "css-loader": "^6.6.0", + "css-minimizer-webpack-plugin": "^3.4.1", + "cssnano": "^5.0.17", + "del": "^6.0.0", + "detect-port": "^1.3.0", + "escape-html": "^1.0.3", + "eta": "^1.12.3", + "file-loader": "^6.2.0", + "fs-extra": "^10.0.1", + "html-minifier-terser": "^6.1.0", + "html-tags": "^3.1.0", + "html-webpack-plugin": "^5.5.0", + "import-fresh": "^3.3.0", + "is-root": "^2.1.0", + "leven": "^3.1.0", + "lodash": "^4.17.21", + "mini-css-extract-plugin": "^2.5.3", + "nprogress": "^0.2.0", + "postcss": "^8.4.7", + "postcss-loader": "^6.2.1", + "prompts": "^2.4.2", + "react-dev-utils": "^12.0.0", + "react-helmet-async": "^1.2.3", + "react-loadable": "npm:@docusaurus/react-loadable@5.5.2", + "react-loadable-ssr-addon-v5-slorber": "^1.0.1", + "react-router": "^5.2.0", + "react-router-config": "^5.1.1", + "react-router-dom": "^5.2.0", + "remark-admonitions": "^1.2.1", + "rtl-detect": "^1.0.4", + "semver": "^7.3.4", + "serve-handler": "^6.1.3", + "shelljs": "^0.8.5", + "terser-webpack-plugin": "^5.3.1", + "tslib": "^2.3.1", + "update-notifier": "^5.1.0", + "url-loader": "^4.1.1", + "wait-on": "^6.0.1", + "webpack": "^5.69.1", + "webpack-bundle-analyzer": "^4.5.0", + "webpack-dev-server": "^4.7.4", + "webpack-merge": "^5.8.0", + "webpackbar": "^5.0.2" + }, + "dependencies": { + "@svgr/babel-plugin-add-jsx-attribute": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-6.0.0.tgz", + "integrity": "sha512-MdPdhdWLtQsjd29Wa4pABdhWbaRMACdM1h31BY+c6FghTZqNGT7pEYdBoaGeKtdTOBC/XNFQaKVj+r/Ei2ryWA==", + "requires": {} + }, + "@svgr/babel-plugin-remove-jsx-attribute": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-6.0.0.tgz", + "integrity": "sha512-aVdtfx9jlaaxc3unA6l+M9YRnKIZjOhQPthLKqmTXC8UVkBLDRGwPKo+r8n3VZN8B34+yVajzPTZ+ptTSuZZCw==", + "requires": {} + }, + "@svgr/babel-plugin-remove-jsx-empty-expression": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-6.0.0.tgz", + "integrity": "sha512-Ccj42ApsePD451AZJJf1QzTD1B/BOU392URJTeXFxSK709i0KUsGtbwyiqsKu7vsYxpTM0IA5clAKDyf9RCZyA==", + "requires": {} + }, + "@svgr/babel-plugin-replace-jsx-attribute-value": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-6.0.0.tgz", + "integrity": "sha512-88V26WGyt1Sfd1emBYmBJRWMmgarrExpKNVmI9vVozha4kqs6FzQJ/Kp5+EYli1apgX44518/0+t9+NU36lThQ==", + "requires": {} + }, + "@svgr/babel-plugin-svg-dynamic-title": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-6.0.0.tgz", + "integrity": "sha512-F7YXNLfGze+xv0KMQxrl2vkNbI9kzT9oDK55/kUuymh1ACyXkMV+VZWX1zEhSTfEKh7VkHVZGmVtHg8eTZ6PRg==", + "requires": {} + }, + "@svgr/babel-plugin-svg-em-dimensions": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-6.0.0.tgz", + "integrity": "sha512-+rghFXxdIqJNLQK08kwPBD3Z22/0b2tEZ9lKiL/yTfuyj1wW8HUXu4bo/XkogATIYuXSghVQOOCwURXzHGKyZA==", + "requires": {} + }, + "@svgr/babel-plugin-transform-react-native-svg": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-6.0.0.tgz", + "integrity": "sha512-VaphyHZ+xIKv5v0K0HCzyfAaLhPGJXSk2HkpYfXIOKb7DjLBv0soHDxNv6X0vr2titsxE7klb++u7iOf7TSrFQ==", + "requires": {} + }, + "@svgr/babel-plugin-transform-svg-component": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-6.2.0.tgz", + "integrity": "sha512-bhYIpsORb++wpsp91fymbFkf09Z/YEKR0DnFjxvN+8JHeCUD2unnh18jIMKnDJTWtvpTaGYPXELVe4OOzFI0xg==", + "requires": {} + }, + "@svgr/babel-preset": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-preset/-/babel-preset-6.2.0.tgz", + "integrity": "sha512-4WQNY0J71JIaL03DRn0vLiz87JXx0b9dYm2aA8XHlQJQoixMl4r/soYHm8dsaJZ3jWtkCiOYy48dp9izvXhDkQ==", + "requires": { + "@svgr/babel-plugin-add-jsx-attribute": "^6.0.0", + "@svgr/babel-plugin-remove-jsx-attribute": "^6.0.0", + "@svgr/babel-plugin-remove-jsx-empty-expression": "^6.0.0", + "@svgr/babel-plugin-replace-jsx-attribute-value": "^6.0.0", + "@svgr/babel-plugin-svg-dynamic-title": "^6.0.0", + "@svgr/babel-plugin-svg-em-dimensions": "^6.0.0", + "@svgr/babel-plugin-transform-react-native-svg": "^6.0.0", + "@svgr/babel-plugin-transform-svg-component": "^6.2.0" + } + }, + "@svgr/core": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/@svgr/core/-/core-6.2.1.tgz", + "integrity": "sha512-NWufjGI2WUyrg46mKuySfviEJ6IxHUOm/8a3Ph38VCWSp+83HBraCQrpEM3F3dB6LBs5x8OElS8h3C0oOJaJAA==", + "requires": { + "@svgr/plugin-jsx": "^6.2.1", + "camelcase": "^6.2.0", + "cosmiconfig": "^7.0.1" + } + }, + "@svgr/hast-util-to-babel-ast": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-6.2.1.tgz", + "integrity": "sha512-pt7MMkQFDlWJVy9ULJ1h+hZBDGFfSCwlBNW1HkLnVi7jUhyEXUaGYWi1x6bM2IXuAR9l265khBT4Av4lPmaNLQ==", + "requires": { + "@babel/types": "^7.15.6", + "entities": "^3.0.1" + } + }, + "@svgr/plugin-jsx": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/@svgr/plugin-jsx/-/plugin-jsx-6.2.1.tgz", + "integrity": "sha512-u+MpjTsLaKo6r3pHeeSVsh9hmGRag2L7VzApWIaS8imNguqoUwDq/u6U/NDmYs/KAsrmtBjOEaAAPbwNGXXp1g==", + "requires": { + "@babel/core": "^7.15.5", + "@svgr/babel-preset": "^6.2.0", + "@svgr/hast-util-to-babel-ast": "^6.2.1", + "svg-parser": "^2.0.2" + } + }, + "@svgr/plugin-svgo": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/@svgr/plugin-svgo/-/plugin-svgo-6.2.0.tgz", + "integrity": "sha512-oDdMQONKOJEbuKwuy4Np6VdV6qoaLLvoY86hjvQEgU82Vx1MSWRyYms6Sl0f+NtqxLI/rDVufATbP/ev996k3Q==", + "requires": { + "cosmiconfig": "^7.0.1", + "deepmerge": "^4.2.2", + "svgo": "^2.5.0" + } + }, + "@svgr/webpack": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/@svgr/webpack/-/webpack-6.2.1.tgz", + "integrity": "sha512-h09ngMNd13hnePwgXa+Y5CgOjzlCvfWLHg+MBnydEedAnuLRzUHUJmGS3o2OsrhxTOOqEsPOFt5v/f6C5Qulcw==", + "requires": { + "@babel/core": "^7.15.5", + "@babel/plugin-transform-react-constant-elements": "^7.14.5", + "@babel/preset-env": "^7.15.6", + "@babel/preset-react": "^7.14.5", + "@babel/preset-typescript": "^7.15.0", + "@svgr/core": "^6.2.1", + "@svgr/plugin-jsx": "^6.2.1", + "@svgr/plugin-svgo": "^6.2.0" + } + }, + "css-loader": { + "version": "6.7.1", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.7.1.tgz", + "integrity": "sha512-yB5CNFa14MbPJcomwNh3wLThtkZgcNyI2bNMRt8iE5Z8Vwl7f8vQXFAzn2HDOJvtDq2NTZBUGMSUNNyrv3/+cw==", + "requires": { + "icss-utils": "^5.1.0", + "postcss": "^8.4.7", + "postcss-modules-extract-imports": "^3.0.0", + "postcss-modules-local-by-default": "^4.0.0", + "postcss-modules-scope": "^3.0.0", + "postcss-modules-values": "^4.0.0", + "postcss-value-parser": "^4.2.0", + "semver": "^7.3.5" + } + }, + "css-tree": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz", + "integrity": "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==", + "requires": { + "mdn-data": "2.0.14", + "source-map": "^0.6.1" + } + }, + "entities": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-3.0.1.tgz", + "integrity": "sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q==" + }, + "icss-utils": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", + "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", + "requires": {} + }, + "mdn-data": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz", + "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==" + }, + "postcss-modules-extract-imports": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz", + "integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==", + "requires": {} + }, + "postcss-modules-local-by-default": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.0.tgz", + "integrity": "sha512-sT7ihtmGSF9yhm6ggikHdV0hlziDTX7oFoXtuVWeDd3hHObNkcHRo9V3yg7vCAY7cONyxJC/XXCmmiHHcvX7bQ==", + "requires": { + "icss-utils": "^5.0.0", + "postcss-selector-parser": "^6.0.2", + "postcss-value-parser": "^4.1.0" + } + }, + "postcss-modules-scope": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.0.0.tgz", + "integrity": "sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg==", + "requires": { + "postcss-selector-parser": "^6.0.4" + } + }, + "postcss-modules-values": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", + "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", + "requires": { + "icss-utils": "^5.0.0" + } + }, + "svgo": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-2.8.0.tgz", + "integrity": "sha512-+N/Q9kV1+F+UeWYoSiULYo4xYSDQlTgb+ayMobAXPwMnLvop7oxKMo9OzIrX5x3eS4L4f2UHhc9axXwY8DpChg==", + "requires": { + "@trysound/sax": "0.2.0", + "commander": "^7.2.0", + "css-select": "^4.1.3", + "css-tree": "^1.1.3", + "csso": "^4.2.0", + "picocolors": "^1.0.0", + "stable": "^0.1.8" + }, + "dependencies": { + "commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==" + } + } + } + } + }, + "@docusaurus/cssnano-preset": { + "version": "2.0.0-beta.17", + "resolved": "https://registry.npmjs.org/@docusaurus/cssnano-preset/-/cssnano-preset-2.0.0-beta.17.tgz", + "integrity": "sha512-DoBwtLjJ9IY9/lNMHIEdo90L4NDayvU28nLgtjR2Sc6aBIMEB/3a5Ndjehnp+jZAkwcDdNASA86EkZVUyz1O1A==", + "requires": { + "cssnano-preset-advanced": "^5.1.12", + "postcss": "^8.4.7", + "postcss-sort-media-queries": "^4.2.1" + } + }, + "@docusaurus/logger": { + "version": "2.0.0-beta.17", + "resolved": "https://registry.npmjs.org/@docusaurus/logger/-/logger-2.0.0-beta.17.tgz", + "integrity": "sha512-F9JDl06/VLg+ylsvnq9NpILSUeWtl0j4H2LtlLzX5gufEL4dGiCMlnUzYdHl7FSHSzYJ0A/R7vu0SYofsexC4w==", + "requires": { + "chalk": "^4.1.2", + "tslib": "^2.3.1" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "@docusaurus/lqip-loader": { + "version": "2.0.0-beta.17", + "resolved": "https://registry.npmjs.org/@docusaurus/lqip-loader/-/lqip-loader-2.0.0-beta.17.tgz", + "integrity": "sha512-pqwVuSYOthQgVVUmc8lI36hHzewKbBZBjLgxl3Khd2xL1gShZcb8o0Zx0IXSvqskZaq3E3TXRuzBAjyvIRaKdw==", + "requires": { + "@docusaurus/logger": "2.0.0-beta.17", + "file-loader": "^6.2.0", + "lodash": "^4.17.21", + "node-vibrant": "^3.1.6", + "sharp": "^0.30.1", + "tslib": "^2.3.1" + } + }, + "@docusaurus/mdx-loader": { + "version": "2.0.0-beta.17", + "resolved": "https://registry.npmjs.org/@docusaurus/mdx-loader/-/mdx-loader-2.0.0-beta.17.tgz", + "integrity": "sha512-AhJ3GWRmjQYCyINHE595pff5tn3Rt83oGpdev5UT9uvG9lPYPC8nEmh1LI6c0ogfw7YkNznzxWSW4hyyVbYQ3A==", + "requires": { + "@babel/parser": "^7.17.3", + "@babel/traverse": "^7.17.3", + "@docusaurus/logger": "2.0.0-beta.17", + "@docusaurus/utils": "2.0.0-beta.17", + "@mdx-js/mdx": "^1.6.22", + "escape-html": "^1.0.3", + "file-loader": "^6.2.0", + "fs-extra": "^10.0.1", + "image-size": "^1.0.1", + "mdast-util-to-string": "^2.0.0", + "remark-emoji": "^2.1.0", + "stringify-object": "^3.3.0", + "tslib": "^2.3.1", + "unist-util-visit": "^2.0.2", + "url-loader": "^4.1.1", + "webpack": "^5.69.1" + } + }, + "@docusaurus/module-type-aliases": { + "version": "2.0.0-beta.17", + "resolved": "https://registry.npmjs.org/@docusaurus/module-type-aliases/-/module-type-aliases-2.0.0-beta.17.tgz", + "integrity": "sha512-Tu+8geC/wyygBudbSwvWIHEvt5RwyA7dEoE1JmPbgQtmqUxOZ9bgnfemwXpJW5mKuDiJASbN4of1DhbLqf4sPg==", + "requires": { + "@docusaurus/types": "2.0.0-beta.17", + "@types/react": "*", + "@types/react-router-config": "*", + "@types/react-router-dom": "*", + "react-helmet-async": "*" + } + }, + "@docusaurus/plugin-content-blog": { + "version": "2.0.0-beta.17", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-blog/-/plugin-content-blog-2.0.0-beta.17.tgz", + "integrity": "sha512-gcX4UR+WKT4bhF8FICBQHy+ESS9iRMeaglSboTZbA/YHGax/3EuZtcPU3dU4E/HFJeZ866wgUdbLKpIpsZOidg==", + "requires": { + "@docusaurus/core": "2.0.0-beta.17", + "@docusaurus/logger": "2.0.0-beta.17", + "@docusaurus/mdx-loader": "2.0.0-beta.17", + "@docusaurus/utils": "2.0.0-beta.17", + "@docusaurus/utils-common": "2.0.0-beta.17", + "@docusaurus/utils-validation": "2.0.0-beta.17", + "cheerio": "^1.0.0-rc.10", + "feed": "^4.2.2", + "fs-extra": "^10.0.1", + "lodash": "^4.17.21", + "reading-time": "^1.5.0", + "remark-admonitions": "^1.2.1", + "tslib": "^2.3.1", + "utility-types": "^3.10.0", + "webpack": "^5.69.1" + } + }, + "@docusaurus/plugin-content-docs": { + "version": "2.0.0-beta.17", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-docs/-/plugin-content-docs-2.0.0-beta.17.tgz", + "integrity": "sha512-YYrBpuRfTfE6NtENrpSHTJ7K7PZifn6j6hcuvdC0QKE+WD8pS+O2/Ws30yoyvHwLnAnfhvaderh1v9Kaa0/ANg==", + "requires": { + "@docusaurus/core": "2.0.0-beta.17", + "@docusaurus/logger": "2.0.0-beta.17", + "@docusaurus/mdx-loader": "2.0.0-beta.17", + "@docusaurus/utils": "2.0.0-beta.17", + "@docusaurus/utils-validation": "2.0.0-beta.17", + "combine-promises": "^1.1.0", + "fs-extra": "^10.0.1", + "import-fresh": "^3.3.0", + "js-yaml": "^4.1.0", + "lodash": "^4.17.21", + "remark-admonitions": "^1.2.1", + "tslib": "^2.3.1", + "utility-types": "^3.10.0", + "webpack": "^5.69.1" + } + }, + "@docusaurus/plugin-content-pages": { + "version": "2.0.0-beta.17", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-pages/-/plugin-content-pages-2.0.0-beta.17.tgz", + "integrity": "sha512-d5x0mXTMJ44ojRQccmLyshYoamFOep2AnBe69osCDnwWMbD3Or3pnc2KMK9N7mVpQFnNFKbHNCLrX3Rv0uwEHA==", + "requires": { + "@docusaurus/core": "2.0.0-beta.17", + "@docusaurus/mdx-loader": "2.0.0-beta.17", + "@docusaurus/utils": "2.0.0-beta.17", + "@docusaurus/utils-validation": "2.0.0-beta.17", + "fs-extra": "^10.0.1", + "remark-admonitions": "^1.2.1", + "tslib": "^2.3.1", + "webpack": "^5.69.1" + } + }, + "@docusaurus/plugin-debug": { + "version": "2.0.0-beta.17", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-debug/-/plugin-debug-2.0.0-beta.17.tgz", + "integrity": "sha512-p26fjYFRSC0esEmKo/kRrLVwXoFnzPCFDumwrImhPyqfVxbj+IKFaiXkayb2qHnyEGE/1KSDIgRF4CHt/pyhiw==", + "requires": { + "@docusaurus/core": "2.0.0-beta.17", + "@docusaurus/utils": "2.0.0-beta.17", + "fs-extra": "^10.0.1", + "react-json-view": "^1.21.3", + "tslib": "^2.3.1" + } + }, + "@docusaurus/plugin-google-analytics": { + "version": "2.0.0-beta.17", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-analytics/-/plugin-google-analytics-2.0.0-beta.17.tgz", + "integrity": "sha512-jvgYIhggYD1W2jymqQVAAyjPJUV1xMCn70bAzaCMxriureMWzhQ/kQMVQpop0ijTMvifOxaV9yTcL1VRXev++A==", + "requires": { + "@docusaurus/core": "2.0.0-beta.17", + "@docusaurus/utils-validation": "2.0.0-beta.17", + "tslib": "^2.3.1" + } + }, + "@docusaurus/plugin-google-gtag": { + "version": "2.0.0-beta.17", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-gtag/-/plugin-google-gtag-2.0.0-beta.17.tgz", + "integrity": "sha512-1pnWHtIk1Jfeqwvr8PlcPE5SODWT1gW4TI+ptmJbJ296FjjyvL/pG0AcGEJmYLY/OQc3oz0VQ0W2ognw9jmFIw==", + "requires": { + "@docusaurus/core": "2.0.0-beta.17", + "@docusaurus/utils-validation": "2.0.0-beta.17", + "tslib": "^2.3.1" + } + }, + "@docusaurus/plugin-ideal-image": { + "version": "2.0.0-beta.17", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-ideal-image/-/plugin-ideal-image-2.0.0-beta.17.tgz", + "integrity": "sha512-9ZUi3cVnQsOCW4NSDyQRbH4UmlLqclKjQNQv+O/BKwO5EkjLeB4Q2TeHaXkivntrY4nARGjRcGBHKb3L9zzJXA==", + "requires": { + "@docusaurus/core": "2.0.0-beta.17", + "@docusaurus/lqip-loader": "2.0.0-beta.17", + "@docusaurus/responsive-loader": "^1.7.0", + "@docusaurus/theme-translations": "2.0.0-beta.17", + "@docusaurus/utils-validation": "2.0.0-beta.17", + "@endiliey/react-ideal-image": "^0.0.11", + "react-waypoint": "^10.1.0", + "sharp": "^0.30.1", + "tslib": "^2.3.1", + "webpack": "^5.69.1" + } + }, + "@docusaurus/plugin-sitemap": { + "version": "2.0.0-beta.17", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-sitemap/-/plugin-sitemap-2.0.0-beta.17.tgz", + "integrity": "sha512-19/PaGCsap6cjUPZPGs87yV9e1hAIyd0CTSeVV6Caega8nmOKk20FTrQGFJjZPeX8jvD9QIXcdg6BJnPxcKkaQ==", + "requires": { + "@docusaurus/core": "2.0.0-beta.17", + "@docusaurus/utils": "2.0.0-beta.17", + "@docusaurus/utils-common": "2.0.0-beta.17", + "@docusaurus/utils-validation": "2.0.0-beta.17", + "fs-extra": "^10.0.1", + "sitemap": "^7.1.1", + "tslib": "^2.3.1" + } + }, + "@docusaurus/preset-classic": { + "version": "2.0.0-beta.17", + "resolved": "https://registry.npmjs.org/@docusaurus/preset-classic/-/preset-classic-2.0.0-beta.17.tgz", + "integrity": "sha512-7YUxPEgM09aZWr25/hpDEp1gPl+1KsCPV1ZTRW43sbQ9TinPm+9AKR3rHVDa8ea8MdiS7BpqCVyK+H/eiyQrUw==", + "requires": { + "@docusaurus/core": "2.0.0-beta.17", + "@docusaurus/plugin-content-blog": "2.0.0-beta.17", + "@docusaurus/plugin-content-docs": "2.0.0-beta.17", + "@docusaurus/plugin-content-pages": "2.0.0-beta.17", + "@docusaurus/plugin-debug": "2.0.0-beta.17", + "@docusaurus/plugin-google-analytics": "2.0.0-beta.17", + "@docusaurus/plugin-google-gtag": "2.0.0-beta.17", + "@docusaurus/plugin-sitemap": "2.0.0-beta.17", + "@docusaurus/theme-classic": "2.0.0-beta.17", + "@docusaurus/theme-common": "2.0.0-beta.17", + "@docusaurus/theme-search-algolia": "2.0.0-beta.17" + } + }, + "@docusaurus/react-loadable": { + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/@docusaurus/react-loadable/-/react-loadable-5.5.2.tgz", + "integrity": "sha512-A3dYjdBGuy0IGT+wyLIGIKLRE+sAk1iNk0f1HjNDysO7u8lhL4N3VEm+FAubmJbAztn94F7MxBTPmnixbiyFdQ==", + "requires": { + "@types/react": "*", + "prop-types": "^15.6.2" + } + }, + "@docusaurus/responsive-loader": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@docusaurus/responsive-loader/-/responsive-loader-1.7.0.tgz", + "integrity": "sha512-N0cWuVqTRXRvkBxeMQcy/OF2l7GN8rmni5EzR3HpwR+iU2ckYPnziceojcxvvxQ5NqZg1QfEW0tycQgHp+e+Nw==", + "requires": { + "loader-utils": "^2.0.0" + } + }, + "@docusaurus/theme-classic": { + "version": "2.0.0-beta.17", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-classic/-/theme-classic-2.0.0-beta.17.tgz", + "integrity": "sha512-xfZ9kpgqo0lP9YO4rJj79wtiQJXU6ARo5wYy10IIwiWN+lg00scJHhkmNV431b05xIUjUr0cKeH9nqZmEsQRKg==", + "requires": { + "@docusaurus/core": "2.0.0-beta.17", + "@docusaurus/plugin-content-blog": "2.0.0-beta.17", + "@docusaurus/plugin-content-docs": "2.0.0-beta.17", + "@docusaurus/plugin-content-pages": "2.0.0-beta.17", + "@docusaurus/theme-common": "2.0.0-beta.17", + "@docusaurus/theme-translations": "2.0.0-beta.17", + "@docusaurus/utils": "2.0.0-beta.17", + "@docusaurus/utils-common": "2.0.0-beta.17", + "@docusaurus/utils-validation": "2.0.0-beta.17", + "@mdx-js/react": "^1.6.22", + "clsx": "^1.1.1", + "copy-text-to-clipboard": "^3.0.1", + "infima": "0.2.0-alpha.37", + "lodash": "^4.17.21", + "postcss": "^8.4.7", + "prism-react-renderer": "^1.2.1", + "prismjs": "^1.27.0", + "react-router-dom": "^5.2.0", + "rtlcss": "^3.3.0" + } + }, + "@docusaurus/theme-common": { + "version": "2.0.0-beta.17", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-common/-/theme-common-2.0.0-beta.17.tgz", + "integrity": "sha512-LJBDhx+Qexn1JHBqZbE4k+7lBaV1LgpE33enXf43ShB7ebhC91d5HLHhBwgt0pih4+elZU4rG+BG/roAmsNM0g==", + "requires": { + "@docusaurus/module-type-aliases": "2.0.0-beta.17", + "@docusaurus/plugin-content-blog": "2.0.0-beta.17", + "@docusaurus/plugin-content-docs": "2.0.0-beta.17", + "@docusaurus/plugin-content-pages": "2.0.0-beta.17", + "clsx": "^1.1.1", + "parse-numeric-range": "^1.3.0", + "prism-react-renderer": "^1.3.1", + "tslib": "^2.3.1", + "utility-types": "^3.10.0" + } + }, + "@docusaurus/theme-search-algolia": { + "version": "2.0.0-beta.17", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-search-algolia/-/theme-search-algolia-2.0.0-beta.17.tgz", + "integrity": "sha512-W12XKM7QC5Jmrec359bJ7aDp5U8DNkCxjVKsMNIs8rDunBoI/N+R35ERJ0N7Bg9ONAWO6o7VkUERQsfGqdvr9w==", + "requires": { + "@docsearch/react": "^3.0.0", + "@docusaurus/core": "2.0.0-beta.17", + "@docusaurus/logger": "2.0.0-beta.17", + "@docusaurus/theme-common": "2.0.0-beta.17", + "@docusaurus/theme-translations": "2.0.0-beta.17", + "@docusaurus/utils": "2.0.0-beta.17", + "@docusaurus/utils-validation": "2.0.0-beta.17", + "algoliasearch": "^4.12.1", + "algoliasearch-helper": "^3.7.0", + "clsx": "^1.1.1", + "eta": "^1.12.3", + "fs-extra": "^10.0.1", + "lodash": "^4.17.21", + "tslib": "^2.3.1", + "utility-types": "^3.10.0" + } + }, + "@docusaurus/theme-translations": { + "version": "2.0.0-beta.17", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-translations/-/theme-translations-2.0.0-beta.17.tgz", + "integrity": "sha512-oxCX6khjZH3lgdRCL0DH06KkUM/kDr9+lzB35+vY8rpFeQruVgRdi8ekPqG3+Wr0U/N+LMhcYE5BmCb6D0Fv2A==", + "requires": { + "fs-extra": "^10.0.1", + "tslib": "^2.3.1" + } + }, + "@docusaurus/types": { + "version": "2.0.0-beta.17", + "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-2.0.0-beta.17.tgz", + "integrity": "sha512-4o7TXu5sKlQpybfFFtsGUElBXwSpiXKsQyyWaRKj7DRBkvMtkDX6ITZNnZO9+EHfLbP/cfrokB8C/oO7mCQ5BQ==", + "requires": { + "commander": "^5.1.0", + "joi": "^17.6.0", + "querystring": "0.2.1", + "utility-types": "^3.10.0", + "webpack": "^5.69.1", + "webpack-merge": "^5.8.0" + } + }, + "@docusaurus/utils": { + "version": "2.0.0-beta.17", + "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-2.0.0-beta.17.tgz", + "integrity": "sha512-yRKGdzSc5v6M/6GyQ4omkrAHCleevwKYiIrufCJgRbOtkhYE574d8mIjjirOuA/emcyLxjh+TLtqAA5TwhIryA==", + "requires": { + "@docusaurus/logger": "2.0.0-beta.17", + "@svgr/webpack": "^6.0.0", + "file-loader": "^6.2.0", + "fs-extra": "^10.0.1", + "github-slugger": "^1.4.0", + "globby": "^11.0.4", + "gray-matter": "^4.0.3", + "js-yaml": "^4.1.0", + "lodash": "^4.17.21", + "micromatch": "^4.0.4", + "resolve-pathname": "^3.0.0", + "shelljs": "^0.8.5", + "tslib": "^2.3.1", + "url-loader": "^4.1.1", + "webpack": "^5.69.1" + }, + "dependencies": { + "@svgr/babel-plugin-add-jsx-attribute": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-6.0.0.tgz", + "integrity": "sha512-MdPdhdWLtQsjd29Wa4pABdhWbaRMACdM1h31BY+c6FghTZqNGT7pEYdBoaGeKtdTOBC/XNFQaKVj+r/Ei2ryWA==", + "requires": {} + }, + "@svgr/babel-plugin-remove-jsx-attribute": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-6.0.0.tgz", + "integrity": "sha512-aVdtfx9jlaaxc3unA6l+M9YRnKIZjOhQPthLKqmTXC8UVkBLDRGwPKo+r8n3VZN8B34+yVajzPTZ+ptTSuZZCw==", + "requires": {} + }, + "@svgr/babel-plugin-remove-jsx-empty-expression": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-6.0.0.tgz", + "integrity": "sha512-Ccj42ApsePD451AZJJf1QzTD1B/BOU392URJTeXFxSK709i0KUsGtbwyiqsKu7vsYxpTM0IA5clAKDyf9RCZyA==", + "requires": {} + }, + "@svgr/babel-plugin-replace-jsx-attribute-value": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-6.0.0.tgz", + "integrity": "sha512-88V26WGyt1Sfd1emBYmBJRWMmgarrExpKNVmI9vVozha4kqs6FzQJ/Kp5+EYli1apgX44518/0+t9+NU36lThQ==", + "requires": {} + }, + "@svgr/babel-plugin-svg-dynamic-title": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-6.0.0.tgz", + "integrity": "sha512-F7YXNLfGze+xv0KMQxrl2vkNbI9kzT9oDK55/kUuymh1ACyXkMV+VZWX1zEhSTfEKh7VkHVZGmVtHg8eTZ6PRg==", + "requires": {} + }, + "@svgr/babel-plugin-svg-em-dimensions": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-6.0.0.tgz", + "integrity": "sha512-+rghFXxdIqJNLQK08kwPBD3Z22/0b2tEZ9lKiL/yTfuyj1wW8HUXu4bo/XkogATIYuXSghVQOOCwURXzHGKyZA==", + "requires": {} + }, + "@svgr/babel-plugin-transform-react-native-svg": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-6.0.0.tgz", + "integrity": "sha512-VaphyHZ+xIKv5v0K0HCzyfAaLhPGJXSk2HkpYfXIOKb7DjLBv0soHDxNv6X0vr2titsxE7klb++u7iOf7TSrFQ==", + "requires": {} + }, + "@svgr/babel-plugin-transform-svg-component": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-6.2.0.tgz", + "integrity": "sha512-bhYIpsORb++wpsp91fymbFkf09Z/YEKR0DnFjxvN+8JHeCUD2unnh18jIMKnDJTWtvpTaGYPXELVe4OOzFI0xg==", + "requires": {} + }, + "@svgr/babel-preset": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-preset/-/babel-preset-6.2.0.tgz", + "integrity": "sha512-4WQNY0J71JIaL03DRn0vLiz87JXx0b9dYm2aA8XHlQJQoixMl4r/soYHm8dsaJZ3jWtkCiOYy48dp9izvXhDkQ==", + "requires": { + "@svgr/babel-plugin-add-jsx-attribute": "^6.0.0", + "@svgr/babel-plugin-remove-jsx-attribute": "^6.0.0", + "@svgr/babel-plugin-remove-jsx-empty-expression": "^6.0.0", + "@svgr/babel-plugin-replace-jsx-attribute-value": "^6.0.0", + "@svgr/babel-plugin-svg-dynamic-title": "^6.0.0", + "@svgr/babel-plugin-svg-em-dimensions": "^6.0.0", + "@svgr/babel-plugin-transform-react-native-svg": "^6.0.0", + "@svgr/babel-plugin-transform-svg-component": "^6.2.0" + } + }, + "@svgr/core": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/@svgr/core/-/core-6.2.1.tgz", + "integrity": "sha512-NWufjGI2WUyrg46mKuySfviEJ6IxHUOm/8a3Ph38VCWSp+83HBraCQrpEM3F3dB6LBs5x8OElS8h3C0oOJaJAA==", + "requires": { + "@svgr/plugin-jsx": "^6.2.1", + "camelcase": "^6.2.0", + "cosmiconfig": "^7.0.1" + } + }, + "@svgr/hast-util-to-babel-ast": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-6.2.1.tgz", + "integrity": "sha512-pt7MMkQFDlWJVy9ULJ1h+hZBDGFfSCwlBNW1HkLnVi7jUhyEXUaGYWi1x6bM2IXuAR9l265khBT4Av4lPmaNLQ==", + "requires": { + "@babel/types": "^7.15.6", + "entities": "^3.0.1" + } + }, + "@svgr/plugin-jsx": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/@svgr/plugin-jsx/-/plugin-jsx-6.2.1.tgz", + "integrity": "sha512-u+MpjTsLaKo6r3pHeeSVsh9hmGRag2L7VzApWIaS8imNguqoUwDq/u6U/NDmYs/KAsrmtBjOEaAAPbwNGXXp1g==", + "requires": { + "@babel/core": "^7.15.5", + "@svgr/babel-preset": "^6.2.0", + "@svgr/hast-util-to-babel-ast": "^6.2.1", + "svg-parser": "^2.0.2" + } + }, + "@svgr/plugin-svgo": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/@svgr/plugin-svgo/-/plugin-svgo-6.2.0.tgz", + "integrity": "sha512-oDdMQONKOJEbuKwuy4Np6VdV6qoaLLvoY86hjvQEgU82Vx1MSWRyYms6Sl0f+NtqxLI/rDVufATbP/ev996k3Q==", + "requires": { + "cosmiconfig": "^7.0.1", + "deepmerge": "^4.2.2", + "svgo": "^2.5.0" + } + }, + "@svgr/webpack": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/@svgr/webpack/-/webpack-6.2.1.tgz", + "integrity": "sha512-h09ngMNd13hnePwgXa+Y5CgOjzlCvfWLHg+MBnydEedAnuLRzUHUJmGS3o2OsrhxTOOqEsPOFt5v/f6C5Qulcw==", + "requires": { + "@babel/core": "^7.15.5", + "@babel/plugin-transform-react-constant-elements": "^7.14.5", + "@babel/preset-env": "^7.15.6", + "@babel/preset-react": "^7.14.5", + "@babel/preset-typescript": "^7.15.0", + "@svgr/core": "^6.2.1", + "@svgr/plugin-jsx": "^6.2.1", + "@svgr/plugin-svgo": "^6.2.0" + } + }, + "commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==" + }, + "css-tree": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz", + "integrity": "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==", + "requires": { + "mdn-data": "2.0.14", + "source-map": "^0.6.1" + } + }, + "entities": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-3.0.1.tgz", + "integrity": "sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q==" + }, + "mdn-data": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz", + "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==" + }, + "svgo": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-2.8.0.tgz", + "integrity": "sha512-+N/Q9kV1+F+UeWYoSiULYo4xYSDQlTgb+ayMobAXPwMnLvop7oxKMo9OzIrX5x3eS4L4f2UHhc9axXwY8DpChg==", + "requires": { + "@trysound/sax": "0.2.0", + "commander": "^7.2.0", + "css-select": "^4.1.3", + "css-tree": "^1.1.3", + "csso": "^4.2.0", + "picocolors": "^1.0.0", + "stable": "^0.1.8" + } + } + } + }, + "@docusaurus/utils-common": { + "version": "2.0.0-beta.17", + "resolved": "https://registry.npmjs.org/@docusaurus/utils-common/-/utils-common-2.0.0-beta.17.tgz", + "integrity": "sha512-90WCVdj6zYzs7neEIS594qfLO78cUL6EVK1CsRHJgVkkGjcYlCQ1NwkyO7bOb+nIAwdJrPJRc2FBSpuEGxPD3w==", + "requires": { + "tslib": "^2.3.1" + } + }, + "@docusaurus/utils-validation": { + "version": "2.0.0-beta.17", + "resolved": "https://registry.npmjs.org/@docusaurus/utils-validation/-/utils-validation-2.0.0-beta.17.tgz", + "integrity": "sha512-5UjayUP16fDjgd52eSEhL7SlN9x60pIhyS+K7kt7RmpSLy42+4/bSr2pns2VlATmuaoNOO6iIFdB2jgSYJ6SGA==", + "requires": { + "@docusaurus/logger": "2.0.0-beta.17", + "@docusaurus/utils": "2.0.0-beta.17", + "joi": "^17.6.0", + "tslib": "^2.3.1" + } + }, + "@emotion/is-prop-valid": { + "version": "0.8.8", + "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-0.8.8.tgz", + "integrity": "sha512-u5WtneEAr5IDG2Wv65yhunPSMLIpuKsbuOktRojfrEiEvRyC85LgPMZI63cr7NUqT8ZIGdSVg8ZKGxIug4lXcA==", + "requires": { + "@emotion/memoize": "0.7.4" + } + }, + "@emotion/memoize": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.7.4.tgz", + "integrity": "sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw==" + }, + "@emotion/stylis": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/@emotion/stylis/-/stylis-0.8.5.tgz", + "integrity": "sha512-h6KtPihKFn3T9fuIrwvXXUOwlx3rfUvfZIcP5a6rh8Y7zjE3O06hT5Ss4S/YI1AYhuZ1kjaE/5EaOOI2NqSylQ==" + }, + "@emotion/unitless": { + "version": "0.7.5", + "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.7.5.tgz", + "integrity": "sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg==" + }, + "@endiliey/react-ideal-image": { + "version": "0.0.11", + "resolved": "https://registry.npmjs.org/@endiliey/react-ideal-image/-/react-ideal-image-0.0.11.tgz", + "integrity": "sha512-QxMjt/Gvur/gLxSoCy7VIyGGGrGmDN+VHcXkN3R2ApoWX0EYUE+hMgPHSW/PV6VVebZ1Nd4t2UnGRBDihu16JQ==", + "requires": {} + }, + "@exodus/schemasafe": { + "version": "1.0.0-rc.6", + "resolved": "https://registry.npmjs.org/@exodus/schemasafe/-/schemasafe-1.0.0-rc.6.tgz", + "integrity": "sha512-dDnQizD94EdBwEj/fh3zPRa/HWCS9O5au2PuHhZBbuM3xWHxuaKzPBOEWze7Nn0xW68MIpZ7Xdyn1CoCpjKCuQ==" + }, + "@hapi/hoek": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz", + "integrity": "sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==" + }, + "@hapi/topo": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-5.1.0.tgz", + "integrity": "sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==", + "requires": { + "@hapi/hoek": "^9.0.0" + } + }, + "@istanbuljs/load-nyc-config": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", + "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", + "dev": true, + "requires": { + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "get-package-type": "^0.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" + }, + "dependencies": { + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true + }, + "js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true + } + } + }, + "@istanbuljs/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "dev": true + }, + "@jest/console": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-27.5.1.tgz", + "integrity": "sha512-kZ/tNpS3NXn0mlXXXPNuDZnb4c0oZ20r4K5eemM2k30ZC3G0T02nXUvyhf5YdbXWHPEJLc9qGLxEZ216MdL+Zg==", + "dev": true, + "requires": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "jest-message-util": "^27.5.1", + "jest-util": "^27.5.1", + "slash": "^3.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "@jest/core": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-27.5.1.tgz", + "integrity": "sha512-AK6/UTrvQD0Cd24NSqmIA6rKsu0tKIxfiCducZvqxYdmMisOYAsdItspT+fQDQYARPf8XgjAFZi0ogW2agH5nQ==", + "dev": true, + "requires": { + "@jest/console": "^27.5.1", + "@jest/reporters": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "emittery": "^0.8.1", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-changed-files": "^27.5.1", + "jest-config": "^27.5.1", + "jest-haste-map": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-regex-util": "^27.5.1", + "jest-resolve": "^27.5.1", + "jest-resolve-dependencies": "^27.5.1", + "jest-runner": "^27.5.1", + "jest-runtime": "^27.5.1", + "jest-snapshot": "^27.5.1", + "jest-util": "^27.5.1", + "jest-validate": "^27.5.1", + "jest-watcher": "^27.5.1", + "micromatch": "^4.0.4", + "rimraf": "^3.0.0", + "slash": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "@jest/create-cache-key-function": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/create-cache-key-function/-/create-cache-key-function-27.5.1.tgz", + "integrity": "sha512-dmH1yW+makpTSURTy8VzdUwFnfQh1G8R+DxO2Ho2FFmBbKFEVm+3jWdvFhE2VqB/LATCTokkP0dotjyQyw5/AQ==", + "dev": true, + "requires": { + "@jest/types": "^27.5.1" + } + }, + "@jest/environment": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-27.5.1.tgz", + "integrity": "sha512-/WQjhPJe3/ghaol/4Bq480JKXV/Rfw8nQdN7f41fM8VDHLcxKXou6QyXAh3EFr9/bVG3x74z1NWDkP87EiY8gA==", + "dev": true, + "requires": { + "@jest/fake-timers": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "jest-mock": "^27.5.1" + } + }, + "@jest/fake-timers": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-27.5.1.tgz", + "integrity": "sha512-/aPowoolwa07k7/oM3aASneNeBGCmGQsc3ugN4u6s4C/+s5M64MFo/+djTdiwcbQlRfFElGuDXWzaWj6QgKObQ==", + "dev": true, + "requires": { + "@jest/types": "^27.5.1", + "@sinonjs/fake-timers": "^8.0.1", + "@types/node": "*", + "jest-message-util": "^27.5.1", + "jest-mock": "^27.5.1", + "jest-util": "^27.5.1" + } + }, + "@jest/globals": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-27.5.1.tgz", + "integrity": "sha512-ZEJNB41OBQQgGzgyInAv0UUfDDj3upmHydjieSxFvTRuZElrx7tXg/uVQ5hYVEwiXs3+aMsAeEc9X7xiSKCm4Q==", + "dev": true, + "requires": { + "@jest/environment": "^27.5.1", + "@jest/types": "^27.5.1", + "expect": "^27.5.1" + } + }, + "@jest/reporters": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-27.5.1.tgz", + "integrity": "sha512-cPXh9hWIlVJMQkVk84aIvXuBB4uQQmFqZiacloFuGiP3ah1sbCxCosidXFDfqG8+6fO1oR2dTJTlsOy4VFmUfw==", + "dev": true, + "requires": { + "@bcoe/v8-coverage": "^0.2.3", + "@jest/console": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "collect-v8-coverage": "^1.0.0", + "exit": "^0.1.2", + "glob": "^7.1.2", + "graceful-fs": "^4.2.9", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-instrument": "^5.1.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.0", + "istanbul-reports": "^3.1.3", + "jest-haste-map": "^27.5.1", + "jest-resolve": "^27.5.1", + "jest-util": "^27.5.1", + "jest-worker": "^27.5.1", + "slash": "^3.0.0", + "source-map": "^0.6.0", + "string-length": "^4.0.1", + "terminal-link": "^2.0.0", + "v8-to-istanbul": "^8.1.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "@jest/source-map": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-27.5.1.tgz", + "integrity": "sha512-y9NIHUYF3PJRlHk98NdC/N1gl88BL08aQQgu4k4ZopQkCw9t9cV8mtl3TV8b/YCB8XaVTFrmUTAJvjsntDireg==", + "dev": true, + "requires": { + "callsites": "^3.0.0", + "graceful-fs": "^4.2.9", + "source-map": "^0.6.0" + } + }, + "@jest/test-result": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-27.5.1.tgz", + "integrity": "sha512-EW35l2RYFUcUQxFJz5Cv5MTOxlJIQs4I7gxzi2zVU7PJhOwfYq1MdC5nhSmYjX1gmMmLPvB3sIaC+BkcHRBfag==", + "dev": true, + "requires": { + "@jest/console": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" + } + }, + "@jest/test-sequencer": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-27.5.1.tgz", + "integrity": "sha512-LCheJF7WB2+9JuCS7VB/EmGIdQuhtqjRNI9A43idHv3E4KltCTsPsLxvdaubFHSYwY/fNjMWjl6vNRhDiN7vpQ==", + "dev": true, + "requires": { + "@jest/test-result": "^27.5.1", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^27.5.1", + "jest-runtime": "^27.5.1" + } + }, + "@jest/transform": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-27.5.1.tgz", + "integrity": "sha512-ipON6WtYgl/1329g5AIJVbUuEh0wZVbdpGwC99Jw4LwuoBNS95MVphU6zOeD9pDkon+LLbFL7lOQRapbB8SCHw==", + "dev": true, + "requires": { + "@babel/core": "^7.1.0", + "@jest/types": "^27.5.1", + "babel-plugin-istanbul": "^6.1.1", + "chalk": "^4.0.0", + "convert-source-map": "^1.4.0", + "fast-json-stable-stringify": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^27.5.1", + "jest-regex-util": "^27.5.1", + "jest-util": "^27.5.1", + "micromatch": "^4.0.4", + "pirates": "^4.0.4", + "slash": "^3.0.0", + "source-map": "^0.6.1", + "write-file-atomic": "^3.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "@jimp/bmp": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/@jimp/bmp/-/bmp-0.16.1.tgz", + "integrity": "sha512-iwyNYQeBawrdg/f24x3pQ5rEx+/GwjZcCXd3Kgc+ZUd+Ivia7sIqBsOnDaMZdKCBPlfW364ekexnlOqyVa0NWg==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.1", + "bmp-js": "^0.1.0" + } + }, + "@jimp/core": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/@jimp/core/-/core-0.16.1.tgz", + "integrity": "sha512-la7kQia31V6kQ4q1kI/uLimu8FXx7imWVajDGtwUG8fzePLWDFJyZl0fdIXVCL1JW2nBcRHidUot6jvlRDi2+g==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.1", + "any-base": "^1.1.0", + "buffer": "^5.2.0", + "exif-parser": "^0.1.12", + "file-type": "^9.0.0", + "load-bmfont": "^1.3.1", + "mkdirp": "^0.5.1", + "phin": "^2.9.1", + "pixelmatch": "^4.0.2", + "tinycolor2": "^1.4.1" + }, + "dependencies": { + "buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "requires": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + } + } + }, + "@jimp/custom": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/@jimp/custom/-/custom-0.16.1.tgz", + "integrity": "sha512-DNUAHNSiUI/j9hmbatD6WN/EBIyeq4AO0frl5ETtt51VN1SvE4t4v83ZA/V6ikxEf3hxLju4tQ5Pc3zmZkN/3A==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/core": "^0.16.1" + } + }, + "@jimp/gif": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/@jimp/gif/-/gif-0.16.1.tgz", + "integrity": "sha512-r/1+GzIW1D5zrP4tNrfW+3y4vqD935WBXSc8X/wm23QTY9aJO9Lw6PEdzpYCEY+SOklIFKaJYUAq/Nvgm/9ryw==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.1", + "gifwrap": "^0.9.2", + "omggif": "^1.0.9" + } + }, + "@jimp/jpeg": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/@jimp/jpeg/-/jpeg-0.16.1.tgz", + "integrity": "sha512-8352zrdlCCLFdZ/J+JjBslDvml+fS3Z8gttdml0We759PnnZGqrnPRhkOEOJbNUlE+dD4ckLeIe6NPxlS/7U+w==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.1", + "jpeg-js": "0.4.2" + } + }, + "@jimp/plugin-resize": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/@jimp/plugin-resize/-/plugin-resize-0.16.1.tgz", + "integrity": "sha512-u4JBLdRI7dargC04p2Ha24kofQBk3vhaf0q8FwSYgnCRwxfvh2RxvhJZk9H7Q91JZp6wgjz/SjvEAYjGCEgAwQ==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.1" + } + }, + "@jimp/png": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/@jimp/png/-/png-0.16.1.tgz", + "integrity": "sha512-iyWoCxEBTW0OUWWn6SveD4LePW89kO7ZOy5sCfYeDM/oTPLpR8iMIGvZpZUz1b8kvzFr27vPst4E5rJhGjwsdw==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.1", + "pngjs": "^3.3.3" + } + }, + "@jimp/tiff": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/@jimp/tiff/-/tiff-0.16.1.tgz", + "integrity": "sha512-3K3+xpJS79RmSkAvFMgqY5dhSB+/sxhwTFA9f4AVHUK0oKW+u6r52Z1L0tMXHnpbAdR9EJ+xaAl2D4x19XShkQ==", + "requires": { + "@babel/runtime": "^7.7.2", + "utif": "^2.0.1" + } + }, + "@jimp/types": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/@jimp/types/-/types-0.16.1.tgz", + "integrity": "sha512-g1w/+NfWqiVW4CaXSJyD28JQqZtm2eyKMWPhBBDCJN9nLCN12/Az0WFF3JUAktzdsEC2KRN2AqB1a2oMZBNgSQ==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/bmp": "^0.16.1", + "@jimp/gif": "^0.16.1", + "@jimp/jpeg": "^0.16.1", + "@jimp/png": "^0.16.1", + "@jimp/tiff": "^0.16.1", + "timm": "^1.6.1" + } + }, + "@jimp/utils": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/@jimp/utils/-/utils-0.16.1.tgz", + "integrity": "sha512-8fULQjB0x4LzUSiSYG6ZtQl355sZjxbv8r9PPAuYHzS9sGiSHJQavNqK/nKnpDsVkU88/vRGcE7t3nMU0dEnVw==", + "requires": { + "@babel/runtime": "^7.7.2", + "regenerator-runtime": "^0.13.3" + } + }, + "@jridgewell/gen-mapping": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz", + "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==", + "requires": { + "@jridgewell/set-array": "^1.0.0", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "@jridgewell/resolve-uri": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.0.6.tgz", + "integrity": "sha512-R7xHtBSNm+9SyvpJkdQl+qrM3Hm2fea3Ef197M3mUug+v+yR+Rhfbs7PBtcBUVnIWJ4JcAdjvij+c8hXS9p5aw==" + }, + "@jridgewell/set-array": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.0.tgz", + "integrity": "sha512-SfJxIxNVYLTsKwzB3MoOQ1yxf4w/E6MdkvTgrgAt1bfxjSrLUoHMKrDOykwN14q65waezZIdqDneUIPh4/sKxg==" + }, + "@jridgewell/sourcemap-codec": { + "version": "1.4.11", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.11.tgz", + "integrity": "sha512-Fg32GrJo61m+VqYSdRSjRXMjQ06j8YIYfcTqndLYVAaHmroZHLJZCydsWBOTDqXS2v+mjxohBWEMfg97GXmYQg==" + }, + "@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "requires": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "@leichtgewicht/ip-codec": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.3.tgz", + "integrity": "sha512-nkalE/f1RvRGChwBnEIoBfSEYOXnCRdleKuv6+lePbMDrMZXeDQnqak5XDOeBgrPPyPfAdcCu/B5z+v3VhplGg==" + }, + "@mdx-js/mdx": { + "version": "1.6.22", + "resolved": "https://registry.npmjs.org/@mdx-js/mdx/-/mdx-1.6.22.tgz", + "integrity": "sha512-AMxuLxPz2j5/6TpF/XSdKpQP1NlG0z11dFOlq+2IP/lSgl11GY8ji6S/rgsViN/L0BDvHvUMruRb7ub+24LUYA==", + "requires": { + "@babel/core": "7.12.9", + "@babel/plugin-syntax-jsx": "7.12.1", + "@babel/plugin-syntax-object-rest-spread": "7.8.3", + "@mdx-js/util": "1.6.22", + "babel-plugin-apply-mdx-type-prop": "1.6.22", + "babel-plugin-extract-import-names": "1.6.22", + "camelcase-css": "2.0.1", + "detab": "2.0.4", + "hast-util-raw": "6.0.1", + "lodash.uniq": "4.5.0", + "mdast-util-to-hast": "10.0.1", + "remark-footnotes": "2.0.0", + "remark-mdx": "1.6.22", + "remark-parse": "8.0.3", + "remark-squeeze-paragraphs": "4.0.0", + "style-to-object": "0.3.0", + "unified": "9.2.0", + "unist-builder": "2.0.3", + "unist-util-visit": "2.0.3" + }, + "dependencies": { + "@babel/core": { + "version": "7.12.9", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.12.9.tgz", + "integrity": "sha512-gTXYh3M5wb7FRXQy+FErKFAv90BnlOuNn1QkCK2lREoPAjrQCO49+HVSrFoe5uakFAF5eenS75KbO2vQiLrTMQ==", + "requires": { + "@babel/code-frame": "^7.10.4", + "@babel/generator": "^7.12.5", + "@babel/helper-module-transforms": "^7.12.1", + "@babel/helpers": "^7.12.5", + "@babel/parser": "^7.12.7", + "@babel/template": "^7.12.7", + "@babel/traverse": "^7.12.9", + "@babel/types": "^7.12.7", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.1", + "json5": "^2.1.2", + "lodash": "^4.17.19", + "resolve": "^1.3.2", + "semver": "^5.4.1", + "source-map": "^0.5.0" + } + }, + "@babel/plugin-syntax-jsx": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.12.1.tgz", + "integrity": "sha512-1yRi7yAtB0ETgxdY9ti/p2TivUxJkTdhu/ZbF9MshVGqOx1TdB3b7xCXs49Fupgg50N45KcAsRP/ZqWjs9SRjg==", + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + } + } + }, + "@mdx-js/react": { + "version": "1.6.22", + "resolved": "https://registry.npmjs.org/@mdx-js/react/-/react-1.6.22.tgz", + "integrity": "sha512-TDoPum4SHdfPiGSAaRBw7ECyI8VaHpK8GJugbJIJuqyh6kzw9ZLJZW3HGL3NNrJGxcAixUvqROm+YuQOo5eXtg==", + "requires": {} + }, + "@mdx-js/util": { + "version": "1.6.22", + "resolved": "https://registry.npmjs.org/@mdx-js/util/-/util-1.6.22.tgz", + "integrity": "sha512-H1rQc1ZOHANWBvPcW+JpGwr+juXSxM8Q8YCkm3GhZd8REu1fHR3z99CErO1p9pkcfcxZnMdIZdIsXkOHY0NilA==" + }, + "@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "requires": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + } + }, + "@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==" + }, + "@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "requires": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + } + }, + "@polka/url": { + "version": "1.0.0-next.21", + "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.21.tgz", + "integrity": "sha512-a5Sab1C4/icpTZVzZc5Ghpz88yQtGOyNqYXcZgOssB2uuAr+wF/MvN6bgtW32q7HHrvBki+BsZ0OuNv6EV3K9g==" + }, + "@redocly/ajv": { + "version": "8.6.4", + "resolved": "https://registry.npmjs.org/@redocly/ajv/-/ajv-8.6.4.tgz", + "integrity": "sha512-y9qNj0//tZtWB2jfXNK3BX18BSBp9zNR7KE7lMysVHwbZtY392OJCjm6Rb/h4UHH2r1AqjNEHFD6bRn+DqU9Mw==", + "requires": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + } + }, + "@redocly/openapi-core": { + "version": "1.0.0-beta.94", + "resolved": "https://registry.npmjs.org/@redocly/openapi-core/-/openapi-core-1.0.0-beta.94.tgz", + "integrity": "sha512-xTklcobv+51bQVkUOpUiNY0GztL+0u3yGsy2BtldaHpcnNGMu3lu/utsoOHkiNTpgVEGyEWVZzBtF6Sz5v/Fkg==", + "requires": { + "@redocly/ajv": "^8.6.4", + "@types/node": "^14.11.8", + "colorette": "^1.2.0", + "js-levenshtein": "^1.1.6", + "js-yaml": "^4.1.0", + "lodash.isequal": "^4.5.0", + "minimatch": "^3.0.4", + "node-fetch": "^2.6.1", + "pluralize": "^8.0.0", + "yaml-ast-parser": "0.0.43" + }, + "dependencies": { + "@types/node": { + "version": "14.18.16", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.16.tgz", + "integrity": "sha512-X3bUMdK/VmvrWdoTkz+VCn6nwKwrKCFTHtqwBIaQJNx4RUIBBUFXM00bqPz/DsDd+Icjmzm6/tyYZzeGVqb6/Q==" + } + } + }, + "@redocly/react-dropdown-aria": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/@redocly/react-dropdown-aria/-/react-dropdown-aria-2.0.12.tgz", + "integrity": "sha512-feQEZlyBvQsbT/fvpJ4jJ5OLGaUPpnskHYDsY8DGpPymN+HUeDQrqkBEbbKRwMKidFTI2cxk2kJNNTnvdS9jyw==", + "requires": {} + }, + "@sideway/address": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.4.tgz", + "integrity": "sha512-7vwq+rOHVWjyXxVlR76Agnvhy8I9rpzjosTESvmhNeXOXdZZB15Fl+TI9x1SiHZH5Jv2wTGduSxFDIaq0m3DUw==", + "requires": { + "@hapi/hoek": "^9.0.0" + } + }, + "@sideway/formula": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.0.tgz", + "integrity": "sha512-vHe7wZ4NOXVfkoRb8T5otiENVlT7a3IAiw7H5M2+GO+9CDgcVUUsX1zalAztCmwyOr2RUTGJdgB+ZvSVqmdHmg==" + }, + "@sideway/pinpoint": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@sideway/pinpoint/-/pinpoint-2.0.0.tgz", + "integrity": "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==" + }, + "@sindresorhus/is": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", + "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==" + }, + "@sinonjs/commons": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.3.tgz", + "integrity": "sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ==", + "dev": true, + "requires": { + "type-detect": "4.0.8" + } + }, + "@sinonjs/fake-timers": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-8.1.0.tgz", + "integrity": "sha512-OAPJUAtgeINhh/TAlUID4QTs53Njm7xzddaVlEs/SXwgtiD1tW22zAB/W1wdqfrpmikgaWQ9Fw6Ws+hsiRm5Vg==", + "dev": true, + "requires": { + "@sinonjs/commons": "^1.7.0" + } + }, + "@slorber/static-site-generator-webpack-plugin": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@slorber/static-site-generator-webpack-plugin/-/static-site-generator-webpack-plugin-4.0.4.tgz", + "integrity": "sha512-FvMavoWEIePps6/JwGCOLYKCRhuwIHhMtmbKpBFgzNkxwpa/569LfTkrbRk1m1I3n+ezJK4on9E1A6cjuZmD9g==", + "requires": { + "bluebird": "^3.7.1", + "cheerio": "^0.22.0", + "eval": "^0.1.8", + "webpack-sources": "^1.4.3" + }, + "dependencies": { + "cheerio": { + "version": "0.22.0", + "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-0.22.0.tgz", + "integrity": "sha512-8/MzidM6G/TgRelkzDG13y3Y9LxBjCb+8yOEZ9+wwq5gVF2w2pV0wmHvjfT0RvuxGyR7UEuK36r+yYMbT4uKgA==", + "requires": { + "css-select": "~1.2.0", + "dom-serializer": "~0.1.0", + "entities": "~1.1.1", + "htmlparser2": "^3.9.1", + "lodash.assignin": "^4.0.9", + "lodash.bind": "^4.1.4", + "lodash.defaults": "^4.0.1", + "lodash.filter": "^4.4.0", + "lodash.flatten": "^4.2.0", + "lodash.foreach": "^4.3.0", + "lodash.map": "^4.4.0", + "lodash.merge": "^4.4.0", + "lodash.pick": "^4.2.1", + "lodash.reduce": "^4.4.0", + "lodash.reject": "^4.4.0", + "lodash.some": "^4.4.0" + } + }, + "css-select": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz", + "integrity": "sha512-dUQOBoqdR7QwV90WysXPLXG5LO7nhYBgiWVfxF80DKPF8zx1t/pUd2FYy73emg3zrjtM6dzmYgbHKfV2rxiHQA==", + "requires": { + "boolbase": "~1.0.0", + "css-what": "2.1", + "domutils": "1.5.1", + "nth-check": "~1.0.1" + } + }, + "css-what": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.3.tgz", + "integrity": "sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg==" + }, + "dom-serializer": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.1.tgz", + "integrity": "sha512-l0IU0pPzLWSHBcieZbpOKgkIn3ts3vAh7ZuFyXNwJxJXk/c4Gwj9xaTJwIDVQCXawWD0qb3IzMGH5rglQaO0XA==", + "requires": { + "domelementtype": "^1.3.0", + "entities": "^1.1.1" + } + }, + "domelementtype": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", + "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==" + }, + "domhandler": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz", + "integrity": "sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==", + "requires": { + "domelementtype": "1" + } + }, + "domutils": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz", + "integrity": "sha512-gSu5Oi/I+3wDENBsOWBiRK1eoGxcywYSqg3rR960/+EfY0CF4EX1VPkgHOZ3WiS/Jg2DtliF6BhWcHlfpYUcGw==", + "requires": { + "dom-serializer": "0", + "domelementtype": "1" + } + }, + "entities": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", + "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==" + }, + "htmlparser2": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.1.tgz", + "integrity": "sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ==", + "requires": { + "domelementtype": "^1.3.1", + "domhandler": "^2.3.0", + "domutils": "^1.5.1", + "entities": "^1.1.1", + "inherits": "^2.0.1", + "readable-stream": "^3.1.1" + } + }, + "nth-check": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz", + "integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==", + "requires": { + "boolbase": "~1.0.0" + } + } + } + }, + "@svgr/babel-plugin-add-jsx-attribute": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-5.4.0.tgz", + "integrity": "sha512-ZFf2gs/8/6B8PnSofI0inYXr2SDNTDScPXhN7k5EqD4aZ3gi6u+rbmZHVB8IM3wDyx8ntKACZbtXSm7oZGRqVg==" + }, + "@svgr/babel-plugin-remove-jsx-attribute": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-5.4.0.tgz", + "integrity": "sha512-yaS4o2PgUtwLFGTKbsiAy6D0o3ugcUhWK0Z45umJ66EPWunAz9fuFw2gJuje6wqQvQWOTJvIahUwndOXb7QCPg==" + }, + "@svgr/babel-plugin-remove-jsx-empty-expression": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-5.0.1.tgz", + "integrity": "sha512-LA72+88A11ND/yFIMzyuLRSMJ+tRKeYKeQ+mR3DcAZ5I4h5CPWN9AHyUzJbWSYp/u2u0xhmgOe0+E41+GjEueA==" + }, + "@svgr/babel-plugin-replace-jsx-attribute-value": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-5.0.1.tgz", + "integrity": "sha512-PoiE6ZD2Eiy5mK+fjHqwGOS+IXX0wq/YDtNyIgOrc6ejFnxN4b13pRpiIPbtPwHEc+NT2KCjteAcq33/F1Y9KQ==" + }, + "@svgr/babel-plugin-svg-dynamic-title": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-5.4.0.tgz", + "integrity": "sha512-zSOZH8PdZOpuG1ZVx/cLVePB2ibo3WPpqo7gFIjLV9a0QsuQAzJiwwqmuEdTaW2pegyBE17Uu15mOgOcgabQZg==" + }, + "@svgr/babel-plugin-svg-em-dimensions": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-5.4.0.tgz", + "integrity": "sha512-cPzDbDA5oT/sPXDCUYoVXEmm3VIoAWAPT6mSPTJNbQaBNUuEKVKyGH93oDY4e42PYHRW67N5alJx/eEol20abw==" + }, + "@svgr/babel-plugin-transform-react-native-svg": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-5.4.0.tgz", + "integrity": "sha512-3eYP/SaopZ41GHwXma7Rmxcv9uRslRDTY1estspeB1w1ueZWd/tPlMfEOoccYpEMZU3jD4OU7YitnXcF5hLW2Q==" + }, + "@svgr/babel-plugin-transform-svg-component": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-5.5.0.tgz", + "integrity": "sha512-q4jSH1UUvbrsOtlo/tKcgSeiCHRSBdXoIoqX1pgcKK/aU3JD27wmMKwGtpB8qRYUYoyXvfGxUVKchLuR5pB3rQ==" + }, + "@svgr/babel-preset": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-preset/-/babel-preset-5.5.0.tgz", + "integrity": "sha512-4FiXBjvQ+z2j7yASeGPEi8VD/5rrGQk4Xrq3EdJmoZgz/tpqChpo5hgXDvmEauwtvOc52q8ghhZK4Oy7qph4ig==", + "requires": { + "@svgr/babel-plugin-add-jsx-attribute": "^5.4.0", + "@svgr/babel-plugin-remove-jsx-attribute": "^5.4.0", + "@svgr/babel-plugin-remove-jsx-empty-expression": "^5.0.1", + "@svgr/babel-plugin-replace-jsx-attribute-value": "^5.0.1", + "@svgr/babel-plugin-svg-dynamic-title": "^5.4.0", + "@svgr/babel-plugin-svg-em-dimensions": "^5.4.0", + "@svgr/babel-plugin-transform-react-native-svg": "^5.4.0", + "@svgr/babel-plugin-transform-svg-component": "^5.5.0" + } + }, + "@svgr/core": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/@svgr/core/-/core-5.5.0.tgz", + "integrity": "sha512-q52VOcsJPvV3jO1wkPtzTuKlvX7Y3xIcWRpCMtBF3MrteZJtBfQw/+u0B1BHy5ColpQc1/YVTrPEtSYIMNZlrQ==", + "requires": { + "@svgr/plugin-jsx": "^5.5.0", + "camelcase": "^6.2.0", + "cosmiconfig": "^7.0.0" + } + }, + "@svgr/hast-util-to-babel-ast": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-5.5.0.tgz", + "integrity": "sha512-cAaR/CAiZRB8GP32N+1jocovUtvlj0+e65TB50/6Lcime+EA49m/8l+P2ko+XPJ4dw3xaPS3jOL4F2X4KWxoeQ==", + "requires": { + "@babel/types": "^7.12.6" + } + }, + "@svgr/plugin-jsx": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/@svgr/plugin-jsx/-/plugin-jsx-5.5.0.tgz", + "integrity": "sha512-V/wVh33j12hGh05IDg8GpIUXbjAPnTdPTKuP4VNLggnwaHMPNQNae2pRnyTAILWCQdz5GyMqtO488g7CKM8CBA==", + "requires": { + "@babel/core": "^7.12.3", + "@svgr/babel-preset": "^5.5.0", + "@svgr/hast-util-to-babel-ast": "^5.5.0", + "svg-parser": "^2.0.2" + } + }, + "@svgr/plugin-svgo": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/@svgr/plugin-svgo/-/plugin-svgo-5.5.0.tgz", + "integrity": "sha512-r5swKk46GuQl4RrVejVwpeeJaydoxkdwkM1mBKOgJLBUJPGaLci6ylg/IjhrRsREKDkr4kbMWdgOtbXEh0fyLQ==", + "requires": { + "cosmiconfig": "^7.0.0", + "deepmerge": "^4.2.2", + "svgo": "^1.2.2" + } + }, + "@svgr/webpack": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/@svgr/webpack/-/webpack-5.5.0.tgz", + "integrity": "sha512-DOBOK255wfQxguUta2INKkzPj6AIS6iafZYiYmHn6W3pHlycSRRlvWKCfLDG10fXfLWqE3DJHgRUOyJYmARa7g==", + "requires": { + "@babel/core": "^7.12.3", + "@babel/plugin-transform-react-constant-elements": "^7.12.1", + "@babel/preset-env": "^7.12.1", + "@babel/preset-react": "^7.12.5", + "@svgr/core": "^5.5.0", + "@svgr/plugin-jsx": "^5.5.0", + "@svgr/plugin-svgo": "^5.5.0", + "loader-utils": "^2.0.0" + } + }, + "@swc/core": { + "version": "1.2.174", + "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.2.174.tgz", + "integrity": "sha512-PbBwwaqrBCyOae+hZV9QK+QeR1azqb+MGKvuk6SVxsk3Rvh1HSX4CieMnuhcmX+Sm4L58eQv9l37ZLCu2hBZcA==", + "dev": true, + "requires": { + "@swc/core-android-arm-eabi": "1.2.174", + "@swc/core-android-arm64": "1.2.174", + "@swc/core-darwin-arm64": "1.2.174", + "@swc/core-darwin-x64": "1.2.174", + "@swc/core-freebsd-x64": "1.2.174", + "@swc/core-linux-arm-gnueabihf": "1.2.174", + "@swc/core-linux-arm64-gnu": "1.2.174", + "@swc/core-linux-arm64-musl": "1.2.174", + "@swc/core-linux-x64-gnu": "1.2.174", + "@swc/core-linux-x64-musl": "1.2.174", + "@swc/core-win32-arm64-msvc": "1.2.174", + "@swc/core-win32-ia32-msvc": "1.2.174", + "@swc/core-win32-x64-msvc": "1.2.174" + } + }, + "@swc/core-android-arm-eabi": { + "version": "1.2.174", + "resolved": "https://registry.npmjs.org/@swc/core-android-arm-eabi/-/core-android-arm-eabi-1.2.174.tgz", + "integrity": "sha512-sxH6jIq57wnZ8LyLKN8SXM4DhMo4aTq0mClo+zBMPTyHzNO5AEAwh5nqs+d51Dycs3epur/8iv/J6xDv+cKkfw==", + "dev": true, + "optional": true + }, + "@swc/core-android-arm64": { + "version": "1.2.174", + "resolved": "https://registry.npmjs.org/@swc/core-android-arm64/-/core-android-arm64-1.2.174.tgz", + "integrity": "sha512-gGXBuY8Zs93eNduyrhm+rB+K/smF535uwmamHB1+7BrkuUtt/Lrk3vDTc4D61GMA/vBOqus9IXKHBc+EFmBbog==", + "dev": true, + "optional": true + }, + "@swc/core-darwin-arm64": { + "version": "1.2.174", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.2.174.tgz", + "integrity": "sha512-dFxu2o8dR55A+d0Qf/Ai0yKnGjon/UT1hWnBY9tcyvgo7XsiFRB/P83tlbVohqq9N+SDVxdBg9bMAR2i8rDTHg==", + "dev": true, + "optional": true + }, + "@swc/core-darwin-x64": { + "version": "1.2.174", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.2.174.tgz", + "integrity": "sha512-LsANlfBkqfJobPvfojTbUY9xw0ZwTxTicdwaK6BC5TLmYXVfvxvMpmhsvIe3bNlx4jV1z0IrFaJ0YxDSc1s6vw==", + "dev": true, + "optional": true + }, + "@swc/core-freebsd-x64": { + "version": "1.2.174", + "resolved": "https://registry.npmjs.org/@swc/core-freebsd-x64/-/core-freebsd-x64-1.2.174.tgz", + "integrity": "sha512-IG0qc9/qUHmiqC6fqT3yq4iBwNRHN1zYbGpzQm4DU/d7DTwsV7D2A+1McFUKmnUOvBG7zdgg5ee91QxUVOCZTQ==", + "dev": true, + "optional": true + }, + "@swc/core-linux-arm-gnueabihf": { + "version": "1.2.174", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.2.174.tgz", + "integrity": "sha512-nK4U8s9++e5AVEhWz3W6V0tUsPPjYJlMsb4ZzZR2qhYe53YBURCznFIhUDwe0ib/f6T773Tn7sr52uemcQBu8A==", + "dev": true, + "optional": true + }, + "@swc/core-linux-arm64-gnu": { + "version": "1.2.174", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.2.174.tgz", + "integrity": "sha512-Tf6Ths472ul9Z4p8uFP7vMJXLmBS2h4PQL/zDj3g3N+9D8hs6+tnnBNrkEm6jXs09gO4bvaN+706QxmZUEgyPg==", + "dev": true, + "optional": true + }, + "@swc/core-linux-arm64-musl": { + "version": "1.2.174", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.2.174.tgz", + "integrity": "sha512-vsQjxyCe3+qRMQSuDlYwmFxbRILIycRC8OB/tBhTJXYuwIh4zvpxc+zvSuERbd4cmMWwM/JtXIlP5grSNjgH6A==", + "dev": true, + "optional": true + }, + "@swc/core-linux-x64-gnu": { + "version": "1.2.174", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.2.174.tgz", + "integrity": "sha512-CFEL2WMIQ1mZvvDguaVGgwan9X7Ah7ctHG8SOa+mFaWXdAyVXOWp8sdNMJbqvwYAv980CENfYioI8yL0z1heWA==", + "dev": true, + "optional": true + }, + "@swc/core-linux-x64-musl": { + "version": "1.2.174", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.2.174.tgz", + "integrity": "sha512-qulTJ3GYE8gUR0yfIOJVfo8SSl/AgLKAplskIHJu/cP0JtRpHL8B598mfny6SuD+ZabBjUvAz6d8ACL9JdhYTw==", + "dev": true, + "optional": true + }, + "@swc/core-win32-arm64-msvc": { + "version": "1.2.174", + "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.2.174.tgz", + "integrity": "sha512-ZogvH4sOVk3pLguYLlc+3lBlGwJ4WOi375VUqDSb92TirBFPjhX98xDn/Xus1fyRKofSGp1zoAs4w80F6hkX6g==", + "dev": true, + "optional": true + }, + "@swc/core-win32-ia32-msvc": { + "version": "1.2.174", + "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.2.174.tgz", + "integrity": "sha512-QcnXBs2L0O5BiV61orDxJqZsmk2wPUscTTY4upfW5++eCI6IpDYVyfQmtQ9OdVCXWfVEPrhQKuUxLZEjoKxdNQ==", + "dev": true, + "optional": true + }, + "@swc/core-win32-x64-msvc": { + "version": "1.2.174", + "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.2.174.tgz", + "integrity": "sha512-9aFcbPTFA5jtiTQbOsq+/QN29F/YNpOrhcwsUa2Haqq0+2h71rMiBn7oluUERFQ+/se9J0C00iSC0QXif4pfuQ==", + "dev": true, + "optional": true + }, + "@swc/jest": { + "version": "0.2.20", + "resolved": "https://registry.npmjs.org/@swc/jest/-/jest-0.2.20.tgz", + "integrity": "sha512-5qSUBYY1wyIMn7p0Vl9qqV4hMI69oJwZCIPUpBsTFWN2wlwn6RDugzdgCn+bLXVYh+Cxi8bJcZ1uumDgsoL+FA==", + "dev": true, + "requires": { + "@jest/create-cache-key-function": "^27.4.2" + } + }, + "@szmarczak/http-timer": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz", + "integrity": "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==", + "requires": { + "defer-to-connect": "^1.0.1" + } + }, + "@testing-library/dom": { + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-8.13.0.tgz", + "integrity": "sha512-9VHgfIatKNXQNaZTtLnalIy0jNZzY35a4S3oi08YAt9Hv1VsfZ/DfA45lM8D/UhtHBGJ4/lGwp0PZkVndRkoOQ==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.10.4", + "@babel/runtime": "^7.12.5", + "@types/aria-query": "^4.2.0", + "aria-query": "^5.0.0", + "chalk": "^4.1.0", + "dom-accessibility-api": "^0.5.9", + "lz-string": "^1.4.4", + "pretty-format": "^27.0.2" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "@testing-library/jest-dom": { + "version": "5.16.4", + "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-5.16.4.tgz", + "integrity": "sha512-Gy+IoFutbMQcky0k+bqqumXZ1cTGswLsFqmNLzNdSKkU9KGV2u9oXhukCbbJ9/LRPKiqwxEE8VpV/+YZlfkPUA==", + "dev": true, + "requires": { + "@babel/runtime": "^7.9.2", + "@types/testing-library__jest-dom": "^5.9.1", + "aria-query": "^5.0.0", + "chalk": "^3.0.0", + "css": "^3.0.0", + "css.escape": "^1.5.1", + "dom-accessibility-api": "^0.5.6", + "lodash": "^4.17.15", + "redent": "^3.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "@testing-library/react": { + "version": "12.1.5", + "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-12.1.5.tgz", + "integrity": "sha512-OfTXCJUFgjd/digLUuPxa0+/3ZxsQmE7ub9kcbW/wi96Bh3o/p5vrETcBGfP17NWPGqeYYl5LTRpwyGoMC4ysg==", + "dev": true, + "requires": { + "@babel/runtime": "^7.12.5", + "@testing-library/dom": "^8.0.0", + "@types/react-dom": "<18.0.0" + } + }, + "@testing-library/user-event": { + "version": "13.5.0", + "resolved": "https://registry.npmjs.org/@testing-library/user-event/-/user-event-13.5.0.tgz", + "integrity": "sha512-5Kwtbo3Y/NowpkbRuSepbyMFkZmHgD+vPzYB/RJ4oxt5Gj/avFFBYjhw27cqSVPVw/3a67NK1PbiIr9k4Gwmdg==", + "dev": true, + "requires": { + "@babel/runtime": "^7.12.5" + } + }, + "@tootallnate/once": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", + "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", + "dev": true + }, + "@trysound/sax": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", + "integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==" + }, + "@types/aria-query": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-4.2.2.tgz", + "integrity": "sha512-HnYpAE1Y6kRyKM/XkEuiRQhTHvkzMBurTHnpFLYLBGPIylZNPs9jJcuOOYWxPLJCSEtmZT0Y8rHDokKN7rRTig==", + "dev": true + }, + "@types/babel__core": { + "version": "7.1.19", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.19.tgz", + "integrity": "sha512-WEOTgRsbYkvA/KCsDwVEGkd7WAr1e3g31VHQ8zy5gul/V1qKullU/BU5I68X5v7V3GnB9eotmom4v5a5gjxorw==", + "dev": true, + "requires": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "@types/babel__generator": { + "version": "7.6.4", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.4.tgz", + "integrity": "sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@types/babel__template": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.1.tgz", + "integrity": "sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g==", + "dev": true, + "requires": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "@types/babel__traverse": { + "version": "7.17.1", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.17.1.tgz", + "integrity": "sha512-kVzjari1s2YVi77D3w1yuvohV2idweYXMCDzqBiVNN63TcDWrIlTVOYpqVrvbbyOE/IyzBoTKF0fdnLPEORFxA==", + "dev": true, + "requires": { + "@babel/types": "^7.3.0" + } + }, + "@types/body-parser": { + "version": "1.19.2", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz", + "integrity": "sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==", + "requires": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "@types/bonjour": { + "version": "3.5.10", + "resolved": "https://registry.npmjs.org/@types/bonjour/-/bonjour-3.5.10.tgz", + "integrity": "sha512-p7ienRMiS41Nu2/igbJxxLDWrSZ0WxM8UQgCeO9KhoVF7cOVFkrKsiDr1EsJIla8vV3oEEjGcz11jc5yimhzZw==", + "requires": { + "@types/node": "*" + } + }, + "@types/connect": { + "version": "3.4.35", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", + "integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==", + "requires": { + "@types/node": "*" + } + }, + "@types/connect-history-api-fallback": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.3.5.tgz", + "integrity": "sha512-h8QJa8xSb1WD4fpKBDcATDNGXghFj6/3GRWG6dhmRcu0RX1Ubasur2Uvx5aeEwlf0MwblEC2bMzzMQntxnw/Cw==", + "requires": { + "@types/express-serve-static-core": "*", + "@types/node": "*" + } + }, + "@types/eslint": { + "version": "8.4.1", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.4.1.tgz", + "integrity": "sha512-GE44+DNEyxxh2Kc6ro/VkIj+9ma0pO0bwv9+uHSyBrikYOHr8zYcdPvnBOp1aw8s+CjRvuSx7CyWqRrNFQ59mA==", + "requires": { + "@types/estree": "*", + "@types/json-schema": "*" + } + }, + "@types/eslint-scope": { + "version": "3.7.3", + "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.3.tgz", + "integrity": "sha512-PB3ldyrcnAicT35TWPs5IcwKD8S333HMaa2VVv4+wdvebJkjWuW/xESoB8IwRcog8HYVYamb1g/R31Qv5Bx03g==", + "requires": { + "@types/eslint": "*", + "@types/estree": "*" + } + }, + "@types/estree": { + "version": "0.0.51", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.51.tgz", + "integrity": "sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ==" + }, + "@types/express": { + "version": "4.17.13", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.13.tgz", + "integrity": "sha512-6bSZTPaTIACxn48l50SR+axgrqm6qXFIxrdAKaG6PaJk3+zuUr35hBlgT7vOmJcum+OEaIBLtHV/qloEAFITeA==", + "requires": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.18", + "@types/qs": "*", + "@types/serve-static": "*" + } + }, + "@types/express-serve-static-core": { + "version": "4.17.28", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.28.tgz", + "integrity": "sha512-P1BJAEAW3E2DJUlkgq4tOL3RyMunoWXqbSCygWo5ZIWTjUgN1YnaXWW4VWl/oc8vs/XoYibEGBKP0uZyF4AHig==", + "requires": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*" + } + }, + "@types/graceful-fs": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.5.tgz", + "integrity": "sha512-anKkLmZZ+xm4p8JWBf4hElkM4XR+EZeA2M9BAkkTldmcyDY4mbdIJnRghDJH3Ov5ooY7/UAoENtmdMSkaAd7Cw==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/hast": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/@types/hast/-/hast-2.3.4.tgz", + "integrity": "sha512-wLEm0QvaoawEDoTRwzTXp4b4jpwiJDvR5KMnFnVodm3scufTlBOWRD6N1OBf9TZMhjlNsSfcO5V+7AF4+Vy+9g==", + "requires": { + "@types/unist": "*" + } + }, + "@types/history": { + "version": "4.7.11", + "resolved": "https://registry.npmjs.org/@types/history/-/history-4.7.11.tgz", + "integrity": "sha512-qjDJRrmvBMiTx+jyLxvLfJU7UznFuokDv4f3WRuriHKERccVpFU+8XMQUAbDzoiJCsmexxRExQeMwwCdamSKDA==" + }, + "@types/html-minifier-terser": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", + "integrity": "sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg==" + }, + "@types/http-proxy": { + "version": "1.17.8", + "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.8.tgz", + "integrity": "sha512-5kPLG5BKpWYkw/LVOGWpiq3nEVqxiN32rTgI53Sk12/xHFQ2rG3ehI9IO+O3W2QoKeyB92dJkoka8SUm6BX1pA==", + "requires": { + "@types/node": "*" + } + }, + "@types/istanbul-lib-coverage": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", + "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==", + "dev": true + }, + "@types/istanbul-lib-report": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", + "integrity": "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "*" + } + }, + "@types/istanbul-reports": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", + "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", + "dev": true, + "requires": { + "@types/istanbul-lib-report": "*" + } + }, + "@types/jest": { + "version": "27.4.1", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-27.4.1.tgz", + "integrity": "sha512-23iPJADSmicDVrWk+HT58LMJtzLAnB2AgIzplQuq/bSrGaxCrlvRFjGbXmamnnk/mAmCdLStiGqggu28ocUyiw==", + "dev": true, + "requires": { + "jest-matcher-utils": "^27.0.0", + "pretty-format": "^27.0.0" + } + }, + "@types/json-schema": { + "version": "7.0.11", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", + "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==" + }, + "@types/katex": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/@types/katex/-/katex-0.11.1.tgz", + "integrity": "sha512-DUlIj2nk0YnJdlWgsFuVKcX27MLW0KbKmGVoUHmFr+74FYYNUDAaj9ZqTADvsbE8rfxuVmSFc7KczYn5Y09ozg==" + }, + "@types/lodash": { + "version": "4.14.182", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.182.tgz", + "integrity": "sha512-/THyiqyQAP9AfARo4pF+aCGcyiQ94tX/Is2I7HofNRqoYLgN1PBoOWu2/zTA5zMxzP5EFutMtWtGAFRKUe961Q==" + }, + "@types/mdast": { + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.10.tgz", + "integrity": "sha512-W864tg/Osz1+9f4lrGTZpCSO5/z4608eUp19tbozkq2HJK6i3z1kT0H9tlADXuYIb1YYOBByU4Jsqkk75q48qA==", + "requires": { + "@types/unist": "*" + } + }, + "@types/mime": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", + "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==" + }, + "@types/node": { + "version": "17.0.31", + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.31.tgz", + "integrity": "sha512-AR0x5HbXGqkEx9CadRH3EBYx/VkiUgZIhP4wvPn/+5KIsgpNoyFaRlVe0Zlx9gRtg8fA06a9tskE2MSN7TcG4Q==" + }, + "@types/parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==" + }, + "@types/parse5": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/@types/parse5/-/parse5-5.0.3.tgz", + "integrity": "sha512-kUNnecmtkunAoQ3CnjmMkzNU/gtxG8guhi+Fk2U/kOpIKjIMKnXGp4IJCgQJrXSgMsWYimYG4TGjz/UzbGEBTw==" + }, + "@types/prettier": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.6.0.tgz", + "integrity": "sha512-G/AdOadiZhnJp0jXCaBQU449W2h716OW/EoXeYkCytxKL06X1WCXB4DZpp8TpZ8eyIJVS1cw4lrlkkSYU21cDw==", + "dev": true + }, + "@types/prop-types": { + "version": "15.7.5", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz", + "integrity": "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==" + }, + "@types/q": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@types/q/-/q-1.5.5.tgz", + "integrity": "sha512-L28j2FcJfSZOnL1WBjDYp2vUHCeIFlyYI/53EwD/rKUBQ7MtUUfbQWiyKJGpcnv4/WgrhWsFKrcPstcAt/J0tQ==" + }, + "@types/qs": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz", + "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==" + }, + "@types/range-parser": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", + "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==" + }, + "@types/react": { + "version": "17.0.44", + "resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.44.tgz", + "integrity": "sha512-Ye0nlw09GeMp2Suh8qoOv0odfgCoowfM/9MG6WeRD60Gq9wS90bdkdRtYbRkNhXOpG4H+YXGvj4wOWhAC0LJ1g==", + "requires": { + "@types/prop-types": "*", + "@types/scheduler": "*", + "csstype": "^3.0.2" + } + }, + "@types/react-dom": { + "version": "17.0.16", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-17.0.16.tgz", + "integrity": "sha512-DWcXf8EbMrO/gWnQU7Z88Ws/p16qxGpPyjTKTpmBSFKeE+HveVubqGO1CVK7FrwlWD5MuOcvh8gtd0/XO38NdQ==", + "dev": true, + "requires": { + "@types/react": "^17" + } + }, + "@types/react-router": { + "version": "5.1.18", + "resolved": "https://registry.npmjs.org/@types/react-router/-/react-router-5.1.18.tgz", + "integrity": "sha512-YYknwy0D0iOwKQgz9v8nOzt2J6l4gouBmDnWqUUznltOTaon+r8US8ky8HvN0tXvc38U9m6z/t2RsVsnd1zM0g==", + "requires": { + "@types/history": "^4.7.11", + "@types/react": "*" + } + }, + "@types/react-router-config": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/@types/react-router-config/-/react-router-config-5.0.6.tgz", + "integrity": "sha512-db1mx37a1EJDf1XeX8jJN7R3PZABmJQXR8r28yUjVMFSjkmnQo6X6pOEEmNl+Tp2gYQOGPdYbFIipBtdElZ3Yg==", + "requires": { + "@types/history": "^4.7.11", + "@types/react": "*", + "@types/react-router": "*" + } + }, + "@types/react-router-dom": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/@types/react-router-dom/-/react-router-dom-5.3.3.tgz", + "integrity": "sha512-kpqnYK4wcdm5UaWI3fLcELopqLrHgLqNsdpHauzlQktfkHL3npOSwtj1Uz9oKBAzs7lFtVkV8j83voAz2D8fhw==", + "requires": { + "@types/history": "^4.7.11", + "@types/react": "*", + "@types/react-router": "*" + } + }, + "@types/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==" + }, + "@types/sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@types/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-pSAff4IAxJjfAXUG6tFkO7dsSbTmf8CtUpfhhZ5VhkRpC4628tJhh3+V6H1E+/Gs9piSzYKT5yzHO5M4GG9jkw==", + "requires": { + "@types/node": "*" + } + }, + "@types/scheduler": { + "version": "0.16.2", + "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz", + "integrity": "sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==" + }, + "@types/serve-index": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.1.tgz", + "integrity": "sha512-d/Hs3nWDxNL2xAczmOVZNj92YZCS6RGxfBPjKzuu/XirCgXdpKEb88dYNbrYGint6IVWLNP+yonwVAuRC0T2Dg==", + "requires": { + "@types/express": "*" + } + }, + "@types/serve-static": { + "version": "1.13.10", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.10.tgz", + "integrity": "sha512-nCkHGI4w7ZgAdNkrEu0bv+4xNV/XDqW+DydknebMOQwkpDGx8G+HTlj7R7ABI8i8nKxVw0wtKPi1D+lPOkh4YQ==", + "requires": { + "@types/mime": "^1", + "@types/node": "*" + } + }, + "@types/sinonjs__fake-timers": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.1.tgz", + "integrity": "sha512-0kSuKjAS0TrGLJ0M/+8MaFkGsQhZpB6pxOmvS3K8FYI72K//YmdfoW9X2qPsAKh1mkwxGD5zib9s1FIFed6E8g==", + "dev": true + }, + "@types/sizzle": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.3.tgz", + "integrity": "sha512-JYM8x9EGF163bEyhdJBpR2QX1R5naCJHC8ucJylJ3w9/CVBaskdQ8WqBf8MmQrd1kRvp/a4TS8HJ+bxzR7ZJYQ==", + "dev": true + }, + "@types/sockjs": { + "version": "0.3.33", + "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.33.tgz", + "integrity": "sha512-f0KEEe05NvUnat+boPTZ0dgaLZ4SfSouXUgv5noUiefG2ajgKjmETo9ZJyuqsl7dfl2aHlLJUiki6B4ZYldiiw==", + "requires": { + "@types/node": "*" + } + }, + "@types/stack-utils": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", + "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==", + "dev": true + }, + "@types/testing-library__jest-dom": { + "version": "5.14.3", + "resolved": "https://registry.npmjs.org/@types/testing-library__jest-dom/-/testing-library__jest-dom-5.14.3.tgz", + "integrity": "sha512-oKZe+Mf4ioWlMuzVBaXQ9WDnEm1+umLx0InILg+yvZVBBDmzV5KfZyLrCvadtWcx8+916jLmHafcmqqffl+iIw==", + "dev": true, + "requires": { + "@types/jest": "*" + } + }, + "@types/unist": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.6.tgz", + "integrity": "sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ==" + }, + "@types/ws": { + "version": "8.5.3", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.3.tgz", + "integrity": "sha512-6YOoWjruKj1uLf3INHH7D3qTXwFfEsg1kf3c0uDdSBJwfa/llkwIjrAGV7j7mVgGNbzTQ3HiHKKDXl6bJPD97w==", + "requires": { + "@types/node": "*" + } + }, + "@types/yargs": { + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", + "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", + "dev": true, + "requires": { + "@types/yargs-parser": "*" + } + }, + "@types/yargs-parser": { + "version": "21.0.0", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz", + "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==", + "dev": true + }, + "@types/yauzl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.0.tgz", + "integrity": "sha512-Cn6WYCm0tXv8p6k+A8PvbDG763EDpBoTzHdA+Q/MF6H3sapGjCm9NzoaJncJS9tUKSuCoDs9XHxYYsQDgxR6kw==", + "dev": true, + "optional": true, + "requires": { + "@types/node": "*" + } + }, + "@webassemblyjs/ast": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.1.tgz", + "integrity": "sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw==", + "requires": { + "@webassemblyjs/helper-numbers": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1" + } + }, + "@webassemblyjs/floating-point-hex-parser": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz", + "integrity": "sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ==" + }, + "@webassemblyjs/helper-api-error": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz", + "integrity": "sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg==" + }, + "@webassemblyjs/helper-buffer": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz", + "integrity": "sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA==" + }, + "@webassemblyjs/helper-numbers": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz", + "integrity": "sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ==", + "requires": { + "@webassemblyjs/floating-point-hex-parser": "1.11.1", + "@webassemblyjs/helper-api-error": "1.11.1", + "@xtuc/long": "4.2.2" + } + }, + "@webassemblyjs/helper-wasm-bytecode": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz", + "integrity": "sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q==" + }, + "@webassemblyjs/helper-wasm-section": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz", + "integrity": "sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg==", + "requires": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-buffer": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/wasm-gen": "1.11.1" + } + }, + "@webassemblyjs/ieee754": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz", + "integrity": "sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ==", + "requires": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "@webassemblyjs/leb128": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.1.tgz", + "integrity": "sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw==", + "requires": { + "@xtuc/long": "4.2.2" + } + }, + "@webassemblyjs/utf8": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.1.tgz", + "integrity": "sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ==" + }, + "@webassemblyjs/wasm-edit": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz", + "integrity": "sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA==", + "requires": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-buffer": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/helper-wasm-section": "1.11.1", + "@webassemblyjs/wasm-gen": "1.11.1", + "@webassemblyjs/wasm-opt": "1.11.1", + "@webassemblyjs/wasm-parser": "1.11.1", + "@webassemblyjs/wast-printer": "1.11.1" + } + }, + "@webassemblyjs/wasm-gen": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz", + "integrity": "sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA==", + "requires": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/ieee754": "1.11.1", + "@webassemblyjs/leb128": "1.11.1", + "@webassemblyjs/utf8": "1.11.1" + } + }, + "@webassemblyjs/wasm-opt": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz", + "integrity": "sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw==", + "requires": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-buffer": "1.11.1", + "@webassemblyjs/wasm-gen": "1.11.1", + "@webassemblyjs/wasm-parser": "1.11.1" + } + }, + "@webassemblyjs/wasm-parser": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz", + "integrity": "sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA==", + "requires": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-api-error": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/ieee754": "1.11.1", + "@webassemblyjs/leb128": "1.11.1", + "@webassemblyjs/utf8": "1.11.1" + } + }, + "@webassemblyjs/wast-printer": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz", + "integrity": "sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg==", + "requires": { + "@webassemblyjs/ast": "1.11.1", + "@xtuc/long": "4.2.2" + } + }, + "@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==" + }, + "@xtuc/long": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==" + }, + "abab": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz", + "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==", + "dev": true + }, + "accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "requires": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + } + }, + "acorn": { + "version": "8.7.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.1.tgz", + "integrity": "sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A==" + }, + "acorn-globals": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-6.0.0.tgz", + "integrity": "sha512-ZQl7LOWaF5ePqqcX4hLuv/bLXYQNfNWw2c0/yX/TsPRKamzHcTGQnlCjHT3TsmkOUVEPS3crCxiPfdzE/Trlhg==", + "dev": true, + "requires": { + "acorn": "^7.1.1", + "acorn-walk": "^7.1.1" + }, + "dependencies": { + "acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "dev": true + } + } + }, + "acorn-import-assertions": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz", + "integrity": "sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==", + "requires": {} + }, + "acorn-walk": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", + "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==", + "dev": true + }, + "address": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/address/-/address-1.2.0.tgz", + "integrity": "sha512-tNEZYz5G/zYunxFm7sfhAxkXEuLj3K6BKwv6ZURlsF6yiUQ65z0Q2wZW9L5cPUl9ocofGvXOdFYbFHp0+6MOig==" + }, + "agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "requires": { + "debug": "4" + } + }, + "aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "requires": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + } + }, + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "dependencies": { + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + } + } + }, + "ajv-formats": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", + "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", + "requires": { + "ajv": "^8.0.0" + }, + "dependencies": { + "ajv": { + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz", + "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==", + "requires": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + } + } + } + }, + "ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "requires": {} + }, + "algoliasearch": { + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-4.13.0.tgz", + "integrity": "sha512-oHv4faI1Vl2s+YC0YquwkK/TsaJs79g2JFg5FDm2rKN12VItPTAeQ7hyJMHarOPPYuCnNC5kixbtcqvb21wchw==", + "requires": { + "@algolia/cache-browser-local-storage": "4.13.0", + "@algolia/cache-common": "4.13.0", + "@algolia/cache-in-memory": "4.13.0", + "@algolia/client-account": "4.13.0", + "@algolia/client-analytics": "4.13.0", + "@algolia/client-common": "4.13.0", + "@algolia/client-personalization": "4.13.0", + "@algolia/client-search": "4.13.0", + "@algolia/logger-common": "4.13.0", + "@algolia/logger-console": "4.13.0", + "@algolia/requester-browser-xhr": "4.13.0", + "@algolia/requester-common": "4.13.0", + "@algolia/requester-node-http": "4.13.0", + "@algolia/transporter": "4.13.0" + } + }, + "algoliasearch-helper": { + "version": "3.8.2", + "resolved": "https://registry.npmjs.org/algoliasearch-helper/-/algoliasearch-helper-3.8.2.tgz", + "integrity": "sha512-AXxiF0zT9oYwl8ZBgU/eRXvfYhz7cBA5YrLPlw9inZHdaYF0QEya/f1Zp1mPYMXc1v6VkHwBq4pk6/vayBLICg==", + "requires": { + "@algolia/events": "^4.0.1" + } + }, + "ansi-align": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", + "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", + "requires": { + "string-width": "^4.1.0" + }, + "dependencies": { + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + } + } + }, + "ansi-colors": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", + "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", + "dev": true + }, + "ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "requires": { + "type-fest": "^0.21.3" + }, + "dependencies": { + "type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true + } + } + }, + "ansi-html-community": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz", + "integrity": "sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==" + }, + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "^1.9.0" + } + }, + "any-base": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/any-base/-/any-base-1.1.0.tgz", + "integrity": "sha512-uMgjozySS8adZZYePpaWs8cxB9/kdzmpX6SgJZ+wbz1K5eYk5QMYDVJaZKhxyIHUdnnJkfR7SVgStgH7LkGUyg==" + }, + "anymatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", + "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + }, + "arch": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/arch/-/arch-2.2.0.tgz", + "integrity": "sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==", + "dev": true + }, + "are-we-there-yet": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz", + "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==", + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "arg": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.1.tgz", + "integrity": "sha512-e0hDa9H2Z9AwFkk2qDlwhoMYE4eToKarchkQHovNdLTCYMHZHeRjI71crOh+dio4K6u1IcwubQqo79Ga4CyAQA==" + }, + "argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + }, + "aria-query": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.0.0.tgz", + "integrity": "sha512-V+SM7AbUwJ+EBnB8+DXs0hPZHO0W6pqBcc0dW90OwtVG02PswOu/teuARoLQjdDOH+t9pJgGnW5/Qmouf3gPJg==", + "dev": true + }, + "array-flatten": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz", + "integrity": "sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==" + }, + "array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==" + }, + "asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=" + }, + "asn1": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", + "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", + "dev": true, + "requires": { + "safer-buffer": "~2.1.0" + } + }, + "asn1.js": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", + "integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==", + "requires": { + "bn.js": "^4.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0", + "safer-buffer": "^2.1.0" + }, + "dependencies": { + "bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + } + } + }, + "assert": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/assert/-/assert-2.0.0.tgz", + "integrity": "sha512-se5Cd+js9dXJnu6Ag2JFc00t+HmHOen+8Q+L7O9zI0PqQXr20uk2J0XQqMxZEeo5U50o8Nvmmx7dZrl+Ufr35A==", + "requires": { + "es6-object-assign": "^1.1.0", + "is-nan": "^1.2.1", + "object-is": "^1.0.1", + "util": "^0.12.0" + } + }, + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", + "dev": true + }, + "astral-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "dev": true + }, + "async": { + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", + "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", + "requires": { + "lodash": "^4.17.14" + } + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, + "at-least-node": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", + "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==" + }, + "atob": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", + "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", + "dev": true + }, + "autoprefixer": { + "version": "10.4.7", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.7.tgz", + "integrity": "sha512-ypHju4Y2Oav95SipEcCcI5J7CGPuvz8oat7sUtYj3ClK44bldfvtvcxK6IEK++7rqB7YchDGzweZIBG+SD0ZAA==", + "requires": { + "browserslist": "^4.20.3", + "caniuse-lite": "^1.0.30001335", + "fraction.js": "^4.2.0", + "normalize-range": "^0.1.2", + "picocolors": "^1.0.0", + "postcss-value-parser": "^4.2.0" + } + }, + "available-typed-arrays": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", + "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==" + }, + "aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==", + "dev": true + }, + "aws4": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz", + "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==", + "dev": true + }, + "axios": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz", + "integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==", + "requires": { + "follow-redirects": "^1.14.9", + "form-data": "^4.0.0" + }, + "dependencies": { + "form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + } + } + } + }, + "babel-jest": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-27.5.1.tgz", + "integrity": "sha512-cdQ5dXjGRd0IBRATiQ4mZGlGlRE8kJpjPOixdNRdT+m3UcNqmYWN6rK6nvtXYfY3D76cb8s/O1Ss8ea24PIwcg==", + "dev": true, + "requires": { + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/babel__core": "^7.1.14", + "babel-plugin-istanbul": "^6.1.1", + "babel-preset-jest": "^27.5.1", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "slash": "^3.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "babel-loader": { + "version": "8.2.5", + "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.2.5.tgz", + "integrity": "sha512-OSiFfH89LrEMiWd4pLNqGz4CwJDtbs2ZVc+iGu2HrkRfPxId9F2anQj38IxWpmRfsUY0aBZYi1EFcd3mhtRMLQ==", + "requires": { + "find-cache-dir": "^3.3.1", + "loader-utils": "^2.0.0", + "make-dir": "^3.1.0", + "schema-utils": "^2.6.5" + } + }, + "babel-plugin-apply-mdx-type-prop": { + "version": "1.6.22", + "resolved": "https://registry.npmjs.org/babel-plugin-apply-mdx-type-prop/-/babel-plugin-apply-mdx-type-prop-1.6.22.tgz", + "integrity": "sha512-VefL+8o+F/DfK24lPZMtJctrCVOfgbqLAGZSkxwhazQv4VxPg3Za/i40fu22KR2m8eEda+IfSOlPLUSIiLcnCQ==", + "requires": { + "@babel/helper-plugin-utils": "7.10.4", + "@mdx-js/util": "1.6.22" + }, + "dependencies": { + "@babel/helper-plugin-utils": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz", + "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==" + } + } + }, + "babel-plugin-dynamic-import-node": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.0.tgz", + "integrity": "sha512-o6qFkpeQEBxcqt0XYlWzAVxNCSCZdUgcR8IRlhD/8DylxjjO4foPcvTW0GGKa/cVt3rvxZ7o5ippJ+/0nvLhlQ==", + "requires": { + "object.assign": "^4.1.0" + } + }, + "babel-plugin-extract-import-names": { + "version": "1.6.22", + "resolved": "https://registry.npmjs.org/babel-plugin-extract-import-names/-/babel-plugin-extract-import-names-1.6.22.tgz", + "integrity": "sha512-yJ9BsJaISua7d8zNT7oRG1ZLBJCIdZ4PZqmH8qa9N5AK01ifk3fnkc98AXhtzE7UkfCsEumvoQWgoYLhOnJ7jQ==", + "requires": { + "@babel/helper-plugin-utils": "7.10.4" + }, + "dependencies": { + "@babel/helper-plugin-utils": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz", + "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==" + } + } + }, + "babel-plugin-istanbul": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", + "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^5.0.4", + "test-exclude": "^6.0.0" + } + }, + "babel-plugin-jest-hoist": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-27.5.1.tgz", + "integrity": "sha512-50wCwD5EMNW4aRpOwtqzyZHIewTYNxLA4nhB+09d8BIssfNfzBRhkBIHiaPv1Si226TQSvp8gxAJm2iY2qs2hQ==", + "dev": true, + "requires": { + "@babel/template": "^7.3.3", + "@babel/types": "^7.3.3", + "@types/babel__core": "^7.0.0", + "@types/babel__traverse": "^7.0.6" + } + }, + "babel-plugin-polyfill-corejs2": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.1.tgz", + "integrity": "sha512-v7/T6EQcNfVLfcN2X8Lulb7DjprieyLWJK/zOWH5DUYcAgex9sP3h25Q+DLsX9TloXe3y1O8l2q2Jv9q8UVB9w==", + "requires": { + "@babel/compat-data": "^7.13.11", + "@babel/helper-define-polyfill-provider": "^0.3.1", + "semver": "^6.1.1" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" + } + } + }, + "babel-plugin-polyfill-corejs3": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.5.2.tgz", + "integrity": "sha512-G3uJih0XWiID451fpeFaYGVuxHEjzKTHtc9uGFEjR6hHrvNzeS/PX+LLLcetJcytsB5m4j+K3o/EpXJNb/5IEQ==", + "requires": { + "@babel/helper-define-polyfill-provider": "^0.3.1", + "core-js-compat": "^3.21.0" + } + }, + "babel-plugin-polyfill-regenerator": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.3.1.tgz", + "integrity": "sha512-Y2B06tvgHYt1x0yz17jGkGeeMr5FeKUu+ASJ+N6nB5lQ8Dapfg42i0OVrf8PNGJ3zKL4A23snMi1IRwrqqND7A==", + "requires": { + "@babel/helper-define-polyfill-provider": "^0.3.1" + } + }, + "babel-plugin-styled-components": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/babel-plugin-styled-components/-/babel-plugin-styled-components-2.0.7.tgz", + "integrity": "sha512-i7YhvPgVqRKfoQ66toiZ06jPNA3p6ierpfUuEWxNF+fV27Uv5gxBkf8KZLHUCc1nFA9j6+80pYoIpqCeyW3/bA==", + "requires": { + "@babel/helper-annotate-as-pure": "^7.16.0", + "@babel/helper-module-imports": "^7.16.0", + "babel-plugin-syntax-jsx": "^6.18.0", + "lodash": "^4.17.11", + "picomatch": "^2.3.0" + } + }, + "babel-plugin-syntax-jsx": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz", + "integrity": "sha1-CvMqmm4Tyno/1QaeYtew9Y0NiUY=" + }, + "babel-preset-current-node-syntax": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz", + "integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==", + "dev": true, + "requires": { + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-bigint": "^7.8.3", + "@babel/plugin-syntax-class-properties": "^7.8.3", + "@babel/plugin-syntax-import-meta": "^7.8.3", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.8.3", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.8.3", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-top-level-await": "^7.8.3" + } + }, + "babel-preset-jest": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-27.5.1.tgz", + "integrity": "sha512-Nptf2FzlPCWYuJg41HBqXVT8ym6bXOevuCTbhxlUpjwtysGaIWFvDEjp4y+G7fl13FgOdjs7P/DmErqH7da0Ag==", + "dev": true, + "requires": { + "babel-plugin-jest-hoist": "^27.5.1", + "babel-preset-current-node-syntax": "^1.0.0" + } + }, + "bail": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/bail/-/bail-1.0.5.tgz", + "integrity": "sha512-xFbRxM1tahm08yHBP16MMjVUAvDaBMD38zsM9EMAUN61omwLmKlOpB/Zku5QkjZ8TZ4vn53pj+t518cH0S03RQ==" + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "base16": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/base16/-/base16-1.0.0.tgz", + "integrity": "sha1-4pf2DX7BAUp6lxo568ipjAtoHnA=" + }, + "base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" + }, + "batch": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", + "integrity": "sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY=" + }, + "bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", + "dev": true, + "requires": { + "tweetnacl": "^0.14.3" + } + }, + "big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==" + }, + "binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==" + }, + "bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "requires": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + }, + "dependencies": { + "buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "requires": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + } + } + }, + "blob-util": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/blob-util/-/blob-util-2.0.2.tgz", + "integrity": "sha512-T7JQa+zsXXEa6/8ZhHcQEW1UFfVM49Ts65uBkFL6fz2QmrElqmbajIDJvuA0tEhRe5eIjpV9ZF+0RfZR9voJFQ==", + "dev": true + }, + "bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" + }, + "bmp-js": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/bmp-js/-/bmp-js-0.1.0.tgz", + "integrity": "sha1-4Fpj95amwf8l9Hcex62twUjAcjM=" + }, + "bn.js": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.0.tgz", + "integrity": "sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw==" + }, + "body-parser": { + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.0.tgz", + "integrity": "sha512-DfJ+q6EPcGKZD1QWUjSpqp+Q7bDQTsQIF4zfUAtZ6qk+H/3/QRhg9CEp39ss+/T2vw0+HaidC0ecJj/DRLIaKg==", + "requires": { + "bytes": "3.1.2", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.10.3", + "raw-body": "2.5.1", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "dependencies": { + "bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==" + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + } + } + }, + "bonjour-service": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.0.12.tgz", + "integrity": "sha512-pMmguXYCu63Ug37DluMKEHdxc+aaIf/ay4YbF8Gxtba+9d3u+rmEWy61VK3Z3hp8Rskok3BunHYnG0dUHAsblw==", + "requires": { + "array-flatten": "^2.1.2", + "dns-equal": "^1.0.0", + "fast-deep-equal": "^3.1.3", + "multicast-dns": "^7.2.4" + } + }, + "boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=" + }, + "boxen": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-6.2.1.tgz", + "integrity": "sha512-H4PEsJXfFI/Pt8sjDWbHlQPx4zL/bvSQjcilJmaulGt5mLDorHOHpmdXAJcBcmru7PhYSp/cDMWRko4ZUMFkSw==", + "requires": { + "ansi-align": "^3.0.1", + "camelcase": "^6.2.0", + "chalk": "^4.1.2", + "cli-boxes": "^3.0.0", + "string-width": "^5.0.1", + "type-fest": "^2.5.0", + "widest-line": "^4.0.1", + "wrap-ansi": "^8.0.1" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "requires": { + "fill-range": "^7.0.1" + } + }, + "brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=" + }, + "browser-process-hrtime": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz", + "integrity": "sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==", + "dev": true + }, + "browserify-aes": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", + "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", + "requires": { + "buffer-xor": "^1.0.3", + "cipher-base": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.3", + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "browserify-cipher": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", + "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", + "requires": { + "browserify-aes": "^1.0.4", + "browserify-des": "^1.0.0", + "evp_bytestokey": "^1.0.0" + } + }, + "browserify-des": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", + "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", + "requires": { + "cipher-base": "^1.0.1", + "des.js": "^1.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "browserify-rsa": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.1.0.tgz", + "integrity": "sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog==", + "requires": { + "bn.js": "^5.0.0", + "randombytes": "^2.0.1" + } + }, + "browserify-sign": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.1.tgz", + "integrity": "sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg==", + "requires": { + "bn.js": "^5.1.1", + "browserify-rsa": "^4.0.1", + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "elliptic": "^6.5.3", + "inherits": "^2.0.4", + "parse-asn1": "^5.1.5", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" + }, + "dependencies": { + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" + } + } + }, + "browserify-zlib": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", + "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", + "requires": { + "pako": "~1.0.5" + } + }, + "browserslist": { + "version": "4.20.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.20.3.tgz", + "integrity": "sha512-NBhymBQl1zM0Y5dQT/O+xiLP9/rzOIQdKM/eMJBAq7yBgaB6krIYLGejrwVYnSHZdqjscB1SPuAjHwxjvN6Wdg==", + "requires": { + "caniuse-lite": "^1.0.30001332", + "electron-to-chromium": "^1.4.118", + "escalade": "^3.1.1", + "node-releases": "^2.0.3", + "picocolors": "^1.0.0" + } + }, + "bser": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", + "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", + "dev": true, + "requires": { + "node-int64": "^0.4.0" + } + }, + "buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "requires": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", + "dev": true + }, + "buffer-equal": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-0.0.1.tgz", + "integrity": "sha1-kbx0sR6kBbyRa8aqkI+q+ltKrEs=" + }, + "buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" + }, + "buffer-xor": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", + "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=" + }, + "builtin-status-codes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", + "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=" + }, + "bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=" + }, + "cacheable-request": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", + "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==", + "requires": { + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^3.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^4.1.0", + "responselike": "^1.0.2" + }, + "dependencies": { + "get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "requires": { + "pump": "^3.0.0" + } + }, + "lowercase-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==" + }, + "normalize-url": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.1.tgz", + "integrity": "sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==" + } + } + }, + "cachedir": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/cachedir/-/cachedir-2.3.0.tgz", + "integrity": "sha512-A+Fezp4zxnit6FanDmv9EqXNAi3vt9DWp51/71UEhXukb7QUuvtv9344h91dyAxuTLoSYJFU299qzR3tzwPAhw==", + "dev": true + }, + "call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "requires": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + } + }, + "call-me-maybe": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.1.tgz", + "integrity": "sha1-JtII6onje1y95gJQoV8DHBak1ms=" + }, + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==" + }, + "camel-case": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz", + "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==", + "requires": { + "pascal-case": "^3.1.2", + "tslib": "^2.0.3" + } + }, + "camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==" + }, + "camelcase-css": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", + "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==" + }, + "camelize": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/camelize/-/camelize-1.0.0.tgz", + "integrity": "sha1-FkpUg+Yw+kMh5a8HAg5TGDGyYJs=" + }, + "caniuse-api": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz", + "integrity": "sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==", + "requires": { + "browserslist": "^4.0.0", + "caniuse-lite": "^1.0.0", + "lodash.memoize": "^4.1.2", + "lodash.uniq": "^4.5.0" + } + }, + "caniuse-lite": { + "version": "1.0.30001335", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001335.tgz", + "integrity": "sha512-ddP1Tgm7z2iIxu6QTtbZUv6HJxSaV/PZeSrWFZtbY4JZ69tOeNhBCl3HyRQgeNZKE5AOn1kpV7fhljigy0Ty3w==" + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==", + "dev": true + }, + "ccount": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/ccount/-/ccount-1.1.0.tgz", + "integrity": "sha512-vlNK021QdI7PNeiUh/lKkC/mNHHfV0m/Ad5JoI0TYtlBnJAslM/JIkm/tGC88bkLIwO6OQ5uV6ztS6kVAtCDlg==" + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "char-regex": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", + "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", + "dev": true + }, + "character-entities": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-1.2.4.tgz", + "integrity": "sha512-iBMyeEHxfVnIakwOuDXpVkc54HijNgCyQB2w0VfGQThle6NXn50zU6V/u+LDhxHcDUPojn6Kpga3PTAD8W1bQw==" + }, + "character-entities-legacy": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-1.1.4.tgz", + "integrity": "sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA==" + }, + "character-reference-invalid": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-1.1.4.tgz", + "integrity": "sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg==" + }, + "check-more-types": { + "version": "2.24.0", + "resolved": "https://registry.npmjs.org/check-more-types/-/check-more-types-2.24.0.tgz", + "integrity": "sha512-Pj779qHxV2tuapviy1bSZNEL1maXr13bPYpsvSDB68HlYcYuhlDrmGd63i0JHMCLKzc7rUSNIrpdJlhVlNwrxA==", + "dev": true + }, + "cheerio": { + "version": "1.0.0-rc.10", + "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.10.tgz", + "integrity": "sha512-g0J0q/O6mW8z5zxQ3A8E8J1hUgp4SMOvEoW/x84OwyHKe/Zccz83PVT4y5Crcr530FV6NgmKI1qvGTKVl9XXVw==", + "requires": { + "cheerio-select": "^1.5.0", + "dom-serializer": "^1.3.2", + "domhandler": "^4.2.0", + "htmlparser2": "^6.1.0", + "parse5": "^6.0.1", + "parse5-htmlparser2-tree-adapter": "^6.0.1", + "tslib": "^2.2.0" + } + }, + "cheerio-select": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-1.6.0.tgz", + "integrity": "sha512-eq0GdBvxVFbqWgmCm7M3XGs1I8oLy/nExUnh6oLqmBditPO9AqQJrkslDpMun/hZ0yyTs8L0m85OHp4ho6Qm9g==", + "requires": { + "css-select": "^4.3.0", + "css-what": "^6.0.1", + "domelementtype": "^2.2.0", + "domhandler": "^4.3.1", + "domutils": "^2.8.0" + } + }, + "chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "requires": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "fsevents": "~2.3.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + } + }, + "chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + }, + "chrome-trace-event": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", + "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==" + }, + "ci-info": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.3.0.tgz", + "integrity": "sha512-riT/3vI5YpVH6/qomlDnJow6TBee2PBKSEpx3O32EGPYbWGIRsIlGRms3Sm74wYE1JMo8RnO04Hb12+v1J5ICw==", + "dev": true + }, + "cipher-base": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", + "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "cjs-module-lexer": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz", + "integrity": "sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA==", + "dev": true + }, + "classnames": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.1.tgz", + "integrity": "sha512-OlQdbZ7gLfGarSqxesMesDa5uz7KFbID8Kpq/SxIoNGDqY8lSYs0D+hhtBXhcdB3rcbXArFr7vlHheLk1voeNA==" + }, + "clean-css": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.0.tgz", + "integrity": "sha512-YYuuxv4H/iNb1Z/5IbMRoxgrzjWGhOEFfd+groZ5dMCVkpENiMZmwspdrzBo9286JjM1gZJPAyL7ZIdzuvu2AQ==", + "requires": { + "source-map": "~0.6.0" + } + }, + "clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==" + }, + "cli-boxes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-3.0.0.tgz", + "integrity": "sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==" + }, + "cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "dev": true, + "requires": { + "restore-cursor": "^3.1.0" + } + }, + "cli-table3": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.2.tgz", + "integrity": "sha512-QyavHCaIC80cMivimWu4aWHilIpiDpfm3hGmqAmXVL1UsnbLuBSMd21hTX6VY4ZSDSM73ESLeF8TOYId3rBTbw==", + "requires": { + "@colors/colors": "1.5.0", + "string-width": "^4.2.0" + }, + "dependencies": { + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + } + } + }, + "cli-truncate": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-2.1.0.tgz", + "integrity": "sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==", + "dev": true, + "requires": { + "slice-ansi": "^3.0.0", + "string-width": "^4.2.0" + }, + "dependencies": { + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + } + } + }, + "cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + } + } + }, + "clone-deep": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", + "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", + "requires": { + "is-plain-object": "^2.0.4", + "kind-of": "^6.0.2", + "shallow-clone": "^3.0.0" + } + }, + "clone-response": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", + "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=", + "requires": { + "mimic-response": "^1.0.0" + }, + "dependencies": { + "mimic-response": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==" + } + } + }, + "clsx": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.1.1.tgz", + "integrity": "sha512-6/bPho624p3S2pMyvP5kKBPXnI3ufHLObBFCfgx+LkeR5lg2XYy2hqZqUf45ypD8COn2bhgGJSUE+l5dhNBieA==" + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", + "dev": true + }, + "coa": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/coa/-/coa-2.0.2.tgz", + "integrity": "sha512-q5/jG+YQnSy4nRTV4F7lPepBJZ8qBNJJDBuJdoejDyLXgmL7IEo+Le2JDZudFTFt7mrCqIRaSjws4ygRCTCAXA==", + "requires": { + "@types/q": "^1.5.1", + "chalk": "^2.4.1", + "q": "^1.1.2" + } + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" + }, + "collapse-white-space": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/collapse-white-space/-/collapse-white-space-1.0.6.tgz", + "integrity": "sha512-jEovNnrhMuqyCcjfEJA56v0Xq8SkIoPKDyaHahwo3POf4qcSXqMYuwNcOTzp74vTsR9Tn08z4MxWqAhcekogkQ==" + }, + "collect-v8-coverage": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz", + "integrity": "sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg==", + "dev": true + }, + "color": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/color/-/color-3.2.1.tgz", + "integrity": "sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA==", + "requires": { + "color-convert": "^1.9.3", + "color-string": "^1.6.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" + }, + "color-string": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", + "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", + "requires": { + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" + } + }, + "colord": { + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.2.tgz", + "integrity": "sha512-Uqbg+J445nc1TKn4FoDPS6ZZqAvEDnwrH42yo8B40JSOgSLxMZ/gt3h4nmCtPLQeXhjJJkqBx7SCY35WnIixaQ==" + }, + "colorette": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.4.0.tgz", + "integrity": "sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g==" + }, + "combine-promises": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/combine-promises/-/combine-promises-1.1.0.tgz", + "integrity": "sha512-ZI9jvcLDxqwaXEixOhArm3r7ReIivsXkpbyEWyeOhzz1QS0iSgBPnWvEqvIQtYyamGCYA88gFhmUrs9hrrQ0pg==" + }, + "combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "comma-separated-tokens": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-1.0.8.tgz", + "integrity": "sha512-GHuDRO12Sypu2cV70d1dkA2EUmXHgntrzbpvOB+Qy+49ypNfGgFQIC2fhhXbnyrJRynDCAARsT7Ou0M6hirpfw==" + }, + "commander": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz", + "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==" + }, + "common-tags": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.2.tgz", + "integrity": "sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==", + "dev": true + }, + "commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=" + }, + "compressible": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", + "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", + "requires": { + "mime-db": ">= 1.43.0 < 2" + } + }, + "compression": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", + "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", + "requires": { + "accepts": "~1.3.5", + "bytes": "3.0.0", + "compressible": "~2.0.16", + "debug": "2.6.9", + "on-headers": "~1.0.2", + "safe-buffer": "5.1.2", + "vary": "~1.1.2" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + } + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "configstore": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/configstore/-/configstore-5.0.1.tgz", + "integrity": "sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA==", + "requires": { + "dot-prop": "^5.2.0", + "graceful-fs": "^4.1.2", + "make-dir": "^3.0.0", + "unique-string": "^2.0.0", + "write-file-atomic": "^3.0.0", + "xdg-basedir": "^4.0.0" + } + }, + "connect-history-api-fallback": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz", + "integrity": "sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg==" + }, + "consola": { + "version": "2.15.3", + "resolved": "https://registry.npmjs.org/consola/-/consola-2.15.3.tgz", + "integrity": "sha512-9vAdYbHj6x2fLKC4+oPH0kFzY/orMZyG2Aj+kNylHxKGJ/Ed4dpNyAQYwJOdqO4zdM7XpVHmyejQDcQHrnuXbw==" + }, + "console-browserify": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.2.0.tgz", + "integrity": "sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==" + }, + "console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" + }, + "consolidated-events": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/consolidated-events/-/consolidated-events-2.0.2.tgz", + "integrity": "sha512-2/uRVMdRypf5z/TW/ncD/66l75P5hH2vM/GR8Jf8HLc2xnfJtmina6F6du8+v4Z2vTrMo7jC+W1tmEEuuELgkQ==" + }, + "constants-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", + "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=" + }, + "content-disposition": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", + "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ=" + }, + "content-type": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" + }, + "convert-source-map": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz", + "integrity": "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==", + "requires": { + "safe-buffer": "~5.1.1" + } + }, + "cookie": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", + "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==" + }, + "cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" + }, + "copy-text-to-clipboard": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/copy-text-to-clipboard/-/copy-text-to-clipboard-3.0.1.tgz", + "integrity": "sha512-rvVsHrpFcL4F2P8ihsoLdFHmd404+CMg71S756oRSeQgqk51U3kicGdnvfkrxva0xXH92SjGS62B0XIJsbh+9Q==" + }, + "copy-webpack-plugin": { + "version": "10.2.4", + "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-10.2.4.tgz", + "integrity": "sha512-xFVltahqlsRcyyJqQbDY6EYTtyQZF9rf+JPjwHObLdPFMEISqkFkr7mFoVOC6BfYS/dNThyoQKvziugm+OnwBg==", + "requires": { + "fast-glob": "^3.2.7", + "glob-parent": "^6.0.1", + "globby": "^12.0.2", + "normalize-path": "^3.0.0", + "schema-utils": "^4.0.0", + "serialize-javascript": "^6.0.0" + }, + "dependencies": { + "ajv": { + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz", + "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==", + "requires": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + } + }, + "ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "requires": { + "fast-deep-equal": "^3.1.3" + } + }, + "array-union": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-3.0.1.tgz", + "integrity": "sha512-1OvF9IbWwaeiM9VhzYXVQacMibxpXOMYVNIvMtKRyX9SImBXpKcFr8XvFDeEslCyuH/t6KRt7HEO94AlP8Iatw==" + }, + "glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "requires": { + "is-glob": "^4.0.3" + } + }, + "globby": { + "version": "12.2.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-12.2.0.tgz", + "integrity": "sha512-wiSuFQLZ+urS9x2gGPl1H5drc5twabmm4m2gTR27XDFyjUHJUNsS8o/2aKyIF6IoBaR630atdher0XJ5g6OMmA==", + "requires": { + "array-union": "^3.0.1", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.7", + "ignore": "^5.1.9", + "merge2": "^1.4.1", + "slash": "^4.0.0" + } + }, + "schema-utils": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.0.0.tgz", + "integrity": "sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg==", + "requires": { + "@types/json-schema": "^7.0.9", + "ajv": "^8.8.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.0.0" + } + }, + "slash": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz", + "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==" + } + } + }, + "core-js": { + "version": "3.22.4", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.22.4.tgz", + "integrity": "sha512-1uLykR+iOfYja+6Jn/57743gc9n73EWiOnSJJ4ba3B4fOEYDBv25MagmEZBxTp5cWq4b/KPx/l77zgsp28ju4w==" + }, + "core-js-compat": { + "version": "3.22.4", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.22.4.tgz", + "integrity": "sha512-dIWcsszDezkFZrfm1cnB4f/J85gyhiCpxbgBdohWCDtSVuAaChTSpPV7ldOQf/Xds2U5xCIJZOK82G4ZPAIswA==", + "requires": { + "browserslist": "^4.20.3", + "semver": "7.0.0" + }, + "dependencies": { + "semver": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz", + "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==" + } + } + }, + "core-js-pure": { + "version": "3.22.4", + "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.22.4.tgz", + "integrity": "sha512-4iF+QZkpzIz0prAFuepmxwJ2h5t4agvE8WPYqs2mjLJMNNwJOnpch76w2Q7bUfCPEv/V7wpvOfog0w273M+ZSw==" + }, + "core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" + }, + "cosmiconfig": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.1.tgz", + "integrity": "sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ==", + "requires": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.2.1", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.10.0" + } + }, + "create-ecdh": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz", + "integrity": "sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==", + "requires": { + "bn.js": "^4.1.0", + "elliptic": "^6.5.3" + }, + "dependencies": { + "bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + } + } + }, + "create-hash": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", + "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", + "requires": { + "cipher-base": "^1.0.1", + "inherits": "^2.0.1", + "md5.js": "^1.3.4", + "ripemd160": "^2.0.1", + "sha.js": "^2.4.0" + } + }, + "create-hmac": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", + "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", + "requires": { + "cipher-base": "^1.0.3", + "create-hash": "^1.1.0", + "inherits": "^2.0.1", + "ripemd160": "^2.0.0", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "cross-fetch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.5.tgz", + "integrity": "sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw==", + "requires": { + "node-fetch": "2.6.7" + } + }, + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, + "crypto-browserify": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", + "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", + "requires": { + "browserify-cipher": "^1.0.0", + "browserify-sign": "^4.0.0", + "create-ecdh": "^4.0.0", + "create-hash": "^1.1.0", + "create-hmac": "^1.1.0", + "diffie-hellman": "^5.0.0", + "inherits": "^2.0.1", + "pbkdf2": "^3.0.3", + "public-encrypt": "^4.0.0", + "randombytes": "^2.0.0", + "randomfill": "^1.0.3" + } + }, + "crypto-random-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", + "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==" + }, + "css": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/css/-/css-3.0.0.tgz", + "integrity": "sha512-DG9pFfwOrzc+hawpmqX/dHYHJG+Bsdb0klhyi1sDneOgGOXy9wQIC8hzyVp1e4NRYDBdxcylvywPkkXCHAzTyQ==", + "dev": true, + "requires": { + "inherits": "^2.0.4", + "source-map": "^0.6.1", + "source-map-resolve": "^0.6.0" + } + }, + "css-color-keywords": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/css-color-keywords/-/css-color-keywords-1.0.0.tgz", + "integrity": "sha1-/qJhbcZ2spYmhrOvjb2+GAskTgU=" }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "css-declaration-sorter": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-6.2.2.tgz", + "integrity": "sha512-Ufadglr88ZLsrvS11gjeu/40Lw74D9Am/Jpr3LlYm5Q4ZP5KdlUhG+6u2EjyXeZcxmZ2h1ebCKngDjolpeLHpg==", + "requires": {} + }, + "css-loader": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-3.6.0.tgz", + "integrity": "sha512-M5lSukoWi1If8dhQAUCvj4H8vUt3vOnwbQBH9DdTm/s4Ym2B/3dPMtYZeJmq7Q3S3Pa+I94DcZ7pc9bP14cWIQ==", + "dev": true, "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "camelcase": "^5.3.1", + "cssesc": "^3.0.0", + "icss-utils": "^4.1.1", + "loader-utils": "^1.2.3", + "normalize-path": "^3.0.0", + "postcss": "^7.0.32", + "postcss-modules-extract-imports": "^2.0.0", + "postcss-modules-local-by-default": "^3.0.2", + "postcss-modules-scope": "^2.2.0", + "postcss-modules-values": "^3.0.0", + "postcss-value-parser": "^4.1.0", + "schema-utils": "^2.7.0", + "semver": "^6.3.0" + }, + "dependencies": { + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true + }, + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + }, + "loader-utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", + "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + } + }, + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "css-minimizer-webpack-plugin": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/css-minimizer-webpack-plugin/-/css-minimizer-webpack-plugin-3.4.1.tgz", + "integrity": "sha512-1u6D71zeIfgngN2XNRJefc/hY7Ybsxd74Jm4qngIXyUEk7fss3VUzuHxLAq/R8NAba4QU9OUSaMZlbpRc7bM4Q==", + "requires": { + "cssnano": "^5.0.6", + "jest-worker": "^27.0.2", + "postcss": "^8.3.5", + "schema-utils": "^4.0.0", + "serialize-javascript": "^6.0.0", + "source-map": "^0.6.1" + }, + "dependencies": { + "ajv": { + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz", + "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==", + "requires": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + } + }, + "ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "requires": { + "fast-deep-equal": "^3.1.3" + } + }, + "schema-utils": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.0.0.tgz", + "integrity": "sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg==", + "requires": { + "@types/json-schema": "^7.0.9", + "ajv": "^8.8.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.0.0" + } + } + } + }, + "css-select": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", + "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==", + "requires": { + "boolbase": "^1.0.0", + "css-what": "^6.0.1", + "domhandler": "^4.3.1", + "domutils": "^2.8.0", + "nth-check": "^2.0.1" + } + }, + "css-select-base-adapter": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/css-select-base-adapter/-/css-select-base-adapter-0.1.1.tgz", + "integrity": "sha512-jQVeeRG70QI08vSTwf1jHxp74JoZsr2XSgETae8/xC8ovSnL2WF87GTLO86Sbwdt2lK4Umg4HnnwMO4YF3Ce7w==" + }, + "css-to-react-native": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/css-to-react-native/-/css-to-react-native-3.0.0.tgz", + "integrity": "sha512-Ro1yETZA813eoyUp2GDBhG2j+YggidUmzO1/v9eYBKR2EHVEniE2MI/NqpTQ954BMpTPZFsGNPm46qFB9dpaPQ==", + "requires": { + "camelize": "^1.0.0", + "css-color-keywords": "^1.0.0", + "postcss-value-parser": "^4.0.2" + } + }, + "css-tree": { + "version": "1.0.0-alpha.37", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.37.tgz", + "integrity": "sha512-DMxWJg0rnz7UgxKT0Q1HU/L9BeJI0M6ksor0OgqOnF+aRCDWg/N2641HmVyU9KVIu0OVVWOb2IpC9A+BJRnejg==", + "requires": { + "mdn-data": "2.0.4", + "source-map": "^0.6.1" + } + }, + "css-what": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", + "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==" + }, + "css.escape": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/css.escape/-/css.escape-1.5.1.tgz", + "integrity": "sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==", + "dev": true + }, + "cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==" + }, + "cssnano": { + "version": "5.1.7", + "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-5.1.7.tgz", + "integrity": "sha512-pVsUV6LcTXif7lvKKW9ZrmX+rGRzxkEdJuVJcp5ftUjWITgwam5LMZOgaTvUrWPkcORBey6he7JKb4XAJvrpKg==", + "requires": { + "cssnano-preset-default": "^5.2.7", + "lilconfig": "^2.0.3", + "yaml": "^1.10.2" + } + }, + "cssnano-preset-advanced": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/cssnano-preset-advanced/-/cssnano-preset-advanced-5.3.3.tgz", + "integrity": "sha512-AB9SmTSC2Gd8T7PpKUsXFJ3eNsg7dc4CTZ0+XAJ29MNxyJsrCEk7N1lw31bpHrsQH2PVJr21bbWgGAfA9j0dIA==", + "requires": { + "autoprefixer": "^10.3.7", + "cssnano-preset-default": "^5.2.7", + "postcss-discard-unused": "^5.1.0", + "postcss-merge-idents": "^5.1.1", + "postcss-reduce-idents": "^5.2.0", + "postcss-zindex": "^5.1.0" + } + }, + "cssnano-preset-default": { + "version": "5.2.7", + "resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-5.2.7.tgz", + "integrity": "sha512-JiKP38ymZQK+zVKevphPzNSGHSlTI+AOwlasoSRtSVMUU285O7/6uZyd5NbW92ZHp41m0sSHe6JoZosakj63uA==", + "requires": { + "css-declaration-sorter": "^6.2.2", + "cssnano-utils": "^3.1.0", + "postcss-calc": "^8.2.3", + "postcss-colormin": "^5.3.0", + "postcss-convert-values": "^5.1.0", + "postcss-discard-comments": "^5.1.1", + "postcss-discard-duplicates": "^5.1.0", + "postcss-discard-empty": "^5.1.1", + "postcss-discard-overridden": "^5.1.0", + "postcss-merge-longhand": "^5.1.4", + "postcss-merge-rules": "^5.1.1", + "postcss-minify-font-values": "^5.1.0", + "postcss-minify-gradients": "^5.1.1", + "postcss-minify-params": "^5.1.2", + "postcss-minify-selectors": "^5.2.0", + "postcss-normalize-charset": "^5.1.0", + "postcss-normalize-display-values": "^5.1.0", + "postcss-normalize-positions": "^5.1.0", + "postcss-normalize-repeat-style": "^5.1.0", + "postcss-normalize-string": "^5.1.0", + "postcss-normalize-timing-functions": "^5.1.0", + "postcss-normalize-unicode": "^5.1.0", + "postcss-normalize-url": "^5.1.0", + "postcss-normalize-whitespace": "^5.1.1", + "postcss-ordered-values": "^5.1.1", + "postcss-reduce-initial": "^5.1.0", + "postcss-reduce-transforms": "^5.1.0", + "postcss-svgo": "^5.1.0", + "postcss-unique-selectors": "^5.1.1" + } + }, + "cssnano-utils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cssnano-utils/-/cssnano-utils-3.1.0.tgz", + "integrity": "sha512-JQNR19/YZhz4psLX/rQ9M83e3z2Wf/HdJbryzte4a3NSuafyp9w/I4U+hx5C2S9g41qlstH7DEWnZaaj83OuEA==", + "requires": {} + }, + "csso": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/csso/-/csso-4.2.0.tgz", + "integrity": "sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA==", + "requires": { + "css-tree": "^1.1.2" + }, + "dependencies": { + "css-tree": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz", + "integrity": "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==", + "requires": { + "mdn-data": "2.0.14", + "source-map": "^0.6.1" + } + }, + "mdn-data": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz", + "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==" + } + } + }, + "cssom": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.4.4.tgz", + "integrity": "sha512-p3pvU7r1MyyqbTk+WbNJIgJjG2VmTIaB10rI93LzVPrmDJKkzKYMtxxyAvQXR/NS6otuzveI7+7BBq3SjBS2mw==", + "dev": true + }, + "cssstyle": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-2.3.0.tgz", + "integrity": "sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==", + "dev": true, + "requires": { + "cssom": "~0.3.6" + }, + "dependencies": { + "cssom": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", + "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", + "dev": true + } + } + }, + "csstype": { + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.11.tgz", + "integrity": "sha512-sa6P2wJ+CAbgyy4KFssIb/JNMLxFvKF1pCYCSXS8ZMuqZnMsrxqI2E5sPyoTpxoPU/gVZMzr2zjOfg8GIZOMsw==" + }, + "cypress": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/cypress/-/cypress-10.3.0.tgz", + "integrity": "sha512-txkQWKzvBVnWdCuKs5Xc08gjpO89W2Dom2wpZgT9zWZT5jXxqPIxqP/NC1YArtkpmp3fN5HW8aDjYBizHLUFvg==", + "dev": true, + "requires": { + "@cypress/request": "^2.88.10", + "@cypress/xvfb": "^1.2.4", + "@types/node": "^14.14.31", + "@types/sinonjs__fake-timers": "8.1.1", + "@types/sizzle": "^2.3.2", + "arch": "^2.2.0", + "blob-util": "^2.0.2", + "bluebird": "^3.7.2", + "buffer": "^5.6.0", + "cachedir": "^2.3.0", + "chalk": "^4.1.0", + "check-more-types": "^2.24.0", + "cli-cursor": "^3.1.0", + "cli-table3": "~0.6.1", + "commander": "^5.1.0", + "common-tags": "^1.8.0", + "dayjs": "^1.10.4", + "debug": "^4.3.2", + "enquirer": "^2.3.6", + "eventemitter2": "^6.4.3", + "execa": "4.1.0", + "executable": "^4.1.1", + "extract-zip": "2.0.1", + "figures": "^3.2.0", + "fs-extra": "^9.1.0", + "getos": "^3.2.1", + "is-ci": "^3.0.0", + "is-installed-globally": "~0.4.0", + "lazy-ass": "^1.6.0", + "listr2": "^3.8.3", + "lodash": "^4.17.21", + "log-symbols": "^4.0.0", + "minimist": "^1.2.6", + "ospath": "^1.2.2", + "pretty-bytes": "^5.6.0", + "proxy-from-env": "1.0.0", + "request-progress": "^3.0.0", + "semver": "^7.3.2", + "supports-color": "^8.1.1", + "tmp": "~0.2.1", + "untildify": "^4.0.0", + "yauzl": "^2.10.0" }, "dependencies": { + "@types/node": { + "version": "14.18.21", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.21.tgz", + "integrity": "sha512-x5W9s+8P4XteaxT/jKF0PSb7XEvo5VmqEWgsMlyeY4ZlLK8I6aH6g5TPPyDlLAep+GYf4kefb7HFyc7PAO3m+Q==", + "dev": true + }, "ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, "requires": { "color-convert": "^2.0.1" } }, + "buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "dev": true, + "requires": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "dependencies": { + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, "color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, "requires": { "color-name": "~1.1.4" } }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" - }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "execa": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-4.1.0.tgz", + "integrity": "sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==", + "dev": true, + "requires": { + "cross-spawn": "^7.0.0", + "get-stream": "^5.0.0", + "human-signals": "^1.1.1", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.0", + "onetime": "^5.1.0", + "signal-exit": "^3.0.2", + "strip-final-newline": "^2.0.0" + } + }, + "fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "requires": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, "has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "human-signals": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz", + "integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==", + "dev": true + }, + "is-ci": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-3.0.1.tgz", + "integrity": "sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==", + "dev": true, + "requires": { + "ci-info": "^3.2.0" + } }, "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, "requires": { "has-flag": "^4.0.0" } } } }, - "character-entities": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-1.2.4.tgz", - "integrity": "sha512-iBMyeEHxfVnIakwOuDXpVkc54HijNgCyQB2w0VfGQThle6NXn50zU6V/u+LDhxHcDUPojn6Kpga3PTAD8W1bQw==" + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==", + "dev": true, + "requires": { + "assert-plus": "^1.0.0" + } }, - "character-entities-legacy": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-1.1.4.tgz", - "integrity": "sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA==" + "data-urls": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-2.0.0.tgz", + "integrity": "sha512-X5eWTSXO/BJmpdIKCRuKUgSCgAN0OwliVK3yPKbwIWU1Tdw5BRajxlzMidvh+gwko9AfQ9zIj52pzF91Q3YAvQ==", + "dev": true, + "requires": { + "abab": "^2.0.3", + "whatwg-mimetype": "^2.3.0", + "whatwg-url": "^8.0.0" + } }, - "character-reference-invalid": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-1.1.4.tgz", - "integrity": "sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg==" + "dayjs": { + "version": "1.11.3", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.3.tgz", + "integrity": "sha512-xxwlswWOlGhzgQ4TKzASQkUhqERI3egRNqgV4ScR8wlANA/A9tZ7miXa44vTTKEq5l7vWoL5G57bG3zA+Kow0A==", + "dev": true }, - "cheerio": { - "version": "0.22.0", - "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-0.22.0.tgz", - "integrity": "sha1-qbqoYKP5tZWmuBsahocxIe06Jp4=", + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "requires": { - "css-select": "~1.2.0", - "dom-serializer": "~0.1.0", - "entities": "~1.1.1", - "htmlparser2": "^3.9.1", - "lodash.assignin": "^4.0.9", - "lodash.bind": "^4.1.4", - "lodash.defaults": "^4.0.1", - "lodash.filter": "^4.4.0", - "lodash.flatten": "^4.2.0", - "lodash.foreach": "^4.3.0", - "lodash.map": "^4.4.0", - "lodash.merge": "^4.4.0", - "lodash.pick": "^4.2.1", - "lodash.reduce": "^4.4.0", - "lodash.reject": "^4.4.0", - "lodash.some": "^4.4.0" - }, - "dependencies": { - "css-select": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz", - "integrity": "sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg=", - "requires": { - "boolbase": "~1.0.0", - "css-what": "2.1", - "domutils": "1.5.1", - "nth-check": "~1.0.1" - } - }, - "css-what": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.3.tgz", - "integrity": "sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg==" - }, - "dom-serializer": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.1.tgz", - "integrity": "sha512-l0IU0pPzLWSHBcieZbpOKgkIn3ts3vAh7ZuFyXNwJxJXk/c4Gwj9xaTJwIDVQCXawWD0qb3IzMGH5rglQaO0XA==", - "requires": { - "domelementtype": "^1.3.0", - "entities": "^1.1.1" - } - }, - "domelementtype": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", - "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==" - }, - "domutils": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz", - "integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=", - "requires": { - "dom-serializer": "0", - "domelementtype": "1" - } - }, - "entities": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", - "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==" - }, - "nth-check": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz", - "integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==", - "requires": { - "boolbase": "~1.0.0" - } - } + "ms": "2.1.2" } }, - "chokidar": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.2.tgz", - "integrity": "sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ==", + "decimal.js": { + "version": "10.3.1", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.3.1.tgz", + "integrity": "sha512-V0pfhfr8suzyPGOx3nmq4aHqabehUZn6Ch9kyFpV79TGDTWFmHqUqXdabR7QHqxzrYolF4+tVmJhUG4OURg5dQ==", + "dev": true + }, + "decko": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decko/-/decko-1.2.0.tgz", + "integrity": "sha1-/UPHNelnuAEzBohKVvvmZZlraBc=" + }, + "decode-uri-component": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", + "integrity": "sha512-hjf+xovcEn31w/EUYdTXQh/8smFL/dzYjohQGEIgjyNavaJfBY2p5F527Bo1VPATxv0VYTUC2bOcXvqFwk78Og==", + "dev": true + }, + "decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", "requires": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "fsevents": "~2.3.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" + "mimic-response": "^3.1.0" } }, - "chownr": { + "dedent": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", + "integrity": "sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==", + "dev": true + }, + "deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==" + }, + "deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, + "deepmerge": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", + "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==" + }, + "default-gateway": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-6.0.3.tgz", + "integrity": "sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg==", + "requires": { + "execa": "^5.0.0" + } + }, + "defer-to-connect": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz", + "integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==" + }, + "define-lazy-prop": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", + "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==" + }, + "define-properties": { "version": "1.1.4", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", - "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz", + "integrity": "sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==", + "requires": { + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + } }, - "chrome-trace-event": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", - "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==" + "del": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/del/-/del-6.0.0.tgz", + "integrity": "sha512-1shh9DQ23L16oXSZKB2JxpL7iMy2E0S9d517ptA1P8iw0alkPtQcrKH7ru31rYtKwF499HkTu+DRzq3TCKDFRQ==", + "requires": { + "globby": "^11.0.1", + "graceful-fs": "^4.2.4", + "is-glob": "^4.0.1", + "is-path-cwd": "^2.2.0", + "is-path-inside": "^3.0.2", + "p-map": "^4.0.0", + "rimraf": "^3.0.2", + "slash": "^3.0.0" + } }, - "ci-info": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.2.0.tgz", - "integrity": "sha512-dVqRX7fLUm8J6FgHJ418XuIgDLZDkYcDFTeL6TA2gt5WlIZUQrrH6EZrNClwT/H0FateUsZkGIOPRrLbP+PR9A==" + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==" }, - "cipher-base": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", - "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=" + }, + "depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" + }, + "des.js": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.1.tgz", + "integrity": "sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA==", "requires": { "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" + "minimalistic-assert": "^1.0.0" + } + }, + "destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==" + }, + "detab": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/detab/-/detab-2.0.4.tgz", + "integrity": "sha512-8zdsQA5bIkoRECvCrNKPla84lyoR7DSAyf7p0YgXzBO9PDJx8KntPUay7NS6yp+KdxdVtiE5SpHKtbp2ZQyA9g==", + "requires": { + "repeat-string": "^1.5.4" + } + }, + "detect-libc": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz", + "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==" + }, + "detect-newline": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", + "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", + "dev": true + }, + "detect-node": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", + "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==" + }, + "detect-port": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/detect-port/-/detect-port-1.3.0.tgz", + "integrity": "sha512-E+B1gzkl2gqxt1IhUzwjrxBKRqx1UzC3WLONHinn8S3T6lwV/agVCyitiFOsGJ/eYuEUBvD71MZHy3Pv1G9doQ==", + "requires": { + "address": "^1.0.1", + "debug": "^2.6.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + } } }, - "class-utils": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", - "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", + "detect-port-alt": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/detect-port-alt/-/detect-port-alt-1.1.6.tgz", + "integrity": "sha512-5tQykt+LqfJFBEYaDITx7S7cR7mJ/zQmLXZ2qt5w04ainYZw6tBf9dBunMjVeVOdYVRUzUOE4HkY5J7+uttb5Q==", "requires": { - "arr-union": "^3.1.0", - "define-property": "^0.2.5", - "isobject": "^3.0.0", - "static-extend": "^0.1.1" + "address": "^1.0.1", + "debug": "^2.6.0" }, "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "requires": { - "is-descriptor": "^0.1.0" + "ms": "2.0.0" } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" } } }, - "classnames": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.1.tgz", - "integrity": "sha512-OlQdbZ7gLfGarSqxesMesDa5uz7KFbID8Kpq/SxIoNGDqY8lSYs0D+hhtBXhcdB3rcbXArFr7vlHheLk1voeNA==" + "diff-sequences": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.5.1.tgz", + "integrity": "sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ==", + "dev": true }, - "clean-css": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.2.1.tgz", - "integrity": "sha512-ooQCa1/70oRfVdUUGjKpbHuxgMgm8BsDT5EBqBGvPxMoRoGXf4PNx5mMnkjzJ9Ptx4vvmDdha0QVh86QtYIk1g==", + "diffie-hellman": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", + "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", "requires": { - "source-map": "~0.6.0" + "bn.js": "^4.1.0", + "miller-rabin": "^4.0.0", + "randombytes": "^2.0.0" }, "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + "bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" } } }, - "clean-stack": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", - "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==" - }, - "cli-boxes": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz", - "integrity": "sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==" - }, - "cliui": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", - "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", "requires": { - "string-width": "^3.1.0", - "strip-ansi": "^5.2.0", - "wrap-ansi": "^5.1.0" - }, - "dependencies": { - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" - }, - "emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==" - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" - }, - "string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - } - }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "requires": { - "ansi-regex": "^4.1.0" - } - }, - "wrap-ansi": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", - "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", - "requires": { - "ansi-styles": "^3.2.0", - "string-width": "^3.0.0", - "strip-ansi": "^5.0.0" - } - } + "path-type": "^4.0.0" } }, - "clone-deep": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", - "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", + "dns-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz", + "integrity": "sha1-s55/HabrCnW6nBcySzR1PEfgZU0=" + }, + "dns-packet": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.3.1.tgz", + "integrity": "sha512-spBwIj0TK0Ey3666GwIdWVfUpLyubpU53BTCu8iPn4r4oXd9O14Hjg3EHw3ts2oed77/SeckunUYCyRlSngqHw==", "requires": { - "is-plain-object": "^2.0.4", - "kind-of": "^6.0.2", - "shallow-clone": "^3.0.0" + "@leichtgewicht/ip-codec": "^2.0.1" } }, - "clone-response": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", - "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=", + "dom-accessibility-api": { + "version": "0.5.14", + "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.14.tgz", + "integrity": "sha512-NMt+m9zFMPZe0JcY9gN224Qvk6qLIdqex29clBvc/y75ZBX9YA9wNK3frsYvu2DI1xcCIwxwnX+TlsJ2DSOADg==", + "dev": true + }, + "dom-converter": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz", + "integrity": "sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==", "requires": { - "mimic-response": "^1.0.0" + "utila": "~0.4" } }, - "clsx": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.1.1.tgz", - "integrity": "sha512-6/bPho624p3S2pMyvP5kKBPXnI3ufHLObBFCfgx+LkeR5lg2XYy2hqZqUf45ypD8COn2bhgGJSUE+l5dhNBieA==" - }, - "coa": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/coa/-/coa-2.0.2.tgz", - "integrity": "sha512-q5/jG+YQnSy4nRTV4F7lPepBJZ8qBNJJDBuJdoejDyLXgmL7IEo+Le2JDZudFTFt7mrCqIRaSjws4ygRCTCAXA==", + "dom-serializer": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", + "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", "requires": { - "@types/q": "^1.5.1", - "chalk": "^2.4.1", - "q": "^1.1.2" - }, - "dependencies": { - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - } + "domelementtype": "^2.0.1", + "domhandler": "^4.2.0", + "entities": "^2.0.0" } }, - "code-point-at": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" + "dom-walk": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.2.tgz", + "integrity": "sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w==" }, - "collapse-white-space": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/collapse-white-space/-/collapse-white-space-1.0.6.tgz", - "integrity": "sha512-jEovNnrhMuqyCcjfEJA56v0Xq8SkIoPKDyaHahwo3POf4qcSXqMYuwNcOTzp74vTsR9Tn08z4MxWqAhcekogkQ==" + "domain-browser": { + "version": "4.22.0", + "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-4.22.0.tgz", + "integrity": "sha512-IGBwjF7tNk3cwypFNH/7bfzBcgSCbaMOD3GsaY1AU/JRrnHnYgEM0+9kQt52iZxjNsjBtJYtao146V+f8jFZNw==" }, - "collection-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", - "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", - "requires": { - "map-visit": "^1.0.0", - "object-visit": "^1.0.0" - } + "domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==" }, - "color": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/color/-/color-3.2.1.tgz", - "integrity": "sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA==", + "domexception": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/domexception/-/domexception-2.0.1.tgz", + "integrity": "sha512-yxJ2mFy/sibVQlu5qHjOkf9J3K6zgmCxgJ94u2EdvDOV09H+32LtRswEcUsmUWN72pVLOEnTSRaIVVzVQgS0dg==", + "dev": true, "requires": { - "color-convert": "^1.9.3", - "color-string": "^1.6.0" + "webidl-conversions": "^5.0.0" + }, + "dependencies": { + "webidl-conversions": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-5.0.0.tgz", + "integrity": "sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA==", + "dev": true + } } }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "domhandler": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", + "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", "requires": { - "color-name": "1.1.3" + "domelementtype": "^2.2.0" } }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" + "dompurify": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-2.3.6.tgz", + "integrity": "sha512-OFP2u/3T1R5CEgWCEONuJ1a5+MFKnOYpkywpUSxv/dj1LeBT1erK+JwM7zK0ROy2BRhqVCf0LRw/kHqKuMkVGg==" }, - "color-string": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.6.0.tgz", - "integrity": "sha512-c/hGS+kRWJutUBEngKKmk4iH3sD59MBkoxVapS/0wgpCz2u7XsNloxknyvBhzwEs1IbV36D9PwqLPJ2DTu3vMA==", + "domutils": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", + "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", "requires": { - "color-name": "^1.0.0", - "simple-swizzle": "^0.2.2" + "dom-serializer": "^1.0.1", + "domelementtype": "^2.2.0", + "domhandler": "^4.2.0" } }, - "colord": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/colord/-/colord-2.8.0.tgz", - "integrity": "sha512-kNkVV4KFta3TYQv0bzs4xNwLaeag261pxgzGQSh4cQ1rEhYjcTJfFRP0SDlbhLONg0eSoLzrDd79PosjbltufA==" - }, - "colorette": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.4.0.tgz", - "integrity": "sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g==" - }, - "combine-promises": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/combine-promises/-/combine-promises-1.1.0.tgz", - "integrity": "sha512-ZI9jvcLDxqwaXEixOhArm3r7ReIivsXkpbyEWyeOhzz1QS0iSgBPnWvEqvIQtYyamGCYA88gFhmUrs9hrrQ0pg==" - }, - "comma-separated-tokens": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-1.0.8.tgz", - "integrity": "sha512-GHuDRO12Sypu2cV70d1dkA2EUmXHgntrzbpvOB+Qy+49ypNfGgFQIC2fhhXbnyrJRynDCAARsT7Ou0M6hirpfw==" - }, - "commander": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz", - "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==" - }, - "commondir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", - "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=" - }, - "component-emitter": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", - "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==" - }, - "compressible": { - "version": "2.0.18", - "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", - "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", + "dot-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", + "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", "requires": { - "mime-db": ">= 1.43.0 < 2" + "no-case": "^3.0.4", + "tslib": "^2.0.3" } }, - "compression": { - "version": "1.7.4", - "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", - "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", + "dot-prop": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", + "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", "requires": { - "accepts": "~1.3.5", - "bytes": "3.0.0", - "compressible": "~2.0.16", - "debug": "2.6.9", - "on-headers": "~1.0.2", - "safe-buffer": "5.1.2", - "vary": "~1.1.2" + "is-obj": "^2.0.0" }, "dependencies": { - "bytes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", - "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=" - }, - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - }, - "ms": { + "is-obj": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", + "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==" } } }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + "dotenv": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-10.0.0.tgz", + "integrity": "sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q==", + "dev": true }, - "configstore": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/configstore/-/configstore-5.0.1.tgz", - "integrity": "sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA==", + "duplexer": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", + "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==" + }, + "duplexer3": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", + "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=" + }, + "eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" + }, + "ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==", + "dev": true, "requires": { - "dot-prop": "^5.2.0", - "graceful-fs": "^4.1.2", - "make-dir": "^3.0.0", - "unique-string": "^2.0.0", - "write-file-atomic": "^3.0.0", - "xdg-basedir": "^4.0.0" + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" } }, - "connect-history-api-fallback": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz", - "integrity": "sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg==" + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" }, - "consola": { - "version": "2.15.3", - "resolved": "https://registry.npmjs.org/consola/-/consola-2.15.3.tgz", - "integrity": "sha512-9vAdYbHj6x2fLKC4+oPH0kFzY/orMZyG2Aj+kNylHxKGJ/Ed4dpNyAQYwJOdqO4zdM7XpVHmyejQDcQHrnuXbw==" + "electron-to-chromium": { + "version": "1.4.129", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.129.tgz", + "integrity": "sha512-GgtN6bsDtHdtXJtlMYZWGB/uOyjZWjmRDumXTas7dGBaB9zUyCjzHet1DY2KhyHN8R0GLbzZWqm4efeddqqyRQ==" }, - "console-browserify": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.2.0.tgz", - "integrity": "sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==" + "elliptic": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", + "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==", + "requires": { + "bn.js": "^4.11.9", + "brorand": "^1.1.0", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.1", + "inherits": "^2.0.4", + "minimalistic-assert": "^1.0.1", + "minimalistic-crypto-utils": "^1.0.1" + }, + "dependencies": { + "bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + } + } }, - "console-control-strings": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" + "emittery": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.8.1.tgz", + "integrity": "sha512-uDfvUjVrfGJJhymx/kz6prltenw1u7WrCg1oa94zYY8xxVpLLUu045LAT0dhDZdXG58/EpPL/5kA180fQ/qudg==", + "dev": true }, - "consolidated-events": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/consolidated-events/-/consolidated-events-2.0.2.tgz", - "integrity": "sha512-2/uRVMdRypf5z/TW/ncD/66l75P5hH2vM/GR8Jf8HLc2xnfJtmina6F6du8+v4Z2vTrMo7jC+W1tmEEuuELgkQ==" + "emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" }, - "constants-browserify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", - "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=" + "emojis-list": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", + "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==" }, - "content-disposition": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", - "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", - "requires": { - "safe-buffer": "5.1.2" - } + "emoticon": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/emoticon/-/emoticon-3.2.0.tgz", + "integrity": "sha512-SNujglcLTTg+lDAcApPNgEdudaqQFiAbJCqzjNxJkvN9vAwCGi0uu8IUVvx+f16h+V44KCY6Y2yboroc9pilHg==" }, - "content-type": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", - "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" + "encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" }, - "convert-source-map": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz", - "integrity": "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==", + "end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", "requires": { - "safe-buffer": "~5.1.1" + "once": "^1.4.0" } }, - "cookie": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", - "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==" + "enhanced-resolve": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.9.3.tgz", + "integrity": "sha512-Bq9VSor+kjvW3f9/MiiR4eE3XYgOl7/rS8lnSxbRbF3kS0B2r+Y9w5krBWxZgDxASVZbdYrn5wT4j/Wb0J9qow==", + "requires": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + } }, - "cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" + "enquirer": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", + "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", + "dev": true, + "requires": { + "ansi-colors": "^4.1.1" + } }, - "copy-descriptor": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", - "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=" + "entities": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==" }, - "copy-text-to-clipboard": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/copy-text-to-clipboard/-/copy-text-to-clipboard-3.0.1.tgz", - "integrity": "sha512-rvVsHrpFcL4F2P8ihsoLdFHmd404+CMg71S756oRSeQgqk51U3kicGdnvfkrxva0xXH92SjGS62B0XIJsbh+9Q==" + "error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "requires": { + "is-arrayish": "^0.2.1" + } }, - "copy-webpack-plugin": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-9.0.1.tgz", - "integrity": "sha512-14gHKKdYIxF84jCEgPgYXCPpldbwpxxLbCmA7LReY7gvbaT555DgeBWBgBZM116tv/fO6RRJrsivBqRyRlukhw==", + "es-abstract": { + "version": "1.19.5", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.19.5.tgz", + "integrity": "sha512-Aa2G2+Rd3b6kxEUKTF4TaW67czBLyAv3z7VOhYRU50YBx+bbsYZ9xQP4lMNazePuFlybXI0V4MruPos7qUo5fA==", "requires": { - "fast-glob": "^3.2.5", - "glob-parent": "^6.0.0", - "globby": "^11.0.3", - "normalize-path": "^3.0.0", - "p-limit": "^3.1.0", - "schema-utils": "^3.0.0", - "serialize-javascript": "^6.0.0" - }, - "dependencies": { - "glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "requires": { - "is-glob": "^4.0.3" - } - } + "call-bind": "^1.0.2", + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "get-intrinsic": "^1.1.1", + "get-symbol-description": "^1.0.0", + "has": "^1.0.3", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.3", + "is-callable": "^1.2.4", + "is-negative-zero": "^2.0.2", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.2", + "is-string": "^1.0.7", + "is-weakref": "^1.0.2", + "object-inspect": "^1.12.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.2", + "string.prototype.trimend": "^1.0.4", + "string.prototype.trimstart": "^1.0.4", + "unbox-primitive": "^1.0.1" } }, - "core-js": { - "version": "3.18.3", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.18.3.tgz", - "integrity": "sha512-tReEhtMReZaPFVw7dajMx0vlsz3oOb8ajgPoHVYGxr8ErnZ6PcYEvvmjGmXlfpnxpkYSdOQttjB+MvVbCGfvLw==" + "es-module-lexer": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.9.3.tgz", + "integrity": "sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ==" }, - "core-js-compat": { - "version": "3.18.3", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.18.3.tgz", - "integrity": "sha512-4zP6/y0a2RTHN5bRGT7PTq9lVt3WzvffTNjqnTKsXhkAYNDTkdCLOIfAdOLcQ/7TDdyRj3c+NeHe1NmF1eDScw==", + "es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", "requires": { - "browserslist": "^4.17.3", - "semver": "7.0.0" - }, - "dependencies": { - "semver": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz", - "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==" - } + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" } }, - "core-js-pure": { - "version": "3.18.3", - "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.18.3.tgz", - "integrity": "sha512-qfskyO/KjtbYn09bn1IPkuhHl5PlJ6IzJ9s9sraJ1EqcuGyLGKzhSM1cY0zgyL9hx42eulQLZ6WaeK5ycJCkqw==" + "es6-object-assign": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/es6-object-assign/-/es6-object-assign-1.1.0.tgz", + "integrity": "sha1-wsNYJlYkfDnqEHyx5mUrb58kUjw=" }, - "core-util-is": { + "es6-promise": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.3.1.tgz", + "integrity": "sha1-oIzd6EzNvzTQJ6FFG8kdS80ophM=" + }, + "escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==" + }, + "escape-goat": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-2.1.1.tgz", + "integrity": "sha512-8/uIhbG12Csjy2JEW7D9pHbreaVaS/OpN3ycnyvElTdwM5n6GY6W6e2IPemfvGZeUMqZ9A/3GqIZMgKnBhAw/Q==" + }, + "escape-html": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" }, - "cosmiconfig": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.1.tgz", - "integrity": "sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ==", + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" + }, + "escodegen": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.0.0.tgz", + "integrity": "sha512-mmHKys/C8BFUGI+MAWNcSYoORYLMdPzjrknd2Vc+bUsjN5bXcr8EhrNB+UTqfL1y3I9c4fw2ihgtMPQLBRiQxw==", + "dev": true, "requires": { - "@types/parse-json": "^4.0.0", - "import-fresh": "^3.2.1", - "parse-json": "^5.0.0", - "path-type": "^4.0.0", - "yaml": "^1.10.0" + "esprima": "^4.0.1", + "estraverse": "^5.2.0", + "esutils": "^2.0.2", + "optionator": "^0.8.1", + "source-map": "~0.6.1" } }, - "create-ecdh": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz", - "integrity": "sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==", + "eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", "requires": { - "bn.js": "^4.1.0", - "elliptic": "^6.5.3" + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" }, "dependencies": { - "bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==" } } }, - "create-hash": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", - "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" + }, + "esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", "requires": { - "cipher-base": "^1.0.1", - "inherits": "^2.0.1", - "md5.js": "^1.3.4", - "ripemd160": "^2.0.1", - "sha.js": "^2.4.0" + "estraverse": "^5.2.0" } }, - "create-hmac": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", - "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==" + }, + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==" + }, + "eta": { + "version": "1.12.3", + "resolved": "https://registry.npmjs.org/eta/-/eta-1.12.3.tgz", + "integrity": "sha512-qHixwbDLtekO/d51Yr4glcaUJCIjGVJyTzuqV4GPlgZo1YpgOKG+avQynErZIYrfM6JIJdtiG2Kox8tbb+DoGg==" + }, + "etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" + }, + "eval": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/eval/-/eval-0.1.8.tgz", + "integrity": "sha512-EzV94NYKoO09GLXGjXj9JIlXijVck4ONSr5wiCWDvhsvj5jxSrzTmRU/9C1DyB6uToszLs8aifA6NQ7lEQdvFw==", "requires": { - "cipher-base": "^1.0.3", - "create-hash": "^1.1.0", - "inherits": "^2.0.1", - "ripemd160": "^2.0.0", - "safe-buffer": "^5.0.1", - "sha.js": "^2.4.8" + "@types/node": "*", + "require-like": ">= 0.1.1" } }, - "cross-fetch": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.4.tgz", - "integrity": "sha512-1eAtFWdIubi6T4XPy6ei9iUFoKpUkIF971QLN8lIvvvwueI65+Nw5haMNKUwfJxabqlIIDODJKGrQ66gxC0PbQ==", + "eventemitter2": { + "version": "6.4.6", + "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-6.4.6.tgz", + "integrity": "sha512-OHqo4wbHX5VbvlbB6o6eDwhYmiTjrpWACjF8Pmof/GTD6rdBNdZFNck3xlhqOiQFGCOoq3uzHvA0cQpFHIGVAQ==", + "dev": true + }, + "eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==" + }, + "events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==" + }, + "evp_bytestokey": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", + "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", "requires": { - "node-fetch": "2.6.1" + "md5.js": "^1.3.4", + "safe-buffer": "^5.1.1" } }, - "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", "requires": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" } }, - "crypto-browserify": { - "version": "3.12.0", - "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", - "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", + "executable": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/executable/-/executable-4.1.1.tgz", + "integrity": "sha512-8iA79xD3uAch729dUG8xaaBBFGaEa0wdD2VkYLFHwlqosEj/jT66AzcreRDSgV7ehnNLBW2WR5jIXwGKjVdTLg==", + "dev": true, "requires": { - "browserify-cipher": "^1.0.0", - "browserify-sign": "^4.0.0", - "create-ecdh": "^4.0.0", - "create-hash": "^1.1.0", - "create-hmac": "^1.1.0", - "diffie-hellman": "^5.0.0", - "inherits": "^2.0.1", - "pbkdf2": "^3.0.3", - "public-encrypt": "^4.0.0", - "randombytes": "^2.0.0", - "randomfill": "^1.0.3" + "pify": "^2.2.0" } }, - "crypto-random-string": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", - "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==" + "exif-parser": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/exif-parser/-/exif-parser-0.1.12.tgz", + "integrity": "sha1-WKnS1ywCwfbwKg70qRZicrd2CSI=" }, - "css-color-keywords": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/css-color-keywords/-/css-color-keywords-1.0.0.tgz", - "integrity": "sha1-/qJhbcZ2spYmhrOvjb2+GAskTgU=" + "exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", + "dev": true }, - "css-color-names": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/css-color-names/-/css-color-names-1.0.1.tgz", - "integrity": "sha512-/loXYOch1qU1biStIFsHH8SxTmOseh1IJqFvy8IujXOm1h+QjUdDhkzOrR5HG8K8mlxREj0yfi8ewCHx0eMxzA==" + "expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==" }, - "css-declaration-sorter": { - "version": "6.1.3", - "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-6.1.3.tgz", - "integrity": "sha512-SvjQjNRZgh4ULK1LDJ2AduPKUKxIqmtU7ZAyi47BTV+M90Qvxr9AB6lKlLbDUfXqI9IQeYA8LbAsCZPpJEV3aA==", + "expect": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/expect/-/expect-27.5.1.tgz", + "integrity": "sha512-E1q5hSUG2AmYQwQJ041nvgpkODHQvB+RKlB4IYdru6uJsyFTRyZAP463M+1lINorwbqAmUggi6+WwkD8lCS/Dw==", + "dev": true, "requires": { - "timsort": "^0.3.0" + "@jest/types": "^27.5.1", + "jest-get-type": "^27.5.1", + "jest-matcher-utils": "^27.5.1", + "jest-message-util": "^27.5.1" } }, - "css-loader": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-3.6.0.tgz", - "integrity": "sha512-M5lSukoWi1If8dhQAUCvj4H8vUt3vOnwbQBH9DdTm/s4Ym2B/3dPMtYZeJmq7Q3S3Pa+I94DcZ7pc9bP14cWIQ==", - "dev": true, + "express": { + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.18.1.tgz", + "integrity": "sha512-zZBcOX9TfehHQhtupq57OF8lFZ3UZi08Y97dwFCkD8p9d/d2Y3M+ykKcwaMDEL+4qyUolgBDX6AblpR3fL212Q==", "requires": { - "camelcase": "^5.3.1", - "cssesc": "^3.0.0", - "icss-utils": "^4.1.1", - "loader-utils": "^1.2.3", - "normalize-path": "^3.0.0", - "postcss": "^7.0.32", - "postcss-modules-extract-imports": "^2.0.0", - "postcss-modules-local-by-default": "^3.0.2", - "postcss-modules-scope": "^2.2.0", - "postcss-modules-values": "^3.0.0", - "postcss-value-parser": "^4.1.0", - "schema-utils": "^2.7.0", - "semver": "^6.3.0" + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.0", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.5.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.2.0", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.7", + "qs": "6.10.3", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.18.0", + "serve-static": "1.15.0", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" }, "dependencies": { - "camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true - }, - "icss-utils": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-4.1.1.tgz", - "integrity": "sha512-4aFq7wvWyMHKgxsH8QQtGpvbASCf+eM3wPRLI6R+MgAnTCZ6STYsRvttLvRWK0Nfif5piF394St3HeJDaljGPA==", - "dev": true, - "requires": { - "postcss": "^7.0.14" - } - }, - "json5": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", - "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", - "dev": true, - "requires": { - "minimist": "^1.2.0" - } + "array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" }, - "loader-utils": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", - "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", - "dev": true, + "content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", "requires": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^1.0.1" + "safe-buffer": "5.2.1" } }, - "picocolors": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", - "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", - "dev": true - }, - "postcss": { - "version": "7.0.39", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", - "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", - "dev": true, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "requires": { - "picocolors": "^0.2.1", - "source-map": "^0.6.1" + "ms": "2.0.0" } }, - "postcss-modules-extract-imports": { + "ms": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-2.0.0.tgz", - "integrity": "sha512-LaYLDNS4SG8Q5WAWqIJgdHPJrDDr/Lv775rMBFUbgjTz6j34lUznACHcdRWroPvXANP2Vj7yNK57vp9eFqzLWQ==", - "dev": true, - "requires": { - "postcss": "^7.0.5" - } - }, - "postcss-modules-local-by-default": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-3.0.3.tgz", - "integrity": "sha512-e3xDq+LotiGesympRlKNgaJ0PCzoUIdpH0dj47iWAui/kyTgh3CiAr1qP54uodmJhl6p9rN6BoNcdEDVJx9RDw==", - "dev": true, - "requires": { - "icss-utils": "^4.1.1", - "postcss": "^7.0.32", - "postcss-selector-parser": "^6.0.2", - "postcss-value-parser": "^4.1.0" - } - }, - "postcss-modules-scope": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-2.2.0.tgz", - "integrity": "sha512-YyEgsTMRpNd+HmyC7H/mh3y+MeFWevy7V1evVhJWewmMbjDHIbZbOXICC2y+m1xI1UVfIT1HMW/O04Hxyu9oXQ==", - "dev": true, - "requires": { - "postcss": "^7.0.6", - "postcss-selector-parser": "^6.0.0" - } - }, - "postcss-modules-values": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-3.0.0.tgz", - "integrity": "sha512-1//E5jCBrZ9DmRX+zCtmQtRSV6PV42Ix7Bzj9GbwJceduuf7IqP8MgeTXuRDHOWj2m0VzZD5+roFWDuU8RQjcg==", - "dev": true, - "requires": { - "icss-utils": "^4.0.0", - "postcss": "^7.0.6" - } + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, - "schema-utils": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz", - "integrity": "sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.5", - "ajv": "^6.12.4", - "ajv-keywords": "^3.5.2" - } + "path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" }, - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true + "range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" } } }, - "css-minimizer-webpack-plugin": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/css-minimizer-webpack-plugin/-/css-minimizer-webpack-plugin-3.1.1.tgz", - "integrity": "sha512-KlB8l5uoNcf9F7i5kXnkxoqJGd2BXH4f0+Lj2vSWSmuvMLYO1kNsJ1KHSzeDW8e45/whgSOPcKVT/3JopkT8dg==", + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "requires": { - "cssnano": "^5.0.6", - "jest-worker": "^27.0.2", - "p-limit": "^3.0.2", - "postcss": "^8.3.5", - "schema-utils": "^3.1.0", - "serialize-javascript": "^6.0.0", - "source-map": "^0.6.1" + "is-extendable": "^0.1.0" + } + }, + "extract-zip": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", + "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", + "dev": true, + "requires": { + "@types/yauzl": "^2.9.1", + "debug": "^4.1.1", + "get-stream": "^5.1.0", + "yauzl": "^2.10.0" }, "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + "get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } } } }, - "css-select": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.1.3.tgz", - "integrity": "sha512-gT3wBNd9Nj49rAbmtFHj1cljIAOLYSX1nZ8CB7TBO3INYckygm5B7LISU/szY//YmdiSLbJvDLOx9VnMVpMBxA==", - "requires": { - "boolbase": "^1.0.0", - "css-what": "^5.0.0", - "domhandler": "^4.2.0", - "domutils": "^2.6.0", - "nth-check": "^2.0.0" - } + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==", + "dev": true }, - "css-select-base-adapter": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/css-select-base-adapter/-/css-select-base-adapter-0.1.1.tgz", - "integrity": "sha512-jQVeeRG70QI08vSTwf1jHxp74JoZsr2XSgETae8/xC8ovSnL2WF87GTLO86Sbwdt2lK4Umg4HnnwMO4YF3Ce7w==" + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" }, - "css-to-react-native": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/css-to-react-native/-/css-to-react-native-3.0.0.tgz", - "integrity": "sha512-Ro1yETZA813eoyUp2GDBhG2j+YggidUmzO1/v9eYBKR2EHVEniE2MI/NqpTQ954BMpTPZFsGNPm46qFB9dpaPQ==", + "fast-glob": { + "version": "3.2.11", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz", + "integrity": "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==", "requires": { - "camelize": "^1.0.0", - "css-color-keywords": "^1.0.0", - "postcss-value-parser": "^4.0.2" + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" } }, - "css-tree": { + "fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true + }, + "fast-safe-stringify": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", + "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==" + }, + "fast-url-parser": { "version": "1.1.3", - "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz", - "integrity": "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==", + "resolved": "https://registry.npmjs.org/fast-url-parser/-/fast-url-parser-1.1.3.tgz", + "integrity": "sha1-9K8+qfNNiicc9YrSs3WfQx8LMY0=", "requires": { - "mdn-data": "2.0.14", - "source-map": "^0.6.1" + "punycode": "^1.3.2" }, "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" } } }, - "css-what": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-5.1.0.tgz", - "integrity": "sha512-arSMRWIIFY0hV8pIxZMEfmMI47Wj3R/aWpZDDxWYCPEiOMv6tfOrnpDtgxBYPEQD4V0Y/958+1TdC3iWTFcUPw==" + "fastq": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", + "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", + "requires": { + "reusify": "^1.0.4" + } }, - "cssesc": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", - "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==" + "faye-websocket": { + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz", + "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==", + "requires": { + "websocket-driver": ">=0.5.1" + } }, - "cssnano": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-5.0.8.tgz", - "integrity": "sha512-Lda7geZU0Yu+RZi2SGpjYuQz4HI4/1Y+BhdD0jL7NXAQ5larCzVn+PUGuZbDMYz904AXXCOgO5L1teSvgu7aFg==", + "fb-watchman": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.1.tgz", + "integrity": "sha512-DkPJKQeY6kKwmuMretBhr7G6Vodr7bFwDYTXIkfG1gjvNpaxBTQV3PbXg6bR1c1UP4jPOX0jHUbbHANL9vRjVg==", + "dev": true, "requires": { - "cssnano-preset-default": "^5.1.4", - "is-resolvable": "^1.1.0", - "lilconfig": "^2.0.3", - "yaml": "^1.10.2" + "bser": "2.1.1" } }, - "cssnano-preset-advanced": { - "version": "5.1.4", - "resolved": "https://registry.npmjs.org/cssnano-preset-advanced/-/cssnano-preset-advanced-5.1.4.tgz", - "integrity": "sha512-pFtIM15OzryDk09RcK+bBBtwSl80+g/POTAf/sVPqPmnOAleK6vBkY5wTmPjqGyV5/UTPjEzWMtbOQ3Z0kCBXA==", + "fbemitter": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/fbemitter/-/fbemitter-3.0.0.tgz", + "integrity": "sha512-KWKaceCwKQU0+HPoop6gn4eOHk50bBv/VxjJtGMfwmJt3D29JpN4H4eisCtIPA+a8GVBam+ldMMpMjJUvpDyHw==", "requires": { - "autoprefixer": "^10.2.0", - "cssnano-preset-default": "^5.1.4", - "postcss-discard-unused": "^5.0.1", - "postcss-merge-idents": "^5.0.1", - "postcss-reduce-idents": "^5.0.1", - "postcss-zindex": "^5.0.1" + "fbjs": "^3.0.0" } }, - "cssnano-preset-default": { - "version": "5.1.4", - "resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-5.1.4.tgz", - "integrity": "sha512-sPpQNDQBI3R/QsYxQvfB4mXeEcWuw0wGtKtmS5eg8wudyStYMgKOQT39G07EbW1LB56AOYrinRS9f0ig4Y3MhQ==", - "requires": { - "css-declaration-sorter": "^6.0.3", - "cssnano-utils": "^2.0.1", - "postcss-calc": "^8.0.0", - "postcss-colormin": "^5.2.0", - "postcss-convert-values": "^5.0.1", - "postcss-discard-comments": "^5.0.1", - "postcss-discard-duplicates": "^5.0.1", - "postcss-discard-empty": "^5.0.1", - "postcss-discard-overridden": "^5.0.1", - "postcss-merge-longhand": "^5.0.2", - "postcss-merge-rules": "^5.0.2", - "postcss-minify-font-values": "^5.0.1", - "postcss-minify-gradients": "^5.0.2", - "postcss-minify-params": "^5.0.1", - "postcss-minify-selectors": "^5.1.0", - "postcss-normalize-charset": "^5.0.1", - "postcss-normalize-display-values": "^5.0.1", - "postcss-normalize-positions": "^5.0.1", - "postcss-normalize-repeat-style": "^5.0.1", - "postcss-normalize-string": "^5.0.1", - "postcss-normalize-timing-functions": "^5.0.1", - "postcss-normalize-unicode": "^5.0.1", - "postcss-normalize-url": "^5.0.2", - "postcss-normalize-whitespace": "^5.0.1", - "postcss-ordered-values": "^5.0.2", - "postcss-reduce-initial": "^5.0.1", - "postcss-reduce-transforms": "^5.0.1", - "postcss-svgo": "^5.0.2", - "postcss-unique-selectors": "^5.0.1" + "fbjs": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/fbjs/-/fbjs-3.0.4.tgz", + "integrity": "sha512-ucV0tDODnGV3JCnnkmoszb5lf4bNpzjv80K41wd4k798Etq+UYD0y0TIfalLjZoKgjive6/adkRnszwapiDgBQ==", + "requires": { + "cross-fetch": "^3.1.5", + "fbjs-css-vars": "^1.0.0", + "loose-envify": "^1.0.0", + "object-assign": "^4.1.0", + "promise": "^7.1.1", + "setimmediate": "^1.0.5", + "ua-parser-js": "^0.7.30" } }, - "cssnano-utils": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/cssnano-utils/-/cssnano-utils-2.0.1.tgz", - "integrity": "sha512-i8vLRZTnEH9ubIyfdZCAdIdgnHAUeQeByEeQ2I7oTilvP9oHO6RScpeq3GsFUVqeB8uZgOQ9pw8utofNn32hhQ==", - "requires": {} + "fbjs-css-vars": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/fbjs-css-vars/-/fbjs-css-vars-1.0.2.tgz", + "integrity": "sha512-b2XGFAFdWZWg0phtAWLHCk836A1Xann+I+Dgd3Gk64MHKZO44FfoD1KxyvbSh0qZsIoXQGGlVztIY+oitJPpRQ==" }, - "csso": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/csso/-/csso-4.2.0.tgz", - "integrity": "sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA==", + "fd-slicer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", + "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", + "dev": true, "requires": { - "css-tree": "^1.1.2" + "pend": "~1.2.0" } }, - "debug": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", - "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "feed": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/feed/-/feed-4.2.2.tgz", + "integrity": "sha512-u5/sxGfiMfZNtJ3OvQpXcvotFpYkL0n9u9mM2vkui2nGo8b4wvDkJ8gAkYqbA8QpGyFCv3RK0Z+Iv+9veCS9bQ==", "requires": { - "ms": "2.1.2" + "xml-js": "^1.6.11" } }, - "decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" + "figures": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", + "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.5" + } }, - "decko": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decko/-/decko-1.2.0.tgz", - "integrity": "sha1-/UPHNelnuAEzBohKVvvmZZlraBc=" + "file-loader": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-6.2.0.tgz", + "integrity": "sha512-qo3glqyTa61Ytg4u73GultjHGjdRyig3tG6lPtyX/jOEJvHif9uB0/OCI2Kif6ctF3caQTW2G5gym21oAsI4pw==", + "requires": { + "loader-utils": "^2.0.0", + "schema-utils": "^3.0.0" + }, + "dependencies": { + "schema-utils": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", + "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", + "requires": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + } + } + } }, - "decode-uri-component": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", - "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=" + "file-type": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-9.0.0.tgz", + "integrity": "sha512-Qe/5NJrgIOlwijpq3B7BEpzPFcgzggOTagZmkXQY4LA6bsXKTUstK7Wp12lEJ/mLKTpvIZxmIuRcLYWT6ov9lw==" }, - "decompress-response": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", - "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", + "filesize": { + "version": "8.0.7", + "resolved": "https://registry.npmjs.org/filesize/-/filesize-8.0.7.tgz", + "integrity": "sha512-pjmC+bkIF8XI7fWaH8KxHcZL3DPybs1roSKP4rKDvy20tAWwIObE4+JIseG2byfGKhud5ZnM4YSGKBz7Sh0ndQ==" + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", "requires": { - "mimic-response": "^1.0.0" + "to-regex-range": "^5.0.1" } }, - "deep-equal": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.1.tgz", - "integrity": "sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g==", + "filter-obj": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/filter-obj/-/filter-obj-2.0.2.tgz", + "integrity": "sha512-lO3ttPjHZRfjMcxWKb1j1eDhTFsu4meeR3lnMcnBFhk6RuLhvEiuALu2TlfL310ph4lCYYwgF/ElIjdP739tdg==" + }, + "finalhandler": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", + "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", "requires": { - "is-arguments": "^1.0.4", - "is-date-object": "^1.0.1", - "is-regex": "^1.0.4", - "object-is": "^1.0.1", - "object-keys": "^1.1.1", - "regexp.prototype.flags": "^1.2.0" + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + } } }, - "deep-extend": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", - "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==" - }, - "deepmerge": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", - "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==" + "find-cache-dir": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", + "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", + "requires": { + "commondir": "^1.0.1", + "make-dir": "^3.0.2", + "pkg-dir": "^4.1.0" + } }, - "default-gateway": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-4.2.0.tgz", - "integrity": "sha512-h6sMrVB1VMWVrW13mSc6ia/DwYYw5MN6+exNu1OaJeFac5aSAvwM7lZ0NVfTABuSkQelr4h5oebg3KB1XPdjgA==", + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "requires": { - "execa": "^1.0.0", - "ip-regex": "^2.1.0" + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" } }, - "defer-to-connect": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz", - "integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==" - }, - "define-properties": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", - "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "flux": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/flux/-/flux-4.0.3.tgz", + "integrity": "sha512-yKAbrp7JhZhj6uiT1FTuVMlIAT1J4jqEyBpFApi1kxpGZCvacMVc/t1pMQyotqHhAgvoE3bNvAykhCo2CLjnYw==", "requires": { - "object-keys": "^1.0.12" + "fbemitter": "^3.0.0", + "fbjs": "^3.0.1" } }, - "define-property": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", - "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "follow-redirects": { + "version": "1.14.9", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.9.tgz", + "integrity": "sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w==" + }, + "foreach": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz", + "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=" + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==", + "dev": true + }, + "fork-ts-checker-webpack-plugin": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-6.5.2.tgz", + "integrity": "sha512-m5cUmF30xkZ7h4tWUgTAcEaKmUW7tfyUyTqNNOz7OxWJ0v1VWKTcOvH8FWHUwSjlW/356Ijc9vi3XfcPstpQKA==", "requires": { - "is-descriptor": "^1.0.2", - "isobject": "^3.0.1" + "@babel/code-frame": "^7.8.3", + "@types/json-schema": "^7.0.5", + "chalk": "^4.1.0", + "chokidar": "^3.4.2", + "cosmiconfig": "^6.0.0", + "deepmerge": "^4.2.2", + "fs-extra": "^9.0.0", + "glob": "^7.1.6", + "memfs": "^3.1.2", + "minimatch": "^3.0.4", + "schema-utils": "2.7.0", + "semver": "^7.3.2", + "tapable": "^1.0.0" }, "dependencies": { - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "requires": { - "kind-of": "^6.0.0" + "color-convert": "^2.0.1" } }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "requires": { - "kind-of": "^6.0.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" } }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "cosmiconfig": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-6.0.0.tgz", + "integrity": "sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg==", + "requires": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.1.0", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.7.2" + } + }, + "fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "requires": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "schema-utils": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.0.tgz", + "integrity": "sha512-0ilKFI6QQF5nxDZLFn2dMjvc4hjg/Wkg7rHd3jK6/A4a1Hl9VFdQWvgB1UMGoU94pad1P/8N7fMcEnLnSiju8A==", + "requires": { + "@types/json-schema": "^7.0.4", + "ajv": "^6.12.2", + "ajv-keywords": "^3.4.1" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" + "has-flag": "^4.0.0" } + }, + "tapable": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", + "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==" } } }, - "del": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/del/-/del-6.0.0.tgz", - "integrity": "sha512-1shh9DQ23L16oXSZKB2JxpL7iMy2E0S9d517ptA1P8iw0alkPtQcrKH7ru31rYtKwF499HkTu+DRzq3TCKDFRQ==", + "form-data": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", + "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==", + "dev": true, "requires": { - "globby": "^11.0.1", - "graceful-fs": "^4.2.4", - "is-glob": "^4.0.1", - "is-path-cwd": "^2.2.0", - "is-path-inside": "^3.0.2", - "p-map": "^4.0.0", - "rimraf": "^3.0.2", - "slash": "^3.0.0" + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" } }, - "delegates": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=" + "forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==" }, - "depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" + "fraction.js": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.2.0.tgz", + "integrity": "sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA==" }, - "des.js": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.1.tgz", - "integrity": "sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA==", - "requires": { - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0" - } + "fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" }, - "destroy": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", - "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" + "fs": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/fs/-/fs-0.0.2.tgz", + "integrity": "sha1-4fJE7zkzwbKmS9R5kTYGDQ9ZFPg=" }, - "detab": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/detab/-/detab-2.0.4.tgz", - "integrity": "sha512-8zdsQA5bIkoRECvCrNKPla84lyoR7DSAyf7p0YgXzBO9PDJx8KntPUay7NS6yp+KdxdVtiE5SpHKtbp2ZQyA9g==", + "fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, + "fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", "requires": { - "repeat-string": "^1.5.4" + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" } }, - "detect-libc": { + "fs-monkey": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", - "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=" + "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.3.tgz", + "integrity": "sha512-cybjIfiiE+pTWicSCLFHSrXZ6EilF30oh91FDP9S2B051prEa7QWfrVTQm10/dDpswBDXZugPa1Ogu8Yh+HV0Q==" }, - "detect-node": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", - "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==" + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" }, - "detect-port": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/detect-port/-/detect-port-1.3.0.tgz", - "integrity": "sha512-E+B1gzkl2gqxt1IhUzwjrxBKRqx1UzC3WLONHinn8S3T6lwV/agVCyitiFOsGJ/eYuEUBvD71MZHy3Pv1G9doQ==", + "fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "optional": true + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, + "gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", "requires": { - "address": "^1.0.1", - "debug": "^2.6.0" + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" }, "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", "requires": { - "ms": "2.0.0" + "number-is-nan": "^1.0.0" } }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "^2.0.0" + } } } }, - "diffie-hellman": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", - "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", + "gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==" + }, + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==" + }, + "get-intrinsic": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", + "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", "requires": { - "bn.js": "^4.1.0", - "miller-rabin": "^4.0.0", - "randombytes": "^2.0.0" - }, - "dependencies": { - "bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" - } + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1" } }, - "dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "requires": { - "path-type": "^4.0.0" - } + "get-own-enumerable-property-symbols": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz", + "integrity": "sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g==" + }, + "get-package-type": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", + "dev": true + }, + "get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==" }, - "dns-equal": { + "get-symbol-description": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz", - "integrity": "sha1-s55/HabrCnW6nBcySzR1PEfgZU0=" - }, - "dns-packet": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-1.3.4.tgz", - "integrity": "sha512-BQ6F4vycLXBvdrJZ6S3gZewt6rcrks9KBgM9vrhW+knGRqc8uEdT7fuCwloc7nny5xNoMJ17HGH0R/6fpo8ECA==", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", + "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", "requires": { - "ip": "^1.1.0", - "safe-buffer": "^5.0.1" + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" } }, - "dns-txt": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/dns-txt/-/dns-txt-2.0.2.tgz", - "integrity": "sha1-uR2Ab10nGI5Ks+fRB9iBocxGQrY=", + "getos": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/getos/-/getos-3.2.1.tgz", + "integrity": "sha512-U56CfOK17OKgTVqozZjUKNdkfEv6jk5WISBJ8SHoagjE6L69zOwl3Z+O8myjY9MEW3i2HPWQBt/LTbCgcC973Q==", + "dev": true, "requires": { - "buffer-indexof": "^1.0.0" + "async": "^3.2.0" + }, + "dependencies": { + "async": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", + "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==", + "dev": true + } } }, - "dom-converter": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz", - "integrity": "sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==", + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==", + "dev": true, "requires": { - "utila": "~0.4" + "assert-plus": "^1.0.0" } }, - "dom-serializer": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.3.2.tgz", - "integrity": "sha512-5c54Bk5Dw4qAxNOI1pFEizPSjVsx5+bpJKmL2kPn8JhBUq2q09tTCa3mjijun2NfK78NMouDYNMBkOrPZiS+ig==", + "gifwrap": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/gifwrap/-/gifwrap-0.9.4.tgz", + "integrity": "sha512-MDMwbhASQuVeD4JKd1fKgNgCRL3fGqMM4WaqpNhWO0JiMOAjbQdumbs4BbBZEy9/M00EHEjKN3HieVhCUlwjeQ==", "requires": { - "domelementtype": "^2.0.1", - "domhandler": "^4.2.0", - "entities": "^2.0.0" + "image-q": "^4.0.0", + "omggif": "^1.0.10" } }, - "dom-walk": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.2.tgz", - "integrity": "sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w==" + "github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha1-l/tdlr/eiXMxPyDoKI75oWf6ZM4=" }, - "domain-browser": { - "version": "4.22.0", - "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-4.22.0.tgz", - "integrity": "sha512-IGBwjF7tNk3cwypFNH/7bfzBcgSCbaMOD3GsaY1AU/JRrnHnYgEM0+9kQt52iZxjNsjBtJYtao146V+f8jFZNw==" + "github-slugger": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/github-slugger/-/github-slugger-1.4.0.tgz", + "integrity": "sha512-w0dzqw/nt51xMVmlaV1+JRzN+oCa1KfcgGEWhxUG16wbdA+Xnt/yoFO8Z8x/V82ZcZ0wy6ln9QDup5avbhiDhQ==" }, - "domelementtype": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz", - "integrity": "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A==" + "glob": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } }, - "domhandler": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.2.2.tgz", - "integrity": "sha512-PzE9aBMsdZO8TK4BnuJwH0QT41wgMbRzuZrHUcpYncEjmQazq8QEaBWgLG7ZyC/DAZKEgglpIA6j4Qn/HmxS3w==", + "glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "requires": { - "domelementtype": "^2.2.0" + "is-glob": "^4.0.1" } }, - "dompurify": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-2.3.3.tgz", - "integrity": "sha512-dqnqRkPMAjOZE0FogZ+ceJNM2dZ3V/yNOuFB7+39qpO93hHhfRpHw3heYQC7DPK9FqbQTfBKUJhiSfz4MvXYwg==" + "glob-to-regexp": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==" }, - "domutils": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", - "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", + "global": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/global/-/global-4.4.0.tgz", + "integrity": "sha512-wv/LAoHdRE3BeTGz53FAamhGlPLhlssK45usmGFThIi4XqnBmjKQ16u+RNbP7WvigRZDxUsM0J3gcQ5yicaL0w==", "requires": { - "dom-serializer": "^1.0.1", - "domelementtype": "^2.2.0", - "domhandler": "^4.2.0" + "min-document": "^2.19.0", + "process": "^0.11.10" } }, - "dot-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", - "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", + "global-dirs": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-3.0.0.tgz", + "integrity": "sha512-v8ho2DS5RiCjftj1nD9NmnfaOzTdud7RRnVd9kFNOjqZbISlx5DQ+OrTkywgd0dIt7oFCvKetZSHoHcP3sDdiA==", "requires": { - "no-case": "^3.0.4", - "tslib": "^2.0.3" + "ini": "2.0.0" + }, + "dependencies": { + "ini": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz", + "integrity": "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==" + } } }, - "dot-prop": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", - "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", + "global-modules": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz", + "integrity": "sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==", "requires": { - "is-obj": "^2.0.0" + "global-prefix": "^3.0.0" } }, - "duplexer": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", - "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==" - }, - "duplexer3": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", - "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=" - }, - "ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" - }, - "electron-to-chromium": { - "version": "1.3.867", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.867.tgz", - "integrity": "sha512-WbTXOv7hsLhjJyl7jBfDkioaY++iVVZomZ4dU6TMe/SzucV6mUAs2VZn/AehBwuZMiNEQDaPuTGn22YK5o+aDw==" - }, - "elliptic": { - "version": "6.5.4", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", - "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==", + "global-prefix": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz", + "integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==", "requires": { - "bn.js": "^4.11.9", - "brorand": "^1.1.0", - "hash.js": "^1.0.0", - "hmac-drbg": "^1.0.1", - "inherits": "^2.0.4", - "minimalistic-assert": "^1.0.1", - "minimalistic-crypto-utils": "^1.0.1" + "ini": "^1.3.5", + "kind-of": "^6.0.2", + "which": "^1.3.1" }, "dependencies": { - "bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "requires": { + "isexe": "^2.0.0" + } } } }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" - }, - "emojis-list": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", - "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==" - }, - "emoticon": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/emoticon/-/emoticon-3.2.0.tgz", - "integrity": "sha512-SNujglcLTTg+lDAcApPNgEdudaqQFiAbJCqzjNxJkvN9vAwCGi0uu8IUVvx+f16h+V44KCY6Y2yboroc9pilHg==" - }, - "encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" + "globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==" }, - "end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", "requires": { - "once": "^1.4.0" + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" } }, - "enhanced-resolve": { - "version": "5.8.3", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.8.3.tgz", - "integrity": "sha512-EGAbGvH7j7Xt2nc0E7D99La1OiEs8LnyimkRgwExpUMScN6O+3x9tIWs7PLQZVNx4YD+00skHXPXi1yQHpAmZA==", + "got": { + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", + "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==", "requires": { - "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" + "@sindresorhus/is": "^0.14.0", + "@szmarczak/http-timer": "^1.1.2", + "cacheable-request": "^6.0.0", + "decompress-response": "^3.3.0", + "duplexer3": "^0.1.4", + "get-stream": "^4.1.0", + "lowercase-keys": "^1.0.1", + "mimic-response": "^1.0.1", + "p-cancelable": "^1.0.0", + "to-readable-stream": "^1.0.0", + "url-parse-lax": "^3.0.0" + }, + "dependencies": { + "decompress-response": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", + "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", + "requires": { + "mimic-response": "^1.0.0" + } + }, + "get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "requires": { + "pump": "^3.0.0" + } + }, + "mimic-response": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==" + } } }, - "entities": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", - "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==" - }, - "errno": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz", - "integrity": "sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==", - "requires": { - "prr": "~1.0.1" - } + "graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" }, - "error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "gray-matter": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/gray-matter/-/gray-matter-4.0.3.tgz", + "integrity": "sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q==", "requires": { - "is-arrayish": "^0.2.1" + "js-yaml": "^3.13.1", + "kind-of": "^6.0.2", + "section-matter": "^1.0.0", + "strip-bom-string": "^1.0.0" + }, + "dependencies": { + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + } } }, - "es-abstract": { - "version": "1.19.1", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.19.1.tgz", - "integrity": "sha512-2vJ6tjA/UfqLm2MPs7jxVybLoB8i1t1Jd9R3kISld20sIxPcTbLuggQOUxeWeAvIUkduv/CfMjuh4WmiXr2v9w==", + "gzip-size": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-6.0.0.tgz", + "integrity": "sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q==", "requires": { - "call-bind": "^1.0.2", - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "get-intrinsic": "^1.1.1", - "get-symbol-description": "^1.0.0", - "has": "^1.0.3", - "has-symbols": "^1.0.2", - "internal-slot": "^1.0.3", - "is-callable": "^1.2.4", - "is-negative-zero": "^2.0.1", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.1", - "is-string": "^1.0.7", - "is-weakref": "^1.0.1", - "object-inspect": "^1.11.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.2", - "string.prototype.trimend": "^1.0.4", - "string.prototype.trimstart": "^1.0.4", - "unbox-primitive": "^1.0.1" + "duplexer": "^0.1.2" } }, - "es-module-lexer": { - "version": "0.9.3", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.9.3.tgz", - "integrity": "sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ==" + "handle-thing": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", + "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==" }, - "es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", "requires": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" + "function-bind": "^1.1.1" } }, - "es6-object-assign": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/es6-object-assign/-/es6-object-assign-1.1.0.tgz", - "integrity": "sha1-wsNYJlYkfDnqEHyx5mUrb58kUjw=" - }, - "es6-promise": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.3.1.tgz", - "integrity": "sha1-oIzd6EzNvzTQJ6FFG8kdS80ophM=" + "has-bigints": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", + "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==" }, - "escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==" + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" }, - "escape-goat": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-2.1.1.tgz", - "integrity": "sha512-8/uIhbG12Csjy2JEW7D9pHbreaVaS/OpN3ycnyvElTdwM5n6GY6W6e2IPemfvGZeUMqZ9A/3GqIZMgKnBhAw/Q==" + "has-property-descriptors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", + "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", + "requires": { + "get-intrinsic": "^1.1.1" + } }, - "escape-html": { + "has-symbols": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==" }, - "eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "has-tostringtag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", + "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", "requires": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" + "has-symbols": "^1.0.2" } }, - "esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=" }, - "esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "has-yarn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/has-yarn/-/has-yarn-2.1.0.tgz", + "integrity": "sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw==" + }, + "hash-base": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", + "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", "requires": { - "estraverse": "^5.2.0" + "inherits": "^2.0.4", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" }, "dependencies": { - "estraverse": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", - "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==" + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" } } }, - "estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==" - }, - "esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==" - }, - "eta": { - "version": "1.12.3", - "resolved": "https://registry.npmjs.org/eta/-/eta-1.12.3.tgz", - "integrity": "sha512-qHixwbDLtekO/d51Yr4glcaUJCIjGVJyTzuqV4GPlgZo1YpgOKG+avQynErZIYrfM6JIJdtiG2Kox8tbb+DoGg==" + "hash.js": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", + "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", + "requires": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" + } }, - "etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" + "hast-to-hyperscript": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/hast-to-hyperscript/-/hast-to-hyperscript-9.0.1.tgz", + "integrity": "sha512-zQgLKqF+O2F72S1aa4y2ivxzSlko3MAvxkwG8ehGmNiqd98BIN3JM1rAJPmplEyLmGLO2QZYJtIneOSZ2YbJuA==", + "requires": { + "@types/unist": "^2.0.3", + "comma-separated-tokens": "^1.0.0", + "property-information": "^5.3.0", + "space-separated-tokens": "^1.0.0", + "style-to-object": "^0.3.0", + "unist-util-is": "^4.0.0", + "web-namespaces": "^1.0.0" + } }, - "eval": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/eval/-/eval-0.1.6.tgz", - "integrity": "sha512-o0XUw+5OGkXw4pJZzQoXUk+H87DHuC+7ZE//oSrRGtatTmr12oTnLfg6QOq9DyTt0c/p4TwzgmkKrBzWTSizyQ==", + "hast-util-from-parse5": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-6.0.1.tgz", + "integrity": "sha512-jeJUWiN5pSxW12Rh01smtVkZgZr33wBokLzKLwinYOUfSzm1Nl/c3GUGebDyOKjdsRgMvoVbV0VpAcpjF4NrJA==", "requires": { - "require-like": ">= 0.1.1" + "@types/parse5": "^5.0.0", + "hastscript": "^6.0.0", + "property-information": "^5.0.0", + "vfile": "^4.0.0", + "vfile-location": "^3.2.0", + "web-namespaces": "^1.0.0" } }, - "eventemitter3": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", - "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==" + "hast-util-is-element": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/hast-util-is-element/-/hast-util-is-element-1.1.0.tgz", + "integrity": "sha512-oUmNua0bFbdrD/ELDSSEadRVtWZOf3iF6Lbv81naqsIV99RnSCieTbWuWCY8BAeEfKJTKl0gRdokv+dELutHGQ==" }, - "events": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==" + "hast-util-parse-selector": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-2.2.5.tgz", + "integrity": "sha512-7j6mrk/qqkSehsM92wQjdIgWM2/BW61u/53G6xmC8i1OmEdKLHbk419QKQUjz6LglWsfqoiHmyMRkP1BGjecNQ==" }, - "eventsource": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-1.1.0.tgz", - "integrity": "sha512-VSJjT5oCNrFvCS6igjzPAt5hBzQ2qPBFIbJ03zLI9SE0mxwZpMw6BfJrbFHm1a141AavMEB8JHmBhWAd66PfCg==", + "hast-util-raw": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/hast-util-raw/-/hast-util-raw-6.0.1.tgz", + "integrity": "sha512-ZMuiYA+UF7BXBtsTBNcLBF5HzXzkyE6MLzJnL605LKE8GJylNjGc4jjxazAHUtcwT5/CEt6afRKViYB4X66dig==", "requires": { - "original": "^1.0.0" + "@types/hast": "^2.0.0", + "hast-util-from-parse5": "^6.0.0", + "hast-util-to-parse5": "^6.0.0", + "html-void-elements": "^1.0.0", + "parse5": "^6.0.0", + "unist-util-position": "^3.0.0", + "vfile": "^4.0.0", + "web-namespaces": "^1.0.0", + "xtend": "^4.0.0", + "zwitch": "^1.0.0" } }, - "evp_bytestokey": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", - "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", + "hast-util-to-parse5": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/hast-util-to-parse5/-/hast-util-to-parse5-6.0.0.tgz", + "integrity": "sha512-Lu5m6Lgm/fWuz8eWnrKezHtVY83JeRGaNQ2kn9aJgqaxvVkFCZQBEhgodZUDUvoodgyROHDb3r5IxAEdl6suJQ==", "requires": { - "md5.js": "^1.3.4", - "safe-buffer": "^5.1.1" - } - }, - "execa": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", - "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", - "requires": { - "cross-spawn": "^6.0.0", - "get-stream": "^4.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" - }, - "dependencies": { - "cross-spawn": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", - "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", - "requires": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - } - }, - "path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=" - }, - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" - }, - "shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", - "requires": { - "shebang-regex": "^1.0.0" - } - }, - "shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=" - }, - "which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "requires": { - "isexe": "^2.0.0" - } - } + "hast-to-hyperscript": "^9.0.0", + "property-information": "^5.0.0", + "web-namespaces": "^1.0.0", + "xtend": "^4.0.0", + "zwitch": "^1.0.0" } }, - "exif-parser": { - "version": "0.1.12", - "resolved": "https://registry.npmjs.org/exif-parser/-/exif-parser-0.1.12.tgz", - "integrity": "sha1-WKnS1ywCwfbwKg70qRZicrd2CSI=" + "hast-util-to-text": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/hast-util-to-text/-/hast-util-to-text-2.0.1.tgz", + "integrity": "sha512-8nsgCARfs6VkwH2jJU9b8LNTuR4700na+0h3PqCaEk4MAnMDeu5P0tP8mjk9LLNGxIeQRLbiDbZVw6rku+pYsQ==", + "requires": { + "hast-util-is-element": "^1.0.0", + "repeat-string": "^1.0.0", + "unist-util-find-after": "^3.0.0" + } }, - "expand-brackets": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", - "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "hastscript": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/hastscript/-/hastscript-6.0.0.tgz", + "integrity": "sha512-nDM6bvd7lIqDUiYEiu5Sl/+6ReP0BMk/2f4U/Rooccxkj0P5nm+acM5PrGJ/t5I8qPGiqZSE6hVAwZEdZIvP4w==", "requires": { - "debug": "^2.3.3", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "posix-character-classes": "^0.1.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - }, - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - } + "@types/hast": "^2.0.0", + "comma-separated-tokens": "^1.0.0", + "hast-util-parse-selector": "^2.0.0", + "property-information": "^5.0.0", + "space-separated-tokens": "^1.0.0" } }, - "expand-template": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", - "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==" + "he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==" }, - "express": { - "version": "4.17.1", - "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", - "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", + "history": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/history/-/history-4.10.1.tgz", + "integrity": "sha512-36nwAD620w12kuzPAsyINPWJqlNbij+hpK1k9XRloDtym8mxzGYl2c17LnV6IAGB2Dmg4tEa7G7DlawS0+qjew==", "requires": { - "accepts": "~1.3.7", - "array-flatten": "1.1.1", - "body-parser": "1.19.0", - "content-disposition": "0.5.3", - "content-type": "~1.0.4", - "cookie": "0.4.0", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "~1.1.2", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "~1.1.2", - "fresh": "0.5.2", - "merge-descriptors": "1.0.1", - "methods": "~1.1.2", - "on-finished": "~2.3.0", - "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", - "proxy-addr": "~2.0.5", - "qs": "6.7.0", - "range-parser": "~1.2.1", - "safe-buffer": "5.1.2", - "send": "0.17.1", - "serve-static": "1.14.1", - "setprototypeof": "1.1.1", - "statuses": "~1.5.0", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - } + "@babel/runtime": "^7.1.2", + "loose-envify": "^1.2.0", + "resolve-pathname": "^3.0.0", + "tiny-invariant": "^1.0.2", + "tiny-warning": "^1.0.0", + "value-equal": "^1.0.1" } }, - "extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + "hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", + "requires": { + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" + } }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "hoist-non-react-statics": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", "requires": { - "is-extendable": "^0.1.0" + "react-is": "^16.7.0" + }, + "dependencies": { + "react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + } } }, - "extglob": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "hpack.js": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", + "integrity": "sha1-h3dMCUnlE/QuhFdbPEVoH63ioLI=", "requires": { - "array-unique": "^0.3.2", - "define-property": "^1.0.0", - "expand-brackets": "^2.1.4", - "extend-shallow": "^2.0.1", - "fragment-cache": "^0.2.1", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" + "inherits": "^2.0.1", + "obuf": "^1.0.0", + "readable-stream": "^2.0.1", + "wbuf": "^1.1.0" }, "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "is-accessor-descriptor": { + "isarray": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "requires": { - "kind-of": "^6.0.0" - } + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", "requires": { - "kind-of": "^6.0.0" + "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" } }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" + "safe-buffer": "~5.1.0" } } } }, - "fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" - }, - "fast-glob": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.7.tgz", - "integrity": "sha512-rYGMRwip6lUMvYD3BTScMwT1HtAs2d71SMv66Vrxs0IekGZEjhM0pcMfjQPnknBt2zeCwQMEupiN02ZP4DiT1Q==", + "html-encoding-sniffer": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz", + "integrity": "sha512-D5JbOMBIR/TVZkubHT+OyT2705QvogUW4IBn6nHd756OwieSF9aDYFj4dv6HHEVGYbHaLETa3WggZYWWMyy3ZQ==", + "dev": true, "requires": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" + "whatwg-encoding": "^1.0.5" } }, - "fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" + "html-entities": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.3.3.tgz", + "integrity": "sha512-DV5Ln36z34NNTDgnz0EWGBLZENelNAtkiFA4kyNOG2tDI6Mz1uSWiq1wAKdyjnJwyDiDO7Fa2SO1CTxPXL8VxA==" }, - "fast-safe-stringify": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", - "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==" + "html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true }, - "fast-url-parser": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/fast-url-parser/-/fast-url-parser-1.1.3.tgz", - "integrity": "sha1-9K8+qfNNiicc9YrSs3WfQx8LMY0=", + "html-minifier-terser": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", + "integrity": "sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw==", "requires": { - "punycode": "^1.3.2" + "camel-case": "^4.1.2", + "clean-css": "^5.2.2", + "commander": "^8.3.0", + "he": "^1.2.0", + "param-case": "^3.0.4", + "relateurl": "^0.2.7", + "terser": "^5.10.0" }, "dependencies": { - "punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" + "commander": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", + "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==" } } }, - "fastq": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", - "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", - "requires": { - "reusify": "^1.0.4" - } + "html-tags": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.2.0.tgz", + "integrity": "sha512-vy7ClnArOZwCnqZgvv+ddgHgJiAFXe3Ge9ML5/mBctVJoUoYPCdxVucOywjDARn6CVoh3dRSFdPHy2sX80L0Wg==" }, - "faye-websocket": { - "version": "0.11.4", - "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz", - "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==", + "html-void-elements": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-1.0.5.tgz", + "integrity": "sha512-uE/TxKuyNIcx44cIWnjr/rfIATDH7ZaOMmstu0CwhFG1Dunhlp4OC6/NMbhiwoq5BpW0ubi303qnEk/PZj614w==" + }, + "html-webpack-plugin": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.5.0.tgz", + "integrity": "sha512-sy88PC2cRTVxvETRgUHFrL4No3UxvcH8G1NepGhqaTT+GXN2kTamqasot0inS5hXeg1cMbFDt27zzo9p35lZVw==", "requires": { - "websocket-driver": ">=0.5.1" + "@types/html-minifier-terser": "^6.0.0", + "html-minifier-terser": "^6.0.2", + "lodash": "^4.17.21", + "pretty-error": "^4.0.0", + "tapable": "^2.0.0" } }, - "fbemitter": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/fbemitter/-/fbemitter-3.0.0.tgz", - "integrity": "sha512-KWKaceCwKQU0+HPoop6gn4eOHk50bBv/VxjJtGMfwmJt3D29JpN4H4eisCtIPA+a8GVBam+ldMMpMjJUvpDyHw==", + "htmlparser2": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", + "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", "requires": { - "fbjs": "^3.0.0" + "domelementtype": "^2.0.1", + "domhandler": "^4.0.0", + "domutils": "^2.5.2", + "entities": "^2.0.0" } }, - "fbjs": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/fbjs/-/fbjs-3.0.0.tgz", - "integrity": "sha512-dJd4PiDOFuhe7vk4F80Mba83Vr2QuK86FoxtgPmzBqEJahncp+13YCmfoa53KHCo6OnlXLG7eeMWPfB5CrpVKg==", + "http-cache-semantics": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", + "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==" + }, + "http-deceiver": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", + "integrity": "sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc=" + }, + "http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", "requires": { - "cross-fetch": "^3.0.4", - "fbjs-css-vars": "^1.0.0", - "loose-envify": "^1.0.0", - "object-assign": "^4.1.0", - "promise": "^7.1.1", - "setimmediate": "^1.0.5", - "ua-parser-js": "^0.7.18" + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" } }, - "fbjs-css-vars": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/fbjs-css-vars/-/fbjs-css-vars-1.0.2.tgz", - "integrity": "sha512-b2XGFAFdWZWg0phtAWLHCk836A1Xann+I+Dgd3Gk64MHKZO44FfoD1KxyvbSh0qZsIoXQGGlVztIY+oitJPpRQ==" + "http-parser-js": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.6.tgz", + "integrity": "sha512-vDlkRPDJn93swjcjqMSaGSPABbIarsr1TLAui/gLDXzV5VsJNdXNzMYDyNBLQkjWQCJ1uizu8T2oDMhmGt0PRA==" + }, + "http-proxy": { + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", + "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", + "requires": { + "eventemitter3": "^4.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" + } }, - "feed": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/feed/-/feed-4.2.2.tgz", - "integrity": "sha512-u5/sxGfiMfZNtJ3OvQpXcvotFpYkL0n9u9mM2vkui2nGo8b4wvDkJ8gAkYqbA8QpGyFCv3RK0Z+Iv+9veCS9bQ==", + "http-proxy-agent": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", + "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", + "dev": true, "requires": { - "xml-js": "^1.6.11" + "@tootallnate/once": "1", + "agent-base": "6", + "debug": "4" } }, - "figures": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", - "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", + "http-proxy-middleware": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.6.tgz", + "integrity": "sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw==", "requires": { - "escape-string-regexp": "^1.0.5" + "@types/http-proxy": "^1.17.8", + "http-proxy": "^1.18.1", + "is-glob": "^4.0.1", + "is-plain-obj": "^3.0.0", + "micromatch": "^4.0.2" + }, + "dependencies": { + "is-plain-obj": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz", + "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==" + } } }, - "file-loader": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-6.2.0.tgz", - "integrity": "sha512-qo3glqyTa61Ytg4u73GultjHGjdRyig3tG6lPtyX/jOEJvHif9uB0/OCI2Kif6ctF3caQTW2G5gym21oAsI4pw==", + "http-signature": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.3.6.tgz", + "integrity": "sha512-3adrsD6zqo4GsTqtO7FyrejHNv+NgiIfAfv68+jVlFmSr9OGy7zrxONceFRLKvnnZA5jbxQBX1u9PpB6Wi32Gw==", + "dev": true, "requires": { - "loader-utils": "^2.0.0", - "schema-utils": "^3.0.0" + "assert-plus": "^1.0.0", + "jsprim": "^2.0.2", + "sshpk": "^1.14.1" } }, - "file-type": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/file-type/-/file-type-9.0.0.tgz", - "integrity": "sha512-Qe/5NJrgIOlwijpq3B7BEpzPFcgzggOTagZmkXQY4LA6bsXKTUstK7Wp12lEJ/mLKTpvIZxmIuRcLYWT6ov9lw==" + "http2-client": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/http2-client/-/http2-client-1.3.5.tgz", + "integrity": "sha512-EC2utToWl4RKfs5zd36Mxq7nzHHBuomZboI0yYL6Y0RmBgT7Sgkq4rQ0ezFTYoIsSs7Tm9SJe+o2FcAg6GBhGA==" }, - "file-uri-to-path": { + "https-browserify": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", - "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", - "optional": true - }, - "filesize": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/filesize/-/filesize-6.1.0.tgz", - "integrity": "sha512-LpCHtPQ3sFx67z+uh2HnSyWSLLu5Jxo21795uRDuar/EOuYWXib5EmPaGIBuSnRqH2IODiKA2k5re/K9OnN/Yg==" + "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", + "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=" }, - "fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dev": true, "requires": { - "to-regex-range": "^5.0.1" + "agent-base": "6", + "debug": "4" } }, - "filter-obj": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/filter-obj/-/filter-obj-2.0.2.tgz", - "integrity": "sha512-lO3ttPjHZRfjMcxWKb1j1eDhTFsu4meeR3lnMcnBFhk6RuLhvEiuALu2TlfL310ph4lCYYwgF/ElIjdP739tdg==" + "human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==" }, - "finalhandler": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", - "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", "requires": { - "debug": "2.6.9", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "on-finished": "~2.3.0", - "parseurl": "~1.3.3", - "statuses": "~1.5.0", - "unpipe": "~1.0.0" + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "icss-utils": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-4.1.1.tgz", + "integrity": "sha512-4aFq7wvWyMHKgxsH8QQtGpvbASCf+eM3wPRLI6R+MgAnTCZ6STYsRvttLvRWK0Nfif5piF394St3HeJDaljGPA==", + "dev": true, + "requires": { + "postcss": "^7.0.14" }, "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, "requires": { - "ms": "2.0.0" + "picocolors": "^0.2.1", + "source-map": "^0.6.1" } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" } } }, - "find-cache-dir": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", - "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", + "ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" + }, + "ignore": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", + "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==" + }, + "image-q": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/image-q/-/image-q-4.0.0.tgz", + "integrity": "sha512-PfJGVgIfKQJuq3s0tTDOKtztksibuUEbJQIYT3by6wctQo+Rdlh7ef4evJ5NCdxY4CfMbvFkocEwbl4BF8RlJw==", "requires": { - "commondir": "^1.0.1", - "make-dir": "^3.0.2", - "pkg-dir": "^4.1.0" + "@types/node": "16.9.1" + }, + "dependencies": { + "@types/node": { + "version": "16.9.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.9.1.tgz", + "integrity": "sha512-QpLcX9ZSsq3YYUUnD3nFDY8H7wctAhQj/TFKL8Ya8v5fMm3CFXxo8zStsLAl780ltoYoo1WvKUVGBQK+1ifr7g==" + } } }, - "find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "image-size": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/image-size/-/image-size-1.0.1.tgz", + "integrity": "sha512-VAwkvNSNGClRw9mDHhc5Efax8PLlsOGcUTh0T/LIriC8vPA3U5PdqXWqkz406MoYHMKW8Uf9gWr05T/rYB44kQ==", "requires": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" + "queue": "6.0.2" } }, - "flux": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/flux/-/flux-4.0.2.tgz", - "integrity": "sha512-u/ucO5ezm3nBvdaSGkWpDlzCePoV+a9x3KHmy13TV/5MzOaCZDN8Mfd94jmf0nOi8ZZay+nOKbBUkOe2VNaupQ==", + "immer": { + "version": "9.0.12", + "resolved": "https://registry.npmjs.org/immer/-/immer-9.0.12.tgz", + "integrity": "sha512-lk7UNmSbAukB5B6dh9fnh5D0bJTOFKxVg2cyJWTYrWRfhLrLMBquONcUs3aFq507hNoIZEDDh8lb8UtOizSMhA==" + }, + "import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", "requires": { - "fbemitter": "^3.0.0", - "fbjs": "^3.0.0" + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" } }, - "follow-redirects": { - "version": "1.14.4", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.4.tgz", - "integrity": "sha512-zwGkiSXC1MUJG/qmeIFH2HBJx9u0V46QGUe3YR1fXG8bXQxq7fLj0RjLZQ5nubr9qNJUZrH+xUcwXEoXNpfS+g==" + "import-lazy": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz", + "integrity": "sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM=" }, - "for-in": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", - "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=" + "import-local": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", + "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", + "dev": true, + "requires": { + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + } }, - "foreach": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz", - "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=" + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=" }, - "fork-ts-checker-webpack-plugin": { - "version": "4.1.6", - "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-4.1.6.tgz", - "integrity": "sha512-DUxuQaKoqfNne8iikd14SAkh5uw4+8vNifp6gmA73yYNS6ywLIWSLD/n/mBzHQRpW3J7rbATEakmiA8JvkTyZw==", + "indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==" + }, + "infima": { + "version": "0.2.0-alpha.37", + "resolved": "https://registry.npmjs.org/infima/-/infima-0.2.0-alpha.37.tgz", + "integrity": "sha512-4GX7Baw+/lwS4PPW/UJNY89tWSvYG1DL6baKVdpK6mC593iRgMssxNtORMTFArLPJ/A/lzsGhRmx+z6MaMxj0Q==" + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", "requires": { - "@babel/code-frame": "^7.5.5", - "chalk": "^2.4.1", - "micromatch": "^3.1.10", - "minimatch": "^3.0.4", - "semver": "^5.6.0", - "tapable": "^1.0.0", - "worker-rpc": "^0.1.0" - }, - "dependencies": { - "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "requires": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "requires": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - }, - "dependencies": { - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "requires": { - "is-plain-object": "^2.0.4" - } - } - } - }, - "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - } - }, - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" - }, - "tapable": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", - "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==" - }, - "to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", - "requires": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" - } - } + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + }, + "inline-style-parser": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.1.1.tgz", + "integrity": "sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q==" + }, + "internal-slot": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz", + "integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==", + "requires": { + "get-intrinsic": "^1.1.0", + "has": "^1.0.3", + "side-channel": "^1.0.4" } }, - "forwarded": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", - "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==" - }, - "fraction.js": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.1.1.tgz", - "integrity": "sha512-MHOhvvxHTfRFpF1geTK9czMIZ6xclsEor2wkIGYYq+PxcQqT7vStJqjhe6S1TenZrMZzo+wlqOufBDVepUEgPg==" + "interpret": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", + "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==" }, - "fragment-cache": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", - "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", + "invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", "requires": { - "map-cache": "^0.2.2" + "loose-envify": "^1.0.0" } }, - "fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" + "ipaddr.js": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.0.1.tgz", + "integrity": "sha512-1qTgH9NG+IIJ4yfKs2e6Pp1bZg8wbDbKHT21HrLIeYBTRLgMYKnMTPAuI3Lcs61nfx5h1xlXnbJtH1kX5/d/ng==" }, - "fs-constants": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", - "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + "is-alphabetical": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-1.0.4.tgz", + "integrity": "sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg==" }, - "fs-extra": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.0.0.tgz", - "integrity": "sha512-C5owb14u9eJwizKGdchcDUQeFtlSHHthBk8pbX9Vc1PFZrLombudjDnNns88aYslCyF6IY5SUw3Roz6xShcEIQ==", + "is-alphanumerical": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-1.0.4.tgz", + "integrity": "sha512-UzoZUr+XfVz3t3v4KyGEniVL9BDRoQtY7tOyrRybkVNjDFWyo1yhXNGrrBTQxp3ib9BLAWs7k2YKBQsFRkZG9A==", "requires": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" + "is-alphabetical": "^1.0.0", + "is-decimal": "^1.0.0" } }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" - }, - "fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "optional": true - }, - "function-bind": { + "is-arguments": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" - }, - "gauge": { - "version": "2.7.4", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", - "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", + "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", "requires": { - "aproba": "^1.0.3", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.0", - "object-assign": "^4.1.0", - "signal-exit": "^3.0.0", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wide-align": "^1.1.0" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "requires": { - "ansi-regex": "^2.0.0" - } - } + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" } }, - "gensync": { - "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==" - }, - "get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==" + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=" }, - "get-intrinsic": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", - "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", + "is-bigint": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", "requires": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1" + "has-bigints": "^1.0.1" } }, - "get-own-enumerable-property-symbols": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz", - "integrity": "sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g==" - }, - "get-stream": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", - "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", "requires": { - "pump": "^3.0.0" + "binary-extensions": "^2.0.0" } }, - "get-symbol-description": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", - "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", + "is-boolean-object": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", "requires": { "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" + "has-tostringtag": "^1.0.0" } }, - "get-value": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", - "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=" + "is-buffer": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz", + "integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==" }, - "gifwrap": { - "version": "0.9.2", - "resolved": "https://registry.npmjs.org/gifwrap/-/gifwrap-0.9.2.tgz", - "integrity": "sha512-fcIswrPaiCDAyO8xnWvHSZdWChjKXUanKKpAiWWJ/UTkEi/aYKn5+90e7DE820zbEaVR9CE2y4z9bzhQijZ0BA==", + "is-callable": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz", + "integrity": "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==" + }, + "is-ci": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", + "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", "requires": { - "image-q": "^1.1.1", - "omggif": "^1.0.10" + "ci-info": "^2.0.0" + }, + "dependencies": { + "ci-info": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", + "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==" + } } }, - "github-from-package": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", - "integrity": "sha1-l/tdlr/eiXMxPyDoKI75oWf6ZM4=" - }, - "github-slugger": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/github-slugger/-/github-slugger-1.4.0.tgz", - "integrity": "sha512-w0dzqw/nt51xMVmlaV1+JRzN+oCa1KfcgGEWhxUG16wbdA+Xnt/yoFO8Z8x/V82ZcZ0wy6ln9QDup5avbhiDhQ==" - }, - "glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", + "is-core-module": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.9.0.tgz", + "integrity": "sha512-+5FPy5PnwmO3lvfMb0AsoPaBG+5KHUI0wYFXOtYPnVVVspTFUuMZNfNaNVRt3FZadstu2c8x23vykRW/NBoU6A==", "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "has": "^1.0.3" } }, - "glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "is-date-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", "requires": { - "is-glob": "^4.0.1" + "has-tostringtag": "^1.0.0" } }, - "glob-to-regexp": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", - "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==" + "is-decimal": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-1.0.4.tgz", + "integrity": "sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw==" }, - "global": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/global/-/global-4.4.0.tgz", - "integrity": "sha512-wv/LAoHdRE3BeTGz53FAamhGlPLhlssK45usmGFThIi4XqnBmjKQ16u+RNbP7WvigRZDxUsM0J3gcQ5yicaL0w==", + "is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==" + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=" + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" + }, + "is-function": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-function/-/is-function-1.0.2.tgz", + "integrity": "sha512-lw7DUp0aWXYg+CBCN+JKkcE0Q2RayZnSvnZBlwgxHBQhqt5pZNVy4Ri7H9GmmXkdu7LUthszM+Tor1u/2iBcpQ==" + }, + "is-generator-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", + "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", + "dev": true + }, + "is-generator-function": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", + "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", "requires": { - "min-document": "^2.19.0", - "process": "^0.11.10" + "has-tostringtag": "^1.0.0" } }, - "global-dirs": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-3.0.0.tgz", - "integrity": "sha512-v8ho2DS5RiCjftj1nD9NmnfaOzTdud7RRnVd9kFNOjqZbISlx5DQ+OrTkywgd0dIt7oFCvKetZSHoHcP3sDdiA==", + "is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", "requires": { - "ini": "2.0.0" - }, - "dependencies": { - "ini": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz", - "integrity": "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==" - } + "is-extglob": "^2.1.1" } }, - "global-modules": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz", - "integrity": "sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==", + "is-hexadecimal": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-1.0.4.tgz", + "integrity": "sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw==" + }, + "is-installed-globally": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.4.0.tgz", + "integrity": "sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ==", "requires": { - "global-prefix": "^3.0.0" + "global-dirs": "^3.0.0", + "is-path-inside": "^3.0.2" } }, - "global-prefix": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz", - "integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==", + "is-nan": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/is-nan/-/is-nan-1.3.2.tgz", + "integrity": "sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==", "requires": { - "ini": "^1.3.5", - "kind-of": "^6.0.2", - "which": "^1.3.1" - }, - "dependencies": { - "which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "requires": { - "isexe": "^2.0.0" - } - } + "call-bind": "^1.0.0", + "define-properties": "^1.1.3" } }, - "globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==" + "is-negative-zero": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", + "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==" }, - "globby": { - "version": "11.0.4", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.4.tgz", - "integrity": "sha512-9O4MVG9ioZJ08ffbcyVYyLOJLk5JQ688pJ4eMGLpdWLHq/Wr1D9BlriLQyL0E+jbkuePVZXYFj47QM/v093wHg==", + "is-npm": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-5.0.0.tgz", + "integrity": "sha512-WW/rQLOazUq+ST/bCAVBp/2oMERWLsR7OrKyt052dNDk4DHcDE0/7QSXITlmi+VBcV13DfIbysG3tZJm5RfdBA==" + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" + }, + "is-number-object": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", + "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", "requires": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.1.1", - "ignore": "^5.1.4", - "merge2": "^1.3.0", - "slash": "^3.0.0" + "has-tostringtag": "^1.0.0" } }, - "got": { - "version": "9.6.0", - "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", - "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==", + "is-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", + "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=" + }, + "is-path-cwd": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz", + "integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==" + }, + "is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==" + }, + "is-plain-obj": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", + "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==" + }, + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", "requires": { - "@sindresorhus/is": "^0.14.0", - "@szmarczak/http-timer": "^1.1.2", - "cacheable-request": "^6.0.0", - "decompress-response": "^3.3.0", - "duplexer3": "^0.1.4", - "get-stream": "^4.1.0", - "lowercase-keys": "^1.0.1", - "mimic-response": "^1.0.1", - "p-cancelable": "^1.0.0", - "to-readable-stream": "^1.0.0", - "url-parse-lax": "^3.0.0" + "isobject": "^3.0.1" } }, - "graceful-fs": { - "version": "4.2.8", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz", - "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==" + "is-potential-custom-element-name": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", + "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", + "dev": true }, - "gray-matter": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/gray-matter/-/gray-matter-4.0.3.tgz", - "integrity": "sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q==", + "is-regex": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", "requires": { - "js-yaml": "^3.13.1", - "kind-of": "^6.0.2", - "section-matter": "^1.0.0", - "strip-bom-string": "^1.0.0" + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" } }, - "gzip-size": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-5.1.1.tgz", - "integrity": "sha512-FNHi6mmoHvs1mxZAds4PpdCS6QG8B4C1krxJsMutgxl5t3+GlRTzzI3NEkifXx2pVsOvJdOGSmIgDhQ55FwdPA==", + "is-regexp": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz", + "integrity": "sha1-/S2INUXEa6xaYz57mgnof6LLUGk=" + }, + "is-root": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-root/-/is-root-2.1.0.tgz", + "integrity": "sha512-AGOriNp96vNBd3HtU+RzFEc75FfR5ymiYv8E553I71SCeXBiMsVDUtdio1OEFvrPyLIQ9tVR5RxXIFe5PUFjMg==" + }, + "is-shared-array-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", + "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", "requires": { - "duplexer": "^0.1.1", - "pify": "^4.0.1" + "call-bind": "^1.0.2" } }, - "handle-thing": { + "is-stream": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", - "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==" + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==" }, - "has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", "requires": { - "function-bind": "^1.1.1" + "has-tostringtag": "^1.0.0" } }, - "has-bigints": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz", - "integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==" - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" - }, - "has-symbols": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", - "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==" - }, - "has-tostringtag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", - "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "is-symbol": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", "requires": { "has-symbols": "^1.0.2" } }, - "has-unicode": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=" + "is-typed-array": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.8.tgz", + "integrity": "sha512-HqH41TNZq2fgtGT8WHVFVJhBVGuY3AnP3Q36K8JKXUxSxRgk/d+7NjmwG2vo2mYmXK8UYZKu0qH8bVP5gEisjA==", + "requires": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "es-abstract": "^1.18.5", + "foreach": "^2.0.5", + "has-tostringtag": "^1.0.0" + } }, - "has-value": { + "is-typedarray": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", - "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" + }, + "is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "dev": true + }, + "is-weakref": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", + "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", "requires": { - "get-value": "^2.0.6", - "has-values": "^1.0.0", - "isobject": "^3.0.0" + "call-bind": "^1.0.2" } }, - "has-values": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", - "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", + "is-whitespace-character": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-whitespace-character/-/is-whitespace-character-1.0.4.tgz", + "integrity": "sha512-SDweEzfIZM0SJV0EUga669UTKlmL0Pq8Lno0QDQsPnvECB3IM2aP0gdx5TrU0A01MAPfViaZiI2V1QMZLaKK5w==" + }, + "is-word-character": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-word-character/-/is-word-character-1.0.4.tgz", + "integrity": "sha512-5SMO8RVennx3nZrqtKwCGyyetPE9VDba5ugvKLaD4KopPG5kR4mQ7tNt/r7feL5yt5h3lpuBbIUmCOG2eSzXHA==" + }, + "is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", "requires": { - "is-number": "^3.0.0", - "kind-of": "^4.0.0" - }, - "dependencies": { - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "kind-of": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", - "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", - "requires": { - "is-buffer": "^1.1.5" - } - } + "is-docker": "^2.0.0" } }, - "has-yarn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/has-yarn/-/has-yarn-2.1.0.tgz", - "integrity": "sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw==" + "is-yarn-global": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/is-yarn-global/-/is-yarn-global-0.3.0.tgz", + "integrity": "sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw==" + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==", + "dev": true }, - "hash-base": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", - "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", + "istanbul-lib-coverage": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", + "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", + "dev": true + }, + "istanbul-lib-instrument": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.0.tgz", + "integrity": "sha512-6Lthe1hqXHBNsqvgDzGO6l03XNeu3CrG4RqQ1KM9+l5+jNGpEJfIELx1NS3SEHmJQA8np/u+E4EPRKRiu6m19A==", + "dev": true, "requires": { - "inherits": "^2.0.4", - "readable-stream": "^3.6.0", - "safe-buffer": "^5.2.0" + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" }, "dependencies": { - "safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true } } }, - "hash.js": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", - "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", - "requires": { - "inherits": "^2.0.3", - "minimalistic-assert": "^1.0.1" - } - }, - "hast-to-hyperscript": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/hast-to-hyperscript/-/hast-to-hyperscript-9.0.1.tgz", - "integrity": "sha512-zQgLKqF+O2F72S1aa4y2ivxzSlko3MAvxkwG8ehGmNiqd98BIN3JM1rAJPmplEyLmGLO2QZYJtIneOSZ2YbJuA==", - "requires": { - "@types/unist": "^2.0.3", - "comma-separated-tokens": "^1.0.0", - "property-information": "^5.3.0", - "space-separated-tokens": "^1.0.0", - "style-to-object": "^0.3.0", - "unist-util-is": "^4.0.0", - "web-namespaces": "^1.0.0" - } - }, - "hast-util-from-parse5": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-5.0.3.tgz", - "integrity": "sha512-gOc8UB99F6eWVWFtM9jUikjN7QkWxB3nY0df5Z0Zq1/Nkwl5V4hAAsl0tmwlgWl/1shlTF8DnNYLO8X6wRV9pA==", - "requires": { - "ccount": "^1.0.3", - "hastscript": "^5.0.0", - "property-information": "^5.0.0", - "web-namespaces": "^1.1.2", - "xtend": "^4.0.1" - } - }, - "hast-util-parse-selector": { - "version": "2.2.5", - "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-2.2.5.tgz", - "integrity": "sha512-7j6mrk/qqkSehsM92wQjdIgWM2/BW61u/53G6xmC8i1OmEdKLHbk419QKQUjz6LglWsfqoiHmyMRkP1BGjecNQ==" - }, - "hast-util-raw": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/hast-util-raw/-/hast-util-raw-6.0.1.tgz", - "integrity": "sha512-ZMuiYA+UF7BXBtsTBNcLBF5HzXzkyE6MLzJnL605LKE8GJylNjGc4jjxazAHUtcwT5/CEt6afRKViYB4X66dig==", + "istanbul-lib-report": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", + "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==", + "dev": true, "requires": { - "@types/hast": "^2.0.0", - "hast-util-from-parse5": "^6.0.0", - "hast-util-to-parse5": "^6.0.0", - "html-void-elements": "^1.0.0", - "parse5": "^6.0.0", - "unist-util-position": "^3.0.0", - "vfile": "^4.0.0", - "web-namespaces": "^1.0.0", - "xtend": "^4.0.0", - "zwitch": "^1.0.0" + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^3.0.0", + "supports-color": "^7.1.0" }, "dependencies": { - "hast-util-from-parse5": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-6.0.1.tgz", - "integrity": "sha512-jeJUWiN5pSxW12Rh01smtVkZgZr33wBokLzKLwinYOUfSzm1Nl/c3GUGebDyOKjdsRgMvoVbV0VpAcpjF4NrJA==", - "requires": { - "@types/parse5": "^5.0.0", - "hastscript": "^6.0.0", - "property-information": "^5.0.0", - "vfile": "^4.0.0", - "vfile-location": "^3.2.0", - "web-namespaces": "^1.0.0" - } + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true }, - "hastscript": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/hastscript/-/hastscript-6.0.0.tgz", - "integrity": "sha512-nDM6bvd7lIqDUiYEiu5Sl/+6ReP0BMk/2f4U/Rooccxkj0P5nm+acM5PrGJ/t5I8qPGiqZSE6hVAwZEdZIvP4w==", + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, "requires": { - "@types/hast": "^2.0.0", - "comma-separated-tokens": "^1.0.0", - "hast-util-parse-selector": "^2.0.0", - "property-information": "^5.0.0", - "space-separated-tokens": "^1.0.0" + "has-flag": "^4.0.0" } - }, - "parse5": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", - "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==" } } }, - "hast-util-to-parse5": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/hast-util-to-parse5/-/hast-util-to-parse5-6.0.0.tgz", - "integrity": "sha512-Lu5m6Lgm/fWuz8eWnrKezHtVY83JeRGaNQ2kn9aJgqaxvVkFCZQBEhgodZUDUvoodgyROHDb3r5IxAEdl6suJQ==", - "requires": { - "hast-to-hyperscript": "^9.0.0", - "property-information": "^5.0.0", - "web-namespaces": "^1.0.0", - "xtend": "^4.0.0", - "zwitch": "^1.0.0" - } - }, - "hastscript": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/hastscript/-/hastscript-5.1.2.tgz", - "integrity": "sha512-WlztFuK+Lrvi3EggsqOkQ52rKbxkXL3RwB6t5lwoa8QLMemoWfBuL43eDrwOamJyR7uKQKdmKYaBH1NZBiIRrQ==", + "istanbul-lib-source-maps": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", + "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", + "dev": true, "requires": { - "comma-separated-tokens": "^1.0.0", - "hast-util-parse-selector": "^2.0.0", - "property-information": "^5.0.0", - "space-separated-tokens": "^1.0.0" + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0", + "source-map": "^0.6.1" } }, - "he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==" - }, - "history": { - "version": "4.10.1", - "resolved": "https://registry.npmjs.org/history/-/history-4.10.1.tgz", - "integrity": "sha512-36nwAD620w12kuzPAsyINPWJqlNbij+hpK1k9XRloDtym8mxzGYl2c17LnV6IAGB2Dmg4tEa7G7DlawS0+qjew==", + "istanbul-reports": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.4.tgz", + "integrity": "sha512-r1/DshN4KSE7xWEknZLLLLDn5CJybV3nw01VTkp6D5jzLuELlcbudfj/eSQFvrKsJuTVCGnePO7ho82Nw9zzfw==", + "dev": true, "requires": { - "@babel/runtime": "^7.1.2", - "loose-envify": "^1.2.0", - "resolve-pathname": "^3.0.0", - "tiny-invariant": "^1.0.2", - "tiny-warning": "^1.0.0", - "value-equal": "^1.0.1" + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" } }, - "hmac-drbg": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", - "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", + "jest": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest/-/jest-27.5.1.tgz", + "integrity": "sha512-Yn0mADZB89zTtjkPJEXwrac3LHudkQMR+Paqa8uxJHCBr9agxztUifWCyiYrjhMPBoUVBjyny0I7XH6ozDr7QQ==", + "dev": true, "requires": { - "hash.js": "^1.0.3", - "minimalistic-assert": "^1.0.0", - "minimalistic-crypto-utils": "^1.0.1" + "@jest/core": "^27.5.1", + "import-local": "^3.0.2", + "jest-cli": "^27.5.1" } }, - "hoist-non-react-statics": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", - "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", + "jest-changed-files": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-27.5.1.tgz", + "integrity": "sha512-buBLMiByfWGCoMsLLzGUUSpAmIAGnbR2KJoMN10ziLhOLvP4e0SlypHnAel8iqQXTrcbmfEY9sSqae5sgUsTvw==", + "dev": true, "requires": { - "react-is": "^16.7.0" + "@jest/types": "^27.5.1", + "execa": "^5.0.0", + "throat": "^6.0.1" } }, - "hpack.js": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", - "integrity": "sha1-h3dMCUnlE/QuhFdbPEVoH63ioLI=", + "jest-circus": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-27.5.1.tgz", + "integrity": "sha512-D95R7x5UtlMA5iBYsOHFFbMD/GVA4R/Kdq15f7xYWUfWHBto9NYRsOvnSauTgdF+ogCpJ4tyKOXhUifxS65gdw==", + "dev": true, "requires": { - "inherits": "^2.0.1", - "obuf": "^1.0.0", - "readable-stream": "^2.0.1", - "wbuf": "^1.1.0" + "@jest/environment": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "co": "^4.6.0", + "dedent": "^0.7.0", + "expect": "^27.5.1", + "is-generator-fn": "^2.0.0", + "jest-each": "^27.5.1", + "jest-matcher-utils": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-runtime": "^27.5.1", + "jest-snapshot": "^27.5.1", + "jest-util": "^27.5.1", + "pretty-format": "^27.5.1", + "slash": "^3.0.0", + "stack-utils": "^2.0.3", + "throat": "^6.0.1" }, "dependencies": { - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, "requires": { - "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" + "color-convert": "^2.0.1" } }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "requires": { - "safe-buffer": "~5.1.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" } } } }, - "html-entities": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-1.4.0.tgz", - "integrity": "sha512-8nxjcBcd8wovbeKx7h3wTji4e6+rhaVuPNpMqwWgnHh+N9ToqsCs6XztWRBPQ+UtzsoMAdKZtUENoVzU/EMtZA==" - }, - "html-minifier-terser": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-5.1.1.tgz", - "integrity": "sha512-ZPr5MNObqnV/T9akshPKbVgyOqLmy+Bxo7juKCfTfnjNniTAMdy4hz21YQqoofMBJD2kdREaqPPdThoR78Tgxg==", + "jest-cli": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-27.5.1.tgz", + "integrity": "sha512-Hc6HOOwYq4/74/c62dEE3r5elx8wjYqxY0r0G/nFrLDPMFRu6RA/u8qINOIkvhxG7mMQ5EJsOGfRpI8L6eFUVw==", + "dev": true, "requires": { - "camel-case": "^4.1.1", - "clean-css": "^4.2.3", - "commander": "^4.1.1", - "he": "^1.2.0", - "param-case": "^3.0.3", - "relateurl": "^0.2.7", - "terser": "^4.6.3" + "@jest/core": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/types": "^27.5.1", + "chalk": "^4.0.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "import-local": "^3.0.2", + "jest-config": "^27.5.1", + "jest-util": "^27.5.1", + "jest-validate": "^27.5.1", + "prompts": "^2.0.1", + "yargs": "^16.2.0" }, "dependencies": { - "clean-css": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.3.tgz", - "integrity": "sha512-VcMWDN54ZN/DS+g58HYL5/n4Zrqe8vHJpGA8KdgUXFU4fuP/aHNw8eld9SyEIyabIMJX/0RaY/fplOo5hYLSFA==", + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, "requires": { - "source-map": "~0.6.0" + "color-name": "~1.1.4" } }, - "commander": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", - "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==" + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" - }, - "terser": { - "version": "4.8.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-4.8.0.tgz", - "integrity": "sha512-EAPipTNeWsb/3wLPeup1tVPaXfIaU68xMnVdPafIL1TV05OhASArYyIfFvnvJCNrR2NIOvDVNNTFRa+Re2MWyw==", - "requires": { - "commander": "^2.20.0", - "source-map": "~0.6.1", - "source-map-support": "~0.5.12" - }, - "dependencies": { - "commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" - } + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" } } } }, - "html-tags": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.1.0.tgz", - "integrity": "sha512-1qYz89hW3lFDEazhjW0yVAV87lw8lVkrJocr72XmBkMKsoSVJCQx3W8BXsC7hO2qAt8BoVjYjtAcZ9perqGnNg==" - }, - "html-void-elements": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-1.0.5.tgz", - "integrity": "sha512-uE/TxKuyNIcx44cIWnjr/rfIATDH7ZaOMmstu0CwhFG1Dunhlp4OC6/NMbhiwoq5BpW0ubi303qnEk/PZj614w==" - }, - "html-webpack-plugin": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.3.2.tgz", - "integrity": "sha512-HvB33boVNCz2lTyBsSiMffsJ+m0YLIQ+pskblXgN9fnjS1BgEcuAfdInfXfGrkdXV406k9FiDi86eVCDBgJOyQ==", - "requires": { - "@types/html-minifier-terser": "^5.0.0", - "html-minifier-terser": "^5.0.1", - "lodash": "^4.17.21", - "pretty-error": "^3.0.4", - "tapable": "^2.0.0" - } - }, - "htmlparser2": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.1.tgz", - "integrity": "sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ==", + "jest-config": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-27.5.1.tgz", + "integrity": "sha512-5sAsjm6tGdsVbW9ahcChPAFCk4IlkQUknH5AvKjuLTSlcO/wCZKyFdn7Rg0EkC+OGgWODEy2hDpWB1PgzH0JNA==", + "dev": true, "requires": { - "domelementtype": "^1.3.1", - "domhandler": "^2.3.0", - "domutils": "^1.5.1", - "entities": "^1.1.1", - "inherits": "^2.0.1", - "readable-stream": "^3.1.1" + "@babel/core": "^7.8.0", + "@jest/test-sequencer": "^27.5.1", + "@jest/types": "^27.5.1", + "babel-jest": "^27.5.1", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "deepmerge": "^4.2.2", + "glob": "^7.1.1", + "graceful-fs": "^4.2.9", + "jest-circus": "^27.5.1", + "jest-environment-jsdom": "^27.5.1", + "jest-environment-node": "^27.5.1", + "jest-get-type": "^27.5.1", + "jest-jasmine2": "^27.5.1", + "jest-regex-util": "^27.5.1", + "jest-resolve": "^27.5.1", + "jest-runner": "^27.5.1", + "jest-util": "^27.5.1", + "jest-validate": "^27.5.1", + "micromatch": "^4.0.4", + "parse-json": "^5.2.0", + "pretty-format": "^27.5.1", + "slash": "^3.0.0", + "strip-json-comments": "^3.1.1" }, "dependencies": { - "dom-serializer": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz", - "integrity": "sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==", + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, "requires": { - "domelementtype": "^2.0.1", - "entities": "^2.0.0" - }, - "dependencies": { - "domelementtype": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz", - "integrity": "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A==" - }, - "entities": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", - "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==" - } + "color-convert": "^2.0.1" } }, - "domelementtype": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", - "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==" - }, - "domhandler": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz", - "integrity": "sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==", + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "requires": { - "domelementtype": "1" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" } }, - "domutils": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz", - "integrity": "sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==", + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, "requires": { - "dom-serializer": "0", - "domelementtype": "1" + "color-name": "~1.1.4" } }, - "entities": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", - "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==" + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } } } }, - "http-cache-semantics": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", - "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==" - }, - "http-deceiver": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", - "integrity": "sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc=" - }, - "http-errors": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", - "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", + "jest-diff": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-27.5.1.tgz", + "integrity": "sha512-m0NvkX55LDt9T4mctTEgnZk3fmEg3NRYutvMPWM/0iPnkFj2wIeF45O1718cMSOFO1vINkqmxqD8vE37uTEbqw==", + "dev": true, "requires": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.1", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.0" + "chalk": "^4.0.0", + "diff-sequences": "^27.5.1", + "jest-get-type": "^27.5.1", + "pretty-format": "^27.5.1" }, "dependencies": { - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" - } - } - }, - "http-parser-js": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.3.tgz", - "integrity": "sha512-t7hjvef/5HEK7RWTdUzVUhl8zkEu+LlaE0IYzdMuvbSDipxBRpOn4Uhw8ZyECEa808iVT8XCjzo6xmYt4CiLZg==" - }, - "http-proxy": { - "version": "1.18.1", - "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", - "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", - "requires": { - "eventemitter3": "^4.0.0", - "follow-redirects": "^1.0.0", - "requires-port": "^1.0.0" - } - }, - "http-proxy-middleware": { - "version": "0.19.1", - "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-0.19.1.tgz", - "integrity": "sha512-yHYTgWMQO8VvwNS22eLLloAkvungsKdKTLO8AJlftYIKNfJr3GK3zK0ZCfzDDGUBttdGc8xFy1mCitvNKQtC3Q==", - "requires": { - "http-proxy": "^1.17.0", - "is-glob": "^4.0.0", - "lodash": "^4.17.11", - "micromatch": "^3.1.10" - }, - "dependencies": { - "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "requires": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, "requires": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - }, - "dependencies": { - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "requires": { - "is-plain-object": "^2.0.4" - } - } + "color-convert": "^2.0.1" } }, - "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "requires": { - "is-extendable": "^0.1.0" - } - } + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" } }, - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "^1.1.5" - } - } + "color-name": "~1.1.4" } }, - "micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - } + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true }, - "to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, "requires": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" + "has-flag": "^4.0.0" } - } - } - }, - "http2-client": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/http2-client/-/http2-client-1.3.5.tgz", - "integrity": "sha512-EC2utToWl4RKfs5zd36Mxq7nzHHBuomZboI0yYL6Y0RmBgT7Sgkq4rQ0ezFTYoIsSs7Tm9SJe+o2FcAg6GBhGA==" - }, - "https-browserify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", - "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=" - }, - "human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==" - }, - "iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, - "icss-utils": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", - "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", - "requires": {} - }, - "ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" - }, - "ignore": { - "version": "5.1.8", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", - "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==" - }, - "image-q": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/image-q/-/image-q-1.1.1.tgz", - "integrity": "sha1-/IQJlmRGC5DKhi2TALa/u7+/gFY=" - }, - "immer": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/immer/-/immer-8.0.1.tgz", - "integrity": "sha512-aqXhGP7//Gui2+UrEtvxZxSquQVXTpZ7KDxfCcKAF3Vysvw0CViVaW9RZ1j1xlIYqaaaipBoqdqeibkc18PNvA==" + } + } }, - "import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "jest-docblock": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-27.5.1.tgz", + "integrity": "sha512-rl7hlABeTsRYxKiUfpHrQrG4e2obOiTQWfMEH3PxPjOtdsfLQO4ReWSZaQ7DETm4xu07rl4q/h4zcKXyU0/OzQ==", + "dev": true, "requires": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" + "detect-newline": "^3.0.0" } }, - "import-lazy": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz", - "integrity": "sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM=" - }, - "import-local": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-2.0.0.tgz", - "integrity": "sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ==", + "jest-each": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-27.5.1.tgz", + "integrity": "sha512-1Ff6p+FbhT/bXQnEouYy00bkNSY7OUpfIcmdl8vZ31A1UUaurOLPA8a8BbJOF2RDUElwJhmeaV7LnagI+5UwNQ==", + "dev": true, "requires": { - "pkg-dir": "^3.0.0", - "resolve-cwd": "^2.0.0" + "@jest/types": "^27.5.1", + "chalk": "^4.0.0", + "jest-get-type": "^27.5.1", + "jest-util": "^27.5.1", + "pretty-format": "^27.5.1" }, "dependencies": { - "find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, "requires": { - "locate-path": "^3.0.0" + "color-convert": "^2.0.1" } }, - "locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "requires": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" } }, - "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, "requires": { - "p-try": "^2.0.0" + "color-name": "~1.1.4" } }, - "p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "requires": { - "p-limit": "^2.0.0" - } + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true }, - "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=" + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true }, - "pkg-dir": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", - "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, "requires": { - "find-up": "^3.0.0" + "has-flag": "^4.0.0" } } } }, - "imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=" - }, - "indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==" - }, - "infima": { - "version": "0.2.0-alpha.33", - "resolved": "https://registry.npmjs.org/infima/-/infima-0.2.0-alpha.33.tgz", - "integrity": "sha512-iLZI8/vGTbbhbeFhlWv1zwvrqfNDLAayuEdqZqNqCyGuh0IW469dRIRm0FLZ98YyLikt2njzuKfy6xUrBWRXcg==" - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "jest-environment-jsdom": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-27.5.1.tgz", + "integrity": "sha512-TFBvkTC1Hnnnrka/fUb56atfDtJ9VMZ94JkjTbggl1PEpwrYtUBKMezB3inLmWqQsXYLcMwNoDQwoBTAvFfsfw==", + "dev": true, "requires": { - "once": "^1.3.0", - "wrappy": "1" + "@jest/environment": "^27.5.1", + "@jest/fake-timers": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "jest-mock": "^27.5.1", + "jest-util": "^27.5.1", + "jsdom": "^16.6.0" } }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" - }, - "inline-style-parser": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.1.1.tgz", - "integrity": "sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q==" - }, - "internal-ip": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/internal-ip/-/internal-ip-4.3.0.tgz", - "integrity": "sha512-S1zBo1D6zcsyuC6PMmY5+55YMILQ9av8lotMx447Bq6SAgo/sDK6y6uUKmuYhW7eacnIhFfsPmCNYdDzsnnDCg==", + "jest-environment-node": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-27.5.1.tgz", + "integrity": "sha512-Jt4ZUnxdOsTGwSRAfKEnE6BcwsSPNOijjwifq5sDFSA2kesnXTvNqKHYgM0hDq3549Uf/KzdXNYn4wMZJPlFLw==", + "dev": true, "requires": { - "default-gateway": "^4.2.0", - "ipaddr.js": "^1.9.0" + "@jest/environment": "^27.5.1", + "@jest/fake-timers": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "jest-mock": "^27.5.1", + "jest-util": "^27.5.1" } }, - "internal-slot": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz", - "integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==", + "jest-get-type": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-27.5.1.tgz", + "integrity": "sha512-2KY95ksYSaK7DMBWQn6dQz3kqAf3BB64y2udeG+hv4KfSOb9qwcYQstTJc1KCbsix+wLZWZYN8t7nwX3GOBLRw==", + "dev": true + }, + "jest-haste-map": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-27.5.1.tgz", + "integrity": "sha512-7GgkZ4Fw4NFbMSDSpZwXeBiIbx+t/46nJ2QitkOjvwPYyZmqttu2TDSimMHP1EkPOi4xUZAN1doE5Vd25H4Jng==", + "dev": true, "requires": { - "get-intrinsic": "^1.1.0", - "has": "^1.0.3", - "side-channel": "^1.0.4" + "@jest/types": "^27.5.1", + "@types/graceful-fs": "^4.1.2", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "fsevents": "^2.3.2", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^27.5.1", + "jest-serializer": "^27.5.1", + "jest-util": "^27.5.1", + "jest-worker": "^27.5.1", + "micromatch": "^4.0.4", + "walker": "^1.0.7" } }, - "interpret": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", - "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==" - }, - "ip": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", - "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=" - }, - "ip-regex": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-2.1.0.tgz", - "integrity": "sha1-+ni/XS5pE8kRzp+BnuUUa7bYROk=" - }, - "ipaddr.js": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", - "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" - }, - "is-absolute-url": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-3.0.3.tgz", - "integrity": "sha512-opmNIX7uFnS96NtPmhWQgQx6/NYFgsUXYMllcfzwWKUMwfo8kku1TvE6hkNcH+Q1ts5cMVrsY7j0bxXQDciu9Q==" - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "jest-jasmine2": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-27.5.1.tgz", + "integrity": "sha512-jtq7VVyG8SqAorDpApwiJJImd0V2wv1xzdheGHRGyuT7gZm6gG47QEskOlzsN1PG/6WNaCo5pmwMHDf3AkG2pQ==", + "dev": true, "requires": { - "kind-of": "^3.0.2" + "@jest/environment": "^27.5.1", + "@jest/source-map": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "co": "^4.6.0", + "expect": "^27.5.1", + "is-generator-fn": "^2.0.0", + "jest-each": "^27.5.1", + "jest-matcher-utils": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-runtime": "^27.5.1", + "jest-snapshot": "^27.5.1", + "jest-util": "^27.5.1", + "pretty-format": "^27.5.1", + "throat": "^6.0.1" }, "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, "requires": { - "is-buffer": "^1.1.5" + "has-flag": "^4.0.0" } } } }, - "is-alphabetical": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-1.0.4.tgz", - "integrity": "sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg==" - }, - "is-alphanumerical": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-1.0.4.tgz", - "integrity": "sha512-UzoZUr+XfVz3t3v4KyGEniVL9BDRoQtY7tOyrRybkVNjDFWyo1yhXNGrrBTQxp3ib9BLAWs7k2YKBQsFRkZG9A==", - "requires": { - "is-alphabetical": "^1.0.0", - "is-decimal": "^1.0.0" - } - }, - "is-arguments": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", - "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", - "requires": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - } - }, - "is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=" - }, - "is-bigint": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", - "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", - "requires": { - "has-bigints": "^1.0.1" - } - }, - "is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "requires": { - "binary-extensions": "^2.0.0" - } - }, - "is-boolean-object": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", - "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "jest-leak-detector": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-27.5.1.tgz", + "integrity": "sha512-POXfWAMvfU6WMUXftV4HolnJfnPOGEu10fscNCA76KBpRRhcMN2c8d3iT2pxQS3HLbA+5X4sOUPzYO2NUyIlHQ==", + "dev": true, "requires": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" + "jest-get-type": "^27.5.1", + "pretty-format": "^27.5.1" } }, - "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" - }, - "is-callable": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz", - "integrity": "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==" - }, - "is-ci": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", - "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", + "jest-matcher-utils": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-27.5.1.tgz", + "integrity": "sha512-z2uTx/T6LBaCoNWNFWwChLBKYxTMcGBRjAt+2SbP929/Fflb9aa5LGma654Rz8z9HLxsrUaYzxE9T/EFIL/PAw==", + "dev": true, "requires": { - "ci-info": "^2.0.0" + "chalk": "^4.0.0", + "jest-diff": "^27.5.1", + "jest-get-type": "^27.5.1", + "pretty-format": "^27.5.1" }, "dependencies": { - "ci-info": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", - "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==" + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } } } }, - "is-core-module": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.7.0.tgz", - "integrity": "sha512-ByY+tjCciCr+9nLryBYcSD50EOGWt95c7tIsKTG1J2ixKKXPvF7Ej3AVd+UfDydAJom3biBGDBALaO79ktwgEQ==", - "requires": { - "has": "^1.0.3" - } - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "jest-message-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-27.5.1.tgz", + "integrity": "sha512-rMyFe1+jnyAAf+NHwTclDz0eAaLkVDdKVHHBFWsBWHnnh5YeJMNWWsv7AbFYXfK3oTqvL7VTWkhNLu1jX24D+g==", + "dev": true, "requires": { - "kind-of": "^3.0.2" + "@babel/code-frame": "^7.12.13", + "@jest/types": "^27.5.1", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^27.5.1", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" }, "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, "requires": { - "is-buffer": "^1.1.5" + "has-flag": "^4.0.0" } } } }, - "is-date-object": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", - "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "jest-mock": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-27.5.1.tgz", + "integrity": "sha512-K4jKbY1d4ENhbrG2zuPWaQBvDly+iZ2yAW+T1fATN78hc0sInwn7wZB8XtlNnvHug5RMwV897Xm4LqmPM4e2Og==", + "dev": true, "requires": { - "has-tostringtag": "^1.0.0" + "@jest/types": "^27.5.1", + "@types/node": "*" } }, - "is-decimal": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-1.0.4.tgz", - "integrity": "sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw==" + "jest-pnp-resolver": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.2.tgz", + "integrity": "sha512-olV41bKSMm8BdnuMsewT4jqlZ8+3TCARAXjZGT9jcoSnrfUnRCqnMoF9XEeoWjbzObpqF9dRhHQj0Xb9QdF6/w==", + "dev": true, + "requires": {} + }, + "jest-regex-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-27.5.1.tgz", + "integrity": "sha512-4bfKq2zie+x16okqDXjXn9ql2B0dScQu+vcwe4TvFVhkVyuWLqpZrZtXxLLWoXYgn0E87I6r6GRYHF7wFZBUvg==", + "dev": true }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "jest-resolve": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-27.5.1.tgz", + "integrity": "sha512-FFDy8/9E6CV83IMbDpcjOhumAQPDyETnU2KZ1O98DwTnz8AOBsW/Xv3GySr1mOZdItLR+zDZ7I/UdTFbgSOVCw==", + "dev": true, "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" + "@jest/types": "^27.5.1", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^27.5.1", + "jest-pnp-resolver": "^1.2.2", + "jest-util": "^27.5.1", + "jest-validate": "^27.5.1", + "resolve": "^1.20.0", + "resolve.exports": "^1.1.0", + "slash": "^3.0.0" }, "dependencies": { - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } } } }, - "is-docker": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", - "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==" - }, - "is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=" - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" - }, - "is-function": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-function/-/is-function-1.0.2.tgz", - "integrity": "sha512-lw7DUp0aWXYg+CBCN+JKkcE0Q2RayZnSvnZBlwgxHBQhqt5pZNVy4Ri7H9GmmXkdu7LUthszM+Tor1u/2iBcpQ==" - }, - "is-generator-function": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", - "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", - "requires": { - "has-tostringtag": "^1.0.0" - } - }, - "is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "requires": { - "is-extglob": "^2.1.1" - } - }, - "is-hexadecimal": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-1.0.4.tgz", - "integrity": "sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw==" - }, - "is-installed-globally": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.4.0.tgz", - "integrity": "sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ==", - "requires": { - "global-dirs": "^3.0.0", - "is-path-inside": "^3.0.2" - } - }, - "is-nan": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/is-nan/-/is-nan-1.3.2.tgz", - "integrity": "sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==", + "jest-resolve-dependencies": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-27.5.1.tgz", + "integrity": "sha512-QQOOdY4PE39iawDn5rzbIePNigfe5B9Z91GDD1ae/xNDlu9kaat8QQ5EKnNmVWPV54hUdxCVwwj6YMgR2O7IOg==", + "dev": true, "requires": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3" + "@jest/types": "^27.5.1", + "jest-regex-util": "^27.5.1", + "jest-snapshot": "^27.5.1" } }, - "is-negative-zero": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.1.tgz", - "integrity": "sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w==" - }, - "is-npm": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-5.0.0.tgz", - "integrity": "sha512-WW/rQLOazUq+ST/bCAVBp/2oMERWLsR7OrKyt052dNDk4DHcDE0/7QSXITlmi+VBcV13DfIbysG3tZJm5RfdBA==" - }, - "is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" - }, - "is-number-object": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.6.tgz", - "integrity": "sha512-bEVOqiRcvo3zO1+G2lVMy+gkkEm9Yh7cDMRusKKu5ZJKPUYSJwICTKZrNKHA2EbSP0Tu0+6B/emsYNHZyn6K8g==", + "jest-runner": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-27.5.1.tgz", + "integrity": "sha512-g4NPsM4mFCOwFKXO4p/H/kWGdJp9V8kURY2lX8Me2drgXqG7rrZAx5kv+5H7wtt/cdFIjhqYx1HrlqWHaOvDaQ==", + "dev": true, "requires": { - "has-tostringtag": "^1.0.0" + "@jest/console": "^27.5.1", + "@jest/environment": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "emittery": "^0.8.1", + "graceful-fs": "^4.2.9", + "jest-docblock": "^27.5.1", + "jest-environment-jsdom": "^27.5.1", + "jest-environment-node": "^27.5.1", + "jest-haste-map": "^27.5.1", + "jest-leak-detector": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-resolve": "^27.5.1", + "jest-runtime": "^27.5.1", + "jest-util": "^27.5.1", + "jest-worker": "^27.5.1", + "source-map-support": "^0.5.6", + "throat": "^6.0.1" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } } }, - "is-obj": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", - "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==" - }, - "is-path-cwd": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz", - "integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==" - }, - "is-path-in-cwd": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-2.1.0.tgz", - "integrity": "sha512-rNocXHgipO+rvnP6dk3zI20RpOtrAM/kzbB258Uw5BWr3TpXi861yzjo16Dn4hUox07iw5AyeMLHWsujkjzvRQ==", + "jest-runtime": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-27.5.1.tgz", + "integrity": "sha512-o7gxw3Gf+H2IGt8fv0RiyE1+r83FJBRruoA+FXrlHw6xEyBsU8ugA6IPfTdVyA0w8HClpbK+DGJxH59UrNMx8A==", + "dev": true, "requires": { - "is-path-inside": "^2.1.0" + "@jest/environment": "^27.5.1", + "@jest/fake-timers": "^27.5.1", + "@jest/globals": "^27.5.1", + "@jest/source-map": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", + "chalk": "^4.0.0", + "cjs-module-lexer": "^1.0.0", + "collect-v8-coverage": "^1.0.0", + "execa": "^5.0.0", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-mock": "^27.5.1", + "jest-regex-util": "^27.5.1", + "jest-resolve": "^27.5.1", + "jest-snapshot": "^27.5.1", + "jest-util": "^27.5.1", + "slash": "^3.0.0", + "strip-bom": "^4.0.0" }, "dependencies": { - "is-path-inside": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-2.1.0.tgz", - "integrity": "sha512-wiyhTzfDWsvwAW53OBWF5zuvaOGlZ6PwYxAbPVDhpm+gM09xKQGjBq/8uYN12aDvMxnAnq3dxTyoSoRNmg5YFg==", + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, "requires": { - "path-is-inside": "^1.0.2" + "has-flag": "^4.0.0" } } } }, - "is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==" - }, - "is-plain-obj": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", - "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==" - }, - "is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "requires": { - "isobject": "^3.0.1" - } - }, - "is-regex": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", - "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", - "requires": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - } - }, - "is-regexp": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz", - "integrity": "sha1-/S2INUXEa6xaYz57mgnof6LLUGk=" - }, - "is-resolvable": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz", - "integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==" - }, - "is-root": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-root/-/is-root-2.1.0.tgz", - "integrity": "sha512-AGOriNp96vNBd3HtU+RzFEc75FfR5ymiYv8E553I71SCeXBiMsVDUtdio1OEFvrPyLIQ9tVR5RxXIFe5PUFjMg==" - }, - "is-shared-array-buffer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.1.tgz", - "integrity": "sha512-IU0NmyknYZN0rChcKhRO1X8LYz5Isj/Fsqh8NJOSf+N/hCOTwy29F32Ik7a+QszE63IdvmwdTPDd6cZ5pg4cwA==" - }, - "is-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" - }, - "is-string": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", - "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "jest-serializer": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-27.5.1.tgz", + "integrity": "sha512-jZCyo6iIxO1aqUxpuBlwTDMkzOAJS4a3eYz3YzgxxVQFwLeSA7Jfq5cbqCY+JLvTDrWirgusI/0KwxKMgrdf7w==", + "dev": true, "requires": { - "has-tostringtag": "^1.0.0" + "@types/node": "*", + "graceful-fs": "^4.2.9" } }, - "is-symbol": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", - "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "jest-snapshot": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-27.5.1.tgz", + "integrity": "sha512-yYykXI5a0I31xX67mgeLw1DZ0bJB+gpq5IpSuCAoyDi0+BhgU/RIrL+RTzDmkNTchvDFWKP8lp+w/42Z3us5sA==", + "dev": true, "requires": { - "has-symbols": "^1.0.2" + "@babel/core": "^7.7.2", + "@babel/generator": "^7.7.2", + "@babel/plugin-syntax-typescript": "^7.7.2", + "@babel/traverse": "^7.7.2", + "@babel/types": "^7.0.0", + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/babel__traverse": "^7.0.4", + "@types/prettier": "^2.1.5", + "babel-preset-current-node-syntax": "^1.0.0", + "chalk": "^4.0.0", + "expect": "^27.5.1", + "graceful-fs": "^4.2.9", + "jest-diff": "^27.5.1", + "jest-get-type": "^27.5.1", + "jest-haste-map": "^27.5.1", + "jest-matcher-utils": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-util": "^27.5.1", + "natural-compare": "^1.4.0", + "pretty-format": "^27.5.1", + "semver": "^7.3.2" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } } }, - "is-typed-array": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.8.tgz", - "integrity": "sha512-HqH41TNZq2fgtGT8WHVFVJhBVGuY3AnP3Q36K8JKXUxSxRgk/d+7NjmwG2vo2mYmXK8UYZKu0qH8bVP5gEisjA==", + "jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "dev": true, "requires": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "es-abstract": "^1.18.5", - "foreach": "^2.0.5", - "has-tostringtag": "^1.0.0" + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } } }, - "is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" - }, - "is-weakref": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.1.tgz", - "integrity": "sha512-b2jKc2pQZjaeFYWEf7ScFj+Be1I+PXmlu572Q8coTXZ+LD/QQZ7ShPMst8h16riVgyXTQwUsFEl74mDvc/3MHQ==", + "jest-validate": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-27.5.1.tgz", + "integrity": "sha512-thkNli0LYTmOI1tDB3FI1S1RTp/Bqyd9pTarJwL87OIBFuqEb5Apv5EaApEudYg4g86e3CT6kM0RowkhtEnCBQ==", + "dev": true, "requires": { - "call-bind": "^1.0.0" + "@jest/types": "^27.5.1", + "camelcase": "^6.2.0", + "chalk": "^4.0.0", + "jest-get-type": "^27.5.1", + "leven": "^3.1.0", + "pretty-format": "^27.5.1" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } } }, - "is-whitespace-character": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-whitespace-character/-/is-whitespace-character-1.0.4.tgz", - "integrity": "sha512-SDweEzfIZM0SJV0EUga669UTKlmL0Pq8Lno0QDQsPnvECB3IM2aP0gdx5TrU0A01MAPfViaZiI2V1QMZLaKK5w==" - }, - "is-windows": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", - "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==" - }, - "is-word-character": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-word-character/-/is-word-character-1.0.4.tgz", - "integrity": "sha512-5SMO8RVennx3nZrqtKwCGyyetPE9VDba5ugvKLaD4KopPG5kR4mQ7tNt/r7feL5yt5h3lpuBbIUmCOG2eSzXHA==" - }, - "is-wsl": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", - "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "jest-watcher": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-27.5.1.tgz", + "integrity": "sha512-z676SuD6Z8o8qbmEGhoEUFOM1+jfEiL3DXHK/xgEiG2EyNYfFG60jluWcupY6dATjfEsKQuibReS1djInQnoVw==", + "dev": true, "requires": { - "is-docker": "^2.0.0" + "@jest/test-result": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "jest-util": "^27.5.1", + "string-length": "^4.0.1" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } } }, - "is-yarn-global": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/is-yarn-global/-/is-yarn-global-0.3.0.tgz", - "integrity": "sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw==" - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - }, - "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" - }, "jest-worker": { - "version": "27.2.5", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.2.5.tgz", - "integrity": "sha512-HTjEPZtcNKZ4LnhSp02NEH4vE+5OpJ0EsOWYvGQpHgUMLngydESAAMH5Wd/asPf29+XUDQZszxpLg1BkIIA2aw==", + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", + "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", "requires": { "@types/node": "*", "merge-stream": "^2.0.0", @@ -24624,13 +32764,13 @@ } }, "joi": { - "version": "17.4.2", - "resolved": "https://registry.npmjs.org/joi/-/joi-17.4.2.tgz", - "integrity": "sha512-Lm56PP+n0+Z2A2rfRvsfWVDXGEWjXxatPopkQ8qQ5mxCEhwHG+Ettgg5o98FFaxilOxozoa14cFhrE/hOzh/Nw==", + "version": "17.6.0", + "resolved": "https://registry.npmjs.org/joi/-/joi-17.6.0.tgz", + "integrity": "sha512-OX5dG6DTbcr/kbMFj0KGYxuew69HPcAE3K/sZpEV2nP6e/j/C0HV+HNiBPCASxdx5T7DMoa0s8UeHWMnb6n2zw==", "requires": { "@hapi/hoek": "^9.0.0", "@hapi/topo": "^5.0.0", - "@sideway/address": "^4.1.0", + "@sideway/address": "^4.1.3", "@sideway/formula": "^3.0.0", "@sideway/pinpoint": "^2.0.0" } @@ -24651,12 +32791,52 @@ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" }, "js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" + "argparse": "^2.0.1" + } + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==", + "dev": true + }, + "jsdom": { + "version": "16.7.0", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-16.7.0.tgz", + "integrity": "sha512-u9Smc2G1USStM+s/x1ru5Sxrl6mPYCbByG1U/hUmqaVsm4tbNyS7CicOSRyuGQYZhTu0h84qkZZQ/I+dzizSVw==", + "dev": true, + "requires": { + "abab": "^2.0.5", + "acorn": "^8.2.4", + "acorn-globals": "^6.0.0", + "cssom": "^0.4.4", + "cssstyle": "^2.3.0", + "data-urls": "^2.0.0", + "decimal.js": "^10.2.1", + "domexception": "^2.0.1", + "escodegen": "^2.0.0", + "form-data": "^3.0.0", + "html-encoding-sniffer": "^2.0.1", + "http-proxy-agent": "^4.0.1", + "https-proxy-agent": "^5.0.0", + "is-potential-custom-element-name": "^1.0.1", + "nwsapi": "^2.2.0", + "parse5": "6.0.1", + "saxes": "^5.0.1", + "symbol-tree": "^3.2.4", + "tough-cookie": "^4.0.0", + "w3c-hr-time": "^1.0.2", + "w3c-xmlserializer": "^2.0.0", + "webidl-conversions": "^6.1.0", + "whatwg-encoding": "^1.0.5", + "whatwg-mimetype": "^2.3.0", + "whatwg-url": "^8.5.0", + "ws": "^7.4.6", + "xml-name-validator": "^3.0.0" } }, "jsesc": { @@ -24680,30 +32860,34 @@ "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" }, "json-pointer": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/json-pointer/-/json-pointer-0.6.1.tgz", - "integrity": "sha512-3OvjqKdCBvH41DLpV4iSt6v2XhZXV1bPB4OROuknvUXI7ZQNofieCPkmE26stEJ9zdQuvIxDHCuYhfgxFAAs+Q==", + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/json-pointer/-/json-pointer-0.6.2.tgz", + "integrity": "sha512-vLWcKbOaXlO+jvRy4qNd+TI1QUPZzfJj1tpJ3vAXDych5XJf93ftpUKe5pKCrzyIIwgBJcOcCVRUfqQP25afBw==", "requires": { "foreach": "^2.0.4" } }, + "json-schema": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", + "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", + "dev": true + }, "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" }, - "json3": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/json3/-/json3-3.3.3.tgz", - "integrity": "sha512-c7/8mbUsKigAbLkD5B010BK4D9LZm7A1pNItkEwiUZRpIN66exu/e7YQWysGun+TRKaJp8MhemM+VkfWv42aCA==" + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", + "dev": true }, "json5": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz", - "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==", - "requires": { - "minimist": "^1.2.5" - } + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz", + "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==" }, "jsonfile": { "version": "6.1.0", @@ -24714,6 +32898,33 @@ "universalify": "^2.0.0" } }, + "jsprim": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-2.0.2.tgz", + "integrity": "sha512-gqXddjPqQ6G40VdnI6T6yObEC+pDNvyP95wdQhkWkg7crHH3km5qP1FsOXEkzEQwnz6gz5qGTn1c2Y52wP3OyQ==", + "dev": true, + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.4.0", + "verror": "1.10.0" + } + }, + "katex": { + "version": "0.13.24", + "resolved": "https://registry.npmjs.org/katex/-/katex-0.13.24.tgz", + "integrity": "sha512-jZxYuKCma3VS5UuxOx/rFV1QyGSl3Uy/i0kTJF3HgQ5xMinCQVF8Zd4bMY/9aI9b9A2pjIBOsjSSm68ykTAr8w==", + "requires": { + "commander": "^8.0.0" + }, + "dependencies": { + "commander": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", + "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==" + } + } + }, "keyv": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", @@ -24722,11 +32933,6 @@ "json-buffer": "3.0.0" } }, - "killable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/killable/-/killable-1.0.1.tgz", - "integrity": "sha512-LzqtLKlUwirEUyl/nicirVmNiPvYs7l5n8wOPP7fyJVpUPkvCnW/vuiXGpylGUlnPDnB7311rARzAt3Mhswpjg==" - }, "kind-of": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", @@ -24738,9 +32944,9 @@ "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==" }, "klona": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/klona/-/klona-2.0.4.tgz", - "integrity": "sha512-ZRbnvdg/NxqzC7L9Uyqzf4psi1OM4Cuc+sJAkQPjO6XkQIJTNbfK2Rsmbw8fx1p2mkZdp2FZYo2+LwXYY/uwIA==" + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/klona/-/klona-2.0.5.tgz", + "integrity": "sha512-pJiBpiXMbt7dkzXe8Ghj/u4FfXOOa98fPW+bihOJ4SjnoijweJrNThJfd3ifXpXhREjpoF2mZVH1GfS9LV3kHQ==" }, "latest-version": { "version": "5.1.0", @@ -24750,20 +32956,112 @@ "package-json": "^6.3.0" } }, + "lazy-ass": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/lazy-ass/-/lazy-ass-1.6.0.tgz", + "integrity": "sha512-cc8oEVoctTvsFZ/Oje/kGnHbpWHYBe8IAJe4C0QNc3t8uM/0Y8+erSz/7Y1ALuXTEZTMvxXwO6YbX1ey3ujiZw==", + "dev": true + }, "leven": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==" }, + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==", + "dev": true, + "requires": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + } + }, "lilconfig": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.0.3.tgz", - "integrity": "sha512-EHKqr/+ZvdKCifpNrJCKxBTgk5XupZA3y/aCPY9mxfgBzmgh93Mt/WqjjQ38oMxXuvDokaKiM3lAgvSH2sjtHg==" + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.0.5.tgz", + "integrity": "sha512-xaYmXZtTHPAw5m+xLN8ab9C+3a8YmV3asNSPOATITbtwrfbwaLJj8h66H1WMIpALCkqsIzK3h7oQ+PdX+LQ9Eg==" }, "lines-and-columns": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.1.6.tgz", - "integrity": "sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=" + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==" + }, + "listr2": { + "version": "3.14.0", + "resolved": "https://registry.npmjs.org/listr2/-/listr2-3.14.0.tgz", + "integrity": "sha512-TyWI8G99GX9GjE54cJ+RrNMcIFBfwMPxc3XTFiAYGN4s10hWROGtOg7+O6u6LE3mNkyld7RSLE6nrKBvTfcs3g==", + "dev": true, + "requires": { + "cli-truncate": "^2.1.0", + "colorette": "^2.0.16", + "log-update": "^4.0.0", + "p-map": "^4.0.0", + "rfdc": "^1.3.0", + "rxjs": "^7.5.1", + "through": "^2.3.8", + "wrap-ansi": "^7.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "colorette": { + "version": "2.0.19", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.19.tgz", + "integrity": "sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ==", + "dev": true + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + } + } }, "load-bmfont": { "version": "1.4.1", @@ -24781,14 +33079,14 @@ } }, "loader-runner": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.2.0.tgz", - "integrity": "sha512-92+huvxMvYlMzMt0iIOukcwYBFpkYJdpl2xsZ7LrlayO7E8SOv+JJUEK17B/dJIHAOLMfh2dZZ/Y18WgmGtYNw==" + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", + "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==" }, "loader-utils": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz", - "integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.2.tgz", + "integrity": "sha512-TM57VeHptv569d/GKh6TAYdzKblwDNiumOdkFnejjD0XwTH87K90w3O7AiJRqdQoXygvi1VQTJTLGhJl7WqA7A==", "requires": { "big.js": "^5.2.2", "emojis-list": "^3.0.0", @@ -24873,6 +33171,12 @@ "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==" }, + "lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==", + "dev": true + }, "lodash.pick": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/lodash.pick/-/lodash.pick-4.4.0.tgz", @@ -24893,15 +33197,153 @@ "resolved": "https://registry.npmjs.org/lodash.some/-/lodash.some-4.6.0.tgz", "integrity": "sha1-G7nzFO9ri63tE7VJFpsqlF62jk0=" }, + "lodash.sortby": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", + "integrity": "sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==" + }, "lodash.uniq": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", "integrity": "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=" }, - "loglevel": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.7.1.tgz", - "integrity": "sha512-Hesni4s5UkWkwCGJMQGAh71PaLUmKFM60dHvq0zi/vDhhrzuk+4GgNbTXJ12YYQJn6ZKBDNIjYcuQGKudvqrIw==" + "log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "dev": true, + "requires": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "log-update": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-4.0.0.tgz", + "integrity": "sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==", + "dev": true, + "requires": { + "ansi-escapes": "^4.3.0", + "cli-cursor": "^3.1.0", + "slice-ansi": "^4.0.0", + "wrap-ansi": "^6.2.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + } + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + } + } }, "loose-envify": { "version": "1.4.0", @@ -24937,6 +33379,12 @@ "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz", "integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==" }, + "lz-string": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.4.4.tgz", + "integrity": "sha512-0ckx7ZHRPqb0oUm8zNr+90mtf9DQB60H1wMCjBtfi62Kl3a7JbHob6gA2bC+xRvZoOL+1hzUK8jeuEIQE8svEQ==", + "dev": true + }, "make-dir": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", @@ -24952,17 +33400,13 @@ } } }, - "map-cache": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", - "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=" - }, - "map-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", - "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", + "makeerror": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", + "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", + "dev": true, "requires": { - "object-visit": "^1.0.0" + "tmpl": "1.0.5" } }, "mark.js": { @@ -24976,9 +33420,9 @@ "integrity": "sha512-8z4efJYk43E0upd0NbVXwgSTQs6cT3T06etieCMEg7dRbzCbxUCK/GHlX8mhHRDcp+OLlHkPKsvqQTCvsRl2cg==" }, "marked": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/marked/-/marked-0.7.0.tgz", - "integrity": "sha512-c+yYdCZJQrsRjTPhUx7VKkApw9bwDkNbHUKo1ovgcfDjb2kc8rLuRbIFyXL5WOEUwzSSKo3IXpph2K6DqB/KZg==" + "version": "4.0.15", + "resolved": "https://registry.npmjs.org/marked/-/marked-4.0.15.tgz", + "integrity": "sha512-esX5lPdTfG4p8LDkv+obbRCyOKzB+820ZZyMOXJZygZBHrH9b3xXR64X4kT3sPe9Nx8qQXbmcz6kFSMt4Nfk6Q==" }, "md5.js": { "version": "1.3.5", @@ -25027,9 +33471,9 @@ "integrity": "sha512-AW4DRS3QbBayY/jJmD8437V1Gombjf8RSOUCMFBuo5iHi58AGEgVCKQ+ezHkZZDpAQS75hcBMpLqjpJTjtUL7w==" }, "mdn-data": { - "version": "2.0.14", - "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz", - "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==" + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.4.tgz", + "integrity": "sha512-iV3XNKw06j5Q7mi6h+9vbx23Tv7JkjEVgKHW4pimwyDGWm0OIQntJJ+u1C6mg6mK1EaTv42XQ7w76yuzH7M2cA==" }, "mdurl": { "version": "1.0.1", @@ -25041,42 +33485,12 @@ "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" }, - "memoize-one": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.2.1.tgz", - "integrity": "sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q==" - }, - "memory-fs": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", - "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=", + "memfs": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.4.1.tgz", + "integrity": "sha512-1c9VPVvW5P7I85c35zAdEr1TD5+F11IToIHIlrVIcflfnzPkJa0ZoYEoEdYDP8KgPFoSZ/opDrUsAoZWym3mtw==", "requires": { - "errno": "^0.1.3", - "readable-stream": "^2.0.1" - }, - "dependencies": { - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } - } + "fs-monkey": "1.0.3" } }, "merge-descriptors": { @@ -25099,18 +33513,13 @@ "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" }, - "microevent.ts": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/microevent.ts/-/microevent.ts-0.1.1.tgz", - "integrity": "sha512-jo1OfR4TaEwd5HOrt5+tAZ9mqT4jmpNAusXtyfNzqVm9uiSYFZlKM1wYL4oU7azZW/PxQW53wM0S6OR1JHNa2g==" - }, "micromatch": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", - "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", "requires": { - "braces": "^3.0.1", - "picomatch": "^2.2.3" + "braces": "^3.0.2", + "picomatch": "^2.3.1" } }, "miller-rabin": { @@ -25135,16 +33544,16 @@ "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" }, "mime-db": { - "version": "1.50.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.50.0.tgz", - "integrity": "sha512-9tMZCDlYHqeERXEHO9f/hKfNXhre5dK2eE/krIvUjZbS2KPcqGDfNShIWS1uW9XOTKQKqK6qbeOci18rbfW77A==" + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" }, "mime-types": { - "version": "2.1.33", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.33.tgz", - "integrity": "sha512-plLElXp7pRDd0bNZHw+nMd52vRYjLwQjygaNg7ddJ2uJtTlmnTCjWuPKxVu6//AdaRuME84SvLW91sIkBqGT0g==", + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", "requires": { - "mime-db": "1.50.0" + "mime-db": "1.52.0" } }, "mimic-fn": { @@ -25153,9 +33562,9 @@ "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==" }, "mimic-response": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", - "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==" + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==" }, "min-document": { "version": "2.19.0", @@ -25165,6 +33574,12 @@ "dom-walk": "^0.1.0" } }, + "min-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", + "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", + "dev": true + }, "mini-create-react-context": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/mini-create-react-context/-/mini-create-react-context-0.4.1.tgz", @@ -25175,27 +33590,41 @@ } }, "mini-css-extract-plugin": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-1.6.2.tgz", - "integrity": "sha512-WhDvO3SjGm40oV5y26GjMJYjd2UMqrLAGKy5YS2/3QKJy2F7jgynuHTir/tgUUOiNQu5saXHdc8reo7YuhhT4Q==", + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.6.0.tgz", + "integrity": "sha512-ndG8nxCEnAemsg4FSgS+yNyHKgkTB4nPKqCOgh65j3/30qqC5RaSQQXMm++Y6sb6E1zRSxPkztj9fqxhS1Eo6w==", "requires": { - "loader-utils": "^2.0.0", - "schema-utils": "^3.0.0", - "webpack-sources": "^1.1.0" + "schema-utils": "^4.0.0" }, "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + "ajv": { + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz", + "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==", + "requires": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + } }, - "webpack-sources": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", - "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", + "ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "requires": { + "fast-deep-equal": "^3.1.3" + } + }, + "schema-utils": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.0.0.tgz", + "integrity": "sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg==", "requires": { - "source-list-map": "^2.0.0", - "source-map": "~0.6.1" + "@types/json-schema": "^7.0.9", + "ajv": "^8.8.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.0.0" } } } @@ -25211,43 +33640,24 @@ "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=" }, "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "requires": { "brace-expansion": "^1.1.7" } }, "minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" - }, - "mixin-deep": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", - "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", - "requires": { - "for-in": "^1.0.2", - "is-extendable": "^1.0.1" - }, - "dependencies": { - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "requires": { - "is-plain-object": "^2.0.4" - } - } - } + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", + "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" }, "mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", "requires": { - "minimist": "^1.2.5" + "minimist": "^1.2.6" } }, "mkdirp-classic": { @@ -25256,28 +33666,28 @@ "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" }, "mobx": { - "version": "6.3.3", - "resolved": "https://registry.npmjs.org/mobx/-/mobx-6.3.3.tgz", - "integrity": "sha512-JoNU50rO6d1wHwKPJqKq4rmUMbYnI9CsJmBo+Cu4exBYenFvIN77LWrZENpzW6reZPADtXMmB1DicbDSfy8Clw==" + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/mobx/-/mobx-6.5.0.tgz", + "integrity": "sha512-pHZ/cySF00FVENDWIDzJyoObFahK6Eg4d0papqm6d7yMkxWTZ/S/csqJX1A3PsYy4t5k3z2QnlwuCfMW5lSEwA==" }, "mobx-react": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/mobx-react/-/mobx-react-7.2.0.tgz", - "integrity": "sha512-KHUjZ3HBmZlNnPd1M82jcdVsQRDlfym38zJhZEs33VxyVQTvL77hODCArq6+C1P1k/6erEeo2R7rpE7ZeOL7dg==", + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/mobx-react/-/mobx-react-7.3.0.tgz", + "integrity": "sha512-RGEcwZokopqyJE5JPwXKB9FWMSqFM9NJVO2QPI+z6laJTJeBHqvPicjnKgY5mvihxTeXB1+72TnooqUePeGV1g==", "requires": { - "mobx-react-lite": "^3.2.0" + "mobx-react-lite": "^3.3.0" } }, "mobx-react-lite": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/mobx-react-lite/-/mobx-react-lite-3.2.1.tgz", - "integrity": "sha512-hwURgfmP2apX3HQrB55V9DN47kuN3C6KlQvI5UIfJRibXma72C/JudcNt2r9dWjAdFMrcZoz1ivvtXMCkJ2aQA==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/mobx-react-lite/-/mobx-react-lite-3.3.0.tgz", + "integrity": "sha512-U/kMSFtV/bNVgY01FuiGWpRkaQVHozBq5CEBZltFvPt4FcV111hEWkgwqVg9GPPZSEuEdV438PEz8mk8mKpYlA==", "requires": {} }, - "module-alias": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/module-alias/-/module-alias-2.2.2.tgz", - "integrity": "sha512-A/78XjoX2EmNvppVWEhM2oGk3x4lLxnkEA4jTbaK97QKSDjkIoOsKQlfylt/d3kKKi596Qy3NP5XrXJ6fZIC9Q==" + "mrmime": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-1.0.0.tgz", + "integrity": "sha512-a70zx7zFfVO7XpnQ2IX1Myh9yY4UYvfld/dikWRnsXxbyvMcfz+u6UfgNAtH+k2QqtJuzVpv6eLTx1G2+WKZbQ==" }, "ms": { "version": "2.1.2", @@ -25285,92 +33695,40 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "multicast-dns": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-6.2.3.tgz", - "integrity": "sha512-ji6J5enbMyGRHIAkAOu3WdV8nggqviKCEKtXcOqfphZZtQrmHKycfynJ2V7eVPUA4NhJ6V7Wf4TmGbTwKE9B6g==", + "version": "7.2.4", + "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-7.2.4.tgz", + "integrity": "sha512-XkCYOU+rr2Ft3LI6w4ye51M3VK31qJXFIxu0XLw169PtKG0Zx47OrXeVW/GCYOfpC9s1yyyf1S+L8/4LY0J9Zw==", "requires": { - "dns-packet": "^1.3.1", + "dns-packet": "^5.2.2", "thunky": "^1.0.2" } }, - "multicast-dns-service-types": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz", - "integrity": "sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE=" - }, - "nan": { - "version": "2.15.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.15.0.tgz", - "integrity": "sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ==", - "optional": true - }, - "nanocolors": { - "version": "0.1.12", - "resolved": "https://registry.npmjs.org/nanocolors/-/nanocolors-0.1.12.tgz", - "integrity": "sha512-2nMHqg1x5PU+unxX7PGY7AuYxl2qDx7PSrTRjizr8sxdd3l/3hBuWWaki62qmtYm2U5i4Z5E7GbjlyDFhs9/EQ==" - }, "nanoid": { - "version": "3.1.29", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.29.tgz", - "integrity": "sha512-dW2pUSGZ8ZnCFIlBIA31SV8huOGCHb6OwzVCc7A69rb/a+SgPBwfmLvK5TKQ3INPbRkcI8a/Owo0XbiTNH19wg==" - }, - "nanomatch": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", - "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "fragment-cache": "^0.2.1", - "is-windows": "^1.0.2", - "kind-of": "^6.0.2", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "requires": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - } - }, - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "requires": { - "is-plain-object": "^2.0.4" - } - } - } + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.3.tgz", + "integrity": "sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==" }, "napi-build-utils": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==" }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, "negotiator": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", - "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==" + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==" }, "neo-async": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" }, - "nice-try": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", - "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==" - }, "no-case": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", @@ -25381,24 +33739,17 @@ } }, "node-abi": { - "version": "2.30.1", - "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.30.1.tgz", - "integrity": "sha512-/2D0wOQPgaUWzVSVgRMx+trKJRC2UG4SUc4oCJoXx9Uxjtp0Vy3/kt7zcbxHF8+Z/pK3UloLWzBISg72brfy1w==", + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.15.0.tgz", + "integrity": "sha512-Ic6z/j6I9RLm4ov7npo1I48UQr2BEyFCqh6p7S1dhEx9jPO0GPGq/e2Rb7x7DroQrmiVMz/Bw1vJm9sPAl2nxA==", "requires": { - "semver": "^5.4.1" - }, - "dependencies": { - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" - } + "semver": "^7.3.5" } }, "node-addon-api": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.2.1.tgz", - "integrity": "sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A==" + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-4.3.0.tgz", + "integrity": "sha512-73sE9+3UaLYYFmDsFZnqCInzPyh3MqIwZO9cw58yIqAZhONrrabrYyYe3TuIqtIiOuTXVhsGau8hcrhhwSsDIQ==" }, "node-emoji": { "version": "1.11.0", @@ -25409,9 +33760,33 @@ } }, "node-fetch": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz", - "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==" + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", + "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "requires": { + "whatwg-url": "^5.0.0" + }, + "dependencies": { + "tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=" + }, + "webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=" + }, + "whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=", + "requires": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + } + } }, "node-fetch-h2": { "version": "2.3.0", @@ -25422,9 +33797,15 @@ } }, "node-forge": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.10.0.tgz", - "integrity": "sha512-PPmu8eEeG9saEUvI97fm4OYxXVB6bFvyNTyiUOBichBpFG8A1Ljw3bY62+5oOjDEMHRnd0Y7HQ+x7uzxOzC6JA==" + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", + "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==" + }, + "node-int64": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", + "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", + "dev": true }, "node-polyfill-webpack-plugin": { "version": "1.1.4", @@ -25455,17 +33836,6 @@ "url": "^0.11.0", "util": "^0.12.4", "vm-browserify": "^1.1.2" - }, - "dependencies": { - "buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "requires": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" - } - } } }, "node-readfiles": { @@ -25477,9 +33847,9 @@ } }, "node-releases": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.0.tgz", - "integrity": "sha512-aA87l0flFYMzCHpTM3DERFSYxc6lv/BltdbRTOMZuxZ0cwZCD3mejE5n9vLhSJCN++/eOqr77G1IO5uXxlQYWA==" + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.4.tgz", + "integrity": "sha512-gbMzqQtTtDz/00jQzZ21PQzdI9PyLYqUSvD0p3naOhX4odFji0ZxYdnVwPTxmSwkmxhcFImpozceidSG+AgoPQ==" }, "node-vibrant": { "version": "3.1.6", @@ -25518,18 +33888,11 @@ "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==" }, "npm-run-path": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", - "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", "requires": { - "path-key": "^2.0.0" - }, - "dependencies": { - "path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=" - } + "path-key": "^3.0.0" } }, "npmlog": { @@ -25561,6 +33924,12 @@ "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" }, + "nwsapi": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.0.tgz", + "integrity": "sha512-h2AatdwYH+JHiZpv7pt/gSX1XoRGb7L/qSIeuqA6GwYoF9w1vP1cw42TO0aI2pNyshRK5893hNSl+1//vHK7hQ==", + "dev": true + }, "oas-kit-common": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/oas-kit-common/-/oas-kit-common-1.0.8.tgz", @@ -25591,39 +33960,39 @@ "yargs": "^17.0.1" }, "dependencies": { - "cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" } }, - "y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==" - }, "yargs": { - "version": "17.2.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.2.1.tgz", - "integrity": "sha512-XfR8du6ua4K6uLGm5S6fA+FIJom/MdJcFNVY8geLlp2v8GYbOXD4EB1tPNZsRn4vBzKGMgb5DRZMeWuFc2GO8Q==", + "version": "17.4.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.4.1.tgz", + "integrity": "sha512-WSZD9jgobAg3ZKuCQZSa3g9QOJeCCqLoLAykiWgmXnDo9EPnn4RPf5qVTtzgOx66o6/oqhcA5tHtJXpG8pMt3g==", "requires": { "cliui": "^7.0.2", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", - "string-width": "^4.2.0", + "string-width": "^4.2.3", "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" + "yargs-parser": "^21.0.0" } }, "yargs-parser": { - "version": "20.2.9", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==" + "version": "21.0.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.0.1.tgz", + "integrity": "sha512-9BK1jFpLzJROCI5TzwZL/TU4gqjK5xiHV/RfWLOahrjAko/e4DJkRDZQXfvqAsiZzzYhgAzbgz6lg48jcm4GLg==" } } }, @@ -25652,38 +34021,10 @@ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" }, - "object-copy": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", - "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", - "requires": { - "copy-descriptor": "^0.1.0", - "define-property": "^0.2.5", - "kind-of": "^3.0.3" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, "object-inspect": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.11.0.tgz", - "integrity": "sha512-jp7ikS6Sd3GxQfZJPyH3cjcbJF6GZPClgdV+EFygjFLQ5FmW/dRUnTd9PQ9k0JhoNDabWFbpF1yCdSWCC6gexg==" + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.0.tgz", + "integrity": "sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g==" }, "object-is": { "version": "1.1.5", @@ -25699,14 +34040,6 @@ "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==" }, - "object-visit": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", - "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", - "requires": { - "isobject": "^3.0.0" - } - }, "object.assign": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", @@ -25728,14 +34061,6 @@ "es-abstract": "^1.19.1" } }, - "object.pick": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", - "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", - "requires": { - "isobject": "^3.0.1" - } - }, "object.values": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.5.tgz", @@ -25757,9 +34082,9 @@ "integrity": "sha512-LMJTtvgc/nugXj0Vcrrs68Mn2D1r0zf630VNtqtpI1FEO7e+O9FP4gqs9AcnBaSEeoHIPm28u6qgPR0oyEpGSw==" }, "on-finished": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", "requires": { "ee-first": "1.1.1" } @@ -25786,21 +34111,22 @@ } }, "open": { - "version": "7.4.2", - "resolved": "https://registry.npmjs.org/open/-/open-7.4.2.tgz", - "integrity": "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==", + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/open/-/open-8.4.0.tgz", + "integrity": "sha512-XgFPPM+B28FtCCgSb9I+s9szOC1vZRSwgWsRUA5ylIxRTgKozqjOCrVOqGsYABPYK5qnfqClxZTFBa8PKt2v6Q==", "requires": { - "is-docker": "^2.0.0", - "is-wsl": "^2.1.1" + "define-lazy-prop": "^2.0.0", + "is-docker": "^2.1.1", + "is-wsl": "^2.2.0" } }, "openapi-sampler": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/openapi-sampler/-/openapi-sampler-1.1.0.tgz", - "integrity": "sha512-/LhZYKNBWphLEpbAG5BdpBZbIbmLgC4vTiTj8N/MV0LF9ptmKOiJ2nETVlacNjXHt7iqDgZDELJCIoZ3q5ZG6A==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/openapi-sampler/-/openapi-sampler-1.2.3.tgz", + "integrity": "sha512-dH2QYXqakorV5dxkP/f1BV3Ku4yNn21YmBsqJunnyrHLw7mnCNZZldftgrEpv/66b1m5oaUAmiJoJN+FqBEkJg==", "requires": { "@types/json-schema": "^7.0.7", - "json-pointer": "^0.6.1" + "json-pointer": "0.6.2" } }, "opener": { @@ -25808,27 +34134,18 @@ "resolved": "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz", "integrity": "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==" }, - "opn": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/opn/-/opn-5.5.0.tgz", - "integrity": "sha512-PqHpggC9bLV0VeWcdKhkpxY+3JTzetLSqTCWL/z/tFIbI6G8JCjondXklT1JinczLz2Xib62sSp0T/gKT4KksA==", - "requires": { - "is-wsl": "^1.1.0" - }, - "dependencies": { - "is-wsl": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", - "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=" - } - } - }, - "original": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/original/-/original-1.0.2.tgz", - "integrity": "sha512-hyBVl6iqqUOJ8FqRe+l/gS8H+kKYjrEndd5Pm1MfBtsEKA038HkkdbAl/72EAXGyonD/PFsvmVG+EvcIpliMBg==", + "optionator": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", + "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", + "dev": true, "requires": { - "url-parse": "^1.4.3" + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.6", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "word-wrap": "~1.2.3" } }, "os-browserify": { @@ -25836,22 +34153,23 @@ "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=" }, + "ospath": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/ospath/-/ospath-1.2.2.tgz", + "integrity": "sha512-o6E5qJV5zkAbIDNhGSIlyOhScKXgQrSRMilfph0clDfM0nEnBOlKlH4sWDmG95BW/CvwNz0vmm7dJVtU2KlMiA==", + "dev": true + }, "p-cancelable": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==" }, - "p-finally": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", - "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=" - }, "p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "requires": { - "yocto-queue": "^0.1.0" + "p-try": "^2.0.0" } }, "p-locate": { @@ -25860,16 +34178,6 @@ "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", "requires": { "p-limit": "^2.2.0" - }, - "dependencies": { - "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "requires": { - "p-try": "^2.0.0" - } - } } }, "p-map": { @@ -25881,11 +34189,12 @@ } }, "p-retry": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-3.0.1.tgz", - "integrity": "sha512-XE6G4+YTTkT2a0UWb2kjZe8xNwf8bIbnqpc/IS/idOBVhyves0mK5OJgeocjx7q5pvX/6m23xuzVPYT1uGM73w==", + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-4.6.2.tgz", + "integrity": "sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==", "requires": { - "retry": "^0.12.0" + "@types/retry": "0.12.0", + "retry": "^0.13.1" } }, "p-try": { @@ -25978,9 +34287,9 @@ } }, "parse-headers": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/parse-headers/-/parse-headers-2.0.4.tgz", - "integrity": "sha512-psZ9iZoCNFLrgRjZ1d8mn0h9WRqJwFxM9q3x7iUjN/YT2OksthDJ5TiPCu2F38kS4zutqfW+YdVVkBZZx3/1aw==" + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/parse-headers/-/parse-headers-2.0.5.tgz", + "integrity": "sha512-ft3iAoLOB/MlwbNXgzy43SWGP6sQki2jQvAyBg/zDFAgr9bfNWZIUj42Kw2eJIl8kEi4PbgE6U1Zau/HwI75HA==" }, "parse-json": { "version": "5.2.0", @@ -25999,9 +34308,17 @@ "integrity": "sha512-twN+njEipszzlMJd4ONUYgSfZPDxgHhT9Ahed5uTigpQn90FggW4SA/AIPq/6a149fTbE9qBEcSwE3FAEp6wQQ==" }, "parse5": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.1.tgz", - "integrity": "sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug==" + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", + "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==" + }, + "parse5-htmlparser2-tree-adapter": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz", + "integrity": "sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==", + "requires": { + "parse5": "^6.0.1" + } }, "parseurl": { "version": "1.3.3", @@ -26017,21 +34334,11 @@ "tslib": "^2.0.3" } }, - "pascalcase": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", - "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=" - }, "path-browserify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==" }, - "path-dirname": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", - "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=" - }, "path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -26058,9 +34365,12 @@ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" }, "path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", + "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", + "requires": { + "isarray": "0.0.1" + } }, "path-type": { "version": "4.0.0", @@ -26079,10 +34389,22 @@ "sha.js": "^2.4.8" } }, + "pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", + "dev": true + }, "perfect-scrollbar": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/perfect-scrollbar/-/perfect-scrollbar-1.5.2.tgz", - "integrity": "sha512-McHAinFkyzKbBZrFtb4MT2mxkehp15KvOX/UrjB8C5EZZXHTHgyETo5IGFYtHRTI2Pb2bsV0OE0YnkjT9Cw3aw==" + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/perfect-scrollbar/-/perfect-scrollbar-1.5.5.tgz", + "integrity": "sha512-dzalfutyP3e/FOpdlhVryN4AJ5XDVauVWxybSkLZmakFE2sS3y3pc4JnSprw8tGmHvkaG5Edr5T7LBTZ+WWU2g==" + }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==", + "dev": true }, "phin": { "version": "2.9.3", @@ -26095,27 +34417,21 @@ "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" }, "picomatch": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", - "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==" + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==" }, "pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==" - }, - "pinkie": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", - "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=" + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "dev": true }, - "pinkie-promise": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", - "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", - "requires": { - "pinkie": "^2.0.0" - } + "pirates": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.5.tgz", + "integrity": "sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ==", + "dev": true }, "pixelmatch": { "version": "4.0.2", @@ -26158,14 +34474,6 @@ "path-exists": "^3.0.0" } }, - "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "requires": { - "p-try": "^2.0.0" - } - }, "p-locate": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", @@ -26181,17 +34489,22 @@ } } }, + "pluralize": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", + "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==" + }, "pngjs": { "version": "3.4.0", "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-3.4.0.tgz", "integrity": "sha512-NCrCHhWmnQklfH4MtJMRjZ2a8c80qXeMlQMv2uVp9ISJMTt562SbGd6n2oq0PaPgKm7Z6pL9E2UlLIhC+SHL3w==" }, "polished": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/polished/-/polished-4.1.3.tgz", - "integrity": "sha512-ocPAcVBUOryJEKe0z2KLd1l9EBa1r5mSwlKpExmrLzsnIzJo4axsoU9O2BjOTkDGDT4mZ0WFE5XKTlR3nLnZOA==", + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/polished/-/polished-4.2.2.tgz", + "integrity": "sha512-Sz2Lkdxz6F2Pgnpi9U5Ng/WdWAUZxmHrNPoVlm3aAemxoy2Qy7LGjQg4uf8qKelDAUW94F4np3iH2YPf2qefcQ==", "requires": { - "@babel/runtime": "^7.14.0" + "@babel/runtime": "^7.17.8" } }, "portfinder": { @@ -26214,390 +34527,519 @@ } } }, - "posix-character-classes": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", - "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=" - }, "postcss": { - "version": "8.3.9", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.3.9.tgz", - "integrity": "sha512-f/ZFyAKh9Dnqytx5X62jgjhhzttjZS7hMsohcI7HEI5tjELX/HxCy3EFhsRxyzGvrzFF+82XPvCS8T9TFleVJw==", + "version": "8.4.13", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.13.tgz", + "integrity": "sha512-jtL6eTBrza5MPzy8oJLFuUscHDXTV5KcLlqAWHl5q5WYRfnNRGSmOZmOZ1T6Gy7A99mOZfqungmZMpMmCVJ8ZA==", "requires": { - "nanoid": "^3.1.28", - "picocolors": "^0.2.1", - "source-map-js": "^0.6.2" - }, - "dependencies": { - "picocolors": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", - "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" - } + "nanoid": "^3.3.3", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" } }, "postcss-calc": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-8.0.0.tgz", - "integrity": "sha512-5NglwDrcbiy8XXfPM11F3HeC6hoT9W7GUH/Zi5U/p7u3Irv4rHhdDcIZwG0llHXV4ftsBjpfWMXAnXNl4lnt8g==", + "version": "8.2.4", + "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-8.2.4.tgz", + "integrity": "sha512-SmWMSJmB8MRnnULldx0lQIyhSNvuDl9HfrZkaqqE/WHAhToYsAvDq+yAsA/kIyINDszOp3Rh0GFoNuH5Ypsm3Q==", "requires": { - "postcss-selector-parser": "^6.0.2", - "postcss-value-parser": "^4.0.2" + "postcss-selector-parser": "^6.0.9", + "postcss-value-parser": "^4.2.0" } }, "postcss-colormin": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-5.2.0.tgz", - "integrity": "sha512-+HC6GfWU3upe5/mqmxuqYZ9B2Wl4lcoUUNkoaX59nEWV4EtADCMiBqui111Bu8R8IvaZTmqmxrqOAqjbHIwXPw==", + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-5.3.0.tgz", + "integrity": "sha512-WdDO4gOFG2Z8n4P8TWBpshnL3JpmNmJwdnfP2gbk2qBA8PWwOYcmjmI/t3CmMeL72a7Hkd+x/Mg9O2/0rD54Pg==", "requires": { "browserslist": "^4.16.6", "caniuse-api": "^3.0.0", - "colord": "^2.0.1", - "postcss-value-parser": "^4.1.0" + "colord": "^2.9.1", + "postcss-value-parser": "^4.2.0" } }, "postcss-convert-values": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-5.0.1.tgz", - "integrity": "sha512-C3zR1Do2BkKkCgC0g3sF8TS0koF2G+mN8xxayZx3f10cIRmTaAnpgpRQZjNekTZxM2ciSPoh2IWJm0VZx8NoQg==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-5.1.0.tgz", + "integrity": "sha512-GkyPbZEYJiWtQB0KZ0X6qusqFHUepguBCNFi9t5JJc7I2OTXG7C0twbTLvCfaKOLl3rSXmpAwV7W5txd91V84g==", "requires": { - "postcss-value-parser": "^4.1.0" + "postcss-value-parser": "^4.2.0" } }, "postcss-discard-comments": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-5.0.1.tgz", - "integrity": "sha512-lgZBPTDvWrbAYY1v5GYEv8fEO/WhKOu/hmZqmCYfrpD6eyDWWzAOsl2rF29lpvziKO02Gc5GJQtlpkTmakwOWg==", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-5.1.1.tgz", + "integrity": "sha512-5JscyFmvkUxz/5/+TB3QTTT9Gi9jHkcn8dcmmuN68JQcv3aQg4y88yEHHhwFB52l/NkaJ43O0dbksGMAo49nfQ==", "requires": {} }, "postcss-discard-duplicates": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-5.0.1.tgz", - "integrity": "sha512-svx747PWHKOGpAXXQkCc4k/DsWo+6bc5LsVrAsw+OU+Ibi7klFZCyX54gjYzX4TH+f2uzXjRviLARxkMurA2bA==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-5.1.0.tgz", + "integrity": "sha512-zmX3IoSI2aoenxHV6C7plngHWWhUOV3sP1T8y2ifzxzbtnuhk1EdPwm0S1bIUNaJ2eNbWeGLEwzw8huPD67aQw==", "requires": {} }, "postcss-discard-empty": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-5.0.1.tgz", - "integrity": "sha512-vfU8CxAQ6YpMxV2SvMcMIyF2LX1ZzWpy0lqHDsOdaKKLQVQGVP1pzhrI9JlsO65s66uQTfkQBKBD/A5gp9STFw==", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-5.1.1.tgz", + "integrity": "sha512-zPz4WljiSuLWsI0ir4Mcnr4qQQ5e1Ukc3i7UfE2XcrwKK2LIPIqE5jxMRxO6GbI3cv//ztXDsXwEWT3BHOGh3A==", "requires": {} }, "postcss-discard-overridden": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-5.0.1.tgz", - "integrity": "sha512-Y28H7y93L2BpJhrdUR2SR2fnSsT+3TVx1NmVQLbcnZWwIUpJ7mfcTC6Za9M2PG6w8j7UQRfzxqn8jU2VwFxo3Q==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-5.1.0.tgz", + "integrity": "sha512-21nOL7RqWR1kasIVdKs8HNqQJhFxLsyRfAnUDm4Fe4t4mCWL9OJiHvlHPjcd8zc5Myu89b/7wZDnOSjFgeWRtw==", "requires": {} }, "postcss-discard-unused": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/postcss-discard-unused/-/postcss-discard-unused-5.0.1.tgz", - "integrity": "sha512-tD6xR/xyZTwfhKYRw0ylfCY8wbfhrjpKAMnDKRTLMy2fNW5hl0hoV6ap5vo2JdCkuHkP3CHw72beO4Y8pzFdww==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-discard-unused/-/postcss-discard-unused-5.1.0.tgz", + "integrity": "sha512-KwLWymI9hbwXmJa0dkrzpRbSJEh0vVUd7r8t0yOGPcfKzyJJxFM8kLyC5Ev9avji6nY95pOp1W6HqIrfT+0VGw==", "requires": { "postcss-selector-parser": "^6.0.5" } }, "postcss-loader": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-5.3.0.tgz", - "integrity": "sha512-/+Z1RAmssdiSLgIZwnJHwBMnlABPgF7giYzTN2NOfr9D21IJZ4mQC1R2miwp80zno9M4zMD/umGI8cR+2EL5zw==", + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-6.2.1.tgz", + "integrity": "sha512-WbbYpmAaKcux/P66bZ40bpWsBucjx/TTgVVzRZ9yUO8yQfVBlameJ0ZGVaPfH64hNSBh63a+ICP5nqOpBA0w+Q==", "requires": { "cosmiconfig": "^7.0.0", - "klona": "^2.0.4", - "semver": "^7.3.4" + "klona": "^2.0.5", + "semver": "^7.3.5" } }, "postcss-merge-idents": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/postcss-merge-idents/-/postcss-merge-idents-5.0.1.tgz", - "integrity": "sha512-xu8ueVU0RszbI2gKkxR6mluupsOSSLvt8q4gA2fcKFkA+x6SlH3cb4cFHpDvcRCNFbUmCR/VUub+Y6zPOjPx+Q==", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-merge-idents/-/postcss-merge-idents-5.1.1.tgz", + "integrity": "sha512-pCijL1TREiCoog5nQp7wUe+TUonA2tC2sQ54UGeMmryK3UFGIYKqDyjnqd6RcuI4znFn9hWSLNN8xKE/vWcUQw==", "requires": { - "cssnano-utils": "^2.0.1", - "postcss-value-parser": "^4.1.0" + "cssnano-utils": "^3.1.0", + "postcss-value-parser": "^4.2.0" } }, "postcss-merge-longhand": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-5.0.2.tgz", - "integrity": "sha512-BMlg9AXSI5G9TBT0Lo/H3PfUy63P84rVz3BjCFE9e9Y9RXQZD3+h3YO1kgTNsNJy7bBc1YQp8DmSnwLIW5VPcw==", + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-5.1.4.tgz", + "integrity": "sha512-hbqRRqYfmXoGpzYKeW0/NCZhvNyQIlQeWVSao5iKWdyx7skLvCfQFGIUsP9NUs3dSbPac2IC4Go85/zG+7MlmA==", "requires": { - "css-color-names": "^1.0.1", - "postcss-value-parser": "^4.1.0", - "stylehacks": "^5.0.1" + "postcss-value-parser": "^4.2.0", + "stylehacks": "^5.1.0" } }, "postcss-merge-rules": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-5.0.2.tgz", - "integrity": "sha512-5K+Md7S3GwBewfB4rjDeol6V/RZ8S+v4B66Zk2gChRqLTCC8yjnHQ601omj9TKftS19OPGqZ/XzoqpzNQQLwbg==", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-5.1.1.tgz", + "integrity": "sha512-8wv8q2cXjEuCcgpIB1Xx1pIy8/rhMPIQqYKNzEdyx37m6gpq83mQQdCxgIkFgliyEnKvdwJf/C61vN4tQDq4Ww==", "requires": { "browserslist": "^4.16.6", "caniuse-api": "^3.0.0", - "cssnano-utils": "^2.0.1", - "postcss-selector-parser": "^6.0.5", - "vendors": "^1.0.3" + "cssnano-utils": "^3.1.0", + "postcss-selector-parser": "^6.0.5" } }, "postcss-minify-font-values": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-5.0.1.tgz", - "integrity": "sha512-7JS4qIsnqaxk+FXY1E8dHBDmraYFWmuL6cgt0T1SWGRO5bzJf8sUoelwa4P88LEWJZweHevAiDKxHlofuvtIoA==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-5.1.0.tgz", + "integrity": "sha512-el3mYTgx13ZAPPirSVsHqFzl+BBBDrXvbySvPGFnQcTI4iNslrPaFq4muTkLZmKlGk4gyFAYUBMH30+HurREyA==", "requires": { - "postcss-value-parser": "^4.1.0" + "postcss-value-parser": "^4.2.0" } }, "postcss-minify-gradients": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-5.0.2.tgz", - "integrity": "sha512-7Do9JP+wqSD6Prittitt2zDLrfzP9pqKs2EcLX7HJYxsxCOwrrcLt4x/ctQTsiOw+/8HYotAoqNkrzItL19SdQ==", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-5.1.1.tgz", + "integrity": "sha512-VGvXMTpCEo4qHTNSa9A0a3D+dxGFZCYwR6Jokk+/3oB6flu2/PnPXAh2x7x52EkY5xlIHLm+Le8tJxe/7TNhzw==", "requires": { - "colord": "^2.6", - "cssnano-utils": "^2.0.1", - "postcss-value-parser": "^4.1.0" + "colord": "^2.9.1", + "cssnano-utils": "^3.1.0", + "postcss-value-parser": "^4.2.0" } }, "postcss-minify-params": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-5.0.1.tgz", - "integrity": "sha512-4RUC4k2A/Q9mGco1Z8ODc7h+A0z7L7X2ypO1B6V8057eVK6mZ6xwz6QN64nHuHLbqbclkX1wyzRnIrdZehTEHw==", + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-5.1.2.tgz", + "integrity": "sha512-aEP+p71S/urY48HWaRHasyx4WHQJyOYaKpQ6eXl8k0kxg66Wt/30VR6/woh8THgcpRbonJD5IeD+CzNhPi1L8g==", "requires": { - "alphanum-sort": "^1.0.2", - "browserslist": "^4.16.0", - "cssnano-utils": "^2.0.1", - "postcss-value-parser": "^4.1.0", - "uniqs": "^2.0.0" + "browserslist": "^4.16.6", + "cssnano-utils": "^3.1.0", + "postcss-value-parser": "^4.2.0" } }, "postcss-minify-selectors": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-5.1.0.tgz", - "integrity": "sha512-NzGBXDa7aPsAcijXZeagnJBKBPMYLaJJzB8CQh6ncvyl2sIndLVWfbcDi0SBjRWk5VqEjXvf8tYwzoKf4Z07og==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-5.2.0.tgz", + "integrity": "sha512-vYxvHkW+iULstA+ctVNx0VoRAR4THQQRkG77o0oa4/mBS0OzGvvzLIvHDv/nNEM0crzN2WIyFU5X7wZhaUK3RA==", "requires": { - "alphanum-sort": "^1.0.2", "postcss-selector-parser": "^6.0.5" } }, "postcss-modules-extract-imports": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz", - "integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==", - "requires": {} + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-2.0.0.tgz", + "integrity": "sha512-LaYLDNS4SG8Q5WAWqIJgdHPJrDDr/Lv775rMBFUbgjTz6j34lUznACHcdRWroPvXANP2Vj7yNK57vp9eFqzLWQ==", + "dev": true, + "requires": { + "postcss": "^7.0.5" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + } + } }, "postcss-modules-local-by-default": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.0.tgz", - "integrity": "sha512-sT7ihtmGSF9yhm6ggikHdV0hlziDTX7oFoXtuVWeDd3hHObNkcHRo9V3yg7vCAY7cONyxJC/XXCmmiHHcvX7bQ==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-3.0.3.tgz", + "integrity": "sha512-e3xDq+LotiGesympRlKNgaJ0PCzoUIdpH0dj47iWAui/kyTgh3CiAr1qP54uodmJhl6p9rN6BoNcdEDVJx9RDw==", + "dev": true, "requires": { - "icss-utils": "^5.0.0", + "icss-utils": "^4.1.1", + "postcss": "^7.0.32", "postcss-selector-parser": "^6.0.2", "postcss-value-parser": "^4.1.0" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + } } }, "postcss-modules-scope": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.0.0.tgz", - "integrity": "sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-2.2.0.tgz", + "integrity": "sha512-YyEgsTMRpNd+HmyC7H/mh3y+MeFWevy7V1evVhJWewmMbjDHIbZbOXICC2y+m1xI1UVfIT1HMW/O04Hxyu9oXQ==", + "dev": true, "requires": { - "postcss-selector-parser": "^6.0.4" + "postcss": "^7.0.6", + "postcss-selector-parser": "^6.0.0" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + } } }, "postcss-modules-values": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", - "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-3.0.0.tgz", + "integrity": "sha512-1//E5jCBrZ9DmRX+zCtmQtRSV6PV42Ix7Bzj9GbwJceduuf7IqP8MgeTXuRDHOWj2m0VzZD5+roFWDuU8RQjcg==", + "dev": true, "requires": { - "icss-utils": "^5.0.0" + "icss-utils": "^4.0.0", + "postcss": "^7.0.6" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + } } }, "postcss-normalize-charset": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-5.0.1.tgz", - "integrity": "sha512-6J40l6LNYnBdPSk+BHZ8SF+HAkS4q2twe5jnocgd+xWpz/mx/5Sa32m3W1AA8uE8XaXN+eg8trIlfu8V9x61eg==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-5.1.0.tgz", + "integrity": "sha512-mSgUJ+pd/ldRGVx26p2wz9dNZ7ji6Pn8VWBajMXFf8jk7vUoSrZ2lt/wZR7DtlZYKesmZI680qjr2CeFF2fbUg==", "requires": {} }, "postcss-normalize-display-values": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/postcss-normalize-display-values/-/postcss-normalize-display-values-5.0.1.tgz", - "integrity": "sha512-uupdvWk88kLDXi5HEyI9IaAJTE3/Djbcrqq8YgjvAVuzgVuqIk3SuJWUisT2gaJbZm1H9g5k2w1xXilM3x8DjQ==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-display-values/-/postcss-normalize-display-values-5.1.0.tgz", + "integrity": "sha512-WP4KIM4o2dazQXWmFaqMmcvsKmhdINFblgSeRgn8BJ6vxaMyaJkwAzpPpuvSIoG/rmX3M+IrRZEz2H0glrQNEA==", "requires": { - "cssnano-utils": "^2.0.1", - "postcss-value-parser": "^4.1.0" + "postcss-value-parser": "^4.2.0" } }, "postcss-normalize-positions": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/postcss-normalize-positions/-/postcss-normalize-positions-5.0.1.tgz", - "integrity": "sha512-rvzWAJai5xej9yWqlCb1OWLd9JjW2Ex2BCPzUJrbaXmtKtgfL8dBMOOMTX6TnvQMtjk3ei1Lswcs78qKO1Skrg==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-positions/-/postcss-normalize-positions-5.1.0.tgz", + "integrity": "sha512-8gmItgA4H5xiUxgN/3TVvXRoJxkAWLW6f/KKhdsH03atg0cB8ilXnrB5PpSshwVu/dD2ZsRFQcR1OEmSBDAgcQ==", "requires": { - "postcss-value-parser": "^4.1.0" + "postcss-value-parser": "^4.2.0" } }, "postcss-normalize-repeat-style": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-5.0.1.tgz", - "integrity": "sha512-syZ2itq0HTQjj4QtXZOeefomckiV5TaUO6ReIEabCh3wgDs4Mr01pkif0MeVwKyU/LHEkPJnpwFKRxqWA/7O3w==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-5.1.0.tgz", + "integrity": "sha512-IR3uBjc+7mcWGL6CtniKNQ4Rr5fTxwkaDHwMBDGGs1x9IVRkYIT/M4NelZWkAOBdV6v3Z9S46zqaKGlyzHSchw==", "requires": { - "cssnano-utils": "^2.0.1", - "postcss-value-parser": "^4.1.0" + "postcss-value-parser": "^4.2.0" } }, "postcss-normalize-string": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/postcss-normalize-string/-/postcss-normalize-string-5.0.1.tgz", - "integrity": "sha512-Ic8GaQ3jPMVl1OEn2U//2pm93AXUcF3wz+OriskdZ1AOuYV25OdgS7w9Xu2LO5cGyhHCgn8dMXh9bO7vi3i9pA==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-string/-/postcss-normalize-string-5.1.0.tgz", + "integrity": "sha512-oYiIJOf4T9T1N4i+abeIc7Vgm/xPCGih4bZz5Nm0/ARVJ7K6xrDlLwvwqOydvyL3RHNf8qZk6vo3aatiw/go3w==", "requires": { - "postcss-value-parser": "^4.1.0" + "postcss-value-parser": "^4.2.0" } }, "postcss-normalize-timing-functions": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-5.0.1.tgz", - "integrity": "sha512-cPcBdVN5OsWCNEo5hiXfLUnXfTGtSFiBU9SK8k7ii8UD7OLuznzgNRYkLZow11BkQiiqMcgPyh4ZqXEEUrtQ1Q==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-5.1.0.tgz", + "integrity": "sha512-DOEkzJ4SAXv5xkHl0Wa9cZLF3WCBhF3o1SKVxKQAa+0pYKlueTpCgvkFAHfk+Y64ezX9+nITGrDZeVGgITJXjg==", "requires": { - "cssnano-utils": "^2.0.1", - "postcss-value-parser": "^4.1.0" + "postcss-value-parser": "^4.2.0" } }, "postcss-normalize-unicode": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/postcss-normalize-unicode/-/postcss-normalize-unicode-5.0.1.tgz", - "integrity": "sha512-kAtYD6V3pK0beqrU90gpCQB7g6AOfP/2KIPCVBKJM2EheVsBQmx/Iof+9zR9NFKLAx4Pr9mDhogB27pmn354nA==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-unicode/-/postcss-normalize-unicode-5.1.0.tgz", + "integrity": "sha512-J6M3MizAAZ2dOdSjy2caayJLQT8E8K9XjLce8AUQMwOrCvjCHv24aLC/Lps1R1ylOfol5VIDMaM/Lo9NGlk1SQ==", "requires": { - "browserslist": "^4.16.0", - "postcss-value-parser": "^4.1.0" + "browserslist": "^4.16.6", + "postcss-value-parser": "^4.2.0" } }, "postcss-normalize-url": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-5.0.2.tgz", - "integrity": "sha512-k4jLTPUxREQ5bpajFQZpx8bCF2UrlqOTzP9kEqcEnOfwsRshWs2+oAFIHfDQB8GO2PaUaSE0NlTAYtbluZTlHQ==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-5.1.0.tgz", + "integrity": "sha512-5upGeDO+PVthOxSmds43ZeMeZfKH+/DKgGRD7TElkkyS46JXAUhMzIKiCa7BabPeIy3AQcTkXwVVN7DbqsiCew==", "requires": { - "is-absolute-url": "^3.0.3", "normalize-url": "^6.0.1", - "postcss-value-parser": "^4.1.0" + "postcss-value-parser": "^4.2.0" } }, "postcss-normalize-whitespace": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/postcss-normalize-whitespace/-/postcss-normalize-whitespace-5.0.1.tgz", - "integrity": "sha512-iPklmI5SBnRvwceb/XH568yyzK0qRVuAG+a1HFUsFRf11lEJTiQQa03a4RSCQvLKdcpX7XsI1Gen9LuLoqwiqA==", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-whitespace/-/postcss-normalize-whitespace-5.1.1.tgz", + "integrity": "sha512-83ZJ4t3NUDETIHTa3uEg6asWjSBYL5EdkVB0sDncx9ERzOKBVJIUeDO9RyA9Zwtig8El1d79HBp0JEi8wvGQnA==", "requires": { - "postcss-value-parser": "^4.1.0" + "postcss-value-parser": "^4.2.0" } }, "postcss-ordered-values": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-5.0.2.tgz", - "integrity": "sha512-8AFYDSOYWebJYLyJi3fyjl6CqMEG/UVworjiyK1r573I56kb3e879sCJLGvR3merj+fAdPpVplXKQZv+ey6CgQ==", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-5.1.1.tgz", + "integrity": "sha512-7lxgXF0NaoMIgyihL/2boNAEZKiW0+HkMhdKMTD93CjW8TdCy2hSdj8lsAo+uwm7EDG16Da2Jdmtqpedl0cMfw==", "requires": { - "cssnano-utils": "^2.0.1", - "postcss-value-parser": "^4.1.0" + "cssnano-utils": "^3.1.0", + "postcss-value-parser": "^4.2.0" } }, "postcss-reduce-idents": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/postcss-reduce-idents/-/postcss-reduce-idents-5.0.1.tgz", - "integrity": "sha512-6Rw8iIVFbqtaZExgWK1rpVgP7DPFRPh0DDFZxJ/ADNqPiH10sPCoq5tgo6kLiTyfh9sxjKYjXdc8udLEcPOezg==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/postcss-reduce-idents/-/postcss-reduce-idents-5.2.0.tgz", + "integrity": "sha512-BTrLjICoSB6gxbc58D5mdBK8OhXRDqud/zodYfdSi52qvDHdMwk+9kB9xsM8yJThH/sZU5A6QVSmMmaN001gIg==", "requires": { - "postcss-value-parser": "^4.1.0" + "postcss-value-parser": "^4.2.0" } }, "postcss-reduce-initial": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-5.0.1.tgz", - "integrity": "sha512-zlCZPKLLTMAqA3ZWH57HlbCjkD55LX9dsRyxlls+wfuRfqCi5mSlZVan0heX5cHr154Dq9AfbH70LyhrSAezJw==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-5.1.0.tgz", + "integrity": "sha512-5OgTUviz0aeH6MtBjHfbr57tml13PuedK/Ecg8szzd4XRMbYxH4572JFG067z+FqBIf6Zp/d+0581glkvvWMFw==", "requires": { - "browserslist": "^4.16.0", + "browserslist": "^4.16.6", "caniuse-api": "^3.0.0" } }, "postcss-reduce-transforms": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-5.0.1.tgz", - "integrity": "sha512-a//FjoPeFkRuAguPscTVmRQUODP+f3ke2HqFNgGPwdYnpeC29RZdCBvGRGTsKpMURb/I3p6jdKoBQ2zI+9Q7kA==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-5.1.0.tgz", + "integrity": "sha512-2fbdbmgir5AvpW9RLtdONx1QoYG2/EtqpNQbFASDlixBbAYuTcJ0dECwlqNqH7VbaUnEnh8SrxOe2sRIn24XyQ==", "requires": { - "cssnano-utils": "^2.0.1", - "postcss-value-parser": "^4.1.0" + "postcss-value-parser": "^4.2.0" } }, "postcss-selector-parser": { - "version": "6.0.6", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.6.tgz", - "integrity": "sha512-9LXrvaaX3+mcv5xkg5kFwqSzSH1JIObIx51PrndZwlmznwXRfxMddDvo9gve3gVR8ZTKgoFDdWkbRFmEhT4PMg==", + "version": "6.0.10", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz", + "integrity": "sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==", "requires": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" } }, "postcss-sort-media-queries": { - "version": "3.12.13", - "resolved": "https://registry.npmjs.org/postcss-sort-media-queries/-/postcss-sort-media-queries-3.12.13.tgz", - "integrity": "sha512-bFbR1+P6HhZWXcT5DVV2pBH5Y2U5daKbFd0j+kcwKdzrxkbmgFu0GhI2JfFUyy5KQIeW+YJGP+vwNDOS5hIn2g==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/postcss-sort-media-queries/-/postcss-sort-media-queries-4.2.1.tgz", + "integrity": "sha512-9VYekQalFZ3sdgcTjXMa0dDjsfBVHXlraYJEMiOJ/2iMmI2JGCMavP16z3kWOaRu8NSaJCTgVpB/IVpH5yT9YQ==", "requires": { "sort-css-media-queries": "2.0.4" } }, "postcss-svgo": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-5.0.2.tgz", - "integrity": "sha512-YzQuFLZu3U3aheizD+B1joQ94vzPfE6BNUcSYuceNxlVnKKsOtdo6hL9/zyC168Q8EwfLSgaDSalsUGa9f2C0A==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-5.1.0.tgz", + "integrity": "sha512-D75KsH1zm5ZrHyxPakAxJWtkyXew5qwS70v56exwvw542d9CRtTo78K0WeFxZB4G7JXKKMbEZtZayTGdIky/eA==", "requires": { - "postcss-value-parser": "^4.1.0", - "svgo": "^2.3.0" + "postcss-value-parser": "^4.2.0", + "svgo": "^2.7.0" + }, + "dependencies": { + "commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==" + }, + "css-tree": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz", + "integrity": "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==", + "requires": { + "mdn-data": "2.0.14", + "source-map": "^0.6.1" + } + }, + "mdn-data": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz", + "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==" + }, + "svgo": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-2.8.0.tgz", + "integrity": "sha512-+N/Q9kV1+F+UeWYoSiULYo4xYSDQlTgb+ayMobAXPwMnLvop7oxKMo9OzIrX5x3eS4L4f2UHhc9axXwY8DpChg==", + "requires": { + "@trysound/sax": "0.2.0", + "commander": "^7.2.0", + "css-select": "^4.1.3", + "css-tree": "^1.1.3", + "csso": "^4.2.0", + "picocolors": "^1.0.0", + "stable": "^0.1.8" + } + } } }, "postcss-unique-selectors": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-5.0.1.tgz", - "integrity": "sha512-gwi1NhHV4FMmPn+qwBNuot1sG1t2OmacLQ/AX29lzyggnjd+MnVD5uqQmpXO3J17KGL2WAxQruj1qTd3H0gG/w==", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-5.1.1.tgz", + "integrity": "sha512-5JiODlELrz8L2HwxfPnhOWZYWDxVHWL83ufOv84NrcgipI7TaeRsatAhK4Tr2/ZiYldpK/wBvw5BD3qfaK96GA==", "requires": { - "alphanum-sort": "^1.0.2", - "postcss-selector-parser": "^6.0.5", - "uniqs": "^2.0.0" + "postcss-selector-parser": "^6.0.5" } }, "postcss-value-parser": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.1.0.tgz", - "integrity": "sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ==" + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" }, "postcss-zindex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/postcss-zindex/-/postcss-zindex-5.0.1.tgz", - "integrity": "sha512-nwgtJJys+XmmSGoYCcgkf/VczP8Mp/0OfSv3v0+fw0uABY4yxw+eFs0Xp9nAZHIKnS5j+e9ywQ+RD+ONyvl5pA==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-zindex/-/postcss-zindex-5.1.0.tgz", + "integrity": "sha512-fgFMf0OtVSBR1va1JNHYgMxYk73yhn/qb4uQDq1DLGYolz8gHCyr/sesEuGUaYs58E3ZJRcpoGuPVoB7Meiq9A==", "requires": {} }, "prebuild-install": { - "version": "6.1.4", - "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-6.1.4.tgz", - "integrity": "sha512-Z4vpywnK1lBg+zdPCVCsKq0xO66eEV9rWo2zrROGGiRS4JtueBOdlB1FnY8lcy7JsUud/Q3ijUxyWN26Ika0vQ==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.0.tgz", + "integrity": "sha512-CNcMgI1xBypOyGqjp3wOc8AAo1nMhZS3Cwd3iHIxOdAUbb+YxdNuM4Z5iIrZ8RLvOsf3F3bl7b7xGq6DjQoNYA==", "requires": { - "detect-libc": "^1.0.3", + "detect-libc": "^2.0.0", "expand-template": "^2.0.3", "github-from-package": "0.0.0", "minimist": "^1.2.3", "mkdirp-classic": "^0.5.3", "napi-build-utils": "^1.0.1", - "node-abi": "^2.21.0", + "node-abi": "^3.3.0", "npmlog": "^4.0.1", "pump": "^3.0.0", "rc": "^1.2.7", - "simple-get": "^3.0.3", + "simple-get": "^4.0.0", "tar-fs": "^2.0.0", "tunnel-agent": "^0.6.0" } }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==", + "dev": true + }, "prepend-http": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=" }, + "pretty-bytes": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz", + "integrity": "sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==", + "dev": true + }, "pretty-error": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-3.0.4.tgz", - "integrity": "sha512-ytLFLfv1So4AO1UkoBF6GXQgJRaKbiSiGFICaOPNwQ3CMvBvXpLRubeQWyPGnsbV/t9ml9qto6IeCsho0aEvwQ==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-4.0.0.tgz", + "integrity": "sha512-AoJ5YMAcXKYxKhuJGdcvse+Voc6v1RgnsR3nWcYU7q4t6z0Q6T86sv5Zq8VIRbOWWFpvdGE83LtdSMNd+6Y0xw==", "requires": { "lodash": "^4.17.20", - "renderkid": "^2.0.6" + "renderkid": "^3.0.0" + } + }, + "pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "dependencies": { + "ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true + }, + "react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "dev": true + } } }, "pretty-time": { @@ -26606,15 +35048,15 @@ "integrity": "sha512-28iF6xPQrP8Oa6uxE6a1biz+lWeTOAPKggvjB8HAs6nVMKZwf5bG++632Dx614hIWgUPkgivRfG+a8uAXGTIbA==" }, "prism-react-renderer": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prism-react-renderer/-/prism-react-renderer-1.2.1.tgz", - "integrity": "sha512-w23ch4f75V1Tnz8DajsYKvY5lF7H1+WvzvLUcF0paFxkTHSp42RS0H5CttdN2Q8RR3DRGZ9v5xD/h3n8C8kGmg==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/prism-react-renderer/-/prism-react-renderer-1.3.1.tgz", + "integrity": "sha512-xUeDMEz074d0zc5y6rxiMp/dlC7C+5IDDlaEUlcBOFE2wddz7hz5PNupb087mPwTt7T9BrFmewObfCBuf/LKwQ==", "requires": {} }, "prismjs": { - "version": "1.25.0", - "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.25.0.tgz", - "integrity": "sha512-WCjJHl1KEWbnkQom1+SzftbtXMKQoezOCYs5rECqMN+jP+apI7ftoflyqigqzopSO3hMhTEb0mFClA8lkolgEg==" + "version": "1.28.0", + "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.28.0.tgz", + "integrity": "sha512-8aaXdYvl1F7iC7Xm1spqSaY/OJBpYW3v+KJ+F17iYxvdc8sfjW194COK5wVhMZX45tGteiBQgdvD/nhxcRwylw==" }, "process": { "version": "0.11.10", @@ -26644,13 +35086,20 @@ } }, "prop-types": { - "version": "15.7.2", - "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz", - "integrity": "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==", + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", "requires": { "loose-envify": "^1.4.0", "object-assign": "^4.1.1", - "react-is": "^16.8.1" + "react-is": "^16.13.1" + }, + "dependencies": { + "react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + } } }, "property-information": { @@ -26668,12 +35117,26 @@ "requires": { "forwarded": "0.2.0", "ipaddr.js": "1.9.1" + }, + "dependencies": { + "ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" + } } }, - "prr": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", - "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=" + "proxy-from-env": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.0.0.tgz", + "integrity": "sha512-F2JHgJQ1iqwnHDcQjVBsq3n/uoaFL+iPW/eAeL7kVxy/2RrWaN4WroKjjvbsoRtv0ftelNyC01bjRhn/bhcf4A==", + "dev": true + }, + "psl": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", + "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==", + "dev": true }, "public-encrypt": { "version": "4.0.3", @@ -26728,24 +35191,30 @@ "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=" }, "qs": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", - "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==" + "version": "6.10.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz", + "integrity": "sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==", + "requires": { + "side-channel": "^1.0.4" + } }, "querystring": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", - "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=" + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.1.tgz", + "integrity": "sha512-wkvS7mL/JMugcup3/rMitHmd9ecIGd2lhFhK9N3UUQ450h66d1r3Y9nvXzQAW1Lq+wyx61k/1pfKS5KuKiyEbg==" }, "querystring-es3": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=" }, - "querystringify": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", - "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==" + "queue": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/queue/-/queue-6.0.2.tgz", + "integrity": "sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA==", + "requires": { + "inherits": "~2.0.3" + } }, "queue-microtask": { "version": "1.2.3", @@ -26770,19 +35239,26 @@ } }, "range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", + "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=" }, "raw-body": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", - "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", + "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", "requires": { - "bytes": "3.1.0", - "http-errors": "1.7.2", + "bytes": "3.1.2", + "http-errors": "2.0.0", "iconv-lite": "0.4.24", "unpipe": "1.0.0" + }, + "dependencies": { + "bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==" + } } }, "rc": { @@ -26794,6 +35270,13 @@ "ini": "~1.3.0", "minimist": "^1.2.0", "strip-json-comments": "~2.0.1" + }, + "dependencies": { + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" + } } }, "react": { @@ -26817,132 +35300,120 @@ } }, "react-dev-utils": { - "version": "11.0.4", - "resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-11.0.4.tgz", - "integrity": "sha512-dx0LvIGHcOPtKbeiSUM4jqpBl3TcY7CDjZdfOIcKeznE7BWr9dg0iPG90G5yfVQ+p/rGNMXdbfStvzQZEVEi4A==", - "requires": { - "@babel/code-frame": "7.10.4", - "address": "1.1.2", - "browserslist": "4.14.2", - "chalk": "2.4.2", - "cross-spawn": "7.0.3", - "detect-port-alt": "1.1.6", - "escape-string-regexp": "2.0.0", - "filesize": "6.1.0", - "find-up": "4.1.0", - "fork-ts-checker-webpack-plugin": "4.1.6", - "global-modules": "2.0.0", - "globby": "11.0.1", - "gzip-size": "5.1.1", - "immer": "8.0.1", - "is-root": "2.1.0", - "loader-utils": "2.0.0", - "open": "^7.0.2", - "pkg-up": "3.1.0", - "prompts": "2.4.0", - "react-error-overlay": "^6.0.9", - "recursive-readdir": "2.2.2", - "shell-quote": "1.7.2", - "strip-ansi": "6.0.0", - "text-table": "0.2.0" - }, - "dependencies": { - "@babel/code-frame": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", - "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", - "requires": { - "@babel/highlight": "^7.10.4" - } - }, - "browserslist": { - "version": "4.14.2", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.14.2.tgz", - "integrity": "sha512-HI4lPveGKUR0x2StIz+2FXfDk9SfVMrxn6PLh1JeGUwcuoDkdKZebWiyLRJ68iIPDpMI4JLVDf7S7XzslgWOhw==", + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-12.0.1.tgz", + "integrity": "sha512-84Ivxmr17KjUupyqzFode6xKhjwuEJDROWKJy/BthkL7Wn6NJ8h4WE6k/exAv6ImS+0oZLRRW5j/aINMHyeGeQ==", + "requires": { + "@babel/code-frame": "^7.16.0", + "address": "^1.1.2", + "browserslist": "^4.18.1", + "chalk": "^4.1.2", + "cross-spawn": "^7.0.3", + "detect-port-alt": "^1.1.6", + "escape-string-regexp": "^4.0.0", + "filesize": "^8.0.6", + "find-up": "^5.0.0", + "fork-ts-checker-webpack-plugin": "^6.5.0", + "global-modules": "^2.0.0", + "globby": "^11.0.4", + "gzip-size": "^6.0.0", + "immer": "^9.0.7", + "is-root": "^2.1.0", + "loader-utils": "^3.2.0", + "open": "^8.4.0", + "pkg-up": "^3.1.0", + "prompts": "^2.4.2", + "react-error-overlay": "^6.0.11", + "recursive-readdir": "^2.2.2", + "shell-quote": "^1.7.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "requires": { - "caniuse-lite": "^1.0.30001125", - "electron-to-chromium": "^1.3.564", - "escalade": "^3.0.2", - "node-releases": "^1.1.61" + "color-convert": "^2.0.1" } }, "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "dependencies": { - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" - } + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" } }, - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "requires": { - "ms": "2.0.0" + "color-name": "~1.1.4" } }, - "detect-port-alt": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/detect-port-alt/-/detect-port-alt-1.1.6.tgz", - "integrity": "sha512-5tQykt+LqfJFBEYaDITx7S7cR7mJ/zQmLXZ2qt5w04ainYZw6tBf9dBunMjVeVOdYVRUzUOE4HkY5J7+uttb5Q==", - "requires": { - "address": "^1.0.1", - "debug": "^2.6.0" - } + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, "escape-string-regexp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", - "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==" + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==" }, - "globby": { - "version": "11.0.1", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.1.tgz", - "integrity": "sha512-iH9RmgwCmUJHi2z5o2l3eTtGBtXek1OYlHrbcxOYugyHLmAsZrPj43OtHThd62Buh/Vv6VyCBD2bdyWcGNQqoQ==", + "find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", "requires": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.1.1", - "ignore": "^5.1.4", - "merge2": "^1.3.0", - "slash": "^3.0.0" + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" } }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" }, - "node-releases": { - "version": "1.1.77", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.77.tgz", - "integrity": "sha512-rB1DUFUNAN4Gn9keO2K1efO35IDK7yKHCdCaIMvFO7yUYmmZYeDjnGKle26G4rwj+LKRQpjyUUvMkPglwGCYNQ==" + "loader-utils": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-3.2.0.tgz", + "integrity": "sha512-HVl9ZqccQihZ7JM85dco1MvO9G+ONvxoGa9rkhzFsneGLKSUg1gJf9bWzhRhcvm2qChhWpebQhP44qxjKIUCaQ==" }, - "prompts": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.0.tgz", - "integrity": "sha512-awZAKrk3vN6CroQukBL+R9051a4R3zCZBlJm/HBfrSZ8iTpYix3VX1vU4mveiLpiwmOJT4wokTF9m6HUk4KqWQ==", + "locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "requires": { - "kleur": "^3.0.3", - "sisteransi": "^1.0.5" + "p-locate": "^5.0.0" } }, - "strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "requires": { - "ansi-regex": "^5.0.0" + "yocto-queue": "^0.1.0" + } + }, + "p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "requires": { + "p-limit": "^3.0.2" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "requires": { + "has-flag": "^4.0.0" } } } @@ -26958,30 +35429,31 @@ } }, "react-error-overlay": { - "version": "6.0.9", - "resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.9.tgz", - "integrity": "sha512-nQTTcUu+ATDbrSD1BZHr5kgSD4oF8OFjxun8uAaL8RwPBacGBNPf/yAuVVdx17N8XNzRDMrZ9XcKZHCjPW+9ew==" + "version": "6.0.11", + "resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.11.tgz", + "integrity": "sha512-/6UZ2qgEyH2aqzYZgQPxEnz33NJ2gNsnHA2o5+o4wW9bLM/JYQitNP9xPhsXwC08hMMovfGe/8retsdDsczPRg==" }, "react-fast-compare": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.0.tgz", "integrity": "sha512-rtGImPZ0YyLrscKI9xTpV8psd6I8VAtjKCzQDlzyDvqJA8XOW78TXYQwNRNd8g8JZnDu8q9Fu/1v4HPAVwVdHA==" }, - "react-helmet": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/react-helmet/-/react-helmet-6.1.0.tgz", - "integrity": "sha512-4uMzEY9nlDlgxr61NL3XbKRy1hEkXmKNXhjbAIOVw5vcFrsdYbH2FEwcNyWvWinl103nXgzYNlns9ca+8kFiWw==", + "react-helmet-async": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/react-helmet-async/-/react-helmet-async-1.3.0.tgz", + "integrity": "sha512-9jZ57/dAn9t3q6hneQS0wukqC2ENOBgMNVEhb/ZG9ZSxUetzVIw4iAmEU38IaVg3QGYauQPhSeUTuIUtFglWpg==", "requires": { - "object-assign": "^4.1.1", + "@babel/runtime": "^7.12.5", + "invariant": "^2.2.4", "prop-types": "^15.7.2", - "react-fast-compare": "^3.1.1", - "react-side-effect": "^2.1.0" + "react-fast-compare": "^3.2.0", + "shallowequal": "^1.1.0" } }, "react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + "version": "18.1.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.1.0.tgz", + "integrity": "sha512-Fl7FuabXsJnV5Q1qIOQwx/sagGF18kogb4gpfcG4gjLBWO0WDiiz1ko/ExayuxE7InyQkBLkxRFG5oxY6Uu3Kg==" }, "react-json-view": { "version": "1.21.3", @@ -27000,11 +35472,12 @@ "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==" }, "react-loadable": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/react-loadable/-/react-loadable-5.5.0.tgz", - "integrity": "sha512-C8Aui0ZpMd4KokxRdVAm2bQtI03k2RMRNzOB+IipV3yxFTSVICv7WoUr5L9ALB5BmKO1iHgZtWM8EvYG83otdg==", + "version": "npm:@docusaurus/react-loadable@5.5.2", + "resolved": "https://registry.npmjs.org/@docusaurus/react-loadable/-/react-loadable-5.5.2.tgz", + "integrity": "sha512-A3dYjdBGuy0IGT+wyLIGIKLRE+sAk1iNk0f1HjNDysO7u8lhL4N3VEm+FAubmJbAztn94F7MxBTPmnixbiyFdQ==", "requires": { - "prop-types": "^15.5.0" + "@types/react": "*", + "prop-types": "^15.6.2" } }, "react-loadable-ssr-addon-v5-slorber": { @@ -27016,9 +35489,9 @@ } }, "react-router": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/react-router/-/react-router-5.2.1.tgz", - "integrity": "sha512-lIboRiOtDLFdg1VTemMwud9vRVuOCZmUIT/7lUoZiSpPODiiH1UQlfXy+vPLC/7IWdFYnhRwAyNqA/+I7wnvKQ==", + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-5.3.1.tgz", + "integrity": "sha512-v+zwjqb7bakqgF+wMVKlAPTca/cEmPOvQ9zt7gpSNyPXau1+0qvuYZ5BWzzNDP1y6s15zDwgb9rPN63+SIniRQ==", "requires": { "@babel/runtime": "^7.12.13", "history": "^4.9.0", @@ -27032,18 +35505,10 @@ "tiny-warning": "^1.0.0" }, "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" - }, - "path-to-regexp": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", - "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", - "requires": { - "isarray": "0.0.1" - } + "react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" } } }, @@ -27056,29 +35521,23 @@ } }, "react-router-dom": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-5.3.0.tgz", - "integrity": "sha512-ObVBLjUZsphUUMVycibxgMdh5jJ1e3o+KpAZBVeHcNQZ4W+uUGGWsokurzlF4YOldQYRQL4y6yFRWM4m3svmuQ==", + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-5.3.1.tgz", + "integrity": "sha512-f0pj/gMAbv9e8gahTmCEY20oFhxhrmHwYeIwH5EO5xu0qme+wXtsdB8YfUOAZzUz4VaXmb58m3ceiLtjMhqYmQ==", "requires": { "@babel/runtime": "^7.12.13", "history": "^4.9.0", "loose-envify": "^1.3.1", "prop-types": "^15.6.2", - "react-router": "5.2.1", + "react-router": "5.3.1", "tiny-invariant": "^1.0.2", "tiny-warning": "^1.0.0" } }, - "react-side-effect": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/react-side-effect/-/react-side-effect-2.1.1.tgz", - "integrity": "sha512-2FoTQzRNTncBVtnzxFOk2mCpcfxQpenBMbk5kSVBg5UcPqV9fRbgY2zhb7GTWWOlpFmAxhClBDlIq8Rsubz1yQ==", - "requires": {} - }, "react-tabs": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/react-tabs/-/react-tabs-3.2.2.tgz", - "integrity": "sha512-/o52eGKxFHRa+ssuTEgSM8qORnV4+k7ibW+aNQzKe+5gifeVz8nLxCrsI9xdRhfb0wCLdgIambIpb1qCxaMN+A==", + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/react-tabs/-/react-tabs-3.2.3.tgz", + "integrity": "sha512-jx325RhRVnS9DdFbeF511z0T0WEqEoMl1uCE3LoZ6VaZZm7ytatxbum0B8bCTmaiV0KsU+4TtLGTGevCic7SWg==", "requires": { "clsx": "^1.1.0", "prop-types": "^15.5.0" @@ -27094,6 +35553,15 @@ "use-latest": "^1.0.0" } }, + "react-tooltip": { + "version": "4.2.21", + "resolved": "https://registry.npmjs.org/react-tooltip/-/react-tooltip-4.2.21.tgz", + "integrity": "sha512-zSLprMymBDowknr0KVDiJ05IjZn9mQhhg4PRsqln0OZtURAJ1snt1xi5daZfagsh6vfsziZrc9pErPTDY1ACig==", + "requires": { + "prop-types": "^15.7.2", + "uuid": "^7.0.3" + } + }, "react-waypoint": { "version": "10.1.0", "resolved": "https://registry.npmjs.org/react-waypoint/-/react-waypoint-10.1.0.tgz", @@ -27149,37 +35617,69 @@ "integrity": "sha512-nRCcW9Sj7NuZwa2XvH9co8NPeXUBhZP7CRKJtU+cS6PW9FpCIFoI5ib0NT1ZrbNuPoRy0ylyCaUL8Gih4LSyFg==", "requires": { "minimatch": "3.0.4" + }, + "dependencies": { + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "requires": { + "brace-expansion": "^1.1.7" + } + } + } + }, + "redent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", + "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", + "dev": true, + "requires": { + "indent-string": "^4.0.0", + "strip-indent": "^3.0.0" } }, "redoc": { - "version": "2.0.0-rc.57", - "resolved": "https://registry.npmjs.org/redoc/-/redoc-2.0.0-rc.57.tgz", - "integrity": "sha512-f8XIqvZF1agphq6xmOU9jTDVNDFHJt3MzDq1lUgZojb/7YY4eqLyDi6er/yCWYkY9DuB+v2jHCOn5UUbMuKAfg==", + "version": "2.0.0-rc.67", + "resolved": "https://registry.npmjs.org/redoc/-/redoc-2.0.0-rc.67.tgz", + "integrity": "sha512-u6rEKB0LylSisN+mFa3flj7zf+prXDB+G02foqC9BOlcXkUYXHFDZM4L3BTBL/DstyGTgjhe2dA9csAjIVti/g==", "requires": { - "@babel/runtime": "^7.14.0", - "@redocly/openapi-core": "^1.0.0-beta.54", + "@redocly/openapi-core": "^1.0.0-beta.88", "@redocly/react-dropdown-aria": "^2.0.11", "classnames": "^2.3.1", "decko": "^1.2.0", "dompurify": "^2.2.8", "eventemitter3": "^4.0.7", - "json-pointer": "^0.6.1", + "json-pointer": "^0.6.2", "lunr": "^2.3.9", "mark.js": "^8.11.1", - "marked": "^0.7.0", - "memoize-one": "^5.2.1", + "marked": "^4.0.10", "mobx-react": "^7.2.0", - "openapi-sampler": "^1.0.1", + "openapi-sampler": "^1.2.1", "path-browserify": "^1.0.1", "perfect-scrollbar": "^1.5.1", "polished": "^4.1.3", - "prismjs": "^1.24.1", + "prismjs": "^1.27.0", "prop-types": "^15.7.2", "react-tabs": "^3.2.2", "slugify": "~1.4.7", "stickyfill": "^1.1.1", + "style-loader": "^3.3.1", "swagger2openapi": "^7.0.6", "url-template": "^2.0.8" + }, + "dependencies": { + "slugify": { + "version": "1.4.7", + "resolved": "https://registry.npmjs.org/slugify/-/slugify-1.4.7.tgz", + "integrity": "sha512-tf+h5W1IrjNm/9rKKj0JU2MDMruiopx0jjVA5zCdBtcGjfp0+c5rHw/zADLC3IeKlGHtVbHtpfzvYA0OYT+HKg==" + }, + "style-loader": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-3.3.1.tgz", + "integrity": "sha512-GPcQ+LDJbrcxHORTRes6Jy2sfvK2kS6hpSfI/fXhPt+spVzxF6LJ1dHLN9zIGmVaaP044YKaIatFaufENRiDoQ==", + "requires": {} + } } }, "reftools": { @@ -27193,9 +35693,9 @@ "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==" }, "regenerate-unicode-properties": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-9.0.0.tgz", - "integrity": "sha512-3E12UeNSPfjrgwjkR81m5J7Aw/T55Tu7nUyZVQYCKEOs+2dkxEY+DpPtZzO4YruuiPb7NkYLVcyJC4+zCbk5pA==", + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.0.1.tgz", + "integrity": "sha512-vn5DU6yg6h8hP/2OkQo3K7uVILvY4iu0oI4t3HFa81UPkhGJwkRwM10JEc3upjdhHjs/k8GJY1sRBhk5sr69Bw==", "requires": { "regenerate": "^1.4.2" } @@ -27203,62 +35703,25 @@ "regenerator-runtime": { "version": "0.13.9", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz", - "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==" - }, - "regenerator-transform": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.5.tgz", - "integrity": "sha512-eOf6vka5IO151Jfsw2NO9WpGX58W6wWmefK3I1zEGr0lOD0u8rwPaNqQL1aRxUaxLeKO3ArNh3VYg1KbaD+FFw==", - "requires": { - "@babel/runtime": "^7.8.4" - } - }, - "regex-not": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", - "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", - "requires": { - "extend-shallow": "^3.0.2", - "safe-regex": "^1.1.0" - }, - "dependencies": { - "extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "requires": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - } - }, - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "requires": { - "is-plain-object": "^2.0.4" - } - } - } + "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==" }, - "regexp.prototype.flags": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.3.1.tgz", - "integrity": "sha512-JiBdRBq91WlY7uRJ0ds7R+dU02i6LKi8r3BuQhNXn+kmeLN+EfHhfjqMRis1zJxnlu88hq/4dx0P2OP3APRTOA==", + "regenerator-transform": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.0.tgz", + "integrity": "sha512-LsrGtPmbYg19bcPHwdtmXwbW+TqNvtY4riE3P83foeHRroMbH6/2ddFBfab3t7kbzc7v7p4wbkIecHImqt0QNg==", "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" + "@babel/runtime": "^7.8.4" } }, "regexpu-core": { - "version": "4.8.0", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.8.0.tgz", - "integrity": "sha512-1F6bYsoYiz6is+oz70NWur2Vlh9KWtswuRuzJOfeYUrfPX2o8n74AnUVaOGDbUqVGO9fNHu48/pjJO4sNVwsOg==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.0.1.tgz", + "integrity": "sha512-CriEZlrKK9VJw/xQGJpQM5rY88BtuL8DM+AEwvcThHilbxiTAy8vq4iJnd2tqq8wLmjbGZzP7ZcKFjbGkmEFrw==", "requires": { "regenerate": "^1.4.2", - "regenerate-unicode-properties": "^9.0.0", - "regjsgen": "^0.5.2", - "regjsparser": "^0.7.0", + "regenerate-unicode-properties": "^10.0.1", + "regjsgen": "^0.6.0", + "regjsparser": "^0.8.2", "unicode-match-property-ecmascript": "^2.0.0", "unicode-match-property-value-ecmascript": "^2.0.0" } @@ -27280,14 +35743,14 @@ } }, "regjsgen": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.2.tgz", - "integrity": "sha512-OFFT3MfrH90xIW8OOSyUrk6QHD5E9JOTeGodiJeBS3J6IwlgzJMNE/1bZklWz5oTg+9dCMyEetclvCVXOPoN3A==" + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.6.0.tgz", + "integrity": "sha512-ozE883Uigtqj3bx7OhL1KNbCzGyW2NQZPl6Hs09WTvCuZD5sTI4JY58bkbQWa/Y9hxIsvJ3M8Nbf7j54IqeZbA==" }, "regjsparser": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.7.0.tgz", - "integrity": "sha512-A4pcaORqmNMDVwUjWoTzuhwMGpP+NykpfqAsEgI1FSH/EzC7lrN5TMd+kN8YCovX+jMpu8eaqXgXPCa0g8FQNQ==", + "version": "0.8.4", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.8.4.tgz", + "integrity": "sha512-J3LABycON/VNEu3abOviqGHuB/LOtOQj8SKmfP9anY5GfAVw/SPjwzSjxGjbZXIxbGfqTHtJw58C2Li/WkStmA==", "requires": { "jsesc": "~0.5.0" }, @@ -27299,6 +35762,30 @@ } } }, + "rehype-katex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/rehype-katex/-/rehype-katex-5.0.0.tgz", + "integrity": "sha512-ksSuEKCql/IiIadOHiKRMjypva9BLhuwQNascMqaoGLDVd0k2NlE2wMvgZ3rpItzRKCd6vs8s7MFbb8pcR0AEg==", + "requires": { + "@types/katex": "^0.11.0", + "hast-util-to-text": "^2.0.0", + "katex": "^0.13.0", + "rehype-parse": "^7.0.0", + "unified": "^9.0.0", + "unist-util-visit": "^2.0.0" + }, + "dependencies": { + "rehype-parse": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/rehype-parse/-/rehype-parse-7.0.1.tgz", + "integrity": "sha512-fOiR9a9xH+Le19i4fGzIEowAbwG7idy2Jzs4mOrFWBSJ0sNUgy0ev871dwWnbOo371SjgjG4pwzrbgSVrKxecw==", + "requires": { + "hast-util-from-parse5": "^6.0.0", + "parse5": "^6.0.0" + } + } + } + }, "rehype-parse": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/rehype-parse/-/rehype-parse-6.0.2.tgz", @@ -27307,6 +35794,36 @@ "hast-util-from-parse5": "^5.0.0", "parse5": "^5.0.0", "xtend": "^4.0.0" + }, + "dependencies": { + "hast-util-from-parse5": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-5.0.3.tgz", + "integrity": "sha512-gOc8UB99F6eWVWFtM9jUikjN7QkWxB3nY0df5Z0Zq1/Nkwl5V4hAAsl0tmwlgWl/1shlTF8DnNYLO8X6wRV9pA==", + "requires": { + "ccount": "^1.0.3", + "hastscript": "^5.0.0", + "property-information": "^5.0.0", + "web-namespaces": "^1.1.2", + "xtend": "^4.0.1" + } + }, + "hastscript": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/hastscript/-/hastscript-5.1.2.tgz", + "integrity": "sha512-WlztFuK+Lrvi3EggsqOkQ52rKbxkXL3RwB6t5lwoa8QLMemoWfBuL43eDrwOamJyR7uKQKdmKYaBH1NZBiIRrQ==", + "requires": { + "comma-separated-tokens": "^1.0.0", + "hast-util-parse-selector": "^2.0.0", + "property-information": "^5.0.0", + "space-separated-tokens": "^1.0.0" + } + }, + "parse5": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.1.tgz", + "integrity": "sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug==" + } } }, "relateurl": { @@ -27322,6 +35839,20 @@ "rehype-parse": "^6.0.2", "unified": "^8.4.2", "unist-util-visit": "^2.0.1" + }, + "dependencies": { + "unified": { + "version": "8.4.2", + "resolved": "https://registry.npmjs.org/unified/-/unified-8.4.2.tgz", + "integrity": "sha512-JCrmN13jI4+h9UAyKEoGcDZV+i1E7BLFuG7OsaDvTXI5P0qhHX+vZO/kOhz9jn8HGENDKbwSeB0nVOg4gVStGA==", + "requires": { + "bail": "^1.0.0", + "extend": "^3.0.0", + "is-plain-obj": "^2.0.0", + "trough": "^1.0.0", + "vfile": "^4.0.0" + } + } } }, "remark-emoji": { @@ -27339,6 +35870,11 @@ "resolved": "https://registry.npmjs.org/remark-footnotes/-/remark-footnotes-2.0.0.tgz", "integrity": "sha512-3Clt8ZMH75Ayjp9q4CorNeyjwIxHFcTkaektplKGl2A1jNGEUey8cKL0ZC5vJwfcD5GFGsNLImLG/NGzWIzoMQ==" }, + "remark-math": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/remark-math/-/remark-math-3.0.1.tgz", + "integrity": "sha512-epT77R/HK0x7NqrWHdSV75uNLwn8g9qTyMqCRCDujL0vj/6T6+yhdrR7mjELWtkse+Fw02kijAaBuVcHBor1+Q==" + }, "remark-mdx": { "version": "1.6.22", "resolved": "https://registry.npmjs.org/remark-mdx/-/remark-mdx-1.6.22.tgz", @@ -27400,28 +35936,15 @@ "@babel/helper-plugin-utils": "^7.10.4" } }, - "is-buffer": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz", - "integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==" - }, "semver": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" }, - "unified": { - "version": "9.2.0", - "resolved": "https://registry.npmjs.org/unified/-/unified-9.2.0.tgz", - "integrity": "sha512-vx2Z0vY+a3YoTj8+pttM3tiJHCwY5UFbYdiWrwBEbHmK8pvsPj2rtAX2BFfgXen8T39CJWblWRDT4L5WGXtDdg==", - "requires": { - "bail": "^1.0.0", - "extend": "^3.0.0", - "is-buffer": "^2.0.0", - "is-plain-obj": "^2.0.0", - "trough": "^1.0.0", - "vfile": "^4.0.0" - } + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" } } }, @@ -27456,59 +35979,32 @@ "mdast-squeeze-paragraphs": "^4.0.0" } }, - "remove-trailing-separator": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", - "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=" - }, "renderkid": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-2.0.7.tgz", - "integrity": "sha512-oCcFyxaMrKsKcTY59qnCAtmDVSLfPbrv6A3tVbPdFMMrv5jaK10V6m40cKsoPNhAqN6rmHW9sswW4o3ruSrwUQ==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-3.0.0.tgz", + "integrity": "sha512-q/7VIQA8lmM1hF+jn+sFSPWGlMkSAeNYcPLmDQx2zzuiDfaLrOmumR8iaUKlenFgh0XRPIUeSPlH3A+AW3Z5pg==", "requires": { "css-select": "^4.1.3", "dom-converter": "^0.2.0", "htmlparser2": "^6.1.0", "lodash": "^4.17.21", - "strip-ansi": "^3.0.1" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" - }, - "htmlparser2": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", - "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", - "requires": { - "domelementtype": "^2.0.1", - "domhandler": "^4.0.0", - "domutils": "^2.5.2", - "entities": "^2.0.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "requires": { - "ansi-regex": "^2.0.0" - } - } + "strip-ansi": "^6.0.1" } }, - "repeat-element": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.4.tgz", - "integrity": "sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ==" - }, "repeat-string": { "version": "1.6.1", "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=" }, + "request-progress": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/request-progress/-/request-progress-3.0.0.tgz", + "integrity": "sha512-MnWzEHHaxHO2iWiQuHrUPBi/1WeBf5PkxQqNyNvLl9VAYSdXkP8tQ3pBSeCPD+yw0v0Aq1zosWLz0BdeXpWwZg==", + "dev": true, + "requires": { + "throttleit": "^1.0.0" + } + }, "require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -27524,37 +36020,35 @@ "resolved": "https://registry.npmjs.org/require-like/-/require-like-0.1.2.tgz", "integrity": "sha1-rW8wwTvs15cBDEaK+ndcDAprR/o=" }, - "require-main-filename": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==" - }, "requires-port": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=" }, "resolve": { - "version": "1.20.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", - "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", + "version": "1.22.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz", + "integrity": "sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==", "requires": { - "is-core-module": "^2.2.0", - "path-parse": "^1.0.6" + "is-core-module": "^2.8.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" } }, "resolve-cwd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-2.0.0.tgz", - "integrity": "sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", + "dev": true, "requires": { - "resolve-from": "^3.0.0" + "resolve-from": "^5.0.0" }, "dependencies": { "resolve-from": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", - "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=" + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true } } }, @@ -27568,10 +36062,11 @@ "resolved": "https://registry.npmjs.org/resolve-pathname/-/resolve-pathname-3.0.0.tgz", "integrity": "sha512-C7rARubxI8bXFNB/hqcp/4iUeIXJhJZvFPFPiSPRnhU5UPxzMFIl+2E6yY6c4k9giDJAhtV+enfA+G89N6Csng==" }, - "resolve-url": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", - "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=" + "resolve.exports": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-1.1.0.tgz", + "integrity": "sha512-J1l+Zxxp4XK3LUDZ9m60LRJF/mAe4z6a4xyabPHk7pvK5t35dACV32iIjJDFeWZFfZlO29w6SZ67knR0tHzJtQ==", + "dev": true }, "responselike": { "version": "1.0.2", @@ -27581,21 +36076,32 @@ "lowercase-keys": "^1.0.0" } }, - "ret": { - "version": "0.1.15", - "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", - "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==" + "restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "dev": true, + "requires": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + } }, "retry": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", - "integrity": "sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs=" + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", + "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==" }, "reusify": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==" }, + "rfdc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", + "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==", + "dev": true + }, "rimraf": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", @@ -27619,14 +36125,13 @@ "integrity": "sha512-EBR4I2VDSSYr7PkBmFy04uhycIpDKp+21p/jARYXlCSjQksTBQcJ0HFUPOO79EPPH5JS6VAhiIQbycf0O3JAxQ==" }, "rtlcss": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/rtlcss/-/rtlcss-3.3.0.tgz", - "integrity": "sha512-XZ2KEatH2nU5yPlts1Wu8SGIuZ3ndN025HQX5MqtUCUiOn5WkCDbcpJ2VJWjpuFmM2cUTQ1xtH21fhMCSseI5A==", + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/rtlcss/-/rtlcss-3.5.0.tgz", + "integrity": "sha512-wzgMaMFHQTnyi9YOwsx9LjOxYXJPzS8sYnFaKm6R5ysvTkwzHiB0vxnbHwchHQT65PTdBjDG21/kQBWI7q9O7A==", "requires": { - "chalk": "^4.1.0", "find-up": "^5.0.0", - "mkdirp": "^1.0.4", - "postcss": "^8.2.4", + "picocolors": "^1.0.0", + "postcss": "^8.3.11", "strip-json-comments": "^3.1.1" }, "dependencies": { @@ -27647,10 +36152,13 @@ "p-locate": "^5.0.0" } }, - "mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==" + "p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "requires": { + "yocto-queue": "^0.1.0" + } }, "p-locate": { "version": "5.0.0", @@ -27659,11 +36167,6 @@ "requires": { "p-limit": "^3.0.2" } - }, - "strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==" } } }, @@ -27676,18 +36179,11 @@ } }, "rxjs": { - "version": "6.6.7", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", - "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.5.5.tgz", + "integrity": "sha512-sy+H0pQofO95VDmFLzyaw9xNJU4KTRSwQIGM6+iG3SypAtCiLDzpeG8sJrNCWn2Up9km+KhkvTdbkrdy+yzZdw==", "requires": { - "tslib": "^1.9.0" - }, - "dependencies": { - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" - } + "tslib": "^2.1.0" } }, "safe-buffer": { @@ -27695,14 +36191,6 @@ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" }, - "safe-regex": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", - "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", - "requires": { - "ret": "~0.1.10" - } - }, "safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", @@ -27713,6 +36201,15 @@ "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" }, + "saxes": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/saxes/-/saxes-5.0.1.tgz", + "integrity": "sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw==", + "dev": true, + "requires": { + "xmlchars": "^2.2.0" + } + }, "scheduler": { "version": "0.20.2", "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.20.2.tgz", @@ -27723,12 +36220,12 @@ } }, "schema-utils": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", - "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz", + "integrity": "sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==", "requires": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", + "@types/json-schema": "^7.0.5", + "ajv": "^6.12.4", "ajv-keywords": "^3.5.2" } }, @@ -27747,17 +36244,17 @@ "integrity": "sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo=" }, "selfsigned": { - "version": "1.10.11", - "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-1.10.11.tgz", - "integrity": "sha512-aVmbPOfViZqOZPgRBT0+3u4yZFHpmnIghLMlAcb5/xhp5ZtB/RVnKhz5vl2M32CLXAqR4kha9zfhNg0Lf/sxKA==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.0.1.tgz", + "integrity": "sha512-LmME957M1zOsUhG+67rAjKfiWFox3SBxE/yymatMZsAx+oMrJ0YQ8AToOnyCm7xbeg2ep37IHLxdu0o2MavQOQ==", "requires": { - "node-forge": "^0.10.0" + "node-forge": "^1" } }, "semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "version": "7.3.7", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", + "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", "requires": { "lru-cache": "^6.0.0" } @@ -27778,23 +36275,23 @@ } }, "send": { - "version": "0.17.1", - "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", - "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", + "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", "requires": { "debug": "2.6.9", - "depd": "~1.1.2", - "destroy": "~1.0.4", + "depd": "2.0.0", + "destroy": "1.2.0", "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "etag": "~1.8.1", "fresh": "0.5.2", - "http-errors": "~1.7.2", + "http-errors": "2.0.0", "mime": "1.6.0", - "ms": "2.1.1", - "on-finished": "~2.3.0", + "ms": "2.1.3", + "on-finished": "2.4.1", "range-parser": "~1.2.1", - "statuses": "~1.5.0" + "statuses": "2.0.1" }, "dependencies": { "debug": { @@ -27808,14 +36305,19 @@ "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" } } }, "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" } } }, @@ -27842,16 +36344,6 @@ "range-parser": "1.2.0" }, "dependencies": { - "bytes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", - "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=" - }, - "content-disposition": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", - "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ=" - }, "mime-db": { "version": "1.33.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz", @@ -27865,15 +36357,18 @@ "mime-db": "~1.33.0" } }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "requires": { + "brace-expansion": "^1.1.7" + } + }, "path-to-regexp": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-2.2.1.tgz", "integrity": "sha512-gu9bD6Ta5bwGrrU8muHzVOBFFREpp2iRkVfhBJahwJ6p6Xw20SjT0MxLnwkjOibQmGSYhiUnf2FLe7k+jcFmGQ==" - }, - "range-parser": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", - "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=" } } }, @@ -27899,6 +36394,11 @@ "ms": "2.0.0" } }, + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==" + }, "http-errors": { "version": "1.6.3", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", @@ -27924,18 +36424,23 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==" + }, + "statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" } } }, "serve-static": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", - "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", "requires": { "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "parseurl": "~1.3.3", - "send": "0.17.1" + "send": "0.18.0" } }, "set-blocking": { @@ -27943,26 +36448,15 @@ "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" }, - "set-value": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", - "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", - "requires": { - "extend-shallow": "^2.0.1", - "is-extendable": "^0.1.1", - "is-plain-object": "^2.0.3", - "split-string": "^3.0.1" - } - }, "setimmediate": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=" }, "setprototypeof": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", - "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" }, "sha.js": { "version": "2.4.11", @@ -27987,18 +36481,42 @@ "integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==" }, "sharp": { - "version": "0.28.3", - "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.28.3.tgz", - "integrity": "sha512-21GEP45Rmr7q2qcmdnjDkNP04Ooh5v0laGS5FDpojOO84D1DJwUijLiSq8XNNM6e8aGXYtoYRh3sVNdm8NodMA==", - "requires": { - "color": "^3.1.3", - "detect-libc": "^1.0.3", - "node-addon-api": "^3.2.0", - "prebuild-install": "^6.1.2", - "semver": "^7.3.5", - "simple-get": "^3.1.0", + "version": "0.30.4", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.30.4.tgz", + "integrity": "sha512-3Onig53Y6lji4NIZo69s14mERXXY/GV++6CzOYx/Rd8bnTwbhFbL09WZd7Ag/CCnA0WxFID8tkY0QReyfL6v0Q==", + "requires": { + "color": "^4.2.3", + "detect-libc": "^2.0.1", + "node-addon-api": "^4.3.0", + "prebuild-install": "^7.0.1", + "semver": "^7.3.7", + "simple-get": "^4.0.1", "tar-fs": "^2.1.1", "tunnel-agent": "^0.6.0" + }, + "dependencies": { + "color": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz", + "integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==", + "requires": { + "color-convert": "^2.0.1", + "color-string": "^1.9.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + } } }, "shebang-command": { @@ -28015,14 +36533,14 @@ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==" }, "shell-quote": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.2.tgz", - "integrity": "sha512-mRz/m/JVscCrkMyPqHc/bczi3OQHkLTqXHEFu0zDhK/qfv3UcOA4SVmRCLmos4bhjr9ekVQubj/R7waKapmiQg==" + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.3.tgz", + "integrity": "sha512-Vpfqwm4EnqGdlsBFNmHhxhElJYrdfcxPThu+ryKS5J8L/fhAwLazFZtq+S+TWZ9ANj2piSQLGj6NQg+lKPmxrw==" }, "shelljs": { - "version": "0.8.4", - "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.4.tgz", - "integrity": "sha512-7gk3UZ9kOfPLIAbslLzyWeGiEqx9e3rxwZM0KE6EL8GlGwjym9Mrlx5/p33bWTu9YG6vcS4MBxYZDHYr5lr8BQ==", + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.5.tgz", + "integrity": "sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==", "requires": { "glob": "^7.0.0", "interpret": "^1.0.0", @@ -28088,9 +36606,9 @@ } }, "signal-exit": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.5.tgz", - "integrity": "sha512-KWcOiKeQj6ZyXx7zq4YxSMgHRlod4czeBQZrPb8OKcohcqAXShm7E20kEMle9WBt26hFcAf0qLOcp5zmY7kOqQ==" + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" }, "simple-concat": { "version": "1.0.1", @@ -28098,28 +36616,13 @@ "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==" }, "simple-get": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-3.1.0.tgz", - "integrity": "sha512-bCR6cP+aTdScaQCnQKbPKtJOKDp/hj9EDLJo3Nw4y1QksqaovlW/bnptB6/c1e+qmNIDHRK+oXFDdEqBT8WzUA==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", "requires": { - "decompress-response": "^4.2.0", + "decompress-response": "^6.0.0", "once": "^1.3.1", "simple-concat": "^1.0.0" - }, - "dependencies": { - "decompress-response": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-4.2.1.tgz", - "integrity": "sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw==", - "requires": { - "mimic-response": "^2.0.0" - } - }, - "mimic-response": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-2.1.0.tgz", - "integrity": "sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==" - } } }, "simple-html-tokenizer": { @@ -28144,20 +36647,13 @@ } }, "sirv": { - "version": "1.0.17", - "resolved": "https://registry.npmjs.org/sirv/-/sirv-1.0.17.tgz", - "integrity": "sha512-qx9go5yraB7ekT7bCMqUHJ5jEaOC/GXBxUWv+jeWnb7WzHUFdcQPGWk7YmAwFBaQBrogpuSqd/azbC2lZRqqmw==", + "version": "1.0.19", + "resolved": "https://registry.npmjs.org/sirv/-/sirv-1.0.19.tgz", + "integrity": "sha512-JuLThK3TnZG1TAKDwNIqNq6QA2afLOCcm+iE8D1Kj3GA40pSPsxQjjJl0J8X3tsR7T+CP1GavpzLwYkgVLWrZQ==", "requires": { "@polka/url": "^1.0.0-next.20", - "mime": "^2.3.1", + "mrmime": "^1.0.0", "totalist": "^1.0.0" - }, - "dependencies": { - "mime": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.5.2.tgz", - "integrity": "sha512-tqkh47FzKeCPD2PUiPB6pkbMzsCasjxAfC62/Wap5qrUWcb+sFasXUC5I3gYM5iBM8v/Qpn4UK0x+j0iHyFPDg==" - } } }, "sisteransi": { @@ -28166,21 +36662,14 @@ "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==" }, "sitemap": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/sitemap/-/sitemap-7.0.0.tgz", - "integrity": "sha512-Ud0jrRQO2k7fEtPAM+cQkBKoMvxQyPKNXKDLn8tRVHxRCsdDQ2JZvw+aZ5IRYYQVAV9iGxEar6boTwZzev+x3g==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/sitemap/-/sitemap-7.1.1.tgz", + "integrity": "sha512-mK3aFtjz4VdJN0igpIJrinf3EO8U8mxOPsTBzSsy06UtjZQJ3YY3o3Xa7zSc5nMqcMrRwlChHZ18Kxg0caiPBg==", "requires": { - "@types/node": "^15.0.1", + "@types/node": "^17.0.5", "@types/sax": "^1.2.1", "arg": "^5.0.0", "sax": "^1.2.4" - }, - "dependencies": { - "@types/node": { - "version": "15.14.9", - "resolved": "https://registry.npmjs.org/@types/node/-/node-15.14.9.tgz", - "integrity": "sha512-qjd88DrCxupx/kJD5yQgZdcYKZKSIGBVDIBE1/LTGcNm3d2Np/jxojkdePDdfnBHJc5W7vSMpbJ1aB7p/Py69A==" - } } }, "slash": { @@ -28188,143 +36677,62 @@ "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==" }, - "slugify": { - "version": "1.4.7", - "resolved": "https://registry.npmjs.org/slugify/-/slugify-1.4.7.tgz", - "integrity": "sha512-tf+h5W1IrjNm/9rKKj0JU2MDMruiopx0jjVA5zCdBtcGjfp0+c5rHw/zADLC3IeKlGHtVbHtpfzvYA0OYT+HKg==" - }, - "snapdragon": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", - "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", - "requires": { - "base": "^0.11.1", - "debug": "^2.2.0", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "map-cache": "^0.2.2", - "source-map": "^0.5.6", - "source-map-resolve": "^0.5.0", - "use": "^3.1.0" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - }, - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - } - } - }, - "snapdragon-node": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", - "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", + "slice-ansi": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz", + "integrity": "sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==", + "dev": true, "requires": { - "define-property": "^1.0.0", - "isobject": "^3.0.0", - "snapdragon-util": "^3.0.1" + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" }, "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, "requires": { - "kind-of": "^6.0.0" + "color-convert": "^2.0.1" } }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, "requires": { - "kind-of": "^6.0.0" + "color-name": "~1.1.4" } }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true } } }, - "snapdragon-util": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", - "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", - "requires": { - "kind-of": "^3.2.0" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "^1.1.5" - } - } - } + "slugify": { + "version": "1.6.5", + "resolved": "https://registry.npmjs.org/slugify/-/slugify-1.6.5.tgz", + "integrity": "sha512-8mo9bslnBO3tr5PEVFzMPIWwWnipGS0xVbYf65zxDqfNwmzYn1LpiKNrR6DlClusuvo+hDHd1zKpmfAe83NQSQ==" }, "sockjs": { - "version": "0.3.21", - "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.21.tgz", - "integrity": "sha512-DhbPFGpxjc6Z3I+uX07Id5ZO2XwYsWOrYjaSeieES78cq+JaJvVe5q/m1uvjIQhXinhIeCFRH6JgXe+mvVMyXw==", + "version": "0.3.24", + "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz", + "integrity": "sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==", "requires": { "faye-websocket": "^0.11.3", - "uuid": "^3.4.0", + "uuid": "^8.3.2", "websocket-driver": "^0.7.4" - } - }, - "sockjs-client": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/sockjs-client/-/sockjs-client-1.5.2.tgz", - "integrity": "sha512-ZzRxPBISQE7RpzlH4tKJMQbHM9pabHluk0WBaxAQ+wm/UieeBVBou0p4wVnSQGN9QmpAZygQ0cDIypWuqOFmFQ==", - "requires": { - "debug": "^3.2.6", - "eventsource": "^1.0.7", - "faye-websocket": "^0.11.3", - "inherits": "^2.0.4", - "json3": "^3.3.3", - "url-parse": "^1.5.3" }, "dependencies": { - "debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "requires": { - "ms": "^2.1.1" - } + "uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" } } }, @@ -28339,48 +36747,34 @@ "integrity": "sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==" }, "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" }, "source-map-js": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-0.6.2.tgz", - "integrity": "sha512-/3GptzWzu0+0MBQFrDKzw/DvvMTUORvgY6k6jd/VS6iCR4RDTKWH6v6WPwQoUO8667uQEf9Oe38DxAYWY5F/Ug==" + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", + "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==" }, "source-map-resolve": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", - "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.6.0.tgz", + "integrity": "sha512-KXBr9d/fO/bWo97NXsPIAW1bFSBOuCnjbNTBMO7N59hsv5i9yzRDfcYwwt0l04+VqnKC+EwzvJZIP/qkuMgR/w==", + "dev": true, "requires": { "atob": "^2.1.2", - "decode-uri-component": "^0.2.0", - "resolve-url": "^0.2.1", - "source-map-url": "^0.4.0", - "urix": "^0.1.0" + "decode-uri-component": "^0.2.0" } }, "source-map-support": { - "version": "0.5.20", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.20.tgz", - "integrity": "sha512-n1lZZ8Ve4ksRqizaBQgxXDgKwttHDhyfQjA6YZZn8+AroHbsIz+JjwxQDxbp+7y5OYCI8t1Yk7etjD9CRd2hIw==", + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", "requires": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" - } } }, - "source-map-url": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.1.tgz", - "integrity": "sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==" - }, "space-separated-tokens": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-1.1.5.tgz", @@ -28411,79 +36805,64 @@ "wbuf": "^1.7.3" } }, - "split-string": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", - "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", - "requires": { - "extend-shallow": "^3.0.0" - }, - "dependencies": { - "extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "requires": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - } - }, - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "requires": { - "is-plain-object": "^2.0.4" - } - } - } - }, "sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" }, + "sshpk": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.17.0.tgz", + "integrity": "sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ==", + "dev": true, + "requires": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + } + }, "stable": { "version": "0.1.8", "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz", "integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==" }, - "state-toggle": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/state-toggle/-/state-toggle-1.0.3.tgz", - "integrity": "sha512-d/5Z4/2iiCnHw6Xzghyhb+GcmF89bxwgXG60wjIiZaxnymbyOmI8Hk4VqHXiVVp6u2ysaskFfXg3ekCj4WNftQ==" - }, - "static-extend": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", - "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", + "stack-utils": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.5.tgz", + "integrity": "sha512-xrQcmYhOsn/1kX+Vraq+7j4oE2j/6BFscZ0etmYg81xuM8Gq0022Pxb8+IqgOFUIaxHs0KaSb7T1+OegiNrNFA==", + "dev": true, "requires": { - "define-property": "^0.2.5", - "object-copy": "^0.1.0" + "escape-string-regexp": "^2.0.0" }, "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "requires": { - "is-descriptor": "^0.1.0" - } + "escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true } } }, + "state-toggle": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/state-toggle/-/state-toggle-1.0.3.tgz", + "integrity": "sha512-d/5Z4/2iiCnHw6Xzghyhb+GcmF89bxwgXG60wjIiZaxnymbyOmI8Hk4VqHXiVVp6u2ysaskFfXg3ekCj4WNftQ==" + }, "statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==" }, "std-env": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/std-env/-/std-env-2.3.1.tgz", - "integrity": "sha512-eOsoKTWnr6C8aWrqJJ2KAReXoa7Vn5Ywyw6uCXgA/xDhxPoaIsBa5aNJmISY04dLwXPBnDHW4diGM7Sn5K4R/g==", - "requires": { - "ci-info": "^3.1.1" - } + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.1.1.tgz", + "integrity": "sha512-/c645XdExBypL01TpFKiG/3RAa/Qmu+zRi0MwAmrdEkwHNuN0ebo8ccAXBBDa5Z0QOJgBskUIbuCK91x0sCVEw==" }, "stickyfill": { "version": "1.1.1", @@ -28525,14 +36904,39 @@ } } }, + "string-length": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", + "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", + "dev": true, + "requires": { + "char-regex": "^1.0.2", + "strip-ansi": "^6.0.0" + } + }, "string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==" + }, + "strip-ansi": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.1.tgz", + "integrity": "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==", + "requires": { + "ansi-regex": "^6.0.1" + } + } } }, "string.prototype.trimend": { @@ -28561,13 +36965,6 @@ "get-own-enumerable-property-symbols": "^3.0.0", "is-obj": "^1.0.1", "is-regexp": "^1.0.0" - }, - "dependencies": { - "is-obj": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", - "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=" - } } }, "strip-ansi": { @@ -28578,25 +36975,35 @@ "ansi-regex": "^5.0.1" } }, + "strip-bom": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "dev": true + }, "strip-bom-string": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/strip-bom-string/-/strip-bom-string-1.0.0.tgz", "integrity": "sha1-5SEekiQ2n7uB1jOi8ABE3IztrZI=" }, - "strip-eof": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", - "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=" - }, "strip-final-newline": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==" }, + "strip-indent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", + "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", + "dev": true, + "requires": { + "min-indent": "^1.0.0" + } + }, "strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==" }, "style-loader": { "version": "1.3.0", @@ -28606,19 +37013,6 @@ "requires": { "loader-utils": "^2.0.0", "schema-utils": "^2.7.0" - }, - "dependencies": { - "schema-utils": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz", - "integrity": "sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.5", - "ajv": "^6.12.4", - "ajv-keywords": "^3.5.2" - } - } } }, "style-to-object": { @@ -28630,9 +37024,9 @@ } }, "styled-components": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/styled-components/-/styled-components-5.3.1.tgz", - "integrity": "sha512-JThv2JRzyH0NOIURrk9iskdxMSAAtCfj/b2Sf1WJaCUsloQkblepy1jaCLX/bYE+mhYo3unmwVSI9I5d9ncSiQ==", + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/styled-components/-/styled-components-5.3.3.tgz", + "integrity": "sha512-++4iHwBM7ZN+x6DtPPWkCI4vdtwumQ+inA/DdAsqYd4SVgUKJie5vXyzotA00ttcFdQkCng7zc6grwlfIfw+lw==", "requires": { "@babel/helper-module-imports": "^7.0.0", "@babel/traverse": "^7.4.5", @@ -28647,11 +37041,11 @@ } }, "stylehacks": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-5.0.1.tgz", - "integrity": "sha512-Es0rVnHIqbWzveU1b24kbw92HsebBepxfcqe5iix7t9j0PQqhs0IxXVXv0pY2Bxa08CgMkzD6OWql7kbGOuEdA==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-5.1.0.tgz", + "integrity": "sha512-SzLmvHQTrIWfSgljkQCw2++C9+Ne91d/6Sp92I8c5uHTcy/PgeHamwITIbBW9wnFTY/3ZfSXR9HIL6Ikqmcu6Q==", "requires": { - "browserslist": "^4.16.0", + "browserslist": "^4.16.6", "postcss-selector-parser": "^6.0.4" } }, @@ -28663,6 +37057,38 @@ "has-flag": "^3.0.0" } }, + "supports-hyperlinks": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.2.0.tgz", + "integrity": "sha512-6sXEzV5+I5j8Bmq9/vUphGRM/RJNT9SCURJLjwfOg51heRtguGWDzcaBlgAzKhQa0EVNpPEKzQuBwZ8S8WaCeQ==", + "dev": true, + "requires": { + "has-flag": "^4.0.0", + "supports-color": "^7.0.0" + }, + "dependencies": { + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==" + }, "svg-inline-loader": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/svg-inline-loader/-/svg-inline-loader-0.8.2.tgz", @@ -28680,48 +37106,115 @@ "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", "dev": true, "requires": { - "minimist": "^1.2.0" + "minimist": "^1.2.0" + } + }, + "loader-utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", + "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + } + } + } + }, + "svg-parser": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/svg-parser/-/svg-parser-2.0.4.tgz", + "integrity": "sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ==" + }, + "svgo": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-1.3.2.tgz", + "integrity": "sha512-yhy/sQYxR5BkC98CY7o31VGsg014AKLEPxdfhora76l36hD9Rdy5NZA/Ocn6yayNPgSamYdtX2rFJdcv07AYVw==", + "requires": { + "chalk": "^2.4.1", + "coa": "^2.0.2", + "css-select": "^2.0.0", + "css-select-base-adapter": "^0.1.1", + "css-tree": "1.0.0-alpha.37", + "csso": "^4.0.2", + "js-yaml": "^3.13.1", + "mkdirp": "~0.5.1", + "object.values": "^1.1.0", + "sax": "~1.2.4", + "stable": "^0.1.8", + "unquote": "~1.1.1", + "util.promisify": "~1.0.0" + }, + "dependencies": { + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "css-select": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-2.1.0.tgz", + "integrity": "sha512-Dqk7LQKpwLoH3VovzZnkzegqNSuAziQyNZUcrdDM401iY+R5NkGBXGmtO05/yaXQziALuPogeG0b7UAgjnTJTQ==", + "requires": { + "boolbase": "^1.0.0", + "css-what": "^3.2.1", + "domutils": "^1.7.0", + "nth-check": "^1.0.2" + } + }, + "css-what": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-3.4.2.tgz", + "integrity": "sha512-ACUm3L0/jiZTqfzRM3Hi9Q8eZqd6IK37mMWPLz9PJxkLWllYeRf+EHUSHYEtFop2Eqytaq1FizFVh7XfBnXCDQ==" + }, + "dom-serializer": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz", + "integrity": "sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==", + "requires": { + "domelementtype": "^2.0.1", + "entities": "^2.0.0" + } + }, + "domutils": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz", + "integrity": "sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==", + "requires": { + "dom-serializer": "0", + "domelementtype": "1" + }, + "dependencies": { + "domelementtype": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", + "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==" + } + } + }, + "js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" } }, - "loader-utils": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", - "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", - "dev": true, + "nth-check": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz", + "integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==", "requires": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^1.0.1" + "boolbase": "~1.0.0" } } } }, - "svg-parser": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/svg-parser/-/svg-parser-2.0.4.tgz", - "integrity": "sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ==" - }, - "svgo": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/svgo/-/svgo-2.7.0.tgz", - "integrity": "sha512-aDLsGkre4fTDCWvolyW+fs8ZJFABpzLXbtdK1y71CKnHzAnpDxKXPj2mNKj+pyOXUCzFHzuxRJ94XOFygOWV3w==", - "requires": { - "@trysound/sax": "0.2.0", - "commander": "^7.2.0", - "css-select": "^4.1.3", - "css-tree": "^1.1.3", - "csso": "^4.2.0", - "nanocolors": "^0.1.12", - "stable": "^0.1.8" - }, - "dependencies": { - "commander": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", - "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==" - } - } - }, "swagger2openapi": { "version": "7.0.8", "resolved": "https://registry.npmjs.org/swagger2openapi/-/swagger2openapi-7.0.8.tgz", @@ -28740,42 +37233,48 @@ "yargs": "^17.0.1" }, "dependencies": { - "cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" } }, - "y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==" - }, "yargs": { - "version": "17.2.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.2.1.tgz", - "integrity": "sha512-XfR8du6ua4K6uLGm5S6fA+FIJom/MdJcFNVY8geLlp2v8GYbOXD4EB1tPNZsRn4vBzKGMgb5DRZMeWuFc2GO8Q==", + "version": "17.4.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.4.1.tgz", + "integrity": "sha512-WSZD9jgobAg3ZKuCQZSa3g9QOJeCCqLoLAykiWgmXnDo9EPnn4RPf5qVTtzgOx66o6/oqhcA5tHtJXpG8pMt3g==", "requires": { "cliui": "^7.0.2", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", - "string-width": "^4.2.0", + "string-width": "^4.2.3", "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" + "yargs-parser": "^21.0.0" } }, "yargs-parser": { - "version": "20.2.9", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==" + "version": "21.0.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.0.1.tgz", + "integrity": "sha512-9BK1jFpLzJROCI5TzwZL/TU4gqjK5xiHV/RfWLOahrjAko/e4DJkRDZQXfvqAsiZzzYhgAzbgz6lg48jcm4GLg==" } } }, + "symbol-tree": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", + "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", + "dev": true + }, "tapable": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", @@ -28804,13 +37303,24 @@ "readable-stream": "^3.1.1" } }, + "terminal-link": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/terminal-link/-/terminal-link-2.1.1.tgz", + "integrity": "sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ==", + "dev": true, + "requires": { + "ansi-escapes": "^4.2.1", + "supports-hyperlinks": "^2.0.0" + } + }, "terser": { - "version": "5.9.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.9.0.tgz", - "integrity": "sha512-h5hxa23sCdpzcye/7b8YqbE5OwKca/ni0RQz1uRX3tGh8haaGHqcuSqbGRybuAKNdntZ0mDgFNXPJ48xQ2RXKQ==", + "version": "5.13.1", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.13.1.tgz", + "integrity": "sha512-hn4WKOfwnwbYfe48NgrQjqNOH9jzLqRcIfbYytOXCOv46LBfWr9bDS17MQqOi+BWGD0sJK3Sj5NC/gJjiojaoA==", "requires": { + "acorn": "^8.5.0", "commander": "^2.20.0", - "source-map": "~0.7.2", + "source-map": "~0.8.0-beta.0", "source-map-support": "~0.5.20" }, "dependencies": { @@ -28820,37 +37330,96 @@ "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" }, "source-map": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", - "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==" + "version": "0.8.0-beta.0", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.8.0-beta.0.tgz", + "integrity": "sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==", + "requires": { + "whatwg-url": "^7.0.0" + } + }, + "tr46": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz", + "integrity": "sha1-qLE/1r/SSJUZZ0zN5VujaTtwbQk=", + "requires": { + "punycode": "^2.1.0" + } + }, + "webidl-conversions": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", + "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==" + }, + "whatwg-url": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz", + "integrity": "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==", + "requires": { + "lodash.sortby": "^4.7.0", + "tr46": "^1.0.1", + "webidl-conversions": "^4.0.2" + } } } }, "terser-webpack-plugin": { - "version": "5.2.4", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.2.4.tgz", - "integrity": "sha512-E2CkNMN+1cho04YpdANyRrn8CyN4yMy+WdFKZIySFZrGXZxJwJP6PMNGGc/Mcr6qygQHUUqRxnAPmi0M9f00XA==", + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.1.tgz", + "integrity": "sha512-GvlZdT6wPQKbDNW/GDQzZFg/j4vKU96yl2q6mcUkzKOgW4gwf1Z8cZToUCrz31XHlPWH8MVb1r2tFtdDtTGJ7g==", "requires": { - "jest-worker": "^27.0.6", - "p-limit": "^3.1.0", + "jest-worker": "^27.4.5", "schema-utils": "^3.1.1", "serialize-javascript": "^6.0.0", "source-map": "^0.6.1", "terser": "^5.7.2" }, "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + "schema-utils": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", + "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", + "requires": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + } } } }, + "test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "dev": true, + "requires": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + } + }, "text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=" }, + "throat": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/throat/-/throat-6.0.1.tgz", + "integrity": "sha512-8hmiGIJMDlwjg7dlJ4yKGLK8EsYqKgPWbG3b4wjJddKNwc7N7Dpn08Df4szr/sZdMVeOstrdYSsqzX6BYbcB+w==", + "dev": true + }, + "throttleit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-1.0.0.tgz", + "integrity": "sha512-rkTVqu6IjfQ/6+uNuuc3sZek4CEYxTJom3IktzgdSxcZqdARuebbA/f4QmAxMQIxqq9ZLEUkSYqvuk1I6VKq4g==", + "dev": true + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", + "dev": true + }, "thunky": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", @@ -28869,15 +37438,10 @@ "resolved": "https://registry.npmjs.org/timm/-/timm-1.7.1.tgz", "integrity": "sha512-IjZc9KIotudix8bMaBW6QvMuq64BrJWFs1+4V0lXwWGQZwH+LnX87doAYhem4caOEusRP9/g6jVDQmZ8XOk1nw==" }, - "timsort": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/timsort/-/timsort-0.3.0.tgz", - "integrity": "sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q=" - }, "tiny-invariant": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.1.0.tgz", - "integrity": "sha512-ytxQvrb1cPc9WBEI/HSeYYoGD0kWnGEOR8RY6KomWLBVhqz0RgTwVO9dLrGz7dC+nN9llyI7OKAgRq8Vq4ZBSw==" + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.2.0.tgz", + "integrity": "sha512-1Uhn/aqw5C6RI4KejVeTg6mIS7IqxnLJ8Mv2tV5rTc0qWobay7pDUz6Wi392Cnc8ak1H0F2cjoRzb2/AW4+Fvg==" }, "tiny-warning": { "version": "1.0.3", @@ -28889,64 +37453,31 @@ "resolved": "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.4.2.tgz", "integrity": "sha512-vJhccZPs965sV/L2sU4oRQVAos0pQXwsvTLkWYdqJ+a8Q5kPFzJTuOFwy7UniPli44NKQGAglksjvOcpo95aZA==" }, + "tmp": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", + "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", + "dev": true, + "requires": { + "rimraf": "^3.0.0" + } + }, + "tmpl": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", + "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", + "dev": true + }, "to-fast-properties": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=" }, - "to-object-path": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", - "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, "to-readable-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz", "integrity": "sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==" }, - "to-regex": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", - "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", - "requires": { - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "regex-not": "^1.0.2", - "safe-regex": "^1.1.0" - }, - "dependencies": { - "extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "requires": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - } - }, - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "requires": { - "is-plain-object": "^2.0.4" - } - } - } - }, "to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -28956,15 +37487,43 @@ } }, "toidentifier": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", - "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==" + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==" }, "totalist": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/totalist/-/totalist-1.1.0.tgz", "integrity": "sha512-gduQwd1rOdDMGxFG1gEvhV88Oirdo2p+KjoYFU7k2g+i7n6AFFbDQ5kMPUsW0pNbfQsB/cwXvT1i4Bue0s9g5g==" }, + "tough-cookie": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.0.0.tgz", + "integrity": "sha512-tHdtEpQCMrc1YLrMaqXXcj6AxhYi/xgit6mZu1+EDWUn+qhUf8wMQoFIy9NXuq23zAwtcB0t/MjACGR18pcRbg==", + "dev": true, + "requires": { + "psl": "^1.1.33", + "punycode": "^2.1.1", + "universalify": "^0.1.2" + }, + "dependencies": { + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true + } + } + }, + "tr46": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-2.1.0.tgz", + "integrity": "sha512-15Ih7phfcdP5YxqiB+iDtLoaTz4Nd35+IiAv0kQ5FNKHzXgdWqPoTIqEDDJmXceQt4JZk6lVPT8lnDlPpGDppw==", + "dev": true, + "requires": { + "punycode": "^2.1.1" + } + }, "trim": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/trim/-/trim-0.0.1.tgz", @@ -28980,15 +37539,10 @@ "resolved": "https://registry.npmjs.org/trough/-/trough-1.0.5.tgz", "integrity": "sha512-rvuRbTarPXmMb79SmzEp8aqXNKcK+y0XaB298IXueQ8I2PsrATcPBCSPyK/dDNa2iWOhKlfNnOjdAOTBU/nkFA==" }, - "ts-essentials": { - "version": "2.0.12", - "resolved": "https://registry.npmjs.org/ts-essentials/-/ts-essentials-2.0.12.tgz", - "integrity": "sha512-3IVX4nI6B5cc31/GFFE+i8ey/N2eA0CZDbo6n0yrz0zDX8ZJ8djmU1p+XRz7G3is0F3bB3pu2pAroFdAWQKU3w==" - }, "tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" }, "tty-browserify": { "version": "0.0.1", @@ -29003,10 +37557,31 @@ "safe-buffer": "^5.0.1" } }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==", + "dev": true + }, + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "dev": true, + "requires": { + "prelude-ls": "~1.1.2" + } + }, + "type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true + }, "type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==" + "version": "2.12.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.12.2.tgz", + "integrity": "sha512-qt6ylCGpLjZ7AaODxbpyBZSs9fCI9SkL3Z9q2oxMBQhs/uyY+VD8jHA8ULCGmWQJlBgqvO3EJeAngOHD8zQCrQ==" }, "type-is": { "version": "1.6.18", @@ -29025,19 +37600,25 @@ "is-typedarray": "^1.0.0" } }, + "typescript": { + "version": "4.7.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.4.tgz", + "integrity": "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==", + "peer": true + }, "ua-parser-js": { - "version": "0.7.28", - "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.28.tgz", - "integrity": "sha512-6Gurc1n//gjp9eQNXjD9O3M/sMwVtN5S8Lv9bvOYBfKfDNiIIhqiyi01vMBO45u4zkDE420w/e0se7Vs+sIg+g==" + "version": "0.7.31", + "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.31.tgz", + "integrity": "sha512-qLK/Xe9E2uzmYI3qLeOmI0tEOt+TBBQyUIAh4aAgU05FVYzeZrKUdkAZfBNVGRaHVgV0TDkdEngJSw/SyQchkQ==" }, "unbox-primitive": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz", - "integrity": "sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", + "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", "requires": { - "function-bind": "^1.1.1", - "has-bigints": "^1.0.1", - "has-symbols": "^1.0.2", + "call-bind": "^1.0.2", + "has-bigints": "^1.0.2", + "has-symbols": "^1.0.3", "which-boxed-primitive": "^1.0.2" } }, @@ -29075,33 +37656,18 @@ "integrity": "sha512-5Zfuy9q/DFr4tfO7ZPeVXb1aPoeQSdeFMLpYuFebehDAhbuevLs5yxSZmIFN1tP5F9Wl4IpJrYojg85/zgyZHQ==" }, "unified": { - "version": "8.4.2", - "resolved": "https://registry.npmjs.org/unified/-/unified-8.4.2.tgz", - "integrity": "sha512-JCrmN13jI4+h9UAyKEoGcDZV+i1E7BLFuG7OsaDvTXI5P0qhHX+vZO/kOhz9jn8HGENDKbwSeB0nVOg4gVStGA==", + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/unified/-/unified-9.2.0.tgz", + "integrity": "sha512-vx2Z0vY+a3YoTj8+pttM3tiJHCwY5UFbYdiWrwBEbHmK8pvsPj2rtAX2BFfgXen8T39CJWblWRDT4L5WGXtDdg==", "requires": { "bail": "^1.0.0", "extend": "^3.0.0", + "is-buffer": "^2.0.0", "is-plain-obj": "^2.0.0", "trough": "^1.0.0", "vfile": "^4.0.0" } }, - "union-value": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", - "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", - "requires": { - "arr-union": "^3.1.0", - "get-value": "^2.0.6", - "is-extendable": "^0.1.1", - "set-value": "^2.0.1" - } - }, - "uniqs": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/uniqs/-/uniqs-2.0.0.tgz", - "integrity": "sha1-/+3ks2slKQaW5uFl1KWe25mOawI=" - }, "unique-string": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", @@ -29115,6 +37681,14 @@ "resolved": "https://registry.npmjs.org/unist-builder/-/unist-builder-2.0.3.tgz", "integrity": "sha512-f98yt5pnlMWlzP539tPc4grGMsFaQQlP/vM396b00jngsiINumNmsY8rkXjfoi1c6QaM8nQ3vaGDuoKWbe/1Uw==" }, + "unist-util-find-after": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/unist-util-find-after/-/unist-util-find-after-3.0.0.tgz", + "integrity": "sha512-ojlBqfsBftYXExNu3+hHLfJQ/X1jYY/9vdm4yZWjIbf0VuWF6CRufci1ZyoD/wV2TYMKxXUoNuoqwy+CkgzAiQ==", + "requires": { + "unist-util-is": "^4.0.0" + } + }, "unist-util-generated": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/unist-util-generated/-/unist-util-generated-1.1.6.tgz", @@ -29188,68 +37762,136 @@ "resolved": "https://registry.npmjs.org/unquote/-/unquote-1.1.1.tgz", "integrity": "sha1-j97XMk7G6IoP+LkF58CYzcCG1UQ=" }, - "unset-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", - "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", + "untildify": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz", + "integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==", + "dev": true + }, + "update-notifier": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-5.1.0.tgz", + "integrity": "sha512-ItnICHbeMh9GqUy31hFPrD1kcuZ3rpxDZbf4KUDavXwS0bW5m7SLbDQpGX3UYr072cbrF5hFUs3r5tUsPwjfHw==", "requires": { - "has-value": "^0.3.1", - "isobject": "^3.0.0" + "boxen": "^5.0.0", + "chalk": "^4.1.0", + "configstore": "^5.0.1", + "has-yarn": "^2.1.0", + "import-lazy": "^2.1.0", + "is-ci": "^2.0.0", + "is-installed-globally": "^0.4.0", + "is-npm": "^5.0.0", + "is-yarn-global": "^0.3.0", + "latest-version": "^5.1.0", + "pupa": "^2.1.1", + "semver": "^7.3.4", + "semver-diff": "^3.1.1", + "xdg-basedir": "^4.0.0" }, "dependencies": { - "has-value": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", - "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "requires": { - "get-value": "^2.0.3", - "has-values": "^0.1.4", - "isobject": "^2.0.0" - }, - "dependencies": { - "isobject": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", - "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", - "requires": { - "isarray": "1.0.0" - } - } + "color-convert": "^2.0.1" + } + }, + "boxen": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-5.1.2.tgz", + "integrity": "sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ==", + "requires": { + "ansi-align": "^3.0.0", + "camelcase": "^6.2.0", + "chalk": "^4.1.0", + "cli-boxes": "^2.2.1", + "string-width": "^4.2.2", + "type-fest": "^0.20.2", + "widest-line": "^3.1.0", + "wrap-ansi": "^7.0.0" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "cli-boxes": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz", + "integrity": "sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==" + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "requires": { + "has-flag": "^4.0.0" + } + }, + "type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==" + }, + "widest-line": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", + "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==", + "requires": { + "string-width": "^4.0.0" } }, - "has-values": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", - "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=" + "wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } } } }, - "upath": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", - "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==" - }, - "update-notifier": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-5.1.0.tgz", - "integrity": "sha512-ItnICHbeMh9GqUy31hFPrD1kcuZ3rpxDZbf4KUDavXwS0bW5m7SLbDQpGX3UYr072cbrF5hFUs3r5tUsPwjfHw==", - "requires": { - "boxen": "^5.0.0", - "chalk": "^4.1.0", - "configstore": "^5.0.1", - "has-yarn": "^2.1.0", - "import-lazy": "^2.1.0", - "is-ci": "^2.0.0", - "is-installed-globally": "^0.4.0", - "is-npm": "^5.0.0", - "is-yarn-global": "^0.3.0", - "latest-version": "^5.1.0", - "pupa": "^2.1.1", - "semver": "^7.3.4", - "semver-diff": "^3.1.1", - "xdg-basedir": "^4.0.0" - } - }, "uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", @@ -29258,11 +37900,6 @@ "punycode": "^2.1.0" } }, - "urix": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", - "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=" - }, "url": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", @@ -29276,6 +37913,11 @@ "version": "1.3.2", "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=" + }, + "querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=" } } }, @@ -29287,15 +37929,18 @@ "loader-utils": "^2.0.0", "mime-types": "^2.1.27", "schema-utils": "^3.0.0" - } - }, - "url-parse": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.3.tgz", - "integrity": "sha512-IIORyIQD9rvj0A4CLWsHkBBJuNqWpFQe224b6j9t/ABmquIS0qDU2pY6kl6AuOrL5OkCXHMCFNe1jBcuAggjvQ==", - "requires": { - "querystringify": "^2.1.1", - "requires-port": "^1.0.0" + }, + "dependencies": { + "schema-utils": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", + "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", + "requires": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + } + } } }, "url-parse-lax": { @@ -29311,31 +37956,24 @@ "resolved": "https://registry.npmjs.org/url-template/-/url-template-2.0.8.tgz", "integrity": "sha1-/FZaPMy/93MMd19WQflVV5FDnyE=" }, - "use": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", - "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==" - }, "use-composed-ref": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/use-composed-ref/-/use-composed-ref-1.1.0.tgz", - "integrity": "sha512-my1lNHGWsSDAhhVAT4MKs6IjBUtG6ZG11uUqexPH9PptiIZDQOzaF4f5tEbJ2+7qvNbtXNBbU3SfmN+fXlWDhg==", - "requires": { - "ts-essentials": "^2.0.3" - } + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/use-composed-ref/-/use-composed-ref-1.3.0.tgz", + "integrity": "sha512-GLMG0Jc/jiKov/3Ulid1wbv3r54K9HlMW29IWcDFPEqFkSO2nS0MuefWgMJpeHQ9YJeXDL3ZUF+P3jdXlZX/cQ==", + "requires": {} }, "use-isomorphic-layout-effect": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.1.1.tgz", - "integrity": "sha512-L7Evj8FGcwo/wpbv/qvSfrkHFtOpCzvM5yl2KVyDJoylVuSvzphiiasmjgQPttIGBAy2WKiBNR98q8w7PiNgKQ==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.1.2.tgz", + "integrity": "sha512-49L8yCO3iGT/ZF9QttjwLF/ZD9Iwto5LnH5LmEdk/6cFmXddqi2ulF0edxTwjj+7mqvpVVGQWvbXZdn32wRSHA==", "requires": {} }, "use-latest": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/use-latest/-/use-latest-1.2.0.tgz", - "integrity": "sha512-d2TEuG6nSLKQLAfW3By8mKr8HurOlTkul0sOpxbClIv4SQ4iOd7BYr7VIzdbktUCnv7dua/60xzd8igMU6jmyw==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/use-latest/-/use-latest-1.2.1.tgz", + "integrity": "sha512-xA+AVm/Wlg3e2P/JiItTziwS7FK92LWrDB0p+hgXloIMuVCeJJ8v6f0eeHyPZaJrM+usM1FkFfbNCrJGs8A/zw==", "requires": { - "use-isomorphic-layout-effect": "^1.0.0" + "use-isomorphic-layout-effect": "^1.1.1" } }, "utif": { @@ -29391,9 +38029,28 @@ "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" }, "uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-7.0.3.tgz", + "integrity": "sha512-DPSke0pXhTZgoF/d+WSt2QaKMCFSfx7QegxEWT+JOuHF5aWrKEn0G+ztjuJg/gG8/ItK+rbPCD/yNv8yyih6Cg==" + }, + "v8-to-istanbul": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-8.1.1.tgz", + "integrity": "sha512-FGtKtv3xIpR6BYhvgH8MI/y78oT7d8Au3ww4QIxymrCtZEh5b8gCw2siywE+puhEmuWKDtmfrvF5UlB298ut3w==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "^2.0.1", + "convert-source-map": "^1.6.0", + "source-map": "^0.7.3" + }, + "dependencies": { + "source-map": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", + "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", + "dev": true + } + } }, "value-equal": { "version": "1.0.1", @@ -29405,10 +38062,24 @@ "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" }, - "vendors": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/vendors/-/vendors-1.0.4.tgz", - "integrity": "sha512-/juG65kTL4Cy2su4P8HjtkTxk6VmJDiOPBufWniqQ6wknac6jNiXS9vU+hO3wgusiyqWlzTbVHi0dyJqRONg3w==" + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==", + "dev": true, + "requires": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + }, + "dependencies": { + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==", + "dev": true + } + } }, "vfile": { "version": "4.2.1", @@ -29419,13 +38090,6 @@ "is-buffer": "^2.0.0", "unist-util-stringify-position": "^2.0.0", "vfile-message": "^2.0.0" - }, - "dependencies": { - "is-buffer": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz", - "integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==" - } } }, "vfile-location": { @@ -29447,22 +38111,59 @@ "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz", "integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==" }, + "w3c-hr-time": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz", + "integrity": "sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ==", + "dev": true, + "requires": { + "browser-process-hrtime": "^1.0.0" + } + }, + "w3c-xmlserializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-2.0.0.tgz", + "integrity": "sha512-4tzD0mF8iSiMiNs30BiLO3EpfGLZUT2MSX/G+o7ZywDzliWQ3OPtTZ0PTC3B3ca1UAf4cJMHB+2Bf56EriJuRA==", + "dev": true, + "requires": { + "xml-name-validator": "^3.0.0" + } + }, "wait-on": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/wait-on/-/wait-on-5.3.0.tgz", - "integrity": "sha512-DwrHrnTK+/0QFaB9a8Ol5Lna3k7WvUR4jzSKmz0YaPBpuN2sACyiPVKVfj6ejnjcajAcvn3wlbTyMIn9AZouOg==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/wait-on/-/wait-on-6.0.1.tgz", + "integrity": "sha512-zht+KASY3usTY5u2LgaNqn/Cd8MukxLGjdcZxT2ns5QzDmTFc4XoWBgC+C/na+sMRZTuVygQoMYwdcVjHnYIVw==", "requires": { - "axios": "^0.21.1", - "joi": "^17.3.0", + "axios": "^0.25.0", + "joi": "^17.6.0", "lodash": "^4.17.21", "minimist": "^1.2.5", - "rxjs": "^6.6.3" + "rxjs": "^7.5.4" + }, + "dependencies": { + "axios": { + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.25.0.tgz", + "integrity": "sha512-cD8FOb0tRH3uuEe6+evtAbgJtfxr7ly3fQjYcMcuPlgkwVS9xboaVIpcDV+cYQe+yGykgwZCs1pzjntcGa6l5g==", + "requires": { + "follow-redirects": "^1.14.7" + } + } + } + }, + "walker": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", + "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", + "dev": true, + "requires": { + "makeerror": "1.0.12" } }, "watchpack": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.2.0.tgz", - "integrity": "sha512-up4YAn/XHgZHIxFBVCdlMiWDj6WaLKpwVeGQk2I5thdYxF/KmF0aaz6TfJZ/hfl1h/XlcDr7k1KH7ThDagpFaA==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.3.1.tgz", + "integrity": "sha512-x0t0JuydIo8qCNctdDrn1OzH/qDzk2+rdCOC3YzumZ42fiMqmQ7T3xQurykYMhYfHaPHTp4ZxAx2NfUo1K6QaA==", "requires": { "glob-to-regexp": "^0.4.1", "graceful-fs": "^4.1.2" @@ -29481,13 +38182,19 @@ "resolved": "https://registry.npmjs.org/web-namespaces/-/web-namespaces-1.1.4.tgz", "integrity": "sha512-wYxSGajtmoP4WxfejAPIr4l0fVh+jeMXZb08wNc0tMg6xsfZXj3cECqIK0G7ZAqUq0PP8WlMDtaOGVBTAWztNw==" }, + "webidl-conversions": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-6.1.0.tgz", + "integrity": "sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w==", + "dev": true + }, "webpack": { - "version": "5.58.2", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.58.2.tgz", - "integrity": "sha512-3S6e9Vo1W2ijk4F4PPWRIu6D/uGgqaPmqw+av3W3jLDujuNkdxX5h5c+RQ6GkjVR+WwIPOfgY8av+j5j4tMqJw==", + "version": "5.72.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.72.0.tgz", + "integrity": "sha512-qmSmbspI0Qo5ld49htys8GY9XhS9CGqFoHTsOVAnjBdg0Zn79y135R+k4IR4rKK6+eKaabMhJwiVB7xw0SJu5w==", "requires": { - "@types/eslint-scope": "^3.7.0", - "@types/estree": "^0.0.50", + "@types/eslint-scope": "^3.7.3", + "@types/estree": "^0.0.51", "@webassemblyjs/ast": "1.11.1", "@webassemblyjs/wasm-edit": "1.11.1", "@webassemblyjs/wasm-parser": "1.11.1", @@ -29495,12 +38202,12 @@ "acorn-import-assertions": "^1.7.6", "browserslist": "^4.14.5", "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.8.3", + "enhanced-resolve": "^5.9.2", "es-module-lexer": "^0.9.0", "eslint-scope": "5.1.1", "events": "^3.2.0", "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.2.4", + "graceful-fs": "^4.2.9", "json-parse-better-errors": "^1.0.2", "loader-runner": "^4.2.0", "mime-types": "^2.1.27", @@ -29508,8 +38215,25 @@ "schema-utils": "^3.1.0", "tapable": "^2.1.1", "terser-webpack-plugin": "^5.1.3", - "watchpack": "^2.2.0", - "webpack-sources": "^3.2.0" + "watchpack": "^2.3.1", + "webpack-sources": "^3.2.3" + }, + "dependencies": { + "schema-utils": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", + "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", + "requires": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + } + }, + "webpack-sources": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", + "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==" + } } }, "webpack-bundle-analyzer": { @@ -29528,415 +38252,194 @@ "ws": "^7.3.1" }, "dependencies": { - "commander": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", - "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==" - }, - "gzip-size": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-6.0.0.tgz", - "integrity": "sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q==", - "requires": { - "duplexer": "^0.1.2" - } - } - } - }, - "webpack-dev-middleware": { - "version": "3.7.3", - "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-3.7.3.tgz", - "integrity": "sha512-djelc/zGiz9nZj/U7PTBi2ViorGJXEWo/3ltkPbDyxCXhhEXkW0ce99falaok4TPj+AsxLiXJR0EBOb0zh9fKQ==", - "requires": { - "memory-fs": "^0.4.1", - "mime": "^2.4.4", - "mkdirp": "^0.5.1", - "range-parser": "^1.2.1", - "webpack-log": "^2.0.0" - }, - "dependencies": { - "mime": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.5.2.tgz", - "integrity": "sha512-tqkh47FzKeCPD2PUiPB6pkbMzsCasjxAfC62/Wap5qrUWcb+sFasXUC5I3gYM5iBM8v/Qpn4UK0x+j0iHyFPDg==" - } - } - }, - "webpack-dev-server": { - "version": "3.11.2", - "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-3.11.2.tgz", - "integrity": "sha512-A80BkuHRQfCiNtGBS1EMf2ChTUs0x+B3wGDFmOeT4rmJOHhHTCH2naNxIHhmkr0/UillP4U3yeIyv1pNp+QDLQ==", - "requires": { - "ansi-html": "0.0.7", - "bonjour": "^3.5.0", - "chokidar": "^2.1.8", - "compression": "^1.7.4", - "connect-history-api-fallback": "^1.6.0", - "debug": "^4.1.1", - "del": "^4.1.1", - "express": "^4.17.1", - "html-entities": "^1.3.1", - "http-proxy-middleware": "0.19.1", - "import-local": "^2.0.0", - "internal-ip": "^4.3.0", - "ip": "^1.1.5", - "is-absolute-url": "^3.0.3", - "killable": "^1.0.1", - "loglevel": "^1.6.8", - "opn": "^5.5.0", - "p-retry": "^3.0.1", - "portfinder": "^1.0.26", - "schema-utils": "^1.0.0", - "selfsigned": "^1.10.8", - "semver": "^6.3.0", - "serve-index": "^1.9.1", - "sockjs": "^0.3.21", - "sockjs-client": "^1.5.0", - "spdy": "^4.0.2", - "strip-ansi": "^3.0.1", - "supports-color": "^6.1.0", - "url": "^0.11.0", - "webpack-dev-middleware": "^3.7.2", - "webpack-log": "^2.0.0", - "ws": "^6.2.1", - "yargs": "^13.3.2" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" - }, - "anymatch": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", - "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", - "requires": { - "micromatch": "^3.1.4", - "normalize-path": "^2.1.1" - }, - "dependencies": { - "normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "requires": { - "remove-trailing-separator": "^1.0.1" - } - } - } - }, - "array-union": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", - "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", - "requires": { - "array-uniq": "^1.0.1" - } - }, - "binary-extensions": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", - "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==" - }, - "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "requires": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "chokidar": { - "version": "2.1.8", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", - "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", - "requires": { - "anymatch": "^2.0.0", - "async-each": "^1.0.1", - "braces": "^2.3.2", - "fsevents": "^1.2.7", - "glob-parent": "^3.1.0", - "inherits": "^2.0.3", - "is-binary-path": "^1.0.0", - "is-glob": "^4.0.0", - "normalize-path": "^3.0.0", - "path-is-absolute": "^1.0.0", - "readdirp": "^2.2.1", - "upath": "^1.1.1" - } - }, - "del": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/del/-/del-4.1.1.tgz", - "integrity": "sha512-QwGuEUouP2kVwQenAsOof5Fv8K9t3D8Ca8NxcXKrIpEHjTXK5J2nXLdP+ALI1cgv8wj7KuwBhTwBkOZSJKM5XQ==", - "requires": { - "@types/glob": "^7.1.1", - "globby": "^6.1.0", - "is-path-cwd": "^2.0.0", - "is-path-in-cwd": "^2.0.0", - "p-map": "^2.0.0", - "pify": "^4.0.1", - "rimraf": "^2.6.3" - } - }, - "extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "requires": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - }, - "dependencies": { - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "requires": { - "is-plain-object": "^2.0.4" - } - } - } - }, - "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "fsevents": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", - "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", - "optional": true, - "requires": { - "bindings": "^1.5.0", - "nan": "^2.12.1" - } + "acorn-walk": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", + "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==" }, - "glob-parent": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", - "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "requires": { - "is-glob": "^3.1.0", - "path-dirname": "^1.0.0" - }, - "dependencies": { - "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "requires": { - "is-extglob": "^2.1.0" - } - } - } - }, - "globby": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", - "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=", - "requires": { - "array-union": "^1.0.1", - "glob": "^7.0.3", - "object-assign": "^4.0.1", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" - }, - "dependencies": { - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" - } + "color-convert": "^2.0.1" } }, - "is-binary-path": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", - "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "requires": { - "binary-extensions": "^1.0.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" } }, - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "^1.1.5" - } - } + "color-name": "~1.1.4" } }, - "micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - } + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, - "p-map": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", - "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==" + "commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==" }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" }, - "readdirp": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", - "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "requires": { - "graceful-fs": "^4.1.11", - "micromatch": "^3.1.10", - "readable-stream": "^2.0.2" + "has-flag": "^4.0.0" } - }, - "rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + } + } + }, + "webpack-dev-middleware": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-5.3.1.tgz", + "integrity": "sha512-81EujCKkyles2wphtdrnPg/QqegC/AtqNH//mQkBYSMqwFVCQrxM6ktB2O/SPlZy7LqeEfTbV3cZARGQz6umhg==", + "requires": { + "colorette": "^2.0.10", + "memfs": "^3.4.1", + "mime-types": "^2.1.31", + "range-parser": "^1.2.1", + "schema-utils": "^4.0.0" + }, + "dependencies": { + "ajv": { + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz", + "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==", "requires": { - "glob": "^7.1.3" + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" } }, - "schema-utils": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", - "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", "requires": { - "ajv": "^6.1.0", - "ajv-errors": "^1.0.0", - "ajv-keywords": "^3.1.0" + "fast-deep-equal": "^3.1.3" } }, - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" + "colorette": { + "version": "2.0.16", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.16.tgz", + "integrity": "sha512-hUewv7oMjCp+wkBv5Rm0v87eJhq4woh5rSR+42YSQJKecCqgIqNkZ6lAlQms/BwHPJA5NKMRlpxPRv0n8HQW6g==" }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" + }, + "schema-utils": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.0.0.tgz", + "integrity": "sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg==", "requires": { - "safe-buffer": "~5.1.0" + "@types/json-schema": "^7.0.9", + "ajv": "^8.8.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.0.0" } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + } + } + }, + "webpack-dev-server": { + "version": "4.8.1", + "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.8.1.tgz", + "integrity": "sha512-dwld70gkgNJa33czmcj/PlKY/nOy/BimbrgZRaR9vDATBQAYgLzggR0nxDtPLJiLrMgZwbE6RRfJ5vnBBasTyg==", + "requires": { + "@types/bonjour": "^3.5.9", + "@types/connect-history-api-fallback": "^1.3.5", + "@types/express": "^4.17.13", + "@types/serve-index": "^1.9.1", + "@types/sockjs": "^0.3.33", + "@types/ws": "^8.5.1", + "ansi-html-community": "^0.0.8", + "bonjour-service": "^1.0.11", + "chokidar": "^3.5.3", + "colorette": "^2.0.10", + "compression": "^1.7.4", + "connect-history-api-fallback": "^1.6.0", + "default-gateway": "^6.0.3", + "express": "^4.17.3", + "graceful-fs": "^4.2.6", + "html-entities": "^2.3.2", + "http-proxy-middleware": "^2.0.3", + "ipaddr.js": "^2.0.1", + "open": "^8.0.9", + "p-retry": "^4.5.0", + "portfinder": "^1.0.28", + "rimraf": "^3.0.2", + "schema-utils": "^4.0.0", + "selfsigned": "^2.0.1", + "serve-index": "^1.9.1", + "sockjs": "^0.3.21", + "spdy": "^4.0.2", + "webpack-dev-middleware": "^5.3.1", + "ws": "^8.4.2" + }, + "dependencies": { + "ajv": { + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz", + "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==", "requires": { - "ansi-regex": "^2.0.0" + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" } }, - "supports-color": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", - "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", "requires": { - "has-flag": "^3.0.0" + "fast-deep-equal": "^3.1.3" } }, - "to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "colorette": { + "version": "2.0.16", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.16.tgz", + "integrity": "sha512-hUewv7oMjCp+wkBv5Rm0v87eJhq4woh5rSR+42YSQJKecCqgIqNkZ6lAlQms/BwHPJA5NKMRlpxPRv0n8HQW6g==" + }, + "schema-utils": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.0.0.tgz", + "integrity": "sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg==", "requires": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" + "@types/json-schema": "^7.0.9", + "ajv": "^8.8.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.0.0" } }, "ws": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.2.tgz", - "integrity": "sha512-zmhltoSR8u1cnDsD43TX59mzoMZsLKqUweyYBAIvTngR3shc0W6aOZylZmq/7hqyVxPdi+5Ud2QInblgyE72fw==", - "requires": { - "async-limiter": "~1.0.0" - } + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.6.0.tgz", + "integrity": "sha512-AzmM3aH3gk0aX7/rZLYvjdvZooofDu3fFOzGqcSnQ1tOcTWwhM/o+q++E8mAyVVIyUdajrkzWUGftaVSDLn1bw==", + "requires": {} } } }, - "webpack-log": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/webpack-log/-/webpack-log-2.0.0.tgz", - "integrity": "sha512-cX8G2vR/85UYG59FgkoMamwHUIkSSlV3bBMRsbxVXVUk2j6NleCKjQ/WE9eYg9WY4w25O9w8wKP4rzNZFmUcUg==", - "requires": { - "ansi-colors": "^3.0.0", - "uuid": "^3.3.2" - } - }, "webpack-merge": { "version": "5.8.0", "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.8.0.tgz", @@ -29947,23 +38450,68 @@ } }, "webpack-sources": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.1.tgz", - "integrity": "sha512-t6BMVLQ0AkjBOoRTZgqrWm7xbXMBzD+XDq2EZ96+vMfn3qKgsvdXZhbPZ4ElUOpdv4u+iiGe+w3+J75iy/bYGA==" + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", + "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", + "requires": { + "source-list-map": "^2.0.0", + "source-map": "~0.6.1" + } }, "webpackbar": { - "version": "5.0.0-3", - "resolved": "https://registry.npmjs.org/webpackbar/-/webpackbar-5.0.0-3.tgz", - "integrity": "sha512-viW6KCYjMb0NPoDrw2jAmLXU2dEOhRrtku28KmOfeE1vxbfwCYuTbTaMhnkrCZLFAFyY9Q49Z/jzYO80Dw5b8g==", + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/webpackbar/-/webpackbar-5.0.2.tgz", + "integrity": "sha512-BmFJo7veBDgQzfWXl/wwYXr/VFus0614qZ8i9znqcl9fnEdiVkdbi0TedLQ6xAK92HZHDJ0QmyQ0fmuZPAgCYQ==", "requires": { - "ansi-escapes": "^4.3.1", "chalk": "^4.1.0", - "consola": "^2.15.0", - "figures": "^3.2.0", + "consola": "^2.15.3", "pretty-time": "^1.1.0", - "std-env": "^2.2.1", - "text-table": "^0.2.0", - "wrap-ansi": "^7.0.0" + "std-env": "^3.0.1" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "requires": { + "has-flag": "^4.0.0" + } + } } }, "websocket-driver": { @@ -29981,6 +38529,32 @@ "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==" }, + "whatwg-encoding": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz", + "integrity": "sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==", + "dev": true, + "requires": { + "iconv-lite": "0.4.24" + } + }, + "whatwg-mimetype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz", + "integrity": "sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==", + "dev": true + }, + "whatwg-url": { + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-8.7.0.tgz", + "integrity": "sha512-gAojqb/m9Q8a5IV96E3fHJM70AzCkgt4uXYX2O7EmuyOnLrViCQlsEBmF9UQIu3/aeAIp2U17rtbpZWNntQqdg==", + "dev": true, + "requires": { + "lodash": "^4.7.0", + "tr46": "^2.1.0", + "webidl-conversions": "^6.1.0" + } + }, "which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -30001,11 +38575,6 @@ "is-symbol": "^1.0.3" } }, - "which-module": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=" - }, "which-typed-array": { "version": "1.1.7", "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.7.tgz", @@ -30020,48 +38589,36 @@ } }, "wide-align": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", - "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", "requires": { - "string-width": "^1.0.2 || 2" + "string-width": "^1.0.2 || 2 || 3 || 4" }, "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - } - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "requires": { - "ansi-regex": "^3.0.0" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" } } } }, "widest-line": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", - "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-4.0.1.tgz", + "integrity": "sha512-o0cyEG0e8GPzT4iGHphIOh0cJOV8fivsXxddQasHPHfoZf1ZexrfeA21w2NaEN1RHE+fXlfISmOE8R9N3u3Qig==", "requires": { - "string-width": "^4.0.0" + "string-width": "^5.0.1" } }, "wildcard": { @@ -30069,44 +38626,39 @@ "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.0.tgz", "integrity": "sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw==" }, - "worker-rpc": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/worker-rpc/-/worker-rpc-0.1.1.tgz", - "integrity": "sha512-P1WjMrUB3qgJNI9jfmpZ/htmBEjFh//6l/5y8SD9hg1Ef5zTTVVoRjTrTEzPrNBQvmhMxkoTsjOXN10GWU7aCg==", - "requires": { - "microevent.ts": "~0.1.1" - } + "word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "dev": true }, "wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.0.1.tgz", + "integrity": "sha512-QFF+ufAqhoYHvoHdajT/Po7KoXVBPXS2bgjIam5isfWJPfIOnQZ50JtUiVvCv/sjgacf3yRrt2ZKUZ/V4itN4g==", "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" }, "dependencies": { + "ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==" + }, "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "requires": { - "color-convert": "^2.0.1" - } + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.1.0.tgz", + "integrity": "sha512-VbqNsoz55SYGczauuup0MFUyXNQviSpFTj1RQtFzmQLk18qbVSpTFFGMT293rmDaQuKCT6InmbuEyUne4mTuxQ==" }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "strip-ansi": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.1.tgz", + "integrity": "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==", "requires": { - "color-name": "~1.1.4" + "ansi-regex": "^6.0.1" } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" } } }, @@ -30127,9 +38679,9 @@ } }, "ws": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.5.tgz", - "integrity": "sha512-BAkMFcAzl8as1G/hArkxOxq3G7pjUqQ3gzYbLL0/5zNkph70e+lCoxBGnm6AW1+/aiNeV4fnKqZ8m4GZewmH2w==", + "version": "7.5.7", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.7.tgz", + "integrity": "sha512-KMvVuFzpKBuiIXW3E4u3mySRO2/mCHSyZDJQM5NQ9Q9KHWHWh0NHgfbRMLLrceUK5qAL4ytALJbpRMjixFZh8A==", "requires": {} }, "xdg-basedir": { @@ -30156,6 +38708,12 @@ "sax": "^1.2.4" } }, + "xml-name-validator": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz", + "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==", + "dev": true + }, "xml-parse-from-string": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/xml-parse-from-string/-/xml-parse-from-string-1.0.1.tgz", @@ -30175,15 +38733,21 @@ "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==" }, + "xmlchars": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", + "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", + "dev": true + }, "xtend": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" }, "y18n": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", - "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==" + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==" }, "yallist": { "version": "4.0.0", @@ -30201,109 +38765,53 @@ "integrity": "sha512-2PTINUwsRqSd+s8XxKaJWQlUuEMHJQyEuh2edBbW8KNJz0SJPwUSD2zRWqezFEdN7IzAgeuYHFUCF7o8zRdZ0A==" }, "yargs": { - "version": "13.3.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", - "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, "requires": { - "cliui": "^5.0.0", - "find-up": "^3.0.0", - "get-caller-file": "^2.0.1", + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^3.0.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^13.1.2" + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" }, "dependencies": { - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" - }, "emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==" - }, - "find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "requires": { - "locate-path": "^3.0.0" - } - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" - }, - "locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "requires": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - } - }, - "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "requires": { - "p-limit": "^2.0.0" - } - }, - "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=" + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true }, "string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - } - }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, "requires": { - "ansi-regex": "^4.1.0" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" } } } }, "yargs-parser": { - "version": "13.1.2", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", - "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true + }, + "yauzl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", + "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", + "dev": true, "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - }, - "dependencies": { - "camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==" - } + "buffer-crc32": "~0.2.3", + "fd-slicer": "~1.1.0" } }, "yocto-queue": { diff --git a/website/package.json b/website/package.json index c315924d7e0..6ef1980d96f 100644 --- a/website/package.json +++ b/website/package.json @@ -2,31 +2,51 @@ "scripts": { "start": "docusaurus start", "build": "docusaurus build", - "swizzle": "docusaurus swizzle" + "swizzle": "docusaurus swizzle", + "test": "npx jest --watch" }, "dependencies": { - "@docusaurus/core": "^2.0.0-beta.6", - "@docusaurus/plugin-ideal-image": "^2.0.0-beta.6", - "@docusaurus/preset-classic": "^2.0.0-beta.6", - "@docusaurus/theme-search-algolia": "^2.0.0-beta.6", + "@docusaurus/core": "2.0.0-beta.17", + "@docusaurus/plugin-ideal-image": "2.0.0-beta.17", + "@docusaurus/preset-classic": "2.0.0-beta.17", + "@docusaurus/theme-search-algolia": "2.0.0-beta.17", "@mdx-js/react": "^1.6.21", - "@svgr/webpack": "^5.5.0", - "classnames": "^2.2.6", + "axios": "^0.27.2", + "@svgr/webpack": "^6.0.0", + "classnames": "^2.3.1", "clsx": "^1.1.1", "color": "^3.1.2", - "core-js": "^3.6.4", + "core-js": "^3.20.0", "file-loader": "^6.2.0", - "mobx": "^6.3.3", + "fs": "0.0.2", + "gray-matter": "^4.0.3", + "hast-util-is-element": "^1.1.0", + "js-yaml": "^4.1.0", + "mobx": "^6.3.9", "node-polyfill-webpack-plugin": "^1.1.4", "prism-react-renderer": "^1.2.1", "react": "^17.0.1", "react-dom": "^17.0.1", + "react-is": "^18.1.0", + "react-tooltip": "^4.2.21", "redoc": "^2.0.0-rc.57", - "styled-components": "^5.0.1", + "rehype-katex": "^5.0.0", + "remark-math": "^3.0.1", + "slugify": "^1.6.1", + "styled-components": "5.3.3", "url-loader": "^4.1.1" }, "devDependencies": { + "@swc/core": "^1.2.174", + "@swc/jest": "^0.2.20", + "@testing-library/jest-dom": "^5.16.2", + "@testing-library/react": "^12.1.3", + "@testing-library/user-event": "^13.5.0", "css-loader": "^3.4.2", + "cypress": "^10.3.0", + "dotenv": "^10.0.0", + "jest": "^27.5.1", + "jest-cli": "^27.5.1", "path-browserify": "^1.0.1", "process": "^0.11.10", "stream-http": "^3.2.0", @@ -34,5 +54,15 @@ "svg-inline-loader": "^0.8.2", "tty-browserify": "0.0.1" }, + "jest": { + "transform": { + "^.+\\.(js|jsx)$": "@swc/jest" + }, + "testEnvironment": "jsdom", + "setupFilesAfterEnv": [ + "/jest.setup.js" + ], + "moduleNameMapper": { "\\.css$": "/static/css/__mocks__/styleMock.js" } + }, "version": "0.0.0" } diff --git a/website/plugins/buildAuthorPages/index.js b/website/plugins/buildAuthorPages/index.js new file mode 100644 index 00000000000..dd31ef41e91 --- /dev/null +++ b/website/plugins/buildAuthorPages/index.js @@ -0,0 +1,40 @@ +const fs = require('fs') +const yaml = require('js-yaml') + +module.exports = function buildAuthorPagesPlugin(context, options) { + return { + name: 'docusaurus-build-author-pages-plugin', + async loadContent() { + // Get all authors + const authors = yaml.load(fs.readFileSync(`blog/authors.yml`, { encoding: 'utf8' })) + return authors + }, + + async contentLoaded({content, actions}) { + const {createData, addRoute} = actions; + + for(let author in content) { + const authorJson = content[author] + authorJson.slug = author + + // Create json with author data + const authorData = await createData( + `author-${author}.json`, + JSON.stringify(authorJson), + ); + + // Add the author routes, and ensure it receives the author's data as props + addRoute({ + path: `/author/${authorJson.slug}`, + component: '@site/src/components/author/index.js', + modules: { + // propName -> JSON file path + authorData, + }, + exact: false, + }); + } + + }, + }; +} diff --git a/website/plugins/buildGlobalData/get-directory-files.js b/website/plugins/buildGlobalData/get-directory-files.js new file mode 100644 index 00000000000..925d66e8f6d --- /dev/null +++ b/website/plugins/buildGlobalData/get-directory-files.js @@ -0,0 +1,41 @@ +/** + * Get an array of all files in a directory + * and the ID from each file's frontmatter + * @param {string} dir Directory path + * @param {Array.} [directoryArr=[]] - Subdirectory found in readdirSync + * @returns {Array} - Array of file paths and file IDs + */ + +const fs = require('fs') +const matter = require('gray-matter') + +const getDirectoryFiles = (dir, directoryArr = []) => { + const files = fs.readdirSync(dir) + files.map(file => { + const filePath = `${dir}/${file}` + if(fs.statSync(filePath).isDirectory()) { + // If current item is directory, self-invoke getDirectoryFiles function + getDirectoryFiles(filePath, directoryArr) + } else { + // If a file, get markdown content + const fileData = fs.readFileSync(filePath, { encoding: 'utf8' }) + if(!fileData) + return null + + // convert frontmatter to json + const fileJson = matter(fileData) + if(!fileJson) + return null + + // add file contents to array + const { data } = fileJson + directoryArr.push({ + filePath, + id: data?.id || null + }) + } + }) + return directoryArr +} + +module.exports = { getDirectoryFiles } diff --git a/website/plugins/buildGlobalData/index.js b/website/plugins/buildGlobalData/index.js new file mode 100644 index 00000000000..cabeed1cf05 --- /dev/null +++ b/website/plugins/buildGlobalData/index.js @@ -0,0 +1,46 @@ +const fs = require('fs') +const yaml = require('js-yaml') +const slugify = require('slugify') +const { getDirectoryFiles } = require('./get-directory-files') + +// Pass custom data to blog +module.exports = function buildGlobalDataPlugin(context, options) { + return { + name: 'docusaurus-build-global-data-plugin', + async loadContent() { + + // Get all tags and build slug for tag + const tagArr = yaml.load(fs.readFileSync(`blog/categories.yml`, { encoding: 'utf8' })) + const tagData = tagArr.map(tag => { + tag.slug = slugify(tag.name) + return tag + }) + + // Get custom blog metadata + const blogMeta = yaml.load(fs.readFileSync(`blog/metadata.yml`, { encoding: 'utf8' })) + + // Get CTA data + const CTAData = yaml.load(fs.readFileSync(`blog/ctas.yml`, { encoding: 'utf8' })) + + // Get versionedPages param + // This controls versioning for sidebar + const { versionedPages } = options + + // Get all FAQ doc ids + // FAQ component uses these to pull file + const faqFiles = getDirectoryFiles(`docs/faqs`) + + return { + tagData, + blogMeta, + CTAData, + versionedPages, + faqFiles + } + }, + async contentLoaded({ content, actions }) { + const { setGlobalData } = actions; + setGlobalData(content); + }, + } +} diff --git a/website/sidebars.js b/website/sidebars.js old mode 100755 new mode 100644 index 69b128acab2..621e4ddd0d9 --- a/website/sidebars.js +++ b/website/sidebars.js @@ -1,14 +1,14 @@ -module.exports = { +const sidebarSettings = { docs: [ { type: "category", label: "Introduction", - items: ["docs/introduction", "docs/available-adapters"], + items: ["docs/introduction", "docs/supported-data-platforms", "docs/core-versions"], }, { type: "category", label: "Building a dbt Project", - collapsed: false, + collapsed: true, items: [ "docs/building-a-dbt-project/projects", { @@ -22,8 +22,10 @@ module.exports = { "docs/building-a-dbt-project/building-models/using-custom-schemas", "docs/building-a-dbt-project/building-models/using-custom-databases", "docs/building-a-dbt-project/building-models/using-variables", + "docs/building-a-dbt-project/building-models/python-models", ], }, + "docs/building-a-dbt-project/managing-environments", "docs/building-a-dbt-project/tests", "docs/building-a-dbt-project/documentation", "docs/building-a-dbt-project/using-sources", @@ -42,63 +44,60 @@ module.exports = { { type: "category", label: "Running a dbt Project", - collapsed: false, + collapsed: true, items: [ "docs/running-a-dbt-project/using-the-dbt-ide", "docs/running-a-dbt-project/using-the-cli", - "docs/running-a-dbt-project/dbt-api", "docs/running-a-dbt-project/running-dbt-in-production", ], }, { type: "category", - label: "Guides", + label: "Contributing", items: [ - "docs/guides/debugging-errors", - "docs/guides/debugging-schema-names", - "docs/guides/navigating-the-docs", - "docs/guides/getting-help", - "docs/guides/best-practices", - "docs/guides/managing-environments", - "docs/guides/writing-custom-generic-tests", - "docs/guides/building-packages", - "docs/guides/creating-new-materializations", - "docs/guides/understanding-state", + "docs/contributing/oss-expectations", + "docs/contributing/contributor-license-agreements", + "docs/contributing/slack-rules-of-the-road", + "docs/contributing/long-lived-discussions-guidelines", { type: "category", - label: "Migration guides", + label: "Adapter development", + link: { + type: 'generated-index', + title: 'Adapter Development', + description: 'Learn what an adapter is what what\'s required to make one. Also how to build, test, document, promote, and verify your new adapter. Visit the [#adapter-ecosystem](https://getdbt.slack.com/archives/C030A0UF5LM) Slack channel for additional help beyond this section.', + + }, items: [ - "docs/guides/migration-guide/upgrading-to-1-0-0", - "docs/guides/migration-guide/upgrading-to-0-21-0", - "docs/guides/migration-guide/upgrading-to-0-20-0", - "docs/guides/migration-guide/upgrading-to-0-19-0", - "docs/guides/migration-guide/upgrading-to-0-18-0", - "docs/guides/migration-guide/upgrading-to-0-17-0", - "docs/guides/migration-guide/upgrading-to-0-16-0", - "docs/guides/migration-guide/upgrading-to-0-15-0", - "docs/guides/migration-guide/upgrading-to-0-14-1", - "docs/guides/migration-guide/upgrading-to-0-14-0", - "docs/guides/migration-guide/upgrading-to-0-13-0", - "docs/guides/migration-guide/upgrading-to-0-12-0", - "docs/guides/migration-guide/upgrading-to-0-11-0", - ], - }, - "docs/guides/videos", + 'docs/contributing/adapter-development/1-what-are-adapters', + 'docs/contributing/adapter-development/2-prerequisites-for-a-new-adapter', + 'docs/contributing/adapter-development/3-building-a-new-adapter', + 'docs/contributing/adapter-development/4-testing-a-new-adapter', + 'docs/contributing/adapter-development/5-documenting-a-new-adapter', + 'docs/contributing/adapter-development/6-promoting-a-new-adapter', + 'docs/contributing/adapter-development/7-verifying-a-new-adapter' + ] + } ], }, { type: "category", - label: "Contributing", - items: [ - "docs/contributing/contributor-license-agreements", - "docs/contributing/building-a-new-adapter", - "docs/contributing/slack-rules-of-the-road", - ], + label: "About", + items: ["docs/about/license", "docs/about/viewpoint"], }, { type: "category", - label: "About", - items: ["docs/about/license", "docs/about/viewpoint"], + label: "Frequently asked questions", + link: { + type: 'generated-index', title: 'Frequently asked questions', + description: 'Our Frequently Asked Questions (FAQs) section is a space where you can find an answer to some questions we get asked a lot (but that we’re happy to answer!). If you have a question or are still stuck on something, just reach out to us by emailing support@getdbt.com or clicking on the chat widget, and we’ll do our best to help out.', slug: '/docs/faqs', + }, + items: [ + { + type: 'autogenerated', + dirName: 'faqs' + }, + ], }, ], "dbt CLI": [ @@ -117,8 +116,14 @@ module.exports = { "dbt-cli/configure-your-profile", ], "dbt Cloud": [ - "docs/dbt-cloud/cloud-overview", - "docs/dbt-cloud/cloud-quickstart", + { + type: "category", + label: "Overview", + link: { type: 'doc', id: 'docs/dbt-cloud/cloud-overview' }, + items: [ + 'docs/dbt-cloud/cloud-quickstart', + ], + }, { type: "category", label: "dbt Cloud IDE", @@ -127,6 +132,7 @@ module.exports = { "docs/dbt-cloud/cloud-ide/handling-merge-conflicts", "docs/dbt-cloud/cloud-ide/viewing-docs-in-the-ide", "docs/dbt-cloud/cloud-ide/the-ide-git-button", + "docs/dbt-cloud/cloud-ide/ide-beta", ], }, { @@ -138,6 +144,15 @@ module.exports = { "docs/dbt-cloud/cloud-configuring-dbt-cloud/cloud-configuring-repositories", "docs/dbt-cloud/cloud-configuring-dbt-cloud/cloud-installing-the-github-application", "docs/dbt-cloud/cloud-configuring-dbt-cloud/connecting-gitlab", + { + type: "category", + label: "Connecting Azure DevOps", + link: { type: 'doc', id: 'docs/dbt-cloud/cloud-configuring-dbt-cloud/connecting-azure-devops' }, + items: [ + 'docs/dbt-cloud/cloud-configuring-dbt-cloud/setup-azure', + 'docs/dbt-cloud/cloud-configuring-dbt-cloud/authenticate-azure', + ], + }, "docs/dbt-cloud/cloud-configuring-dbt-cloud/cloud-import-a-project-by-git-url", "docs/dbt-cloud/cloud-configuring-dbt-cloud/cloud-choosing-a-dbt-version", "docs/dbt-cloud/cloud-configuring-dbt-cloud/cloud-upgrading-dbt-versions", @@ -146,6 +161,12 @@ module.exports = { { type: "category", label: "Using dbt Cloud", + link: { + type: 'generated-index', + title: 'Using dbt Cloud', + description: 'Learn how you can use dbt Cloud.', + slug: '/docs/dbt-cloud', + }, items: [ "docs/dbt-cloud/using-dbt-cloud/cloud-enabling-continuous-integration", "docs/dbt-cloud/using-dbt-cloud/cloud-generating-documentation", @@ -154,8 +175,10 @@ module.exports = { "docs/dbt-cloud/using-dbt-cloud/cloud-using-a-custom-cron-schedule", "docs/dbt-cloud/using-dbt-cloud/cloud-setting-a-custom-target-name", "docs/dbt-cloud/using-dbt-cloud/cloud-environment-variables", - "docs/dbt-cloud/using-dbt-cloud/cloud-slack-notifications", + "docs/dbt-cloud/using-dbt-cloud/cloud-notifications", "docs/dbt-cloud/using-dbt-cloud/cloud-dashboard-status-tiles", + "docs/dbt-cloud/using-dbt-cloud/cloud-model-timing-tab", + "docs/dbt-cloud/using-dbt-cloud/cloud-metrics-layer", ], }, { @@ -191,6 +214,7 @@ module.exports = { "docs/dbt-cloud/cloud-configuring-dbt-cloud/cloud-setting-up-bigquery-oauth", ], }, + "docs/dbt-cloud/dbt-cloud-enterprise/audit-log", ], }, { @@ -229,22 +253,36 @@ module.exports = { items: [ "docs/dbt-cloud/dbt-cloud-api/metadata/schema/metadata-schema-model", "docs/dbt-cloud/dbt-cloud-api/metadata/schema/metadata-schema-models", + "docs/dbt-cloud/dbt-cloud-api/metadata/schema/metadata-schema-modelByEnv", + "docs/dbt-cloud/dbt-cloud-api/metadata/schema/metadata-schema-metric", + "docs/dbt-cloud/dbt-cloud-api/metadata/schema/metadata-schema-metrics", "docs/dbt-cloud/dbt-cloud-api/metadata/schema/metadata-schema-source", "docs/dbt-cloud/dbt-cloud-api/metadata/schema/metadata-schema-sources", "docs/dbt-cloud/dbt-cloud-api/metadata/schema/metadata-schema-seed", "docs/dbt-cloud/dbt-cloud-api/metadata/schema/metadata-schema-seeds", + "docs/dbt-cloud/dbt-cloud-api/metadata/schema/metadata-schema-snapshots", "docs/dbt-cloud/dbt-cloud-api/metadata/schema/metadata-schema-test", "docs/dbt-cloud/dbt-cloud-api/metadata/schema/metadata-schema-tests", "docs/dbt-cloud/dbt-cloud-api/metadata/schema/metadata-schema-exposure", "docs/dbt-cloud/dbt-cloud-api/metadata/schema/metadata-schema-exposures", - ], + ], }, ], }, ], }, "docs/dbt-cloud/cloud-dbt-cloud-support", - "docs/dbt-cloud/cloud-changelog", + { + type: "category", + label: "dbt Cloud Release Notes", + link: { type: 'doc', id: 'docs/dbt-cloud/release-notes' }, + items: [ + { + type: "autogenerated", + dirName: "docs/dbt-cloud/release-notes", + }, + ], + }, ], reference: [ { @@ -283,7 +321,17 @@ module.exports = { "reference/resource-configs/bigquery-configs", "reference/resource-configs/redshift-configs", "reference/resource-configs/snowflake-configs", + "reference/resource-configs/singlestore-configs", "reference/resource-configs/spark-configs", + "reference/resource-configs/materialize-configs", + "reference/resource-configs/firebolt-configs", + "reference/resource-configs/teradata-configs", + "reference/resource-configs/clickhouse-configs", + "reference/resource-configs/mindsdb-configs", + "reference/resource-configs/mssql-configs", + "reference/resource-configs/azuresynapse-configs", + "reference/resource-configs/greenplum-configs", + "reference/resource-configs/impala-configs", ], }, { @@ -298,7 +346,6 @@ module.exports = { "reference/resource-properties/columns", "reference/resource-properties/config", "reference/resource-properties/description", - "reference/resource-properties/docs", "reference/resource-properties/quote", "reference/resource-properties/tests", ], @@ -311,6 +358,8 @@ module.exports = { "reference/resource-configs/database", "reference/resource-configs/enabled", "reference/resource-configs/full_refresh", + "reference/resource-configs/grants", + "reference/resource-configs/docs", "reference/resource-configs/persist_docs", "reference/resource-configs/pre-hook-post-hook", "reference/resource-configs/schema", @@ -461,49 +510,20 @@ module.exports = { type: "category", label: "Jinja Reference", items: [ - "reference/dbt-jinja-functions", { type: "category", - label: "List of dbt Jinja functions", + label: "dbt Jinja functions", + link: { + type: 'generated-index', + title: 'dbt Jinja functions', + description: 'In addition to the standard Jinja library, we\'ve added additional functions and variables to the Jinja context that are useful when working with a dbt project.', + slug: '/reference/dbt-jinja-functions', + }, items: [ - "reference/dbt-jinja-functions/adapter", - "reference/dbt-jinja-functions/as_bool", - "reference/dbt-jinja-functions/as_native", - "reference/dbt-jinja-functions/as_number", - "reference/dbt-jinja-functions/as_text", - "reference/dbt-jinja-functions/builtins", - "reference/dbt-jinja-functions/config", - "reference/dbt-jinja-functions/dbt_version", - "reference/dbt-jinja-functions/debug-method", - "reference/dbt-jinja-functions/dispatch", - "reference/dbt-jinja-functions/doc", - "reference/dbt-jinja-functions/env_var", - "reference/dbt-jinja-functions/exceptions", - "reference/dbt-jinja-functions/execute", - "reference/dbt-jinja-functions/flags", - "reference/dbt-jinja-functions/fromjson", - "reference/dbt-jinja-functions/fromyaml", - "reference/dbt-jinja-functions/graph", - "reference/dbt-jinja-functions/invocation_id", - "reference/dbt-jinja-functions/log", - "reference/dbt-jinja-functions/model", - "reference/dbt-jinja-functions/modules", - "reference/dbt-jinja-functions/project_name", - "reference/dbt-jinja-functions/ref", - "reference/dbt-jinja-functions/return", - "reference/dbt-jinja-functions/run_query", - "reference/dbt-jinja-functions/run_started_at", - "reference/dbt-jinja-functions/schema", - "reference/dbt-jinja-functions/source", - "reference/dbt-jinja-functions/statement-blocks", - "reference/dbt-jinja-functions/target", - "reference/dbt-jinja-functions/this", - "reference/dbt-jinja-functions/tojson", - "reference/dbt-jinja-functions/toyaml", - "reference/dbt-jinja-functions/var", - "reference/dbt-jinja-functions/profiles-yml-context", - "reference/dbt-jinja-functions/dbt-project-yml-context", - "reference/dbt-jinja-functions/on-run-end-context", + { + type: "autogenerated", + dirName: "reference/dbt-jinja-functions", + }, ], }, "reference/dbt-classes", @@ -511,24 +531,42 @@ module.exports = { }, { type: "category", - label: "Profiles (CLI only)", + label: "Setups (CLI only)", items: [ "reference/profiles.yml", - "reference/warehouse-profiles/bigquery-profile", - "reference/warehouse-profiles/postgres-profile", - "reference/warehouse-profiles/redshift-profile", - "reference/warehouse-profiles/snowflake-profile", - "reference/warehouse-profiles/mssql-profile", - "reference/warehouse-profiles/presto-profile", - "reference/warehouse-profiles/trino-profile", - "reference/warehouse-profiles/spark-profile", - "reference/warehouse-profiles/exasol-profile", - "reference/warehouse-profiles/oracle-profile", - "reference/warehouse-profiles/azuresynapse-profile", - "reference/warehouse-profiles/dremio-profile", - "reference/warehouse-profiles/clickhouse-profile", - "reference/warehouse-profiles/materialize-profile", - "reference/warehouse-profiles/rockset-profile" + "reference/warehouse-setups/bigquery-setup", + "reference/warehouse-setups/postgres-setup", + "reference/warehouse-setups/redshift-setup", + "reference/warehouse-setups/snowflake-setup", + "reference/warehouse-setups/mssql-setup", + "reference/warehouse-setups/trino-setup", + "reference/warehouse-setups/singlestore-setup", + "reference/warehouse-setups/spark-setup", + "reference/warehouse-setups/databricks-setup", + "reference/warehouse-setups/hive-setup", + "reference/warehouse-setups/exasol-setup", + "reference/warehouse-setups/oracle-setup", + "reference/warehouse-setups/azuresynapse-setup", + "reference/warehouse-setups/dremio-setup", + "reference/warehouse-setups/clickhouse-setup", + "reference/warehouse-setups/materialize-setup", + "reference/warehouse-setups/rockset-setup", + "reference/warehouse-setups/firebolt-setup", + "reference/warehouse-setups/teradata-setup", + "reference/warehouse-setups/athena-setup", + "reference/warehouse-setups/vertica-setup", + "reference/warehouse-setups/tidb-setup", + "reference/warehouse-setups/glue-setup", + "reference/warehouse-setups/mindsdb-setup", + "reference/warehouse-setups/greenplum-setup", + "reference/warehouse-setups/impala-setup", + "reference/warehouse-setups/layer-setup", + "reference/warehouse-setups/iomete-setup", + "reference/warehouse-setups/duckdb-setup", + "reference/warehouse-setups/sqlite-setup", + "reference/warehouse-setups/mysql-setup", + "reference/warehouse-setups/ibmdb2-setup", + "reference/warehouse-setups/alloydb-setup", ], }, { @@ -543,54 +581,195 @@ module.exports = { "reference/artifacts/other-artifacts", ], }, + , + { + type: "category", + label: "Database Permissions", + items: [ + "reference/snowflake-permissions", + ], + }, ], - tutorial: [ + guides: [ { type: "category", - label: "Getting Started", - collapsed: false, + label: "Getting Started with dbt Cloud", + link: { type: 'doc', id: 'guides/getting-started/getting-started' }, items: [ - "tutorial/setting-up", { type: "category", - label: "Create a project", + label: "Getting set up", + link: { type: 'doc', id: 'guides/getting-started/getting-set-up' }, items: [ - "tutorial/create-a-project-dbt-cloud", - "tutorial/create-a-project-dbt-cli", + "guides/getting-started/getting-set-up/setting-up-bigquery", + "guides/getting-started/getting-set-up/setting-up-databricks", + "guides/getting-started/getting-set-up/setting-up-redshift", + "guides/getting-started/getting-set-up/setting-up-snowflake", ], }, - "tutorial/build-your-first-models", - "tutorial/test-and-document-your-project", - "tutorial/deploy-your-project", - ], + { + type: "category", + label: "Building your first project", + link: { type: 'doc', id: 'guides/getting-started/building-your-first-project' }, + + items: [ + "guides/getting-started/building-your-first-project/build-your-first-models", + "guides/getting-started/building-your-first-project/test-and-document-your-project", + "guides/getting-started/building-your-first-project/schedule-a-job", + ], + }, + { + type: "category", + label: "Learning more", + link: { type: 'doc', id: 'guides/getting-started/learning-more' }, + items: [ + "guides/getting-started/learning-more/getting-started-dbt-core", + "guides/getting-started/learning-more/using-jinja", + "guides/getting-started/learning-more/refactoring-legacy-sql", + ], + } + ] }, { type: "category", - label: "Leveling up", - collapsed: false, + label: "Best practices", + link: { + type: 'generated-index', + title: 'Best practice guides', + description: 'Learn how dbt Labs approaches building projects through our current viewpoints on structure, style, and setup.', + slug: '/guides/best-practices', + }, items: [ - "tutorial/using-jinja", - "tutorial/refactoring-legacy-sql" + { + type: "category", + label: "How we structure our dbt projects", + link: { type: 'doc', id: 'guides/best-practices/how-we-structure/1-guide-overview' }, + items: [ + "guides/best-practices/how-we-structure/2-staging", + "guides/best-practices/how-we-structure/3-intermediate", + "guides/best-practices/how-we-structure/4-marts", + "guides/best-practices/how-we-structure/5-the-rest-of-the-project", + ] + }, ], }, - ], - learn: [ { type: "category", - label: "Getting Started", + label: "Orchestration", + link: { + type: 'generated-index', + title: 'Orchestration guides', + description: 'Learn how to orchestrate your data transformations in dbt, using dbt Cloud, a variety of popular tools, or both working together.', + slug: '/guides/orchestration', + }, items: [ - "learn/setting-up", { type: "category", - label: "Create a project", + label: "Airflow and dbt Cloud", + link: { type: 'doc', id: 'guides/orchestration/airflow-and-dbt-cloud/1-airflow-and-dbt-cloud' }, items: [ - "learn/create-a-project-dbt-cloud", - "learn/create-a-project-dbt-cli", + "guides/orchestration/airflow-and-dbt-cloud/2-setting-up-airflow-and-dbt-cloud", + "guides/orchestration/airflow-and-dbt-cloud/3-running-airflow-and-dbt-cloud", + "guides/orchestration/airflow-and-dbt-cloud/4-airflow-and-dbt-cloud-faqs", ], }, - "learn/build-your-first-models", - "learn/test-and-document-your-project", + { + type: "category", + label: "Customizing CI/CD", + link: { type: 'doc', id: 'guides/orchestration/custom-cicd-pipelines/1-cicd-background' }, + items: [ + "guides/orchestration/custom-cicd-pipelines/2-lint-on-push", + "guides/orchestration/custom-cicd-pipelines/3-dbt-cloud-job-on-merge", + "guides/orchestration/custom-cicd-pipelines/4-something-to-consider", + ], + }, + ] + }, + { + type: "category", + label: "Migration", + items: [ + { + type: "category", + label: "Versions", + link: { + type: 'generated-index', + title: 'Version migration guides', + description: 'Learn how to upgrade to the latest version of dbt Core.', + slug: '/guides/migration/versions', + }, + items: [ + { + type: "autogenerated", + dirName: "guides/migration/versions", + }, + ], + }, + { + type: "category", + label: "Tools", + link: { + type: 'generated-index', + title: 'Tool migration guides', + description: 'Learn how to migrate to dbt from other tools and platforms.', + slug: '/guides/migration/tools', + }, + items: [ + { + type: "category", + label: "Migrating from stored procedures", + link: { + type: 'doc', + id: 'guides/migration/tools/migrating-from-stored-procedures/1-migrating-from-stored-procedures', + }, + items: [ + 'guides/migration/tools/migrating-from-stored-procedures/2-inserts', + 'guides/migration/tools/migrating-from-stored-procedures/3-updates', + 'guides/migration/tools/migrating-from-stored-procedures/4-deletes', + 'guides/migration/tools/migrating-from-stored-procedures/5-merges', + 'guides/migration/tools/migrating-from-stored-procedures/6-migrating-from-stored-procedures-conclusion', + ] + } + ] + }, + ] + }, + { + type: "category", + label: "Legacy", + items: [ + "guides/legacy/debugging-errors", + "guides/legacy/debugging-schema-names", + "guides/legacy/navigating-the-docs", + "guides/legacy/getting-help", + "guides/legacy/best-practices", + "guides/legacy/writing-custom-generic-tests", + "guides/legacy/building-packages", + "guides/legacy/creating-new-materializations", + "guides/legacy/understanding-state", + "guides/legacy/videos", + ] + }, + ], + "Glossary": [ + { + type: "category", + label: "Analytics Engineering Glossary", + link: { + type: 'generated-index', + title: 'Analytics Engineering Glossary', + description: 'The Analytics Engineering Glossary is a living collection of terms & concepts commonly used in the data industry. You can use and contribute to this resource to educate yourself, your team, and your stakeholders.', + slug: '/glossary', + }, + items: [ + { + type: 'autogenerated', + dirName: 'terms' + }, ], }, ], }; + + +module.exports = sidebarSettings diff --git a/website/snippets/available-beta-banner-metadata.md b/website/snippets/available-beta-banner-metadata.md new file mode 100644 index 00000000000..3ed785e95cb --- /dev/null +++ b/website/snippets/available-beta-banner-metadata.md @@ -0,0 +1,3 @@ +:::info Beta feature +This feature is currently in beta and subject to change. If you want to provide feedback, please [contact us](mailto:metadata@dbtlabs.com). +::: diff --git a/website/snippets/available-beta-banner.md b/website/snippets/available-beta-banner.md new file mode 100644 index 00000000000..15d365a84b1 --- /dev/null +++ b/website/snippets/available-beta-banner.md @@ -0,0 +1,3 @@ +:::info Beta feature +This feature is currently in beta and subject to change. If you are interested in getting access to the beta, please [contact us](mailto:support@getdbt.com). +::: diff --git a/website/snippets/available-enterprise-tier-only.md b/website/snippets/available-enterprise-tier-only.md new file mode 100644 index 00000000000..87ee93e776e --- /dev/null +++ b/website/snippets/available-enterprise-tier-only.md @@ -0,0 +1,5 @@ +:::caution Available for dbt Cloud Enterprise + +Connecting an Azure DevOps account is available for organizations using the dbt Cloud Enterprise tier. + +::: diff --git a/website/snippets/available-prerelease-banner.md b/website/snippets/available-prerelease-banner.md new file mode 100644 index 00000000000..3531a2f646f --- /dev/null +++ b/website/snippets/available-prerelease-banner.md @@ -0,0 +1,7 @@ +:::info Release candidate +dbt Core v1.2 is now available as a **release candidate**. + +For more information on prereleases, see ["About Core versions: Trying prereleases"](core-versions#trying-prereleases). + +Join the [#dbt-prereleases](https://getdbt.slack.com/archives/C016X6ABVUK) channel in the Community Slack so you can be the first to read about prereleases as soon as they're available! +::: diff --git a/website/snippets/core-versions-table.md b/website/snippets/core-versions-table.md new file mode 100644 index 00000000000..d8cd6314b6a --- /dev/null +++ b/website/snippets/core-versions-table.md @@ -0,0 +1,9 @@ +| dbt Core | Initial Release | Active Support Until | Critical Support Until | dbt Cloud Until | Final Patch | +|---------------------------------|-----------------|----------------------|-------------------------|-----------------|-------------| +| **v0.X** | (various dates) | v1.0.0 release | Dec 3, 2021 | See below ⚠️ | v0.21.1 | +| [**v1.0**](upgrading-to-v1.0) | Dec 3, 2021 | v1.1.0 release | Dec 3, 2022 | Dec 2022 | | +| [**v1.1**](upgrading-to-v1.1) | Apr 28, 2022 | v1.2.0 release | Apr 28, 2023 | Apr 2023 | | +| [**v1.2**](upgrading-to-v1.2) | Jul 26, 2022 | v1.3.0 release | Jul 26, 2023 | Jul 2023 | | +| _**v1.3**_ | _Oct 2022_ | _v1.4.0 release_ | _Oct 2023_ | _Oct 2023_ | | + +_Italics: Future releases, NOT definite commitments. Shown for indication only._ diff --git a/website/snippets/grants-vs-access-to.md b/website/snippets/grants-vs-access-to.md new file mode 100644 index 00000000000..6304a0fea78 --- /dev/null +++ b/website/snippets/grants-vs-access-to.md @@ -0,0 +1,12 @@ + + +:::info Note +The `grants` config and the `grant_access_to` config are distinct. + +- **`grant_access_to`:** Enables you to set up authorized views. When configured, dbt provides an authorized view access to show partial information from other datasets, without providing end users with full access to those underlying datasets. For more information, see ["BigQuery configurations: Authorized views"](/reference/resource-configs/bigquery-configs#authorized-views) +- **`grants`:** Provides specific permissions to users, groups, or service accounts for managing access to datasets you're producing with dbt. For more information, see ["Resource configs: grants"](resource-configs/grants) + +You can use the two features together: "authorize" a view model with the `grants_access_to` configuration, and then add `grants` to that view model to share its query results (and _only_ its query results) with other users, groups, or service accounts. +::: + + diff --git a/website/snippets/hooks-to-grants.md b/website/snippets/hooks-to-grants.md new file mode 100644 index 00000000000..3bbdd04879f --- /dev/null +++ b/website/snippets/hooks-to-grants.md @@ -0,0 +1,5 @@ + + +In older versions of dbt, the most common use of `post-hook` was to execute `grant` statements, to apply database permissions to models right after creating them. Starting in v1.2, we recommend using the [`grants` resource config](/reference/resource-configs/grants) instead, in order to automatically apply grants when your dbt model runs. + + diff --git a/website/snippets/slack-notifications-config-steps.md b/website/snippets/slack-notifications-config-steps.md new file mode 100644 index 00000000000..e643d4c5644 --- /dev/null +++ b/website/snippets/slack-notifications-config-steps.md @@ -0,0 +1,28 @@ +Setting up Slack notifications in dbt Cloud enables you to receive alerts in a chosen Slack channel when a job run succeeds, fails, or is cancelled. + +:::info Note +Currently, Slack notifications can only be configured by one user to one Slack channel. Additionally, you must be an admin of the Slack workspace in order to configure Slack notifications. + +If there have been changes to the user roles and you need to move ownership, please reach out to support@getdbt.com and provide the support team with the necessary information needed to make this change for you. +::: +### Setup the integration + +1. Click the gear in the top right and select **Profile**. +2. Click **Integrations** to the left. + +3. Click **Link your Slack profile** + +4. Allow dbt Labs to access the Slack workspace. If you are a member of multiple, you can select the appropriate workspace from the dropdown menu in the top right corner. + + +### Configure the notifications + +1. Click the gear in the top right and select **Account Settings**. +2. Click **Slack Notifications** to the left and click **Edit** to the right. + +3. You can find the Slack notification settings at the bottom of the page. + +### Disabling the Slack integration + +To disable the integration entirely, navigate back to the Integrations page and click **Disconnect Account** in the Slack pane. Confirm the disconnect, and the option will revert to its original state. + diff --git a/website/snippets/snowflake-acct-name.md b/website/snippets/snowflake-acct-name.md new file mode 100644 index 00000000000..7ab7bbd106f --- /dev/null +++ b/website/snippets/snowflake-acct-name.md @@ -0,0 +1,2 @@ +  ✅ `db5261993` or `db5261993.east-us-2.azure`
❌ `db5261993.eu-central-1.snowflakecomputing.com` diff --git a/website/snippets/test-snippet.md b/website/snippets/test-snippet.md new file mode 100644 index 00000000000..c1de326aa7a --- /dev/null +++ b/website/snippets/test-snippet.md @@ -0,0 +1,8 @@ +--- +--- + +### Header 2 + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam fermentum porttitor dui, id scelerisque enim scelerisque at. Proin imperdiet sem sed magna ornare, sit amet rutrum ligula vehicula. Aenean eget magna placerat, dictum velit sed, dapibus quam. Maecenas lectus tellus, dictum semper gravida vel, feugiat vitae nibh. Vestibulum nec lorem nibh. Fusce nisi felis, tincidunt ac scelerisque ut, aliquam in eros. Praesent euismod dolor ac lacinia laoreet. Phasellus orci orci, scelerisque vitae mollis id, consectetur ut libero. Aenean diam leo, tempor ut vulputate in, laoreet id ipsum. Quisque gravida et ex id eleifend. Etiam ultricies erat diam. Morbi hendrerit, ligula non aliquam tempus, erat elit suscipit quam, eu cursus quam nisi sit amet dui. Cras iaculis risus vel enim tempor molestie. + +Curabitur a porttitor odio. Curabitur sit amet tristique ante. Ut eleifend, erat eget imperdiet accumsan, quam diam sodales dolor, vulputate consequat lacus felis non sapien. Nam et nunc sed diam congue rutrum nec non massa. Nam eget fermentum sem. Nam ac imperdiet massa. Phasellus a elementum dui. diff --git a/website/snippets/tutorial-add-tests-to-models.md b/website/snippets/tutorial-add-tests-to-models.md new file mode 100644 index 00000000000..9989cbe2ecc --- /dev/null +++ b/website/snippets/tutorial-add-tests-to-models.md @@ -0,0 +1,62 @@ +Adding [tests](/docs/building-a-dbt-project/tests) to a project helps validate that your models are working correctly. + +To add tests to your project: + +1. Create a new YAML file in the `models` directory, named `models/schema.yml` +2. Add the following contents to the file: + + + + ```yaml + version: 2 + + models: + - name: customers + columns: + - name: customer_id + tests: + - unique + - not_null + + - name: stg_customers + columns: + - name: customer_id + tests: + - unique + - not_null + + - name: stg_orders + columns: + - name: order_id + tests: + - unique + - not_null + - name: status + tests: + - accepted_values: + values: ['placed', 'shipped', 'completed', 'return_pending', 'returned'] + - name: customer_id + tests: + - not_null + - relationships: + to: ref('stg_customers') + field: customer_id + + ``` + + + +3. Run `dbt test`, and confirm that all your tests passed. + +When you run `dbt test`, dbt iterates through your YAML files, and constructs a query for each test. Each query will return the number of records that fail the test. If this number is 0, then the test is successful. + +#### FAQs + + + + + + + + + diff --git a/website/snippets/tutorial-build-models-atop-other-models.md b/website/snippets/tutorial-build-models-atop-other-models.md new file mode 100644 index 00000000000..c769f1fc255 --- /dev/null +++ b/website/snippets/tutorial-build-models-atop-other-models.md @@ -0,0 +1,202 @@ +As a best practice in SQL, you should separate logic that cleans up your data from logic that transforms your data. You have already started doing this in the existing query by using common table expressions (CTEs). + +Now you can experiment by separating the logic out into separate models and using the [ref](ref) function to build models on top of other models: + +
+ +
+ +1. Create a new SQL file, `models/stg_customers.sql`, with the SQL from the `customers` CTE in our original query. +2. Create a second new SQL file, `models/stg_orders.sql`, with the SQL from the `orders` CTE in our original query. + + + +
+ + + + ```sql + select + id as customer_id, + first_name, + last_name + + from `dbt-tutorial`.jaffle_shop.customers + ``` + + + + + + ```sql + select + id as order_id, + user_id as customer_id, + order_date, + status + + from `dbt-tutorial`.jaffle_shop.orders + ``` + + + +
+ +
+ + + + ```sql + select + id as customer_id, + first_name, + last_name + + from jaffle_shop_customers + ``` + + + + + + ```sql + select + id as order_id, + user_id as customer_id, + order_date, + status + + from jaffle_shop_orders + ``` + + + +
+ +
+ + + + ```sql + select + id as customer_id, + first_name, + last_name + + from jaffle_shop.customers + ``` + + + + + + ```sql + select + id as order_id, + user_id as customer_id, + order_date, + status + + from jaffle_shop.orders + ``` + + + +
+ +
+ + + + ```sql + select + id as customer_id, + first_name, + last_name + + from raw.jaffle_shop.customers + ``` + + + + + + ```sql + select + id as order_id, + user_id as customer_id, + order_date, + status + + from raw.jaffle_shop.orders + ``` + + + +
+ +
+ +3. Edit the SQL in your `models/customers.sql` file as follows: + + + + ```sql + with customers as ( + + select * from {{ ref('stg_customers') }} + + ), + + orders as ( + + select * from {{ ref('stg_orders') }} + + ), + + customer_orders as ( + + select + customer_id, + + min(order_date) as first_order_date, + max(order_date) as most_recent_order_date, + count(order_id) as number_of_orders + + from orders + + group by 1 + + ), + + final as ( + + select + customers.customer_id, + customers.first_name, + customers.last_name, + customer_orders.first_order_date, + customer_orders.most_recent_order_date, + coalesce(customer_orders.number_of_orders, 0) as number_of_orders + + from customers + + left join customer_orders using (customer_id) + + ) + + select * from final + + ``` + + + +4. Execute `dbt run` + +This time, when you performed a `dbt run`, separate views/tables were created for `stg_customers`, `stg_orders` and `customers`. dbt inferred the order to run these models. Because `customers` depends on `stg_customers` and `stg_orders`, dbt builds `customers` last. You do not need to explicitly define these dependencies. + +### FAQs + + + + diff --git a/website/snippets/tutorial-change-way-model-materialized.md b/website/snippets/tutorial-change-way-model-materialized.md new file mode 100644 index 00000000000..395f3ea2e54 --- /dev/null +++ b/website/snippets/tutorial-change-way-model-materialized.md @@ -0,0 +1,64 @@ +One of the most powerful features of dbt is that you can change the way a model is materialized in your warehouse, simply by changing a configuration value. You can change things between tables and views by changing a keyword rather than writing the data definition language (DDL) to do this behind the scenes. + +By default, everything gets created as a view. You can override that by materializing everything in jaffle_shop as a table. Everything in the example project will still be materialized as a view. + +1. Edit your `dbt_project.yml` file. + - Update your project `name` to: + + + ```yaml + name: 'jaffle_shop' + ``` + + + - Update your `models` config block to: + + + + ```yaml + models: + jaffle_shop: + +materialized: table + example: + +materialized: view + ``` + + + - Click **Save**. + +2. Enter the `dbt run` command. Your `customers` model should now be built as a table! + :::info + To do this, dbt had to first run a `drop view` statement (or API call on BigQuery), then a `create table as` statement. + ::: + +3. Edit `models/customers.sql` to override the `dbt_project.yml` for the `customers` model only by adding the following snippet to the top, and click **Save**: + + + + ```sql + {{ + config( + materialized='view' + ) + }} + + with customers as ( + + select + id as customer_id + ... + + ) + + ``` + + + +4. Enter the `dbt run` command. Your model, `customers` should now build as a view. +5. Enter the `dbt run --full-refresh` command for this to take effect in your warehouse. + +### FAQs + + + + diff --git a/website/snippets/tutorial-create-new-dbt-cloud-account.md b/website/snippets/tutorial-create-new-dbt-cloud-account.md new file mode 100644 index 00000000000..bdde874d0c9 --- /dev/null +++ b/website/snippets/tutorial-create-new-dbt-cloud-account.md @@ -0,0 +1,10 @@ +Let's start this section by creating a dbt Cloud account if you haven't already. + +1. Navigate to [dbt Cloud](https://cloud.getdbt.com). +2. If you don't have a dbt Cloud account, create a new one, and verify your account via email. +3. If you already have a dbt Cloud account, you can create a new project from your existing account: + 1. Click the gear icon in the top-right, then click **Projects**. + 2. Click **+ New Project**. +4. You've arrived at the "Setup a New Project" page. +5. Type "Analytics" in the dbt Project Name field. You will be able to rename this project later. +6. Click **Continue**. \ No newline at end of file diff --git a/website/snippets/tutorial-delete-example-models.md b/website/snippets/tutorial-delete-example-models.md new file mode 100644 index 00000000000..e290877437c --- /dev/null +++ b/website/snippets/tutorial-delete-example-models.md @@ -0,0 +1,35 @@ +You can now delete the files that dbt created when you initialized the project: + +1. Delete the `models/example/` directory. +2. Delete the `example:` key from your `dbt_project.yml` file, and any configurations that are listed under it. + + + + ```yaml + # before + models: + jaffle_shop: + +materialized: table + example: + +materialized: view + ``` + + + + + + ```yaml + # after + models: + jaffle_shop: + +materialized: table + ``` + + + +3. Save your changes. + +#### FAQs + + + diff --git a/website/snippets/tutorial-document-your-models.md b/website/snippets/tutorial-document-your-models.md new file mode 100644 index 00000000000..87df51e45a6 --- /dev/null +++ b/website/snippets/tutorial-document-your-models.md @@ -0,0 +1,48 @@ +Adding [documentation](/docs/building-a-dbt-project/documentation) to your project allows you to describe your models in rich detail, and share that information with your team. Here, we're going to add some basic documentation to our project. + +1. Update your `models/schema.yml` file to include some descriptions, such as those below. + + + + ```yaml + version: 2 + + models: + - name: customers + description: One record per customer + columns: + - name: customer_id + description: Primary key + tests: + - unique + - not_null + - name: first_order_date + description: NULL when a customer has not yet placed an order. + + - name: stg_customers + description: This model cleans up customer data + columns: + - name: customer_id + description: Primary key + tests: + - unique + - not_null + + - name: stg_orders + description: This model cleans up order data + columns: + - name: order_id + description: Primary key + tests: + - unique + - not_null + - name: status + tests: + - accepted_values: + values: ['placed', 'shipped', 'completed', 'return_pending', 'returned'] + + ``` + + + +2. Run `dbt docs generate` to generate the documentation for your project. dbt introspects your project and your warehouse to generate a file with rich documentation about your project. diff --git a/website/snippets/tutorial-initiate-project.md b/website/snippets/tutorial-initiate-project.md new file mode 100644 index 00000000000..8711e4d2747 --- /dev/null +++ b/website/snippets/tutorial-initiate-project.md @@ -0,0 +1,45 @@ +Now that you have a repository configured, you can initialize your project and start development in dbt Cloud: + +1. Click **Develop** from the upper left. It might take a few minutes for your project to spin up for the first time as it establishes your git connection, clones your repo, and tests the connection to the warehouse. +2. Above the file tree to the left, click **Initialize your project**. This builds out your folder structure with example models. +3. Make your initial commit by clicking **Commit**. Use the commit message `initial commit`. This creates the first commit to your managed repo and allows you to open a branch where you can add new dbt code. +4. Now you should be able to **directly query data from your warehouse** and **execute dbt run**. You can try this out now: + - In "Scratchpad 1", delete all text and paste your warehouse-specific code into Scratchpad 1: + + + +
+ +```sql +select * from `dbt-tutorial.jaffle_shop.customers` +``` + +
+ +
+ +```sql +select * from default.jaffle_shop_customers +``` + +
+ +
+ +```sql +select * from jaffle_shop_customers +``` + +
+ +
+ +```sql +select * from raw.jaffle_shop.customers +``` + +
+ +
+ +- In the command line bar at the bottom, type `dbt run` and click **Enter**. We will explore what happens in the next section of the tutorial. diff --git a/website/snippets/tutorial-managed-repo.md b/website/snippets/tutorial-managed-repo.md new file mode 100644 index 00000000000..f0e34319a4e --- /dev/null +++ b/website/snippets/tutorial-managed-repo.md @@ -0,0 +1,6 @@ +dbt Cloud uses Git for version control, but using a managed repository makes this easier. To set up a managed repository: + +1. Under "Add repository from", select **Managed**. +2. Type a name for your repo such as `bbaggins-dbt-quickstart` +3. Click **Create**. It will take a few seconds for your repository to be created and imported. +4. Once you see the "Successfully imported repository," click **Continue**. \ No newline at end of file diff --git a/website/snippets/tutorial-next-steps-1st-model.md b/website/snippets/tutorial-next-steps-1st-model.md new file mode 100644 index 00000000000..76cf72bf8a7 --- /dev/null +++ b/website/snippets/tutorial-next-steps-1st-model.md @@ -0,0 +1,7 @@ +Before moving on from building your first models, make a change and see how it affects your results: + +* Write some bad SQL to cause an error — can you debug the error? +* Run only a single model at a time. For more information, see [Syntax overview](/reference/node-selection/syntax). +* Group your models with a `stg_` prefix into a `staging` subdirectory. For example, `models/staging/stg_customers.sql`. + * Configure your `staging` models to be views. + * Run only the `staging` models. diff --git a/website/snippets/tutorial-next-steps-setting-up.md b/website/snippets/tutorial-next-steps-setting-up.md new file mode 100644 index 00000000000..364189b57cb --- /dev/null +++ b/website/snippets/tutorial-next-steps-setting-up.md @@ -0,0 +1 @@ +You can **[Continue the tutorial by building your first project](/building-your-first-project)**. You will learn and apply the fundamentals of dbt with models, tests, docs, and deploying your first job! diff --git a/website/snippets/tutorial-next-steps-tests.md b/website/snippets/tutorial-next-steps-tests.md new file mode 100644 index 00000000000..ee4277b694e --- /dev/null +++ b/website/snippets/tutorial-next-steps-tests.md @@ -0,0 +1,5 @@ +Before moving on from testing, make a change and see how it affects your results: + +* Write a test that fails, for example, omit one of the order statuses in the `accepted_values` list. What does a failing test look like? Can you debug the failure? +* Run the tests for one model only. If you grouped your `stg_` models into a directory, try running the tests for all the models in that directory. +* Use a [docs block](/docs/building-a-dbt-project/documentation#using-docs-blocks) to add a Markdown description to a model. diff --git a/website/snippets/tutorial-sql-query.md b/website/snippets/tutorial-sql-query.md new file mode 100644 index 00000000000..b39373608e8 --- /dev/null +++ b/website/snippets/tutorial-sql-query.md @@ -0,0 +1,258 @@ + + + +
+ +```sql +with customers as ( + + select + id as customer_id, + first_name, + last_name + + from `dbt-tutorial`.jaffle_shop.customers + +), + +orders as ( + + select + id as order_id, + user_id as customer_id, + order_date, + status + + from `dbt-tutorial`.jaffle_shop.orders + +), + +customer_orders as ( + + select + customer_id, + + min(order_date) as first_order_date, + max(order_date) as most_recent_order_date, + count(order_id) as number_of_orders + + from orders + + group by 1 + +), + +final as ( + + select + customers.customer_id, + customers.first_name, + customers.last_name, + customer_orders.first_order_date, + customer_orders.most_recent_order_date, + coalesce(customer_orders.number_of_orders, 0) as number_of_orders + + from customers + + left join customer_orders using (customer_id) + +) + +select * from final +``` + +
+ + + +
+ +```sql +with customers as ( + + select + id as customer_id, + first_name, + last_name + + from jaffle_shop_customers + +), + +orders as ( + + select + id as order_id, + user_id as customer_id, + order_date, + status + + from jaffle_shop_orders + +), + +customer_orders as ( + + select + customer_id, + + min(order_date) as first_order_date, + max(order_date) as most_recent_order_date, + count(order_id) as number_of_orders + + from orders + + group by 1 + +), + +final as ( + + select + customers.customer_id, + customers.first_name, + customers.last_name, + customer_orders.first_order_date, + customer_orders.most_recent_order_date, + coalesce(customer_orders.number_of_orders, 0) as number_of_orders + + from customers + + left join customer_orders using (customer_id) + +) + +select * from final +``` + +
+ + + +
+ +```sql +with customers as ( + + select + id as customer_id, + first_name, + last_name + + from jaffle_shop.customers + +), + +orders as ( + + select + id as order_id, + user_id as customer_id, + order_date, + status + + from jaffle_shop.orders + +), + +customer_orders as ( + + select + customer_id, + + min(order_date) as first_order_date, + max(order_date) as most_recent_order_date, + count(order_id) as number_of_orders + + from orders + + group by 1 + +), + +final as ( + + select + customers.customer_id, + customers.first_name, + customers.last_name, + customer_orders.first_order_date, + customer_orders.most_recent_order_date, + coalesce(customer_orders.number_of_orders, 0) as number_of_orders + + from customers + + left join customer_orders using (customer_id) + +) + +select * from final +``` + +
+ + + +
+ +```sql +with customers as ( + + select + id as customer_id, + first_name, + last_name + + from raw.jaffle_shop.customers + +), + +orders as ( + + select + id as order_id, + user_id as customer_id, + order_date, + status + + from raw.jaffle_shop.orders + +), + +customer_orders as ( + + select + customer_id, + + min(order_date) as first_order_date, + max(order_date) as most_recent_order_date, + count(order_id) as number_of_orders + + from orders + + group by 1 + +), + +final as ( + + select + customers.customer_id, + customers.first_name, + customers.last_name, + customer_orders.first_order_date, + customer_orders.most_recent_order_date, + coalesce(customer_orders.number_of_orders, 0) as number_of_orders + + from customers + + left join customer_orders using (customer_id) + +) + +select * from final +``` + +
+ +
diff --git a/website/src/components/author/index.js b/website/src/components/author/index.js new file mode 100644 index 00000000000..9fc568c1d0c --- /dev/null +++ b/website/src/components/author/index.js @@ -0,0 +1,102 @@ +import React from 'react'; +import Head from '@docusaurus/Head'; +import Link from '@docusaurus/Link'; +import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; +import BlogLayout from '@theme/BlogLayout'; +import getAllPosts from '../../utils/get-all-posts'; + +function Author(props) { + const { authorData } = props + const { siteConfig } = useDocusaurusContext() + + const presets = + siteConfig.presets && + siteConfig.presets[0].find(preset => preset['blog']) + + let blogData = {} + if(presets) blogData = presets['blog'] + + const { name, job_title, image_url, organization, description, links, slug } = authorData + + // Get all posts and filter by Author + let authorPosts = getAllPosts().filter(post => + post.authors.find(auth => auth.key === slug) + ) + + return ( + + + + + {description && + + } + + +
+
+
+ {name} +
+
+

{name}

+

+ {job_title && job_title} {organization && `@ ${organization}`} +
+ {links && links.length > 0 && ( + <> + | + {links.map((link, i) => ( + + + + ))} + + ) + } +
+

+

{description ? description : ''}

+
+
+ {authorPosts && authorPosts.length > 0 && + + } +
+
+ ); +} + +// Author Posts component +function AuthorPosts({posts, siteImg}) { + return ( +
+

Author Posts

+
+ {posts.map((post, i) => { + const { authors, date, formattedDate, permalink, title, description } = post + return ( +
+ +

{title}

+ +

{description}

+
+ ) + })} +
+
+ ) +} + + + +export default Author; + diff --git a/website/src/components/cta/index.js b/website/src/components/cta/index.js new file mode 100644 index 00000000000..eb0ad21bea5 --- /dev/null +++ b/website/src/components/cta/index.js @@ -0,0 +1,29 @@ +import React, { useState, useEffect } from 'react' +import {usePluginData} from '@docusaurus/useGlobalData'; + +export default function CTA({ cta }) { + + const { CTAData } = usePluginData('docusaurus-build-global-data-plugin'); + + const thisCta = CTAData.find(data => data.name === cta) + + if(!thisCta) + return false + + const { header, subheader, button_text, url } = thisCta + + return ( +
+

{header}

+

{subheader}

+ {button_text && ( + {button_text} + )} +
+ ) +} diff --git a/website/src/components/discourse/index.js b/website/src/components/discourse/index.js new file mode 100644 index 00000000000..ade96f5fd99 --- /dev/null +++ b/website/src/components/discourse/index.js @@ -0,0 +1,207 @@ +import React, { useState, useEffect } from 'react' +import axios from 'axios' +import feedStyles from './styles.module.css'; + +// Bare component with no default props set +export const DiscourseFeed = ({ + order, + status, + after, + before, + inString, + min_posts, + max_posts, + min_views, + max_views, + tags, + term, + category, + title, + link_text, + link_href, + show_cta, + topic_count = 5, + styles = {} +}) => { + + const [topics, setTopics] = useState([]) + const [loading, setLoading] = useState(true) + const [isError, setIsError] = useState(false) + + useEffect(() => { + let isMounted = true + + // Get topics from Discourse API + const fetchData = async () => { + try { + // Ensure error state is false and loading true + setLoading(true) + setIsError(false) + + // Build Netlify Function endpoint + const endpoint = window?.location?.hostname?.includes('localhost') + ? 'http://localhost:8888/.netlify/functions/get-discourse-topics' + : '/.netlify/functions/get-discourse-topics' + + // If 'after' prop not passed in, set relative after date + let afterDate = after + if(!afterDate) { + // Today's date + let today = new Date(); + if(category === 'help') { + const relativeDate = new Date(today.setDate(today.getDate() - 30)); + afterDate = formatDate(relativeDate) + } else { + const relativeDate = new Date(today.setDate(today.getDate() - 90)); + afterDate = formatDate(relativeDate) + } + } + + // Get Discourse topics data + const { data } = await axios.post(endpoint, { + status, + order, + after: afterDate, + before, + inString, + min_posts, + max_posts, + min_views, + max_views, + tags, + term, + category, + }) + + // Set error state if data not available + if(!data) throw new Error('Unable to get latest topics.') + + // Set topics count + if(isMounted) { + setTopics(data.slice(0, topic_count)) + setLoading(false) + } + } catch(err) { + setIsError(true) + setLoading(false) + } + } + fetchData() + + return () => { + isMounted = false + } + }, []) + + // Set initial min-height + // This is to avoid layout shifts + // which affects Lighthouse performance scores + const setMinHeight = isError + ? 'auto' + : 414 + + return ( +
+ {title && ( +

{title}

+ )} + {loading ? ( + Loading + ) : isError || !topics?.length > 0 ? ( +

Unable to load forum topics at this time.

+ ) : ( +
    + {topics.map(topic => ( +
  • + {topic?.has_accepted_answer && ( + + )} + {topic.title} + {(topic?.author || topic?.posts_count || topic?.like_count) && ( + <> + {' '} + + {topic?.author && `by ${topic.author}${topic?.posts_count ? ',' : ''}`} + {' '} + {topic?.posts_count && `${topic.posts_count - 1} ${(topic.posts_count - 1) === 1 ? 'reply' : 'replies'}${topic?.like_count ? ',' : ''}`} + {' '} + {topic?.like_count ? `${topic.like_count} ${(topic.like_count) === 1 ? 'like' : 'likes'}` : ''} + + + )} +
  • + ))} +
+ )} + {show_cta && ( + {link_text} + )} +
+ ) +} + +// A more specific version of DiscourseFeed +// with default props set. Same props can be used +export const DiscourseHelpFeed = ({ + order = 'latest_topic', + status = 'solved', + category = 'help', + tags, + show_cta = true, + link_text = 'Ask the Community', + link_href = `https://discourse.getdbt.com/new-topic${category ? `?category=${category}` : ''}${tags ? (!category ? `?tags=${tags}` : `&tags=${tags}`) : ''}`, + after, + before, + inString, + min_posts, + max_posts, + min_views, + max_views, + term, + title, + topic_count = 5, + styles = {} +}) => { + return +} + +// Helpers +function TopicWrapper({ topic, children }) { + if(topic?.slug && topic?.id) { + return ( + {children} + ) + } else { + return ( +
{children}
+ ) + } +} + +function formatDate(date) { + return `${date.getFullYear()}-${('0'+ (date.getMonth()+1)).slice(-2)}-${('0'+ date.getDate()).slice(-2)}` +} + diff --git a/website/src/components/discourse/index.test.js b/website/src/components/discourse/index.test.js new file mode 100644 index 00000000000..c0d40e26b8f --- /dev/null +++ b/website/src/components/discourse/index.test.js @@ -0,0 +1,93 @@ +import React from 'react' +import axios from 'axios' +import { render, screen } from '@testing-library/react' +import { DiscourseFeed } from './index' + +// Mock api data +const mockAxiosResponse = { + data: [ + { + "id": 4911, + "title": "Processing source tables with differing arrival times throughout day", + "has_accepted_answer": true, + "author": "MatthewMunn", + "like_count": 1, + "posts_count": 2 + } + ], +} + +describe("Test DiscourseFeed component", () => { + // returns mocks to original state (ex: window = undefined) + afterEach(() => jest.restoreAllMocks()) + + it('Should render same text passed into title prop', () => { + render() + const testElement = screen.getByText(/Open topics/i) + expect(testElement).toBeInTheDocument() + }) + + it('Should display loading icon on inital load', () => { + render() + const img = screen.getByTestId('feed-loader') + expect(img).toBeInTheDocument() + }) + + it('Should display Discourse data after API fetch', async () => { + // Get mock api response + jest.spyOn(axios, 'post').mockResolvedValueOnce(mockAxiosResponse) + + render() + // Topic "has_accepted_answer" - should display ✅ ahead of title + const topicCheckMark = await screen.findByText(/✅/i) + expect(topicCheckMark).toBeInTheDocument() + + // Topic title should exist in document + const topicTitle = await screen.findByText(/Processing source tables/i) + expect(topicTitle).toBeInTheDocument() + + // Author should display + const topicAuthor = await screen.findByText(/MatthewMunn/i) + expect(topicAuthor).toBeInTheDocument() + + // Should display reply + const topicReply = await screen.findByText(/1 reply/i) + expect(topicReply).toBeInTheDocument() + + // Has 1 like, should display '1 like' and not '1 likes' + const topicLikes = await screen.findByText(/1 like/i) + expect(topicLikes).toBeInTheDocument() + }) + + it('Should show cta with correct text and href', async () => { + // Get mock api response + jest.spyOn(axios, 'post').mockResolvedValueOnce(mockAxiosResponse) + + render() + + const button = await screen.findByTestId('feed-cta') + const buttonText = await screen.findByText(/See open topics/i) + const buttonHref = buttonText.closest('a') + expect(button).toBeInTheDocument() + expect(buttonText).toBeInTheDocument() + expect(buttonHref).toHaveAttribute('href', 'https://discourse.getdbt.com/c/help/19') + }) + + it('Should display message when no topics found', async () => { + // Get mock api response + const mockEmptyResponse = { + data: [], + } + jest.spyOn(axios, 'post').mockResolvedValueOnce(mockEmptyResponse) + + render() + + const errorText = await screen.findByTestId('error-text') + expect(errorText).toBeInTheDocument() + }) +}) + diff --git a/website/src/components/discourse/styles.module.css b/website/src/components/discourse/styles.module.css new file mode 100644 index 00000000000..34c228838f9 --- /dev/null +++ b/website/src/components/discourse/styles.module.css @@ -0,0 +1,51 @@ +/* Topics Section */ +.discourseTopics { + margin: 2rem 0 3rem; + display: flex; + flex-direction: column; + align-items: flex-start; +} +.discourseTopics:last-of-type { + margin-bottom: 0; +} +.discourseTopics .solvedTopic { + font-size: .8rem; +} +.discourseTopics .solvedTopic:hover { + cursor: default; +} +.discourseTopics ul { + list-style: none; + margin: 0 0 1rem; + padding: 0; + width: 100%; +} +.discourseTopics ul li { + padding: 1rem 0; + border-bottom: 2px solid var(--color-off-white); +} +.discourseTopics ul li:last-of-type { + border-bottom: none; +} +.discourseTopics ul li a { + font-weight: 600; + font-size: 18px; +} + +/* Cta */ +.discourseCta { + font-size: 1.1rem; + margin-top: auto; + color: #fff; +} +.discourseCta:hover { + background: var(--color-light-teal); + color: #fff; +} + +/* Loading icon */ +.discourseTopics .loadingIcon { + max-width: 100px; + display: block; +} + diff --git a/website/src/components/events/index.js b/website/src/components/events/index.js new file mode 100644 index 00000000000..a2c0df8eba5 --- /dev/null +++ b/website/src/components/events/index.js @@ -0,0 +1,16 @@ +import React, { useEffect } from 'react' +import feedStyles from './styles.module.css'; + +export default function EventsFeed(styles = {}) { + useEffect(() => { + const script = document.createElement('script'); + script.src = 'https://cdn.addevent.com/libs/cal/js/cal.events.embed.t3.init.js'; + script.async = true; + document.body.appendChild(script); + }, []) + return ( +
+
+
+ ) +} diff --git a/website/src/components/events/styles.module.css b/website/src/components/events/styles.module.css new file mode 100644 index 00000000000..d5b3e877c45 --- /dev/null +++ b/website/src/components/events/styles.module.css @@ -0,0 +1,5 @@ +.aeEmbed { + width: 100%; + height: 500px; + margin: 0 auto 20px; +} diff --git a/website/src/components/faqList/index.js b/website/src/components/faqList/index.js index b04d22d73b2..e29cbfddd54 100644 --- a/website/src/components/faqList/index.js +++ b/website/src/components/faqList/index.js @@ -2,13 +2,13 @@ import React from 'react'; import styles from './styles.module.css'; const files = require.context( - '../../../docs/faqs', - true, - /\.md$/ + '../../../docs/faqs', + true, + /\.md$/ ); var faqs = []; -files.keys().forEach(function(key, i) { +files.keys().forEach(function (key, i) { if (key.endsWith('index.md')) { return; } @@ -18,22 +18,22 @@ files.keys().forEach(function(key, i) { var el = faq.default({}); faqs.push( -
-

- # - {i+1}. {meta.title} -

-
- {el} -
+
+

+ # + {i + 1}. {meta.title} +

+
+ {el} +
); }); -function FAQList({children, style}) { +function FAQList({ children, style }) { return (
- {faqs} + {faqs}
); } diff --git a/website/src/components/faqs/index.js b/website/src/components/faqs/index.js index 000c76964e1..4f07d9127f4 100644 --- a/website/src/components/faqs/index.js +++ b/website/src/components/faqs/index.js @@ -1,30 +1,60 @@ -import React, {useState} from 'react'; +import React, { useState, useEffect } from 'react'; import styles from './styles.module.css'; +import { usePluginData } from '@docusaurus/useGlobalData'; -function FAQ({children, src, alt_header=null}) { - const file = require('../../../docs/faqs/' + src + '.md') - const meta = file.metadata; - const contents = file.default({}); +function FAQ({ children, src, alt_header = null }) { const [isOn, setOn] = useState(false); - const toggleOn = function() { - setOn(!isOn); + const [filePath, setFilePath] = useState(src) + const [fileContent, setFileContent] = useState({}) + + // Get all faq file paths from plugin + const { faqFiles } = usePluginData('docusaurus-build-global-data-plugin'); + + useEffect(() => { + // Search for faq where frontmatter ID matches src prop + const faqFile = faqFiles.find(file => file.id === src) + + // If faqFile found with ID, set filePath for this file + if (faqFile?.id) { + const data = faqFile.filePath.match(/(docs\/docs\/faqs\/(.*)\.md$)/g) + if (data?.length) { + setFilePath(data[1]) + } + } + }, []) + + useEffect(() => { + try { + const file = require(`../../../docs/faqs/${filePath}.md`) + if (file) { + const meta = file.metadata; + const contents = file.default({}); + setFileContent({ meta, contents }) + } + } catch (err) { + return null + } + }, [filePath]) + + const toggleOn = function () { + setOn(!isOn); } return ( -
- - -   - { alt_header || meta.title } - -
- { contents } -
+
+ + +   + {alt_header || fileContent?.meta && fileContent.meta.title} + +
+ {fileContent?.contents && fileContent.contents}
+
); } diff --git a/website/src/components/faqs/styles.module.css b/website/src/components/faqs/styles.module.css index d37b292825b..baeecd2c2f5 100644 --- a/website/src/components/faqs/styles.module.css +++ b/website/src/components/faqs/styles.module.css @@ -10,7 +10,7 @@ :local(.toggle) { background-image: var(--ifm-menu-link-sublist-icon); - background-size: 2rem 2rem; + background-size: 1.25rem 1.25rem; background-position: center; content: ' '; display: inline-block; @@ -19,11 +19,17 @@ vertical-align: middle; } +/* hack for unswizzled FAQ arrows */ +:local(html[data-theme='dark'] .toggle) { + filter: invert(1); +} + :local(.body) { margin-left: 2em; margin-bottom: 10px; padding: 20px; background-color: #e3f8f8; + color: var(--ifm-color-gray-900); } :local(.body > p:last-child) { diff --git a/website/src/components/file/styles.module.css b/website/src/components/file/styles.module.css index dc9cf008306..a461116cad6 100644 --- a/website/src/components/file/styles.module.css +++ b/website/src/components/file/styles.module.css @@ -18,6 +18,12 @@ font-size: 12px; } +:local(html[data-theme='dark'] .title) { + background-color: var(--ifm-menu-color-background-active); + border: 1px solid var(--ifm-menu-color-background-active); + color: white; +} + :local(.titleInner) { margin: 4px 8px; } diff --git a/website/src/components/lightbox/index.js b/website/src/components/lightbox/index.js index 90ae6e3898c..d312e67ca8f 100644 --- a/website/src/components/lightbox/index.js +++ b/website/src/components/lightbox/index.js @@ -5,19 +5,32 @@ import styles from './styles.module.css'; function Lightbox({children, src, title, collapsed}) { var collapsedClass = !!collapsed ? styles.collapsed : ''; + const featherlightStyles = ` + /** + * Featherlight - ultra slim jQuery lightbox + * Version 1.7.14 - http://noelboss.github.io/featherlight/ + * + * Copyright 2019, Noël Raoul Bossart (http://www.noelboss.com) + * MIT Licensed. + **/ + html.with-featherlight{overflow:hidden}.featherlight{display:none;position:fixed;top:0;right:0;bottom:0;left:0;z-index:2147483647;text-align:center;white-space:nowrap;cursor:pointer;background:#333;background:rgba(0,0,0,0)}.featherlight:last-of-type{background:rgba(0,0,0,.8)}.featherlight:before{content:'';display:inline-block;height:100%;vertical-align:middle}.featherlight .featherlight-content{position:relative;text-align:left;vertical-align:middle;display:inline-block;overflow:auto;padding:25px 25px 0;border-bottom:25px solid transparent;margin-left:5%;margin-right:5%;max-height:95%;background:#fff;cursor:auto;white-space:normal}.featherlight .featherlight-inner{display:block}.featherlight link.featherlight-inner,.featherlight script.featherlight-inner,.featherlight style.featherlight-inner{display:none}.featherlight .featherlight-close-icon{position:absolute;z-index:9999;top:0;right:0;line-height:25px;width:25px;cursor:pointer;text-align:center;font-family:Arial,sans-serif;background:#fff;background:rgba(255,255,255,.3);color:#000;border:0;padding:0}.featherlight .featherlight-close-icon::-moz-focus-inner{border:0;padding:0}.featherlight .featherlight-image{width:100%}.featherlight-iframe .featherlight-content{border-bottom:0;padding:0;-webkit-overflow-scrolling:touch}.featherlight iframe{border:0}.featherlight *{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}@media only screen and (max-width:1024px){.featherlight .featherlight-content{margin-left:0;margin-right:0;max-height:98%;padding:10px 10px 0;border-bottom:10px solid transparent}}@media print{html.with-featherlight>*>:not(.featherlight){display:none}} + ` return ( -
- - - {title} - - -

{ title }

-
+ + +
+ + + {title} + + +

{ title }

+
+
); } diff --git a/website/src/components/lightbox/styles.module.css b/website/src/components/lightbox/styles.module.css index f86929d94fc..4c33e5173e5 100644 --- a/website/src/components/lightbox/styles.module.css +++ b/website/src/components/lightbox/styles.module.css @@ -1,18 +1,18 @@ :local(.title) { text-align: center; + font-size: small; width: 100%; } - :local(.docImage) { - filter: drop-shadow(1px 4px 10px #aaaaaa33); + filter: drop-shadow(4px 4px 6px #aaaaaa33); margin: 10px auto; display: block; - width: 600px; + max-width: 400px; } :local(.collapsed) { - max-width: 300px !important; + max-width: 400px !important; display: inline-block; } diff --git a/website/src/components/snippet/index.js b/website/src/components/snippet/index.js new file mode 100644 index 00000000000..e92c2aed901 --- /dev/null +++ b/website/src/components/snippet/index.js @@ -0,0 +1,18 @@ +import React from 'react' +import styles from './styles.module.css'; +import WHCore from '@site/src/components/whcode'; + +{/* + The Snippet component works in a similar way as FAQs. + Pass the filename of a snippet within the snippets directory + as a prop to use throughout the docs. +*/} +export default function Snippet({ src }) { + const file = require('../../../snippets/' + src + '.md') + const contents = file.default({}); + return ( +
+ { contents } +
+ ) +} diff --git a/website/src/components/snippet/styles.module.css b/website/src/components/snippet/styles.module.css new file mode 100644 index 00000000000..38d1e96f42e --- /dev/null +++ b/website/src/components/snippet/styles.module.css @@ -0,0 +1,3 @@ +:local(.snippet) { + margin: 2rem 0; +} diff --git a/website/src/components/term/index.js b/website/src/components/term/index.js new file mode 100644 index 00000000000..c233647dc73 --- /dev/null +++ b/website/src/components/term/index.js @@ -0,0 +1,67 @@ +import React, { useState, useEffect } from 'react' +import Link from '@docusaurus/Link'; +import ReactTooltip from "react-tooltip"; +import styles from './styles.module.css'; + +{/* + Props: + id: filename of term + children (optional): to display different text + other than displayText property for term +*/} +export default function Term({ id, children = undefined }) { + + const [uniqueID, setUniqueID] = useState(String(Math.random())) + const [pageReady, setPageReady] = useState(false) + + // Rebuild tooltips on every update + useEffect(() => { + ReactTooltip.rebuild() + setPageReady(true) + }) + + const file = require('../../../docs/terms/' + id + '.md') + if(!file) + return null + + const fm = file.frontMatter + if(!fm) + return null + + const { displayText, hoverSnippet } = fm + + return ( + <> + {pageReady ? ( + <> + + {/* If component has children, show children text, + Else, default to displayText frontmatter field, + Or filename if displayText not set + */} + {children ? children : displayText ? displayText : id} + + {hoverSnippet && ( + + {hoverSnippet} + + )} + + ) : ( + {children ? children : displayText ? displayText : id} + )} + + ) +} diff --git a/website/src/components/term/styles.module.css b/website/src/components/term/styles.module.css new file mode 100644 index 00000000000..482e76bda52 --- /dev/null +++ b/website/src/components/term/styles.module.css @@ -0,0 +1,17 @@ +.term { + cursor: pointer; + position: relative; + text-decoration: underline dotted var(--ifm-font-color-base); + color: var(--ifm-font-color-base); +} +.term:hover { + color: var(--ifm-link-color); + text-decoration: underline dotted var(--ifm-link-color); +} +.termToolTip { + background: var(--color-primary-blue) !important; + font-size: .9rem !important; + color: #fff !important; + max-width: 400px; + font-style: normal; +} diff --git a/website/src/components/variable/index.js b/website/src/components/variable/index.js new file mode 100644 index 00000000000..444f3203327 --- /dev/null +++ b/website/src/components/variable/index.js @@ -0,0 +1,45 @@ +import React, { useState, useEffect, useContext } from 'react' +import { dbtVariables } from '../../../dbt-global-variables'; +import VersionContext from '../../stores/VersionContext'; + +export default function Var({ name }) { + if(!name) + return null + + const [variableName, setVariableName] = useState('') + + const { version } = useContext(VersionContext) + + const currentVariable = dbtVariables[name] + if(!currentVariable) + return null + + useEffect(() => { + if(currentVariable?.versions?.length && version) { + {/* + * If versions set for variable + * show correct variable name for current version + * + * Sort by lowest version first + * If this version is greater or equal to the active version + * Show this variable name + * If no match is found, show original variable name + * + */} + const thisVersionVariable = currentVariable.versions + .sort((item1, item2) => (parseFloat(item1.version) > parseFloat(item2.version)) ? 1 : -1) + .find(varVersion => + parseFloat(varVersion.version) >= parseFloat(version) ? true : false + ) + + !thisVersionVariable + ? setVariableName(currentVariable.name) + : setVariableName(thisVersionVariable.name) + + } else { + setVariableName(currentVariable.name) + } + }, [version]) + + return { variableName } +} diff --git a/website/src/components/versionBlock/index.js b/website/src/components/versionBlock/index.js new file mode 100644 index 00000000000..01d6381c0e1 --- /dev/null +++ b/website/src/components/versionBlock/index.js @@ -0,0 +1,39 @@ +import React, { useState, useEffect, useContext } from 'react' +import VersionContext from '../../stores/VersionContext'; + +export default function VersionBlock({ firstVersion = 0, lastVersion = undefined, children }) { + const { version } = useContext(VersionContext) + + const [loading, setLoading] = useState(true) + + // Hide versionBlock components until version ready + useEffect(() => { + version && setLoading(false) + }, [version]) + + // Only check version if current version set + if(version) { + const currentVersionVal = parseFloat(version) + const firstVersionVal = parseFloat(firstVersion) + {/* + * If last version set, check if current version greater than last version + * Or if current version less than first version + * If either is true, hide block + * Else, if current version less than first version, hide block + */} + if(lastVersion) { + if((currentVersionVal > parseFloat(lastVersion)) + || (currentVersionVal < firstVersionVal)) + return null + } else { + if(currentVersionVal < firstVersionVal) { + return null + } + + } + } + + return loading + ? null + : <>{children} +} diff --git a/website/src/components/versionBlock/index.test.js b/website/src/components/versionBlock/index.test.js new file mode 100644 index 00000000000..b001ac2b6df --- /dev/null +++ b/website/src/components/versionBlock/index.test.js @@ -0,0 +1,47 @@ +import React from 'react' +import { render, screen } from '@testing-library/react'; +import { fail } from 'assert'; +import VersionBlock from './index' +import { VersionContextProvider } from '../../stores/VersionContext' + +describe("Test VersionBlock component", () => { + // returns mocks to original state (ex: window = undefined) + afterEach(() => jest.restoreAllMocks()) + + it('Should render same text passed into title prop', () => { + render(Versioned content) + const testElement = screen.getByText(/Versioned content/i) + expect(testElement).toBeInTheDocument() + }) + + it.each([ + [ + 'Should render content if current version >= firstVersion', + "0.21", + true + ], + [ + 'Should not render content if current version less than firstVersion', + "0.20", + false + ], + ])('%s', (desc, version, shouldShowContent) => { + // '%s' prints first arg in each array + // '%s %s' prints first two args in each array + jest.spyOn(window.localStorage.__proto__, 'getItem').mockReturnValue(version) + + const firstVersion = "0.21" + render( + + + Current version + + + ) + const content = screen.queryByText(/current version/i) + shouldShowContent + ? expect(content).toBeInTheDocument() + : expect(content).not.toBeInTheDocument() + }) +}) + diff --git a/website/src/components/whcode/index.js b/website/src/components/whcode/index.js new file mode 100644 index 00000000000..cf581442208 --- /dev/null +++ b/website/src/components/whcode/index.js @@ -0,0 +1,36 @@ +import React from 'react'; + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +function WHCode({children}) { + + let tabValuesArr = [] + let value + + const tabItems = children.map((child, index) => { + if (child.props.warehouse == undefined || child.props.warehouse == '') { + throw "Expected warehouse prop to be defined for each child of WHCode component"; + } + + tabValuesArr.push({ label: child.props.warehouse, value: child.props.warehouse }) + + value = child.props.warehouse + + return ( + + {child} + + ); + }) + + return ( + + {tabItems} + + ); +} + +export default WHCode; diff --git a/website/src/components/wistia/index.js b/website/src/components/wistia/index.js index 5c2c7387b7e..fdcfad99b62 100644 --- a/website/src/components/wistia/index.js +++ b/website/src/components/wistia/index.js @@ -1,19 +1,21 @@ import React from 'react'; -function WistiaVideo({id}) { + + +function WistiaVideo({id, paddingTweak = "56.25%"}) { return ( -
-
+
+
diff --git a/website/src/css/custom.css b/website/src/css/custom.css index 87cabbb54f6..0b5c456e5a2 100644 --- a/website/src/css/custom.css +++ b/website/src/css/custom.css @@ -1,8 +1,14 @@ :root { - --ifm-color-success: #047377 !important; + --ifm-color-success: #086343 !important; --ifm-color-info: #047377 !important; - --ifm-color-warning: #ff694a !important; - --ifm-color-danger: #ff694a !important; + --ifm-color-warning: #9f1b1f !important; + --ifm-color-danger: #a64f21 !important; + --ifm-color-success-light: #d6f3e2 !important; + --ifm-color-info-light: #d9f6f4 !important; + --ifm-color-warning-light: #ffe1be !important; + --ifm-color-danger-light: #f9d3d4 !important; + --ifm-color-gray-900: #262a38; + --ifm-font-weight-narrow: 400; --ifm-font-weight-semibold: 600; --ifm-font-weight-bold: 700; --ifm-h1-font-size: 2.5rem; @@ -10,16 +16,21 @@ --ifm-h3-font-size: 1.563rem; --ifm-h4-font-size: 1.063rem; --ifm-h5-font-size: 0.938rem; - --ifm-navbar-height: 94px; + --ifm-navbar-height: 85px; + --ifm-navbar-link-hover-color: var(--color-orange); + --ifm-navbar-link-active-color: var(--color-orange); + --ifm-footer-padding-vertical: calc(var(--ifm-spacing-vertical) * 1.875); --ifm-footer-background-color: #4f5d75; - --ifm-footer-color: #bfc0c0; + --ifm-footer-color: var(--color-white); --ifm-link-color: #009999; + --ifm-color-primary: #047377; --ifm-link-hover-color: #047377; - --ifm-button-border-radius: 4px; + --ifm-button-border-radius: 5px; --ifm-menu-color: #262a38; --ifm-menu-color-active: #009999; --ifm-pagination-nav-color-hover: #047377; --ifm-tabs-color-active: #047377; + --ifm-menu-color-background-active: #EFFBFA; --ifm-font-family-monospace: "Source Code Pro", SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; --ifm-font-family-base: "Source Sans Pro", sans-serif; @@ -29,46 +40,187 @@ --ifm-code-background: var(--ifm-color-emphasis-200); --ifm-navbar-item-padding-horizontal: 1rem; --ifm-alert-color: var(--ifm-font-color-base-inverse); + --ifm-color-info-contrast-foreground: var(--ifm-color-gray-900); + --ifm-alert-foreground-color: --ifm-color-gray-900; + --ifm-toc-padding-vertical: 1rem; --color-primary-blue: #262a38; --color-green-blue: #047377; --color-light-teal: #009999; --color-light-blue: #96d7d1; --color-orange: #ff694a; --color-off-white: #eff2f3; + --color-white: white; --color-nav-text: #bfc0c0; + --color-nav-sub-level-text: #545A66; + --color-footer-accent: #979EAB; + --docsearch-text-color: #262a38; + --pagination-icon-next: '\2192'; + --pagination-icon-prev: '\2190'; + --filter-brightness-low: 1.1; + --filter-brightness-high: 1.5; + + --light-dark-toggle: 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0iTTQuMzA4IDMuMzg1YzAtMS4xNzguMTczLTIuMzcuNjE1LTMuMzg1QzEuOTgzIDEuMjggMCA0LjI4MiAwIDcuNjkyQTguMzA4IDguMzA4IDAgMCAwIDguMzA4IDE2YzMuNDEgMCA2LjQxMi0xLjk4MyA3LjY5Mi00LjkyMy0xLjAxNS40NDItMi4yMDcuNjE1LTMuMzg1LjYxNWE4LjMwOCA4LjMwOCAwIDAgMS04LjMwNy04LjMwN1oiIGZpbGw9IiM5MkEwQjMiLz48L3N2Zz4='; + + /* search overrides */ + --docsearch-searchbox-background: var(--color-white) !important; + --docsearch-searchbox-focus-background: var(--color-white) !important; + --docsearch-searchbox-shadow: inset 0 0 0 0 var(--docsearch-primary-color) !important; + + --docsearch-modal-background: var(--color-white) !important; + --docsearch-modal-shadow: none; + --docsearch-muted-color-for-keys: #EFF2F3; + + --docsearch-highlight-color: var(--docsearch-muted-color) !important; + --docsearch-muted-color: #545A66; + --docsearch-container-background: rgba(255,255,255, 1) !important; + + --docsearch-key-gradient: transparent !important; + --docsearch-key-shadow: inset 0 0 0 0 #cdcde6,inset 0 0 0 0 #fff,0 0 0 0 rgba(30,35,90,0.0) !important; + --docsearch-key-shadow: none !important; } -.container.home:nth-child(odd) { - background: var(--color-off-white); +/* dark theme styles!!! */ +html[data-theme='dark'] { + --ifm-navbar-background-color: var(--color-primary-blue); + --ifm-menu-color-background-active: var(--color-primary-blue); + --ifm-menu-color: var(--color-white); + + /* search button darkmode */ + --docsearch-muted-color: var(--color-off-white); + --docsearch-muted-color-for-keys: var(--docsearch-muted-color); + --docsearch-searchbox-background: var(--color-primary-blue) !important; + + /* search popup */ + --docsearch-modal-background: var(--color-primary-blue) !important; + --docsearch-footer-background: var(--color-primary-blue) !important; + --docsearch-searchbox-focus-background: var(--color-primary-blue) !important; + --docsearch-highlight-color: var(--docsearch-muted-color) !important; + + /* admonition icon */ + --ifm-color-info-contrast-foreground: var(--ifm-color-gray-900); + + --ifm-table-cell-color: var(--color-green-blue); } -/* For /dbt-cloud/api redoc page */ -div.collapser { +/* For /dbt-cloud/api REDOC Page */ +html[data-theme='dark'] .api-content h2, +html[data-theme='dark'] .api-content h3, +html[data-theme='dark'] .api-content h4, +html[data-theme='dark'] .api-content h5, +html[data-theme='dark'] .api-content h5 span, +html[data-theme='dark'] .api-content h1 { color: white; } -.admonition h5 { - text-transform: none; +html[data-theme='dark'] .api-content button, +html[data-theme='dark'] .api-content a { + filter: brightness(1.25); +} + +html[data-theme='dark'] .api-content a:hover { + filter: brightness(1.25); +} + +.redoc-wrap .api-content a, +.redoc-wrap .api-content a:visited { + color: var(--color-green-blue); +} + +.redoc-wrap { font-size: 1rem; } -.navbar__link--active { - border-bottom: 1px solid #fff; - padding: 0px 2px; - margin-left: 10px; - margin-right: 10px; +.api-content { + font-size: 1.125rem; +} + +.menu-content { + font-size: 1rem; + margin-top: 1em; +} + +html[data-theme='dark'] .api-content { + color: white; +} + +html[data-theme='dark'] .api-content table td > span, +html[data-theme='dark'] .api-content table td p { + color: var(--color-orange); +} + +html[data-theme='dark'] table td { + filter: brightness(1.25); + color: white; +} + +html[data-theme='dark'] .api-content table td span { + color: white; +} + +html[data-theme='dark'] .hComDo div { + background: transparent; +} + +html[data-theme='dark'] .api-content table td p { + color: brown; +} + +html[data-theme='dark'] .redoc-wrap .menu-content * :not(.operation-type), +html[data-theme='dark'] .redoc-wrap .menu-content, +html[data-theme='dark'] .redoc-wrap .menu-content .search-input { + color: white !important; + background-color: transparent !important; +} + +html[data-theme='dark'] .redoc-wrap svg { + filter: brightness(4.5); +} + +html[data-theme='dark'] .redoc-markdown pre { + filter: brightness(1.5); +} + +html[data-theme='dark'] input.sc-avest { + filter: brightness(2.5); +} + +.dropdown--version--hide .dropdown__menu { + opacity: 0; + visibility: hidden; + display: none; +} + +.container.home:nth-child(odd) { + background: var(--color-off-white); +} + +html[data-theme='dark'] .container.home { + background: var(--ifm-background-color) !important; +} + +div.collapser { + color: var(--color-white); } h1, h2, h3 { - font-weight: var(--ifm-font-weight-semibold); + font-weight: var(--ifm-font-weight-bold); } -.navbar__search-input { - color: #505d73; - font-weight: var(--ifm-font-weight-semibold); - font-size: 1rem; +/* V2.0.0-beta.6 style updates */ +.padding-top--md { + padding-top: 2rem !important; +} + +code { + border: none; + background-color: var(--ifm-color-emphasis-200); + color: var(--ifm-color-emphasis-900); +} + +html[data-theme='dark'] a code { + color: var(--color-white); } .main-wrapper .home .col > p { @@ -79,6 +231,7 @@ h3 { h1.docTitle_node_modules-\@docusaurus-theme-classic-src-theme-DocItem- { font-size: 2rem; } + /* Adding FAQ specific links so we can left-justify the FAQ page titles */ a.hash-link-faq:link { margin-left: -20px; @@ -87,27 +240,17 @@ a.hash-link-faq:link { a.hash-link-faq:visited, a.hash-link-faq:hover { - color: black; + color: var(--docsearch-text-color); } a.hash-link-faq:active { - color: black; + color: var(--docsearch-text-color); } a.hash-link:link, a.hash-link:visited, a.hash-link:hover { - color: black; -} - -footer { - font-weight: var(--ifm-font-weight-bold); -} - -/* Fix for nav links that break (like dbt Cloud) */ - -.navbar__item.navbar__link { - white-space: nowrap; + color: var(--docsearch-text-color); } pre { @@ -123,38 +266,206 @@ a.code-link:hover { text-decoration: underline; } -nav.navbar, -div.navbar-sidebar__brand { - background-color: var(--color-primary-blue); +/* navbar */ +[data-theme='dark'] nav.navbar, +[data-theme='dark'] div.navbar-sidebar__brand { + background-color: var(--ifm-navbar-background-color); } -nav.navbar a.navbar__link { - color: var(--color-nav-text); - font-weight: var(--ifm-font-weight-bold); - transition: 100ms all ease-in-out; +.navbar__logo { + margin-left: 1.25rem; } -nav.navbar a.navbar__link:hover { - color: var(--color-light-teal); +.navbar__search-input { + color: #505d73; + font-weight: var(--ifm-font-weight-semibold); + font-size: 1rem; } -nav.navbar .navbar__toggle, -nav.navbar a.navbar__link--active { - color: white !important; - font-weight: bold !important; +.navbar__link { + font-size: 1rem; + margin: var(--ifm-navbar-item-padding-vertical) var(--ifm-navbar-item-padding-horizontal) 0; + padding: 0; + border-bottom: 1px solid transparent; +} + +/* Fix for nav links that break (like dbt Cloud) */ +.navbar__item.navbar__link { + white-space: nowrap; + align-items: center; +} + +.navbar__link--active { + border-bottom: 1px solid var(--color-orange); + color: var(--color-orange); +} + +.navbar__link.nav-versioning { + display: flex; + align-items: baseline; + justify-content: center; +} + +/* Search Button Styles */ +.search { + width: 100%; + padding: 10px 0px; + font-size: 20px; + border: 0px; + outline-width: 0px; + transition: all .3s ease; +} + +/* search popup */ +.DocSearch-Container { + background-color: rgba(0,0,0,.85) !important; +} + +.DocSearch-Form { + border: 1px solid var(--docsearch-muted-color); } -li.menu__list-item a.navbar__link--active { - color: black !important; - font-weight: bold !important; +.DocSearch-Footer { + background: var(--docsearch-footer-background); + padding: 0 var(--docsearch-spacing); + border-radius: 0 0 5px 5px !important; } -nav.navbar div.navbar__inner { - margin-left: 10px !important; +.navbar-sidebar__close { + margin-right: .75em; } -.dropdown__link { +/* navbar buttons */ +a.navbar__item.navbar__link.btn { + border: none; + color: var(--color-white); + background-color: var(--ifm-tabs-color-active); + align-self: center; + padding: 0.5em 1em; + border-radius: var(--ifm-button-border-radius); +} + +a.navbar__item.navbar__link.btn:hover { + filter: brightness(var(--filter-brightness-high)); + transition: all .3s ease; +} + +/* sidebar menu */ +.menu__link { font-size: 1rem; + justify-content: flex-end; + flex-direction: row-reverse; + padding: 1rem; +} + +.menu__list-item-collapsible .menu__link { + color: inherit; +} + +.menu__caret, .menu__link { + display: flex; + align-items: center; +} + +.menu__caret { + padding: 0; +} + +.menu__caret:hover { + background: transparent; +} + +.hasHref_src-theme-DocSidebarItem-styles-module { + padding-left: 0; +} + +/* level2 */ +.menu__list .menu__list { + font-weight: var(--ifm-font-weight-narrow); + padding-left: 1.5rem; +} + +.menu__list .menu__list .menu__link { + padding-top: .5rem; + padding-bottom: .5rem; +} + +.menu__list-item-collapsible a { + padding-left: 0; +} + +.menu__list .menu__list a.menu__link.menu__link--sublist { + font-weight: var(--ifm-font-weight-semibold); + padding: 1rem; +} + +.menu__list-item-collapsible .menu__link--active { + color: inherit; +} + +i.theme-doc-sidebar-item-category.theme-doc-sidebar-item-category-level-2.menu__list-item { + margin-left: 1rem; +} + + + +/* color for subtext only */ +.theme-doc-sidebar-item-link :not(.menu__list-item-collapsible .menu__link:first-of-type) { + color: var(--color-nav-sub-level-text); +} + +[data-theme='dark'] .theme-doc-sidebar-item-link :not(.menu__list-item-collapsible .menu__link:first-of-type) { + color: var(--color-white); +} + +.theme-doc-sidebar-item-link .menu__link--active { + color: var(--ifm-link-color); +} + +/* set < icon to left side */ +.menu__list-item-collapsible { + flex-direction: row-reverse; + background-color: transparent; +} + +.menu__list-item-collapsible:hover { + background-color: transparent; +} + +.menu__list-item--collapsed .menu__link--sublist::after, +.menu__list-item--collapsed .menu__caret::before { + transform: rotateZ(90deg); +} + +/* < icon */ +.menu__link--sublist::after, +.menu__caret::before { + transform: rotate(-90deg); + margin-right: 1em; + background: var(--ifm-breadcrumb-separator) center; + background-repeat: no-repeat; + height: 9px; + min-width: 6px; + width: calc( var(--ifm-breadcrumb-separator-size) * var(--ifm-breadcrumb-size-multiplier) * var(--ifm-breadcrumb-separator-size-multiplier) ); +} + +/* Table of Contents */ +.table-of-contents__link:hover, +.table-of-contents__link:hover code, +.table-of-contents__link--active, +.table-of-contents__link--active code, +.tableOfContents_src-theme-TOC-styles-module a.theme-edit-this-page:hover { + color: var(--color-orange); +} + +.tableOfContents_src-theme-TOC-styles-module a.theme-edit-this-page { + color: var(--ifm-toc-link-color); +} + +.table-of-contents { + font-size: 0.9rem; + padding-left: 1.25rem; + padding-right: 1.25rem; } .featherlight:before { @@ -174,13 +485,34 @@ nav.navbar div.navbar__inner { font-size: 20px !important; } -/* Shamelessly copy/pasted from our style guide */ +/* admonition */ +.admonition { + border-left-width: 0.625rem; + border-radius: 0.625rem; +} + +.admonition h5 { + text-transform: none; + font-size: 1.5rem; +} + +.admonition-icon svg { + fill: var(--ifm-color-gray-900); +} + +.admonition:not(.admonition-note) h5, +.admonition:not(.admonition-note) .admonition-content, +.admonition:not(.admonition-note) .admonition-content a { + color: var(--ifm-color-gray-900); +} +/* Shamelessly copy/pasted from our style guide */ .alert { padding: 1.5rem 2rem; - margin-bottom: 1.8rem; - border: 1px solid transparent; - border-radius: 4px; + margin-top: 2.125em; + margin-bottom: 1.8em; + /* border: 1px solid transparent; */ + border-radius: 5px; } .alert h4 { margin-top: 0; @@ -196,54 +528,34 @@ nav.navbar div.navbar__inner { .alert > p + p { margin-top: 5px; } -.alert-default { - background-color: var(--color-off-white); - border-color: transparent; - color: var(--color-primary-blue); -} -.alert-success { - background-color: var(--color-off-white); - border-color: transparent; - color: var(--color-green-blue); -} -.alert-success hr { - border-top-color: transparent; -} -.alert-success .alert-link { - color: var(--color-green-blue); -} -.alert-info { - background-color: var(--color-light-blue); - border-color: transparent; - color: var(--color-green-blue); -} -.alert-info hr { - border-top-color: transparent; -} -.alert-info .alert-link { - color: var(--color-green-blue); -} -.alert-warning { - background-color: var(--color-off-white); - border-color: transparent; - color: var(--color-orange); -} -.alert-warning hr { - border-top-color: transparent; + +.alert--info { + --ifm-alert-background-color: var(--ifm-color-info-light); + --ifm-alert-border-color: var(--ifm-color-info); + color: var(--ifm-color-gray-900); } -.alert-warning .alert-link { - color: var(--color-orange); +.alert--success { + --ifm-alert-background-color: var(--ifm-color-success-light); + --ifm-alert-border-color: var(--ifm-color-success); + color: var(--ifm-color-gray-900); } -.alert-danger { - background-color: #ffe1db; - border-color: transparent; - color: var(--color-orange); +.alert--danger { + --ifm-alert-background-color: var(--ifm-color-danger-light); + --ifm-alert-border-color: var(--ifm-color-danger); + color: var(--ifm-color-gray-900); } -.alert-danger hr { - border-top-color: transparent; +.alert--warning { + --ifm-alert-background-color: var(--ifm-color-warning-light); + --ifm-alert-border-color: var(--ifm-color-warning); + color: var(--ifm-color-gray-900); } -.alert-danger .alert-link { - color: var(--color-orange); + +/* for dark mode */ +.alert--info a, +.alert--success a, +.alert--danger a, +.alert--warning a { + color: var(--ifm-color-gray-900); } .linkout { @@ -257,6 +569,7 @@ nav.navbar div.navbar__inner { vertical-align: middle; } +/* banners */ .banner-animation { /*background-color: #013544;*/ background-color: var(--color-off-white); @@ -293,23 +606,16 @@ nav.navbar div.navbar__inner { animation: march 8s linear infinite forwards; } -.search { - width: 100%; - padding: 10px 0px; - font-size: 20px; - border: 0px; - outline-width: 0px; -} - -.menu__link { - font-size: 1rem; - padding: 5px 0px 5px 10px !important; +div .toggle_src-components-faqs-styles-module { + background-size: 1.25rem 1.25rem; } .home .row .col--4 { margin-bottom: 20px; min-height: 251px; } + +/* card styles */ .card.large { position: relative; height: 100%; @@ -322,6 +628,7 @@ nav.navbar div.navbar__inner { .card.large .card__footer { z-index: 9; } + .card.large:before { position: absolute; z-index: 0; @@ -332,6 +639,7 @@ nav.navbar div.navbar__inner { background: var(--color-primary-blue); content: ""; } + .card.large:after { position: absolute; z-index: 0; @@ -347,12 +655,13 @@ nav.navbar div.navbar__inner { content: ""; } -.card { +.home .card { background: var(--ifm-footer-background-color); - color: #fff; + color: var(--color-white); } .card.large .button { + color: var(--color-white); font-size: 1.25rem; font-weight: var(--ifm-font-weight-semibold); margin-top: 0.25rem; @@ -366,14 +675,14 @@ nav.navbar div.navbar__inner { .card.large .button:hover { background: #fff; - border-color: #fff; + border-color: var(--color-white); color: var(--color-green-blue); } .card.large.dark .button:hover { background: var(--color-light-teal); border-color: var(--color-light-teal); - color: #fff; + color: var(--color-white); } .card.large.light .button, @@ -385,7 +694,7 @@ nav.navbar div.navbar__inner { .card.large.light .button:hover { background: #de5d43; border-color: #de5d43; - color: #fff; + color: var(--color-white); } .card.large.light-blue .button { @@ -405,106 +714,742 @@ nav.navbar div.navbar__inner { line-height: 26px; } -/* Table of Contents */ -.table-of-contents__link:hover, -.table-of-contents__link:hover code, -.table-of-contents__link--active, -.table-of-contents__link--active code { - color: var(--ifm-link-hover-color); -} -.table-of-contents { - font-size: 0.9rem; +/* Pagination */ +.pagination-nav { + gap: 1em; } -/* Pagination */ .pagination-nav__link { + padding: 1rem 0; transition: 100ms all ease-in-out; + border: none; +} + +.pagination-nav__item--next .pagination-nav__label::after { + content: var(--pagination-icon-next); + font-weight: var(--ifm-font-weight-narrow); + margin-left: .5em; +} + +.pagination-nav__item:first-child .pagination-nav__label::before { + content: var(--pagination-icon-prev) ; + font-weight: var(--ifm-font-weight-narrow); + margin-right: .5em; +} + +.pagination-nav__sublabel { + font-weight: var(--ifm-font-weight-narrow); + margin-bottom: 1em; } /* Font Sizing Adjustments */ -.markdown > p { - font-size: 1.05rem; +.markdown > p, +.markdown li, +blockquote { + font-size: 1.125rem; + line-height: 1.5; } .pagination-nav__link { - font-size: 1.05rem; + font-size: 1rem; } .title_src-components-file- { - font-size: 0.813rem !important; + font-size: 1.125rem !important; +} +.markdown h1:first-child { + font-size: clamp(var(--ifm-h1-font-size) * .9375, 1vw, var(--ifm-h1-font-size)); + margin-top: .5rem; +} +.link_src-components-faqs-styles-module { + font-size: 1.125rem; } /* Docs */ -.docImage_src-components-lightbox-, .docImage_2V3X { +.docImage_src-components-lightbox-, +.docImage_src-components-lightbox-styles-module, +.docImage_2V3X, .docImage_917O { max-width: 100%; } +.generatedIndexPage_node_modules-\@docusaurus-theme-classic-lib-next-theme-DocCategoryGeneratedIndexPage-styles-module .cardContainer_node_modules-\@docusaurus-theme-classic-lib-next-theme-DocCard-styles-module, .generatedIndexPage_aEAk .card { + color: var(--color-white); + background: var(--ifm-footer-background-color); +} +.generatedIndexPage_node_modules-\@docusaurus-theme-classic-lib-next-theme-DocCategoryGeneratedIndexPage-styles-module .cardContainer_node_modules-\@docusaurus-theme-classic-lib-next-theme-DocCard-styles-module:hover, .generatedIndexPage_aEAk .card:hover { + color: var(--color-white); + background: var(--color-primary-blue); +} + +/* Custom Blog Styles */ +.blog-breadcrumbs { + display: block; + margin-bottom: 0; + background: var(--color-off-white); + padding: .5rem 0; +} + +html[data-theme='dark'] .blog-breadcrumbs { + background-color: rgba(20,20,10,0.75); +} + +.blog-breadcrumbs a { + margin-right: 1.5rem; + position: relative; +} + +.blog-breadcrumbs a[href="#"] { + cursor: initial; + pointer-events: none; +} + +/* darkmode breadcrumbs */ +html[data-theme='dark'] .blog-breadcrumbs a[href="#"] { + filter: brightness(var(--filter-brightness-low)); +} + +html[data-theme='dark'] .blog-breadcrumbs a:not(:last-of-type):after { + color: var(--ifm-link-color); +} + +html[data-theme='dark'] .breadcrumbs__item--active .breadcrumbs__link { + filter: brightness(var(--filter-brightness-high)); +} + +.blog-breadcrumbs a:not(:last-of-type):after { + content: ">"; + color: var(--color-primary-blue); + position: absolute; + right: -15px; + top: 0; + bottom: 0; + margin: auto 0; + width: auto; + font-size: .9rem; + pointer-events: none; +} + +.blog-main-row { + margin: 0; + justify-content: flex-start; + flex-wrap: nowrap; +} + +.blog-main-row .blog-aside { + border-right: 1px solid var(--ifm-toc-border-color); + margin-bottom: 2rem !important; + width: 300px !important; + flex: 1 0 300px; + max-width: 300px; +} + +.blog-main-row .blog-aside li a { + font-size: 1rem; + line-height: 1.25; +} + +/* footer styles */ +.footer { + font-weight: var(--ifm-font-weight-narrow); + font-size: .875rem; + padding-top: var(--ifm-footer-padding-vertical); + padding-bottom: var(--ifm-footer-padding-vertical); +} + +.footer button { + font-size: .875rem !important; +} + +.footer a { + color: var(--ifm-footer-color); + text-decoration: none; +} + +.footer a:hover { + text-decoration: underline; + color: var(--ifm-footer-color); +} + +.footer__links { + margin-bottom: 0; +} + +.footer__link-item { + color: var(--ifm-footer-color); + display: flex; + justify-content: space-between; +} + +.footer__items { + list-style: none; + margin-bottom: 1em; + padding-left: 0; + gap: 1.5em; + display: flex; +} + +/* social media icons in footer */ +.footer__items--right { + display: flex; + gap: 1.5em; +} + +/* fontawesome icons in footer */ +.footer .fa-brands { + color: var(--color-footer-accent); + font-size: 1.6rem; + transition: all .3s ease-in-out; +} + +.footer .fa-brands:hover { +filter: opacity(.75); +} + +/* copyright */ +.footer__bottom { + text-align: left; + color: var(--color-footer-accent); + font-size: .875rem; +} + +.footer__copyright { + margin-top: .5em; +} + +@media (min-width: 997px) and (max-width: 1045px) { + .navbar__link.nav-versioning { + transition: all .3s ease-in-out; + } +} + +@media (min-width: 997px) and (max-width: 1729px) { + .container > .row .col { + padding-left: 2.5rem; + } + /* for non row divs like on /category/adapter-development */ + .container > div:not(.row) { + padding-left: 2.5rem; + } +} + +/* Begin @Media Queries */ @media (min-width: 997px) and (max-width: 1150px) { nav.navbar a.navbar__link { - font-size: 0.9rem; + font-size: 0.875rem; } + .navbar__search .navbar__search-input { max-width: 160px; } } -@media screen and (max-width: 700px) { +@media (max-width: 910px) { + .footer__items { + flex-direction: column; + align-items: flex-start; + } +} + +@media (max-width: 996px) { + .navbar-sidebar__brand .navbarSidebarToggle_node_modules-\@docusaurus-theme-classic-lib-next-theme-Navbar-styles-module { + margin-right: 0; + margin-left: .25em; + } + + .navbar-sidebar__brand > div:first-of-type { + order: 1; + margin-right: 0; + } + + .footer__link-item { + flex-direction: column; + } + + .footer__copyright { + margin-top: 1em; + } +} + +@media screen and (max-width: 750px) { .card.large { height: auto; text-align: center; } + .container.container--fluid.home .row { margin: calc(2vh) auto !important; } } -/* V2.0.0-beta.6 style updates */ -.padding-top--md { - padding-top: 2rem !important; +@media screen and (max-width: 1199px) { + button.DocSearch-Button { + background: var(--ifm-color-gray-100); + } + + [data-theme='dark'] button.DocSearch-Button { + background-color: #ffffff20; + } + + .DocSearch-Button .DocSearch-Search-Icon { + color: var(--docsearch-muted-color); + } + + /* hide search text and keys until 1201px */ + button .DocSearch-Button-Placeholder, + button .DocSearch-Button-Keys { + display: none; + } } -code { - border: none; - background-color: var(--ifm-color-emphasis-200); - color: var(--ifm-color-emphasis-900); +@media screen and (min-width: 1200px) { + /* search bar styles */ + button.DocSearch-Button { + border: 1px solid #95a0b1; + border-radius: 5px; + height: 35px; + } + + button.DocSearch-Button:active, + button.DocSearch-Button:focus, + button.DocSearch-Button:hover { + color: var(--docsearch-muted-color); + background: white; + box-shadow: var(--docsearch-searchbox-shadow); + border: 1px solid var(--ifm-link-color); + } + + button .DocSearch-Button-Placeholder { + font-size: .875rem; + font-weight: 600; + padding: 0 12px 0 8px; + } + + /* magnifying glass icon */ + button.DocSearch-Button .DocSearch-Search-Icon { + color: var(--docsearch-muted-color); + stroke-width: 2px; + width: 1em; + height: 1em; + } + + /* keys wrapper */ + button .DocSearch-Button-Keys { + border: 1px solid var(--docsearch-muted-color-for-keys); + border-radius: 5px; + padding: 0.24em 0.5em; + gap: 0.1em; + } + + /* single key */ + button .DocSearch-Button-Key { + font-size: 1.25rem; + margin-right: 0; + padding: 4px 4px 2px; + } } -.DocSearch-Button-Container .DocSearch-Button-Placeholder { - padding: 0 2.25rem 0 0; +@media (min-width: 1440px) { + .container--fluid { + max-width: inherit; + } + + html.docs-version-current .navbar__brand { + background-color: var(--ifm-background-color); + border-right: 1px solid var(--ifm-toc-border-color); + } + + button.DocSearch-Button { + min-width: 175px; + } + } -.alert { - color: var(--ifm-alert-color); +@media (min-width: 997px) { + html.docs-version-current .navbar__brand { + padding: 0 var(--ifm-navbar-padding-horizontal) 0 0; + min-height: var(--ifm-navbar-height); + max-height: var(--ifm-navbar-height); + width: 300px; + min-width: 5.5em; } -.alert a { - color: var(--ifm-alert-color); - text-decoration: underline; - text-decoration-color: #fff !important; + html.docs-version-current .navbar { + width: 100%; + margin-left: 0; + } + + .navbar { + padding: 0 var(--ifm-navbar-padding-horizontal) 0 0; + } + + html.docs-version-current aside html.docs-version-current .sidebar_node_modules-\@docusaurus-theme-classic-lib-next-theme-DocSidebar-styles-module { + position: relative; + } + + aside .menu { + padding-left: 1.25rem; + padding-right: 1.25rem; + } + + .navbar__item { + padding: var(--ifm-navbar-item-padding-vertical) 0; } -.admonition-icon svg { - fill: #fff; - stroke: #fff; + .navbar__item.navbar__link { + display: flex; + align-self: stretch; + } + + .navbar__items.navbar__items--right > div:nth-of-type(3) { + order: 1; + } + + .navbar__items--right > :last-child { + padding: var(--ifm-navbar-item-padding-vertical) 1em var(--ifm-navbar-item-padding-vertical) .5em; + } + + .blog-main-row > main { + width: 100%; + flex-grow: 1; + max-width: calc(100% - var(--doc-sidebar-width)); + } + + .table-of-contents::before { + content: 'CONTENTS'; + margin-left: 0.5rem; + color: var(--color-nav-sub-level-text); + font-size: .875rem; + font-weight: var(--ifm-font-weight-semibold); + } + + [data-theme='dark'] .table-of-contents::before { + color: var(--color-white); + } + + html[data-theme='dark'] .menu-content { + border-right: 1px solid #dadde1; + } + + .docSidebarContainer_src-theme-DocPage-styles-module { + margin-top: calc(-.8 * var(--ifm-navbar-height)) !important; + } } -.alert--info { - --ifm-alert-background-color: var(--ifm-color-info); - --ifm-alert-border-color: var(--ifm-color-info); +.blog-main-row .blog-right-sidebar { + max-width: 400px !important; + margin-top: 2rem; } -.alert--success { - --ifm-alert-background-color: var(--ifm-color-success); - --ifm-alert-border-color: var(--ifm-color-success); + +.blog-list-item { + margin-bottom: 3rem; } -.alert--danger { - --ifm-alert-background-color: var(--ifm-color-danger); - --ifm-alert-border-color: var(--ifm-color-danger); + +.blog-post-page .docItemCol_node_modules-\@docusaurus-theme-classic-lib-next-theme-DocItem-styles-module { + max-width: 70% !important; } -.alert--warning { - --ifm-alert-background-color: var(--ifm-color-warning); - --ifm-alert-border-color: var(--ifm-color-warning); + +@media (max-width: 996px) { + .blog-post-page .container { + margin-top: 0 !important; + } + .blog-main-row .blog-aside { + margin: 0 !important; + display: none; + } + .blog-main-row .blog-right-sidebar { + max-width: initial !important; + } + .blog-post-page .docItemCol_node_modules-\@docusaurus-theme-classic-lib-next-theme-DocItem-styles-module { + max-width: 100% !important; + } } -@media (min-width: 1440px) { - .container--fluid { - max-width: inherit; +.blog-list-page .blog-index-posts-section:not(:last-of-type) { + border-bottom: 1px solid var(--color-off-white); + margin-bottom: 2rem; + padding-bottom: 2rem; +} + +.blog-list-page .blog-index-posts-section h3 a { + color: var(--color-primary-blue); +} + +.blog-list-page .blog-index-posts-flex { + display: flex; + justify-content: space-between; + flex-flow: row wrap; +} +.blog-list-page .blog-index-posts-flex article { + flex: 0 0 100%; + max-width: 100%; + margin: 1rem 0 !important; +} +.blog-list-page .blog-index-posts-flex article h2 { + font-size: 2rem; + line-height: 37.5px; +} +.blog-list-page .blog-index-posts-flex article footer.row .col--9 { + flex: calc(8 / 12 * 100%); + max-width: calc(8 / 12 * 100%); +} +.blog-list-page .blog-index-posts-flex article footer.row .col--3 { + flex: calc(4 / 12 * 100%); + max-width: calc(4 / 12 * 100%); +} +.blogPostTitle_src-theme-BlogPostItem-styles-module > img { + display: none; +} + +@media (min-width: 700px) { + .blog-list-page .blog-index-posts-flex article { + flex: 0 0 49%; + max-width: 49%; + } +} + +.blog-hero { + height: 250px; + background-repeat: no-repeat; + background-size: cover; + background-position: center; +} +@media (min-width: 997px) { + .blog-hero { + height: 500px; + } +} + +.card.large.blog-hero-card:before { + right: 350px; +} +.card.large.blog-hero-card:after { + right: 250px; +} +.blog-hero-card { + background: var(--ifm-footer-background-color); + color: var(--color-white); +} +.blog-hero-card .button { + text-decoration: none; +} +.blog-hero-card-content { + z-index: 2; + max-width: 75%; + text-align: left; +} +@media (max-width: 699px) { + .card.large.blog-hero-card:before, .card.large.blog-hero-card:after { + display: none; + } + .blog-hero-card { + background: var(--color-primary-blue); } + .blog-hero-card-content { + max-width: 100%; + } +} + +.left-sidebar-hidden { + max-width: 100% !important; + width: 100%; +} + +/* Custom Author Styles */ +.author-header { + align-items: center; +} +.author-header-left, .author-header-right { + padding: 20px; +} +.author-header img { + max-width: 100px; + border-radius: 50%; + display: block; + margin: 0 auto; +} +.author-header h1 { + display: block; + margin-bottom: 5px; +} +.author-header .author-title { + display: flex; + align-items: center; + margin-bottom: 10px; +} +.author-header .author-links { + display: flex; + align-items: center; + justify-content: center; +} +.author-header .author-links span { + padding-left: 10px; +} +.author-header .author-links a { + display: block; + padding: 5px; +} +.author-header .author-links a:first-of-type { + padding-left: 10px; +} +.author-header .author-links i { + font-size: 1.1rem; +} +.author-posts-section { + margin-top: 2rem; +} +.author-posts .author-post { + flex: 0 0 100%; + max-width: 100%; + padding: 0 1rem 1rem; +} +.author-posts .author-post img { + max-width: 100%; + width: 100%; + display: block; + margin: 0 auto; +} +.author-posts .author-post h3 { + margin: 10px 0; +} +@media screen and (min-width: 700px) { + .author-posts .author-post { + flex: 0 0 50%; + max-width: 50%; + } +} +@media (min-width: 997px) { + .author-posts .author-post { + flex: 0 0 33%; + max-width: 33%; + } +} + +/* Tag Page Styles */ +.tag-header { + margin: 0 0 var(--ifm-paragraph-margin-bottom); +} + +/* CTA Styles */ +.docs-cta { + padding: 20px 10px; + margin: 1rem; + border-radius: 1rem; + /*position: sticky;*/ + text-align: center; + background: var(--color-off-white); + position:relative; + bottom:0; + max-width: 400px; +} +.docs-cta h4 { + margin-bottom: 10px; +} +.docs-cta p { + font-size: .9rem; + line-height: 21px; +} +.docs-cta .docs-cta-btn { + background: var(--ifm-color-primary); + color: var(--color-white); + border-radius: 5px; + border: none; + text-decoration: none; + padding: 10px 20px; + transition: 100ms all ease-in-out; + white-space: nowrap; +} +.docs-cta .docs-cta-btn:hover { + background: var(--ifm-menu-color-active); +} + +@media (max-width: 996px) { + .docs-cta { + display:none; + } +} + +.mobile-toc-section { + display: none; +} +.mobile-toc-section .mobile-toc-container { + padding: 0 var(--ifm-spacing-horizontal); +} + +@media (max-width: 996px) { + .mobile-toc-section { + display: block; + } + .mobile-toc-section .tableOfContents_node_modules-\@docusaurus-theme-classic-lib-next-theme-TOC-styles-module { + display: none; + } + .mobile-toc-section .tableOfContents_node_modules-\@docusaurus-theme-classic-lib-next-theme-TOC-styles-module.tocActive { + display: block; + } + .mobile-toc-section .tableOfContents_node_modules-\@docusaurus-theme-classic-lib-next-theme-TOC-styles-module .table-of-contents__left-border { + border-left: none; + } + #mobile-toc-dropdown button.tocActive:after { + transform: rotate(0deg); + } + #mobile-toc-dropdown { + background-color: var(--ifm-menu-color-background-active); + border-radius: var(--ifm-global-radius); + margin: 1rem 0; + } + #mobile-toc-dropdown > button { + font-size: inherit; + display: flex; + justify-content: space-between; + align-items: center; + padding: 0.4rem 0.8rem; + width: 100%; + } + #mobile-toc-dropdown > button::after { + content: ''; + background: var(--ifm-menu-link-sublist-icon) 50% 50% / 2rem 2rem no-repeat; + filter: var(--ifm-menu-link-sublist-icon-filter); + height: 1.25rem; + width: 1.25rem; + transform: rotate(180deg); + transition: transform var(--ifm-transition-fast); + } + #mobile-toc-dropdown button.tocActive::after { + transform: rotate(0deg); + } + #mobile-toc-dropdown > div.tocActive { + display: block; + } + #mobile-toc-dropdown > div > ul { + border-left: none; + } +} + +.docs-wrapper.docs-doc-page main div.row > article.col--6 { + margin-bottom: 1.5rem; +} + +/* OneTrust Cookies Settings Btn in Footer */ +footer #ot-sdk-btn.ot-sdk-show-settings, +footer #ot-sdk-btn.optanon-show-settings { + background: none; + border: none; + color: var(--ifm-footer-color); + text-decoration: none; + font-weight: var(--ifm-font-weight-bold); + font-family: var(--ifm-font-family-base); + padding: 0; + line-height: inherit; + font-size: 1.125rem; + font-weight: 400; + cursor: pointer; +} +footer #ot-sdk-btn.ot-sdk-show-settings:hover, +footer #ot-sdk-btn.optanon-show-settings:hover{ + background: none; + border: none; + color: var(--ifm-footer-color); + text-decoration: underline; +} + +/* Discourse Forum & Events Page */ +.events-page section, section.discourse-forum-page { + padding: 4rem 0; } diff --git a/website/src/pages/events.js b/website/src/pages/events.js new file mode 100644 index 00000000000..8002daf0301 --- /dev/null +++ b/website/src/pages/events.js @@ -0,0 +1,27 @@ + +import React from 'react'; +import Layout from '@theme/Layout'; +import Head from '@docusaurus/Head'; +import EventsFeed from '@site/src/components/events'; + + +function Events() { + return ( + + + dbt Community Events + + +
+
+

Upcoming dbt Community Events

+

Join us for upcoming meetups, conferences, or office hours with the dbt Labs team. Events are online unless explicitly listed as in-person.

+ + +
+
+
+ ); +} + +export default Events; diff --git a/website/src/pages/forum.js b/website/src/pages/forum.js new file mode 100644 index 00000000000..a90e2cc875c --- /dev/null +++ b/website/src/pages/forum.js @@ -0,0 +1,25 @@ +import React from 'react'; +import Layout from '@theme/Layout'; +import Head from '@docusaurus/Head'; +import { DiscourseFeed } from '@site/src/components/discourse'; + +function Events() { + return ( + + + dbt Discourse + + +
+
+

dbt Discourse

+ + + +
+
+
+ ); +} + +export default Events; diff --git a/website/src/pages/index.js b/website/src/pages/index.js index 5215207c362..df3446b9971 100644 --- a/website/src/pages/index.js +++ b/website/src/pages/index.js @@ -10,7 +10,7 @@ import Head from '@docusaurus/Head'; const bannerAnimation = require('@site/static/img/banner-white.svg'); function getBanner() { - return {__html: bannerAnimation}; + return { __html: bannerAnimation }; }; function Home() { @@ -23,261 +23,261 @@ function Home() { -
-
-
-

Get started

-

If you’re new to dbt, start here. These resources will get you off to a strong start:

-
-
-
-
-
-
-

What is dbt?

-
-
-

- Some of the very first questions a new user has are covered in this introduction. -

-
-
- - Learn More - -
-
-
-
-
-
-

Getting Started Tutorial

-
-
-

- Follow along with this tutorial to learn how to build, test, and deploy a new dbt project. -

-
-
- - Watch Tutorial - -
-
-
-
-
-
-

dbt Learn

-
-
-

- Learn dbt on your own time with our on demand course or sign up for an upcoming, live public course. -

-
-
- - Learn Now - -
-
-
+
+
+
+

Get started

+

If you’re new to dbt™, start here. These resources will get you off to a strong start:

+
+
+
+
+
+
+

What is dbt?

+
+
+

+ Some of the very first questions a new user has are covered in this introduction. +

+
+
+ + Learn More + +
+
+
+
+
+
+

Getting started guide

+
+
+

+ Read this guide to learn how to build, test, and deploy a new dbt project. +

+
+
+ + Learn More + +
+
+
+
+
+
+

dbt Learn

+
+
+

+ Learn dbt on your own time with our on demand course or sign up for an upcoming, live public course. +

+
+
+ + Learn Now + +
+
+
+
+
+
+
+
+

Build your project

+

If you’re getting comfortable with dbt, bookmark these resources! They’ll help you level up quickly.

+
+
+
+
+
+
+

Docs

+
+
+

+ The core concepts of dbt, from models, to sources, to tests. +

+
+
+ + Read Up + +
+
+
+
+
+

Reference

+
+
+

+ The technical reference for dbt configurations. You’ll need to know the basics of dbt before using this section. +

+
+
+ + Browse Reference + +
+
+
+
+
+
+

FAQs

+
+
+

+ Commonly asked questions about dbt. +

+
+
+ + Get Answers + +
+
+
+
+
+
+

If you’re a dbt Cloud™ user, these resources may also be helpful:

+
-
-
-
-

Build your project

-

If you’re getting comfortable with dbt, bookmark these resources! They’ll help you level up quickly.

-
-
-
-
-
-
-

Docs

-
-
-

- The core concepts of dbt, from models, to sources, to tests. -

-
-
- - Read Up - -
-
-
-
-
-
-

Reference

-
-
-

- The technical reference for dbt configurations. You’ll need to know the basics of dbt before using this section. -

-
-
- - Browse Reference - -
-
-
-
-
-
-

FAQs

-
-
-

- Commonly asked questions about dbt. -

-
-
- - Get Answers - -
-
-
+
+
+
+
+

dbt Cloud guides

+
+
+

+ Guides to help you set up your dbt project in dbt Cloud +

+
+
+ + Cloud Overview + +
-
-
-

If you’re a dbt Cloud user, these resources may also be helpful:

-
-
-
-
-
-
-

dbt Cloud guides

-
-
-

- Guides to help you set up your dbt project in dbt Cloud -

-
-
- - Cloud Overview - -
-
-
-
-
-
-

dbt Cloud API

-
-
-

- Technical reference docs for using the dbt Cloud APIs. -

-
-
- - API docs - -
-
-
+
+
+
+
+

dbt Cloud API

+
+
+

+ Technical reference docs for using the dbt Cloud APIs. +

+
+
+ + API docs + +
+
-
-
-
-

Learn from the community

-

Every data team uses dbt to solve different analytics engineering problems. It can be useful to learn how other teams are using dbt with the following resources:

-
-
-
-
-
-
-

Discourse

-
-
-

- Common use cases and helpful articles from the community have been published here -

-
-
- - Get Advice - -
-
-
-
-
-
-

Slack

-
-
-

- Where the dbt community hangs out, discusses issues, and troubleshoots problems together -

-
-
- - Join us on Slack - -
-
-
-
-
-
-

Example projects

-
-
-

- A list of some dbt projects in the wild -

-
-
- - View Projects - -
-
-
+
+
+
+
+

Learn from the community

+

Every data team uses dbt to solve different analytics engineering problems. It can be useful to learn how other teams are using dbt with the following resources:

+
+
+
+
+
+
+

Discourse

+
+
+

+ Common use cases and helpful articles from the community have been published here +

+
+
+ + Get Advice + +
+
+
+
+
+
+

Slack

+
+
+

+ Where the dbt community hangs out, discusses issues, and troubleshoots problems together +

+
+
+ + Join us on Slack + +
+
+
+
+
+
+

Example projects

+
+
+

+ A list of some dbt projects in the wild +

+
+
+ + View Projects + +
+
-
-
-
-

Having trouble?

-

If you're having trouble, check out our guide on Getting Help for information on getting support and asking questions in the community.

-
-
+
+
+
+
+

Having trouble?

+

If you're having trouble, check out our guide on Getting Help for information on getting support and asking questions in the community.

+
-
+
+
); diff --git a/website/src/pages/styles.js b/website/src/pages/styles.js index 4ac31ad37f9..22a53de5b1f 100644 --- a/website/src/pages/styles.js +++ b/website/src/pages/styles.js @@ -11,6 +11,7 @@ import CodeBlock from '@theme/CodeBlock'; import Changelog from '@site/src/components/changelog'; import CloudCore from '@site/src/components/cloudcore'; +import WHCode from '@site/src/components/whcode'; import Collapsible from '@site/src/components/collapsible'; import FAQList from '@site/src/components/faqList'; import FAQ from '@site/src/components/faqs'; @@ -104,9 +105,9 @@ description: "this is \[an escaped link](docs.getdbt.com)"

FAQ

-
{``}
- - +
{``}
+ +
@@ -129,8 +130,8 @@ password: hunter2

Lightbox

-
{``}
- +
{``}
+
@@ -142,7 +143,7 @@ Links to pages can be specified using:
Bad links will appear with red underlines when building locally, and will cause an error in a deploy preview.
-
{`[link to unique id](available-adapters)
+
{`[Supported Data Platforms](supported-data-platforms)
 [disambiguated link to duplicate id](docs/about/overview)
 [second disambiguated link to duplicate id](dbt-cli/install/overview)
 [file paths work too](docs/about/overview.md)
@@ -150,7 +151,7 @@ Bad links will appear with red underlines when building locally, and will cause
 [a bad link](bad-link)
 `}
- link to unique id + link to unique id
disambiguated link to duplicate id
diff --git a/website/src/stores/VersionContext.js b/website/src/stores/VersionContext.js new file mode 100644 index 00000000000..b84b7d7a05b --- /dev/null +++ b/website/src/stores/VersionContext.js @@ -0,0 +1,78 @@ +import React, { useState, useEffect, createContext } from "react" +import { versions } from '../../dbt-versions' + +const lastReleasedVersion = versions && versions.find(ver => ver.version && ver.version != "" && !ver.isPrerelease); + +const VersionContext = createContext({ + version: lastReleasedVersion.version, + EOLDate: lastReleasedVersion.EOLDate || undefined, + isPrerelease: lastReleasedVersion.isPrerelease || false, + latestStableRelease: lastReleasedVersion.version, + updateVersion: () => {}, +}) + +export const VersionContextProvider = ({ value = "", children }) => { + + const [version, setVersion] = useState(value) + + useEffect(() => { + const storageVersion = window.localStorage.getItem('dbtVersion') + const { search } = window.location + const urlParams = new URLSearchParams(search); + const versionParam = urlParams.get('version') + + if(versionParam && versions.find(ver => ver?.version && ver.version === versionParam)) { + {/* + * Check if version param exists in url, + * and is in current versions array + * If true, set version to param value + */} + setVersion(versionParam) + window.localStorage.setItem('dbtVersion', versionParam) + } else { + {/* + * If localStorage version exists, set version to LS value + * Otherwise set version to latest version + */} + if(storageVersion && versions.find(ver => ver?.version && ver.version === storageVersion)) { + setVersion(storageVersion) + } else { + setVersion(lastReleasedVersion.version) + window.localStorage.setItem('dbtVersion', lastReleasedVersion.version) + } + } + }, []) + + const updateVersion = (e) => { + if(!e.target) + return + + const versionValue = e.target.text.replace('v', '') + versionValue && + setVersion(versionValue) + window.localStorage.setItem('dbtVersion', versionValue) + } + + let context = { + version, + updateVersion + } + + // Determine isPrerelease status + End of Life date for current version + const currentVersion = versions.find(ver => ver.version === version) + if(currentVersion) + context.EOLDate = currentVersion.EOLDate + context.isPrerelease = currentVersion?.isPrerelease + + // Get latest stable release + const latestStableRelease = versions.find(ver => !ver?.isPrerelease) + context.latestStableRelease = latestStableRelease.version + + return ( + + { children } + + ) +} + +export default VersionContext diff --git a/website/src/theme/AnnouncementBar/index.js b/website/src/theme/AnnouncementBar/index.js new file mode 100644 index 00000000000..f82645c9b1c --- /dev/null +++ b/website/src/theme/AnnouncementBar/index.js @@ -0,0 +1,76 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ +import React from 'react'; +import clsx from 'clsx'; +import {useThemeConfig, useAnnouncementBar} from '@docusaurus/theme-common'; +import {translate} from '@docusaurus/Translate'; +import IconClose from '@theme/IconClose'; +import styles from './styles.module.css'; +export default function AnnouncementBar() { + const {isActive, close} = useAnnouncementBar(); + const {announcementBar, announcementBarActive, announcementBarLink} = useThemeConfig(); + + if (!isActive || !announcementBarActive) { + return null; + } + + const {content, backgroundColor, textColor, isCloseable} = announcementBar; + + return ( +
+ {isCloseable &&
} + {announcementBarLink ? ( + + + + ) : ( + + )} + + {isCloseable ? ( + + ) : null} +
+ ); +} + +function AnnouncementBarContent({ content, styles }) { + return ( +
+ ) +} diff --git a/website/src/theme/AnnouncementBar/styles.module.css b/website/src/theme/AnnouncementBar/styles.module.css new file mode 100644 index 00000000000..e76f981dfbb --- /dev/null +++ b/website/src/theme/AnnouncementBar/styles.module.css @@ -0,0 +1,67 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +:root { + --docusaurus-announcement-bar-height: auto; +} + +.announcementBar { + display: flex; + align-items: center; + height: auto; +} + +html[data-announcement-bar-initially-dismissed='true'] .announcementBar { + display: none; +} + +.announcementBarPlaceholder { + flex: 0 0 10px; +} + +.announcementBarClose { + flex: 0 0 30px; + align-self: stretch; + padding: 0; + line-height: 0; + color: var(--ifm-color-white); + opacity: 1; +} + +.announcementBarContent { + flex: 1 1 auto; + font-size: 1.125rem; + text-align: center; + padding: 15px 0; +} + +@media print { + .announcementBar { + display: none; + } +} + +.announcementBarContent a { + color: inherit; + text-decoration: underline; +} + +@media (min-width: 997px) { + .announcementBarPlaceholder, + .announcementBarClose { + flex-basis: 50px; + } +} + +.announcementBarLink { + color: var(--ifm-color-white); + width: 100%; +} +.announcementBarLink:hover { + color: var(--ifm-color-white); + text-decoration: none; +} diff --git a/website/src/theme/BlogLayout/index.js b/website/src/theme/BlogLayout/index.js new file mode 100644 index 00000000000..5905a60f6fe --- /dev/null +++ b/website/src/theme/BlogLayout/index.js @@ -0,0 +1,193 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + import React from 'react'; + import clsx from 'clsx'; + import Layout from '@theme/Layout'; + import BlogSidebar from '@theme/BlogSidebar'; + import TOC from '@theme/TOC'; + + // dbt Custom + import Head from '@docusaurus/Head'; + import Link from '@docusaurus/Link'; + import {usePluginData} from '@docusaurus/useGlobalData'; + + function BlogLayout(props) { + const {title, description, blogPageTitle, sidebar, toc, children, ...layoutProps} = props; + + // dbt Custom + const { blogMeta, tagData } = usePluginData('docusaurus-build-global-data-plugin'); + const { + featured_image, + featured_cta, + show_title, + show_description, + hero_button_url, + hero_button_text, + hero_button_new_tab, + show_left_sidebar + } = blogMeta + + const hasSidebar = layoutProps.pageClassName === "blog-post-page" + ? show_left_sidebar && (sidebar && sidebar.items.length > 0) + : sidebar && sidebar.items.length > 0 + + // The pageTitle variable sets the final item in breadcrumbs + let breadcrumbTitle = undefined + if(blogPageTitle) { + // Set to blogPageTitle prop + breadcrumbTitle = blogPageTitle + } else if(title) { + // Set to title prop + breadcrumbTitle = title + } else if (layoutProps.pageClassName === "blog-post-page") { + // Set to blog post title + const { props: { frontMatter }} = children.find(child => child.props.frontMatter) + breadcrumbTitle = frontMatter.title + } + + const metaTitle = layoutProps.pageClassName !== "blog-list-page" + ? `${breadcrumbTitle} | dbt Developer Blog` + : breadcrumbTitle + + return ( + + + {/* Set Custom Metadata */} + {featured_image && featured_image !== "" && + + + + + } + + {metaTitle && + + {metaTitle} + + + } + + {description && + + + + + } + {/* End Custom Metadata */} + + {featured_image && featured_image !== "" && + +
+ + } + + {layoutProps.pageClassName && layoutProps.pageClassName === "blog-list-page" && + ((show_title || show_description) && (title || description)) && ( +
+
+
+
+ {title && show_title &&

{title}

} + {description && show_description &&

{description}

} + {blogMeta.test} + {(hero_button_text !== "" && hero_button_text !== "") && ( + hero_button_new_tab ? ( + {hero_button_text} + ) : ( + {hero_button_text} + ) + )} +
+
+
+
+ ) + } + +
+
+ dbt Docs + Developer Blog + {(layoutProps.pageClassName !== "blog-list-page" && breadcrumbTitle) && + + {breadcrumbTitle} + + } +
+
+ +
+ {toc && ( +
+
+ + +
+
+ )} +
+ +
+ {hasSidebar && ( + + )} +
+
+
+
+ {children} +
+ {layoutProps.pageClassName && +
+ {toc && ( + + )} +
+ } +
+
+
+
+
+ ); + } + + // Show or hide table of contents for mobile + function handleTocClick(e) { + const tocButton = document.querySelector('#mobile-toc-dropdown > button') + const toc = document.querySelector('#mobile-toc-dropdown > div') + + if(toc.classList.contains('tocActive')) { + toc.classList.remove('tocActive') + tocButton.classList.remove('tocActive') + } else { + toc.classList.add('tocActive') + tocButton.classList.add('tocActive') + } + } + + export default BlogLayout; + \ No newline at end of file diff --git a/website/src/theme/BlogListPage/index.js b/website/src/theme/BlogListPage/index.js new file mode 100644 index 00000000000..627f08abdbf --- /dev/null +++ b/website/src/theme/BlogListPage/index.js @@ -0,0 +1,115 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ +import React from 'react'; +import Link from '@docusaurus/Link'; +import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; +import BlogLayout from '@theme/BlogLayout'; +import BlogPostItem from '@theme/BlogPostItem'; +import BlogListPaginator from '@theme/BlogListPaginator'; +import {ThemeClassNames} from '@docusaurus/theme-common'; +import {usePluginData} from '@docusaurus/useGlobalData'; + +function BlogListPage(props) { + const {metadata, items, sidebar} = props; + const { + siteConfig: {title: siteTitle}, + } = useDocusaurusContext(); + const {blogDescription, blogTitle, permalink} = metadata; + const isBlogOnlyMode = permalink === '/'; + const title = isBlogOnlyMode ? siteTitle : blogTitle; + + // dbt Custom + const { + blogMeta, + tagData + } = usePluginData('docusaurus-build-global-data-plugin'); + const { + featured_posts_count, + regular_posts_count + } = blogMeta + + // Sort posts by date then title + const handlePostsSort = (a, b) => { + const { date: a_date, title: a_title } = a.content.frontMatter + const { date: b_date, title: b_title } = b.content.frontMatter + return b_date - a_date || a_title.localeCompare(b_title) + } + + // Set Featured Posts + const featuredPosts = items + .filter(post => post.content.frontMatter.is_featured) + .slice(0, featured_posts_count ? featured_posts_count : 2) + + // Get all non-featured posts + let allOtherPosts = items + .filter(post => !post.content.frontMatter.is_featured) + + // Get all featured posts + // which aren't included in featured posts section + const allOtherFeaturedPosts = items + .filter(post => post.content.frontMatter.is_featured) + .slice(featured_posts_count ? featured_posts_count : 2) + + // Group together all posts not featured + allOtherPosts = allOtherPosts.concat(allOtherFeaturedPosts) + + return ( + + + {/* Featured Posts */} +
+

Featured Posts

+
+ {featuredPosts + .sort(handlePostsSort) + .map(({content: BlogPostContent}) => ( + + + + ))} +
+
+ +
+

Recent Posts

+
+ {allOtherPosts + .sort(handlePostsSort) + .slice(0, regular_posts_count ? regular_posts_count : 15) + .map(({content: BlogPostContent}) => ( + + + + ))} +
+
+ + {/* */} +
+ ); +} + +export default BlogListPage; diff --git a/website/src/theme/BlogPostAuthor/index.js b/website/src/theme/BlogPostAuthor/index.js new file mode 100644 index 00000000000..ccdeeb56314 --- /dev/null +++ b/website/src/theme/BlogPostAuthor/index.js @@ -0,0 +1,46 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ +import React from 'react'; +import Link from '@docusaurus/Link'; +import styles from './styles.module.css'; + +function BlogPostAuthor({author}) { + const {name, job_title, organization, url, imageURL, key} = author; + return ( +
+ {imageURL && ( + + {name} + + )} + + { + // Note: only legacy author frontmatter allow empty name (not frontMatter.authors) + name && ( + + ) + } +
+ ); +} + +export default BlogPostAuthor; diff --git a/website/src/theme/BlogPostAuthor/styles.module.css b/website/src/theme/BlogPostAuthor/styles.module.css new file mode 100644 index 00000000000..aae60add2db --- /dev/null +++ b/website/src/theme/BlogPostAuthor/styles.module.css @@ -0,0 +1,12 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +.image { + width: 100%; + height: 100%; + object-fit: cover; +} diff --git a/website/src/theme/BlogPostItem/index.js b/website/src/theme/BlogPostItem/index.js new file mode 100644 index 00000000000..9e93d67efe3 --- /dev/null +++ b/website/src/theme/BlogPostItem/index.js @@ -0,0 +1,173 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +/** + * Swizzled on 10-15-21 + * + * Custom dbtLabs Changes: + * - Add image above title for blog posts + */ + +import React from 'react'; +import clsx from 'clsx'; +import {MDXProvider} from '@mdx-js/react'; +import Translate, {translate} from '@docusaurus/Translate'; +import Head from '@docusaurus/Head'; +import Link from '@docusaurus/Link'; +import {useBaseUrlUtils} from '@docusaurus/useBaseUrl'; +import {usePluralForm} from '@docusaurus/theme-common'; +import MDXComponents from '@theme/MDXComponents'; +import EditThisPage from '@theme/EditThisPage'; +import styles from './styles.module.css'; +import TagsListInline from '@theme/TagsListInline'; +import BlogPostAuthors from '@theme/BlogPostAuthors'; // Very simple pluralization: probably good enough for now + +function useReadingTimePlural() { + const {selectMessage} = usePluralForm(); + return (readingTimeFloat) => { + const readingTime = Math.ceil(readingTimeFloat); + return selectMessage( + readingTime, + translate( + { + id: 'theme.blog.post.readingTime.plurals', + description: + 'Pluralized label for "{readingTime} min read". Use as much plural forms (separated by "|") as your language support (see https://www.unicode.org/cldr/cldr-aux/charts/34/supplemental/language_plural_rules.html)', + message: 'One min read|{readingTime} min read', + }, + { + readingTime, + }, + ), + ); + }; +} + +function BlogPostItem(props) { + const readingTimePlural = useReadingTimePlural(); + const {withBaseUrl} = useBaseUrlUtils(); + const { + children, + frontMatter, + assets, + metadata, + truncated, + isBlogPostPage = false, + } = props; + const { + date, + formattedDate, + permalink, + tags, + readingTime, + title, + editUrl, + authors, + } = metadata; + const image = assets.image ?? frontMatter.image ?? '/img/avatar.png'; + + const renderPostHeader = () => { + const TitleHeading = isBlogPostPage ? 'h1' : 'h2'; + return ( +
+ + + {isBlogPostPage ? ( + title + ) : ( + + {title} + + )} + +
+ + + {typeof readingTime !== 'undefined' && ( + <> + {' · '} + {readingTimePlural(readingTime)} + + )} +
+ +
+ ); + }; + + return ( + <> + {frontMatter.canonical_url && ( + + + + )} +
+ {renderPostHeader()} + + {image && ( + + )} + +
+ {children} +
+ + {(tags.length > 0 || truncated) && ( +
+ {tags.length > 0 && ( +
+ +
+ )} + + {isBlogPostPage && editUrl && ( +
+ +
+ )} + + {!isBlogPostPage && truncated && ( +
+ + + + Read More + + + +
+ )} +
+ )} +
+ + ); +} + +export default BlogPostItem; diff --git a/website/src/theme/BlogPostItem/styles.module.css b/website/src/theme/BlogPostItem/styles.module.css new file mode 100644 index 00000000000..1acc4921d9d --- /dev/null +++ b/website/src/theme/BlogPostItem/styles.module.css @@ -0,0 +1,14 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +.blogPostData { + font-size: 0.9rem; +} + +.blogPostDetailsFull { + flex-direction: column; +} diff --git a/website/src/theme/BlogPostPage/index.js b/website/src/theme/BlogPostPage/index.js new file mode 100644 index 00000000000..58b7dea63e4 --- /dev/null +++ b/website/src/theme/BlogPostPage/index.js @@ -0,0 +1,88 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + import React from 'react'; + import Seo from '@theme/Seo'; + import Head from '@docusaurus/Head'; + import BlogLayout from '@theme/BlogLayout'; + import BlogPostItem from '@theme/BlogPostItem'; + import BlogPostPaginator from '@theme/BlogPostPaginator'; + import {ThemeClassNames} from '@docusaurus/theme-common'; + + function BlogPostPage(props) { + const {content: BlogPostContents, sidebar} = props; + const {frontMatter, assets, metadata} = BlogPostContents; + const { + title, + description, + nextItem, + prevItem, + date, + tags, + authors, + } = metadata; + const {hide_table_of_contents: hideTableOfContents, keywords} = frontMatter; + const image = assets.image ?? frontMatter.image; + return ( + + + + + + {/* TODO double check those article metas array syntaxes, see https://ogp.me/#array */} + {authors.some((author) => author.url) && ( + author.url) + .filter(Boolean) + .join(',')} + /> + )} + {tags.length > 0 && ( + tag.label).join(',')} + /> + )} + + + {/* dbt Custom */} + + {title} | dbt Developer Blog + + + {/* End dbt Custom */} + + + + + + {(nextItem || prevItem) && ( + + )} + + ); + } + + export default BlogPostPage; diff --git a/website/src/theme/BlogSidebar/index.js b/website/src/theme/BlogSidebar/index.js new file mode 100644 index 00000000000..c68112aa0a1 --- /dev/null +++ b/website/src/theme/BlogSidebar/index.js @@ -0,0 +1,71 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ +import React from 'react'; +import clsx from 'clsx'; +import Link from '@docusaurus/Link'; +import styles from './styles.module.css'; +import {translate} from '@docusaurus/Translate'; + +export default function BlogSidebar({sidebar, tagData}) { + if (sidebar.items.length === 0) { + return null; + } + + return ( + + ); +} diff --git a/website/src/theme/BlogSidebar/styles.module.css b/website/src/theme/BlogSidebar/styles.module.css new file mode 100644 index 00000000000..5c64cc008ef --- /dev/null +++ b/website/src/theme/BlogSidebar/styles.module.css @@ -0,0 +1,45 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +.sidebar { + max-height: calc(100vh - (var(--ifm-navbar-height) + 2rem)); + overflow-y: auto; + position: sticky; + top: calc(var(--ifm-navbar-height) + 2rem); + margin-top: 1rem; +} + +.sidebarItemTitle { + font-size: var(--ifm-h4-font-size); + font-weight: var(--ifm-font-weight-bold); +} + +.sidebarItemList { + list-style: none; + font-size: 0.9rem; + padding-left: 0; +} + +.sidebarItem { + margin-top: 0.7rem; +} + +.sidebarItemLink { + color: var(--ifm-font-color-base); +} +.sidebarItemLink:hover { + text-decoration: none; +} +.sidebarItemLinkActive { + color: var(--ifm-color-primary); +} + +@media only screen and (max-width: 996px) { + .sidebar { + display: none; + } +} diff --git a/website/src/theme/BlogTagsPostsPage/index.js b/website/src/theme/BlogTagsPostsPage/index.js new file mode 100644 index 00000000000..efb78485c44 --- /dev/null +++ b/website/src/theme/BlogTagsPostsPage/index.js @@ -0,0 +1,104 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ +import React from 'react'; +import Link from '@docusaurus/Link'; +import BlogLayout from '@theme/BlogLayout'; +import BlogPostItem from '@theme/BlogPostItem'; +import Translate, {translate} from '@docusaurus/Translate'; +import {ThemeClassNames, usePluralForm} from '@docusaurus/theme-common'; // Very simple pluralization: probably good enough for now + +// dbt Custom +import Head from '@docusaurus/Head'; +import {usePluginData} from '@docusaurus/useGlobalData'; + +function useBlogPostsPlural() { + const {selectMessage} = usePluralForm(); + return (count) => + selectMessage( + count, + translate( + { + id: 'theme.blog.post.plurals', + description: + 'Pluralized label for "{count} posts". Use as much plural forms (separated by "|") as your language support (see https://www.unicode.org/cldr/cldr-aux/charts/34/supplemental/language_plural_rules.html)', + message: 'One post|{count} posts', + }, + { + count, + }, + ), + ); +} + +export default function BlogTagsPostsPage(props) { + const {metadata, items, sidebar} = props; + const {allTagsPath, name: tagName, count} = metadata; + const blogPostsPlural = useBlogPostsPlural(); + const title = translate( + { + id: 'theme.blog.tagTitle', + description: 'The title of the page for a blog tag', + message: '{nPosts} tagged with "{tagName}"', + }, + { + nPosts: blogPostsPlural(count), + tagName, + }, + ); + + // dbt Custom + const { tagData } = usePluginData('docusaurus-build-global-data-plugin'); + const thisTagData = tagData.find(tag => tag.name === tagName) + + return ( + +
+ + {/* dbt Custom */} + {thisTagData ? ( + <> +

{thisTagData.display_title ? thisTagData.display_title : title}

+ + + + +

{thisTagData.description}

+ + ) : ''} + {/* end dbt Custom */} + + + + View All Tags + + +
+ + {items.map(({content: BlogPostContent}) => ( + + + + ))} +
+ ); +} diff --git a/website/src/theme/CodeBlock/README.md b/website/src/theme/CodeBlock/README.md deleted file mode 100644 index 3707b4a5d32..00000000000 --- a/website/src/theme/CodeBlock/README.md +++ /dev/null @@ -1,10 +0,0 @@ - -This is a swizzled CodeBlock component from docusaurus. Please be -careful when modifying this file, and keep the changes as minimal as possible -to maintain forwards compatibility with new docusaurus releases. - -To re-swizzle, run: - -``` -npm run swizzle @docusaurus/theme-classic CodeBlock -``` diff --git a/website/src/theme/CodeBlock/index.js b/website/src/theme/CodeBlock/index.js index 71704f4239f..2a9a9bac488 100644 --- a/website/src/theme/CodeBlock/index.js +++ b/website/src/theme/CodeBlock/index.js @@ -4,98 +4,36 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ -import React, {useEffect, useState, useRef} from 'react'; +import React, {isValidElement, useEffect, useState} from 'react'; import clsx from 'clsx'; import Highlight, {defaultProps} from 'prism-react-renderer'; import copy from 'copy-text-to-clipboard'; -import rangeParser from 'parse-numeric-range'; -import usePrismTheme from '@theme/hooks/usePrismTheme'; import Translate, {translate} from '@docusaurus/Translate'; +import { + useThemeConfig, + parseCodeBlockTitle, + parseLanguage, + parseLines, + ThemeClassNames, + usePrismTheme, +} from '@docusaurus/theme-common'; import styles from './styles.module.css'; -import {useThemeConfig, parseCodeBlockTitle} from '@docusaurus/theme-common'; - -/* D.B. The only code change from the base swizzled component. This - * adds a squashLinks function that condenses markdown links in the - * generated yml tokens into a single Link token - * - * See the usage of squashLinks below - */ -import squashLinks from './inline-link'; - -const HighlightLinesRangeRegex = /{([\d,-]+)}/; -const HighlightLanguages = ['js', 'jsBlock', 'jsx', 'python', 'html']; -// Supported types of highlight comments -const HighlightComments = { - js: { - start: '\\/\\/', - end: '', - }, - jsBlock: { - start: '\\/\\*', - end: '\\*\\/', - }, - jsx: { - start: '\\{\\s*\\/\\*', - end: '\\*\\/\\s*\\}', - }, - python: { - start: '#', - end: '', - }, - html: { - start: '', - }, -}; // Supported highlight directives - -const HighlightDirectives = [ - 'highlight-next-line', - 'highlight-start', - 'highlight-end', -]; - -const getHighlightDirectiveRegex = (languages = HighlightLanguages) => { - // to be more reliable, the opening and closing comment must match - const commentPattern = languages - .map((lang) => { - const {start, end} = HighlightComments[lang]; - return `(?:${start}\\s*(${HighlightDirectives.join('|')})\\s*${end})`; - }) - .join('|'); // white space is allowed, but otherwise it should be on it's own line - - return new RegExp(`^\\s*(?:${commentPattern})\\s*$`); -}; // select comment styles based on language - -const highlightDirectiveRegex = (lang) => { - switch (lang) { - case 'js': - case 'javascript': - case 'ts': - case 'typescript': - return getHighlightDirectiveRegex(['js', 'jsBlock']); - - case 'jsx': - case 'tsx': - return getHighlightDirectiveRegex(['js', 'jsBlock', 'jsx']); - - case 'html': - return getHighlightDirectiveRegex(['js', 'jsBlock', 'html']); - - case 'python': - case 'py': - return getHighlightDirectiveRegex(['python']); - - default: - // all comment types - return getHighlightDirectiveRegex(); - } -}; + /* D.B. The only code change from the base swizzled component. This + * adds a squashLinks function that condenses markdown links in the + * generated yml tokens into a single Link token + * + * See the usage of squashLinks below + */ + import squashLinks from './inline-link'; + +/* pushing comment commit to trigger rebuild, will delete */ export default function CodeBlock({ children, - className: languageClassName, + className: blockClassName = '', metastring, title, + language: languageProp, }) { const {prism} = useThemeConfig(); const [showCopied, setShowCopied] = useState(false); @@ -107,78 +45,50 @@ export default function CodeBlock({ // the flash will require changing the theming approach and is not worth it // at this point. + useEffect(() => { setMounted(true); - }, []); // TODO: the title is provided by MDX as props automatically - // so we probably don't need to parse the metastring - // (note: title="xyz" => title prop still has the quotes) + }, []); // We still parse the metastring in case we want to support more syntax in the + // future. Note that MDX doesn't strip quotes when parsing metastring: + // "title=\"xyz\"" => title: "\"xyz\"" const codeBlockTitle = parseCodeBlockTitle(metastring) || title; - const button = useRef(null); - let highlightLines = []; - const prismTheme = usePrismTheme(); // In case interleaved Markdown (e.g. when using CodeBlock as standalone component). + const prismTheme = usePrismTheme(); //
 tags in markdown map to CodeBlocks and they may contain JSX children.
+  // When the children is not a simple string, we just return a styled block
+  // without actually highlighting.
+
+  if (React.Children.toArray(children).some((el) => isValidElement(el))) {
+    return (
+      
+        {({className, style}) => (
+          
+            {children}
+          
+ )} +
+ ); + } // The children is now guaranteed to be one/more plain strings const content = Array.isArray(children) ? children.join('') : children; - - if (metastring && HighlightLinesRangeRegex.test(metastring)) { - // Tested above - const highlightLinesRange = metastring.match(HighlightLinesRangeRegex)[1]; - highlightLines = rangeParser(highlightLinesRange).filter((n) => n > 0); - } - - let language = languageClassName?.replace(/language-/, ''); - - if (!language && prism.defaultLanguage) { - language = prism.defaultLanguage; - } // only declaration OR directive highlight can be used for a block - - let code = content.replace(/\n$/, ''); - - if (highlightLines.length === 0 && language !== undefined) { - let range = ''; - const directiveRegex = highlightDirectiveRegex(language); // go through line by line - - const lines = content.replace(/\n$/, '').split('\n'); - let blockStart; // loop through lines - - for (let index = 0; index < lines.length; ) { - const line = lines[index]; // adjust for 0-index - - const lineNumber = index + 1; - const match = line.match(directiveRegex); - - if (match !== null) { - const directive = match - .slice(1) - .reduce((final, item) => final || item, undefined); - - switch (directive) { - case 'highlight-next-line': - range += `${lineNumber},`; - break; - - case 'highlight-start': - blockStart = lineNumber; - break; - - case 'highlight-end': - range += `${blockStart}-${lineNumber - 1},`; - break; - - default: - break; - } - - lines.splice(index, 1); - } else { - // lines without directives are unchanged - index += 1; - } - } - - highlightLines = rangeParser(range); - code = lines.join('\n'); - } + const language = + languageProp ?? parseLanguage(blockClassName) ?? prism.defaultLanguage; + const {highlightLines, code} = parseLines(content, metastring, language); const handleCopyCode = () => { copy(code); @@ -192,9 +102,18 @@ export default function CodeBlock({ key={String(mounted)} theme={prismTheme} code={code} - language={language}> + language={language ?? 'text'}> {({className, style, tokens, getLineProps, getTokenProps}) => ( -
+
{codeBlockTitle && (
{codeBlockTitle} @@ -208,8 +127,8 @@ export default function CodeBlock({ style={style}> {tokens.map((line, i) => { - if (line.length === 1 && line[0].content === '') { - line[0].content = '\n'; // eslint-disable-line no-param-reassign + if (line.length === 1 && line[0].content === '\n') { + line[0].content = ''; } const lineProps = getLineProps({ @@ -217,23 +136,23 @@ export default function CodeBlock({ key: i, }); - if (highlightLines.includes(i + 1)) { + if (highlightLines.includes(i)) { lineProps.className += ' docusaurus-highlight-code-line'; } return ( - {squashLinks(line).map((token, key) => ( - - ))} - + {squashLinks(line).map((token, key) => ( + + ))} +
+
); })}
+ + + + + + ); +} + +function DocSidebarItemLink({item, onItemClick, activePath, level, ...props}) { + const {href, label, className} = item; + const isActive = isActiveSidebarItem(item, activePath); + return ( +
  • + onItemClick(item) : undefined, + })} + {...props}> + {isInternalUrl(href) ? ( + label + ) : ( + + {label} + + + )} + +
  • + ); +} diff --git a/website/src/theme/DocSidebarItem/styles.module.css b/website/src/theme/DocSidebarItem/styles.module.css new file mode 100644 index 00000000000..2fcd42e59fe --- /dev/null +++ b/website/src/theme/DocSidebarItem/styles.module.css @@ -0,0 +1,19 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +@media (min-width: 997px) { + .menuLinkText { + cursor: initial; + } + .menuLinkText:hover { + background: none; + } + + .menuLinkText.hasHref { + cursor: pointer; + } +} diff --git a/website/src/theme/MDXComponents/index.js b/website/src/theme/MDXComponents/index.js old mode 100755 new mode 100644 index bca05ce27f1..2fe4c79a228 --- a/website/src/theme/MDXComponents/index.js +++ b/website/src/theme/MDXComponents/index.js @@ -1,22 +1,25 @@ /** - * Copyright (c) 2017-present, Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ - -import React from 'react'; +import React, { isValidElement } from 'react'; +import Head from '@docusaurus/Head'; import CodeBlock from '@theme/CodeBlock'; import Heading from '@theme/Heading'; -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; -import styles from './styles.module.css'; +import Details from '@theme/Details'; +import './styles.css'; // MDX elements are wrapped through the MDX pragma. In some cases (notably usage +// with Head/Helmet) we need to unwrap those elements. /* * docs.getdbt.com additions: */ +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem' import Changelog from '@site/src/components/changelog'; import CloudCore from '@site/src/components/cloudcore'; +import WHCode from '@site/src/components/whcode'; import Collapsible from '@site/src/components/collapsible'; import FAQ from '@site/src/components/faqs'; import FAQList from '@site/src/components/faqList'; @@ -24,25 +27,78 @@ import File from '@site/src/components/file'; import Lightbox from '@site/src/components/lightbox'; import Link from '@site/src/components/link'; import LoomVideo from '@site/src/components/loom'; +import Snippet from '@site/src/components/snippet'; import YoutubeVideo from '@site/src/components/youtube'; import WistiaVideo from '@site/src/components/wistia'; +import VersionBlock from '@site/src/components/versionBlock'; +import Var from '@site/src/components/variable'; +import Term from '@site/src/components/term'; +import EventsFeed from '@site/src/components/events'; +import { DiscourseFeed, DiscourseHelpFeed } from '@site/src/components/discourse'; + +function unwrapMDXElement(element) { + if (element?.props?.mdxType && element?.props?.originalType) { + const { mdxType, originalType, ...newProps } = element.props; + return React.createElement(element.props.originalType, newProps); + } -export default { - code: props => { - const {children} = props; - if (typeof children === 'string') { - return ; - } - return children; + return element; +} + +const MDXComponents = { + head: (props) => { + const unwrappedChildren = React.Children.map(props.children, (child) => + unwrapMDXElement(child), + ); + return {unwrappedChildren}; + }, + code: (props) => { + const inlineElements = [ + 'a', + 'b', + 'big', + 'i', + 'span', + 'em', + 'strong', + 'sup', + 'sub', + 'small', + ]; + const shouldBeInline = React.Children.toArray(props.children).every( + (el) => + (typeof el === 'string' && !el.includes('\n')) || + (React.isValidElement(el) && inlineElements.includes(el.props.mdxType)), + ); + return shouldBeInline ? : ; }, a: (props) => , - pre: props =>
    ,
    -  h1: Heading('h1'),
    -  h2: Heading('h2'),
    -  h3: Heading('h3'),
    -  h4: Heading('h4'),
    -  h5: Heading('h5'),
    -  h6: Heading('h6'),
    +  pre: (props) => (
    +    
    +  ),
    +  details: (props) => {
    +    const items = React.Children.toArray(props.children); // Split summary item from the rest to pass it as a separate prop to the
    +    // Details theme component
    +
    +    const summary = items.find((item) => item?.props?.mdxType === 'summary');
    +    const children = <>{items.filter((item) => item !== summary)};
    +    return (
    +      
    + {children} +
    + ); + }, + h1: (props) => , + h2: (props) => , + h3: (props) => , + h4: (props) => , + h5: (props) => , + h6: (props) => , Changelog: Changelog, CloudCore: CloudCore, @@ -55,6 +111,15 @@ export default { LoomVideo: LoomVideo, Tabs: Tabs, TabItem: TabItem, + Snippet: Snippet, WistiaVideo: WistiaVideo, + WHCode: WHCode, YoutubeVideo: YoutubeVideo, + VersionBlock: VersionBlock, + Var: Var, + Term: Term, + EventsFeed: EventsFeed, + DiscourseFeed: DiscourseFeed, + DiscourseHelpFeed: DiscourseHelpFeed, }; +export default MDXComponents; diff --git a/website/src/theme/MDXComponents/styles.css b/website/src/theme/MDXComponents/styles.css new file mode 100644 index 00000000000..3c263a23347 --- /dev/null +++ b/website/src/theme/MDXComponents/styles.css @@ -0,0 +1,15 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +ul.contains-task-list { + padding-left: 0; + list-style: none; +} + +img { + height: auto; +} diff --git a/website/src/theme/MDXComponents/styles.module.css b/website/src/theme/MDXComponents/styles.module.css deleted file mode 100755 index 7f782bbb318..00000000000 --- a/website/src/theme/MDXComponents/styles.module.css +++ /dev/null @@ -1,14 +0,0 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -.mdxCodeBlock { - background-color: transparent; - border-radius: var(--ifm-global-radius); - box-sizing: border-box; - font-family: inherit; - padding: 0; -} diff --git a/website/src/theme/NavbarItem/DropdownNavbarItem.js b/website/src/theme/NavbarItem/DropdownNavbarItem.js new file mode 100644 index 00000000000..9dfef4fcf06 --- /dev/null +++ b/website/src/theme/NavbarItem/DropdownNavbarItem.js @@ -0,0 +1,219 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ +import React, {useState, useRef, useEffect, useContext} from 'react'; +import clsx from 'clsx'; +import { + isSamePath, + useCollapsible, + Collapsible, + isRegexpStringMatch, + useLocalPathname, +} from '@docusaurus/theme-common'; +import NavbarNavLink from '@theme/NavbarItem/NavbarNavLink'; +import NavbarItem from '@theme/NavbarItem'; +import VersionsNavbarItem from './VersionsNavItem'; +import VersionContext from '../../stores/VersionContext'; + +const dropdownLinkActiveClass = 'dropdown__link--active'; + +function isItemActive(item, localPathname) { + if (isSamePath(item.to, localPathname)) { + return true; + } + + if (isRegexpStringMatch(item.activeBaseRegex, localPathname)) { + return true; + } + + if (item.activeBasePath && localPathname.startsWith(item.activeBasePath)) { + return true; + } + + return false; +} + +function containsActiveItems(items, localPathname) { + return items.some((item) => isItemActive(item, localPathname)); +} + +function DropdownNavbarItemDesktop({items, position, className, versionContext, ...props}) { + const dropdownRef = useRef(null); + const [showDropdown, setShowDropdown] = useState(false); + + // handle version dropdown state on click + const [showVersionDropdown, setShowVersionDropdown] = useState(true); + + useEffect(() => { + const handleClickOutside = (event) => { + if (!dropdownRef.current || dropdownRef.current.contains(event.target)) { + return; + } + + setShowDropdown(false); + }; + + document.addEventListener('mousedown', handleClickOutside); + document.addEventListener('touchstart', handleClickOutside); + return () => { + document.removeEventListener('mousedown', handleClickOutside); + document.removeEventListener('touchstart', handleClickOutside); + }; + }, [dropdownRef]); + + // Hide version dropdown on click + // This adds dropdown--version--hide class on line 87 + const handleVersionMenuClick = () => { + setShowVersionDropdown(false) + } + + // Run when showVersionDropdown state changes + // which occurs during version menu item clicked + // This resets version dropdown to original state + // and removes the dropdown--version--hide class + useEffect(() => { + setShowVersionDropdown(true) + }, [showVersionDropdown]) + + return ( +
    + e.preventDefault()} + onKeyDown={(e) => { + if (e.key === 'Enter') { + e.preventDefault(); + setShowDropdown(!showDropdown); + } + }}> + {props.children ?? props.label} + +
      + {items.map((childItemProps, i) => ( + className === "nav-versioning" ? ( + { + if (i === items.length - 1 && e.key === 'Tab') { + e.preventDefault(); + setShowDropdown(false); + const nextNavbarItem = dropdownRef.current.nextElementSibling; + + if (nextNavbarItem) { + nextNavbarItem.focus(); + } + } + }} + activeClassName={dropdownLinkActiveClass} + {...childItemProps} + onClick={(e) => { + handleVersionMenuClick() + versionContext.updateVersion(e)} + } + key={i} + /> + ) : ( + { + if (i === items.length - 1 && e.key === 'Tab') { + e.preventDefault(); + setShowDropdown(false); + const nextNavbarItem = dropdownRef.current.nextElementSibling; + + if (nextNavbarItem) { + nextNavbarItem.focus(); + } + } + }} + activeClassName={dropdownLinkActiveClass} + {...childItemProps} + key={i} + /> + ) + ))} +
    +
    + ); +} + +function DropdownNavbarItemMobile({ + items, + className, + position: _position, + versionContext, + // Need to destructure position from props so that it doesn't get passed on. + ...props +}) { + const localPathname = useLocalPathname(); + const containsActive = containsActiveItems(items, localPathname); + const {collapsed, toggleCollapsed, setCollapsed} = useCollapsible({ + initialState: () => !containsActive, + }); // Expand/collapse if any item active after a navigation + + useEffect(() => { + if (containsActive) { + setCollapsed(!containsActive); + } + }, [localPathname, containsActive, setCollapsed]); + return ( +
  • + { + e.preventDefault(); + toggleCollapsed(); + }}> + {props.children ?? props.label} + + + {items.map((childItemProps, i) => ( + className === "nav-versioning" ? ( + versionContext.updateVersion(e)} + activeClassName="menu__link--active" + {...childItemProps} + key={i} + /> + ) : ( + + ) + ))} + +
  • + ); +} + +export default function DropdownNavbarItem({mobile = false, ...props}) { + const versionContext = useContext(VersionContext) + + const Comp = mobile ? DropdownNavbarItemMobile : DropdownNavbarItemDesktop; + return ; +} diff --git a/website/src/theme/NavbarItem/VersionsNavItem.js b/website/src/theme/NavbarItem/VersionsNavItem.js new file mode 100644 index 00000000000..d801c72d2c2 --- /dev/null +++ b/website/src/theme/NavbarItem/VersionsNavItem.js @@ -0,0 +1,84 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + import React from 'react'; + import clsx from 'clsx'; + import {getInfimaActiveClassName} from '@theme/NavbarItem/utils'; + + const dropdownLinkActiveClass = 'dropdown__link--active'; + export function NavLink({ + activeBasePath, + activeBaseRegex, + to, + href, + label, + activeClassName = '', + prependBaseUrlToHref, + ...props + }) { + + return ( + + { label } + + ); + } + + function DefaultNavbarItemDesktop({ + className, + isDropdownItem = false, + ...props + }) { + const element = ( + + ); + + if (isDropdownItem) { + return
  • {element}
  • ; + } + + return element; + } + + function DefaultNavbarItemMobile({ + className, + isDropdownItem: _isDropdownItem, + ...props + }) { + return ( +
  • + +
  • + ); + } + + function DefaultNavbarItem({ + mobile = false, + position: _position, + // Need to destructure position from props so that it doesn't get passed on. + ...props + }) { + const Comp = mobile ? DefaultNavbarItemMobile : DefaultNavbarItemDesktop; + return ( + + ); + } + + export default DefaultNavbarItem; diff --git a/website/src/theme/NavbarItem/index.js b/website/src/theme/NavbarItem/index.js new file mode 100644 index 00000000000..a45147298bc --- /dev/null +++ b/website/src/theme/NavbarItem/index.js @@ -0,0 +1,53 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ +import React from 'react'; +import DefaultNavbarItem from '@theme/NavbarItem/DefaultNavbarItem'; +import DropdownNavbarItem from '@theme/NavbarItem/DropdownNavbarItem'; +import LocaleDropdownNavbarItem from '@theme/NavbarItem/LocaleDropdownNavbarItem'; +import SearchNavbarItem from '@theme/NavbarItem/SearchNavbarItem'; +const NavbarItemComponents = { + default: () => DefaultNavbarItem, + localeDropdown: () => LocaleDropdownNavbarItem, + search: () => SearchNavbarItem, + dropdown: () => DropdownNavbarItem, + // Need to lazy load these items as we don't know for sure the docs plugin is + // loaded. See https://github.com/facebook/docusaurus/issues/3360 + + /* eslint-disable @typescript-eslint/no-var-requires, global-require */ + docsVersion: () => require('@theme/NavbarItem/DocsVersionNavbarItem').default, + docsVersionDropdown: () => + require('@theme/NavbarItem/DocsVersionDropdownNavbarItem').default, + doc: () => require('@theme/NavbarItem/DocNavbarItem').default, + docSidebar: () => require('@theme/NavbarItem/DocSidebarNavbarItem').default, + /* eslint-enable @typescript-eslint/no-var-requires, global-require */ +}; + +const getNavbarItemComponent = (type) => { + const navbarItemComponentFn = NavbarItemComponents[type]; + + if (!navbarItemComponentFn) { + throw new Error(`No NavbarItem component found for type "${type}".`); + } + + return navbarItemComponentFn(); +}; + +function getComponentType(type, isDropdown) { + // Backward compatibility: navbar item with no type set + // but containing dropdown items should use the type "dropdown" + if (!type || type === 'default') { + return isDropdown ? 'dropdown' : 'default'; + } + + return type; +} + +export default function NavbarItem({type, ...props}) { + const componentType = getComponentType(type, props.items !== undefined); + const NavbarItemComponent = getNavbarItemComponent(componentType); + return ; +} diff --git a/website/src/theme/Root.js b/website/src/theme/Root.js new file mode 100644 index 00000000000..b2762f89e9e --- /dev/null +++ b/website/src/theme/Root.js @@ -0,0 +1,13 @@ +import React from 'react' +import { VersionContextProvider } from '../stores/VersionContext' + +// Default implementation, that you can customize +function Root({children}) { + return ( + + {children} + + ) +} + +export default Root diff --git a/website/src/theme/SearchBar/index.js b/website/src/theme/SearchBar/index.js deleted file mode 100644 index bde8d2d68df..00000000000 --- a/website/src/theme/SearchBar/index.js +++ /dev/null @@ -1,207 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -import React, {useState, useRef, useCallback, useMemo} from 'react'; -import {createPortal} from 'react-dom'; -import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; -import {useHistory} from '@docusaurus/router'; -import {useBaseUrlUtils} from '@docusaurus/useBaseUrl'; -import Link from '@docusaurus/Link'; -import Head from '@docusaurus/Head'; -import useSearchQuery from '@theme/hooks/useSearchQuery'; -import {DocSearchButton, useDocSearchKeyboardEvents} from '@docsearch/react'; -import useAlgoliaContextualFacetFilters from '@theme/hooks/useAlgoliaContextualFacetFilters'; -import {translate} from '@docusaurus/Translate'; -import styles from './styles.module.css'; - -let DocSearchModal = null; - -function Hit({hit, children}) { - return {children}; -} - -function ResultsFooter({state, onClose}) { - const {generateSearchPageLink} = useSearchQuery(); - - return ( - - See all {state.context.nbHits} results - - ); -} - -function DocSearch({contextualSearch, ...props}) { - const {siteMetadata} = useDocusaurusContext(); - - const contextualSearchFacetFilters = useAlgoliaContextualFacetFilters(); - - const configFacetFilters = props.searchParameters?.facetFilters ?? []; - - const facetFilters = contextualSearch - ? // Merge contextual search filters with config filters - [...contextualSearchFacetFilters, ...configFacetFilters] - : // ... or use config facetFilters - configFacetFilters; - - // we let user override default searchParameters if he wants to - const searchParameters = { - ...props.searchParameters, - facetFilters, - }; - - const {withBaseUrl} = useBaseUrlUtils(); - const history = useHistory(); - const searchContainer = useRef(null); - const searchButtonRef = useRef(null); - const [isOpen, setIsOpen] = useState(false); - const [initialQuery, setInitialQuery] = useState(null); - - const importDocSearchModalIfNeeded = useCallback(() => { - if (DocSearchModal) { - return Promise.resolve(); - } - - return Promise.all([ - import('@docsearch/react/modal'), - import('@docsearch/react/style'), - import('./styles.css'), - ]).then(([{DocSearchModal: Modal}]) => { - DocSearchModal = Modal; - }); - }, []); - - const onOpen = useCallback(() => { - importDocSearchModalIfNeeded().then(() => { - searchContainer.current = document.createElement('div'); - document.body.insertBefore( - searchContainer.current, - document.body.firstChild, - ); - setIsOpen(true); - }); - }, [importDocSearchModalIfNeeded, setIsOpen]); - - const onClose = useCallback(() => { - setIsOpen(false); - searchContainer.current.remove(); - }, [setIsOpen]); - - const onInput = useCallback( - (event) => { - importDocSearchModalIfNeeded().then(() => { - setIsOpen(true); - setInitialQuery(event.key); - }); - }, - [importDocSearchModalIfNeeded, setIsOpen, setInitialQuery], - ); - - const navigator = useRef({ - navigate({itemUrl}) { - history.push(itemUrl); - }, - }).current; - - const transformItems = useRef((items) => { - return items.map((item) => { - // We transform the absolute URL into a relative URL. - // Alternatively, we can use `new URL(item.url)` but it's not - // supported in IE. - const a = document.createElement('a'); - a.href = item.url; - - return { - ...item, - url: withBaseUrl(`${a.pathname}${a.hash}`), - }; - }); - }).current; - - const resultsFooterComponent = useMemo( - () => (footerProps) => , - [onClose], - ); - - const transformSearchClient = useCallback( - (searchClient) => { - searchClient.addAlgoliaAgent( - 'docusaurus', - siteMetadata.docusaurusVersion, - ); - - return searchClient; - }, - [siteMetadata.docusaurusVersion], - ); - - useDocSearchKeyboardEvents({ - isOpen, - onOpen, - onClose, - onInput, - searchButtonRef, - }); - - const translatedSearchLabel = translate({ - id: 'theme.SearchBar.label', - message: 'Search', - description: 'The ARIA label and placeholder for search button', - }); - - return ( - <> - - {/* This hints the browser that the website will load data from Algolia, - and allows it to preconnect to the DocSearch cluster. It makes the first - query faster, especially on mobile. */} - - - -
    - -
    - - {isOpen && - createPortal( - , - searchContainer.current, - )} - - ); -} - -function SearchBar() { - const {siteConfig} = useDocusaurusContext(); - return ; -} - -export default SearchBar; diff --git a/website/src/theme/SearchBar/styles.css b/website/src/theme/SearchBar/styles.css deleted file mode 100644 index c80dd71d37d..00000000000 --- a/website/src/theme/SearchBar/styles.css +++ /dev/null @@ -1,21 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -:root { - --docsearch-primary-color: var(--ifm-color-primary); - --docsearch-text-color: var(--ifm-font-color-base); -} - -.DocSearch-Button { - margin: 0; - transition: all var(--ifm-transition-fast) - var(--ifm-transition-timing-default); -} - -.DocSearch-Container { - z-index: calc(var(--ifm-z-index-fixed) + 1); -} diff --git a/website/src/theme/SearchBar/styles.module.css b/website/src/theme/SearchBar/styles.module.css deleted file mode 100644 index ca386bb12db..00000000000 --- a/website/src/theme/SearchBar/styles.module.css +++ /dev/null @@ -1,20 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -@media (max-width: 996px) { - .searchBox { - position: absolute; - right: var(--ifm-navbar-padding-horizontal); - } -} - -@media (min-width: 997px) { - .searchBox { - padding: var(--ifm-navbar-item-padding-vertical) - var(--ifm-navbar-item-padding-horizontal); - } -} diff --git a/website/src/theme/TOC/index.js b/website/src/theme/TOC/index.js new file mode 100644 index 00000000000..e3e34f6f6b7 --- /dev/null +++ b/website/src/theme/TOC/index.js @@ -0,0 +1,43 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ +import React from 'react'; +import clsx from 'clsx'; +import TOCItems from '@theme/TOCItems'; +import EditThisPage from '@theme/EditThisPage'; +import styles from './styles.module.css'; // Using a custom className +// This prevents TOC highlighting to highlight TOCInline/TOCCollapsible by mistake + +//dbt Custom +import CTA from '../../components/cta'; + +const LINK_CLASS_NAME = 'table-of-contents__link toc-highlight'; +const LINK_ACTIVE_CLASS_NAME = 'table-of-contents__link--active'; + +function TOC({className, featured_cta, editUrl, ...props}) { + + return ( +
    + + + {editUrl && ( +
    + +
    )} + + {featured_cta && ( + + )} +
    + ); +} + +export default TOC; diff --git a/website/src/theme/TOC/styles.module.css b/website/src/theme/TOC/styles.module.css new file mode 100644 index 00000000000..4b6d2bcc657 --- /dev/null +++ b/website/src/theme/TOC/styles.module.css @@ -0,0 +1,23 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +.tableOfContents { + max-height: calc(100vh - (var(--ifm-navbar-height) + 2rem)); + overflow-y: auto; + position: sticky; + top: calc(var(--ifm-navbar-height) + 1rem); +} + +@media (max-width: 996px) { + .tableOfContents { + display: none; + } + + .docItemContainer { + padding: 0 0.3rem; + } +} diff --git a/website/src/utils/get-all-posts.js b/website/src/utils/get-all-posts.js new file mode 100644 index 00000000000..ed2cb251c3c --- /dev/null +++ b/website/src/utils/get-all-posts.js @@ -0,0 +1,28 @@ +// Util function to get all posts +export default function getAllPosts() { + /* + * Credit to get all posts: + * https://blog.johnnyreilly.com/2021/05/01/blog-archive-for-docusaurus/ + */ + return ((ctx) => { + const blogpostNames = ctx.keys(); + return blogpostNames.reduce((blogposts, blogpostName, i) => { + const module = ctx(blogpostName); + const { image } = module.frontMatter + const { date, formattedDate, title, permalink, authors, description, tags } = module.metadata; + return [ + ...blogposts, + { + date, + formattedDate, + title, + permalink, + authors, + image, + description, + tags + }, + ]; + }, ([])); + })(require.context('../../blog', true, /.md/)); +} diff --git a/website/src/utils/get-html-elements.js b/website/src/utils/get-html-elements.js new file mode 100644 index 00000000000..95b5e0a014b --- /dev/null +++ b/website/src/utils/get-html-elements.js @@ -0,0 +1,21 @@ +// Returns a promise with elements +// This is used for elements which may not be +// immediately available on page load +export default function getElements(group) { + return new Promise((resolve) => { + let count = 0 + const eleInt = setInterval(function() { + const elements = document.querySelectorAll(group) + if(count < 10) { + if(elements && elements.length) { + resolve(elements) + clearInterval(eleInt) + } else { + count++ + } + } else { + clearInterval(eleInt) + } + }, 500) + }) +} diff --git a/website/src/utils/page-version-check.js b/website/src/utils/page-version-check.js new file mode 100644 index 00000000000..cc2611929af --- /dev/null +++ b/website/src/utils/page-version-check.js @@ -0,0 +1,41 @@ +export default function pageVersionCheck(version, versionedPages, path) { + let pageAvailableObj = { + pageAvailable: true + } + + if(!path) + return pageAvailableObj + + let updatedPath = path.charAt(0) === '/' + ? path.substr(1) + : path + + const itemFound = versionedPages.find(vpage => vpage.page === updatedPath) + + if(itemFound) { + + const { firstVersion, lastVersion } = itemFound + const currentVersionVal = parseFloat(version) + const firstVersionVal = parseFloat(firstVersion) || 0 + + pageAvailableObj.firstAvailableVersion = firstVersion + + // Determine if sidebar item within version range + if(lastVersion) { + const lastVersionVal = parseFloat(lastVersion) + // If lastVersion set for sidebar item, + // check if current version is higher than lastVersion + // or if current version is less than firstVersion + // If true, remove item in sidebar + if(currentVersionVal > lastVersionVal || currentVersionVal < firstVersionVal) { + pageAvailableObj.pageAvailable = false + } + } else if(firstVersionVal > currentVersionVal) { + // If firstVersion is greater than currentVersion + // remove item from sidebar + pageAvailableObj.pageAvailable = false + } + } + + return pageAvailableObj +} diff --git a/website/static/css/__mocks__/styleMock.js b/website/static/css/__mocks__/styleMock.js new file mode 100644 index 00000000000..f053ebf7976 --- /dev/null +++ b/website/static/css/__mocks__/styleMock.js @@ -0,0 +1 @@ +module.exports = {}; diff --git a/website/static/img/adapter-guide/0-full-release-notes.png b/website/static/img/adapter-guide/0-full-release-notes.png new file mode 100644 index 00000000000..7acb59d8ffa Binary files /dev/null and b/website/static/img/adapter-guide/0-full-release-notes.png differ diff --git a/website/static/img/adapter-guide/1-announcement.png b/website/static/img/adapter-guide/1-announcement.png new file mode 100644 index 00000000000..32f5cd6ba5d Binary files /dev/null and b/website/static/img/adapter-guide/1-announcement.png differ diff --git a/website/static/img/adapter-guide/2-short-description.png b/website/static/img/adapter-guide/2-short-description.png new file mode 100644 index 00000000000..547b856ebb0 Binary files /dev/null and b/website/static/img/adapter-guide/2-short-description.png differ diff --git a/website/static/img/adapter-guide/3-additional-resources.png b/website/static/img/adapter-guide/3-additional-resources.png new file mode 100644 index 00000000000..575157b9d54 Binary files /dev/null and b/website/static/img/adapter-guide/3-additional-resources.png differ diff --git a/website/static/img/adapter-guide/4-installation.png b/website/static/img/adapter-guide/4-installation.png new file mode 100644 index 00000000000..c728ff6952b Binary files /dev/null and b/website/static/img/adapter-guide/4-installation.png differ diff --git a/website/static/img/adapter-guide/5-coming-up.png b/website/static/img/adapter-guide/5-coming-up.png new file mode 100644 index 00000000000..4681ee87a1b Binary files /dev/null and b/website/static/img/adapter-guide/5-coming-up.png differ diff --git a/website/static/img/adapter-guide/6-thank-contribs.png b/website/static/img/adapter-guide/6-thank-contribs.png new file mode 100644 index 00000000000..b2db6df4856 Binary files /dev/null and b/website/static/img/adapter-guide/6-thank-contribs.png differ diff --git a/website/static/img/adapter-guide/adapter architecture - postgres.png b/website/static/img/adapter-guide/adapter architecture - postgres.png new file mode 100644 index 00000000000..d64dbc95026 Binary files /dev/null and b/website/static/img/adapter-guide/adapter architecture - postgres.png differ diff --git a/website/static/img/api-access-profile.png b/website/static/img/api-access-profile.png index 71a19e15ec2..deade9f2135 100644 Binary files a/website/static/img/api-access-profile.png and b/website/static/img/api-access-profile.png differ diff --git a/website/static/img/bigquery/api-create-key.png b/website/static/img/bigquery/api-create-key.png new file mode 100644 index 00000000000..72c43411e5e Binary files /dev/null and b/website/static/img/bigquery/api-create-key.png differ diff --git a/website/static/img/bigquery/api-credential-type.png b/website/static/img/bigquery/api-credential-type.png new file mode 100644 index 00000000000..3d924cde438 Binary files /dev/null and b/website/static/img/bigquery/api-credential-type.png differ diff --git a/website/static/img/bigquery/api-grant-service-access.png b/website/static/img/bigquery/api-grant-service-access.png new file mode 100644 index 00000000000..8a165ac45ed Binary files /dev/null and b/website/static/img/bigquery/api-grant-service-access.png differ diff --git a/website/static/img/bigquery/api-grant-user-access.png b/website/static/img/bigquery/api-grant-user-access.png new file mode 100644 index 00000000000..0d7f180bd94 Binary files /dev/null and b/website/static/img/bigquery/api-grant-user-access.png differ diff --git a/website/static/img/bigquery/api-key-type.png b/website/static/img/bigquery/api-key-type.png new file mode 100644 index 00000000000..7d40ba1c0a6 Binary files /dev/null and b/website/static/img/bigquery/api-key-type.png differ diff --git a/website/static/img/bigquery/api-select-service-account.png b/website/static/img/bigquery/api-select-service-account.png new file mode 100644 index 00000000000..b5e59126e84 Binary files /dev/null and b/website/static/img/bigquery/api-select-service-account.png differ diff --git a/website/static/img/bigquery/api-service-account-details.png b/website/static/img/bigquery/api-service-account-details.png new file mode 100644 index 00000000000..dc4536dcdbe Binary files /dev/null and b/website/static/img/bigquery/api-service-account-details.png differ diff --git a/website/static/img/bigquery/create-dataset-id.png b/website/static/img/bigquery/create-dataset-id.png new file mode 100644 index 00000000000..507a14d3c96 Binary files /dev/null and b/website/static/img/bigquery/create-dataset-id.png differ diff --git a/website/static/img/bigquery/create-dataset-options.png b/website/static/img/bigquery/create-dataset-options.png new file mode 100644 index 00000000000..fe8e602958a Binary files /dev/null and b/website/static/img/bigquery/create-dataset-options.png differ diff --git a/website/static/img/bigquery/create-dataset.png b/website/static/img/bigquery/create-dataset.png new file mode 100644 index 00000000000..3a911298004 Binary files /dev/null and b/website/static/img/bigquery/create-dataset.png differ diff --git a/website/static/img/bigquery/database-connection-json-file.png b/website/static/img/bigquery/database-connection-json-file.png new file mode 100644 index 00000000000..bb834c45921 Binary files /dev/null and b/website/static/img/bigquery/database-connection-json-file.png differ diff --git a/website/static/img/bigquery/database-connection-test.png b/website/static/img/bigquery/database-connection-test.png new file mode 100644 index 00000000000..d41f5f91a9c Binary files /dev/null and b/website/static/img/bigquery/database-connection-test.png differ diff --git a/website/static/img/bigquery/database-connection.png b/website/static/img/bigquery/database-connection.png new file mode 100644 index 00000000000..90ab4795a73 Binary files /dev/null and b/website/static/img/bigquery/database-connection.png differ diff --git a/website/static/img/bigquery/expose-options.png b/website/static/img/bigquery/expose-options.png new file mode 100644 index 00000000000..79863b9300b Binary files /dev/null and b/website/static/img/bigquery/expose-options.png differ diff --git a/website/static/img/bigquery/init-commit.png b/website/static/img/bigquery/init-commit.png new file mode 100644 index 00000000000..08531b91bdc Binary files /dev/null and b/website/static/img/bigquery/init-commit.png differ diff --git a/website/static/img/bigquery/initialize-your-project.png b/website/static/img/bigquery/initialize-your-project.png new file mode 100644 index 00000000000..c0f7b45d2ba Binary files /dev/null and b/website/static/img/bigquery/initialize-your-project.png differ diff --git a/website/static/img/bigquery/new-project-creation.png b/website/static/img/bigquery/new-project-creation.png new file mode 100644 index 00000000000..f0e1f89bf4a Binary files /dev/null and b/website/static/img/bigquery/new-project-creation.png differ diff --git a/website/static/img/bigquery/preview-data.png b/website/static/img/bigquery/preview-data.png new file mode 100644 index 00000000000..a7b55c0d867 Binary files /dev/null and b/website/static/img/bigquery/preview-data.png differ diff --git a/website/static/img/bigquery/preview-open-data.png b/website/static/img/bigquery/preview-open-data.png new file mode 100644 index 00000000000..34d6e1875b5 Binary files /dev/null and b/website/static/img/bigquery/preview-open-data.png differ diff --git a/website/static/img/bigquery/project-dropdown.png b/website/static/img/bigquery/project-dropdown.png new file mode 100644 index 00000000000..fc5fd749a38 Binary files /dev/null and b/website/static/img/bigquery/project-dropdown.png differ diff --git a/website/static/img/bigquery/project-name.png b/website/static/img/bigquery/project-name.png new file mode 100644 index 00000000000..ad0cfb82ff2 Binary files /dev/null and b/website/static/img/bigquery/project-name.png differ diff --git a/website/static/img/bigquery/project-selected.png b/website/static/img/bigquery/project-selected.png new file mode 100644 index 00000000000..939791036f5 Binary files /dev/null and b/website/static/img/bigquery/project-selected.png differ diff --git a/website/static/img/bigquery/query-results.png b/website/static/img/bigquery/query-results.png new file mode 100644 index 00000000000..51613eab397 Binary files /dev/null and b/website/static/img/bigquery/query-results.png differ diff --git a/website/static/img/bigquery/save-view-datasets.png b/website/static/img/bigquery/save-view-datasets.png new file mode 100644 index 00000000000..cdd807b1a7b Binary files /dev/null and b/website/static/img/bigquery/save-view-datasets.png differ diff --git a/website/static/img/bigquery/save-view-table.png b/website/static/img/bigquery/save-view-table.png new file mode 100644 index 00000000000..a3938777af9 Binary files /dev/null and b/website/static/img/bigquery/save-view-table.png differ diff --git a/website/static/img/bigquery/save-view.png b/website/static/img/bigquery/save-view.png new file mode 100644 index 00000000000..2361b52b8f5 Binary files /dev/null and b/website/static/img/bigquery/save-view.png differ diff --git a/website/static/img/bigquery/set-up-new-project.png b/website/static/img/bigquery/set-up-new-project.png new file mode 100644 index 00000000000..2a7e9d13c87 Binary files /dev/null and b/website/static/img/bigquery/set-up-new-project.png differ diff --git a/website/static/img/bigquery/set-up-repository.png b/website/static/img/bigquery/set-up-repository.png new file mode 100644 index 00000000000..0d241c55a65 Binary files /dev/null and b/website/static/img/bigquery/set-up-repository.png differ diff --git a/website/static/img/bigquery/start-developing.png b/website/static/img/bigquery/start-developing.png new file mode 100644 index 00000000000..26743afb277 Binary files /dev/null and b/website/static/img/bigquery/start-developing.png differ diff --git a/website/static/img/bigquery/view-created.png b/website/static/img/bigquery/view-created.png new file mode 100644 index 00000000000..e34abb749a3 Binary files /dev/null and b/website/static/img/bigquery/view-created.png differ diff --git a/website/static/img/blog/2021-11-29-dbt-airflow-spiritual-alignment/Monitor-Job-Runs.png b/website/static/img/blog/2021-11-29-dbt-airflow-spiritual-alignment/Monitor-Job-Runs.png new file mode 100644 index 00000000000..01d6a7ab0df Binary files /dev/null and b/website/static/img/blog/2021-11-29-dbt-airflow-spiritual-alignment/Monitor-Job-Runs.png differ diff --git a/website/static/img/blog/2021-11-29-dbt-airflow-spiritual-alignment/airflow-connection-ID.png b/website/static/img/blog/2021-11-29-dbt-airflow-spiritual-alignment/airflow-connection-ID.png new file mode 100644 index 00000000000..121340f7dde Binary files /dev/null and b/website/static/img/blog/2021-11-29-dbt-airflow-spiritual-alignment/airflow-connection-ID.png differ diff --git a/website/static/img/blog/2021-11-29-dbt-airflow-spiritual-alignment/airflow-dbt-run-select.png b/website/static/img/blog/2021-11-29-dbt-airflow-spiritual-alignment/airflow-dbt-run-select.png new file mode 100644 index 00000000000..58038259763 Binary files /dev/null and b/website/static/img/blog/2021-11-29-dbt-airflow-spiritual-alignment/airflow-dbt-run-select.png differ diff --git a/website/static/img/blog/2021-11-29-dbt-airflow-spiritual-alignment/dbt-Cloud-API-graph.png b/website/static/img/blog/2021-11-29-dbt-airflow-spiritual-alignment/dbt-Cloud-API-graph.png new file mode 100644 index 00000000000..9851eaacaed Binary files /dev/null and b/website/static/img/blog/2021-11-29-dbt-airflow-spiritual-alignment/dbt-Cloud-API-graph.png differ diff --git a/website/static/img/blog/2021-11-29-dbt-airflow-spiritual-alignment/dbt-airflow-tree-graph.png b/website/static/img/blog/2021-11-29-dbt-airflow-spiritual-alignment/dbt-airflow-tree-graph.png new file mode 100644 index 00000000000..78287a5ca75 Binary files /dev/null and b/website/static/img/blog/2021-11-29-dbt-airflow-spiritual-alignment/dbt-airflow-tree-graph.png differ diff --git a/website/static/img/blog/2021-11-29-dbt-airflow-spiritual-alignment/job-settings.png b/website/static/img/blog/2021-11-29-dbt-airflow-spiritual-alignment/job-settings.png new file mode 100644 index 00000000000..8874987d79b Binary files /dev/null and b/website/static/img/blog/2021-11-29-dbt-airflow-spiritual-alignment/job-settings.png differ diff --git a/website/static/img/blog/2021-11-29-dbt-airflow-spiritual-alignment/run-number.png b/website/static/img/blog/2021-11-29-dbt-airflow-spiritual-alignment/run-number.png new file mode 100644 index 00000000000..28ee5484d4f Binary files /dev/null and b/website/static/img/blog/2021-11-29-dbt-airflow-spiritual-alignment/run-number.png differ diff --git a/website/static/img/blog/2022-01-12-time-on-task/image_0.png b/website/static/img/blog/2022-01-12-time-on-task/image_0.png new file mode 100644 index 00000000000..6373a75a684 Binary files /dev/null and b/website/static/img/blog/2022-01-12-time-on-task/image_0.png differ diff --git a/website/static/img/blog/2022-01-12-time-on-task/image_1.png b/website/static/img/blog/2022-01-12-time-on-task/image_1.png new file mode 100644 index 00000000000..9d6ffb1e27c Binary files /dev/null and b/website/static/img/blog/2022-01-12-time-on-task/image_1.png differ diff --git a/website/static/img/blog/2022-01-12-time-on-task/image_2.png b/website/static/img/blog/2022-01-12-time-on-task/image_2.png new file mode 100644 index 00000000000..57500f13edf Binary files /dev/null and b/website/static/img/blog/2022-01-12-time-on-task/image_2.png differ diff --git a/website/static/img/blog/2022-01-12-time-on-task/image_3.png b/website/static/img/blog/2022-01-12-time-on-task/image_3.png new file mode 100644 index 00000000000..4d1abdd1799 Binary files /dev/null and b/website/static/img/blog/2022-01-12-time-on-task/image_3.png differ diff --git a/website/static/img/blog/2022-01-12-time-on-task/image_4.png b/website/static/img/blog/2022-01-12-time-on-task/image_4.png new file mode 100644 index 00000000000..f24cafd73a4 Binary files /dev/null and b/website/static/img/blog/2022-01-12-time-on-task/image_4.png differ diff --git a/website/static/img/blog/2022-02-08-customer-360-view/image_0.jpg b/website/static/img/blog/2022-02-08-customer-360-view/image_0.jpg new file mode 100644 index 00000000000..a5c8cd9f413 Binary files /dev/null and b/website/static/img/blog/2022-02-08-customer-360-view/image_0.jpg differ diff --git a/website/static/img/blog/2022-02-08-customer-360-view/image_1.png b/website/static/img/blog/2022-02-08-customer-360-view/image_1.png new file mode 100644 index 00000000000..25a87e51cdc Binary files /dev/null and b/website/static/img/blog/2022-02-08-customer-360-view/image_1.png differ diff --git a/website/static/img/blog/2022-02-08-customer-360-view/image_10.png b/website/static/img/blog/2022-02-08-customer-360-view/image_10.png new file mode 100644 index 00000000000..5907875d0e5 Binary files /dev/null and b/website/static/img/blog/2022-02-08-customer-360-view/image_10.png differ diff --git a/website/static/img/blog/2022-02-08-customer-360-view/image_11.png b/website/static/img/blog/2022-02-08-customer-360-view/image_11.png new file mode 100644 index 00000000000..70a5288de6a Binary files /dev/null and b/website/static/img/blog/2022-02-08-customer-360-view/image_11.png differ diff --git a/website/static/img/blog/2022-02-08-customer-360-view/image_2.png b/website/static/img/blog/2022-02-08-customer-360-view/image_2.png new file mode 100644 index 00000000000..2f2e33c18ee Binary files /dev/null and b/website/static/img/blog/2022-02-08-customer-360-view/image_2.png differ diff --git a/website/static/img/blog/2022-02-08-customer-360-view/image_3.png b/website/static/img/blog/2022-02-08-customer-360-view/image_3.png new file mode 100644 index 00000000000..3764e774047 Binary files /dev/null and b/website/static/img/blog/2022-02-08-customer-360-view/image_3.png differ diff --git a/website/static/img/blog/2022-02-08-customer-360-view/image_4.png b/website/static/img/blog/2022-02-08-customer-360-view/image_4.png new file mode 100644 index 00000000000..1cd40bc96a0 Binary files /dev/null and b/website/static/img/blog/2022-02-08-customer-360-view/image_4.png differ diff --git a/website/static/img/blog/2022-02-08-customer-360-view/image_5.png b/website/static/img/blog/2022-02-08-customer-360-view/image_5.png new file mode 100644 index 00000000000..5de4697e9b4 Binary files /dev/null and b/website/static/img/blog/2022-02-08-customer-360-view/image_5.png differ diff --git a/website/static/img/blog/2022-02-08-customer-360-view/image_6.png b/website/static/img/blog/2022-02-08-customer-360-view/image_6.png new file mode 100644 index 00000000000..29134c61b81 Binary files /dev/null and b/website/static/img/blog/2022-02-08-customer-360-view/image_6.png differ diff --git a/website/static/img/blog/2022-02-08-customer-360-view/image_7.png b/website/static/img/blog/2022-02-08-customer-360-view/image_7.png new file mode 100644 index 00000000000..6a7e0cab42c Binary files /dev/null and b/website/static/img/blog/2022-02-08-customer-360-view/image_7.png differ diff --git a/website/static/img/blog/2022-02-08-customer-360-view/image_8.png b/website/static/img/blog/2022-02-08-customer-360-view/image_8.png new file mode 100644 index 00000000000..b997017d37f Binary files /dev/null and b/website/static/img/blog/2022-02-08-customer-360-view/image_8.png differ diff --git a/website/static/img/blog/2022-02-08-customer-360-view/image_9.png b/website/static/img/blog/2022-02-08-customer-360-view/image_9.png new file mode 100644 index 00000000000..b7756c8caa8 Binary files /dev/null and b/website/static/img/blog/2022-02-08-customer-360-view/image_9.png differ diff --git a/website/static/img/blog/2022-02-08-customer-360-view/jafflegaggle_screenshot.png b/website/static/img/blog/2022-02-08-customer-360-view/jafflegaggle_screenshot.png new file mode 100644 index 00000000000..6ea9a214410 Binary files /dev/null and b/website/static/img/blog/2022-02-08-customer-360-view/jafflegaggle_screenshot.png differ diff --git a/website/static/img/blog/2022-02-18-machine-learning-dbt-baton-pass/JTBD-workflow.png b/website/static/img/blog/2022-02-18-machine-learning-dbt-baton-pass/JTBD-workflow.png new file mode 100644 index 00000000000..f2541fb3065 Binary files /dev/null and b/website/static/img/blog/2022-02-18-machine-learning-dbt-baton-pass/JTBD-workflow.png differ diff --git a/website/static/img/blog/2022-02-18-machine-learning-dbt-baton-pass/fal-install-1.png b/website/static/img/blog/2022-02-18-machine-learning-dbt-baton-pass/fal-install-1.png new file mode 100644 index 00000000000..8d98ddc2253 Binary files /dev/null and b/website/static/img/blog/2022-02-18-machine-learning-dbt-baton-pass/fal-install-1.png differ diff --git a/website/static/img/blog/2022-02-18-machine-learning-dbt-baton-pass/fal-install-2.png b/website/static/img/blog/2022-02-18-machine-learning-dbt-baton-pass/fal-install-2.png new file mode 100644 index 00000000000..90fbd31ed8a Binary files /dev/null and b/website/static/img/blog/2022-02-18-machine-learning-dbt-baton-pass/fal-install-2.png differ diff --git a/website/static/img/blog/2022-02-18-machine-learning-dbt-baton-pass/lineage-graph.png b/website/static/img/blog/2022-02-18-machine-learning-dbt-baton-pass/lineage-graph.png new file mode 100644 index 00000000000..bc8715eafd3 Binary files /dev/null and b/website/static/img/blog/2022-02-18-machine-learning-dbt-baton-pass/lineage-graph.png differ diff --git a/website/static/img/blog/2022-02-18-machine-learning-dbt-baton-pass/macro-names.png b/website/static/img/blog/2022-02-18-machine-learning-dbt-baton-pass/macro-names.png new file mode 100644 index 00000000000..87bfee59662 Binary files /dev/null and b/website/static/img/blog/2022-02-18-machine-learning-dbt-baton-pass/macro-names.png differ diff --git a/website/static/img/blog/2022-02-18-machine-learning-dbt-baton-pass/modelbit-api.png b/website/static/img/blog/2022-02-18-machine-learning-dbt-baton-pass/modelbit-api.png new file mode 100644 index 00000000000..c3529c4d0bd Binary files /dev/null and b/website/static/img/blog/2022-02-18-machine-learning-dbt-baton-pass/modelbit-api.png differ diff --git a/website/static/img/blog/2022-02-18-machine-learning-dbt-baton-pass/notebook-dbt-sync.png b/website/static/img/blog/2022-02-18-machine-learning-dbt-baton-pass/notebook-dbt-sync.png new file mode 100644 index 00000000000..ad09601a59b Binary files /dev/null and b/website/static/img/blog/2022-02-18-machine-learning-dbt-baton-pass/notebook-dbt-sync.png differ diff --git a/website/static/img/blog/2022-02-23-founding-an-AE-team-smartsheet/completed-process.png b/website/static/img/blog/2022-02-23-founding-an-AE-team-smartsheet/completed-process.png new file mode 100644 index 00000000000..f64ed2546f8 Binary files /dev/null and b/website/static/img/blog/2022-02-23-founding-an-AE-team-smartsheet/completed-process.png differ diff --git a/website/static/img/blog/2022-02-23-founding-an-AE-team-smartsheet/current-enrichment-structure.png b/website/static/img/blog/2022-02-23-founding-an-AE-team-smartsheet/current-enrichment-structure.png new file mode 100644 index 00000000000..ec68b3cace2 Binary files /dev/null and b/website/static/img/blog/2022-02-23-founding-an-AE-team-smartsheet/current-enrichment-structure.png differ diff --git a/website/static/img/blog/2022-02-23-founding-an-AE-team-smartsheet/enrichment-structure-solutions.png b/website/static/img/blog/2022-02-23-founding-an-AE-team-smartsheet/enrichment-structure-solutions.png new file mode 100644 index 00000000000..4d0e3ebe2d8 Binary files /dev/null and b/website/static/img/blog/2022-02-23-founding-an-AE-team-smartsheet/enrichment-structure-solutions.png differ diff --git a/website/static/img/blog/2022-02-23-founding-an-AE-team-smartsheet/new-structure-example.png b/website/static/img/blog/2022-02-23-founding-an-AE-team-smartsheet/new-structure-example.png new file mode 100644 index 00000000000..3f1eb82e235 Binary files /dev/null and b/website/static/img/blog/2022-02-23-founding-an-AE-team-smartsheet/new-structure-example.png differ diff --git a/website/static/img/blog/2022-02-23-founding-an-AE-team-smartsheet/new-transformation-workflow.png b/website/static/img/blog/2022-02-23-founding-an-AE-team-smartsheet/new-transformation-workflow.png new file mode 100644 index 00000000000..c4d53aa8ea9 Binary files /dev/null and b/website/static/img/blog/2022-02-23-founding-an-AE-team-smartsheet/new-transformation-workflow.png differ diff --git a/website/static/img/blog/2022-04-05-when-backend-devs-spark-joy/slack_thread_screenshot.png b/website/static/img/blog/2022-04-05-when-backend-devs-spark-joy/slack_thread_screenshot.png new file mode 100644 index 00000000000..e5c2d1a27cc Binary files /dev/null and b/website/static/img/blog/2022-04-05-when-backend-devs-spark-joy/slack_thread_screenshot.png differ diff --git a/website/static/img/blog/2022-04-14-add-ci-cd-to-bitbucket/2022-04-14-add-ci-cd-to-bitbucket-image-1.png b/website/static/img/blog/2022-04-14-add-ci-cd-to-bitbucket/2022-04-14-add-ci-cd-to-bitbucket-image-1.png new file mode 100644 index 00000000000..a969d70156a Binary files /dev/null and b/website/static/img/blog/2022-04-14-add-ci-cd-to-bitbucket/2022-04-14-add-ci-cd-to-bitbucket-image-1.png differ diff --git a/website/static/img/blog/2022-04-14-add-ci-cd-to-bitbucket/2022-04-14-add-ci-cd-to-bitbucket-image-2.png b/website/static/img/blog/2022-04-14-add-ci-cd-to-bitbucket/2022-04-14-add-ci-cd-to-bitbucket-image-2.png new file mode 100644 index 00000000000..0ff67221251 Binary files /dev/null and b/website/static/img/blog/2022-04-14-add-ci-cd-to-bitbucket/2022-04-14-add-ci-cd-to-bitbucket-image-2.png differ diff --git a/website/static/img/blog/2022-04-14-add-ci-cd-to-bitbucket/2022-04-14-add-ci-cd-to-bitbucket-image-3.png b/website/static/img/blog/2022-04-14-add-ci-cd-to-bitbucket/2022-04-14-add-ci-cd-to-bitbucket-image-3.png new file mode 100644 index 00000000000..363f5e1dec8 Binary files /dev/null and b/website/static/img/blog/2022-04-14-add-ci-cd-to-bitbucket/2022-04-14-add-ci-cd-to-bitbucket-image-3.png differ diff --git a/website/static/img/blog/2022-04-19-complex-deduplication/dancing-baby.gif b/website/static/img/blog/2022-04-19-complex-deduplication/dancing-baby.gif new file mode 100644 index 00000000000..33e311e79bb Binary files /dev/null and b/website/static/img/blog/2022-04-19-complex-deduplication/dancing-baby.gif differ diff --git a/website/static/img/blog/2022-04-19-dbt-cloud-postman-collection/dbt-cloud-api-ID.png b/website/static/img/blog/2022-04-19-dbt-cloud-postman-collection/dbt-cloud-api-ID.png new file mode 100644 index 00000000000..3eba58c62ef Binary files /dev/null and b/website/static/img/blog/2022-04-19-dbt-cloud-postman-collection/dbt-cloud-api-ID.png differ diff --git a/website/static/img/blog/2022-04-19-dbt-cloud-postman-collection/example-cloud-environment.png b/website/static/img/blog/2022-04-19-dbt-cloud-postman-collection/example-cloud-environment.png new file mode 100644 index 00000000000..2a40bcb1a81 Binary files /dev/null and b/website/static/img/blog/2022-04-19-dbt-cloud-postman-collection/example-cloud-environment.png differ diff --git a/website/static/img/blog/2022-05-17-stakeholder-friendly-model-names/PR-view.png b/website/static/img/blog/2022-05-17-stakeholder-friendly-model-names/PR-view.png new file mode 100644 index 00000000000..ee214259c5d Binary files /dev/null and b/website/static/img/blog/2022-05-17-stakeholder-friendly-model-names/PR-view.png differ diff --git a/website/static/img/blog/2022-05-17-stakeholder-friendly-model-names/dag-view.png b/website/static/img/blog/2022-05-17-stakeholder-friendly-model-names/dag-view.png new file mode 100644 index 00000000000..0ec7c47f459 Binary files /dev/null and b/website/static/img/blog/2022-05-17-stakeholder-friendly-model-names/dag-view.png differ diff --git a/website/static/img/blog/2022-05-17-stakeholder-friendly-model-names/data-warehouse-dropdown.png b/website/static/img/blog/2022-05-17-stakeholder-friendly-model-names/data-warehouse-dropdown.png new file mode 100644 index 00000000000..efc5f9a8eb1 Binary files /dev/null and b/website/static/img/blog/2022-05-17-stakeholder-friendly-model-names/data-warehouse-dropdown.png differ diff --git a/website/static/img/blog/2022-05-17-stakeholder-friendly-model-names/dbt-cloud-ide-folder.png b/website/static/img/blog/2022-05-17-stakeholder-friendly-model-names/dbt-cloud-ide-folder.png new file mode 100644 index 00000000000..5d3b467b35d Binary files /dev/null and b/website/static/img/blog/2022-05-17-stakeholder-friendly-model-names/dbt-cloud-ide-folder.png differ diff --git a/website/static/img/blog/2022-05-17-stakeholder-friendly-model-names/project-view.png b/website/static/img/blog/2022-05-17-stakeholder-friendly-model-names/project-view.png new file mode 100644 index 00000000000..cc574bb114c Binary files /dev/null and b/website/static/img/blog/2022-05-17-stakeholder-friendly-model-names/project-view.png differ diff --git a/website/static/img/blog/2022-05-19-redshift-configurations-dbt-model-optimizations/All-Distribution.png b/website/static/img/blog/2022-05-19-redshift-configurations-dbt-model-optimizations/All-Distribution.png new file mode 100644 index 00000000000..d92e60db2a6 Binary files /dev/null and b/website/static/img/blog/2022-05-19-redshift-configurations-dbt-model-optimizations/All-Distribution.png differ diff --git a/website/static/img/blog/2022-05-19-redshift-configurations-dbt-model-optimizations/All-Joining.gif b/website/static/img/blog/2022-05-19-redshift-configurations-dbt-model-optimizations/All-Joining.gif new file mode 100644 index 00000000000..add5ad6a3ee Binary files /dev/null and b/website/static/img/blog/2022-05-19-redshift-configurations-dbt-model-optimizations/All-Joining.gif differ diff --git a/website/static/img/blog/2022-05-19-redshift-configurations-dbt-model-optimizations/Cluster.png b/website/static/img/blog/2022-05-19-redshift-configurations-dbt-model-optimizations/Cluster.png new file mode 100644 index 00000000000..646ce22fd48 Binary files /dev/null and b/website/static/img/blog/2022-05-19-redshift-configurations-dbt-model-optimizations/Cluster.png differ diff --git a/website/static/img/blog/2022-05-19-redshift-configurations-dbt-model-optimizations/Even-Distribution.png b/website/static/img/blog/2022-05-19-redshift-configurations-dbt-model-optimizations/Even-Distribution.png new file mode 100644 index 00000000000..342db8ec486 Binary files /dev/null and b/website/static/img/blog/2022-05-19-redshift-configurations-dbt-model-optimizations/Even-Distribution.png differ diff --git a/website/static/img/blog/2022-05-19-redshift-configurations-dbt-model-optimizations/Even-Joining.gif b/website/static/img/blog/2022-05-19-redshift-configurations-dbt-model-optimizations/Even-Joining.gif new file mode 100644 index 00000000000..eef74f5fb42 Binary files /dev/null and b/website/static/img/blog/2022-05-19-redshift-configurations-dbt-model-optimizations/Even-Joining.gif differ diff --git a/website/static/img/blog/2022-05-19-redshift-configurations-dbt-model-optimizations/Key-Based-2.png b/website/static/img/blog/2022-05-19-redshift-configurations-dbt-model-optimizations/Key-Based-2.png new file mode 100644 index 00000000000..911d3d4af50 Binary files /dev/null and b/website/static/img/blog/2022-05-19-redshift-configurations-dbt-model-optimizations/Key-Based-2.png differ diff --git a/website/static/img/blog/2022-05-19-redshift-configurations-dbt-model-optimizations/Key-Based-All.gif b/website/static/img/blog/2022-05-19-redshift-configurations-dbt-model-optimizations/Key-Based-All.gif new file mode 100644 index 00000000000..88e0f7f6abd Binary files /dev/null and b/website/static/img/blog/2022-05-19-redshift-configurations-dbt-model-optimizations/Key-Based-All.gif differ diff --git a/website/static/img/blog/2022-05-19-redshift-configurations-dbt-model-optimizations/Key-Based-Even.gif b/website/static/img/blog/2022-05-19-redshift-configurations-dbt-model-optimizations/Key-Based-Even.gif new file mode 100644 index 00000000000..d8b3cda617c Binary files /dev/null and b/website/static/img/blog/2022-05-19-redshift-configurations-dbt-model-optimizations/Key-Based-Even.gif differ diff --git a/website/static/img/blog/2022-05-19-redshift-configurations-dbt-model-optimizations/Key-Based-Joining-2.png b/website/static/img/blog/2022-05-19-redshift-configurations-dbt-model-optimizations/Key-Based-Joining-2.png new file mode 100644 index 00000000000..9daf17cb1da Binary files /dev/null and b/website/static/img/blog/2022-05-19-redshift-configurations-dbt-model-optimizations/Key-Based-Joining-2.png differ diff --git a/website/static/img/blog/2022-05-19-redshift-configurations-dbt-model-optimizations/Key-Based-Joining.gif b/website/static/img/blog/2022-05-19-redshift-configurations-dbt-model-optimizations/Key-Based-Joining.gif new file mode 100644 index 00000000000..04a35bde69e Binary files /dev/null and b/website/static/img/blog/2022-05-19-redshift-configurations-dbt-model-optimizations/Key-Based-Joining.gif differ diff --git a/website/static/img/blog/2022-05-19-redshift-configurations-dbt-model-optimizations/Key-Based.png b/website/static/img/blog/2022-05-19-redshift-configurations-dbt-model-optimizations/Key-Based.png new file mode 100644 index 00000000000..c1800f18651 Binary files /dev/null and b/website/static/img/blog/2022-05-19-redshift-configurations-dbt-model-optimizations/Key-Based.png differ diff --git a/website/static/img/blog/2022-05-19-redshift-configurations-dbt-model-optimizations/Resolve-to-single-key.png b/website/static/img/blog/2022-05-19-redshift-configurations-dbt-model-optimizations/Resolve-to-single-key.png new file mode 100644 index 00000000000..a9686e83ee8 Binary files /dev/null and b/website/static/img/blog/2022-05-19-redshift-configurations-dbt-model-optimizations/Resolve-to-single-key.png differ diff --git a/website/static/img/blog/2022-05-19-redshift-configurations-dbt-model-optimizations/Scanning-Sort.gif b/website/static/img/blog/2022-05-19-redshift-configurations-dbt-model-optimizations/Scanning-Sort.gif new file mode 100644 index 00000000000..f2bdf6c589b Binary files /dev/null and b/website/static/img/blog/2022-05-19-redshift-configurations-dbt-model-optimizations/Scanning-Sort.gif differ diff --git a/website/static/img/blog/2022-05-19-redshift-configurations-dbt-model-optimizations/Sorting.gif b/website/static/img/blog/2022-05-19-redshift-configurations-dbt-model-optimizations/Sorting.gif new file mode 100644 index 00000000000..5353a34a27a Binary files /dev/null and b/website/static/img/blog/2022-05-19-redshift-configurations-dbt-model-optimizations/Sorting.gif differ diff --git a/website/static/img/blog/2022-05-19-redshift-configurations-dbt-model-optimizations/Source-Data.png b/website/static/img/blog/2022-05-19-redshift-configurations-dbt-model-optimizations/Source-Data.png new file mode 100644 index 00000000000..41e3fef5662 Binary files /dev/null and b/website/static/img/blog/2022-05-19-redshift-configurations-dbt-model-optimizations/Source-Data.png differ diff --git a/website/static/img/blog/2022-05-19-redshift-configurations-dbt-model-optimizations/Staggered-Joins.png b/website/static/img/blog/2022-05-19-redshift-configurations-dbt-model-optimizations/Staggered-Joins.png new file mode 100644 index 00000000000..0e256ff7632 Binary files /dev/null and b/website/static/img/blog/2022-05-19-redshift-configurations-dbt-model-optimizations/Staggered-Joins.png differ diff --git a/website/static/img/blog/2022-05-24-joining-snapshot-complexity/backtothefuture.gif b/website/static/img/blog/2022-05-24-joining-snapshot-complexity/backtothefuture.gif new file mode 100644 index 00000000000..b6e35261c21 Binary files /dev/null and b/website/static/img/blog/2022-05-24-joining-snapshot-complexity/backtothefuture.gif differ diff --git a/website/static/img/blog/2022-05-24-joining-snapshot-complexity/clean-data-meme.png b/website/static/img/blog/2022-05-24-joining-snapshot-complexity/clean-data-meme.png new file mode 100644 index 00000000000..048889e0e14 Binary files /dev/null and b/website/static/img/blog/2022-05-24-joining-snapshot-complexity/clean-data-meme.png differ diff --git a/website/static/img/blog/2022-07-12-change-data-capture-metrics/fct-income-dag.png b/website/static/img/blog/2022-07-12-change-data-capture-metrics/fct-income-dag.png new file mode 100644 index 00000000000..861b8591568 Binary files /dev/null and b/website/static/img/blog/2022-07-12-change-data-capture-metrics/fct-income-dag.png differ diff --git a/website/static/img/blog/2022-07-12-change-data-capture-metrics/final-dag.png b/website/static/img/blog/2022-07-12-change-data-capture-metrics/final-dag.png new file mode 100644 index 00000000000..37243ff06dc Binary files /dev/null and b/website/static/img/blog/2022-07-12-change-data-capture-metrics/final-dag.png differ diff --git a/website/static/img/blog/2022-07-12-change-data-capture-metrics/income-meme.png b/website/static/img/blog/2022-07-12-change-data-capture-metrics/income-meme.png new file mode 100644 index 00000000000..4174b3fceb6 Binary files /dev/null and b/website/static/img/blog/2022-07-12-change-data-capture-metrics/income-meme.png differ diff --git a/website/static/img/blog/2022-07-12-change-data-capture-metrics/income-report-versions-dag.png b/website/static/img/blog/2022-07-12-change-data-capture-metrics/income-report-versions-dag.png new file mode 100644 index 00000000000..63eb3400ca6 Binary files /dev/null and b/website/static/img/blog/2022-07-12-change-data-capture-metrics/income-report-versions-dag.png differ diff --git a/website/static/img/blog/2022-07-12-change-data-capture-metrics/int-income-history-dag.png b/website/static/img/blog/2022-07-12-change-data-capture-metrics/int-income-history-dag.png new file mode 100644 index 00000000000..00684a680a2 Binary files /dev/null and b/website/static/img/blog/2022-07-12-change-data-capture-metrics/int-income-history-dag.png differ diff --git a/website/static/img/blog/2022-07-12-change-data-capture-metrics/snapshots-dag.png b/website/static/img/blog/2022-07-12-change-data-capture-metrics/snapshots-dag.png new file mode 100644 index 00000000000..801331f7057 Binary files /dev/null and b/website/static/img/blog/2022-07-12-change-data-capture-metrics/snapshots-dag.png differ diff --git a/website/static/img/blog/2022-07-13-star-sql-love-letter/star-is-born.jpg b/website/static/img/blog/2022-07-13-star-sql-love-letter/star-is-born.jpg new file mode 100644 index 00000000000..53192f53206 Binary files /dev/null and b/website/static/img/blog/2022-07-13-star-sql-love-letter/star-is-born.jpg differ diff --git a/website/static/img/blog/2022-07-13-star-sql-love-letter/utils-madness-1.png b/website/static/img/blog/2022-07-13-star-sql-love-letter/utils-madness-1.png new file mode 100644 index 00000000000..faf078cd2bc Binary files /dev/null and b/website/static/img/blog/2022-07-13-star-sql-love-letter/utils-madness-1.png differ diff --git a/website/static/img/blog/2022-07-13-star-sql-love-letter/utils-madness-2.png b/website/static/img/blog/2022-07-13-star-sql-love-letter/utils-madness-2.png new file mode 100644 index 00000000000..94b99f28a8c Binary files /dev/null and b/website/static/img/blog/2022-07-13-star-sql-love-letter/utils-madness-2.png differ diff --git a/website/static/img/blog/2022-07-19-migrating-from-stored-procs/dbt-approach-model.png b/website/static/img/blog/2022-07-19-migrating-from-stored-procs/dbt-approach-model.png new file mode 100644 index 00000000000..66b85b343cc Binary files /dev/null and b/website/static/img/blog/2022-07-19-migrating-from-stored-procs/dbt-approach-model.png differ diff --git a/website/static/img/blog/2022-07-19-migrating-from-stored-procs/dbt-diagram.png b/website/static/img/blog/2022-07-19-migrating-from-stored-procs/dbt-diagram.png new file mode 100644 index 00000000000..37d3ed910bd Binary files /dev/null and b/website/static/img/blog/2022-07-19-migrating-from-stored-procs/dbt-diagram.png differ diff --git a/website/static/img/blog/2022-07-19-migrating-from-stored-procs/stored-procs-diagram.png b/website/static/img/blog/2022-07-19-migrating-from-stored-procs/stored-procs-diagram.png new file mode 100644 index 00000000000..b24faaeab4c Binary files /dev/null and b/website/static/img/blog/2022-07-19-migrating-from-stored-procs/stored-procs-diagram.png differ diff --git a/website/static/img/blog/2022-07-26-pre-commit-dbt/checks-failed.png b/website/static/img/blog/2022-07-26-pre-commit-dbt/checks-failed.png new file mode 100644 index 00000000000..a4d116e2f1e Binary files /dev/null and b/website/static/img/blog/2022-07-26-pre-commit-dbt/checks-failed.png differ diff --git a/website/static/img/blog/2022-07-26-pre-commit-dbt/customers-model.png b/website/static/img/blog/2022-07-26-pre-commit-dbt/customers-model.png new file mode 100644 index 00000000000..a5bc90b8483 Binary files /dev/null and b/website/static/img/blog/2022-07-26-pre-commit-dbt/customers-model.png differ diff --git a/website/static/img/blog/2022-07-26-pre-commit-dbt/define-strategy.png b/website/static/img/blog/2022-07-26-pre-commit-dbt/define-strategy.png new file mode 100644 index 00000000000..29c9ec6b7ce Binary files /dev/null and b/website/static/img/blog/2022-07-26-pre-commit-dbt/define-strategy.png differ diff --git a/website/static/img/blog/2022-07-26-pre-commit-dbt/error-logs.png b/website/static/img/blog/2022-07-26-pre-commit-dbt/error-logs.png new file mode 100644 index 00000000000..e4118d11598 Binary files /dev/null and b/website/static/img/blog/2022-07-26-pre-commit-dbt/error-logs.png differ diff --git a/website/static/img/blog/2022-07-26-pre-commit-dbt/install-pre-commit.png b/website/static/img/blog/2022-07-26-pre-commit-dbt/install-pre-commit.png new file mode 100644 index 00000000000..53b80639266 Binary files /dev/null and b/website/static/img/blog/2022-07-26-pre-commit-dbt/install-pre-commit.png differ diff --git a/website/static/img/blog/2022-07-26-pre-commit-dbt/next-strategy.png b/website/static/img/blog/2022-07-26-pre-commit-dbt/next-strategy.png new file mode 100644 index 00000000000..e55aed176df Binary files /dev/null and b/website/static/img/blog/2022-07-26-pre-commit-dbt/next-strategy.png differ diff --git a/website/static/img/blog/2022-07-26-pre-commit-dbt/testing-running.png b/website/static/img/blog/2022-07-26-pre-commit-dbt/testing-running.png new file mode 100644 index 00000000000..f1980332db0 Binary files /dev/null and b/website/static/img/blog/2022-07-26-pre-commit-dbt/testing-running.png differ diff --git a/website/static/img/blog/2022-07-26-pre-commit-dbt/why-not-both-meme.png b/website/static/img/blog/2022-07-26-pre-commit-dbt/why-not-both-meme.png new file mode 100644 index 00000000000..e388c5ced80 Binary files /dev/null and b/website/static/img/blog/2022-07-26-pre-commit-dbt/why-not-both-meme.png differ diff --git a/website/static/img/blog/2022-07-27-getting-started-with-the-dbt-semantic-layer/crypto-meme.png b/website/static/img/blog/2022-07-27-getting-started-with-the-dbt-semantic-layer/crypto-meme.png new file mode 100644 index 00000000000..605d97a38e7 Binary files /dev/null and b/website/static/img/blog/2022-07-27-getting-started-with-the-dbt-semantic-layer/crypto-meme.png differ diff --git a/website/static/img/blog/2022-07-27-getting-started-with-the-dbt-semantic-layer/metrics-dag.png b/website/static/img/blog/2022-07-27-getting-started-with-the-dbt-semantic-layer/metrics-dag.png new file mode 100644 index 00000000000..71218089305 Binary files /dev/null and b/website/static/img/blog/2022-07-27-getting-started-with-the-dbt-semantic-layer/metrics-dag.png differ diff --git a/website/static/img/blog/2022-07-27-getting-started-with-the-dbt-semantic-layer/semantic-layer-description.png b/website/static/img/blog/2022-07-27-getting-started-with-the-dbt-semantic-layer/semantic-layer-description.png new file mode 100644 index 00000000000..b01b2b619b6 Binary files /dev/null and b/website/static/img/blog/2022-07-27-getting-started-with-the-dbt-semantic-layer/semantic-layer-description.png differ diff --git a/website/static/img/blog/2022-08-12-model-timing/model_timing_after.png b/website/static/img/blog/2022-08-12-model-timing/model_timing_after.png new file mode 100644 index 00000000000..2d9cdd12db1 Binary files /dev/null and b/website/static/img/blog/2022-08-12-model-timing/model_timing_after.png differ diff --git a/website/static/img/blog/2022-08-12-model-timing/model_timing_before.png b/website/static/img/blog/2022-08-12-model-timing/model_timing_before.png new file mode 100644 index 00000000000..d55ed331227 Binary files /dev/null and b/website/static/img/blog/2022-08-12-model-timing/model_timing_before.png differ diff --git a/website/static/img/blog/2022-08-12-model-timing/snowflake_query_plan.png b/website/static/img/blog/2022-08-12-model-timing/snowflake_query_plan.png new file mode 100644 index 00000000000..f4c4502ce05 Binary files /dev/null and b/website/static/img/blog/2022-08-12-model-timing/snowflake_query_plan.png differ diff --git a/website/static/img/blog/2022-08-22-narrative-modeling/dimensional-modeling-dag.png b/website/static/img/blog/2022-08-22-narrative-modeling/dimensional-modeling-dag.png new file mode 100644 index 00000000000..43fdef2796d Binary files /dev/null and b/website/static/img/blog/2022-08-22-narrative-modeling/dimensional-modeling-dag.png differ diff --git a/website/static/img/blog/2022-08-22-narrative-modeling/narrative-modeling-dag.png b/website/static/img/blog/2022-08-22-narrative-modeling/narrative-modeling-dag.png new file mode 100644 index 00000000000..658d59a1607 Binary files /dev/null and b/website/static/img/blog/2022-08-22-narrative-modeling/narrative-modeling-dag.png differ diff --git a/website/static/img/blog/2022-09-07-leverage-accounting-principles-when-financial-modeling/captain-planet-combine.gif b/website/static/img/blog/2022-09-07-leverage-accounting-principles-when-financial-modeling/captain-planet-combine.gif new file mode 100644 index 00000000000..d37d6c4d9c0 Binary files /dev/null and b/website/static/img/blog/2022-09-07-leverage-accounting-principles-when-financial-modeling/captain-planet-combine.gif differ diff --git a/website/static/img/blog/2022-09-07-leverage-accounting-principles-when-financial-modeling/crown-adjustment.gif b/website/static/img/blog/2022-09-07-leverage-accounting-principles-when-financial-modeling/crown-adjustment.gif new file mode 100644 index 00000000000..0874301461b Binary files /dev/null and b/website/static/img/blog/2022-09-07-leverage-accounting-principles-when-financial-modeling/crown-adjustment.gif differ diff --git a/website/static/img/blog/2022-09-07-leverage-accounting-principles-when-financial-modeling/devil-prada-glacial-pace.gif b/website/static/img/blog/2022-09-07-leverage-accounting-principles-when-financial-modeling/devil-prada-glacial-pace.gif new file mode 100644 index 00000000000..32a1be8c683 Binary files /dev/null and b/website/static/img/blog/2022-09-07-leverage-accounting-principles-when-financial-modeling/devil-prada-glacial-pace.gif differ diff --git a/website/static/img/blog/2022-09-07-leverage-accounting-principles-when-financial-modeling/hobbit-adventure.gif b/website/static/img/blog/2022-09-07-leverage-accounting-principles-when-financial-modeling/hobbit-adventure.gif new file mode 100644 index 00000000000..842462a5e03 Binary files /dev/null and b/website/static/img/blog/2022-09-07-leverage-accounting-principles-when-financial-modeling/hobbit-adventure.gif differ diff --git a/website/static/img/blog/2022-09-07-leverage-accounting-principles-when-financial-modeling/office-its-a-date.gif b/website/static/img/blog/2022-09-07-leverage-accounting-principles-when-financial-modeling/office-its-a-date.gif new file mode 100644 index 00000000000..a075798764b Binary files /dev/null and b/website/static/img/blog/2022-09-07-leverage-accounting-principles-when-financial-modeling/office-its-a-date.gif differ diff --git a/website/static/img/blog/2022-09-07-leverage-accounting-principles-when-financial-modeling/parks-and-rec-ben-wyatt.gif b/website/static/img/blog/2022-09-07-leverage-accounting-principles-when-financial-modeling/parks-and-rec-ben-wyatt.gif new file mode 100644 index 00000000000..4c481bb9ce4 Binary files /dev/null and b/website/static/img/blog/2022-09-07-leverage-accounting-principles-when-financial-modeling/parks-and-rec-ben-wyatt.gif differ diff --git a/website/static/img/blog/2022-09-07-leverage-accounting-principles-when-financial-modeling/supranos-bada-bing.gif b/website/static/img/blog/2022-09-07-leverage-accounting-principles-when-financial-modeling/supranos-bada-bing.gif new file mode 100644 index 00000000000..4e20e2bbad6 Binary files /dev/null and b/website/static/img/blog/2022-09-07-leverage-accounting-principles-when-financial-modeling/supranos-bada-bing.gif differ diff --git a/website/static/img/blog/2022-09-07-leverage-accounting-principles-when-financial-modeling/supranos-boom.gif b/website/static/img/blog/2022-09-07-leverage-accounting-principles-when-financial-modeling/supranos-boom.gif new file mode 100644 index 00000000000..328dddea3f6 Binary files /dev/null and b/website/static/img/blog/2022-09-07-leverage-accounting-principles-when-financial-modeling/supranos-boom.gif differ diff --git a/website/static/img/blog/2022-09-07-leverage-accounting-principles-when-financial-modeling/top-gun-classified.gif b/website/static/img/blog/2022-09-07-leverage-accounting-principles-when-financial-modeling/top-gun-classified.gif new file mode 100644 index 00000000000..b4bcaab77fa Binary files /dev/null and b/website/static/img/blog/2022-09-07-leverage-accounting-principles-when-financial-modeling/top-gun-classified.gif differ diff --git a/website/static/img/blog/2022-09-08-konmari-your-query-migration/buried-in-boxes.webp b/website/static/img/blog/2022-09-08-konmari-your-query-migration/buried-in-boxes.webp new file mode 100644 index 00000000000..5833eaa437d Binary files /dev/null and b/website/static/img/blog/2022-09-08-konmari-your-query-migration/buried-in-boxes.webp differ diff --git a/website/static/img/blog/2022-09-08-konmari-your-query-migration/cat_kitchen.jpeg b/website/static/img/blog/2022-09-08-konmari-your-query-migration/cat_kitchen.jpeg new file mode 100644 index 00000000000..de74601dce2 Binary files /dev/null and b/website/static/img/blog/2022-09-08-konmari-your-query-migration/cat_kitchen.jpeg differ diff --git a/website/static/img/blog/2022-09-08-konmari-your-query-migration/fully-konmarid-project.png b/website/static/img/blog/2022-09-08-konmari-your-query-migration/fully-konmarid-project.png new file mode 100644 index 00000000000..f89659f26a0 Binary files /dev/null and b/website/static/img/blog/2022-09-08-konmari-your-query-migration/fully-konmarid-project.png differ diff --git a/website/static/img/blog/2022-09-08-konmari-your-query-migration/many-to-one-dag.png b/website/static/img/blog/2022-09-08-konmari-your-query-migration/many-to-one-dag.png new file mode 100644 index 00000000000..5b8240b58d8 Binary files /dev/null and b/website/static/img/blog/2022-09-08-konmari-your-query-migration/many-to-one-dag.png differ diff --git a/website/static/img/blog/2022-09-08-konmari-your-query-migration/mariekondo.gif b/website/static/img/blog/2022-09-08-konmari-your-query-migration/mariekondo.gif new file mode 100644 index 00000000000..7ff20dd33b6 Binary files /dev/null and b/website/static/img/blog/2022-09-08-konmari-your-query-migration/mariekondo.gif differ diff --git a/website/static/img/blog/2022-09-08-konmari-your-query-migration/nachka-cat.gif b/website/static/img/blog/2022-09-08-konmari-your-query-migration/nachka-cat.gif new file mode 100644 index 00000000000..ab69c07942f Binary files /dev/null and b/website/static/img/blog/2022-09-08-konmari-your-query-migration/nachka-cat.gif differ diff --git a/website/static/img/blog/2022-09-08-konmari-your-query-migration/spaghetti-data-dag.png b/website/static/img/blog/2022-09-08-konmari-your-query-migration/spaghetti-data-dag.png new file mode 100644 index 00000000000..e7ef3a5f0ea Binary files /dev/null and b/website/static/img/blog/2022-09-08-konmari-your-query-migration/spaghetti-data-dag.png differ diff --git a/website/static/img/blog/2022-09-13-the-case-against-cherry-picking/1_basic_git_workflow.png b/website/static/img/blog/2022-09-13-the-case-against-cherry-picking/1_basic_git_workflow.png new file mode 100644 index 00000000000..a734fb92f9c Binary files /dev/null and b/website/static/img/blog/2022-09-13-the-case-against-cherry-picking/1_basic_git_workflow.png differ diff --git a/website/static/img/blog/2022-09-13-the-case-against-cherry-picking/2_multienvironment.png b/website/static/img/blog/2022-09-13-the-case-against-cherry-picking/2_multienvironment.png new file mode 100644 index 00000000000..f3bd1a71aeb Binary files /dev/null and b/website/static/img/blog/2022-09-13-the-case-against-cherry-picking/2_multienvironment.png differ diff --git a/website/static/img/blog/2022-09-13-the-case-against-cherry-picking/3_gru.jpg b/website/static/img/blog/2022-09-13-the-case-against-cherry-picking/3_gru.jpg new file mode 100644 index 00000000000..2d330a868cc Binary files /dev/null and b/website/static/img/blog/2022-09-13-the-case-against-cherry-picking/3_gru.jpg differ diff --git a/website/static/img/blog/2022-09-13-the-case-against-cherry-picking/4_scenario_1.png b/website/static/img/blog/2022-09-13-the-case-against-cherry-picking/4_scenario_1.png new file mode 100644 index 00000000000..257ce91b010 Binary files /dev/null and b/website/static/img/blog/2022-09-13-the-case-against-cherry-picking/4_scenario_1.png differ diff --git a/website/static/img/blog/2022-09-13-the-case-against-cherry-picking/5_scenario_2.png b/website/static/img/blog/2022-09-13-the-case-against-cherry-picking/5_scenario_2.png new file mode 100644 index 00000000000..4b381c26155 Binary files /dev/null and b/website/static/img/blog/2022-09-13-the-case-against-cherry-picking/5_scenario_2.png differ diff --git a/website/static/img/blog/2022-09-13-the-case-against-cherry-picking/6_scenario_3.png b/website/static/img/blog/2022-09-13-the-case-against-cherry-picking/6_scenario_3.png new file mode 100644 index 00000000000..35d6cd99d8f Binary files /dev/null and b/website/static/img/blog/2022-09-13-the-case-against-cherry-picking/6_scenario_3.png differ diff --git a/website/static/img/blog/2022-09-13-the-case-against-cherry-picking/7_bernie.jpg b/website/static/img/blog/2022-09-13-the-case-against-cherry-picking/7_bernie.jpg new file mode 100644 index 00000000000..f849471786e Binary files /dev/null and b/website/static/img/blog/2022-09-13-the-case-against-cherry-picking/7_bernie.jpg differ diff --git a/website/static/img/blog/2022-09-28-analyst-to-ae/first_loop.png b/website/static/img/blog/2022-09-28-analyst-to-ae/first_loop.png new file mode 100644 index 00000000000..a5ab1b0f89c Binary files /dev/null and b/website/static/img/blog/2022-09-28-analyst-to-ae/first_loop.png differ diff --git a/website/static/img/blog/2022-09-28-analyst-to-ae/multiple_loops.png b/website/static/img/blog/2022-09-28-analyst-to-ae/multiple_loops.png new file mode 100644 index 00000000000..e37a0d8dd21 Binary files /dev/null and b/website/static/img/blog/2022-09-28-analyst-to-ae/multiple_loops.png differ diff --git a/website/static/img/blog/2022-09-28-analyst-to-ae/new_workflow.png b/website/static/img/blog/2022-09-28-analyst-to-ae/new_workflow.png new file mode 100644 index 00000000000..e2ddb7da352 Binary files /dev/null and b/website/static/img/blog/2022-09-28-analyst-to-ae/new_workflow.png differ diff --git a/website/static/img/blog/2022-09-28-analyst-to-ae/old_workflow.png b/website/static/img/blog/2022-09-28-analyst-to-ae/old_workflow.png new file mode 100644 index 00000000000..a2e10841b6a Binary files /dev/null and b/website/static/img/blog/2022-09-28-analyst-to-ae/old_workflow.png differ diff --git a/website/static/img/blog/airflow-dbt-dashboard.png b/website/static/img/blog/airflow-dbt-dashboard.png new file mode 100644 index 00000000000..3d7c99f3260 Binary files /dev/null and b/website/static/img/blog/airflow-dbt-dashboard.png differ diff --git a/website/static/img/blog/airflow-dbt-run-log.png b/website/static/img/blog/airflow-dbt-run-log.png new file mode 100644 index 00000000000..5c7f31f3a96 Binary files /dev/null and b/website/static/img/blog/airflow-dbt-run-log.png differ diff --git a/website/static/img/blog/airflow-dbt-skills.png b/website/static/img/blog/airflow-dbt-skills.png new file mode 100644 index 00000000000..fffb2ff39aa Binary files /dev/null and b/website/static/img/blog/airflow-dbt-skills.png differ diff --git a/website/static/img/blog/analyst-ux-twitter.png b/website/static/img/blog/analyst-ux-twitter.png new file mode 100644 index 00000000000..a2423b26b08 Binary files /dev/null and b/website/static/img/blog/analyst-ux-twitter.png differ diff --git a/website/static/img/blog/analyst-ux-weather.png b/website/static/img/blog/analyst-ux-weather.png new file mode 100644 index 00000000000..c0d2991abce Binary files /dev/null and b/website/static/img/blog/analyst-ux-weather.png differ diff --git a/website/static/img/blog/authors/achen.png b/website/static/img/blog/authors/achen.png new file mode 100644 index 00000000000..6133c1948a0 Binary files /dev/null and b/website/static/img/blog/authors/achen.png differ diff --git a/website/static/img/blog/authors/aescay.jpeg b/website/static/img/blog/authors/aescay.jpeg new file mode 100644 index 00000000000..59d285da3da Binary files /dev/null and b/website/static/img/blog/authors/aescay.jpeg differ diff --git a/website/static/img/blog/authors/barr-yaron.png b/website/static/img/blog/authors/barr-yaron.png new file mode 100644 index 00000000000..558bb00c8d8 Binary files /dev/null and b/website/static/img/blog/authors/barr-yaron.png differ diff --git a/website/static/img/blog/authors/bennie-regenold.png b/website/static/img/blog/authors/bennie-regenold.png new file mode 100644 index 00000000000..ce74b1de9f9 Binary files /dev/null and b/website/static/img/blog/authors/bennie-regenold.png differ diff --git a/website/static/img/blog/authors/benoit-perigaud.jpeg b/website/static/img/blog/authors/benoit-perigaud.jpeg new file mode 100644 index 00000000000..e4106464475 Binary files /dev/null and b/website/static/img/blog/authors/benoit-perigaud.jpeg differ diff --git a/website/static/img/blog/authors/brittany-krauth.png b/website/static/img/blog/authors/brittany-krauth.png new file mode 100644 index 00000000000..da413820fbc Binary files /dev/null and b/website/static/img/blog/authors/brittany-krauth.png differ diff --git a/website/static/img/blog/authors/callum-mccann.jpg b/website/static/img/blog/authors/callum-mccann.jpg new file mode 100644 index 00000000000..3dd05c6cb90 Binary files /dev/null and b/website/static/img/blog/authors/callum-mccann.jpg differ diff --git a/website/static/img/blog/authors/christine-berger.jpeg b/website/static/img/blog/authors/christine-berger.jpeg new file mode 100644 index 00000000000..660492ffad1 Binary files /dev/null and b/website/static/img/blog/authors/christine-berger.jpeg differ diff --git a/website/static/img/blog/authors/claire.jpeg b/website/static/img/blog/authors/claire.jpeg new file mode 100644 index 00000000000..57843b618e2 Binary files /dev/null and b/website/static/img/blog/authors/claire.jpeg differ diff --git a/website/static/img/blog/authors/craigie.png b/website/static/img/blog/authors/craigie.png new file mode 100644 index 00000000000..378e8630302 Binary files /dev/null and b/website/static/img/blog/authors/craigie.png differ diff --git a/website/static/img/blog/authors/dbeatty.jpeg b/website/static/img/blog/authors/dbeatty.jpeg new file mode 100644 index 00000000000..34c027ea308 Binary files /dev/null and b/website/static/img/blog/authors/dbeatty.jpeg differ diff --git a/website/static/img/blog/authors/dconnors.jpeg b/website/static/img/blog/authors/dconnors.jpeg new file mode 100644 index 00000000000..15e3ca88895 Binary files /dev/null and b/website/static/img/blog/authors/dconnors.jpeg differ diff --git a/website/static/img/blog/authors/dflynn.jpeg b/website/static/img/blog/authors/dflynn.jpeg new file mode 100644 index 00000000000..b5308252916 Binary files /dev/null and b/website/static/img/blog/authors/dflynn.jpeg differ diff --git a/website/static/img/blog/authors/dkrevitt.jpg b/website/static/img/blog/authors/dkrevitt.jpg new file mode 100644 index 00000000000..21ad3fb38a7 Binary files /dev/null and b/website/static/img/blog/authors/dkrevitt.jpg differ diff --git a/website/static/img/blog/authors/grace-goheen.jpeg b/website/static/img/blog/authors/grace-goheen.jpeg new file mode 100644 index 00000000000..06b059b08cb Binary files /dev/null and b/website/static/img/blog/authors/grace-goheen.jpeg differ diff --git a/website/static/img/blog/authors/ian-fahey.png b/website/static/img/blog/authors/ian-fahey.png new file mode 100644 index 00000000000..5d2bd2a0ff4 Binary files /dev/null and b/website/static/img/blog/authors/ian-fahey.png differ diff --git a/website/static/img/blog/authors/izzy.jpeg b/website/static/img/blog/authors/izzy.jpeg new file mode 100644 index 00000000000..53a1ae9faff Binary files /dev/null and b/website/static/img/blog/authors/izzy.jpeg differ diff --git a/website/static/img/blog/authors/jasnonaz.jpeg b/website/static/img/blog/authors/jasnonaz.jpeg new file mode 100644 index 00000000000..489bb061a0d Binary files /dev/null and b/website/static/img/blog/authors/jasnonaz.jpeg differ diff --git a/website/static/img/blog/authors/jerco.jpeg b/website/static/img/blog/authors/jerco.jpeg new file mode 100644 index 00000000000..c19b58bcd61 Binary files /dev/null and b/website/static/img/blog/authors/jerco.jpeg differ diff --git a/website/static/img/blog/authors/jess.png b/website/static/img/blog/authors/jess.png new file mode 100644 index 00000000000..20fe773a5c6 Binary files /dev/null and b/website/static/img/blog/authors/jess.png differ diff --git a/website/static/img/blog/authors/jlabes.png b/website/static/img/blog/authors/jlabes.png new file mode 100644 index 00000000000..2f74a8eeb75 Binary files /dev/null and b/website/static/img/blog/authors/jlabes.png differ diff --git a/website/static/img/blog/authors/joe-markiewicz.jpeg b/website/static/img/blog/authors/joe-markiewicz.jpeg new file mode 100644 index 00000000000..0531255fbda Binary files /dev/null and b/website/static/img/blog/authors/joe-markiewicz.jpeg differ diff --git a/website/static/img/blog/authors/jonathan-natkins.jpeg b/website/static/img/blog/authors/jonathan-natkins.jpeg new file mode 100644 index 00000000000..6eb69ca30ce Binary files /dev/null and b/website/static/img/blog/authors/jonathan-natkins.jpeg differ diff --git a/website/static/img/blog/authors/josh-fell.jpeg b/website/static/img/blog/authors/josh-fell.jpeg new file mode 100644 index 00000000000..3978846ca71 Binary files /dev/null and b/website/static/img/blog/authors/josh-fell.jpeg differ diff --git a/website/static/img/blog/authors/kira-furuichi.png b/website/static/img/blog/authors/kira-furuichi.png new file mode 100644 index 00000000000..e17cc4648bc Binary files /dev/null and b/website/static/img/blog/authors/kira-furuichi.png differ diff --git a/website/static/img/blog/authors/lauren-benezra.jpeg b/website/static/img/blog/authors/lauren-benezra.jpeg new file mode 100644 index 00000000000..77570e4dcb0 Binary files /dev/null and b/website/static/img/blog/authors/lauren-benezra.jpeg differ diff --git a/website/static/img/blog/authors/matt-winkler.jpeg b/website/static/img/blog/authors/matt-winkler.jpeg new file mode 100644 index 00000000000..0a086054605 Binary files /dev/null and b/website/static/img/blog/authors/matt-winkler.jpeg differ diff --git a/website/static/img/blog/authors/nate-sooter.jpeg b/website/static/img/blog/authors/nate-sooter.jpeg new file mode 100644 index 00000000000..95aa28fb7a7 Binary files /dev/null and b/website/static/img/blog/authors/nate-sooter.jpeg differ diff --git a/website/static/img/blog/authors/pkearns.png b/website/static/img/blog/authors/pkearns.png new file mode 100644 index 00000000000..53ff603833b Binary files /dev/null and b/website/static/img/blog/authors/pkearns.png differ diff --git a/website/static/img/blog/authors/ross-turk.png b/website/static/img/blog/authors/ross-turk.png new file mode 100644 index 00000000000..e612601cc04 Binary files /dev/null and b/website/static/img/blog/authors/ross-turk.png differ diff --git a/website/static/img/blog/authors/sanjana.png b/website/static/img/blog/authors/sanjana.png new file mode 100644 index 00000000000..ebf59473997 Binary files /dev/null and b/website/static/img/blog/authors/sanjana.png differ diff --git a/website/static/img/blog/authors/seth-rosen.jpeg b/website/static/img/blog/authors/seth-rosen.jpeg new file mode 100644 index 00000000000..cff5a4164c0 Binary files /dev/null and b/website/static/img/blog/authors/seth-rosen.jpeg differ diff --git a/website/static/img/blog/authors/simo-tumelius.jpeg b/website/static/img/blog/authors/simo-tumelius.jpeg new file mode 100644 index 00000000000..cef0713c587 Binary files /dev/null and b/website/static/img/blog/authors/simo-tumelius.jpeg differ diff --git a/website/static/img/blog/authors/simon-podhajsky.jpeg b/website/static/img/blog/authors/simon-podhajsky.jpeg new file mode 100644 index 00000000000..f69f3f4e30f Binary files /dev/null and b/website/static/img/blog/authors/simon-podhajsky.jpeg differ diff --git a/website/static/img/blog/authors/sung.jpeg b/website/static/img/blog/authors/sung.jpeg new file mode 100644 index 00000000000..a1cd91ccb70 Binary files /dev/null and b/website/static/img/blog/authors/sung.jpeg differ diff --git a/website/static/img/blog/authors/viraj-parekh.jpeg b/website/static/img/blog/authors/viraj-parekh.jpeg new file mode 100644 index 00000000000..946dc40fe7e Binary files /dev/null and b/website/static/img/blog/authors/viraj-parekh.jpeg differ diff --git a/website/static/img/blog/authors/yu-ishikawa.jpg b/website/static/img/blog/authors/yu-ishikawa.jpg new file mode 100644 index 00000000000..d236b8403f9 Binary files /dev/null and b/website/static/img/blog/authors/yu-ishikawa.jpg differ diff --git a/website/static/img/blog/building-a-mature-dbt-project-from-scratch/image_0.png b/website/static/img/blog/building-a-mature-dbt-project-from-scratch/image_0.png new file mode 100644 index 00000000000..9f621f540bc Binary files /dev/null and b/website/static/img/blog/building-a-mature-dbt-project-from-scratch/image_0.png differ diff --git a/website/static/img/blog/building-a-mature-dbt-project-from-scratch/image_1.png b/website/static/img/blog/building-a-mature-dbt-project-from-scratch/image_1.png new file mode 100644 index 00000000000..f2c435eccb0 Binary files /dev/null and b/website/static/img/blog/building-a-mature-dbt-project-from-scratch/image_1.png differ diff --git a/website/static/img/blog/building-a-mature-dbt-project-from-scratch/image_10.png b/website/static/img/blog/building-a-mature-dbt-project-from-scratch/image_10.png new file mode 100644 index 00000000000..1af605ff3b6 Binary files /dev/null and b/website/static/img/blog/building-a-mature-dbt-project-from-scratch/image_10.png differ diff --git a/website/static/img/blog/building-a-mature-dbt-project-from-scratch/image_2.png b/website/static/img/blog/building-a-mature-dbt-project-from-scratch/image_2.png new file mode 100644 index 00000000000..a77ce8e56ae Binary files /dev/null and b/website/static/img/blog/building-a-mature-dbt-project-from-scratch/image_2.png differ diff --git a/website/static/img/blog/building-a-mature-dbt-project-from-scratch/image_3.png b/website/static/img/blog/building-a-mature-dbt-project-from-scratch/image_3.png new file mode 100644 index 00000000000..07e8dfde2e7 Binary files /dev/null and b/website/static/img/blog/building-a-mature-dbt-project-from-scratch/image_3.png differ diff --git a/website/static/img/blog/building-a-mature-dbt-project-from-scratch/image_4.png b/website/static/img/blog/building-a-mature-dbt-project-from-scratch/image_4.png new file mode 100644 index 00000000000..68919c660dc Binary files /dev/null and b/website/static/img/blog/building-a-mature-dbt-project-from-scratch/image_4.png differ diff --git a/website/static/img/blog/building-a-mature-dbt-project-from-scratch/image_5.png b/website/static/img/blog/building-a-mature-dbt-project-from-scratch/image_5.png new file mode 100644 index 00000000000..31024e38e2d Binary files /dev/null and b/website/static/img/blog/building-a-mature-dbt-project-from-scratch/image_5.png differ diff --git a/website/static/img/blog/building-a-mature-dbt-project-from-scratch/image_6.png b/website/static/img/blog/building-a-mature-dbt-project-from-scratch/image_6.png new file mode 100644 index 00000000000..23134a5f190 Binary files /dev/null and b/website/static/img/blog/building-a-mature-dbt-project-from-scratch/image_6.png differ diff --git a/website/static/img/blog/building-a-mature-dbt-project-from-scratch/image_7.png b/website/static/img/blog/building-a-mature-dbt-project-from-scratch/image_7.png new file mode 100644 index 00000000000..0d38e8f5d43 Binary files /dev/null and b/website/static/img/blog/building-a-mature-dbt-project-from-scratch/image_7.png differ diff --git a/website/static/img/blog/building-a-mature-dbt-project-from-scratch/image_8.png b/website/static/img/blog/building-a-mature-dbt-project-from-scratch/image_8.png new file mode 100644 index 00000000000..9c0dfde2f6f Binary files /dev/null and b/website/static/img/blog/building-a-mature-dbt-project-from-scratch/image_8.png differ diff --git a/website/static/img/blog/building-a-mature-dbt-project-from-scratch/image_9.png b/website/static/img/blog/building-a-mature-dbt-project-from-scratch/image_9.png new file mode 100644 index 00000000000..9f5fe8615e9 Binary files /dev/null and b/website/static/img/blog/building-a-mature-dbt-project-from-scratch/image_9.png differ diff --git a/website/static/img/blog/checklist-0532fd13a7d63e3e5df71d025700c4d9c158a7ff_2_517x155.jpeg b/website/static/img/blog/checklist-0532fd13a7d63e3e5df71d025700c4d9c158a7ff_2_517x155.jpeg new file mode 100644 index 00000000000..7157f34582b Binary files /dev/null and b/website/static/img/blog/checklist-0532fd13a7d63e3e5df71d025700c4d9c158a7ff_2_517x155.jpeg differ diff --git a/website/static/img/blog/checklist-28c75101367e272fbc2db2ebb1a1ec030517bb5e_2_517x250.jpeg b/website/static/img/blog/checklist-28c75101367e272fbc2db2ebb1a1ec030517bb5e_2_517x250.jpeg new file mode 100644 index 00000000000..bcb95a92b2f Binary files /dev/null and b/website/static/img/blog/checklist-28c75101367e272fbc2db2ebb1a1ec030517bb5e_2_517x250.jpeg differ diff --git a/website/static/img/blog/checklist-33fcd7c4922233412d1364b39227c876d0cb8215_2_517x111.jpeg b/website/static/img/blog/checklist-33fcd7c4922233412d1364b39227c876d0cb8215_2_517x111.jpeg new file mode 100644 index 00000000000..12d8f5c0c6a Binary files /dev/null and b/website/static/img/blog/checklist-33fcd7c4922233412d1364b39227c876d0cb8215_2_517x111.jpeg differ diff --git a/website/static/img/blog/checklist-5d8ad45deb695eb6771003e010b242c0a3c122b9_2_517x220.jpeg b/website/static/img/blog/checklist-5d8ad45deb695eb6771003e010b242c0a3c122b9_2_517x220.jpeg new file mode 100644 index 00000000000..46a041b200e Binary files /dev/null and b/website/static/img/blog/checklist-5d8ad45deb695eb6771003e010b242c0a3c122b9_2_517x220.jpeg differ diff --git a/website/static/img/blog/checklist-8ddc2f76de24c98690ef986dcc7974bff09adb59.png b/website/static/img/blog/checklist-8ddc2f76de24c98690ef986dcc7974bff09adb59.png new file mode 100644 index 00000000000..dee3ff17b5d Binary files /dev/null and b/website/static/img/blog/checklist-8ddc2f76de24c98690ef986dcc7974bff09adb59.png differ diff --git a/website/static/img/blog/checklist-acd57c0e781b1eaf75a65b5063f97ac3ddc5c493_2_517x136.jpeg b/website/static/img/blog/checklist-acd57c0e781b1eaf75a65b5063f97ac3ddc5c493_2_517x136.jpeg new file mode 100644 index 00000000000..7ddfd86a884 Binary files /dev/null and b/website/static/img/blog/checklist-acd57c0e781b1eaf75a65b5063f97ac3ddc5c493_2_517x136.jpeg differ diff --git a/website/static/img/blog/checklist-on-run-end.png b/website/static/img/blog/checklist-on-run-end.png new file mode 100644 index 00000000000..4dda3acdcd0 Binary files /dev/null and b/website/static/img/blog/checklist-on-run-end.png differ diff --git a/website/static/img/blog/community-growth-dashboard.png b/website/static/img/blog/community-growth-dashboard.png new file mode 100644 index 00000000000..e37c8b70d2b Binary files /dev/null and b/website/static/img/blog/community-growth-dashboard.png differ diff --git a/website/static/img/blog/community-growth-marquez.png b/website/static/img/blog/community-growth-marquez.png new file mode 100644 index 00000000000..918add3853f Binary files /dev/null and b/website/static/img/blog/community-growth-marquez.png differ diff --git a/website/static/img/blog/community-growth-trend.png b/website/static/img/blog/community-growth-trend.png new file mode 100644 index 00000000000..3f793a46ad8 Binary files /dev/null and b/website/static/img/blog/community-growth-trend.png differ diff --git a/website/static/img/blog/dateadd_matrix.png b/website/static/img/blog/dateadd_matrix.png new file mode 100644 index 00000000000..ac68c6fb7c9 Binary files /dev/null and b/website/static/img/blog/dateadd_matrix.png differ diff --git a/website/static/img/blog/dbt-project-structure-318751d1b7d09a0abc1627a7f6d219d3a8c0455b_2_690x173.jpeg b/website/static/img/blog/dbt-project-structure-318751d1b7d09a0abc1627a7f6d219d3a8c0455b_2_690x173.jpeg new file mode 100644 index 00000000000..a2fad495db1 Binary files /dev/null and b/website/static/img/blog/dbt-project-structure-318751d1b7d09a0abc1627a7f6d219d3a8c0455b_2_690x173.jpeg differ diff --git a/website/static/img/blog/dbt-project-structure-a5567e3711a30c72bbf9c117548452fac476d8c6_2_690x160.jpeg b/website/static/img/blog/dbt-project-structure-a5567e3711a30c72bbf9c117548452fac476d8c6_2_690x160.jpeg new file mode 100644 index 00000000000..63562f9d529 Binary files /dev/null and b/website/static/img/blog/dbt-project-structure-a5567e3711a30c72bbf9c117548452fac476d8c6_2_690x160.jpeg differ diff --git a/website/static/img/blog/how_to_build_a_package_image_0.png b/website/static/img/blog/how_to_build_a_package_image_0.png new file mode 100644 index 00000000000..09024f1ab89 Binary files /dev/null and b/website/static/img/blog/how_to_build_a_package_image_0.png differ diff --git a/website/static/img/blog/monorepo-275ba0c84ef31370a57f125ac13a0cbcb808af9a_2_600x365.png b/website/static/img/blog/monorepo-275ba0c84ef31370a57f125ac13a0cbcb808af9a_2_600x365.png new file mode 100644 index 00000000000..68b37507ba4 Binary files /dev/null and b/website/static/img/blog/monorepo-275ba0c84ef31370a57f125ac13a0cbcb808af9a_2_600x365.png differ diff --git a/website/static/img/blog/monorepo-3d6f91c1ab275d953417d2239f66e8f81bad7078_2_600x217.png b/website/static/img/blog/monorepo-3d6f91c1ab275d953417d2239f66e8f81bad7078_2_600x217.png new file mode 100644 index 00000000000..78601ea1668 Binary files /dev/null and b/website/static/img/blog/monorepo-3d6f91c1ab275d953417d2239f66e8f81bad7078_2_600x217.png differ diff --git a/website/static/img/blog/monorepo-52954083da8268c53f27a578b4b5722b35803b03_2_624x439.png b/website/static/img/blog/monorepo-52954083da8268c53f27a578b4b5722b35803b03_2_624x439.png new file mode 100644 index 00000000000..d083a947cc8 Binary files /dev/null and b/website/static/img/blog/monorepo-52954083da8268c53f27a578b4b5722b35803b03_2_624x439.png differ diff --git a/website/static/img/blog/monorepo-7f6c787766d980479e44a0419e845bc2fc80fa1a_2_296x390.png b/website/static/img/blog/monorepo-7f6c787766d980479e44a0419e845bc2fc80fa1a_2_296x390.png new file mode 100644 index 00000000000..4a89b5fe6b1 Binary files /dev/null and b/website/static/img/blog/monorepo-7f6c787766d980479e44a0419e845bc2fc80fa1a_2_296x390.png differ diff --git a/website/static/img/blog/on_the_importance_of_naming_image_0.png b/website/static/img/blog/on_the_importance_of_naming_image_0.png new file mode 100644 index 00000000000..81cf041420d Binary files /dev/null and b/website/static/img/blog/on_the_importance_of_naming_image_0.png differ diff --git a/website/static/img/blog/on_the_importance_of_naming_image_1.png b/website/static/img/blog/on_the_importance_of_naming_image_1.png new file mode 100644 index 00000000000..af3958530a4 Binary files /dev/null and b/website/static/img/blog/on_the_importance_of_naming_image_1.png differ diff --git a/website/static/img/blog/on_the_importance_of_naming_image_2.png b/website/static/img/blog/on_the_importance_of_naming_image_2.png new file mode 100644 index 00000000000..e86886530bb Binary files /dev/null and b/website/static/img/blog/on_the_importance_of_naming_image_2.png differ diff --git a/website/static/img/blog/on_the_importance_of_naming_image_3.png b/website/static/img/blog/on_the_importance_of_naming_image_3.png new file mode 100644 index 00000000000..159c251de24 Binary files /dev/null and b/website/static/img/blog/on_the_importance_of_naming_image_3.png differ diff --git a/website/static/img/blog/pr-template-dag-check.png b/website/static/img/blog/pr-template-dag-check.png new file mode 100644 index 00000000000..65628203f5a Binary files /dev/null and b/website/static/img/blog/pr-template-dag-check.png differ diff --git a/website/static/img/blog/pr-template-fct-meme.jpeg b/website/static/img/blog/pr-template-fct-meme.jpeg new file mode 100644 index 00000000000..0fe568e5458 Binary files /dev/null and b/website/static/img/blog/pr-template-fct-meme.jpeg differ diff --git a/website/static/img/blog/pr-template-test-validation.png b/website/static/img/blog/pr-template-test-validation.png new file mode 100644 index 00000000000..cdea50438f9 Binary files /dev/null and b/website/static/img/blog/pr-template-test-validation.png differ diff --git a/website/static/img/blog/pr-template-woof.gif b/website/static/img/blog/pr-template-woof.gif new file mode 100644 index 00000000000..0654d9a8099 Binary files /dev/null and b/website/static/img/blog/pr-template-woof.gif differ diff --git a/website/static/img/blog/real-time-5ab4b384ec36ed52d422e3ffcf238a4446dc3ba5_2_624x345.jpeg b/website/static/img/blog/real-time-5ab4b384ec36ed52d422e3ffcf238a4446dc3ba5_2_624x345.jpeg new file mode 100644 index 00000000000..6190c61acc1 Binary files /dev/null and b/website/static/img/blog/real-time-5ab4b384ec36ed52d422e3ffcf238a4446dc3ba5_2_624x345.jpeg differ diff --git a/website/static/img/blog/real-time-9eb7699399fe576a2a20b13bcf523a1e8b96cf09_2_624x244.png b/website/static/img/blog/real-time-9eb7699399fe576a2a20b13bcf523a1e8b96cf09_2_624x244.png new file mode 100644 index 00000000000..43a1172b7c2 Binary files /dev/null and b/website/static/img/blog/real-time-9eb7699399fe576a2a20b13bcf523a1e8b96cf09_2_624x244.png differ diff --git a/website/static/img/blog/union_unsplash.jpg b/website/static/img/blog/union_unsplash.jpg new file mode 100644 index 00000000000..d8973b24851 Binary files /dev/null and b/website/static/img/blog/union_unsplash.jpg differ diff --git a/website/static/img/create-bigquery-dbt-connection.png b/website/static/img/create-bigquery-dbt-connection.png index f39ab545a64..78e96ca52d6 100644 Binary files a/website/static/img/create-bigquery-dbt-connection.png and b/website/static/img/create-bigquery-dbt-connection.png differ diff --git a/website/static/img/databricks_tutorial/images/Generate_user_token.png b/website/static/img/databricks_tutorial/images/Generate_user_token.png new file mode 100644 index 00000000000..bfbb4c35498 Binary files /dev/null and b/website/static/img/databricks_tutorial/images/Generate_user_token.png differ diff --git a/website/static/img/databricks_tutorial/images/IDE.png b/website/static/img/databricks_tutorial/images/IDE.png new file mode 100644 index 00000000000..4048f95e738 Binary files /dev/null and b/website/static/img/databricks_tutorial/images/IDE.png differ diff --git a/website/static/img/databricks_tutorial/images/SQL_Endpoint_Details.png b/website/static/img/databricks_tutorial/images/SQL_Endpoint_Details.png new file mode 100644 index 00000000000..c59a707ac57 Binary files /dev/null and b/website/static/img/databricks_tutorial/images/SQL_Endpoint_Details.png differ diff --git a/website/static/img/databricks_tutorial/images/choose_plan.png b/website/static/img/databricks_tutorial/images/choose_plan.png new file mode 100644 index 00000000000..a76dba6d528 Binary files /dev/null and b/website/static/img/databricks_tutorial/images/choose_plan.png differ diff --git a/website/static/img/databricks_tutorial/images/create_cluster.png b/website/static/img/databricks_tutorial/images/create_cluster.png new file mode 100644 index 00000000000..a69eeb46339 Binary files /dev/null and b/website/static/img/databricks_tutorial/images/create_cluster.png differ diff --git a/website/static/img/databricks_tutorial/images/create_new_table.png b/website/static/img/databricks_tutorial/images/create_new_table.png new file mode 100644 index 00000000000..4acfd9da494 Binary files /dev/null and b/website/static/img/databricks_tutorial/images/create_new_table.png differ diff --git a/website/static/img/databricks_tutorial/images/create_query.png b/website/static/img/databricks_tutorial/images/create_query.png new file mode 100644 index 00000000000..85aa3942096 Binary files /dev/null and b/website/static/img/databricks_tutorial/images/create_query.png differ diff --git a/website/static/img/databricks_tutorial/images/create_stack.png b/website/static/img/databricks_tutorial/images/create_stack.png new file mode 100644 index 00000000000..10b8dcfee27 Binary files /dev/null and b/website/static/img/databricks_tutorial/images/create_stack.png differ diff --git a/website/static/img/databricks_tutorial/images/create_table_upload.png b/website/static/img/databricks_tutorial/images/create_table_upload.png new file mode 100644 index 00000000000..d46a1de6eb4 Binary files /dev/null and b/website/static/img/databricks_tutorial/images/create_table_upload.png differ diff --git a/website/static/img/databricks_tutorial/images/create_table_using_databricks_SQL.png b/website/static/img/databricks_tutorial/images/create_table_using_databricks_SQL.png new file mode 100644 index 00000000000..c7811ba80c8 Binary files /dev/null and b/website/static/img/databricks_tutorial/images/create_table_using_databricks_SQL.png differ diff --git a/website/static/img/databricks_tutorial/images/databricks_connect_to_dbt_cloud.png b/website/static/img/databricks_tutorial/images/databricks_connect_to_dbt_cloud.png new file mode 100644 index 00000000000..7876b30c398 Binary files /dev/null and b/website/static/img/databricks_tutorial/images/databricks_connect_to_dbt_cloud.png differ diff --git a/website/static/img/databricks_tutorial/images/databricks_connect_to_partner.png b/website/static/img/databricks_tutorial/images/databricks_connect_to_partner.png new file mode 100644 index 00000000000..f4df7699460 Binary files /dev/null and b/website/static/img/databricks_tutorial/images/databricks_connect_to_partner.png differ diff --git a/website/static/img/databricks_tutorial/images/databricks_partner_connect.png b/website/static/img/databricks_tutorial/images/databricks_partner_connect.png new file mode 100644 index 00000000000..c6c5ca051c9 Binary files /dev/null and b/website/static/img/databricks_tutorial/images/databricks_partner_connect.png differ diff --git a/website/static/img/databricks_tutorial/images/databricks_partner_connect_create_account.png b/website/static/img/databricks_tutorial/images/databricks_partner_connect_create_account.png new file mode 100644 index 00000000000..080898186dd Binary files /dev/null and b/website/static/img/databricks_tutorial/images/databricks_partner_connect_create_account.png differ diff --git a/website/static/img/databricks_tutorial/images/databricks_table_loader.png b/website/static/img/databricks_tutorial/images/databricks_table_loader.png new file mode 100644 index 00000000000..85f9408f135 Binary files /dev/null and b/website/static/img/databricks_tutorial/images/databricks_table_loader.png differ diff --git a/website/static/img/databricks_tutorial/images/databricks_welcome.png b/website/static/img/databricks_tutorial/images/databricks_welcome.png new file mode 100644 index 00000000000..4e81a5fa168 Binary files /dev/null and b/website/static/img/databricks_tutorial/images/databricks_welcome.png differ diff --git a/website/static/img/databricks_tutorial/images/dbt_cloud_setup_databricks_connection_details.png b/website/static/img/databricks_tutorial/images/dbt_cloud_setup_databricks_connection_details.png new file mode 100644 index 00000000000..7ff30872d49 Binary files /dev/null and b/website/static/img/databricks_tutorial/images/dbt_cloud_setup_databricks_connection_details.png differ diff --git a/website/static/img/databricks_tutorial/images/dbt_cloud_setup_databricks_connection_start.png b/website/static/img/databricks_tutorial/images/dbt_cloud_setup_databricks_connection_start.png new file mode 100644 index 00000000000..bd637493e73 Binary files /dev/null and b/website/static/img/databricks_tutorial/images/dbt_cloud_setup_databricks_connection_start.png differ diff --git a/website/static/img/databricks_tutorial/images/dbt_run.png b/website/static/img/databricks_tutorial/images/dbt_run.png new file mode 100644 index 00000000000..6473099ca68 Binary files /dev/null and b/website/static/img/databricks_tutorial/images/dbt_run.png differ diff --git a/website/static/img/databricks_tutorial/images/dbt_run_status.png b/website/static/img/databricks_tutorial/images/dbt_run_status.png new file mode 100644 index 00000000000..09bb14ce563 Binary files /dev/null and b/website/static/img/databricks_tutorial/images/dbt_run_status.png differ diff --git a/website/static/img/databricks_tutorial/images/development_credentials.png b/website/static/img/databricks_tutorial/images/development_credentials.png new file mode 100644 index 00000000000..73fc07c208f Binary files /dev/null and b/website/static/img/databricks_tutorial/images/development_credentials.png differ diff --git a/website/static/img/databricks_tutorial/images/generate_token.png b/website/static/img/databricks_tutorial/images/generate_token.png new file mode 100644 index 00000000000..6917cef9d7e Binary files /dev/null and b/website/static/img/databricks_tutorial/images/generate_token.png differ diff --git a/website/static/img/databricks_tutorial/images/go_to_sql.png b/website/static/img/databricks_tutorial/images/go_to_sql.png new file mode 100644 index 00000000000..d77c7f56fbf Binary files /dev/null and b/website/static/img/databricks_tutorial/images/go_to_sql.png differ diff --git a/website/static/img/databricks_tutorial/images/jaffle_shop_customers_upload.png b/website/static/img/databricks_tutorial/images/jaffle_shop_customers_upload.png new file mode 100644 index 00000000000..9155c978f05 Binary files /dev/null and b/website/static/img/databricks_tutorial/images/jaffle_shop_customers_upload.png differ diff --git a/website/static/img/databricks_tutorial/images/jaffle_shop_orders_upload.png b/website/static/img/databricks_tutorial/images/jaffle_shop_orders_upload.png new file mode 100644 index 00000000000..c52cb2bd016 Binary files /dev/null and b/website/static/img/databricks_tutorial/images/jaffle_shop_orders_upload.png differ diff --git a/website/static/img/databricks_tutorial/images/new_query.png b/website/static/img/databricks_tutorial/images/new_query.png new file mode 100644 index 00000000000..6abaa6b8965 Binary files /dev/null and b/website/static/img/databricks_tutorial/images/new_query.png differ diff --git a/website/static/img/databricks_tutorial/images/new_table_created.png b/website/static/img/databricks_tutorial/images/new_table_created.png new file mode 100644 index 00000000000..f037f92ccc8 Binary files /dev/null and b/website/static/img/databricks_tutorial/images/new_table_created.png differ diff --git a/website/static/img/databricks_tutorial/images/parameters.png b/website/static/img/databricks_tutorial/images/parameters.png new file mode 100644 index 00000000000..4dfad0b5245 Binary files /dev/null and b/website/static/img/databricks_tutorial/images/parameters.png differ diff --git a/website/static/img/databricks_tutorial/images/preview_query.png b/website/static/img/databricks_tutorial/images/preview_query.png new file mode 100644 index 00000000000..5260ceff83a Binary files /dev/null and b/website/static/img/databricks_tutorial/images/preview_query.png differ diff --git a/website/static/img/databricks_tutorial/images/query_check.png b/website/static/img/databricks_tutorial/images/query_check.png new file mode 100644 index 00000000000..ac76e67b7c3 Binary files /dev/null and b/website/static/img/databricks_tutorial/images/query_check.png differ diff --git a/website/static/img/databricks_tutorial/images/query_table_test.png b/website/static/img/databricks_tutorial/images/query_table_test.png new file mode 100644 index 00000000000..0984763c5fe Binary files /dev/null and b/website/static/img/databricks_tutorial/images/query_table_test.png differ diff --git a/website/static/img/databricks_tutorial/images/quick_create_stack.png b/website/static/img/databricks_tutorial/images/quick_create_stack.png new file mode 100644 index 00000000000..31522c56aac Binary files /dev/null and b/website/static/img/databricks_tutorial/images/quick_create_stack.png differ diff --git a/website/static/img/databricks_tutorial/images/raw_tables_created.png b/website/static/img/databricks_tutorial/images/raw_tables_created.png new file mode 100644 index 00000000000..9d6057ba962 Binary files /dev/null and b/website/static/img/databricks_tutorial/images/raw_tables_created.png differ diff --git a/website/static/img/databricks_tutorial/images/select_cluster_to_preview_table.png b/website/static/img/databricks_tutorial/images/select_cluster_to_preview_table.png new file mode 100644 index 00000000000..905456ef0f4 Binary files /dev/null and b/website/static/img/databricks_tutorial/images/select_cluster_to_preview_table.png differ diff --git a/website/static/img/databricks_tutorial/images/setup_database_connection.png b/website/static/img/databricks_tutorial/images/setup_database_connection.png new file mode 100644 index 00000000000..8a3d8f64d9e Binary files /dev/null and b/website/static/img/databricks_tutorial/images/setup_database_connection.png differ diff --git a/website/static/img/databricks_tutorial/images/setup_first_workspace.png b/website/static/img/databricks_tutorial/images/setup_first_workspace.png new file mode 100644 index 00000000000..a3656d53bef Binary files /dev/null and b/website/static/img/databricks_tutorial/images/setup_first_workspace.png differ diff --git a/website/static/img/databricks_tutorial/images/setup_flow_dbt_cloud.png b/website/static/img/databricks_tutorial/images/setup_flow_dbt_cloud.png new file mode 100644 index 00000000000..9a6c19f86b3 Binary files /dev/null and b/website/static/img/databricks_tutorial/images/setup_flow_dbt_cloud.png differ diff --git a/website/static/img/databricks_tutorial/images/signup_form.png b/website/static/img/databricks_tutorial/images/signup_form.png new file mode 100644 index 00000000000..5cf4a4e26b7 Binary files /dev/null and b/website/static/img/databricks_tutorial/images/signup_form.png differ diff --git a/website/static/img/databricks_tutorial/images/sql_endpoints.png b/website/static/img/databricks_tutorial/images/sql_endpoints.png new file mode 100644 index 00000000000..45574ad7004 Binary files /dev/null and b/website/static/img/databricks_tutorial/images/sql_endpoints.png differ diff --git a/website/static/img/databricks_tutorial/images/stack_status.png b/website/static/img/databricks_tutorial/images/stack_status.png new file mode 100644 index 00000000000..a1bd4912744 Binary files /dev/null and b/website/static/img/databricks_tutorial/images/stack_status.png differ diff --git a/website/static/img/databricks_tutorial/images/stripe_payments_upload.png b/website/static/img/databricks_tutorial/images/stripe_payments_upload.png new file mode 100644 index 00000000000..4318b448be8 Binary files /dev/null and b/website/static/img/databricks_tutorial/images/stripe_payments_upload.png differ diff --git a/website/static/img/databricks_tutorial/images/token_generated.png b/website/static/img/databricks_tutorial/images/token_generated.png new file mode 100644 index 00000000000..d9793bed42e Binary files /dev/null and b/website/static/img/databricks_tutorial/images/token_generated.png differ diff --git a/website/static/img/databricks_tutorial/images/validate_1.png b/website/static/img/databricks_tutorial/images/validate_1.png new file mode 100644 index 00000000000..2ccb63c038e Binary files /dev/null and b/website/static/img/databricks_tutorial/images/validate_1.png differ diff --git a/website/static/img/databricks_tutorial/images/validate_2.png b/website/static/img/databricks_tutorial/images/validate_2.png new file mode 100644 index 00000000000..c447e3cbb9a Binary files /dev/null and b/website/static/img/databricks_tutorial/images/validate_2.png differ diff --git a/website/static/img/databricks_tutorial/images/welcome_page.png b/website/static/img/databricks_tutorial/images/welcome_page.png new file mode 100644 index 00000000000..2104581ea7e Binary files /dev/null and b/website/static/img/databricks_tutorial/images/welcome_page.png differ diff --git a/website/static/img/databricks_tutorial/images/workspaces.png b/website/static/img/databricks_tutorial/images/workspaces.png new file mode 100644 index 00000000000..535a4f96463 Binary files /dev/null and b/website/static/img/databricks_tutorial/images/workspaces.png differ diff --git a/website/static/img/dbt-cloud-github-integration.png b/website/static/img/dbt-cloud-github-integration.png index c76c9c7e655..d1c53d5c1fd 100644 Binary files a/website/static/img/dbt-cloud-github-integration.png and b/website/static/img/dbt-cloud-github-integration.png differ diff --git a/website/static/img/dbt-cloud-project-setup-flow-next.png b/website/static/img/dbt-cloud-project-setup-flow-next.png new file mode 100644 index 00000000000..660e8ae446a Binary files /dev/null and b/website/static/img/dbt-cloud-project-setup-flow-next.png differ diff --git a/website/static/img/dbt-cloud-project-setup-flow.png b/website/static/img/dbt-cloud-project-setup-flow.png deleted file mode 100644 index 4e9f4b306c6..00000000000 Binary files a/website/static/img/dbt-cloud-project-setup-flow.png and /dev/null differ diff --git a/website/static/img/dbt-cloud-snowflake-connection.png b/website/static/img/dbt-cloud-snowflake-connection.png index c0f2929143b..3fae9097752 100644 Binary files a/website/static/img/dbt-cloud-snowflake-connection.png and b/website/static/img/dbt-cloud-snowflake-connection.png differ diff --git a/website/static/img/dbt-logo-full-white.png b/website/static/img/dbt-logo-full-white.png deleted file mode 100644 index 19bc0a0ac74..00000000000 Binary files a/website/static/img/dbt-logo-full-white.png and /dev/null differ diff --git a/website/static/img/dbt-logo-full.png b/website/static/img/dbt-logo-full.png deleted file mode 100644 index d3695c82368..00000000000 Binary files a/website/static/img/dbt-logo-full.png and /dev/null differ diff --git a/website/static/img/dbt-logo-light.svg b/website/static/img/dbt-logo-light.svg index 103162d92c6..bdf84371b42 100644 --- a/website/static/img/dbt-logo-light.svg +++ b/website/static/img/dbt-logo-light.svg @@ -1,6 +1,7 @@ - - - - - + + + + + + diff --git a/website/static/img/dbt-logo.svg b/website/static/img/dbt-logo.svg index 8bd63d6878f..4f540b88802 100644 --- a/website/static/img/dbt-logo.svg +++ b/website/static/img/dbt-logo.svg @@ -1,7 +1,7 @@ - - - - + + + + diff --git a/website/static/img/docs/building-a-dbt-project/0d01884-sqlcode.png b/website/static/img/docs/building-a-dbt-project/0d01884-sqlcode.png index febaa554438..6010e36123a 100644 Binary files a/website/static/img/docs/building-a-dbt-project/0d01884-sqlcode.png and b/website/static/img/docs/building-a-dbt-project/0d01884-sqlcode.png differ diff --git a/website/static/img/docs/building-a-dbt-project/3506cd5-Screen_Shot_2018-08-14_at_6.29.55_PM.png b/website/static/img/docs/building-a-dbt-project/3506cd5-Screen_Shot_2018-08-14_at_6.29.55_PM.png index 29e84f146af..00a33ccba31 100644 Binary files a/website/static/img/docs/building-a-dbt-project/3506cd5-Screen_Shot_2018-08-14_at_6.29.55_PM.png and b/website/static/img/docs/building-a-dbt-project/3506cd5-Screen_Shot_2018-08-14_at_6.29.55_PM.png differ diff --git a/website/static/img/docs/building-a-dbt-project/building-models/python-models/dataproc-connector-initialization.png b/website/static/img/docs/building-a-dbt-project/building-models/python-models/dataproc-connector-initialization.png new file mode 100644 index 00000000000..4c6095372f1 Binary files /dev/null and b/website/static/img/docs/building-a-dbt-project/building-models/python-models/dataproc-connector-initialization.png differ diff --git a/website/static/img/docs/building-a-dbt-project/building-models/python-models/dataproc-pip-packages.png b/website/static/img/docs/building-a-dbt-project/building-models/python-models/dataproc-pip-packages.png new file mode 100644 index 00000000000..d2c87003042 Binary files /dev/null and b/website/static/img/docs/building-a-dbt-project/building-models/python-models/dataproc-pip-packages.png differ diff --git a/website/static/img/docs/building-a-dbt-project/building-models/python-models/python-model-dag.png b/website/static/img/docs/building-a-dbt-project/building-models/python-models/python-model-dag.png new file mode 100644 index 00000000000..f89070468d1 Binary files /dev/null and b/website/static/img/docs/building-a-dbt-project/building-models/python-models/python-model-dag.png differ diff --git a/website/static/img/docs/building-a-dbt-project/dag-exposures.png b/website/static/img/docs/building-a-dbt-project/dag-exposures.png index c94b6a593ff..d086b6bdfd1 100644 Binary files a/website/static/img/docs/building-a-dbt-project/dag-exposures.png and b/website/static/img/docs/building-a-dbt-project/dag-exposures.png differ diff --git a/website/static/img/docs/building-a-dbt-project/dbt-cloud-project-setup-flow-next.png b/website/static/img/docs/building-a-dbt-project/dbt-cloud-project-setup-flow-next.png new file mode 100644 index 00000000000..660e8ae446a Binary files /dev/null and b/website/static/img/docs/building-a-dbt-project/dbt-cloud-project-setup-flow-next.png differ diff --git a/website/static/img/docs/building-a-dbt-project/dbt-docs-exposures.png b/website/static/img/docs/building-a-dbt-project/dbt-docs-exposures.png index 8304fce89ed..6efc1d39a22 100644 Binary files a/website/static/img/docs/building-a-dbt-project/dbt-docs-exposures.png and b/website/static/img/docs/building-a-dbt-project/dbt-docs-exposures.png differ diff --git a/website/static/img/docs/building-a-dbt-project/dbt-docs-screenshot.png b/website/static/img/docs/building-a-dbt-project/dbt-docs-screenshot.png index d60cf384d3c..8443192589d 100644 Binary files a/website/static/img/docs/building-a-dbt-project/dbt-docs-screenshot.png and b/website/static/img/docs/building-a-dbt-project/dbt-docs-screenshot.png differ diff --git a/website/static/img/docs/building-a-dbt-project/snapshot-freshness.png b/website/static/img/docs/building-a-dbt-project/snapshot-freshness.png index a0926621eb9..37a025e2d55 100644 Binary files a/website/static/img/docs/building-a-dbt-project/snapshot-freshness.png and b/website/static/img/docs/building-a-dbt-project/snapshot-freshness.png differ diff --git a/website/static/img/docs/building-a-dbt-project/sources-dag.png b/website/static/img/docs/building-a-dbt-project/sources-dag.png index f0b4daf2a7c..67dde014786 100644 Binary files a/website/static/img/docs/building-a-dbt-project/sources-dag.png and b/website/static/img/docs/building-a-dbt-project/sources-dag.png differ diff --git a/website/static/img/docs/building-a-dbt-project/testing-and-documentation/5fec8d1-Screen_Shot_2018-08-14_at_6.22.24_PM.png b/website/static/img/docs/building-a-dbt-project/testing-and-documentation/5fec8d1-Screen_Shot_2018-08-14_at_6.22.24_PM.png index dc7a416f756..d8137ff7273 100644 Binary files a/website/static/img/docs/building-a-dbt-project/testing-and-documentation/5fec8d1-Screen_Shot_2018-08-14_at_6.22.24_PM.png and b/website/static/img/docs/building-a-dbt-project/testing-and-documentation/5fec8d1-Screen_Shot_2018-08-14_at_6.22.24_PM.png differ diff --git a/website/static/img/docs/building-a-dbt-project/testing-and-documentation/ac97fba-Screen_Shot_2018-08-14_at_6.35.14_PM.png b/website/static/img/docs/building-a-dbt-project/testing-and-documentation/ac97fba-Screen_Shot_2018-08-14_at_6.35.14_PM.png index 9df3a3c377d..53b64e99491 100644 Binary files a/website/static/img/docs/building-a-dbt-project/testing-and-documentation/ac97fba-Screen_Shot_2018-08-14_at_6.35.14_PM.png and b/website/static/img/docs/building-a-dbt-project/testing-and-documentation/ac97fba-Screen_Shot_2018-08-14_at_6.35.14_PM.png differ diff --git a/website/static/img/docs/building-a-dbt-project/testing-and-documentation/ec77c45-Screen_Shot_2018-08-14_at_6.31.56_PM.png b/website/static/img/docs/building-a-dbt-project/testing-and-documentation/ec77c45-Screen_Shot_2018-08-14_at_6.31.56_PM.png index 9d332dd5cf2..bf0bc74fa08 100644 Binary files a/website/static/img/docs/building-a-dbt-project/testing-and-documentation/ec77c45-Screen_Shot_2018-08-14_at_6.31.56_PM.png and b/website/static/img/docs/building-a-dbt-project/testing-and-documentation/ec77c45-Screen_Shot_2018-08-14_at_6.31.56_PM.png differ diff --git a/website/static/img/docs/building-a-dbt-project/testing-and-documentation/f2221dc-Screen_Shot_2018-08-14_at_6.29.55_PM.png b/website/static/img/docs/building-a-dbt-project/testing-and-documentation/f2221dc-Screen_Shot_2018-08-14_at_6.29.55_PM.png index 29e84f146af..00a33ccba31 100644 Binary files a/website/static/img/docs/building-a-dbt-project/testing-and-documentation/f2221dc-Screen_Shot_2018-08-14_at_6.29.55_PM.png and b/website/static/img/docs/building-a-dbt-project/testing-and-documentation/f2221dc-Screen_Shot_2018-08-14_at_6.29.55_PM.png differ diff --git a/website/static/img/docs/dbt-cloud/28f97e6-job-schedule.gif b/website/static/img/docs/dbt-cloud/28f97e6-job-schedule.gif deleted file mode 100644 index 8d6cd95defc..00000000000 Binary files a/website/static/img/docs/dbt-cloud/28f97e6-job-schedule.gif and /dev/null differ diff --git a/website/static/img/docs/dbt-cloud/3af80f1-Screen_Shot_2019-02-01_at_9.51.54_AM.png b/website/static/img/docs/dbt-cloud/3af80f1-Screen_Shot_2019-02-01_at_9.51.54_AM.png index 061370e6b09..24d2979bd2d 100644 Binary files a/website/static/img/docs/dbt-cloud/3af80f1-Screen_Shot_2019-02-01_at_9.51.54_AM.png and b/website/static/img/docs/dbt-cloud/3af80f1-Screen_Shot_2019-02-01_at_9.51.54_AM.png differ diff --git a/website/static/img/docs/dbt-cloud/50e939e-Screen_Shot_2019-11-05_at_9.08.38_PM.png b/website/static/img/docs/dbt-cloud/50e939e-Screen_Shot_2019-11-05_at_9.08.38_PM.png index 8747a3a6791..51cfe5b667c 100644 Binary files a/website/static/img/docs/dbt-cloud/50e939e-Screen_Shot_2019-11-05_at_9.08.38_PM.png and b/website/static/img/docs/dbt-cloud/50e939e-Screen_Shot_2019-11-05_at_9.08.38_PM.png differ diff --git a/website/static/img/docs/dbt-cloud/7adcb15-Screen_Shot_2019-11-05_at_9.35.48_PM.png b/website/static/img/docs/dbt-cloud/7adcb15-Screen_Shot_2019-11-05_at_9.35.48_PM.png index 6f1b8a793aa..653ca84cb0d 100644 Binary files a/website/static/img/docs/dbt-cloud/7adcb15-Screen_Shot_2019-11-05_at_9.35.48_PM.png and b/website/static/img/docs/dbt-cloud/7adcb15-Screen_Shot_2019-11-05_at_9.35.48_PM.png differ diff --git a/website/static/img/docs/dbt-cloud/813b88c-Screen_Shot_2019-02-08_at_4.54.41_PM.png b/website/static/img/docs/dbt-cloud/813b88c-Screen_Shot_2019-02-08_at_4.54.41_PM.png index 63be778551d..9a74bb11d47 100644 Binary files a/website/static/img/docs/dbt-cloud/813b88c-Screen_Shot_2019-02-08_at_4.54.41_PM.png and b/website/static/img/docs/dbt-cloud/813b88c-Screen_Shot_2019-02-08_at_4.54.41_PM.png differ diff --git a/website/static/img/docs/dbt-cloud/8959807-Screen_Shot_2019-11-05_at_9.15.46_PM.png b/website/static/img/docs/dbt-cloud/8959807-Screen_Shot_2019-11-05_at_9.15.46_PM.png index 5284860ffc8..4d4364748f0 100644 Binary files a/website/static/img/docs/dbt-cloud/8959807-Screen_Shot_2019-11-05_at_9.15.46_PM.png and b/website/static/img/docs/dbt-cloud/8959807-Screen_Shot_2019-11-05_at_9.15.46_PM.png differ diff --git a/website/static/img/docs/dbt-cloud/Allow-dbt-to-access-slack.png b/website/static/img/docs/dbt-cloud/Allow-dbt-to-access-slack.png new file mode 100644 index 00000000000..2e6b198959c Binary files /dev/null and b/website/static/img/docs/dbt-cloud/Allow-dbt-to-access-slack.png differ diff --git a/website/static/img/docs/dbt-cloud/Configure-SSO-Access.png b/website/static/img/docs/dbt-cloud/Configure-SSO-Access.png new file mode 100644 index 00000000000..1c1f88b9298 Binary files /dev/null and b/website/static/img/docs/dbt-cloud/Configure-SSO-Access.png differ diff --git a/website/static/img/docs/dbt-cloud/Configure-Slack-notifications.png b/website/static/img/docs/dbt-cloud/Configure-Slack-notifications.png new file mode 100644 index 00000000000..5a76792f649 Binary files /dev/null and b/website/static/img/docs/dbt-cloud/Configure-Slack-notifications.png differ diff --git a/website/static/img/docs/dbt-cloud/Fix Session Timeout.png b/website/static/img/docs/dbt-cloud/Fix Session Timeout.png new file mode 100644 index 00000000000..a8b7079b427 Binary files /dev/null and b/website/static/img/docs/dbt-cloud/Fix Session Timeout.png differ diff --git a/website/static/img/docs/dbt-cloud/Link-your-Slack-Profile.png b/website/static/img/docs/dbt-cloud/Link-your-Slack-Profile.png new file mode 100644 index 00000000000..ab2697ec6ce Binary files /dev/null and b/website/static/img/docs/dbt-cloud/Link-your-Slack-Profile.png differ diff --git a/website/static/img/docs/dbt-cloud/Model-timing-tab.png b/website/static/img/docs/dbt-cloud/Model-timing-tab.png new file mode 100644 index 00000000000..dbe76f76a0d Binary files /dev/null and b/website/static/img/docs/dbt-cloud/Model-timing-tab.png differ diff --git a/website/static/img/docs/dbt-cloud/Navigate-to-integrations.png b/website/static/img/docs/dbt-cloud/Navigate-to-integrations.png new file mode 100644 index 00000000000..b1e2789f334 Binary files /dev/null and b/website/static/img/docs/dbt-cloud/Navigate-to-integrations.png differ diff --git a/website/static/img/docs/dbt-cloud/Navigate-to-notifications.png b/website/static/img/docs/dbt-cloud/Navigate-to-notifications.png new file mode 100644 index 00000000000..13da17d5deb Binary files /dev/null and b/website/static/img/docs/dbt-cloud/Navigate-to-notifications.png differ diff --git a/website/static/img/docs/dbt-cloud/Save-Group-Information.png b/website/static/img/docs/dbt-cloud/Save-Group-Information.png new file mode 100644 index 00000000000..4ef53211fa0 Binary files /dev/null and b/website/static/img/docs/dbt-cloud/Save-Group-Information.png differ diff --git a/website/static/img/docs/dbt-cloud/Select-Groups-RBAC.png b/website/static/img/docs/dbt-cloud/Select-Groups-RBAC.png new file mode 100644 index 00000000000..99bfa215d3a Binary files /dev/null and b/website/static/img/docs/dbt-cloud/Select-Groups-RBAC.png differ diff --git a/website/static/img/docs/dbt-cloud/View-docs-in-IDE.png b/website/static/img/docs/dbt-cloud/View-docs-in-IDE.png new file mode 100644 index 00000000000..9f9d3a34154 Binary files /dev/null and b/website/static/img/docs/dbt-cloud/View-docs-in-IDE.png differ diff --git a/website/static/img/docs/dbt-cloud/a5e2b52-Screen_Shot_2019-01-31_at_4.14.45_PM.png b/website/static/img/docs/dbt-cloud/a5e2b52-Screen_Shot_2019-01-31_at_4.14.45_PM.png index a05a0313d59..6f3615d20d8 100644 Binary files a/website/static/img/docs/dbt-cloud/a5e2b52-Screen_Shot_2019-01-31_at_4.14.45_PM.png and b/website/static/img/docs/dbt-cloud/a5e2b52-Screen_Shot_2019-01-31_at_4.14.45_PM.png differ diff --git a/website/static/img/docs/dbt-cloud/a7c5859-Screen_Shot_2019-01-31_at_11.54.32_PM.png b/website/static/img/docs/dbt-cloud/a7c5859-Screen_Shot_2019-01-31_at_11.54.32_PM.png index 2e31749ebe1..16c6fc2e775 100644 Binary files a/website/static/img/docs/dbt-cloud/a7c5859-Screen_Shot_2019-01-31_at_11.54.32_PM.png and b/website/static/img/docs/dbt-cloud/a7c5859-Screen_Shot_2019-01-31_at_11.54.32_PM.png differ diff --git a/website/static/img/docs/dbt-cloud/access-control/license-manual.png b/website/static/img/docs/dbt-cloud/access-control/license-manual.png index a1be2776feb..d92f5f77eb9 100644 Binary files a/website/static/img/docs/dbt-cloud/access-control/license-manual.png and b/website/static/img/docs/dbt-cloud/access-control/license-manual.png differ diff --git a/website/static/img/docs/dbt-cloud/access-control/license-mapping.png b/website/static/img/docs/dbt-cloud/access-control/license-mapping.png index 14e4b8e60cb..b483c760d70 100644 Binary files a/website/static/img/docs/dbt-cloud/access-control/license-mapping.png and b/website/static/img/docs/dbt-cloud/access-control/license-mapping.png differ diff --git a/website/static/img/docs/dbt-cloud/b070a02-Screen_Shot_2019-01-31_at_11.48.15_PM.png b/website/static/img/docs/dbt-cloud/b070a02-Screen_Shot_2019-01-31_at_11.48.15_PM.png index 1e147b2aace..9cdacc79a1d 100644 Binary files a/website/static/img/docs/dbt-cloud/b070a02-Screen_Shot_2019-01-31_at_11.48.15_PM.png and b/website/static/img/docs/dbt-cloud/b070a02-Screen_Shot_2019-01-31_at_11.48.15_PM.png differ diff --git a/website/static/img/docs/dbt-cloud/b19ca51-Screen_Shot_2019-02-01_at_12.42.18_PM.png b/website/static/img/docs/dbt-cloud/b19ca51-Screen_Shot_2019-02-01_at_12.42.18_PM.png index b7919984fce..b39d21a7ceb 100644 Binary files a/website/static/img/docs/dbt-cloud/b19ca51-Screen_Shot_2019-02-01_at_12.42.18_PM.png and b/website/static/img/docs/dbt-cloud/b19ca51-Screen_Shot_2019-02-01_at_12.42.18_PM.png differ diff --git a/website/static/img/docs/dbt-cloud/b4f242f-view-docs.gif b/website/static/img/docs/dbt-cloud/b4f242f-view-docs.gif deleted file mode 100644 index 370eb048a95..00000000000 Binary files a/website/static/img/docs/dbt-cloud/b4f242f-view-docs.gif and /dev/null differ diff --git a/website/static/img/docs/dbt-cloud/c3fe800-Screen_Shot_2019-02-08_at_6.53.29_PM.png b/website/static/img/docs/dbt-cloud/c3fe800-Screen_Shot_2019-02-08_at_6.53.29_PM.png deleted file mode 100644 index 3a15b7696b0..00000000000 Binary files a/website/static/img/docs/dbt-cloud/c3fe800-Screen_Shot_2019-02-08_at_6.53.29_PM.png and /dev/null differ diff --git a/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/14dba0a-Screen_Shot_2019-11-18_at_9.49.03_PM.png b/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/14dba0a-Screen_Shot_2019-11-18_at_9.49.03_PM.png index 1b2dab8abf4..7bd76d7f42d 100644 Binary files a/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/14dba0a-Screen_Shot_2019-11-18_at_9.49.03_PM.png and b/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/14dba0a-Screen_Shot_2019-11-18_at_9.49.03_PM.png differ diff --git a/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/3f25478-Screen_Shot_2019-11-18_at_9.43.32_PM.png b/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/3f25478-Screen_Shot_2019-11-18_at_9.43.32_PM.png index b6cc088c48e..954a9e93f02 100644 Binary files a/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/3f25478-Screen_Shot_2019-11-18_at_9.43.32_PM.png and b/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/3f25478-Screen_Shot_2019-11-18_at_9.43.32_PM.png differ diff --git a/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/4483b17-Screen_Shot_2019-11-18_at_9.46.47_PM.png b/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/4483b17-Screen_Shot_2019-11-18_at_9.46.47_PM.png index 5ff0a9f463f..a8df3740a5b 100644 Binary files a/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/4483b17-Screen_Shot_2019-11-18_at_9.46.47_PM.png and b/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/4483b17-Screen_Shot_2019-11-18_at_9.46.47_PM.png differ diff --git a/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/52bfdaa-Screen_Shot_2020-03-09_at_4.13.20_PM.png b/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/52bfdaa-Screen_Shot_2020-03-09_at_4.13.20_PM.png index 042e4ae451d..05ebc3a70e6 100644 Binary files a/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/52bfdaa-Screen_Shot_2020-03-09_at_4.13.20_PM.png and b/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/52bfdaa-Screen_Shot_2020-03-09_at_4.13.20_PM.png differ diff --git a/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/63cf3d2-Screen_Shot_2019-01-31_at_4.39.52_PM.png b/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/63cf3d2-Screen_Shot_2019-01-31_at_4.39.52_PM.png index 38dbf4a2507..ff12ec542cf 100644 Binary files a/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/63cf3d2-Screen_Shot_2019-01-31_at_4.39.52_PM.png and b/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/63cf3d2-Screen_Shot_2019-01-31_at_4.39.52_PM.png differ diff --git a/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/6c90f15-Screen_Shot_2020-01-13_at_8.37.36_PM.png b/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/6c90f15-Screen_Shot_2020-01-13_at_8.37.36_PM.png index 1d90d2cc136..06fa461fee0 100644 Binary files a/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/6c90f15-Screen_Shot_2020-01-13_at_8.37.36_PM.png and b/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/6c90f15-Screen_Shot_2020-01-13_at_8.37.36_PM.png differ diff --git a/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/6d8e980-Screen_Shot_2020-03-09_at_4.13.27_PM.png b/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/6d8e980-Screen_Shot_2020-03-09_at_4.13.27_PM.png index 74aa567929d..fa595a6197b 100644 Binary files a/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/6d8e980-Screen_Shot_2020-03-09_at_4.13.27_PM.png and b/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/6d8e980-Screen_Shot_2020-03-09_at_4.13.27_PM.png differ diff --git a/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/aae6ccf-Screen_Shot_2019-01-31_at_4.40.54_PM.png b/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/aae6ccf-Screen_Shot_2019-01-31_at_4.40.54_PM.png index 6dac4471371..8eef28cd1b6 100644 Binary files a/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/aae6ccf-Screen_Shot_2019-01-31_at_4.40.54_PM.png and b/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/aae6ccf-Screen_Shot_2019-01-31_at_4.40.54_PM.png differ diff --git a/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/bigquery-connection.png b/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/bigquery-connection.png index 85e9260727c..32a92486b3a 100644 Binary files a/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/bigquery-connection.png and b/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/bigquery-connection.png differ diff --git a/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/bitbucket-ssh-key.png b/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/bitbucket-ssh-key.png index c32ec3a174e..8473969f9f9 100644 Binary files a/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/bitbucket-ssh-key.png and b/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/bitbucket-ssh-key.png differ diff --git a/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/cd7351c-Screen_Shot_2019-10-16_at_1.09.41_PM.png b/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/cd7351c-Screen_Shot_2019-10-16_at_1.09.41_PM.png index 1c6dc027794..f05cbd99f5b 100644 Binary files a/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/cd7351c-Screen_Shot_2019-10-16_at_1.09.41_PM.png and b/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/cd7351c-Screen_Shot_2019-10-16_at_1.09.41_PM.png differ diff --git a/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/choosing-dbt-version/Environment-settings.png b/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/choosing-dbt-version/Environment-settings.png new file mode 100644 index 00000000000..cee053bf983 Binary files /dev/null and b/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/choosing-dbt-version/Environment-settings.png differ diff --git a/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/choosing-dbt-version/job-settings.png b/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/choosing-dbt-version/job-settings.png new file mode 100644 index 00000000000..2c7b2a7b560 Binary files /dev/null and b/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/choosing-dbt-version/job-settings.png differ diff --git a/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/cloud-upgrading-dbt-versions/upgrade-environment.png b/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/cloud-upgrading-dbt-versions/upgrade-environment.png new file mode 100644 index 00000000000..026dbcdff74 Binary files /dev/null and b/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/cloud-upgrading-dbt-versions/upgrade-environment.png differ diff --git a/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/configure-template-url.png b/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/configure-template-url.png index 5397f6e8580..4a6461d984b 100644 Binary files a/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/configure-template-url.png and b/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/configure-template-url.png differ diff --git a/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/connecting-github/configure-github.png b/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/connecting-github/configure-github.png new file mode 100644 index 00000000000..ead2e76a994 Binary files /dev/null and b/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/connecting-github/configure-github.png differ diff --git a/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/connecting-github/github-app-install.png b/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/connecting-github/github-app-install.png new file mode 100644 index 00000000000..442b6c18781 Binary files /dev/null and b/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/connecting-github/github-app-install.png differ diff --git a/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/connecting-github/github-auth.png b/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/connecting-github/github-auth.png new file mode 100644 index 00000000000..2c9fb7032d5 Binary files /dev/null and b/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/connecting-github/github-auth.png differ diff --git a/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/connecting-github/github-connect.gif b/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/connecting-github/github-connect.gif new file mode 100644 index 00000000000..d29ed18db15 Binary files /dev/null and b/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/connecting-github/github-connect.gif differ diff --git a/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/d19f199-Screen_Shot_2020-03-09_at_4.13.50_PM.png b/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/d19f199-Screen_Shot_2020-03-09_at_4.13.50_PM.png index 639e8e3821e..9ceacd6894a 100644 Binary files a/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/d19f199-Screen_Shot_2020-03-09_at_4.13.50_PM.png and b/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/d19f199-Screen_Shot_2020-03-09_at_4.13.50_PM.png differ diff --git a/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/databricks-connection.png b/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/databricks-connection.png index 2d183255e32..3c10f1b9799 100644 Binary files a/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/databricks-connection.png and b/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/databricks-connection.png differ diff --git a/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/databricks-connections.png b/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/databricks-connections.png new file mode 100644 index 00000000000..d028ae0f06c Binary files /dev/null and b/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/databricks-connections.png differ diff --git a/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/dev-environment-custom-branch.png b/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/dev-environment-custom-branch.png new file mode 100644 index 00000000000..487188b1c88 Binary files /dev/null and b/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/dev-environment-custom-branch.png differ diff --git a/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/e180a10-Screen_Shot_2019-11-18_at_9.44.44_PM.png b/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/e180a10-Screen_Shot_2019-11-18_at_9.44.44_PM.png index f6272d73b8d..bdc4da7f638 100644 Binary files a/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/e180a10-Screen_Shot_2019-11-18_at_9.44.44_PM.png and b/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/e180a10-Screen_Shot_2019-11-18_at_9.44.44_PM.png differ diff --git a/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/e7ae24e-Screen_Shot_2019-10-16_at_4.45.17_PM.png b/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/e7ae24e-Screen_Shot_2019-10-16_at_4.45.17_PM.png index 2cc72fdedd8..2adb0ae327f 100644 Binary files a/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/e7ae24e-Screen_Shot_2019-10-16_at_4.45.17_PM.png and b/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/e7ae24e-Screen_Shot_2019-10-16_at_4.45.17_PM.png differ diff --git a/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/f3ea88d-Screen_Shot_2019-10-16_at_4.45.50_PM.png b/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/f3ea88d-Screen_Shot_2019-10-16_at_4.45.50_PM.png index 98833729a9c..88a8a85559a 100644 Binary files a/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/f3ea88d-Screen_Shot_2019-10-16_at_4.45.50_PM.png and b/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/f3ea88d-Screen_Shot_2019-10-16_at_4.45.50_PM.png differ diff --git a/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/github-app-2.png b/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/github-app-2.png index a2bbd7ab63d..2d6ab0bceff 100644 Binary files a/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/github-app-2.png and b/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/github-app-2.png differ diff --git a/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/github-app.png b/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/github-app.png index b22d076fa3e..0700d109160 100644 Binary files a/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/github-app.png and b/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/github-app.png differ diff --git a/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/gitlab_application_auth.png b/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/gitlab_application_auth.png index fb47f2d7f32..c96ff5c86c0 100644 Binary files a/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/gitlab_application_auth.png and b/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/gitlab_application_auth.png differ diff --git a/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/gitlab_integration_edit_button.png b/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/gitlab_integration_edit_button.png index 310fb774f71..03eec5081db 100644 Binary files a/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/gitlab_integration_edit_button.png and b/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/gitlab_integration_edit_button.png differ diff --git a/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/gitlab_personal_auth.png b/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/gitlab_personal_auth.png index 9ddee6c2a4e..64c61c29906 100644 Binary files a/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/gitlab_personal_auth.png and b/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/gitlab_personal_auth.png differ diff --git a/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/managed-repo.png b/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/managed-repo.png index d1946776eea..5f1cb58461e 100644 Binary files a/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/managed-repo.png and b/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/managed-repo.png differ diff --git a/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/postgres-redshift-connection.png b/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/postgres-redshift-connection.png index d8e9f792056..bc89b429ad4 100644 Binary files a/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/postgres-redshift-connection.png and b/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/postgres-redshift-connection.png differ diff --git a/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/postgres-redshift-ssh-tunnel.png b/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/postgres-redshift-ssh-tunnel.png index 280130453b1..04461afa9ed 100644 Binary files a/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/postgres-redshift-ssh-tunnel.png and b/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/postgres-redshift-ssh-tunnel.png differ diff --git a/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/profile_integrations_page.png b/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/profile_integrations_page.png index 002325b76e3..6a64a80dfc6 100644 Binary files a/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/profile_integrations_page.png and b/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/profile_integrations_page.png differ diff --git a/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/spark-connection.png b/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/spark-connection.png index d71d491930b..4752e1d565d 100644 Binary files a/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/spark-connection.png and b/website/static/img/docs/dbt-cloud/cloud-configuring-dbt-cloud/spark-connection.png differ diff --git a/website/static/img/docs/dbt-cloud/cloud-ide/breadcrumbs.png b/website/static/img/docs/dbt-cloud/cloud-ide/breadcrumbs.png new file mode 100644 index 00000000000..eef522a742d Binary files /dev/null and b/website/static/img/docs/dbt-cloud/cloud-ide/breadcrumbs.png differ diff --git a/website/static/img/docs/dbt-cloud/cloud-ide/build.png b/website/static/img/docs/dbt-cloud/cloud-ide/build.png new file mode 100644 index 00000000000..c21ebead49d Binary files /dev/null and b/website/static/img/docs/dbt-cloud/cloud-ide/build.png differ diff --git a/website/static/img/docs/dbt-cloud/cloud-ide/clean-commit-modal.png b/website/static/img/docs/dbt-cloud/cloud-ide/clean-commit-modal.png index ebc2c3d7263..a90fbf11cd8 100644 Binary files a/website/static/img/docs/dbt-cloud/cloud-ide/clean-commit-modal.png and b/website/static/img/docs/dbt-cloud/cloud-ide/clean-commit-modal.png differ diff --git a/website/static/img/docs/dbt-cloud/cloud-ide/command_bar.png b/website/static/img/docs/dbt-cloud/cloud-ide/command_bar.png new file mode 100644 index 00000000000..5a2a67a7303 Binary files /dev/null and b/website/static/img/docs/dbt-cloud/cloud-ide/command_bar.png differ diff --git a/website/static/img/docs/dbt-cloud/cloud-ide/commit-to-merge-conflict.png b/website/static/img/docs/dbt-cloud/cloud-ide/commit-to-merge-conflict.png index e2eea3973c9..4cdb3ad1ba0 100644 Binary files a/website/static/img/docs/dbt-cloud/cloud-ide/commit-to-merge-conflict.png and b/website/static/img/docs/dbt-cloud/cloud-ide/commit-to-merge-conflict.png differ diff --git a/website/static/img/docs/dbt-cloud/cloud-ide/commit-to-resolve.png b/website/static/img/docs/dbt-cloud/cloud-ide/commit-to-resolve.png index 4e091adf4ca..c85b35dd528 100644 Binary files a/website/static/img/docs/dbt-cloud/cloud-ide/commit-to-resolve.png and b/website/static/img/docs/dbt-cloud/cloud-ide/commit-to-resolve.png differ diff --git a/website/static/img/docs/dbt-cloud/cloud-ide/commit-warning.png b/website/static/img/docs/dbt-cloud/cloud-ide/commit-warning.png index cc7771dd37d..0a6d91bc764 100644 Binary files a/website/static/img/docs/dbt-cloud/cloud-ide/commit-warning.png and b/website/static/img/docs/dbt-cloud/cloud-ide/commit-warning.png differ diff --git a/website/static/img/docs/dbt-cloud/cloud-ide/commit.png b/website/static/img/docs/dbt-cloud/cloud-ide/commit.png index e335cc1d538..4caf14415df 100644 Binary files a/website/static/img/docs/dbt-cloud/cloud-ide/commit.png and b/website/static/img/docs/dbt-cloud/cloud-ide/commit.png differ diff --git a/website/static/img/docs/dbt-cloud/cloud-ide/conflict-section.png b/website/static/img/docs/dbt-cloud/cloud-ide/conflict-section.png index e5fd09a816e..dbad2d78e47 100644 Binary files a/website/static/img/docs/dbt-cloud/cloud-ide/conflict-section.png and b/website/static/img/docs/dbt-cloud/cloud-ide/conflict-section.png differ diff --git a/website/static/img/docs/dbt-cloud/cloud-ide/create_new_branch.png b/website/static/img/docs/dbt-cloud/cloud-ide/create_new_branch.png index 107367a08f5..e3d66303c72 100644 Binary files a/website/static/img/docs/dbt-cloud/cloud-ide/create_new_branch.png and b/website/static/img/docs/dbt-cloud/cloud-ide/create_new_branch.png differ diff --git a/website/static/img/docs/dbt-cloud/cloud-ide/file-explorer.png b/website/static/img/docs/dbt-cloud/cloud-ide/file-explorer.png new file mode 100644 index 00000000000..bbf1fcc0427 Binary files /dev/null and b/website/static/img/docs/dbt-cloud/cloud-ide/file-explorer.png differ diff --git a/website/static/img/docs/dbt-cloud/cloud-ide/file-highlight.png b/website/static/img/docs/dbt-cloud/cloud-ide/file-highlight.png index 68b7fa51dd0..db09d84c1d7 100644 Binary files a/website/static/img/docs/dbt-cloud/cloud-ide/file-highlight.png and b/website/static/img/docs/dbt-cloud/cloud-ide/file-highlight.png differ diff --git a/website/static/img/docs/dbt-cloud/cloud-ide/git-overview.png b/website/static/img/docs/dbt-cloud/cloud-ide/git-overview.png new file mode 100644 index 00000000000..eae4da2da85 Binary files /dev/null and b/website/static/img/docs/dbt-cloud/cloud-ide/git-overview.png differ diff --git a/website/static/img/docs/dbt-cloud/cloud-ide/initialize.png b/website/static/img/docs/dbt-cloud/cloud-ide/initialize.png index 6a31f0c9592..2a458c9074e 100644 Binary files a/website/static/img/docs/dbt-cloud/cloud-ide/initialize.png and b/website/static/img/docs/dbt-cloud/cloud-ide/initialize.png differ diff --git a/website/static/img/docs/dbt-cloud/cloud-ide/lineage.png b/website/static/img/docs/dbt-cloud/cloud-ide/lineage.png new file mode 100644 index 00000000000..a4293bbcaf3 Binary files /dev/null and b/website/static/img/docs/dbt-cloud/cloud-ide/lineage.png differ diff --git a/website/static/img/docs/dbt-cloud/cloud-ide/multi-selector.gif b/website/static/img/docs/dbt-cloud/cloud-ide/multi-selector.gif new file mode 100644 index 00000000000..9159ed61c17 Binary files /dev/null and b/website/static/img/docs/dbt-cloud/cloud-ide/multi-selector.gif differ diff --git a/website/static/img/docs/dbt-cloud/cloud-ide/needs-resolution.png b/website/static/img/docs/dbt-cloud/cloud-ide/needs-resolution.png index 9080b64689a..c7dc9d4b4fd 100644 Binary files a/website/static/img/docs/dbt-cloud/cloud-ide/needs-resolution.png and b/website/static/img/docs/dbt-cloud/cloud-ide/needs-resolution.png differ diff --git a/website/static/img/docs/dbt-cloud/cloud-ide/open_pr.png b/website/static/img/docs/dbt-cloud/cloud-ide/open_pr.png index da36cb307c4..219aad2d92d 100644 Binary files a/website/static/img/docs/dbt-cloud/cloud-ide/open_pr.png and b/website/static/img/docs/dbt-cloud/cloud-ide/open_pr.png differ diff --git a/website/static/img/docs/dbt-cloud/cloud-ide/pull_from_master.png b/website/static/img/docs/dbt-cloud/cloud-ide/pull_from_master.png index 7a138fb0352..a23af24873a 100644 Binary files a/website/static/img/docs/dbt-cloud/cloud-ide/pull_from_master.png and b/website/static/img/docs/dbt-cloud/cloud-ide/pull_from_master.png differ diff --git a/website/static/img/docs/dbt-cloud/cloud-ide/pull_from_remote.png b/website/static/img/docs/dbt-cloud/cloud-ide/pull_from_remote.png index 95d6b07c2f9..0a0b6c694b3 100644 Binary files a/website/static/img/docs/dbt-cloud/cloud-ide/pull_from_remote.png and b/website/static/img/docs/dbt-cloud/cloud-ide/pull_from_remote.png differ diff --git a/website/static/img/docs/dbt-cloud/cloud-ide/resolve-section.png b/website/static/img/docs/dbt-cloud/cloud-ide/resolve-section.png index 9b3f19a9283..100faefff12 100644 Binary files a/website/static/img/docs/dbt-cloud/cloud-ide/resolve-section.png and b/website/static/img/docs/dbt-cloud/cloud-ide/resolve-section.png differ diff --git a/website/static/img/docs/dbt-cloud/cloud-ide/resolved-file.png b/website/static/img/docs/dbt-cloud/cloud-ide/resolved-file.png index b04979a1b39..282c2d058d0 100644 Binary files a/website/static/img/docs/dbt-cloud/cloud-ide/resolved-file.png and b/website/static/img/docs/dbt-cloud/cloud-ide/resolved-file.png differ diff --git a/website/static/img/docs/dbt-cloud/cloud-ide/status-icon.png b/website/static/img/docs/dbt-cloud/cloud-ide/status-icon.png new file mode 100644 index 00000000000..129986a1e60 Binary files /dev/null and b/website/static/img/docs/dbt-cloud/cloud-ide/status-icon.png differ diff --git a/website/static/img/docs/dbt-cloud/cloud-ide/tab-options.png b/website/static/img/docs/dbt-cloud/cloud-ide/tab-options.png new file mode 100644 index 00000000000..0af73130cf3 Binary files /dev/null and b/website/static/img/docs/dbt-cloud/cloud-ide/tab-options.png differ diff --git a/website/static/img/docs/dbt-cloud/cloud-ide/view-docs.png b/website/static/img/docs/dbt-cloud/cloud-ide/view-docs.png new file mode 100644 index 00000000000..9c7c9312fa4 Binary files /dev/null and b/website/static/img/docs/dbt-cloud/cloud-ide/view-docs.png differ diff --git a/website/static/img/docs/dbt-cloud/connecting-azure-devops/AD app.png b/website/static/img/docs/dbt-cloud/connecting-azure-devops/AD app.png new file mode 100644 index 00000000000..900bfb83e55 Binary files /dev/null and b/website/static/img/docs/dbt-cloud/connecting-azure-devops/AD app.png differ diff --git a/website/static/img/docs/dbt-cloud/connecting-azure-devops/ADnavigation.gif b/website/static/img/docs/dbt-cloud/connecting-azure-devops/ADnavigation.gif new file mode 100644 index 00000000000..d00dc262511 Binary files /dev/null and b/website/static/img/docs/dbt-cloud/connecting-azure-devops/ADnavigation.gif differ diff --git a/website/static/img/docs/dbt-cloud/connecting-azure-devops/AzureDevopsAppdbtCloud.gif b/website/static/img/docs/dbt-cloud/connecting-azure-devops/AzureDevopsAppdbtCloud.gif new file mode 100644 index 00000000000..0c68cc06f35 Binary files /dev/null and b/website/static/img/docs/dbt-cloud/connecting-azure-devops/AzureDevopsAppdbtCloud.gif differ diff --git a/website/static/img/docs/dbt-cloud/connecting-azure-devops/LinktoAzure.png b/website/static/img/docs/dbt-cloud/connecting-azure-devops/LinktoAzure.png new file mode 100644 index 00000000000..143d4127aec Binary files /dev/null and b/website/static/img/docs/dbt-cloud/connecting-azure-devops/LinktoAzure.png differ diff --git a/website/static/img/docs/dbt-cloud/connecting-azure-devops/OAuth Acceptance.png b/website/static/img/docs/dbt-cloud/connecting-azure-devops/OAuth Acceptance.png new file mode 100644 index 00000000000..61e33737b69 Binary files /dev/null and b/website/static/img/docs/dbt-cloud/connecting-azure-devops/OAuth Acceptance.png differ diff --git a/website/static/img/docs/dbt-cloud/connecting-azure-devops/azure-service-user.png b/website/static/img/docs/dbt-cloud/connecting-azure-devops/azure-service-user.png new file mode 100644 index 00000000000..20277967f22 Binary files /dev/null and b/website/static/img/docs/dbt-cloud/connecting-azure-devops/azure-service-user.png differ diff --git a/website/static/img/docs/dbt-cloud/connecting-azure-devops/connect AD to Azure DevOps.gif b/website/static/img/docs/dbt-cloud/connecting-azure-devops/connect AD to Azure DevOps.gif new file mode 100644 index 00000000000..0a9f0e5b484 Binary files /dev/null and b/website/static/img/docs/dbt-cloud/connecting-azure-devops/connect AD to Azure DevOps.gif differ diff --git a/website/static/img/docs/dbt-cloud/connecting-azure-devops/profile link.gif b/website/static/img/docs/dbt-cloud/connecting-azure-devops/profile link.gif new file mode 100644 index 00000000000..1354b4aa640 Binary files /dev/null and b/website/static/img/docs/dbt-cloud/connecting-azure-devops/profile link.gif differ diff --git a/website/static/img/docs/dbt-cloud/connecting-azure-devops/redirect-uri.gif b/website/static/img/docs/dbt-cloud/connecting-azure-devops/redirect-uri.gif new file mode 100644 index 00000000000..f3112372dcc Binary files /dev/null and b/website/static/img/docs/dbt-cloud/connecting-azure-devops/redirect-uri.gif differ diff --git a/website/static/img/docs/dbt-cloud/connecting-azure-devops/user-impersonation.gif b/website/static/img/docs/dbt-cloud/connecting-azure-devops/user-impersonation.gif new file mode 100644 index 00000000000..437ba3bc356 Binary files /dev/null and b/website/static/img/docs/dbt-cloud/connecting-azure-devops/user-impersonation.gif differ diff --git a/website/static/img/docs/dbt-cloud/connecting-gitlab/GitLab-Navigation.gif b/website/static/img/docs/dbt-cloud/connecting-gitlab/GitLab-Navigation.gif new file mode 100644 index 00000000000..a9d624ae6e3 Binary files /dev/null and b/website/static/img/docs/dbt-cloud/connecting-gitlab/GitLab-Navigation.gif differ diff --git a/website/static/img/docs/dbt-cloud/connecting-gitlab/gitlab app.png b/website/static/img/docs/dbt-cloud/connecting-gitlab/gitlab app.png new file mode 100644 index 00000000000..e90c6b08148 Binary files /dev/null and b/website/static/img/docs/dbt-cloud/connecting-gitlab/gitlab app.png differ diff --git a/website/static/img/docs/dbt-cloud/connecting-gitlab/gitlab nav.gif b/website/static/img/docs/dbt-cloud/connecting-gitlab/gitlab nav.gif new file mode 100644 index 00000000000..419ce38bc3c Binary files /dev/null and b/website/static/img/docs/dbt-cloud/connecting-gitlab/gitlab nav.gif differ diff --git a/website/static/img/docs/dbt-cloud/connecting-gitlab/gitlab redirect.gif b/website/static/img/docs/dbt-cloud/connecting-gitlab/gitlab redirect.gif new file mode 100644 index 00000000000..c153b64cf88 Binary files /dev/null and b/website/static/img/docs/dbt-cloud/connecting-gitlab/gitlab redirect.gif differ diff --git a/website/static/img/docs/dbt-cloud/d6a75a5-Screen_Shot_2019-11-05_at_9.04.02_PM.png b/website/static/img/docs/dbt-cloud/d6a75a5-Screen_Shot_2019-11-05_at_9.04.02_PM.png index e0f7c0934e6..dd30b292f89 100644 Binary files a/website/static/img/docs/dbt-cloud/d6a75a5-Screen_Shot_2019-11-05_at_9.04.02_PM.png and b/website/static/img/docs/dbt-cloud/d6a75a5-Screen_Shot_2019-11-05_at_9.04.02_PM.png differ diff --git a/website/static/img/docs/dbt-cloud/dag v1.1.56 release.png b/website/static/img/docs/dbt-cloud/dag v1.1.56 release.png new file mode 100644 index 00000000000..1066ff22d5b Binary files /dev/null and b/website/static/img/docs/dbt-cloud/dag v1.1.56 release.png differ diff --git a/website/static/img/docs/dbt-cloud/dbt docs generate command.png b/website/static/img/docs/dbt-cloud/dbt docs generate command.png new file mode 100644 index 00000000000..2e9bc318dc5 Binary files /dev/null and b/website/static/img/docs/dbt-cloud/dbt docs generate command.png differ diff --git a/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/0ccb854-Screen_Shot_2019-12-03_at_10.11.15_AM.png b/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/0ccb854-Screen_Shot_2019-12-03_at_10.11.15_AM.png index 172799f8ca4..8d1633427ca 100644 Binary files a/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/0ccb854-Screen_Shot_2019-12-03_at_10.11.15_AM.png and b/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/0ccb854-Screen_Shot_2019-12-03_at_10.11.15_AM.png differ diff --git a/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/137b611-Screen_Shot_2019-04-25_at_6.10.43_PM.png b/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/137b611-Screen_Shot_2019-04-25_at_6.10.43_PM.png index 0fa1c1c7e76..25897df047b 100644 Binary files a/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/137b611-Screen_Shot_2019-04-25_at_6.10.43_PM.png and b/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/137b611-Screen_Shot_2019-04-25_at_6.10.43_PM.png differ diff --git a/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/1bd0c42-Screen_Shot_2020-03-10_at_6.20.05_PM.png b/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/1bd0c42-Screen_Shot_2020-03-10_at_6.20.05_PM.png deleted file mode 100644 index 9566f7b13b4..00000000000 Binary files a/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/1bd0c42-Screen_Shot_2020-03-10_at_6.20.05_PM.png and /dev/null differ diff --git a/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/21ea0d3-Screen_Shot_2019-07-25_at_9.31.26_AM.png b/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/21ea0d3-Screen_Shot_2019-07-25_at_9.31.26_AM.png index 3f77fae1b8a..f5bc364372b 100644 Binary files a/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/21ea0d3-Screen_Shot_2019-07-25_at_9.31.26_AM.png and b/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/21ea0d3-Screen_Shot_2019-07-25_at_9.31.26_AM.png differ diff --git a/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/2be2b70-Screen_Shot_2019-04-25_at_6.06.31_PM.png b/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/2be2b70-Screen_Shot_2019-04-25_at_6.06.31_PM.png index 8b166da34b7..0a9133d6423 100644 Binary files a/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/2be2b70-Screen_Shot_2019-04-25_at_6.06.31_PM.png and b/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/2be2b70-Screen_Shot_2019-04-25_at_6.06.31_PM.png differ diff --git a/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/3b9da88-Screen_Shot_2019-07-25_at_9.54.53_AM.png b/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/3b9da88-Screen_Shot_2019-07-25_at_9.54.53_AM.png index 02234eca7d8..35991c69463 100644 Binary files a/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/3b9da88-Screen_Shot_2019-07-25_at_9.54.53_AM.png and b/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/3b9da88-Screen_Shot_2019-07-25_at_9.54.53_AM.png differ diff --git a/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/41b00ff-Screen_Shot_2019-04-25_at_6.06.08_PM.png b/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/41b00ff-Screen_Shot_2019-04-25_at_6.06.08_PM.png index 3e9256503be..76e9693f423 100644 Binary files a/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/41b00ff-Screen_Shot_2019-04-25_at_6.06.08_PM.png and b/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/41b00ff-Screen_Shot_2019-04-25_at_6.06.08_PM.png differ diff --git a/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/51f1bb7-Screen_Shot_2019-04-25_at_6.05.32_PM.png b/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/51f1bb7-Screen_Shot_2019-04-25_at_6.05.32_PM.png index cb66fa6e872..e94561ef4bb 100644 Binary files a/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/51f1bb7-Screen_Shot_2019-04-25_at_6.05.32_PM.png and b/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/51f1bb7-Screen_Shot_2019-04-25_at_6.05.32_PM.png differ diff --git a/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/61d2b48-Screen_Shot_2019-04-25_at_6.05.23_PM.png b/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/61d2b48-Screen_Shot_2019-04-25_at_6.05.23_PM.png index ce168bf000a..3cc4de2a4b1 100644 Binary files a/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/61d2b48-Screen_Shot_2019-04-25_at_6.05.23_PM.png and b/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/61d2b48-Screen_Shot_2019-04-25_at_6.05.23_PM.png differ diff --git a/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/7f36f50-Screen_Shot_2019-12-03_at_10.15.01_AM.png b/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/7f36f50-Screen_Shot_2019-12-03_at_10.15.01_AM.png index 4a6b23b0a4d..e8ac29017da 100644 Binary files a/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/7f36f50-Screen_Shot_2019-12-03_at_10.15.01_AM.png and b/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/7f36f50-Screen_Shot_2019-12-03_at_10.15.01_AM.png differ diff --git a/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/84427818-841b3680-abf3-11ea-8faf-693d4a39cffb.png b/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/84427818-841b3680-abf3-11ea-8faf-693d4a39cffb.png new file mode 100644 index 00000000000..062ad9f7fb4 Binary files /dev/null and b/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/84427818-841b3680-abf3-11ea-8faf-693d4a39cffb.png differ diff --git a/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/access-control/group-detail.png b/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/access-control/group-detail.png deleted file mode 100644 index c37a7b7a7ec..00000000000 Binary files a/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/access-control/group-detail.png and /dev/null differ diff --git a/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/access-control/group-list.png b/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/access-control/group-list.png index b7d3875916b..28262bd5635 100644 Binary files a/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/access-control/group-list.png and b/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/access-control/group-list.png differ diff --git a/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/access-control/group-permissions.png b/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/access-control/group-permissions.png index d2f2f8e2076..55655ef6b78 100644 Binary files a/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/access-control/group-permissions.png and b/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/access-control/group-permissions.png differ diff --git a/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/ae2045a-Screen_Shot_2019-04-25_at_6.05.12_PM.png b/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/ae2045a-Screen_Shot_2019-04-25_at_6.05.12_PM.png deleted file mode 100644 index a5303eb9695..00000000000 Binary files a/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/ae2045a-Screen_Shot_2019-04-25_at_6.05.12_PM.png and /dev/null differ diff --git a/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/audit-log-export-csv.png b/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/audit-log-export-csv.png new file mode 100644 index 00000000000..ad3ddb441af Binary files /dev/null and b/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/audit-log-export-csv.png differ diff --git a/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/audit-log-menu.png b/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/audit-log-menu.png new file mode 100644 index 00000000000..a5010c50ef3 Binary files /dev/null and b/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/audit-log-menu.png differ diff --git a/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/audit-log-search.png b/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/audit-log-search.png new file mode 100644 index 00000000000..5827f954a90 Binary files /dev/null and b/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/audit-log-search.png differ diff --git a/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/azure/azure-app-registration-empty.png b/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/azure/azure-app-registration-empty.png index 42aca4e464c..61974c8ba7f 100644 Binary files a/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/azure/azure-app-registration-empty.png and b/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/azure/azure-app-registration-empty.png differ diff --git a/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/azure/azure-application-permissions.png b/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/azure/azure-application-permissions.png index 86d9e9cf81e..29288ec3e57 100644 Binary files a/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/azure/azure-application-permissions.png and b/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/azure/azure-application-permissions.png differ diff --git a/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/azure/azure-cloud-sso-verify.png b/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/azure/azure-cloud-sso-verify.png index dcadfcbbb33..a557b1ab96b 100644 Binary files a/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/azure/azure-cloud-sso-verify.png and b/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/azure/azure-cloud-sso-verify.png differ diff --git a/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/azure/azure-cloud-sso.png b/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/azure/azure-cloud-sso.png index 473adc78395..ea8d2a985f1 100644 Binary files a/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/azure/azure-cloud-sso.png and b/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/azure/azure-cloud-sso.png differ diff --git a/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/azure/azure-delegated-permissions.png b/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/azure/azure-delegated-permissions.png index 44c21ccfce9..d0e5c053c55 100644 Binary files a/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/azure/azure-delegated-permissions.png and b/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/azure/azure-delegated-permissions.png differ diff --git a/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/azure/azure-domain-in-dbt.png b/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/azure/azure-domain-in-dbt.png index 9f0a0281b07..04891ff54c5 100644 Binary files a/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/azure/azure-domain-in-dbt.png and b/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/azure/azure-domain-in-dbt.png differ diff --git a/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/azure/azure-enterprise-app-users.png b/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/azure/azure-enterprise-app-users.png index 132b25ff27b..9caca081a5d 100644 Binary files a/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/azure/azure-enterprise-app-users.png and b/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/azure/azure-enterprise-app-users.png differ diff --git a/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/azure/azure-get-domain.png b/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/azure/azure-get-domain.png index e650a79e6b7..f9b962a32df 100644 Binary files a/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/azure/azure-get-domain.png and b/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/azure/azure-get-domain.png differ diff --git a/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/azure/azure-new-application-alternative.png b/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/azure/azure-new-application-alternative.png index 8181a9fc4a8..fe66d932f92 100644 Binary files a/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/azure/azure-new-application-alternative.png and b/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/azure/azure-new-application-alternative.png differ diff --git a/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/azure/azure-new-application.png b/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/azure/azure-new-application.png index 14c53af3e41..e7e3ebca18a 100644 Binary files a/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/azure/azure-new-application.png and b/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/azure/azure-new-application.png differ diff --git a/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/azure/azure-overview.png b/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/azure/azure-overview.png index bf7326ad70c..d1ecca1d3a1 100644 Binary files a/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/azure/azure-overview.png and b/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/azure/azure-overview.png differ diff --git a/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/azure/azure-permissions-overview.png b/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/azure/azure-permissions-overview.png index 088d02a7b07..ea0f7d28840 100644 Binary files a/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/azure/azure-permissions-overview.png and b/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/azure/azure-permissions-overview.png differ diff --git a/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/azure/azure-redirect-uri.png b/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/azure/azure-redirect-uri.png index 49b40eb7ef3..7daaab4504d 100644 Binary files a/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/azure/azure-redirect-uri.png and b/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/azure/azure-redirect-uri.png differ diff --git a/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/azure/azure-secret-config.png b/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/azure/azure-secret-config.png index da147ac35c3..ef1eb04f45d 100644 Binary files a/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/azure/azure-secret-config.png and b/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/azure/azure-secret-config.png differ diff --git a/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/azure/azure-secret-saved.png b/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/azure/azure-secret-saved.png index 789e41f376d..580d6e43e23 100644 Binary files a/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/azure/azure-secret-saved.png and b/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/azure/azure-secret-saved.png differ diff --git a/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/azure/azure-secret.png b/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/azure/azure-secret.png index 4912fab53a2..0389271e9a7 100644 Binary files a/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/azure/azure-secret.png and b/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/azure/azure-secret.png differ diff --git a/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/database-connection-snowflake-oauth.png b/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/database-connection-snowflake-oauth.png new file mode 100644 index 00000000000..4c638eed6ae Binary files /dev/null and b/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/database-connection-snowflake-oauth.png differ diff --git a/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/gsuite/gsuite-sso-cloud-config.png b/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/gsuite/gsuite-sso-cloud-config.png index 5d210eeb299..3e7bde2651d 100644 Binary files a/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/gsuite/gsuite-sso-cloud-config.png and b/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/gsuite/gsuite-sso-cloud-config.png differ diff --git a/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/gsuite/gsuite-sso-cloud-verify.png b/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/gsuite/gsuite-sso-cloud-verify.png index a3f726dc8f9..8636cbd7186 100644 Binary files a/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/gsuite/gsuite-sso-cloud-verify.png and b/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/gsuite/gsuite-sso-cloud-verify.png differ diff --git a/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/gsuite/gsuite-sso-consent-bottom.png b/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/gsuite/gsuite-sso-consent-bottom.png index d3ae940ad41..cdde490b19c 100644 Binary files a/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/gsuite/gsuite-sso-consent-bottom.png and b/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/gsuite/gsuite-sso-consent-bottom.png differ diff --git a/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/gsuite/gsuite-sso-consent-top.png b/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/gsuite/gsuite-sso-consent-top.png index 0381c1ad17e..dba5728e408 100644 Binary files a/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/gsuite/gsuite-sso-consent-top.png and b/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/gsuite/gsuite-sso-consent-top.png differ diff --git a/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/gsuite/gsuite-sso-credentials.png b/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/gsuite/gsuite-sso-credentials.png index 21ef17819e0..303f5ca8d79 100644 Binary files a/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/gsuite/gsuite-sso-credentials.png and b/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/gsuite/gsuite-sso-credentials.png differ diff --git a/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/okta/okta-1-new-app-create.png b/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/okta/okta-1-new-app-create.png index c7819e69f0b..358fb818e0c 100644 Binary files a/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/okta/okta-1-new-app-create.png and b/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/okta/okta-1-new-app-create.png differ diff --git a/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/okta/okta-1-new-app.png b/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/okta/okta-1-new-app.png index 2bdfad40d7c..c7bc3e7a853 100644 Binary files a/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/okta/okta-1-new-app.png and b/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/okta/okta-1-new-app.png differ diff --git a/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/okta/okta-2-general-settings.png b/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/okta/okta-2-general-settings.png index c90b2e773ad..e7ef3f08887 100644 Binary files a/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/okta/okta-2-general-settings.png and b/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/okta/okta-2-general-settings.png differ diff --git a/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/okta/okta-3-saml-settings-bottom.png b/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/okta/okta-3-saml-settings-bottom.png index 9c28bb7cdc1..5f8e92939ac 100644 Binary files a/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/okta/okta-3-saml-settings-bottom.png and b/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/okta/okta-3-saml-settings-bottom.png differ diff --git a/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/okta/okta-3-saml-settings-top.png b/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/okta/okta-3-saml-settings-top.png index 81cc6d4bebe..53876b8af50 100644 Binary files a/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/okta/okta-3-saml-settings-top.png and b/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/okta/okta-3-saml-settings-top.png differ diff --git a/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/okta/okta-4-feedback.png b/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/okta/okta-4-feedback.png index 9c36919a99c..55a451c57db 100644 Binary files a/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/okta/okta-4-feedback.png and b/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/okta/okta-4-feedback.png differ diff --git a/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/okta/okta-5-instructions.png b/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/okta/okta-5-instructions.png index fee8bacc011..cbbdb1cf193 100644 Binary files a/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/okta/okta-5-instructions.png and b/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/okta/okta-5-instructions.png differ diff --git a/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/okta/okta-5-view-instructions.png b/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/okta/okta-5-view-instructions.png index 4c9e29a39fd..9cf547e7ee7 100644 Binary files a/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/okta/okta-5-view-instructions.png and b/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/okta/okta-5-view-instructions.png differ diff --git a/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/okta/okta-6-setup-integration.png b/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/okta/okta-6-setup-integration.png index f58a47f9333..acf8395663f 100644 Binary files a/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/okta/okta-6-setup-integration.png and b/website/static/img/docs/dbt-cloud/dbt-cloud-enterprise/okta/okta-6-setup-integration.png differ diff --git a/website/static/img/docs/dbt-cloud/dbt-docs-generate-command.png b/website/static/img/docs/dbt-cloud/dbt-docs-generate-command.png new file mode 100644 index 00000000000..2e9bc318dc5 Binary files /dev/null and b/website/static/img/docs/dbt-cloud/dbt-docs-generate-command.png differ diff --git a/website/static/img/docs/dbt-cloud/dbt-quickstart-connection.png b/website/static/img/docs/dbt-cloud/dbt-quickstart-connection.png index 00ae07b69d0..bc49b6c9400 100644 Binary files a/website/static/img/docs/dbt-cloud/dbt-quickstart-connection.png and b/website/static/img/docs/dbt-cloud/dbt-quickstart-connection.png differ diff --git a/website/static/img/docs/dbt-cloud/dbt-quickstart-environment.png b/website/static/img/docs/dbt-cloud/dbt-quickstart-environment.png index c519294e546..565fd248815 100644 Binary files a/website/static/img/docs/dbt-cloud/dbt-quickstart-environment.png and b/website/static/img/docs/dbt-cloud/dbt-quickstart-environment.png differ diff --git a/website/static/img/docs/dbt-cloud/dbt-quickstart-new-job-schedule.png b/website/static/img/docs/dbt-cloud/dbt-quickstart-new-job-schedule.png index 82c31a5482f..22838440554 100644 Binary files a/website/static/img/docs/dbt-cloud/dbt-quickstart-new-job-schedule.png and b/website/static/img/docs/dbt-cloud/dbt-quickstart-new-job-schedule.png differ diff --git a/website/static/img/docs/dbt-cloud/dbt-quickstart-new-job.png b/website/static/img/docs/dbt-cloud/dbt-quickstart-new-job.png index e509e4b45ac..bae0b6f486d 100644 Binary files a/website/static/img/docs/dbt-cloud/dbt-quickstart-new-job.png and b/website/static/img/docs/dbt-cloud/dbt-quickstart-new-job.png differ diff --git a/website/static/img/docs/dbt-cloud/dbt-quickstart-repository.png b/website/static/img/docs/dbt-cloud/dbt-quickstart-repository.png index 584d8e6a591..c015709d7b4 100644 Binary files a/website/static/img/docs/dbt-cloud/dbt-quickstart-repository.png and b/website/static/img/docs/dbt-cloud/dbt-quickstart-repository.png differ diff --git a/website/static/img/docs/dbt-cloud/dbt-run-logs.png b/website/static/img/docs/dbt-cloud/dbt-run-logs.png new file mode 100644 index 00000000000..f9886ccba4f Binary files /dev/null and b/website/static/img/docs/dbt-cloud/dbt-run-logs.png differ diff --git a/website/static/img/docs/dbt-cloud/dbt_cloud_gitlab_application_settings.png b/website/static/img/docs/dbt-cloud/dbt_cloud_gitlab_application_settings.png index d7fc368e14b..f35a9722683 100644 Binary files a/website/static/img/docs/dbt-cloud/dbt_cloud_gitlab_application_settings.png and b/website/static/img/docs/dbt-cloud/dbt_cloud_gitlab_application_settings.png differ diff --git a/website/static/img/docs/dbt-cloud/deployment/aws-network-architecture.png b/website/static/img/docs/dbt-cloud/deployment/aws-network-architecture.png index 6316c5f21bb..1dc2de876cb 100644 Binary files a/website/static/img/docs/dbt-cloud/deployment/aws-network-architecture.png and b/website/static/img/docs/dbt-cloud/deployment/aws-network-architecture.png differ diff --git a/website/static/img/docs/dbt-cloud/overview-job-schedule.gif b/website/static/img/docs/dbt-cloud/overview-job-schedule.gif new file mode 100644 index 00000000000..c9848e5d654 Binary files /dev/null and b/website/static/img/docs/dbt-cloud/overview-job-schedule.gif differ diff --git a/website/static/img/docs/dbt-cloud/select-source-freshness.png b/website/static/img/docs/dbt-cloud/select-source-freshness.png index 511d3385f66..8ca6a7eec8c 100644 Binary files a/website/static/img/docs/dbt-cloud/select-source-freshness.png and b/website/static/img/docs/dbt-cloud/select-source-freshness.png differ diff --git a/website/static/img/docs/dbt-cloud/snowflake-conn-details.png b/website/static/img/docs/dbt-cloud/snowflake-conn-details.png index 450e4560895..3d55ebb3bab 100644 Binary files a/website/static/img/docs/dbt-cloud/snowflake-conn-details.png and b/website/static/img/docs/dbt-cloud/snowflake-conn-details.png differ diff --git a/website/static/img/docs/dbt-cloud/snowflake-keypair-auth.png b/website/static/img/docs/dbt-cloud/snowflake-keypair-auth.png index 40aa21a5a8c..7f0e29de590 100644 Binary files a/website/static/img/docs/dbt-cloud/snowflake-keypair-auth.png and b/website/static/img/docs/dbt-cloud/snowflake-keypair-auth.png differ diff --git a/website/static/img/docs/dbt-cloud/snowflake-userpass-auth.png b/website/static/img/docs/dbt-cloud/snowflake-userpass-auth.png index ecc4ee91f2f..2dc87cabe32 100644 Binary files a/website/static/img/docs/dbt-cloud/snowflake-userpass-auth.png and b/website/static/img/docs/dbt-cloud/snowflake-userpass-auth.png differ diff --git a/website/static/img/docs/dbt-cloud/using-dbt-cloud/3c3c1ca-Screen_Shot_2019-03-21_at_11.05.28_AM.png b/website/static/img/docs/dbt-cloud/using-dbt-cloud/3c3c1ca-Screen_Shot_2019-03-21_at_11.05.28_AM.png deleted file mode 100644 index a60b91b8d66..00000000000 Binary files a/website/static/img/docs/dbt-cloud/using-dbt-cloud/3c3c1ca-Screen_Shot_2019-03-21_at_11.05.28_AM.png and /dev/null differ diff --git a/website/static/img/docs/dbt-cloud/using-dbt-cloud/568adab-Screen_Shot_2019-02-08_at_9.13.09_PM.png b/website/static/img/docs/dbt-cloud/using-dbt-cloud/568adab-Screen_Shot_2019-02-08_at_9.13.09_PM.png deleted file mode 100644 index 780d4c48a0c..00000000000 Binary files a/website/static/img/docs/dbt-cloud/using-dbt-cloud/568adab-Screen_Shot_2019-02-08_at_9.13.09_PM.png and /dev/null differ diff --git a/website/static/img/docs/dbt-cloud/using-dbt-cloud/60f3fa2-Screen_Shot_2019-02-08_at_10.33.20_PM.png b/website/static/img/docs/dbt-cloud/using-dbt-cloud/60f3fa2-Screen_Shot_2019-02-08_at_10.33.20_PM.png deleted file mode 100644 index de4c52f8c89..00000000000 Binary files a/website/static/img/docs/dbt-cloud/using-dbt-cloud/60f3fa2-Screen_Shot_2019-02-08_at_10.33.20_PM.png and /dev/null differ diff --git a/website/static/img/docs/dbt-cloud/using-dbt-cloud/61536c9-Screen_Shot_2019-02-08_at_9.46.29_PM.png b/website/static/img/docs/dbt-cloud/using-dbt-cloud/61536c9-Screen_Shot_2019-02-08_at_9.46.29_PM.png index c6fb2282839..1fd34b2f29d 100644 Binary files a/website/static/img/docs/dbt-cloud/using-dbt-cloud/61536c9-Screen_Shot_2019-02-08_at_9.46.29_PM.png and b/website/static/img/docs/dbt-cloud/using-dbt-cloud/61536c9-Screen_Shot_2019-02-08_at_9.46.29_PM.png differ diff --git a/website/static/img/docs/dbt-cloud/using-dbt-cloud/98c05c5-Screen_Shot_2019-02-08_at_9.18.22_PM.png b/website/static/img/docs/dbt-cloud/using-dbt-cloud/98c05c5-Screen_Shot_2019-02-08_at_9.18.22_PM.png index 11e4e26b29b..fc11996726c 100644 Binary files a/website/static/img/docs/dbt-cloud/using-dbt-cloud/98c05c5-Screen_Shot_2019-02-08_at_9.18.22_PM.png and b/website/static/img/docs/dbt-cloud/using-dbt-cloud/98c05c5-Screen_Shot_2019-02-08_at_9.18.22_PM.png differ diff --git a/website/static/img/docs/dbt-cloud/using-dbt-cloud/Enabling-CI/ADO CI.png b/website/static/img/docs/dbt-cloud/using-dbt-cloud/Enabling-CI/ADO CI.png new file mode 100644 index 00000000000..b83406d2c5a Binary files /dev/null and b/website/static/img/docs/dbt-cloud/using-dbt-cloud/Enabling-CI/ADO CI.png differ diff --git a/website/static/img/docs/dbt-cloud/using-dbt-cloud/Enabling-CI/Disconnect-Repository.png b/website/static/img/docs/dbt-cloud/using-dbt-cloud/Enabling-CI/Disconnect-Repository.png index 7e657e2a0a8..58b07f42047 100644 Binary files a/website/static/img/docs/dbt-cloud/using-dbt-cloud/Enabling-CI/Disconnect-Repository.png and b/website/static/img/docs/dbt-cloud/using-dbt-cloud/Enabling-CI/Disconnect-Repository.png differ diff --git a/website/static/img/docs/dbt-cloud/using-dbt-cloud/Enabling-CI/repo-config.png b/website/static/img/docs/dbt-cloud/using-dbt-cloud/Enabling-CI/repo-config.png index 5f944102f5a..b49c1887039 100644 Binary files a/website/static/img/docs/dbt-cloud/using-dbt-cloud/Enabling-CI/repo-config.png and b/website/static/img/docs/dbt-cloud/using-dbt-cloud/Enabling-CI/repo-config.png differ diff --git a/website/static/img/docs/dbt-cloud/using-dbt-cloud/Environment Variables/DBT_ENV_SECRET.png b/website/static/img/docs/dbt-cloud/using-dbt-cloud/Environment Variables/DBT_ENV_SECRET.png index b768f27803f..2a8b17dac70 100644 Binary files a/website/static/img/docs/dbt-cloud/using-dbt-cloud/Environment Variables/DBT_ENV_SECRET.png and b/website/static/img/docs/dbt-cloud/using-dbt-cloud/Environment Variables/DBT_ENV_SECRET.png differ diff --git a/website/static/img/docs/dbt-cloud/using-dbt-cloud/Environment Variables/job-override.gif b/website/static/img/docs/dbt-cloud/using-dbt-cloud/Environment Variables/job-override.gif index e8c71a1360d..f513c5170b1 100644 Binary files a/website/static/img/docs/dbt-cloud/using-dbt-cloud/Environment Variables/job-override.gif and b/website/static/img/docs/dbt-cloud/using-dbt-cloud/Environment Variables/job-override.gif differ diff --git a/website/static/img/docs/dbt-cloud/using-dbt-cloud/Environment Variables/job-override.png b/website/static/img/docs/dbt-cloud/using-dbt-cloud/Environment Variables/job-override.png index 3eac8bb095a..6467b0d0fa9 100644 Binary files a/website/static/img/docs/dbt-cloud/using-dbt-cloud/Environment Variables/job-override.png and b/website/static/img/docs/dbt-cloud/using-dbt-cloud/Environment Variables/job-override.png differ diff --git a/website/static/img/docs/dbt-cloud/using-dbt-cloud/Environment Variables/navigate-to-env-vars.gif b/website/static/img/docs/dbt-cloud/using-dbt-cloud/Environment Variables/navigate-to-env-vars.gif index 5e964d45d33..5ae365c4244 100644 Binary files a/website/static/img/docs/dbt-cloud/using-dbt-cloud/Environment Variables/navigate-to-env-vars.gif and b/website/static/img/docs/dbt-cloud/using-dbt-cloud/Environment Variables/navigate-to-env-vars.gif differ diff --git a/website/static/img/docs/dbt-cloud/using-dbt-cloud/Environment Variables/personal-override.gif b/website/static/img/docs/dbt-cloud/using-dbt-cloud/Environment Variables/personal-override.gif index 3244966d967..9eabb2458de 100644 Binary files a/website/static/img/docs/dbt-cloud/using-dbt-cloud/Environment Variables/personal-override.gif and b/website/static/img/docs/dbt-cloud/using-dbt-cloud/Environment Variables/personal-override.gif differ diff --git a/website/static/img/docs/dbt-cloud/using-dbt-cloud/Environment Variables/personal-override.png b/website/static/img/docs/dbt-cloud/using-dbt-cloud/Environment Variables/personal-override.png index 0df7461065d..505461fea48 100644 Binary files a/website/static/img/docs/dbt-cloud/using-dbt-cloud/Environment Variables/personal-override.png and b/website/static/img/docs/dbt-cloud/using-dbt-cloud/Environment Variables/personal-override.png differ diff --git a/website/static/img/docs/dbt-cloud/using-dbt-cloud/Environment Variables/project-environment-view.png b/website/static/img/docs/dbt-cloud/using-dbt-cloud/Environment Variables/project-environment-view.png index b3bdf505589..a973448c032 100644 Binary files a/website/static/img/docs/dbt-cloud/using-dbt-cloud/Environment Variables/project-environment-view.png and b/website/static/img/docs/dbt-cloud/using-dbt-cloud/Environment Variables/project-environment-view.png differ diff --git a/website/static/img/docs/dbt-cloud/using-dbt-cloud/Environment Variables/warehouse-override.png b/website/static/img/docs/dbt-cloud/using-dbt-cloud/Environment Variables/warehouse-override.png index d067fc37f7c..25c7ce3edd5 100644 Binary files a/website/static/img/docs/dbt-cloud/using-dbt-cloud/Environment Variables/warehouse-override.png and b/website/static/img/docs/dbt-cloud/using-dbt-cloud/Environment Variables/warehouse-override.png differ diff --git a/website/static/img/docs/dbt-cloud/using-dbt-cloud/ci-deferral.png b/website/static/img/docs/dbt-cloud/using-dbt-cloud/ci-deferral.png index 0eca99ad59b..5186b0a9a76 100644 Binary files a/website/static/img/docs/dbt-cloud/using-dbt-cloud/ci-deferral.png and b/website/static/img/docs/dbt-cloud/using-dbt-cloud/ci-deferral.png differ diff --git a/website/static/img/docs/dbt-cloud/using-dbt-cloud/d43d5e6-job-schedule.gif b/website/static/img/docs/dbt-cloud/using-dbt-cloud/d43d5e6-job-schedule.gif deleted file mode 100644 index 8d6cd95defc..00000000000 Binary files a/website/static/img/docs/dbt-cloud/using-dbt-cloud/d43d5e6-job-schedule.gif and /dev/null differ diff --git a/website/static/img/docs/dbt-cloud/using-dbt-cloud/dashboard-status-tiles/tableau-object.png b/website/static/img/docs/dbt-cloud/using-dbt-cloud/dashboard-status-tiles/tableau-object.png new file mode 100644 index 00000000000..3125cda7335 Binary files /dev/null and b/website/static/img/docs/dbt-cloud/using-dbt-cloud/dashboard-status-tiles/tableau-object.png differ diff --git a/website/static/img/docs/dbt-cloud/using-dbt-cloud/data-sources-next.png b/website/static/img/docs/dbt-cloud/using-dbt-cloud/data-sources-next.png new file mode 100644 index 00000000000..f4db3f40638 Binary files /dev/null and b/website/static/img/docs/dbt-cloud/using-dbt-cloud/data-sources-next.png differ diff --git a/website/static/img/docs/dbt-cloud/using-dbt-cloud/data-sources.png b/website/static/img/docs/dbt-cloud/using-dbt-cloud/data-sources.png index ce34963b056..c8ee5c8f684 100644 Binary files a/website/static/img/docs/dbt-cloud/using-dbt-cloud/data-sources.png and b/website/static/img/docs/dbt-cloud/using-dbt-cloud/data-sources.png differ diff --git a/website/static/img/docs/dbt-cloud/using-dbt-cloud/dbt-cloud-enterprise/BQ-auth/BQ-access.png b/website/static/img/docs/dbt-cloud/using-dbt-cloud/dbt-cloud-enterprise/BQ-auth/BQ-access.png new file mode 100644 index 00000000000..3ac8118710d Binary files /dev/null and b/website/static/img/docs/dbt-cloud/using-dbt-cloud/dbt-cloud-enterprise/BQ-auth/BQ-access.png differ diff --git a/website/static/img/docs/dbt-cloud/using-dbt-cloud/dbt-cloud-enterprise/BQ-auth/BQ-nav.gif b/website/static/img/docs/dbt-cloud/using-dbt-cloud/dbt-cloud-enterprise/BQ-auth/BQ-nav.gif new file mode 100644 index 00000000000..27e3caf39cc Binary files /dev/null and b/website/static/img/docs/dbt-cloud/using-dbt-cloud/dbt-cloud-enterprise/BQ-auth/BQ-nav.gif differ diff --git a/website/static/img/docs/dbt-cloud/using-dbt-cloud/dbt-cloud-enterprise/BQ-auth/bq-oauth-app.gif b/website/static/img/docs/dbt-cloud/using-dbt-cloud/dbt-cloud-enterprise/BQ-auth/bq-oauth-app.gif new file mode 100644 index 00000000000..071263396f1 Binary files /dev/null and b/website/static/img/docs/dbt-cloud/using-dbt-cloud/dbt-cloud-enterprise/BQ-auth/bq-oauth-app.gif differ diff --git a/website/static/img/docs/dbt-cloud/using-dbt-cloud/dbt-cloud-enterprise/BQ-auth/dbt-cloud-bq-id-secret.gif b/website/static/img/docs/dbt-cloud/using-dbt-cloud/dbt-cloud-enterprise/BQ-auth/dbt-cloud-bq-id-secret.gif new file mode 100644 index 00000000000..0545fb853a3 Binary files /dev/null and b/website/static/img/docs/dbt-cloud/using-dbt-cloud/dbt-cloud-enterprise/BQ-auth/dbt-cloud-bq-id-secret.gif differ diff --git a/website/static/img/docs/dbt-cloud/using-dbt-cloud/dbt-cloud-enterprise/developer-bq-auth.gif b/website/static/img/docs/dbt-cloud/using-dbt-cloud/dbt-cloud-enterprise/developer-bq-auth.gif new file mode 100644 index 00000000000..b3d1f82751c Binary files /dev/null and b/website/static/img/docs/dbt-cloud/using-dbt-cloud/dbt-cloud-enterprise/developer-bq-auth.gif differ diff --git a/website/static/img/docs/dbt-cloud/using-dbt-cloud/development-credentials.png b/website/static/img/docs/dbt-cloud/using-dbt-cloud/development-credentials.png index d6502609e1b..7eea1bddf32 100644 Binary files a/website/static/img/docs/dbt-cloud/using-dbt-cloud/development-credentials.png and b/website/static/img/docs/dbt-cloud/using-dbt-cloud/development-credentials.png differ diff --git a/website/static/img/docs/dbt-cloud/using-dbt-cloud/doc-menu.png b/website/static/img/docs/dbt-cloud/using-dbt-cloud/doc-menu.png index 66b4de030ac..9fb71acafff 100644 Binary files a/website/static/img/docs/dbt-cloud/using-dbt-cloud/doc-menu.png and b/website/static/img/docs/dbt-cloud/using-dbt-cloud/doc-menu.png differ diff --git a/website/static/img/docs/dbt-cloud/using-dbt-cloud/documentation-job-execution-settings.png b/website/static/img/docs/dbt-cloud/using-dbt-cloud/documentation-job-execution-settings.png new file mode 100644 index 00000000000..b8db4ab22d2 Binary files /dev/null and b/website/static/img/docs/dbt-cloud/using-dbt-cloud/documentation-job-execution-settings.png differ diff --git a/website/static/img/docs/dbt-cloud/using-dbt-cloud/documentation-project-details.png b/website/static/img/docs/dbt-cloud/using-dbt-cloud/documentation-project-details.png new file mode 100644 index 00000000000..6b1aad38f2e Binary files /dev/null and b/website/static/img/docs/dbt-cloud/using-dbt-cloud/documentation-project-details.png differ diff --git a/website/static/img/docs/dbt-cloud/using-dbt-cloud/edit-job-generate-artifacts.png b/website/static/img/docs/dbt-cloud/using-dbt-cloud/edit-job-generate-artifacts.png new file mode 100644 index 00000000000..365e2a4a9e1 Binary files /dev/null and b/website/static/img/docs/dbt-cloud/using-dbt-cloud/edit-job-generate-artifacts.png differ diff --git a/website/static/img/docs/dbt-cloud/using-dbt-cloud/email-notifications.png b/website/static/img/docs/dbt-cloud/using-dbt-cloud/email-notifications.png new file mode 100644 index 00000000000..7e77098d63e Binary files /dev/null and b/website/static/img/docs/dbt-cloud/using-dbt-cloud/email-notifications.png differ diff --git a/website/static/img/docs/dbt-cloud/using-dbt-cloud/job-schedule.png b/website/static/img/docs/dbt-cloud/using-dbt-cloud/job-schedule.png new file mode 100644 index 00000000000..58bb199aeeb Binary files /dev/null and b/website/static/img/docs/dbt-cloud/using-dbt-cloud/job-schedule.png differ diff --git a/website/static/img/docs/dbt-cloud/using-dbt-cloud/job-step-source-freshness.png b/website/static/img/docs/dbt-cloud/using-dbt-cloud/job-step-source-freshness.png index 8a10b76236a..cc027ef58f9 100644 Binary files a/website/static/img/docs/dbt-cloud/using-dbt-cloud/job-step-source-freshness.png and b/website/static/img/docs/dbt-cloud/using-dbt-cloud/job-step-source-freshness.png differ diff --git a/website/static/img/docs/dbt-cloud/using-dbt-cloud/jobs-settings-target-name.png b/website/static/img/docs/dbt-cloud/using-dbt-cloud/jobs-settings-target-name.png new file mode 100644 index 00000000000..eaeb4b65c3f Binary files /dev/null and b/website/static/img/docs/dbt-cloud/using-dbt-cloud/jobs-settings-target-name.png differ diff --git a/website/static/img/docs/dbt-cloud/using-dbt-cloud/project-level-artifact-updated.gif b/website/static/img/docs/dbt-cloud/using-dbt-cloud/project-level-artifact-updated.gif deleted file mode 100644 index 8fb3fd8015e..00000000000 Binary files a/website/static/img/docs/dbt-cloud/using-dbt-cloud/project-level-artifact-updated.gif and /dev/null differ diff --git a/website/static/img/docs/dbt-cloud/using-dbt-cloud/project-level-artifact-updated.png b/website/static/img/docs/dbt-cloud/using-dbt-cloud/project-level-artifact-updated.png new file mode 100644 index 00000000000..6ec0c9b32f0 Binary files /dev/null and b/website/static/img/docs/dbt-cloud/using-dbt-cloud/project-level-artifact-updated.png differ diff --git a/website/static/img/docs/dbt-cloud/using-dbt-cloud/project-level-artifacts.png b/website/static/img/docs/dbt-cloud/using-dbt-cloud/project-level-artifacts.png deleted file mode 100644 index be4661c85c2..00000000000 Binary files a/website/static/img/docs/dbt-cloud/using-dbt-cloud/project-level-artifacts.png and /dev/null differ diff --git a/website/static/img/docs/dbt-cloud/using-dbt-cloud/using_ci_dbt_cloud.png b/website/static/img/docs/dbt-cloud/using-dbt-cloud/using_ci_dbt_cloud.png index bb6410e4ffc..63fa5a1450d 100644 Binary files a/website/static/img/docs/dbt-cloud/using-dbt-cloud/using_ci_dbt_cloud.png and b/website/static/img/docs/dbt-cloud/using-dbt-cloud/using_ci_dbt_cloud.png differ diff --git a/website/static/img/docs/dbt-cloud/using-dbt-cloud/viewing-docs.gif b/website/static/img/docs/dbt-cloud/using-dbt-cloud/viewing-docs.gif new file mode 100644 index 00000000000..0f15c867ac4 Binary files /dev/null and b/website/static/img/docs/dbt-cloud/using-dbt-cloud/viewing-docs.gif differ diff --git a/website/static/img/docs/dbt-cloud/v1.1.46releasenotes_img1.png b/website/static/img/docs/dbt-cloud/v1.1.46releasenotes_img1.png new file mode 100644 index 00000000000..3f92858f88f Binary files /dev/null and b/website/static/img/docs/dbt-cloud/v1.1.46releasenotes_img1.png differ diff --git a/website/static/img/docs/reference/bigquery-query-comment-job-labels.png b/website/static/img/docs/reference/bigquery-query-comment-job-labels.png index d029c516e57..cb79cb0c566 100644 Binary files a/website/static/img/docs/reference/bigquery-query-comment-job-labels.png and b/website/static/img/docs/reference/bigquery-query-comment-job-labels.png differ diff --git a/website/static/img/docs/running-a-dbt-project/0d9f366-Screen_Shot_2019-11-19_at_12.13.28_PM.png b/website/static/img/docs/running-a-dbt-project/0d9f366-Screen_Shot_2019-11-19_at_12.13.28_PM.png deleted file mode 100644 index e9dd0437967..00000000000 Binary files a/website/static/img/docs/running-a-dbt-project/0d9f366-Screen_Shot_2019-11-19_at_12.13.28_PM.png and /dev/null differ diff --git a/website/static/img/docs/running-a-dbt-project/65fb95f-Screen_Shot_2019-11-19_at_11.30.00_AM.png b/website/static/img/docs/running-a-dbt-project/65fb95f-Screen_Shot_2019-11-19_at_11.30.00_AM.png deleted file mode 100644 index 50c442ec1ed..00000000000 Binary files a/website/static/img/docs/running-a-dbt-project/65fb95f-Screen_Shot_2019-11-19_at_11.30.00_AM.png and /dev/null differ diff --git a/website/static/img/docs/running-a-dbt-project/8e7a6eb-cloud-img.png b/website/static/img/docs/running-a-dbt-project/8e7a6eb-cloud-img.png deleted file mode 100644 index 3975ac5b53b..00000000000 Binary files a/website/static/img/docs/running-a-dbt-project/8e7a6eb-cloud-img.png and /dev/null differ diff --git a/website/static/img/docs/running-a-dbt-project/a810a20-Screen_Shot_2019-11-19_at_11.26.55_AM.png b/website/static/img/docs/running-a-dbt-project/a810a20-Screen_Shot_2019-11-19_at_11.26.55_AM.png deleted file mode 100644 index 54344121cbf..00000000000 Binary files a/website/static/img/docs/running-a-dbt-project/a810a20-Screen_Shot_2019-11-19_at_11.26.55_AM.png and /dev/null differ diff --git a/website/static/img/docs/running-a-dbt-project/abbd17c-Screen_Shot_2019-11-11_at_12.20.29_PM.png b/website/static/img/docs/running-a-dbt-project/abbd17c-Screen_Shot_2019-11-11_at_12.20.29_PM.png index 0ab7853dab2..aa9b0e13bfb 100644 Binary files a/website/static/img/docs/running-a-dbt-project/abbd17c-Screen_Shot_2019-11-11_at_12.20.29_PM.png and b/website/static/img/docs/running-a-dbt-project/abbd17c-Screen_Shot_2019-11-11_at_12.20.29_PM.png differ diff --git a/website/static/img/docs/running-a-dbt-project/airflow_dbt_connector.png b/website/static/img/docs/running-a-dbt-project/airflow_dbt_connector.png new file mode 100644 index 00000000000..bb771af6287 Binary files /dev/null and b/website/static/img/docs/running-a-dbt-project/airflow_dbt_connector.png differ diff --git a/website/static/img/docs/running-a-dbt-project/dbt_cloud_airflow_trigger.png b/website/static/img/docs/running-a-dbt-project/dbt_cloud_airflow_trigger.png new file mode 100644 index 00000000000..892370656c0 Binary files /dev/null and b/website/static/img/docs/running-a-dbt-project/dbt_cloud_airflow_trigger.png differ diff --git a/website/static/img/docs/running-a-dbt-project/ec04c10-Screen_Shot_2019-11-19_at_12.13.46_PM.png b/website/static/img/docs/running-a-dbt-project/ec04c10-Screen_Shot_2019-11-19_at_12.13.46_PM.png deleted file mode 100644 index 7db6bdc3f7b..00000000000 Binary files a/website/static/img/docs/running-a-dbt-project/ec04c10-Screen_Shot_2019-11-19_at_12.13.46_PM.png and /dev/null differ diff --git a/website/static/img/docs/running-a-dbt-project/using-the-dbt-ide/create-dev-env.png b/website/static/img/docs/running-a-dbt-project/using-the-dbt-ide/create-dev-env.png new file mode 100644 index 00000000000..6e27d9922b8 Binary files /dev/null and b/website/static/img/docs/running-a-dbt-project/using-the-dbt-ide/create-dev-env.png differ diff --git a/website/static/img/docs/running-a-dbt-project/using-the-dbt-ide/dev-cred-edit-proj.png b/website/static/img/docs/running-a-dbt-project/using-the-dbt-ide/dev-cred-edit-proj.png new file mode 100644 index 00000000000..50ad975613b Binary files /dev/null and b/website/static/img/docs/running-a-dbt-project/using-the-dbt-ide/dev-cred-edit-proj.png differ diff --git a/website/static/img/docs/running-a-dbt-project/using-the-dbt-ide/dev-cred-project-setup.png b/website/static/img/docs/running-a-dbt-project/using-the-dbt-ide/dev-cred-project-setup.png new file mode 100644 index 00000000000..f907ff27edc Binary files /dev/null and b/website/static/img/docs/running-a-dbt-project/using-the-dbt-ide/dev-cred-project-setup.png differ diff --git a/website/static/img/docs/running-a-dbt-project/using-the-dbt-ide/empty-env-page.png b/website/static/img/docs/running-a-dbt-project/using-the-dbt-ide/empty-env-page.png new file mode 100644 index 00000000000..14444259f6e Binary files /dev/null and b/website/static/img/docs/running-a-dbt-project/using-the-dbt-ide/empty-env-page.png differ diff --git a/website/static/img/docs/terms/dag/bad_dag.png b/website/static/img/docs/terms/dag/bad_dag.png new file mode 100644 index 00000000000..99fe8f8c56f Binary files /dev/null and b/website/static/img/docs/terms/dag/bad_dag.png differ diff --git a/website/static/img/docs/terms/dag/lineage_graph.png b/website/static/img/docs/terms/dag/lineage_graph.png new file mode 100644 index 00000000000..a2b88adff87 Binary files /dev/null and b/website/static/img/docs/terms/dag/lineage_graph.png differ diff --git a/website/static/img/docs/terms/dag/mini_dag.png b/website/static/img/docs/terms/dag/mini_dag.png new file mode 100644 index 00000000000..19693581ab2 Binary files /dev/null and b/website/static/img/docs/terms/dag/mini_dag.png differ diff --git a/website/static/img/docs/terms/data-lineage/bad_dag.png b/website/static/img/docs/terms/data-lineage/bad_dag.png new file mode 100644 index 00000000000..99fe8f8c56f Binary files /dev/null and b/website/static/img/docs/terms/data-lineage/bad_dag.png differ diff --git a/website/static/img/docs/terms/data-lineage/dag_example.png b/website/static/img/docs/terms/data-lineage/dag_example.png new file mode 100644 index 00000000000..eb78ab0a0ca Binary files /dev/null and b/website/static/img/docs/terms/data-lineage/dag_example.png differ diff --git a/website/static/img/docs/terms/ddl/drop-a-table-meme.png b/website/static/img/docs/terms/ddl/drop-a-table-meme.png new file mode 100644 index 00000000000..393ebba4c30 Binary files /dev/null and b/website/static/img/docs/terms/ddl/drop-a-table-meme.png differ diff --git a/website/static/img/docs/terms/dimensional-modeling/fact-star.png b/website/static/img/docs/terms/dimensional-modeling/fact-star.png new file mode 100644 index 00000000000..22ebed964c1 Binary files /dev/null and b/website/static/img/docs/terms/dimensional-modeling/fact-star.png differ diff --git a/website/static/img/docs/terms/edw/meme.png b/website/static/img/docs/terms/edw/meme.png new file mode 100644 index 00000000000..7aa96ef8780 Binary files /dev/null and b/website/static/img/docs/terms/edw/meme.png differ diff --git a/website/static/img/docs/terms/elt/elt-diagram.png b/website/static/img/docs/terms/elt/elt-diagram.png new file mode 100644 index 00000000000..33196841b51 Binary files /dev/null and b/website/static/img/docs/terms/elt/elt-diagram.png differ diff --git a/website/static/img/docs/terms/etl/etl-diagram.png b/website/static/img/docs/terms/etl/etl-diagram.png new file mode 100644 index 00000000000..85a200a4f45 Binary files /dev/null and b/website/static/img/docs/terms/etl/etl-diagram.png differ diff --git a/website/static/img/docs/terms/reverse-etl/reverse-etl-diagram.png b/website/static/img/docs/terms/reverse-etl/reverse-etl-diagram.png new file mode 100644 index 00000000000..73acadd6953 Binary files /dev/null and b/website/static/img/docs/terms/reverse-etl/reverse-etl-diagram.png differ diff --git a/website/static/img/first-commit-dbt-cloud.png b/website/static/img/first-commit-dbt-cloud.png index 085e000e3f1..44f229ffaf2 100644 Binary files a/website/static/img/first-commit-dbt-cloud.png and b/website/static/img/first-commit-dbt-cloud.png differ diff --git a/website/static/img/first-model-dbt-cli.png b/website/static/img/first-model-dbt-cli.png index f42070134a0..045adff04df 100644 Binary files a/website/static/img/first-model-dbt-cli.png and b/website/static/img/first-model-dbt-cli.png differ diff --git a/website/static/img/first-model-dbt-cloud.png b/website/static/img/first-model-dbt-cloud.png index 93b25fc329d..46e15e7c643 100644 Binary files a/website/static/img/first-model-dbt-cloud.png and b/website/static/img/first-model-dbt-cloud.png differ diff --git a/website/static/img/guides/best-practices/how-we-structure/narrowing-dag.png b/website/static/img/guides/best-practices/how-we-structure/narrowing-dag.png new file mode 100644 index 00000000000..66fe71acc8f Binary files /dev/null and b/website/static/img/guides/best-practices/how-we-structure/narrowing-dag.png differ diff --git a/website/static/img/guides/best-practices/how-we-structure/widening-dag.png b/website/static/img/guides/best-practices/how-we-structure/widening-dag.png new file mode 100644 index 00000000000..13e987aa25e Binary files /dev/null and b/website/static/img/guides/best-practices/how-we-structure/widening-dag.png differ diff --git a/website/static/img/guides/orchestration/airflow-and-dbt-cloud/airflow-connections-menu.png b/website/static/img/guides/orchestration/airflow-and-dbt-cloud/airflow-connections-menu.png new file mode 100644 index 00000000000..7a55d0bbad0 Binary files /dev/null and b/website/static/img/guides/orchestration/airflow-and-dbt-cloud/airflow-connections-menu.png differ diff --git a/website/static/img/guides/orchestration/airflow-and-dbt-cloud/airflow-dag.png b/website/static/img/guides/orchestration/airflow-and-dbt-cloud/airflow-dag.png new file mode 100644 index 00000000000..3c491d484a5 Binary files /dev/null and b/website/static/img/guides/orchestration/airflow-and-dbt-cloud/airflow-dag.png differ diff --git a/website/static/img/guides/orchestration/airflow-and-dbt-cloud/airflow-login.png b/website/static/img/guides/orchestration/airflow-and-dbt-cloud/airflow-login.png new file mode 100644 index 00000000000..a3fa42efe15 Binary files /dev/null and b/website/static/img/guides/orchestration/airflow-and-dbt-cloud/airflow-login.png differ diff --git a/website/static/img/guides/orchestration/airflow-and-dbt-cloud/approve-clearing.png b/website/static/img/guides/orchestration/airflow-and-dbt-cloud/approve-clearing.png new file mode 100644 index 00000000000..3cc7442189f Binary files /dev/null and b/website/static/img/guides/orchestration/airflow-and-dbt-cloud/approve-clearing.png differ diff --git a/website/static/img/guides/orchestration/airflow-and-dbt-cloud/clear-task-instance.png b/website/static/img/guides/orchestration/airflow-and-dbt-cloud/clear-task-instance.png new file mode 100644 index 00000000000..92ac3f1cd97 Binary files /dev/null and b/website/static/img/guides/orchestration/airflow-and-dbt-cloud/clear-task-instance.png differ diff --git a/website/static/img/guides/orchestration/airflow-and-dbt-cloud/connection-type.png b/website/static/img/guides/orchestration/airflow-and-dbt-cloud/connection-type.png new file mode 100644 index 00000000000..d64163d6173 Binary files /dev/null and b/website/static/img/guides/orchestration/airflow-and-dbt-cloud/connection-type.png differ diff --git a/website/static/img/guides/orchestration/airflow-and-dbt-cloud/create-connection.png b/website/static/img/guides/orchestration/airflow-and-dbt-cloud/create-connection.png new file mode 100644 index 00000000000..b6b2ecc412b Binary files /dev/null and b/website/static/img/guides/orchestration/airflow-and-dbt-cloud/create-connection.png differ diff --git a/website/static/img/guides/orchestration/airflow-and-dbt-cloud/re-run.png b/website/static/img/guides/orchestration/airflow-and-dbt-cloud/re-run.png new file mode 100644 index 00000000000..a57a6be01c5 Binary files /dev/null and b/website/static/img/guides/orchestration/airflow-and-dbt-cloud/re-run.png differ diff --git a/website/static/img/guides/orchestration/airflow-and-dbt-cloud/task-dag-view.png b/website/static/img/guides/orchestration/airflow-and-dbt-cloud/task-dag-view.png new file mode 100644 index 00000000000..3c491d484a5 Binary files /dev/null and b/website/static/img/guides/orchestration/airflow-and-dbt-cloud/task-dag-view.png differ diff --git a/website/static/img/guides/orchestration/airflow-and-dbt-cloud/task-run-instance.png b/website/static/img/guides/orchestration/airflow-and-dbt-cloud/task-run-instance.png new file mode 100644 index 00000000000..757515554e2 Binary files /dev/null and b/website/static/img/guides/orchestration/airflow-and-dbt-cloud/task-run-instance.png differ diff --git a/website/static/img/guides/orchestration/custom-cicd-pipelines/dbt-api-key-gitlab.png b/website/static/img/guides/orchestration/custom-cicd-pipelines/dbt-api-key-gitlab.png new file mode 100644 index 00000000000..b339f5aa9bd Binary files /dev/null and b/website/static/img/guides/orchestration/custom-cicd-pipelines/dbt-api-key-gitlab.png differ diff --git a/website/static/img/guides/orchestration/custom-cicd-pipelines/dbt-cloud-job-github-triggered.png b/website/static/img/guides/orchestration/custom-cicd-pipelines/dbt-cloud-job-github-triggered.png new file mode 100644 index 00000000000..8bff1464c30 Binary files /dev/null and b/website/static/img/guides/orchestration/custom-cicd-pipelines/dbt-cloud-job-github-triggered.png differ diff --git a/website/static/img/guides/orchestration/custom-cicd-pipelines/dbt-cloud-job-gitlab-triggered.png b/website/static/img/guides/orchestration/custom-cicd-pipelines/dbt-cloud-job-gitlab-triggered.png new file mode 100644 index 00000000000..5c0ad4b43f7 Binary files /dev/null and b/website/static/img/guides/orchestration/custom-cicd-pipelines/dbt-cloud-job-gitlab-triggered.png differ diff --git a/website/static/img/guides/orchestration/custom-cicd-pipelines/dbt-cloud-job-url.png b/website/static/img/guides/orchestration/custom-cicd-pipelines/dbt-cloud-job-url.png new file mode 100644 index 00000000000..3d06935abc1 Binary files /dev/null and b/website/static/img/guides/orchestration/custom-cicd-pipelines/dbt-cloud-job-url.png differ diff --git a/website/static/img/guides/orchestration/custom-cicd-pipelines/dbt-run-on-merge-github.png b/website/static/img/guides/orchestration/custom-cicd-pipelines/dbt-run-on-merge-github.png new file mode 100644 index 00000000000..d9106d5627c Binary files /dev/null and b/website/static/img/guides/orchestration/custom-cicd-pipelines/dbt-run-on-merge-github.png differ diff --git a/website/static/img/guides/orchestration/custom-cicd-pipelines/dbt-run-on-merge-gitlab.png b/website/static/img/guides/orchestration/custom-cicd-pipelines/dbt-run-on-merge-gitlab.png new file mode 100644 index 00000000000..1f7a102ace5 Binary files /dev/null and b/website/static/img/guides/orchestration/custom-cicd-pipelines/dbt-run-on-merge-gitlab.png differ diff --git a/website/static/img/guides/orchestration/custom-cicd-pipelines/dbt-service-token-page.png b/website/static/img/guides/orchestration/custom-cicd-pipelines/dbt-service-token-page.png new file mode 100644 index 00000000000..d213c03b83a Binary files /dev/null and b/website/static/img/guides/orchestration/custom-cicd-pipelines/dbt-service-token-page.png differ diff --git a/website/static/img/guides/orchestration/custom-cicd-pipelines/gitlab-cicd-payment-warning.png b/website/static/img/guides/orchestration/custom-cicd-pipelines/gitlab-cicd-payment-warning.png new file mode 100644 index 00000000000..7df73f200f2 Binary files /dev/null and b/website/static/img/guides/orchestration/custom-cicd-pipelines/gitlab-cicd-payment-warning.png differ diff --git a/website/static/img/guides/orchestration/custom-cicd-pipelines/lint-on-push-github.png b/website/static/img/guides/orchestration/custom-cicd-pipelines/lint-on-push-github.png new file mode 100644 index 00000000000..e21be5a8a7c Binary files /dev/null and b/website/static/img/guides/orchestration/custom-cicd-pipelines/lint-on-push-github.png differ diff --git a/website/static/img/guides/orchestration/custom-cicd-pipelines/lint-on-push-gitlab.png b/website/static/img/guides/orchestration/custom-cicd-pipelines/lint-on-push-gitlab.png new file mode 100644 index 00000000000..e232dddbe04 Binary files /dev/null and b/website/static/img/guides/orchestration/custom-cicd-pipelines/lint-on-push-gitlab.png differ diff --git a/website/static/img/guides/orchestration/custom-cicd-pipelines/lint-on-push-logs-github.png b/website/static/img/guides/orchestration/custom-cicd-pipelines/lint-on-push-logs-github.png new file mode 100644 index 00000000000..ea27ed6e527 Binary files /dev/null and b/website/static/img/guides/orchestration/custom-cicd-pipelines/lint-on-push-logs-github.png differ diff --git a/website/static/img/guides/orchestration/custom-cicd-pipelines/lint-on-push-logs-gitlab.png b/website/static/img/guides/orchestration/custom-cicd-pipelines/lint-on-push-logs-gitlab.png new file mode 100644 index 00000000000..f4fe49c97b1 Binary files /dev/null and b/website/static/img/guides/orchestration/custom-cicd-pipelines/lint-on-push-logs-gitlab.png differ diff --git a/website/static/img/guides/orchestration/custom-cicd-pipelines/pipeline-diagram.png b/website/static/img/guides/orchestration/custom-cicd-pipelines/pipeline-diagram.png new file mode 100644 index 00000000000..224a122246f Binary files /dev/null and b/website/static/img/guides/orchestration/custom-cicd-pipelines/pipeline-diagram.png differ diff --git a/website/static/img/guides/orchestration/custom-cicd-pipelines/pipeline-programs-diagram.png b/website/static/img/guides/orchestration/custom-cicd-pipelines/pipeline-programs-diagram.png new file mode 100644 index 00000000000..40e2912f087 Binary files /dev/null and b/website/static/img/guides/orchestration/custom-cicd-pipelines/pipeline-programs-diagram.png differ diff --git a/website/static/img/hamburger-icon.png b/website/static/img/hamburger-icon.png new file mode 100644 index 00000000000..dae6a8d726a Binary files /dev/null and b/website/static/img/hamburger-icon.png differ diff --git a/website/static/img/kebob-menu.png b/website/static/img/kebob-menu.png new file mode 100644 index 00000000000..f5d69e6a30c Binary files /dev/null and b/website/static/img/kebob-menu.png differ diff --git a/website/static/img/loader-icon.svg b/website/static/img/loader-icon.svg new file mode 100644 index 00000000000..b5003c3cfa2 --- /dev/null +++ b/website/static/img/loader-icon.svg @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/website/static/img/moon.svg b/website/static/img/moon.svg new file mode 100644 index 00000000000..09b2a867b79 --- /dev/null +++ b/website/static/img/moon.svg @@ -0,0 +1,3 @@ + + + diff --git a/website/static/img/node_color_example.png b/website/static/img/node_color_example.png new file mode 100644 index 00000000000..83b26f5735a Binary files /dev/null and b/website/static/img/node_color_example.png differ diff --git a/website/static/img/redshift_tutorial/images/IDE_initialize_project.png b/website/static/img/redshift_tutorial/images/IDE_initialize_project.png new file mode 100644 index 00000000000..4048f95e738 Binary files /dev/null and b/website/static/img/redshift_tutorial/images/IDE_initialize_project.png differ diff --git a/website/static/img/redshift_tutorial/images/choose_redshift.png b/website/static/img/redshift_tutorial/images/choose_redshift.png new file mode 100644 index 00000000000..992d0998f26 Binary files /dev/null and b/website/static/img/redshift_tutorial/images/choose_redshift.png differ diff --git a/website/static/img/redshift_tutorial/images/cloud_formation_in_progress.png b/website/static/img/redshift_tutorial/images/cloud_formation_in_progress.png new file mode 100644 index 00000000000..5df47c93adc Binary files /dev/null and b/website/static/img/redshift_tutorial/images/cloud_formation_in_progress.png differ diff --git a/website/static/img/redshift_tutorial/images/cluster_overview.png b/website/static/img/redshift_tutorial/images/cluster_overview.png new file mode 100644 index 00000000000..19f1e939c21 Binary files /dev/null and b/website/static/img/redshift_tutorial/images/cluster_overview.png differ diff --git a/website/static/img/redshift_tutorial/images/connect_to_redshift_cluster.png b/website/static/img/redshift_tutorial/images/connect_to_redshift_cluster.png new file mode 100644 index 00000000000..de0af4bcf30 Binary files /dev/null and b/website/static/img/redshift_tutorial/images/connect_to_redshift_cluster.png differ diff --git a/website/static/img/redshift_tutorial/images/copy_data.png b/website/static/img/redshift_tutorial/images/copy_data.png new file mode 100644 index 00000000000..d124c15e434 Binary files /dev/null and b/website/static/img/redshift_tutorial/images/copy_data.png differ diff --git a/website/static/img/redshift_tutorial/images/create_schemas.png b/website/static/img/redshift_tutorial/images/create_schemas.png new file mode 100644 index 00000000000..206b7a3a1b5 Binary files /dev/null and b/website/static/img/redshift_tutorial/images/create_schemas.png differ diff --git a/website/static/img/redshift_tutorial/images/dbt_cloud_redshift_account_settings.png b/website/static/img/redshift_tutorial/images/dbt_cloud_redshift_account_settings.png new file mode 100644 index 00000000000..38ec200ed91 Binary files /dev/null and b/website/static/img/redshift_tutorial/images/dbt_cloud_redshift_account_settings.png differ diff --git a/website/static/img/redshift_tutorial/images/dbt_cloud_redshift_development_credentials.png b/website/static/img/redshift_tutorial/images/dbt_cloud_redshift_development_credentials.png new file mode 100644 index 00000000000..523ba9f0c6c Binary files /dev/null and b/website/static/img/redshift_tutorial/images/dbt_cloud_redshift_development_credentials.png differ diff --git a/website/static/img/redshift_tutorial/images/dbt_cloud_setup_redshift_connection_start.png b/website/static/img/redshift_tutorial/images/dbt_cloud_setup_redshift_connection_start.png new file mode 100644 index 00000000000..8d2e5ffcb70 Binary files /dev/null and b/website/static/img/redshift_tutorial/images/dbt_cloud_setup_redshift_connection_start.png differ diff --git a/website/static/img/redshift_tutorial/images/go_to_S3.png b/website/static/img/redshift_tutorial/images/go_to_S3.png new file mode 100644 index 00000000000..99176a966fa Binary files /dev/null and b/website/static/img/redshift_tutorial/images/go_to_S3.png differ diff --git a/website/static/img/redshift_tutorial/images/go_to_redshift.png b/website/static/img/redshift_tutorial/images/go_to_redshift.png new file mode 100644 index 00000000000..39bf2c76dbb Binary files /dev/null and b/website/static/img/redshift_tutorial/images/go_to_redshift.png differ diff --git a/website/static/img/redshift_tutorial/images/redshift_query_editor.png b/website/static/img/redshift_tutorial/images/redshift_query_editor.png new file mode 100644 index 00000000000..bfe1ad70047 Binary files /dev/null and b/website/static/img/redshift_tutorial/images/redshift_query_editor.png differ diff --git a/website/static/img/redshift_tutorial/images/review_jaffle_shop.png b/website/static/img/redshift_tutorial/images/review_jaffle_shop.png new file mode 100644 index 00000000000..a5558ac5d39 Binary files /dev/null and b/website/static/img/redshift_tutorial/images/review_jaffle_shop.png differ diff --git a/website/static/img/redshift_tutorial/images/s3_bucket.png b/website/static/img/redshift_tutorial/images/s3_bucket.png new file mode 100644 index 00000000000..801bd0bffd6 Binary files /dev/null and b/website/static/img/redshift_tutorial/images/s3_bucket.png differ diff --git a/website/static/img/redshift_tutorial/images/select_jaffle_redshift.png b/website/static/img/redshift_tutorial/images/select_jaffle_redshift.png new file mode 100644 index 00000000000..29b5b7d1a04 Binary files /dev/null and b/website/static/img/redshift_tutorial/images/select_jaffle_redshift.png differ diff --git a/website/static/img/redshift_tutorial/images/setup_project.png b/website/static/img/redshift_tutorial/images/setup_project.png new file mode 100644 index 00000000000..9a6c19f86b3 Binary files /dev/null and b/website/static/img/redshift_tutorial/images/setup_project.png differ diff --git a/website/static/img/redshift_tutorial/images/upload_csv.png b/website/static/img/redshift_tutorial/images/upload_csv.png new file mode 100644 index 00000000000..074e51113cd Binary files /dev/null and b/website/static/img/redshift_tutorial/images/upload_csv.png differ diff --git a/website/static/img/snowflake_tutorial/dbt_cloud_account_info.png b/website/static/img/snowflake_tutorial/dbt_cloud_account_info.png new file mode 100644 index 00000000000..da0fb322284 Binary files /dev/null and b/website/static/img/snowflake_tutorial/dbt_cloud_account_info.png differ diff --git a/website/static/img/snowflake_tutorial/dbt_cloud_account_registration.png b/website/static/img/snowflake_tutorial/dbt_cloud_account_registration.png new file mode 100644 index 00000000000..e62b206e734 Binary files /dev/null and b/website/static/img/snowflake_tutorial/dbt_cloud_account_registration.png differ diff --git a/website/static/img/snowflake_tutorial/dbt_cloud_click_commit.png b/website/static/img/snowflake_tutorial/dbt_cloud_click_commit.png new file mode 100644 index 00000000000..791d4fcf46b Binary files /dev/null and b/website/static/img/snowflake_tutorial/dbt_cloud_click_commit.png differ diff --git a/website/static/img/snowflake_tutorial/dbt_cloud_connect_snowflake.png b/website/static/img/snowflake_tutorial/dbt_cloud_connect_snowflake.png new file mode 100644 index 00000000000..a272f9395b5 Binary files /dev/null and b/website/static/img/snowflake_tutorial/dbt_cloud_connect_snowflake.png differ diff --git a/website/static/img/snowflake_tutorial/dbt_cloud_dbt_run.png b/website/static/img/snowflake_tutorial/dbt_cloud_dbt_run.png new file mode 100644 index 00000000000..32864f9fd66 Binary files /dev/null and b/website/static/img/snowflake_tutorial/dbt_cloud_dbt_run.png differ diff --git a/website/static/img/snowflake_tutorial/dbt_cloud_initialize_your_project.png b/website/static/img/snowflake_tutorial/dbt_cloud_initialize_your_project.png new file mode 100644 index 00000000000..d5d3fd037b6 Binary files /dev/null and b/website/static/img/snowflake_tutorial/dbt_cloud_initialize_your_project.png differ diff --git a/website/static/img/snowflake_tutorial/dbt_cloud_preview_results.png b/website/static/img/snowflake_tutorial/dbt_cloud_preview_results.png new file mode 100644 index 00000000000..ecc4d27abb7 Binary files /dev/null and b/website/static/img/snowflake_tutorial/dbt_cloud_preview_results.png differ diff --git a/website/static/img/snowflake_tutorial/dbt_cloud_run_results.png b/website/static/img/snowflake_tutorial/dbt_cloud_run_results.png new file mode 100644 index 00000000000..c8e467c1daa Binary files /dev/null and b/website/static/img/snowflake_tutorial/dbt_cloud_run_results.png differ diff --git a/website/static/img/snowflake_tutorial/dbt_cloud_set_up_a_repository.png b/website/static/img/snowflake_tutorial/dbt_cloud_set_up_a_repository.png new file mode 100644 index 00000000000..31f37cc9249 Binary files /dev/null and b/website/static/img/snowflake_tutorial/dbt_cloud_set_up_a_repository.png differ diff --git a/website/static/img/snowflake_tutorial/dbt_cloud_setup.png b/website/static/img/snowflake_tutorial/dbt_cloud_setup.png new file mode 100644 index 00000000000..9d8bf5c65e9 Binary files /dev/null and b/website/static/img/snowflake_tutorial/dbt_cloud_setup.png differ diff --git a/website/static/img/snowflake_tutorial/dbt_cloud_setup_snowflake_connection_start.png b/website/static/img/snowflake_tutorial/dbt_cloud_setup_snowflake_connection_start.png new file mode 100644 index 00000000000..34e83360c7e Binary files /dev/null and b/website/static/img/snowflake_tutorial/dbt_cloud_setup_snowflake_connection_start.png differ diff --git a/website/static/img/snowflake_tutorial/dbt_cloud_snowflake_account_settings.png b/website/static/img/snowflake_tutorial/dbt_cloud_snowflake_account_settings.png new file mode 100644 index 00000000000..9084558d601 Binary files /dev/null and b/website/static/img/snowflake_tutorial/dbt_cloud_snowflake_account_settings.png differ diff --git a/website/static/img/snowflake_tutorial/dbt_cloud_snowflake_development_credentials.png b/website/static/img/snowflake_tutorial/dbt_cloud_snowflake_development_credentials.png new file mode 100644 index 00000000000..1e6187e2b2a Binary files /dev/null and b/website/static/img/snowflake_tutorial/dbt_cloud_snowflake_development_credentials.png differ diff --git a/website/static/img/snowflake_tutorial/dbt_cloud_snowflake_project_overview.png b/website/static/img/snowflake_tutorial/dbt_cloud_snowflake_project_overview.png new file mode 100644 index 00000000000..553384f3799 Binary files /dev/null and b/website/static/img/snowflake_tutorial/dbt_cloud_snowflake_project_overview.png differ diff --git a/website/static/img/snowflake_tutorial/dbt_cloud_update_database_and_warehouse.png b/website/static/img/snowflake_tutorial/dbt_cloud_update_database_and_warehouse.png new file mode 100644 index 00000000000..575060593e7 Binary files /dev/null and b/website/static/img/snowflake_tutorial/dbt_cloud_update_database_and_warehouse.png differ diff --git a/website/static/img/snowflake_tutorial/dbt_cloud_welcome_page.png b/website/static/img/snowflake_tutorial/dbt_cloud_welcome_page.png new file mode 100644 index 00000000000..b70e83aa92e Binary files /dev/null and b/website/static/img/snowflake_tutorial/dbt_cloud_welcome_page.png differ diff --git a/website/static/img/snowflake_tutorial/dbt_cloud_write_commit_message.png b/website/static/img/snowflake_tutorial/dbt_cloud_write_commit_message.png new file mode 100644 index 00000000000..54c6e7db965 Binary files /dev/null and b/website/static/img/snowflake_tutorial/dbt_cloud_write_commit_message.png differ diff --git a/website/static/img/snowflake_tutorial/snowflake_account_configuration.png b/website/static/img/snowflake_tutorial/snowflake_account_configuration.png new file mode 100644 index 00000000000..a5b23b7699f Binary files /dev/null and b/website/static/img/snowflake_tutorial/snowflake_account_configuration.png differ diff --git a/website/static/img/snowflake_tutorial/snowflake_account_signup.png b/website/static/img/snowflake_tutorial/snowflake_account_signup.png new file mode 100644 index 00000000000..252768d825b Binary files /dev/null and b/website/static/img/snowflake_tutorial/snowflake_account_signup.png differ diff --git a/website/static/img/snowflake_tutorial/snowflake_classic_ui_activation_window.png b/website/static/img/snowflake_tutorial/snowflake_classic_ui_activation_window.png new file mode 100644 index 00000000000..80d030d3309 Binary files /dev/null and b/website/static/img/snowflake_tutorial/snowflake_classic_ui_activation_window.png differ diff --git a/website/static/img/snowflake_tutorial/snowflake_classic_ui_connection_box.png b/website/static/img/snowflake_tutorial/snowflake_classic_ui_connection_box.png new file mode 100644 index 00000000000..7c1894b2f7a Binary files /dev/null and b/website/static/img/snowflake_tutorial/snowflake_classic_ui_connection_box.png differ diff --git a/website/static/img/snowflake_tutorial/snowflake_classic_ui_partner_connect.png b/website/static/img/snowflake_tutorial/snowflake_classic_ui_partner_connect.png new file mode 100644 index 00000000000..be8301b2195 Binary files /dev/null and b/website/static/img/snowflake_tutorial/snowflake_classic_ui_partner_connect.png differ diff --git a/website/static/img/snowflake_tutorial/snowflake_create_customers_table.png b/website/static/img/snowflake_tutorial/snowflake_create_customers_table.png new file mode 100644 index 00000000000..878fbb9ddf8 Binary files /dev/null and b/website/static/img/snowflake_tutorial/snowflake_create_customers_table.png differ diff --git a/website/static/img/snowflake_tutorial/snowflake_create_orders_table.png b/website/static/img/snowflake_tutorial/snowflake_create_orders_table.png new file mode 100644 index 00000000000..c97822be696 Binary files /dev/null and b/website/static/img/snowflake_tutorial/snowflake_create_orders_table.png differ diff --git a/website/static/img/snowflake_tutorial/snowflake_create_payments_table.png b/website/static/img/snowflake_tutorial/snowflake_create_payments_table.png new file mode 100644 index 00000000000..f0db1df3c90 Binary files /dev/null and b/website/static/img/snowflake_tutorial/snowflake_create_payments_table.png differ diff --git a/website/static/img/snowflake_tutorial/snowflake_create_warehouse_database_and_schema_commands.png b/website/static/img/snowflake_tutorial/snowflake_create_warehouse_database_and_schema_commands.png new file mode 100644 index 00000000000..d347d3732b5 Binary files /dev/null and b/website/static/img/snowflake_tutorial/snowflake_create_warehouse_database_and_schema_commands.png differ diff --git a/website/static/img/snowflake_tutorial/snowflake_free_trial_signup_form.png b/website/static/img/snowflake_tutorial/snowflake_free_trial_signup_form.png new file mode 100644 index 00000000000..b46dbfda06a Binary files /dev/null and b/website/static/img/snowflake_tutorial/snowflake_free_trial_signup_form.png differ diff --git a/website/static/img/snowflake_tutorial/snowflake_new_ui_activation_window.png b/website/static/img/snowflake_tutorial/snowflake_new_ui_activation_window.png new file mode 100644 index 00000000000..4f8710d755e Binary files /dev/null and b/website/static/img/snowflake_tutorial/snowflake_new_ui_activation_window.png differ diff --git a/website/static/img/snowflake_tutorial/snowflake_new_ui_connection_box.png b/website/static/img/snowflake_tutorial/snowflake_new_ui_connection_box.png new file mode 100644 index 00000000000..7eb5c75bbc4 Binary files /dev/null and b/website/static/img/snowflake_tutorial/snowflake_new_ui_connection_box.png differ diff --git a/website/static/img/snowflake_tutorial/snowflake_new_ui_create_new_worksheet.png b/website/static/img/snowflake_tutorial/snowflake_new_ui_create_new_worksheet.png new file mode 100644 index 00000000000..dc9ed0cac3b Binary files /dev/null and b/website/static/img/snowflake_tutorial/snowflake_new_ui_create_new_worksheet.png differ diff --git a/website/static/img/snowflake_tutorial/snowflake_new_ui_partner_connect.png b/website/static/img/snowflake_tutorial/snowflake_new_ui_partner_connect.png new file mode 100644 index 00000000000..41b960e0ae8 Binary files /dev/null and b/website/static/img/snowflake_tutorial/snowflake_new_ui_partner_connect.png differ diff --git a/website/static/img/snowflake_tutorial/snowflake_partner_connect_box.png b/website/static/img/snowflake_tutorial/snowflake_partner_connect_box.png new file mode 100644 index 00000000000..2cb58f32a28 Binary files /dev/null and b/website/static/img/snowflake_tutorial/snowflake_partner_connect_box.png differ diff --git a/website/static/img/snowflake_tutorial/snowflake_workspace.png b/website/static/img/snowflake_tutorial/snowflake_workspace.png new file mode 100644 index 00000000000..932c14aaeb0 Binary files /dev/null and b/website/static/img/snowflake_tutorial/snowflake_workspace.png differ diff --git a/website/static/img/starter-project-dbt-cli.png b/website/static/img/starter-project-dbt-cli.png index eb150311eaa..24f2a942c31 100644 Binary files a/website/static/img/starter-project-dbt-cli.png and b/website/static/img/starter-project-dbt-cli.png differ diff --git a/website/static/img/starter-project-dbt-cloud.png b/website/static/img/starter-project-dbt-cloud.png index 3461b50b539..cb9fdb89ac3 100644 Binary files a/website/static/img/starter-project-dbt-cloud.png and b/website/static/img/starter-project-dbt-cloud.png differ diff --git a/website/static/img/successful-bigquery-query.png b/website/static/img/successful-bigquery-query.png index 129425e07af..32c503737f3 100644 Binary files a/website/static/img/successful-bigquery-query.png and b/website/static/img/successful-bigquery-query.png differ diff --git a/website/static/img/successful-dbt-debug-snowflake.png b/website/static/img/successful-dbt-debug-snowflake.png index 8c31410198e..2d73f42dee6 100644 Binary files a/website/static/img/successful-dbt-debug-snowflake.png and b/website/static/img/successful-dbt-debug-snowflake.png differ diff --git a/website/static/img/successful-dbt-debug.png b/website/static/img/successful-dbt-debug.png index c09346ccb7b..6fe161bf259 100644 Binary files a/website/static/img/successful-dbt-debug.png and b/website/static/img/successful-dbt-debug.png differ diff --git a/website/static/img/successful-dbt-run.png b/website/static/img/successful-dbt-run.png index c3119c6ec96..0b5fba5c59e 100644 Binary files a/website/static/img/successful-dbt-run.png and b/website/static/img/successful-dbt-run.png differ diff --git a/website/static/img/successful-snowflake-query.png b/website/static/img/successful-snowflake-query.png index 3158290d233..a55dbe66b1a 100644 Binary files a/website/static/img/successful-snowflake-query.png and b/website/static/img/successful-snowflake-query.png differ diff --git a/website/static/img/successful-starter-project-run-dbt-cloud.png b/website/static/img/successful-starter-project-run-dbt-cloud.png index 71fc51d49b1..d4e35b05a8a 100644 Binary files a/website/static/img/successful-starter-project-run-dbt-cloud.png and b/website/static/img/successful-starter-project-run-dbt-cloud.png differ diff --git a/website/static/img/successful-tests-dbt-cli.png b/website/static/img/successful-tests-dbt-cli.png index 58ba701c629..e1cabc5908e 100644 Binary files a/website/static/img/successful-tests-dbt-cli.png and b/website/static/img/successful-tests-dbt-cli.png differ diff --git a/website/static/img/successful-tests-dbt-cloud.png b/website/static/img/successful-tests-dbt-cloud.png index d1700e3ad23..e3506f1ea3d 100644 Binary files a/website/static/img/successful-tests-dbt-cloud.png and b/website/static/img/successful-tests-dbt-cloud.png differ