diff --git a/.cursor/rules/docs-example-data-model.mdc b/.cursor/rules/docs-example-data-model.mdc new file mode 100644 index 0000000000000..c69df0ac4cc17 --- /dev/null +++ b/.cursor/rules/docs-example-data-model.mdc @@ -0,0 +1,69 @@ +--- +description: Canonical data model to use as the basis for all documentation examples +globs: docs-mintlify/** +alwaysApply: false +--- + +# Canonical Example Data Model + +All documentation examples and recipes must use the [ecommerce demo data model](https://github.com/cubedevinc/ecommerce_demo) as their basis unless the topic genuinely requires a different domain. + +## Cubes + +### `order_items` (fact, `ECOMMERCE.ORDER_ITEMS`) +The primary fact table. Use this as the starting point for most examples. + +Key fields: +- `id` — primary key +- `order_id`, `user_id`, `product_id`, `inventory_item_id` — foreign keys +- `status` (string) — `complete`, `processing`, `shipped`, `cancelled`, `returned` +- `sale_price` (number) — revenue per line item; measure `total_sale_price` (sum, currency) +- `created_at`, `shipped_at`, `delivered_at`, `returned_at` (time) +- `is_delivered` (boolean) +- measures: `count`, `order_count` (count_distinct on order_id), `total_sale_price` + +### `orders` (`ECOMMERCE.ORDERS`) +Order-level table. Use when examples are about order status or counts. + +Key fields: +- `order_id` — primary key +- `user_id`, `status`, `gender`, `num_of_item` +- `created_at`, `delivered_at`, `shipped_at` (time) +- measures: `count` + +### `products` (`ECOMMERCE.PRODUCTS`) +Product catalog. Use when examples need brand, category, or product dimensions. + +Key fields: +- `id` — primary key +- `brand`, `category`, `department`, `name`, `sku` +- `cost`, `retail_price` (number) +- measures: `count` + +### `users` (`ECOMMERCE.USERS`) +Customer table. Use when examples need demographic or geographic dimensions. + +Key fields: +- `id` — primary key +- `first_name`, `last_name`, `full_name`, `email` +- `age`, `gender` +- `city`, `state`, `country` +- `traffic_source` +- `created_at` (time) +- measures: `count` + +## Common example patterns + +**Revenue over time** → `order_items.total_sale_price` + `order_items.created_at` + +**Orders by status** → `order_items.count` + `order_items.status` + +**Revenue by brand/category** → `order_items.total_sale_price` joined to `products.brand` / `products.category` + +**User demographics** → `users.count` + `users.city` / `users.country` / `users.traffic_source` + +**Multi-cube join** → `order_items` joins `orders`, `products`, `users` via foreign keys defined in the repo + +## Reference + +Full model: https://github.com/cubedevinc/ecommerce_demo diff --git a/.cursor/rules/mintlify-mdx-gotchas.mdc b/.cursor/rules/mintlify-mdx-gotchas.mdc new file mode 100644 index 0000000000000..69f051ca47003 --- /dev/null +++ b/.cursor/rules/mintlify-mdx-gotchas.mdc @@ -0,0 +1,110 @@ +--- +description: Mintlify MDX parsing gotchas — patterns that look correct but render broken +globs: docs-mintlify/** +alwaysApply: true +--- + +# Mintlify MDX gotchas + +Mintlify uses MDX (Markdown + JSX). A handful of patterns parse cleanly in +plain Markdown but render broken once wrapped in JSX components like +``. Use these rules when authoring or editing pages in +`docs-mintlify/`. + +## `` must start with prose, not a fenced code block + +When a fenced code block is the **first child** of a `` component, +Mintlify's MDX parser collapses the entire block onto one line, exposing +the literal triple backticks. Every `` body must begin with at least +one line of prose (a single sentence is enough). + +❌ Renders broken — fence is the first child: + +````mdx + + ```json + { + "Version": "2012-10-17", + ... + } + ``` + +```` + +✅ Add a one-line lead-in: + +````mdx + + Allow the role to read, write, and list objects in your bucket: + + ```json + { + "Version": "2012-10-17", + ... + } + ``` + +```` + +The intro line also reads better — it tells the user what the snippet does +before they hit it. Apply the same rule to any code block (`json`, `bash`, +`dotenv`, `yaml`, `sql`, …) that would otherwise be the first child of a +``. + +This rule applies anywhere a fenced code block sits at the top of a JSX +component body. `` is the most common offender; `` and `` +behave the same way. + +## Angle-bracket placeholders must be backticked in prose + +``, ``, ``, etc. are useful +placeholders inside fenced code blocks (they're plain text there) but in +prose they have to be wrapped in backticks. Otherwise MDX tries to parse +them as JSX components and either errors out or silently swallows them. + +❌ MDX tries to parse `` as a component: + +```mdx +The issuer URL is https://.cubecloud.dev. +``` + +✅ Backticked: + +```mdx +The issuer URL is `https://.cubecloud.dev`. +``` + +Inside fenced ```` ``` ```` blocks (and Mermaid diagrams that don't pass +through the JSX parser) the bare form is fine. + +## Mermaid participant labels can't carry angle-bracket placeholders + +Mermaid renders `
` inside participant labels as a line break, but it +doesn't tolerate other `<…>` tags — they break the diagram. Use a plain +description ("your tenant URL") instead of `.cubecloud.dev` +in `participant` labels. + +## Bash heredoc / assignment with `` breaks copy-paste + +`PROJECT_NUMBER=` looks fine in a doc, but bash interprets +`<` as input redirection — pasting the line errors out. Quote it: + +```bash +PROJECT_NUMBER="" +DEPLOYMENT_ID="" +``` + +Quotes preserve the placeholder visually and let the user `sed`-replace +without the line failing first. + +## Don't use a body H1 + +Mintlify renders the frontmatter `title` as the page H1. Adding `# Heading` +in the body produces two H1s and breaks the doc outline. Use `## Heading` +for the first body section. + +## Verifying + +`mintlify dev --no-open` boots a local preview and surfaces compile errors +on startup. `mintlify broken-links` flags dead internal anchors. Run both +before publishing a non-trivial doc change. diff --git a/.cursor/rules/static-assets.mdc b/.cursor/rules/static-assets.mdc new file mode 100644 index 0000000000000..bb1a53dafee67 --- /dev/null +++ b/.cursor/rules/static-assets.mdc @@ -0,0 +1,135 @@ +--- +description: How to upload and reference static images/assets for Mintlify docs +globs: docs-mintlify/** +alwaysApply: false +--- + +# Static assets for the Mintlify docs + +## Where assets live + +- **Editorial assets** (provider logos, UI screenshots, architecture diagrams, + recipe images, etc.) → S3 bucket `cube-dev-websites-shared`, served via CDN + at `https://static.cube.dev/`. **Never** commit these binaries to the + repo. +- **Site chrome** that ships with Mintlify itself (the favicon and the logos + in `docs-mintlify/logo/`) stays in the repo. Don't add new files there. + +If you're not sure: anything you'd reference from an `.mdx` page → S3. + +## Uploading editorial assets + +Use the script in `docs-mintlify/scripts/` (no AWS console clicks needed). +Run it from the `docs-mintlify/` directory: + +```bash +./scripts/upload-asset.sh +``` + +Examples: + +```bash +./scripts/upload-asset.sh ./snowflake.svg icons/snowflake.svg +./scripts/upload-asset.sh ./architecture.png docs/getting-started/architecture.png +./scripts/upload-asset.sh ./flow.svg diagrams/pre-aggregations-flow.svg +``` + +The script prints (and copies to clipboard on macOS) the final +`https://static.cube.dev/` URL. Paste that URL into the relevant +`.mdx` file. + +Full docs: `docs-mintlify/scripts/README.md`. + +## First-time AWS setup + +The upload script needs the AWS CLI and credentials for the +`cube-dev-websites-shared` bucket. If `./scripts/upload-asset.sh` fails with +`command not found: aws` or an AWS auth error, run through these steps once. + +If the user hasn't configured AWS yet, walk them through this — don't try to +guess credentials or upload without a working profile. + +1. **Install the AWS CLI** + + ```bash + brew install awscli # macOS + # or: pipx install awscli # cross-platform + ``` + +2. **Get credentials** + + You need an IAM user / SSO role with `s3:PutObject` and `s3:HeadObject` + on `cube-dev-websites-shared`. Ask whoever manages Cube's AWS account + (post in the internal infra/ops channel) — don't reuse personal keys. + +3. **Configure a local profile** + + The script picks up the `cube-static` profile by default. Use that name + to avoid having to set `AWS_PROFILE` every time: + + ```bash + aws configure --profile cube-static + # AWS Access Key ID: + # AWS Secret Access Key: + # Default region name: us-west-2 + # Default output format: json + ``` + + If you must use a different profile name, prefix every invocation: + + ```bash + AWS_PROFILE=my-profile ./scripts/upload-asset.sh ./logo.svg icons/foo.svg + ``` + +4. **Verify access** before your first real upload: + + ```bash + aws sts get-caller-identity --profile cube-static + aws s3 ls s3://cube-dev-websites-shared/icons/ --profile cube-static | head + ``` + + Both commands should succeed. If `ls` returns an `AccessDenied` error, + credentials are wrong or lack S3 permissions — fix that before uploading. + +Never commit AWS keys to the repo or paste them into chat. They live only in +`~/.aws/credentials` (or your SSO config). + +## Path conventions + +| Prefix | Use for | +| --------------------------------- | -------------------------------------------------- | +| `icons/.svg` | Provider / integration / vendor logos for `` | +| `icons/-light.svg` | Logo, light variant (use on dark backgrounds) | +| `icons/-dark.svg` | Logo, dark variant (use on light backgrounds) | +| `docs/
//` | Screenshots & images for a specific docs page | +| `diagrams/.svg` | Architecture / flow diagrams | +| `recipes//` | Recipe-specific screenshots | + +Use kebab-case slugs. Match the existing `icons/.svg` pattern already +referenced from pages like `admin/connect-to-data/visualization-tools/index.mdx` +and `admin/deployment/providers/index.mdx` — don't invent a new top-level +prefix when one of the above fits. + +For provider logos, prefer SVG. For UI screenshots, prefer PNG (or WebP for +larger images). Compress before uploading — the bucket is cached aggressively. + +## Immutability rule + +Asset URLs are **immutable by convention** — files are served with +`Cache-Control: public, max-age=31536000, immutable`. The upload script +refuses to overwrite existing keys. + +When an asset needs to change: + +1. Upload a new key with a version suffix (e.g. `snowflake-v2.svg`). +2. Update the `.mdx` reference in the same PR. + +Never use `--force` on an asset that is already live. + +## Don't + +- Don't commit screenshots, provider logos, or diagrams into `docs-mintlify/` + itself — they bloat the repo and Mintlify build, and can't be reused. +- Don't reference Contentful (`ucarecdn.com`, `images.ctfassets.net`) URLs in + new docs content. Mirror to `static.cube.dev` first. +- Don't reuse the same key for a different image. Bump the version suffix. diff --git a/.cursor/rules/writing-documentation.mdc b/.cursor/rules/writing-documentation.mdc new file mode 100644 index 0000000000000..9b7cfc7dfdac1 --- /dev/null +++ b/.cursor/rules/writing-documentation.mdc @@ -0,0 +1,9 @@ +--- +alwaysApply: true +globs: docs-mintlify/** +--- + +This repo only contains code for Cube Core and documentation. +Our cloud product codebase is located in ~/code/cubejs-enterprise (at least that is where it is located on Artyom's mac). Research the cloud product codebase when documenting new features. +Our documenation is built with https://www.mintlify.com. Make sure you follow Mintlify best practices when designing documentation. +Our competitors are [Omni](https://omni.co/) and [Hex](https://hex.tech/). We use their documentation sometimes as a reference. \ No newline at end of file diff --git a/.github/actions/deploy-example.sh b/.github/actions/deploy-example.sh deleted file mode 100755 index 700af36579aa9..0000000000000 --- a/.github/actions/deploy-example.sh +++ /dev/null @@ -1,33 +0,0 @@ -#!/bin/sh - -# Exit on first error -set -e - -npm config set loglevel error - -# Required environment variable -EXAMPLE_SLUG=${EXAMPLE_SLUG} - -EXAMPLE_DIRECTORY=examples/${EXAMPLE_SLUG} -EXAMPLE_CUBE_SKIP=${EXAMPLE_CUBE_SKIP:-0} -EXAMPLE_FRONTEND_SKIP=${EXAMPLE_FRONTEND_SKIP:-0} -EXAMPLE_FRONTEND_SUBDIRECTORY=${EXAMPLE_FRONTEND_SUBDIRECTORY:-dashboard-app} -EXAMPLE_FRONTEND_BUILD_SUBDIRECTORY=${EXAMPLE_FRONTEND_BUILD_SUBDIRECTORY:-build} - -cd "$EXAMPLE_DIRECTORY" - -if [ "$EXAMPLE_CUBE_SKIP" -eq 0 ] -then - yarn install - npm install -g cubejs-cli - cubejs deploy -fi - -if [ "$EXAMPLE_FRONTEND_SKIP" -eq 0 ] -then - cd "$EXAMPLE_FRONTEND_SUBDIRECTORY" - yarn install - yarn build - npm install -g netlify-cli - netlify deploy --dir="$EXAMPLE_FRONTEND_BUILD_SUBDIRECTORY" --prod -fi \ No newline at end of file diff --git a/.github/actions/integration/clickhouse.sh b/.github/actions/integration/clickhouse.sh index 9630f77e3acf1..187ba47fab16e 100755 --- a/.github/actions/integration/clickhouse.sh +++ b/.github/actions/integration/clickhouse.sh @@ -1,24 +1,34 @@ #!/bin/bash set -eo pipefail +# Cube officially maintained upstream LTS releases (as of 2026-06): 25.8, 26.3. + 1 EOL release +# 24.8 can be removed, but let's test that it still works + # Debug log for test containers export DEBUG=testcontainers -export TEST_CLICKHOUSE_VERSION=23.11 +export TEST_CLICKHOUSE_VERSION=26.3 + +echo "::group::Clickhouse ${TEST_CLICKHOUSE_VERSION}"; +docker pull clickhouse/clickhouse-server:${TEST_CLICKHOUSE_VERSION} +yarn lerna run --concurrency 1 --stream --no-prefix integration:clickhouse +echo "::endgroup::" + +export TEST_CLICKHOUSE_VERSION=25.8 echo "::group::Clickhouse ${TEST_CLICKHOUSE_VERSION}"; docker pull clickhouse/clickhouse-server:${TEST_CLICKHOUSE_VERSION} yarn lerna run --concurrency 1 --stream --no-prefix integration:clickhouse echo "::endgroup::" -export TEST_CLICKHOUSE_VERSION=22.8 +export TEST_CLICKHOUSE_VERSION=25.3 echo "::group::Clickhouse ${TEST_CLICKHOUSE_VERSION}"; docker pull clickhouse/clickhouse-server:${TEST_CLICKHOUSE_VERSION} yarn lerna run --concurrency 1 --stream --no-prefix integration:clickhouse echo "::endgroup::" -export TEST_CLICKHOUSE_VERSION=21.8 +export TEST_CLICKHOUSE_VERSION=24.8 echo "::group::Clickhouse ${TEST_CLICKHOUSE_VERSION}"; docker pull clickhouse/clickhouse-server:${TEST_CLICKHOUSE_VERSION} diff --git a/.github/actions/integration/mysql.sh b/.github/actions/integration/mysql.sh index 3baef5c280dc6..07a80f8a979ea 100755 --- a/.github/actions/integration/mysql.sh +++ b/.github/actions/integration/mysql.sh @@ -4,6 +4,11 @@ set -eo pipefail # Debug log for test containers export DEBUG=testcontainers +# Recursive CTE based generated time series require MySQL 8.0+. +# Keep it disabled for 5.6/5.7 (falls back to the portable VALUES series) and +# enable it only for the 8.0.x run below. +export CUBEJS_DB_MYSQL_USE_GENERATED_TIME_SERIES=false + export TEST_MYSQL_VERSION=5.6 echo "::group::MySQL ${TEST_MYSQL_VERSION}"; @@ -19,6 +24,7 @@ yarn lerna run --concurrency 1 --stream --no-prefix integration:mysql echo "::endgroup::" export TEST_MYSQL_VERSION=8.0.24 +export CUBEJS_DB_MYSQL_USE_GENERATED_TIME_SERIES=true echo "::group::MySQL ${TEST_MYSQL_VERSION}"; docker pull mysql:${TEST_MYSQL_VERSION} diff --git a/.github/actions/integration/snowflake.sh b/.github/actions/integration/snowflake.sh index 7a30dc062a699..31feb9adc1990 100755 --- a/.github/actions/integration/snowflake.sh +++ b/.github/actions/integration/snowflake.sh @@ -12,6 +12,7 @@ export CUBEJS_DB_SNOWFLAKE_WAREHOUSE=COMPUTE_WH export CUBEJS_DB_USER=$DRIVERS_TESTS_SNOWFLAKE_CUBEJS_DB_USER export CUBEJS_DB_PASS=$DRIVERS_TESTS_SNOWFLAKE_CUBEJS_DB_PASS +yarn lerna run --concurrency 1 --stream --no-prefix integration:snowflake yarn lerna run --concurrency 1 --stream --no-prefix smoke:snowflake echo "::endgroup::" diff --git a/.github/actions/setup-claude-code-review.sh b/.github/actions/setup-claude-code-review.sh new file mode 100755 index 0000000000000..ce14e9878ac5e --- /dev/null +++ b/.github/actions/setup-claude-code-review.sh @@ -0,0 +1,47 @@ +#!/usr/bin/env bash +# +# Configures two narrowly-scoped `gh` aliases used by the Claude PR review workflow +# to list and resolve review threads without granting `gh api graphql:*` broadly. +# +# Aliases installed: +# gh list-review-threads +# gh resolve-thread + +set -euo pipefail + +gh alias set --shell list-review-threads "$(cat <<'EOF' +gh api graphql \ + -f query=' + query($owner: String!, $repo: String!, $pr: Int!) { + repository(owner: $owner, name: $repo) { + pullRequest(number: $pr) { + reviewThreads(first: 100) { + nodes { + id + isResolved + isOutdated + comments(first: 1) { + nodes { author { login } body path line } + } + } + } + } + } + } + ' \ + -F owner="$1" -F repo="$2" -F pr="$3" +EOF +)" + +gh alias set --shell resolve-thread "$(cat <<'EOF' +gh api graphql \ + -f query=' + mutation($id: ID!) { + resolveReviewThread(input: { threadId: $id }) { + thread { isResolved } + } + } + ' \ + -F id="$1" +EOF +)" diff --git a/.github/actions/smoke.sh b/.github/actions/smoke.sh index e3c052506230a..e58b66a27e1b1 100755 --- a/.github/actions/smoke.sh +++ b/.github/actions/smoke.sh @@ -14,6 +14,10 @@ yarn lerna run --concurrency 1 --stream --no-prefix integration:duckdb yarn lerna run --concurrency 1 --stream --no-prefix smoke:duckdb echo "::endgroup::" +echo "::group::View Groups" +yarn lerna run --concurrency 1 --stream --no-prefix smoke:view-groups +echo "::endgroup::" + echo "::group::Postgres" yarn lerna run --concurrency 1 --stream --no-prefix smoke:postgres echo "::endgroup::" @@ -67,3 +71,11 @@ echo "::endgroup::" echo "::group::RBAC" yarn lerna run --concurrency 1 --stream --no-prefix smoke:rbac echo "::endgroup::" + +echo "::group::RBAC GraphQL" +yarn lerna run --concurrency 1 --stream --no-prefix smoke:rbac-graphql +echo "::endgroup::" + +echo "::group::Links" +yarn lerna run --concurrency 1 --stream --no-prefix smoke:links +echo "::endgroup::" diff --git a/.github/workflows/bridge-tests.yml b/.github/workflows/bridge-tests.yml new file mode 100644 index 0000000000000..30469aa1df583 --- /dev/null +++ b/.github/workflows/bridge-tests.yml @@ -0,0 +1,69 @@ +name: Bridge tests + +on: + pull_request: + paths: + - '.github/workflows/bridge-tests.yml' + - 'rust/cube/cubesqlplanner/**' + - 'rust/cube/cubenativeutils/**' + - 'packages/cubejs-backend-native/src/bridge_test_exports.rs' + - 'packages/cubejs-backend-native/test/bridge/**' + - 'packages/cubejs-backend-native/jest-bridge.config.js' + +permissions: + contents: read + +jobs: + bridge-tests: + runs-on: ubuntu-24.04 + timeout-minutes: 40 + name: Bridge tests (debug, --features bridge-test-harness) + + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Install Rust + uses: actions-rust-lang/setup-rust-toolchain@v1 + with: + toolchain: 1.90.0 + rustflags: "" + cache: false + - uses: Swatinem/rust-cache@v2 + with: + workspaces: ./packages/cubejs-backend-native -> target + key: bridge-tests-${{ runner.OS }}-x86_64-unknown-linux-gnu + shared-key: bridge-tests-${{ runner.OS }}-x86_64-unknown-linux-gnu + - name: Install Node.js + uses: actions/setup-node@v4 + with: + node-version: 22.x + - name: Set Yarn version + run: yarn policies set-version v1.22.22 + - name: Get yarn cache directory path + id: yarn-cache-dir-path + run: echo "dir=$(yarn cache dir)" >> "$GITHUB_OUTPUT" + - name: Restore yarn cache + uses: actions/cache@v4 + with: + path: ${{ steps.yarn-cache-dir-path.outputs.dir }} + key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }} + restore-keys: | + ${{ runner.os }}-yarn- + - name: Yarn install + uses: nick-fields/retry@v3 + env: + CUBESTORE_SKIP_POST_INSTALL: true + with: + max_attempts: 3 + retry_on: error + retry_wait_seconds: 15 + timeout_minutes: 20 + command: yarn install --frozen-lockfile + - name: Build native (debug, --features bridge-test-harness) + working-directory: ./packages/cubejs-backend-native + run: yarn run native:build-debug-bridge-tests + - name: TypeScript compile (lerna, root) + run: yarn tsc + - name: Run bridge tests + working-directory: ./packages/cubejs-backend-native + run: yarn jest --config jest-bridge.config.js --forceExit diff --git a/.github/workflows/claude-code-review.yml b/.github/workflows/claude-code-review.yml new file mode 100644 index 0000000000000..790090c8c7483 --- /dev/null +++ b/.github/workflows/claude-code-review.yml @@ -0,0 +1,217 @@ +name: Claude Code PR Review +on: + pull_request: + types: [opened, ready_for_review, reopened, synchronize] + workflow_call: + inputs: + pr_number: + required: true + type: number + effort: + required: false + type: string + default: medium + +concurrency: + # PR number lives in different fields depending on entry point — coalesce so + # the same PR shares a group regardless of whether we got here via + # pull_request or via the /bot-review proxy. + group: claude-code-review-${{ inputs.pr_number || github.event.pull_request.number }}-${{ github.event.action || 'manual' }} + cancel-in-progress: true + +jobs: + review-with-tracking: + # On `pull_request`, skip draft PRs — they get noisy synchronize pushes + # while WIP, and running a full Claude review on every intermediate commit + # gets expensive fast. ready_for_review picks it up on draft exit. + # On `workflow_call`, trust the caller; the proxy workflow handles its own + # auth gates. + if: ${{ github.event_name != 'pull_request' || github.event.pull_request.draft == false }} + runs-on: ubuntu-latest + permissions: + contents: read + pull-requests: write + id-token: write + env: + # Same coalesce as the concurrency group above (which can't read `env`, + # so the expression appears twice). + PR_NUMBER: ${{ inputs.pr_number || github.event.pull_request.number }} + steps: + - name: React to trigger comment + # Quick ACK so the user who typed /bot-review or /bot-deep-review sees + # the bot picked up the command — actual review takes a few minutes. + if: github.event_name == 'issue_comment' + env: + GH_TOKEN: ${{ github.token }} + REPO: ${{ github.repository }} + COMMENT_ID: ${{ github.event.comment.id }} + run: | + gh api --method POST \ + "repos/$REPO/issues/comments/$COMMENT_ID/reactions" \ + -f content=eyes \ + --silent + + - name: Checkout repository + uses: actions/checkout@v6 + with: + # A fork PR's head branch doesn't exist in the base repo, so checking it + # out by branch name fails. GitHub mirrors every PR head into the base + # repo as refs/pull//head — readable with the workflow token + ref: refs/pull/${{ env.PR_NUMBER }}/head + fetch-depth: 1 + persist-credentials: false + + - name: Configure gh aliases for review-thread operations + run: bash .github/actions/setup-claude-code-review.sh + + - name: Review + id: review + uses: anthropics/claude-code-action@v1 + with: + anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} + track_progress: true + # Allow PRs opened by coding-agent bots (e.g. cursor) to trigger reviews. + allowed_bots: "cursor[bot]" + prompt: | + REPO: ${{ github.repository }} + PR NUMBER: ${{ env.PR_NUMBER }} + + Perform a comprehensive code review with the following focus areas: + + 1. **Code Quality** + - Clean code principles and best practices + - Proper error handling and edge cases + - Code readability and maintainability + + 2. **Security** + - Check for potential security vulnerabilities + - Validate input sanitization + - Review authentication/authorization logic + + 3. **Performance** + - Identify potential performance bottlenecks + - Review database queries for efficiency + - Check for memory leaks or resource issues + + 4. **Testing** + - Verify adequate test coverage + - Review test quality and edge cases + - Check for missing test scenarios + + 5. **Documentation** + - Ensure code is properly documented + - Verify README updates for new features + - Check API documentation accuracy + + Provide detailed feedback using inline comments for specific issues. + Use top-level comments for general observations or praise. + + **Tracking comment formatting:** + + Applies only to the FINAL update of the tracking comment (the one that contains + the completed review). While work is still in progress — todos partially checked, + "working…" spinner, intermediate status updates — keep everything visible so the + reader can watch progress without expanding anything. + + On the final update, hide EVERYTHING — including the todo checklist itself — + inside a single collapsed `
` block. The completed checklist is just + stale progress signal at that point; it belongs behind the spoiler alongside the + rest of the review. Only a short one-line headline with the verdict and issue + counts (e.g. "1 high, 2 medium, 5 low") stays visible outside the spoiler — the + reader expands when they want details. + + Leave a blank line after `` and before `
`, otherwise GitHub + won't render the markdown inside (tables and lists especially). + + **Resolving your own stale review threads:** + + Before posting new comments, list existing review threads on this PR using the + preconfigured alias: + + gh list-review-threads ${{ github.repository_owner }} ${{ github.event.repository.name }} ${{ env.PR_NUMBER }} + + For each thread where ALL of the following hold: + - `isResolved` is false + - the first comment's `author.login` is `claude` + - the concern is no longer applicable in the current diff (file/line gone, + code rewritten, issue addressed) + + resolve it with: + + gh resolve-thread + + Do not resolve threads from human reviewers under any circumstance, even if the + concern looks addressed — leave that decision to the reviewer. Only the two + aliases above are available; raw `gh api graphql` is not permitted. + + **Avoiding duplicate inline comments:** + + Use the same `gh list-review-threads` output (from the resolve step above) to + deduplicate against your own prior comments. Before calling + `mcp__github_inline_comment__create_inline_comment` for a new issue, check whether + an existing thread already covers it. Skip creating a new inline comment when ALL + of the following hold for any thread in the list: + - `isResolved` is false + - the first comment's `author.login` is `claude` + - the thread is on the same `path` and `line` as the new issue you would post + - the existing comment's body raises substantively the same concern (same root + cause, same fix direction — wording does not need to match) + + When you skip, briefly note it in your top-level summary (e.g. "Re-affirmed N + prior threads still apply") so the reader knows you considered the issue. Do not + post a "still applies" reply on the thread — silence is fine; the unresolved + state already communicates that. + + If the issue is on a different line or the fix direction has shifted (different + root cause), post a new inline comment as usual. + + # Tools for comprehensive PR review + claude_args: | + --allowedTools "mcp__github_inline_comment__create_inline_comment,mcp__github__get_issue_comments,Bash(gh pr comment:*),Bash(gh pr diff:*),Bash(gh pr view:*),Bash(gh list-review-threads:*),Bash(gh resolve-thread:*)" + --model "claude-opus-5" + --effort ${{ inputs.effort || 'medium' }} + + - name: Write run summary + if: always() && steps.review.outputs.execution_file != '' + env: + EXECUTION_FILE: ${{ steps.review.outputs.execution_file }} + run: | + jq -r ' + [.[] | select(.type == "result")] | last as $r | + ([.[] | select(.type == "assistant")] | length) as $turns | + ([.[] | select(.type == "assistant") | .message.usage.input_tokens // 0] | add) as $in_tok | + ([.[] | select(.type == "assistant") | .message.usage.output_tokens // 0] | add) as $out_tok | + ([.[] | select(.type == "assistant") | .message.usage.cache_read_input_tokens // 0] | add) as $cache_tok | + ([.[] | select(.type == "assistant") | .message.model] | last) as $model | + if $r then + "### Claude Code review run", + "| Metric | Value |", + "|---|---|", + "| Model | `\($model // "?")` |", + "| Cost | $\($r.total_cost_usd) |", + "| Wall time | \(($r.duration_ms / 1000) | floor)s |", + "| API time | \((($r.duration_api_ms // 0) / 1000) | floor)s |", + "| Turns | \($turns) |", + "| Input tokens | \($in_tok) |", + "| Output tokens | \($out_tok) |", + "| Cache read tokens | \($cache_tok) |" + else empty end + ' "$EXECUTION_FILE" >> "$GITHUB_STEP_SUMMARY" + + - name: React to trigger comment (completion) + if: always() && github.event_name == 'issue_comment' + env: + GH_TOKEN: ${{ github.token }} + REPO: ${{ github.repository }} + COMMENT_ID: ${{ github.event.comment.id }} + REVIEW_OUTCOME: ${{ steps.review.outcome }} + run: | + if [ "$REVIEW_OUTCOME" = "success" ]; then + reaction=rocket + else + reaction=confused + fi + gh api --method POST \ + "repos/$REPO/issues/comments/$COMMENT_ID/reactions" \ + -f "content=$reaction" \ + --silent diff --git a/.github/workflows/claude-code.yml b/.github/workflows/claude-code.yml new file mode 100644 index 0000000000000..8b8513835e910 --- /dev/null +++ b/.github/workflows/claude-code.yml @@ -0,0 +1,84 @@ +name: Claude Code + +on: + issue_comment: + types: [created] + pull_request_review_comment: + types: [created] + pull_request_review: + types: [submitted] + pull_request: + types: [assigned, opened] + +jobs: + claude: + if: | + ( + github.event_name == 'pull_request' && + github.event.action == 'assigned' && + github.event.assignee.login == 'claude-code[bot]' + ) || + ( + github.event.sender.type == 'User' && + contains(fromJSON('["OWNER", "MEMBER", "COLLABORATOR"]'), github.event.comment.author_association || github.event.review.author_association) && + ( + (github.event_name == 'issue_comment' && github.event.issue.pull_request && contains(github.event.comment.body, '@claude')) || + (github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude')) || + (github.event_name == 'pull_request_review' && contains(github.event.review.body, '@claude')) + ) + ) + runs-on: ubuntu-latest + permissions: + contents: read + pull-requests: write + issues: write + id-token: write + actions: read + steps: + - name: Checkout repository + uses: actions/checkout@v6 + with: + fetch-depth: 1 + + - name: Run Claude Code + id: claude + uses: anthropics/claude-code-action@v1 + with: + anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} + + # `/bot-review` command in a PR comment + # Only Cube team can trigger review for now + bot-review: + if: | + github.event_name == 'issue_comment' && + github.event.issue.pull_request && + startsWith(github.event.comment.body, '/bot-review') && + github.event.sender.type == 'User' && + contains(fromJSON('["OWNER", "MEMBER"]'), github.event.comment.author_association) + permissions: + contents: read + pull-requests: write + id-token: write + uses: ./.github/workflows/claude-code-review.yml + with: + pr_number: ${{ github.event.issue.number }} + secrets: inherit + + # `/bot-deep-review` — same review, but with max reasoning effort (xhigh). + # Costs more tokens; use sparingly on complex / high-stakes PRs. + bot-deep-review: + if: | + github.event_name == 'issue_comment' && + github.event.issue.pull_request && + startsWith(github.event.comment.body, '/bot-deep-review') && + github.event.sender.type == 'User' && + contains(fromJSON('["OWNER", "MEMBER"]'), github.event.comment.author_association) + permissions: + contents: read + pull-requests: write + id-token: write + uses: ./.github/workflows/claude-code-review.yml + with: + pr_number: ${{ github.event.issue.number }} + effort: xhigh + secrets: inherit diff --git a/.github/workflows/drivers-tests.yml b/.github/workflows/drivers-tests.yml index 8f509a3f92d49..8c5825bb1ad91 100644 --- a/.github/workflows/drivers-tests.yml +++ b/.github/workflows/drivers-tests.yml @@ -29,7 +29,7 @@ on: - 'packages/cubejs-backend-native/**' - 'rust/cubesql/**' - - 'rust/cubesqlplanner/**' + - 'rust/cube/**' pull_request: paths: - '.github/workflows/drivers-tests.yml' @@ -56,7 +56,7 @@ on: - 'packages/cubejs-backend-native/**' - 'rust/cubesql/**' - - 'rust/cubesqlplanner/**' + - 'rust/cube/**' workflow_dispatch: inputs: use_tesseract_sql_planner: @@ -265,7 +265,9 @@ jobs: - databricks-jdbc-export-bucket-gcs-prefix - mssql - mysql + - oracle - postgres + - postgres-pre-agg-credentials - redshift - redshift-export-bucket-s3 - snowflake @@ -294,6 +296,12 @@ jobs: use_tesseract_sql_planner: true - database: mysql use_tesseract_sql_planner: true + - database: clickhouse + use_tesseract_sql_planner: true + - database: mssql + use_tesseract_sql_planner: true + - database: oracle + use_tesseract_sql_planner: true fail-fast: false steps: diff --git a/.github/workflows/examples-publish.yml b/.github/workflows/examples-publish.yml deleted file mode 100644 index 22a453fc7db45..0000000000000 --- a/.github/workflows/examples-publish.yml +++ /dev/null @@ -1,700 +0,0 @@ -name: Examples - -on: - push: - paths: - - '.github/workflows/examples-publish.yml' - - '.github/actions/deploy-example.sh' - - 'examples/**' - branches: - - master - -jobs: - - clickhouse-multi-tenancy: - runs-on: ubuntu-24.04 - timeout-minutes: 30 - - steps: - - uses: actions/checkout@v4 - - - uses: pheel/path-watcher-action@v1 - id: modified - with: - paths: '.github/workflows/examples-publish.yml,.github/actions/deploy-example.sh,examples/building-an-open-source-data-stack-with-clickhouse-and-cube-workshop/*,examples/building-an-open-source-data-stack-with-clickhouse-and-cube-workshop/**' - - - if: steps.modified.outputs.modified - uses: actions/setup-node@v4 - with: - node-version: 14.x - - - if: steps.modified.outputs.modified - run: .github/actions/deploy-example.sh - env: - EXAMPLE_SLUG: building-an-open-source-data-stack-with-clickhouse-and-cube-workshop - EXAMPLE_FRONTEND_SUBDIRECTORY: dashboard-app-multi-tenancy - EXAMPLE_FRONTEND_BUILD_SUBDIRECTORY: dist/ - NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }} - EXAMPLE_CUBE_SKIP: 1 - - clickhouse-multiple-sources: - runs-on: ubuntu-24.04 - timeout-minutes: 30 - - steps: - - uses: actions/checkout@v4 - - - uses: pheel/path-watcher-action@v1 - id: modified - with: - paths: '.github/workflows/examples-publish.yml,.github/actions/deploy-example.sh,examples/building-an-open-source-data-stack-with-clickhouse-and-cube-workshop/*,examples/building-an-open-source-data-stack-with-clickhouse-and-cube-workshop/**' - - - if: steps.modified.outputs.modified - uses: actions/setup-node@v4 - with: - node-version: 14.x - - - if: steps.modified.outputs.modified - run: .github/actions/deploy-example.sh - env: - EXAMPLE_SLUG: building-an-open-source-data-stack-with-clickhouse-and-cube-workshop - EXAMPLE_FRONTEND_SUBDIRECTORY: dashboard-app-multiple-data-sources - EXAMPLE_FRONTEND_BUILD_SUBDIRECTORY: dist/ - NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }} - EXAMPLE_CUBE_SKIP: 1 - - apollo-federation: - runs-on: ubuntu-24.04 - timeout-minutes: 30 - - steps: - - uses: actions/checkout@v4 - - - uses: pheel/path-watcher-action@v1 - id: modified - with: - paths: '.github/workflows/examples-publish.yml,.github/actions/deploy-example.sh,examples/apollo-federation-with-cube/*,examples/apollo-federation-with-cube/**' - - - if: steps.modified.outputs.modified - uses: actions/setup-node@v4 - with: - node-version: 14.x - - - if: steps.modified.outputs.modified - run: .github/actions/deploy-example.sh - env: - EXAMPLE_SLUG: apollo-federation-with-cube - EXAMPLE_FRONTEND_BUILD_SUBDIRECTORY: dist/ - NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }} - EXAMPLE_CUBE_SKIP: 1 - - ksql: - runs-on: ubuntu-24.04 - timeout-minutes: 30 - - steps: - - uses: actions/checkout@v4 - - - uses: pheel/path-watcher-action@v1 - id: modified - with: - paths: '.github/workflows/examples-publish.yml,.github/actions/deploy-example.sh,examples/ksql/*,examples/ksql/**' - - - if: steps.modified.outputs.modified - uses: actions/setup-node@v4 - with: - node-version: 14.x - - - if: steps.modified.outputs.modified - run: .github/actions/deploy-example.sh - env: - EXAMPLE_SLUG: ksql - EXAMPLE_FRONTEND_BUILD_SUBDIRECTORY: build/ - NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }} - EXAMPLE_CUBE_SKIP: 1 - - hasura-remote-schema: - runs-on: ubuntu-24.04 - timeout-minutes: 30 - - steps: - - uses: actions/checkout@v4 - - - uses: pheel/path-watcher-action@v1 - id: modified - with: - paths: '.github/workflows/examples-publish.yml,.github/actions/deploy-example.sh,examples/hasura-remote-schema-with-cube/*,examples/hasura-remote-schema-with-cube/**' - - - if: steps.modified.outputs.modified - uses: actions/setup-node@v4 - with: - node-version: 14.x - - - if: steps.modified.outputs.modified - run: .github/actions/deploy-example.sh - env: - EXAMPLE_SLUG: hasura-remote-schema-with-cube - EXAMPLE_FRONTEND_BUILD_SUBDIRECTORY: dist/ - NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }} - EXAMPLE_CUBE_SKIP: 1 - - angular-dashboard: - runs-on: ubuntu-24.04 - timeout-minutes: 30 - - steps: - - uses: actions/checkout@v4 - - - uses: pheel/path-watcher-action@v1 - id: modified - with: - paths: '.github/workflows/examples-publish.yml,.github/actions/deploy-example.sh,examples/angular-dashboard-with-material-ui/*,examples/angular-dashboard-with-material-ui/**' - - - if: steps.modified.outputs.modified - uses: actions/setup-node@v4 - with: - node-version: 14.x - - - if: steps.modified.outputs.modified - run: .github/actions/deploy-example.sh - env: - EXAMPLE_SLUG: angular-dashboard-with-material-ui - EXAMPLE_FRONTEND_BUILD_SUBDIRECTORY: dist/dashboard-app - CUBE_CLOUD_DEPLOY_AUTH: ${{ secrets.CUBE_CLOUD_DEPLOY_AUTH_ANGULAR_DASHBOARD }} - NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }} - - compare-date-range: - runs-on: ubuntu-24.04 - timeout-minutes: 30 - - steps: - - uses: actions/checkout@v4 - - - uses: pheel/path-watcher-action@v1 - id: modified - with: - paths: '.github/workflows/examples-publish.yml,.github/actions/deploy-example.sh,examples/compare-date-range/*,examples/compare-date-range/**' - - - if: steps.modified.outputs.modified - uses: actions/setup-node@v4 - with: - node-version: 14.x - - - if: steps.modified.outputs.modified - run: .github/actions/deploy-example.sh - env: - EXAMPLE_SLUG: compare-date-range - CUBE_CLOUD_DEPLOY_AUTH: ${{ secrets.CUBE_CLOUD_DEPLOY_AUTH_DATA_RANGE }} - NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }} - - clickhouse-dashboard: - runs-on: ubuntu-24.04 - timeout-minutes: 30 - - steps: - - uses: actions/checkout@v4 - - - uses: pheel/path-watcher-action@v1 - id: modified - with: - paths: '.github/workflows/examples-publish.yml,.github/actions/deploy-example.sh,examples/clickhouse-dashboard/*,examples/clickhouse-dashboard/**' - - - if: steps.modified.outputs.modified - uses: actions/setup-node@v4 - with: - node-version: 14.x - - - if: steps.modified.outputs.modified - run: .github/actions/deploy-example.sh - env: - EXAMPLE_SLUG: clickhouse-dashboard - CUBE_CLOUD_DEPLOY_AUTH: ${{ secrets.CUBE_CLOUD_DEPLOY_AUTH_CLICKHOUSE_DASHBOARD }} - NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }} - - d3-dashboard: - runs-on: ubuntu-24.04 - timeout-minutes: 30 - - steps: - - uses: actions/checkout@v4 - - - uses: pheel/path-watcher-action@v1 - id: modified - with: - paths: '.github/workflows/examples-publish.yml,.github/actions/deploy-example.sh,examples/d3-dashboard/*,examples/d3-dashboard/**' - - - if: steps.modified.outputs.modified - uses: actions/setup-node@v4 - with: - node-version: 14.x - - - if: steps.modified.outputs.modified - run: .github/actions/deploy-example.sh - env: - EXAMPLE_SLUG: d3-dashboard - CUBE_CLOUD_DEPLOY_AUTH: ${{ secrets.CUBE_CLOUD_DEPLOY_AUTH_D3_DASHBOARD }} - NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }} - - data-blending: - runs-on: ubuntu-24.04 - timeout-minutes: 30 - - steps: - - uses: actions/checkout@v4 - - - uses: pheel/path-watcher-action@v1 - id: modified - with: - paths: '.github/workflows/examples-publish.yml,.github/actions/deploy-example.sh,examples/data-blending/*,examples/data-blending/**' - - - if: steps.modified.outputs.modified - uses: actions/setup-node@v4 - with: - node-version: 14.x - - - if: steps.modified.outputs.modified - run: .github/actions/deploy-example.sh - env: - EXAMPLE_SLUG: data-blending - CUBE_CLOUD_DEPLOY_AUTH: ${{ secrets.CUBE_CLOUD_DEPLOY_AUTH_DATA_BLENDING }} - NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }} - - drill-downs: - runs-on: ubuntu-24.04 - timeout-minutes: 30 - - steps: - - uses: actions/checkout@v4 - - - uses: pheel/path-watcher-action@v1 - id: modified - with: - paths: '.github/workflows/examples-publish.yml,.github/actions/deploy-example.sh,examples/drill-downs/*,examples/drill-downs/**' - - - if: steps.modified.outputs.modified - uses: actions/setup-node@v4 - with: - node-version: 14.x - - - if: steps.modified.outputs.modified - run: .github/actions/deploy-example.sh - env: - EXAMPLE_SLUG: drill-downs - CUBE_CLOUD_DEPLOY_AUTH: ${{ secrets.CUBE_CLOUD_DEPLOY_AUTH_DRILL_DOWNS }} - NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }} - - ecom-backend: - runs-on: ubuntu-24.04 - timeout-minutes: 30 - - steps: - - uses: actions/checkout@v4 - - - uses: pheel/path-watcher-action@v1 - id: modified - with: - paths: '.github/workflows/examples-publish.yml,.github/actions/deploy-example.sh,examples/ecom-backend/*,examples/ecom-backend/**' - - - if: steps.modified.outputs.modified - uses: actions/setup-node@v4 - with: - node-version: 14.x - - - if: steps.modified.outputs.modified - run: .github/actions/deploy-example.sh - env: - EXAMPLE_SLUG: ecom-backend - EXAMPLE_FRONTEND_SKIP: 1 - CUBE_CLOUD_DEPLOY_AUTH: ${{ secrets.CUBE_CLOUD_DEPLOY_AUTH_ECOM_BACKEND }} - NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }} - - external-rollups: - runs-on: ubuntu-24.04 - timeout-minutes: 30 - - steps: - - uses: actions/checkout@v4 - - - uses: pheel/path-watcher-action@v1 - id: modified - with: - paths: '.github/workflows/examples-publish.yml,.github/actions/deploy-example.sh,examples/external-rollups/*,examples/external-rollups/**' - - - if: steps.modified.outputs.modified - uses: actions/setup-node@v4 - with: - node-version: 14.x - - - if: steps.modified.outputs.modified - run: .github/actions/deploy-example.sh - env: - EXAMPLE_SLUG: external-rollups - CUBE_CLOUD_DEPLOY_AUTH: ${{ secrets.CUBE_CLOUD_DEPLOY_AUTH_EXTERNAL_ROLLUPS }} - NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }} - - hacktoberfest: - runs-on: ubuntu-24.04 - timeout-minutes: 30 - - steps: - - uses: actions/checkout@v4 - - - uses: pheel/path-watcher-action@v1 - id: modified - with: - paths: '.github/workflows/examples-publish.yml,.github/actions/deploy-example.sh,examples/hacktoberfest/*,examples/hacktoberfest/**' - - - if: steps.modified.outputs.modified - uses: actions/setup-node@v4 - with: - node-version: 14.x - - - if: steps.modified.outputs.modified - run: .github/actions/deploy-example.sh - env: - EXAMPLE_SLUG: hacktoberfest - EXAMPLE_FRONTEND_SUBDIRECTORY: dashboard - CUBE_CLOUD_DEPLOY_AUTH: ${{ secrets.CUBE_CLOUD_DEPLOY_AUTH_HACKTOBERFEST }} - NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }} - - mapbox: - runs-on: ubuntu-24.04 - timeout-minutes: 30 - - steps: - - uses: actions/checkout@v4 - - - uses: pheel/path-watcher-action@v1 - id: modified - with: - paths: '.github/workflows/examples-publish.yml,.github/actions/deploy-example.sh,examples/mapbox/*,examples/mapbox/**' - - - if: steps.modified.outputs.modified - uses: actions/setup-node@v4 - with: - node-version: 14.x - - - if: steps.modified.outputs.modified - run: .github/actions/deploy-example.sh - env: - EXAMPLE_SLUG: mapbox - CUBE_CLOUD_DEPLOY_AUTH: ${{ secrets.CUBE_CLOUD_DEPLOY_AUTH_MAPBOX }} - NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }} - - react-dashboard: - runs-on: ubuntu-24.04 - timeout-minutes: 30 - - steps: - - uses: actions/checkout@v4 - - - uses: pheel/path-watcher-action@v1 - id: modified - with: - paths: '.github/workflows/examples-publish.yml,.github/actions/deploy-example.sh,examples/react-dashboard/*,examples/react-dashboard/**' - - - if: steps.modified.outputs.modified - uses: actions/setup-node@v4 - with: - node-version: 14.x - - - if: steps.modified.outputs.modified - run: .github/actions/deploy-example.sh - env: - EXAMPLE_SLUG: react-dashboard - CUBE_CLOUD_DEPLOY_AUTH: ${{ secrets.CUBE_CLOUD_DEPLOY_AUTH_REACT_DASHBOARD }} - NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }} - - react-muze: - runs-on: ubuntu-24.04 - timeout-minutes: 30 - - steps: - - uses: actions/checkout@v4 - - - uses: pheel/path-watcher-action@v1 - id: modified - with: - paths: '.github/workflows/examples-publish.yml,.github/actions/deploy-example.sh,examples/react-muze/*,examples/react-muze/**' - - - if: steps.modified.outputs.modified - uses: actions/setup-node@v4 - with: - node-version: 14.x - - - if: steps.modified.outputs.modified - run: .github/actions/deploy-example.sh - env: - EXAMPLE_SLUG: react-muze - CUBE_CLOUD_DEPLOY_AUTH: ${{ secrets.CUBE_CLOUD_DEPLOY_AUTH_REACT_MUZE }} - NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }} - - real-time-dashboard: - runs-on: ubuntu-24.04 - timeout-minutes: 30 - - steps: - - uses: actions/checkout@v4 - - - uses: pheel/path-watcher-action@v1 - id: modified - with: - paths: '.github/workflows/examples-publish.yml,.github/actions/deploy-example.sh,examples/real-time-dashboard/*,examples/real-time-dashboard/**' - - - if: steps.modified.outputs.modified - uses: actions/setup-node@v4 - with: - node-version: 14.x - - - if: steps.modified.outputs.modified - run: .github/actions/deploy-example.sh - env: - EXAMPLE_SLUG: real-time-dashboard - CUBE_CLOUD_DEPLOY_AUTH: ${{ secrets.CUBE_CLOUD_DEPLOY_AUTH_REAL_TIME_DASHBOARD }} - NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }} - - web-analytics: - runs-on: ubuntu-24.04 - timeout-minutes: 30 - - steps: - - uses: actions/checkout@v4 - - - uses: pheel/path-watcher-action@v1 - id: modified - with: - paths: '.github/workflows/examples-publish.yml,.github/actions/deploy-example.sh,examples/web-analytics/*,examples/web-analytics/**' - - - if: steps.modified.outputs.modified - uses: actions/setup-node@v4 - with: - node-version: 14.x - - - if: steps.modified.outputs.modified - run: .github/actions/deploy-example.sh - env: - EXAMPLE_SLUG: web-analytics - CUBE_CLOUD_DEPLOY_AUTH: ${{ secrets.CUBE_CLOUD_DEPLOY_AUTH_WEB_ANALYTICS }} - NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }} - - auth0: - runs-on: ubuntu-24.04 - timeout-minutes: 30 - - steps: - - uses: actions/checkout@v4 - - - uses: pheel/path-watcher-action@v1 - id: modified - with: - paths: '.github/workflows/examples-publish.yml,.github/actions/deploy-example.sh,examples/auth0/*,examples/auth0/**' - - - if: steps.modified.outputs.modified - uses: actions/setup-node@v4 - with: - node-version: 14.x - - - if: steps.modified.outputs.modified - run: .github/actions/deploy-example.sh - env: - EXAMPLE_SLUG: auth0 - CUBE_CLOUD_DEPLOY_AUTH: ${{ secrets.CUBE_CLOUD_DEPLOY_AUTH_AUTH0 }} - NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }} - - bigquery-public-datasets: - runs-on: ubuntu-24.04 - timeout-minutes: 30 - - steps: - - uses: actions/checkout@v4 - - - uses: pheel/path-watcher-action@v1 - id: modified - with: - paths: '.github/workflows/examples-publish.yml,.github/actions/deploy-example.sh,examples/bigquery-public-datasets/*,examples/bigquery-public-datasets/**' - - - if: steps.modified.outputs.modified - uses: actions/setup-node@v4 - with: - node-version: 14.x - - - if: steps.modified.outputs.modified - run: .github/actions/deploy-example.sh - env: - EXAMPLE_SLUG: bigquery-public-datasets - EXAMPLE_CUBE_SKIP: 1 - NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }} - - google-charts-moma: - runs-on: ubuntu-24.04 - timeout-minutes: 30 - - steps: - - uses: actions/checkout@v4 - - - uses: pheel/path-watcher-action@v1 - id: modified - with: - paths: '.github/workflows/examples-publish.yml,.github/actions/deploy-example.sh,examples/google-charts-moma/*,examples/google-charts-moma/**' - - - if: steps.modified.outputs.modified - uses: actions/setup-node@v4 - with: - node-version: 14.x - - - if: steps.modified.outputs.modified - run: .github/actions/deploy-example.sh - env: - EXAMPLE_SLUG: google-charts-moma - EXAMPLE_CUBE_SKIP: 1 - EXAMPLE_FRONTEND_BUILD_SUBDIRECTORY: public/ - NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }} - - deepnote: - runs-on: ubuntu-24.04 - timeout-minutes: 30 - - steps: - - uses: actions/checkout@v4 - - - uses: pheel/path-watcher-action@v1 - id: modified - with: - paths: '.github/workflows/examples-publish.yml,.github/actions/deploy-example.sh,examples/deepnote/*,examples/deepnote/**' - - - if: steps.modified.outputs.modified - uses: actions/setup-node@v4 - with: - node-version: 14.x - - - if: steps.modified.outputs.modified - run: .github/actions/deploy-example.sh - env: - EXAMPLE_SLUG: deepnote - EXAMPLE_CUBE_SKIP: 1 - EXAMPLE_FRONTEND_BUILD_SUBDIRECTORY: dist/ - NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }} - EXAMPLE_FRONTEND_SUBDIRECTORY: './' - - graphql-api-metrics-dashboard: - runs-on: ubuntu-24.04 - timeout-minutes: 30 - - steps: - - uses: actions/checkout@v4 - - - uses: pheel/path-watcher-action@v1 - id: modified - with: - paths: '.github/workflows/examples-publish.yml,.github/actions/deploy-example.sh,examples/graphql-api-metrics-dashboard/*,examples/graphql-api-metrics-dashboard/**' - - - if: steps.modified.outputs.modified - uses: actions/setup-node@v4 - with: - node-version: 14.x - - - if: steps.modified.outputs.modified - run: .github/actions/deploy-example.sh - env: - EXAMPLE_SLUG: graphql-api-metrics-dashboard - EXAMPLE_CUBE_SKIP: 1 - NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }} - EXAMPLE_FRONTEND_SUBDIRECTORY: './' - - multi-tenant-analytics: - runs-on: ubuntu-24.04 - timeout-minutes: 30 - - steps: - - uses: actions/checkout@v4 - - - uses: pheel/path-watcher-action@v1 - id: modified - with: - paths: '.github/workflows/examples-publish.yml,.github/actions/deploy-example.sh,examples/multi-tenant-analytics/*,examples/multi-tenant-analytics/**' - - - if: steps.modified.outputs.modified - uses: actions/setup-node@v4 - with: - node-version: 14.x - - - if: steps.modified.outputs.modified - run: .github/actions/deploy-example.sh - env: - EXAMPLE_SLUG: multi-tenant-analytics - EXAMPLE_CUBE_SKIP: 1 - NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }} - - multitenancy-workshop: - runs-on: ubuntu-24.04 - timeout-minutes: 30 - - steps: - - uses: actions/checkout@v4 - - - uses: pheel/path-watcher-action@v1 - id: modified - with: - paths: '.github/workflows/examples-publish.yml,.github/actions/deploy-example.sh,examples/multitenancy-workshop/*,examples/multitenancy-workshop/**' - - - if: steps.modified.outputs.modified - uses: actions/setup-node@v4 - with: - node-version: 14.x - - - if: steps.modified.outputs.modified - run: .github/actions/deploy-example.sh - env: - EXAMPLE_SLUG: multitenancy-workshop - EXAMPLE_CUBE_SKIP: 1 - NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }} - - aws-web-analytics: - runs-on: ubuntu-24.04 - timeout-minutes: 30 - - steps: - - uses: actions/checkout@v4 - - - uses: pheel/path-watcher-action@v1 - id: modified - with: - paths: '.github/workflows/examples-publish.yml,.github/actions/deploy-example.sh,examples/aws-web-analytics/*,examples/aws-web-analytics/**' - - - if: steps.modified.outputs.modified - uses: actions/setup-node@v4 - with: - node-version: 14.x - - - if: steps.modified.outputs.modified - run: .github/actions/deploy-example.sh - env: - EXAMPLE_SLUG: aws-web-analytics - EXAMPLE_CUBE_SKIP: 1 - NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }} - EXAMPLE_FRONTEND_SUBDIRECTORY: 'analytics-dashboard' - - event-analytics: - runs-on: ubuntu-24.04 - timeout-minutes: 30 - - steps: - - uses: actions/checkout@v4 - - - uses: pheel/path-watcher-action@v1 - id: modified - with: - paths: '.github/workflows/examples-publish.yml,.github/actions/deploy-example.sh,examples/event-analytics/*,examples/event-analytics/**' - - - if: steps.modified.outputs.modified - uses: actions/setup-node@v4 - with: - node-version: 14.x - - - if: steps.modified.outputs.modified - run: .github/actions/deploy-example.sh - env: - EXAMPLE_SLUG: event-analytics - EXAMPLE_CUBE_SKIP: 1 - NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }} - EXAMPLE_FRONTEND_SUBDIRECTORY: 'frontend' diff --git a/.github/workflows/master.yml b/.github/workflows/master.yml index 910b829bece26..b58f3b75adde8 100644 --- a/.github/workflows/master.yml +++ b/.github/workflows/master.yml @@ -11,13 +11,10 @@ on: - 'package.json' - 'rollup.config.js' - 'yarn.lock' - - 'rust/cubesqlplanner/**' - - 'rust/cubenativeutils/**' + - 'rust/cube/**' - 'rust/cubesql/**' branches: - master -env: - CUBEJS_TESSERACT_ORCHESTRATOR: true jobs: latest-tag-sha: runs-on: ubuntu-24.04 diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index df56a8b28aecf..7b7291256fc79 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -10,10 +10,7 @@ on: - 'packages/**' - 'rust/cubestore/**' - 'rust/cubesql/**' - - 'rust/cubenativeutils/**' - - 'rust/cubeorchestrator/**' - - 'rust/cubeshared/**' - - 'rust/cubesqlplanner/**' + - 'rust/cube/**' - '.eslintrc.js' - '.prettierrc' - 'package.json' @@ -32,10 +29,7 @@ on: - 'packages/**' - 'rust/cubestore/**' - 'rust/cubesql/**' - - 'rust/cubenativeutils/**' - - 'rust/cubeorchestrator/**' - - 'rust/cubeshared/**' - - 'rust/cubesqlplanner/**' + - 'rust/cube/**' - '.eslintrc.js' - '.prettierrc' - 'package.json' @@ -45,7 +39,6 @@ on: - 'yarn.lock' env: - CUBEJS_TESSERACT_ORCHESTRATOR: true # Current user version for Python. Should be aligned between build-native & docker-dev PYTHON_VERSION_CURRENT: 3.11 @@ -205,26 +198,17 @@ jobs: run: yarn lint:npm - name: Lerna lint run: yarn lerna run --concurrency 1 lint - - name: Cargo fmt cubeorchestrator + - name: Cargo fmt cube workspace run: | - cargo fmt --manifest-path rust/cubeorchestrator/Cargo.toml -- --check - - name: Cargo fmt cubenativeutils - run: | - cargo fmt --manifest-path rust/cubenativeutils/Cargo.toml -- --check - - name: Cargo fmt cubeshared - run: | - cargo fmt --manifest-path rust/cubeshared/Cargo.toml -- --check + cargo fmt --manifest-path rust/cube/Cargo.toml --all -- --check # - name: Cargo fmt cubesql # run: | # cargo fmt --manifest-path rust/cubesql/Cargo.toml -- --check - - name: Cargo fmt cubesqlplanner - run: | - cargo fmt --manifest-path rust/cubesqlplanner/cubesqlplanner/Cargo.toml -- --check unit-core: runs-on: ubuntu-24.04 timeout-minutes: 60 - needs: latest-tag-sha + needs: [latest-tag-sha, build-cubestore] if: (needs['latest-tag-sha'].outputs.sha != github.sha) steps: @@ -235,14 +219,17 @@ jobs: with: toolchain: 1.90.0 components: rustfmt - - name: Cargo test cubeorchestrator - run: cargo test --manifest-path rust/cubeorchestrator/Cargo.toml -j 4 - - name: Cargo test cubenativeutils - run: cargo test --manifest-path rust/cubenativeutils/Cargo.toml -j 4 - - name: Cargo test cubeshared - run: cargo test --manifest-path rust/cubeshared/Cargo.toml -j 4 - - name: Cargo test cubesqlplanner - run: cargo test --manifest-path rust/cubesqlplanner/cubesqlplanner/Cargo.toml -j 4 + # cubesqlplanner pre-aggregation tests run against this binary; the + # resolver picks up target/release first (see cubestore_service.rs). + - name: Download cubestored artifact + uses: actions/download-artifact@v4 + with: + path: ./rust/cubestore/target/release/ + name: cubestored-x86_64-unknown-linux-gnu-release + - name: Chmod +x for cubestored + run: chmod +x ./rust/cubestore/target/release/cubestored + - name: Cargo test cube workspace + run: cargo test --manifest-path rust/cube/Cargo.toml --workspace --features cubesqlplanner/integration-cubestore -j 4 build-cubestore: needs: [latest-tag-sha] @@ -432,6 +419,18 @@ jobs: - db: postgres node-version: 22.x use_tesseract_sql_planner: true + - db: mssql + node-version: 22.x + use_tesseract_sql_planner: true + - db: firebolt + node-version: 22.x + use_tesseract_sql_planner: true + - db: mysql + node-version: 22.x + use_tesseract_sql_planner: true + - db: clickhouse + node-version: 22.x + use_tesseract_sql_planner: true fail-fast: false steps: @@ -498,6 +497,7 @@ jobs: (!contains(env.CLOUD_DATABASES, matrix.db)) env: CUBEJS_TESSERACT_SQL_PLANNER: ${{ matrix.use_tesseract_sql_planner }} + CUBEJS_TESSERACT_PRE_AGGREGATIONS: ${{ matrix.use_tesseract_sql_planner }} # Firebolt Integration DRIVERS_TESTS_FIREBOLT_CUBEJS_FIREBOLT_ENGINE_NAME: ${{ secrets.DRIVERS_TESTS_FIREBOLT_CUBEJS_FIREBOLT_ENGINE_NAME }} @@ -543,6 +543,7 @@ jobs: matrix: node-version: [ 22.x ] python-version: [ 3.11 ] + use_tesseract_sql_planner: [ true, false ] fail-fast: false steps: @@ -602,6 +603,9 @@ jobs: chmod +x ./rust/cubestore/downloaded/latest/bin/cubestored - name: Run Integration smoke tests timeout-minutes: 30 + env: + CUBEJS_TESSERACT_SQL_PLANNER: ${{ matrix.use_tesseract_sql_planner }} + CUBEJS_TESSERACT_PRE_AGGREGATIONS: ${{ matrix.use_tesseract_sql_planner }} run: ./.github/actions/smoke.sh docker-image-latest-set-tag: diff --git a/.github/workflows/rust-cubesql.yml b/.github/workflows/rust-cubesql.yml index 1603c9756fe92..860285a48a759 100644 --- a/.github/workflows/rust-cubesql.yml +++ b/.github/workflows/rust-cubesql.yml @@ -5,8 +5,7 @@ on: paths: - '.github/workflows/rust-cubesql.yml' - 'packages/cubejs-backend-native/**' - - 'rust/cubenativeutils/**' - - 'rust/cubesqlplanner/**' + - 'rust/cube/**' - 'rust/cubesql/**' branches: - 'master' @@ -14,8 +13,7 @@ on: paths: - '.github/workflows/rust-cubesql.yml' - 'packages/cubejs-backend-native/**' - - 'rust/cubenativeutils/**' - - 'rust/cubesqlplanner/**' + - 'rust/cube/**' - 'rust/cubesql/**' jobs: @@ -47,20 +45,16 @@ jobs: run: cd rust/cubesql && cargo fmt --all -- --check - name: Lint Native run: cd packages/cubejs-backend-native && cargo fmt --all -- --check - - name: Lint cubenativeutils - run: cd rust/cubenativeutils && cargo fmt --all -- --check - - name: Lint cubesqlplanner - run: cd rust/cubesqlplanner && cargo fmt --all -- --check + - name: Lint cube workspace + run: cd rust/cube && cargo fmt --all -- --check - name: Clippy CubeSQL run: cd rust/cubesql && cargo clippy --locked --workspace --all-targets --keep-going -- -D warnings - name: Clippy Native run: cd packages/cubejs-backend-native && cargo clippy --locked --workspace --all-targets --keep-going -- -D warnings - name: Clippy Native (with Python) run: cd packages/cubejs-backend-native && cargo clippy --locked --workspace --all-targets --keep-going --features python -- -D warnings - - name: Clippy cubenativeutils - run: cd rust/cubenativeutils && cargo clippy --locked --workspace --all-targets --keep-going -- -D warnings - - name: Clippy cubesqlplanner - run: cd rust/cubesqlplanner && cargo clippy --locked --workspace --all-targets --keep-going -- -D warnings + - name: Clippy cube workspace + run: cd rust/cube && cargo clippy --locked --workspace --all-targets --keep-going -- -D warnings unit: # We use host instead of cross container, because it's much faster diff --git a/.github/workflows/rust-cubestore-master.yml b/.github/workflows/rust-cubestore-master.yml index 325251283cf84..b4deccbab7e6a 100644 --- a/.github/workflows/rust-cubestore-master.yml +++ b/.github/workflows/rust-cubestore-master.yml @@ -213,7 +213,7 @@ jobs: if: ${{ startsWith(matrix.os, 'windows') }} run: choco install -y --force llvm --version 18.1.6 - name: Set Env Variables for Windows - uses: allenevans/set-env@v3.0.0 + uses: allenevans/set-env@v4.0.0 if: ${{ startsWith(matrix.os, 'windows') }} with: OPENSSL_DIR: 'C:/vcpkg/packages/openssl_x64-windows' diff --git a/.github/workflows/rust-cubestore.yml b/.github/workflows/rust-cubestore.yml index 509e6b92a4ebe..c76e7e8c0f444 100644 --- a/.github/workflows/rust-cubestore.yml +++ b/.github/workflows/rust-cubestore.yml @@ -152,7 +152,7 @@ jobs: if: ${{ startsWith(matrix.os, 'windows') }} run: choco install -y --force llvm --version 18.1.6 - name: Set Env Variables for Windows - uses: allenevans/set-env@v3.0.0 + uses: allenevans/set-env@v4.0.0 if: ${{ startsWith(matrix.os, 'windows') }} with: OPENSSL_DIR: 'C:/vcpkg/packages/openssl_x64-windows' diff --git a/.nvmrc b/.nvmrc index 85e502778f623..b8b23ca93cf13 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -22.22.0 +22.23.4 diff --git a/CHANGELOG.md b/CHANGELOG.md index c0ad8540d04eb..6647d4b33a21a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,803 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.6.75](https://github.com/cube-js/cube/compare/v1.6.74...v1.6.75) (2026-10-23) + +### Features + +- **docker:** Security upgrade Node.js from 22.22.0 to 22.23.4 ([#12399](https://github.com/cube-js/cube/issues/12399)) ([27a305c](https://github.com/cube-js/cube/commit/27a305c3d2298d8eecbe90b9df7094dc22c81779)), closes [High-severity](https://github.com/Hi/issues/severity) [#12300](https://github.com/cube-js/cube/issues/12300) + +## [1.6.74](https://github.com/cube-js/cube/compare/v1.6.73...v1.6.74) (2026-10-09) + +### Bug Fixes + +- **query-orchestrator:** Drop touch/used keys when pre-aggregation build fails ([#11314](https://github.com/cube-js/cube/issues/11314)) ([8ed75e8](https://github.com/cube-js/cube/commit/8ed75e8cc0eed61ce3f4b399139a6fa522a7fb75)) + +## [1.6.73](https://github.com/cube-js/cube/compare/v1.6.72...v1.6.73) (2026-08-26) + +### Bug Fixes + +- Validate query timezone against IANA zones ([#11575](https://github.com/cube-js/cube/issues/11575)) ([7f7a59e](https://github.com/cube-js/cube/commit/7f7a59eebd36bb28b0b5b6e8bd3954c500d5f370)) + +## [1.6.72](https://github.com/cube-js/cube/compare/v1.6.71...v1.6.72) (2026-08-18) + +### Performance Improvements + +- **postgres-driver:** build user defined types map in linear time ([#11586](https://github.com/cube-js/cube/issues/11586)) ([a2a136a](https://github.com/cube-js/cube/commit/a2a136ae23e2a732711e967b31f0df25f324ee6e)), closes [#11149](https://github.com/cube-js/cube/issues/11149) +- **postgres-driver:** Skip relation array types when loading user defined types ([#11587](https://github.com/cube-js/cube/issues/11587)) ([4a960ff](https://github.com/cube-js/cube/commit/4a960ffe4bc07f9fa6591a85a006aa8c0eec38d4)), closes [#11149](https://github.com/cube-js/cube/issues/11149) + +## [1.6.71](https://github.com/cube-js/cube/compare/v1.6.70...v1.6.71) (2026-08-17) + +### Bug Fixes + +- **api-gateway:** require an isDevToken scope for the playground bypass ([#11579](https://github.com/cube-js/cube/issues/11579)) ([ff7c674](https://github.com/cube-js/cube/commit/ff7c67433837e282a12cb5381ea7e1f05df6102c)) + +## [1.6.70](https://github.com/cube-js/cube/compare/v1.6.69...v1.6.70) (2026-07-28) + +### Bug Fixes + +- **athena-driver:** Correct SQL parameter escaping ([#11370](https://github.com/cube-js/cube/issues/11370)) ([5d28530](https://github.com/cube-js/cube/commit/5d28530e91a608eba85198735496bd76d66122c9)) +- **cubesql:** Bound Bind/Parse parameter allocations in PG wire protocol ([#11341](https://github.com/cube-js/cube/issues/11341)) ([6b94612](https://github.com/cube-js/cube/commit/6b94612f1918c83d83faca721f7e268740accbac)) +- **cubesql:** Bound PostgreSQL packet sizes ([#11339](https://github.com/cube-js/cube/issues/11339)) ([2d20dda](https://github.com/cube-js/cube/commit/2d20ddad6cbec4d7b3b9b771b73fda9b920f7860)) +- **pinot/dremio/ksql/databriks/hive/jdbc-driver:** Сorrect SQL parameter escaping ([#11374](https://github.com/cube-js/cube/issues/11374)) ([e77c444](https://github.com/cube-js/cube/commit/e77c44471a720d31b29c7741a8a6040ec5836739)) +- **trino/prestodb-driver:** Сorrect SQL parameter escaping ([#11345](https://github.com/cube-js/cube/issues/11345)) ([20931ca](https://github.com/cube-js/cube/commit/20931cafbb115bd37dc90b94dbd171f4d15ba7ab)) + +## [1.6.69](https://github.com/cube-js/cube/compare/v1.6.68...v1.6.69) (2026-07-10) + +### Bug Fixes + +- **trino-driver:** Use SSL options in testConnection ([#11217](https://github.com/cube-js/cube/issues/11217)) ([abd8dbf](https://github.com/cube-js/cube/commit/abd8dbfa8021e6de7b99002d8a2629b385cc223d)) + +## [1.6.68](https://github.com/cube-js/cube/compare/v1.6.67...v1.6.68) (2026-07-07) + +### Bug Fixes + +- **api-gateway:** Accept timezone-suffixed timestamps in date filters, fix [#11213](https://github.com/cube-js/cube/issues/11213) ([#11208](https://github.com/cube-js/cube/issues/11208)) ([35459bf](https://github.com/cube-js/cube/commit/35459bf88fd487428a0df7c7995afbf2d9ce7058)) + +## [1.6.67](https://github.com/cube-js/cube/compare/v1.6.66...v1.6.67) (2026-07-06) + +### Bug Fixes + +- **schema-compiler:** Prevent alias gathering from polluting long-lived collector caches ([#11199](https://github.com/cube-js/cube/issues/11199)) ([17b0bee](https://github.com/cube-js/cube/commit/17b0beee06faa7f9b4fbf6275985ac223915b36b)) + +### Features + +- **api-gateway:** Support relative date ranges in OR/AND filters, thanks [@elijah-evans-deel](https://github.com/elijah-evans-deel) ([#11167](https://github.com/cube-js/cube/issues/11167)) ([a869654](https://github.com/cube-js/cube/commit/a869654e3eae264a0a67dce2e05101d49570fca4)) + +## [1.6.66](https://github.com/cube-js/cube/compare/v1.6.65...v1.6.66) (2026-07-03) + +### Bug Fixes + +- **cubestore:** Force standard Decimal128 bitWidth in Arrow response ([#11200](https://github.com/cube-js/cube/issues/11200)) ([c4c3594](https://github.com/cube-js/cube/commit/c4c3594bfad1055877bc7838dea36584e41e62b2)), closes [cube-js/arrow-rs#48](https://github.com/cube-js/arrow-rs/issues/48) +- **tesseract:** apply time_shift to FILTER_PARAMS column in shifted CTEs ([#11191](https://github.com/cube-js/cube/issues/11191)) ([f9398ab](https://github.com/cube-js/cube/commit/f9398ab78ac96af2541ca450633f792505f5fede)) +- **tesseract:** reduce_by/grain matches time dimensions regardless of granularity ([#11188](https://github.com/cube-js/cube/issues/11188)) ([b99d546](https://github.com/cube-js/cube/commit/b99d54617e6f3af7b7df812fc27285892a2bcb59)) +- **tesseract:** resolve FILTER_PARAMS callback-column placeholders in segments ([#11189](https://github.com/cube-js/cube/issues/11189)) ([5b96418](https://github.com/cube-js/cube/commit/5b964187c42b21ebeaf093e34da5d29ed68492f0)) + +### Features + +- **databricks-jdbc-driver:** Upgrade driver to 1.0.11 (to fix out of sequence response: expected N but got N-1) ([#11198](https://github.com/cube-js/cube/issues/11198)) ([8a4a054](https://github.com/cube-js/cube/commit/8a4a054081cdb850b1d8ad7b82bed54c7162f505)) + +## [1.6.65](https://github.com/cube-js/cube/compare/v1.6.64...v1.6.65) (2026-07-01) + +### Bug Fixes + +- **cubestore:** add statsd metrics bind address ENV VAR ([#9922](https://github.com/cube-js/cube/issues/9922)) ([6b98135](https://github.com/cube-js/cube/commit/6b98135acd24e499c874f53653e9d4621cb4fb08)) +- **cubestore:** guard replay handle seq pointer / location length mismatch ([#11093](https://github.com/cube-js/cube/issues/11093)) ([d257168](https://github.com/cube-js/cube/commit/d257168d4674fa37b874e6d753bfd841a94914ef)) +- **druid-driver:** Emulate ILIKE for Tesseract and SQL API push down ([#11164](https://github.com/cube-js/cube/issues/11164)) ([ff3f5c9](https://github.com/cube-js/cube/commit/ff3f5c9c1236bdc929e69554fb40c4aef39a3db3)) +- **tesseract:** cast bound param on measure filters ([#11176](https://github.com/cube-js/cube/issues/11176)) ([28e91ed](https://github.com/cube-js/cube/commit/28e91edeae265d42dad24deaaf6b5f97ad0593d2)) +- **tesseract:** Drop order-by-only measures from pre-aggregation reads ([#11179](https://github.com/cube-js/cube/issues/11179)) ([30bdcbb](https://github.com/cube-js/cube/commit/30bdcbbd5141e98997e396ac648e66dd8f7596b2)) +- **tesseract:** Honor memberToAlias for granularized time dimensions ([#11142](https://github.com/cube-js/cube/issues/11142)) ([96a6f28](https://github.com/cube-js/cube/commit/96a6f28369b742322329e829bd080acc2598abfd)) +- **tesseract:** honor rolling window offset without granularity ([#11169](https://github.com/cube-js/cube/issues/11169)) ([9b6a960](https://github.com/cube-js/cube/commit/9b6a9602fffbf960982397a38b6b941b34db7c92)) +- **tesseract:** Incorrect measure for ungrouped rollup pre-aggregation ([#11181](https://github.com/cube-js/cube/issues/11181)) ([45fac55](https://github.com/cube-js/cube/commit/45fac55edaf986b6109802706fa893bedf8bcd9d)) +- **tesseract:** match rolling pre-aggregations without a date range via match-only mode ([#11178](https://github.com/cube-js/cube/issues/11178)) ([b3448e9](https://github.com/cube-js/cube/commit/b3448e9fa1e70c6ce53b63a96cada4c8d9c333a6)) +- **tesseract:** Per branch aliases in rollupLambda unions ([#11184](https://github.com/cube-js/cube/issues/11184)) ([6e5c98f](https://github.com/cube-js/cube/commit/6e5c98f1a1cd88ddd1ae42dfce06f33bc0e5fa33)) +- **tesseract:** preserve FILTER_PARAMS pushdown with segments ([#11182](https://github.com/cube-js/cube/issues/11182)) ([c27af09](https://github.com/cube-js/cube/commit/c27af09bba7c473c1a9a460f671f54db2a5d0787)) +- **tesseract:** Reject pre-agg when a measure is multiplied only in t… ([#11173](https://github.com/cube-js/cube/issues/11173)) ([660c0a2](https://github.com/cube-js/cube/commit/660c0a2511e25bb63981538488db326e56deee0a)), closes [#9541](https://github.com/cube-js/cube/issues/9541) +- **tesseract:** Render dimension mask filters on grouped masked measures ([#11177](https://github.com/cube-js/cube/issues/11177)) ([f0569ad](https://github.com/cube-js/cube/commit/f0569adc67080a409f605cf0cd42f58ee5375ce2)) + +### Features + +- **cubestore:** top-k merge strategies via CUBESTORE_TOPK_STRATEGY ([#11152](https://github.com/cube-js/cube/issues/11152)) ([0c8cd24](https://github.com/cube-js/cube/commit/0c8cd244113ba611802b870e7ec731fc0af7f349)) +- **oracle-driver:** Improvements & fixes, fix [#10834](https://github.com/cube-js/cube/issues/10834) ([#11174](https://github.com/cube-js/cube/issues/11174)) ([9da8e07](https://github.com/cube-js/cube/commit/9da8e076897071f204711456b92ff69150547d9c)) +- **tesseract:** Support Funnels extension ([#11187](https://github.com/cube-js/cube/issues/11187)) ([183cd6e](https://github.com/cube-js/cube/commit/183cd6e4e34db8b15011a86c5b73358c0ae0cb4d)) + +### Performance Improvements + +- **cubestore:** worker-side group-by-limit hash-aggregate trim ([#11144](https://github.com/cube-js/cube/issues/11144)) ([dc7fba9](https://github.com/cube-js/cube/commit/dc7fba933de93eac6c4fb31571ca3ddb3800b582)) + +## [1.6.64](https://github.com/cube-js/cube/compare/v1.6.63...v1.6.64) (2026-06-25) + +### Bug Fixes + +- **cubestore:** Фvoid empty SortPreservingMerge for empty sort_on ([#11160](https://github.com/cube-js/cube/issues/11160)) ([c7d3ad1](https://github.com/cube-js/cube/commit/c7d3ad18ac6327d6196d2ef0430d3e2ac6b0ec33)) + +### Features + +- **clickhouse-driver:** Support passing custom HTTP headers ([#11161](https://github.com/cube-js/cube/issues/11161)) ([dd791e2](https://github.com/cube-js/cube/commit/dd791e2b9f52c71ac24add05cab0a9912a964d84)) + +## [1.6.63](https://github.com/cube-js/cube/compare/v1.6.62...v1.6.63) (2026-06-25) + +### Bug Fixes + +- **cubesql:** Handle array-typed columns in streaming SQL mode ([#11149](https://github.com/cube-js/cube/issues/11149)) ([56ba7c6](https://github.com/cube-js/cube/commit/56ba7c65fa1133a7d4b55b39e3f16bdca743ad46)) +- **firebolt-driver:** Cast BOOLEAN filter params under Tesseract planner ([#11153](https://github.com/cube-js/cube/issues/11153)) ([0f0300d](https://github.com/cube-js/cube/commit/0f0300db04fbc3150d59e8f6147f9a446a12cdd9)) +- **schema-compiler:** Thread memberToAlias through multi-stage CTEs ([#11150](https://github.com/cube-js/cube/issues/11150)) ([9a24249](https://github.com/cube-js/cube/commit/9a2424909b2a4d0bfe1610d42efeb4ce12538f88)) +- **tesseract:** Incorrect time dimenssion cast for Clickhouse ([#11155](https://github.com/cube-js/cube/issues/11155)) ([b33b95c](https://github.com/cube-js/cube/commit/b33b95ca0b2cb5702725c8c57bffb298692b7072)) +- **tesseract:** Support time series queries for MySQL 8+ ([#11154](https://github.com/cube-js/cube/issues/11154)) ([da1d68d](https://github.com/cube-js/cube/commit/da1d68d616c45cf0a21d95cdf2fd376e0873794c)) + +### Features + +- **tesseract:** Support use_original_sql_pre_aggregations in rollup ([#11146](https://github.com/cube-js/cube/issues/11146)) ([6a640a6](https://github.com/cube-js/cube/commit/6a640a63d79ea844ae31269efed84a246f82f162)) + +## [1.6.62](https://github.com/cube-js/cube/compare/v1.6.61...v1.6.62) (2026-06-23) + +### Bug Fixes + +- **cubesql:** Support EXTRACT(EPOCH) over timestamp diff on Snowflake ([#11105](https://github.com/cube-js/cube/issues/11105)) ([8e9d38c](https://github.com/cube-js/cube/commit/8e9d38cdaffb8b7f9f22377eeb3a35a338cacbab)) +- **databricks-jdbc-driver:** support OIDC/workload identity for export buckets ([#11143](https://github.com/cube-js/cube/issues/11143)) ([f4d2dde](https://github.com/cube-js/cube/commit/f4d2ddec1a74865357998b47d83805c2623d9a57)) +- **tesseract:** Push ad-hoc filters into view measure aggregation ([#11137](https://github.com/cube-js/cube/issues/11137)) ([a4a3e79](https://github.com/cube-js/cube/commit/a4a3e79f2e5a2bf9f0e915df4df509175fa122de)) +- **tesseract:** Resolve join for hint-less member-expression measures ([#11136](https://github.com/cube-js/cube/issues/11136)) ([741138a](https://github.com/cube-js/cube/commit/741138a21ca96eec64d2e0e329da91de8898948c)) + +### Features + +- **cubesql:** Push `Limit`-`Sort` down `Union` inputs ([#11125](https://github.com/cube-js/cube/issues/11125)) ([932e253](https://github.com/cube-js/cube/commit/932e2538b165ffbb168d8ee7de1e4f2c93684717)) +- **cubesql:** Support parsing IANA timezones ([#11140](https://github.com/cube-js/cube/issues/11140)) ([c79eb98](https://github.com/cube-js/cube/commit/c79eb986fb696398b3c3e959b836c02d3af0c211)) +- **tesseract:** Support boolean and numeric filter values ([#11135](https://github.com/cube-js/cube/issues/11135)) ([789333d](https://github.com/cube-js/cube/commit/789333d313dc22281a9af3610781a7c1e6b7b28f)) +- **tesseract:** Support SQL API grouped sub-query joins ([#11138](https://github.com/cube-js/cube/issues/11138)) ([4d4b8cd](https://github.com/cube-js/cube/commit/4d4b8cde62fdf3c676467b712b9759b601c574e8)) + +## [1.6.61](https://github.com/cube-js/cube/compare/v1.6.60...v1.6.61) (2026-06-22) + +### Bug Fixes + +- **cubejs-client-core:** surface cubeSql error chunks instead of dropping rows ([#11097](https://github.com/cube-js/cube/issues/11097)) ([88e57d4](https://github.com/cube-js/cube/commit/88e57d48b36407aa76ed7076e51903fd9daeffd7)) +- **cubestore:** Skip rolling rewrite for aggregates without aggregates ([#11134](https://github.com/cube-js/cube/issues/11134)) ([2ef39d1](https://github.com/cube-js/cube/commit/2ef39d1a47b41b12c7435591d226cd0673f3dafd)) +- **tesseract:** keep pre-aggregations for RBAC access-denied 1=0 segment ([#11123](https://github.com/cube-js/cube/issues/11123)) ([a67fa3c](https://github.com/cube-js/cube/commit/a67fa3c236120a4d6b5a62547c7d524753156e0f)) + +### Features + +- support nested view groups via includes ([#10999](https://github.com/cube-js/cube/issues/10999)) ([155987f](https://github.com/cube-js/cube/commit/155987faab5ae9e33a5571e725f7f6f6b239cb94)) + +### Performance Improvements + +- **cubestore:** faster repartition (prefetch, per-partition merge, range jobs) ([#11088](https://github.com/cube-js/cube/issues/11088)) ([f1b0ea4](https://github.com/cube-js/cube/commit/f1b0ea4d32d30673a85032c3aeef5943df7fca90)) +- **cubestore:** reduce metastore RPC fan-out during partitioning ([#11095](https://github.com/cube-js/cube/issues/11095)) ([3eae361](https://github.com/cube-js/cube/commit/3eae3613d2faf5581ca04fe2cd69984d4b7e76bb)) + +## [1.6.60](https://github.com/cube-js/cube/compare/v1.6.59...v1.6.60) (2026-06-18) + +### Bug Fixes + +- **cubesql:** Normalize BETWEEN timestamp/date bounds ([#11104](https://github.com/cube-js/cube/issues/11104)) ([455de8f](https://github.com/cube-js/cube/commit/455de8fe3656b42c3080cf5452b4d33c4c7c9eeb)) +- **docs-mintlify:** broken internal links ([#11081](https://github.com/cube-js/cube/issues/11081)) ([75bb366](https://github.com/cube-js/cube/commit/75bb366734ea48b28a2f9ddb0a22076dfd88b89f)), closes [#base_pathv1](https://github.com/cube-js/cube/issues/base_pathv1) [#query-1](https://github.com/cube-js/cube/issues/query-1) [#query-2](https://github.com/cube-js/cube/issues/query-2) +- **tesseract:** memory leaks in the native planner ([#11120](https://github.com/cube-js/cube/issues/11120)) ([6eb7afa](https://github.com/cube-js/cube/commit/6eb7afab5ad8f5e62a22a78b7097e23a8531c7d5)) + +### Features + +- **cubesql:** Support `ILIKE` SQL push down for BigQuery ([#11112](https://github.com/cube-js/cube/issues/11112)) ([73b7805](https://github.com/cube-js/cube/commit/73b78050395b58e706e344974671f3622b35ad0c)) + +## [1.6.59](https://github.com/cube-js/cube/compare/v1.6.58...v1.6.59) (2026-06-17) + +### Performance Improvements + +- **schema-compiler:** optimize granularityHierarchies to avoid O(n^2) object spread ([#11098](https://github.com/cube-js/cube/issues/11098)) ([13f1c91](https://github.com/cube-js/cube/commit/13f1c91576b0205edb0def130e90dccf4a536fad)) + +## [1.6.58](https://github.com/cube-js/cube/compare/v1.6.57...v1.6.58) (2026-06-17) + +### Bug Fixes + +- **cubesql:** Fix grouped join SQL push down regressions ([#11049](https://github.com/cube-js/cube/issues/11049)) ([c70e7ec](https://github.com/cube-js/cube/commit/c70e7ec1deffecbc58670e18905d3e81b1f8c9e5)) +- **cubestore:** stop main-node OOM from concurrent metastore scans ([#11082](https://github.com/cube-js/cube/issues/11082)) ([ee86b13](https://github.com/cube-js/cube/commit/ee86b13912246355d138ab9946125a4e5fda1d89)) +- **cubestore:** support Float32 in query result conversion ([#11078](https://github.com/cube-js/cube/issues/11078)) ([46a8454](https://github.com/cube-js/cube/commit/46a84541af3e7b512405204a9cc4f30a7e609ab8)) +- **tesseract:** Unexpected panic when pre-aggregation time_dimension are not resolved ([#11066](https://github.com/cube-js/cube/issues/11066)) ([fda5ab5](https://github.com/cube-js/cube/commit/fda5ab543b7360a1cdbcf5dbc64c8e096095e667)) + +### Features + +- **backend-shared:** add CUBEJS_AUTO_RUN_MODE env variable ([#11062](https://github.com/cube-js/cube/issues/11062)) ([3278e4d](https://github.com/cube-js/cube/commit/3278e4d4ba7180c28eb558b296c2603c8c948bb6)) +- **cubesql:** Support FULL and RIGHT joins with non-push-to-Cube SQL push down ([#11008](https://github.com/cube-js/cube/issues/11008)) ([8ef4b54](https://github.com/cube-js/cube/commit/8ef4b54e825b2bb83743e10375694aa92f119ab9)) +- **cubestore:** batch persisted-chunk repartition per partition ([#11068](https://github.com/cube-js/cube/issues/11068)) ([b5dbdf5](https://github.com/cube-js/cube/commit/b5dbdf5cf7a4234c7df98dc3e1f6ee6effae80f7)) +- **cubestore:** dedicated reserve job pool for CSV imports ([#11069](https://github.com/cube-js/cube/issues/11069)) ([85bd67b](https://github.com/cube-js/cube/commit/85bd67bd0d0fd16e8307aa3e9b9646a5dd77801e)) +- **cubestore:** env-gate last week's planning/processing changes ([#11086](https://github.com/cube-js/cube/issues/11086)) ([689d842](https://github.com/cube-js/cube/commit/689d8428eb4ec2d0f2669debc903ca8a0b9099e7)) +- **cubestore:** execute sorted partial aggregate per partition below the merge, propagate LIMIT into it ([#10995](https://github.com/cube-js/cube/issues/10995)) ([d91df4b](https://github.com/cube-js/cube/commit/d91df4b826ef9423de5bff3152ae1c0bf576e8c1)) +- **cubestore:** pre-filter in-memory chunks on worker before IPC ([#11040](https://github.com/cube-js/cube/issues/11040)) ([2394513](https://github.com/cube-js/cube/commit/2394513eba55970cde80c2660f8e482cc0820821)) +- **cubestore:** tolerant job reads + cleanup of unknown job types ([#11087](https://github.com/cube-js/cube/issues/11087)) ([87ae095](https://github.com/cube-js/cube/commit/87ae095c69588a77d2711968a66e07c9764c2e6b)) +- **schema-compiler:** capitalize ID acronyms in default meta titles ([#11047](https://github.com/cube-js/cube/issues/11047)) ([094974b](https://github.com/cube-js/cube/commit/094974b20c1bd573ac57873bedd58a32f2bbc1d4)) + +### Performance Improvements + +- **cubestore:** early compaction split ([#11079](https://github.com/cube-js/cube/issues/11079)) ([26eec6f](https://github.com/cube-js/cube/commit/26eec6f2546e89675bb7e8e6759550e328e3da20)) +- **cubestore:** load-aware placement of CSV import jobs ([#11084](https://github.com/cube-js/cube/issues/11084)) ([ddf77f2](https://github.com/cube-js/cube/commit/ddf77f2bcdc311ad936d6c8890a861c9e6854ea2)) +- **cubestore:** streaming k-way merge for compaction ([#11072](https://github.com/cube-js/cube/issues/11072)) ([b42b780](https://github.com/cube-js/cube/commit/b42b780352138fbf1a54427f03266623824c2a76)) + +## [1.6.57](https://github.com/cube-js/cube/compare/v1.6.56...v1.6.57) (2026-06-09) + +### Features + +- **cubesql:** merge view joins on a shared cube member into a single CubeScan ([#10977](https://github.com/cube-js/cube/issues/10977)) ([281e920](https://github.com/cube-js/cube/commit/281e920948552524313a67697989caa1d746e1e1)) + +## [1.6.56](https://github.com/cube-js/cube/compare/v1.6.55...v1.6.56) (2026-06-08) + +### Bug Fixes + +- **access-policies:** masked aggregate measures with row filters + multi-group member-level union ([#11026](https://github.com/cube-js/cube/issues/11026)) ([bf13b69](https://github.com/cube-js/cube/commit/bf13b69f87fe83e3ffe9ac779b91a5174d9b320a)) +- **native:** Don't fail deserializing JS numbers above u64/i64 range ([#11034](https://github.com/cube-js/cube/issues/11034)) ([44bd455](https://github.com/cube-js/cube/commit/44bd455bbaa4446088e9f20c2014d06c8da24031)) +- **prestodb-driver:** Send custom headers on nextUri poll requests ([#11037](https://github.com/cube-js/cube/issues/11037)) ([7583983](https://github.com/cube-js/cube/commit/758398358e9274cb8f8e126f5170b348c2f24ce6)) + +### Features + +- **cubestore:** EXPLAIN ANALYZE DETAILED per-query trace ([#11016](https://github.com/cube-js/cube/issues/11016)) ([107e63f](https://github.com/cube-js/cube/commit/107e63f297e5ed03b235450d0cafa4edce2fd1b5)) + +## [1.6.55](https://github.com/cube-js/cube/compare/v1.6.54...v1.6.55) (2026-06-05) + +### Features + +- **cubestore:** Introduce HttpQueryResultCompleted for zero-column r… ([#11019](https://github.com/cube-js/cube/issues/11019)) ([5a994ff](https://github.com/cube-js/cube/commit/5a994ffd0261b457aa65d77ab0125192e6187782)) +- **cubestore:** unique key filter pushdown below last-row dedup ([#11006](https://github.com/cube-js/cube/issues/11006)) ([adc8d26](https://github.com/cube-js/cube/commit/adc8d2601973635383c6b09eac46375f1586fcf6)) + +### Performance Improvements + +- **snowflake-driver:** Combine session init into a single ALTER SESSION ([#11010](https://github.com/cube-js/cube/issues/11010)) ([e29e04c](https://github.com/cube-js/cube/commit/e29e04c3e253d756816fe23347f19933577229a5)) + +## [1.6.54](https://github.com/cube-js/cube/compare/v1.6.53...v1.6.54) (2026-06-04) + +### Bug Fixes + +- **cubesql:** Don't mix filter params between subqueries in SQL push down ([#10996](https://github.com/cube-js/cube/issues/10996)) ([38b7d8c](https://github.com/cube-js/cube/commit/38b7d8c7f87e274816ce125bfcb8f94f05ebf8ea)) +- **tesseract:** make pre-aggregations tests work under native SQL planner ([#10992](https://github.com/cube-js/cube/issues/10992)) ([33ca484](https://github.com/cube-js/cube/commit/33ca484e15dedee2a7a27ba99f8d2204829926d0)) +- **tesseract:** nested CTE generation with duplicate names ([#11005](https://github.com/cube-js/cube/issues/11005)) ([a321af5](https://github.com/cube-js/cube/commit/a321af5bd635ef38cad1673902c62345b1e6c593)) +- **tesseract:** pre-aggregation table name corruption when one name is a prefix of another ([#11000](https://github.com/cube-js/cube/issues/11000)) ([f401118](https://github.com/cube-js/cube/commit/f401118db91b06fa740eb8a63bbe3755940da449)) + +### Features + +- **api-gateway:** accept a list of API secrets for verification ([#10985](https://github.com/cube-js/cube/issues/10985)) ([d9a308f](https://github.com/cube-js/cube/commit/d9a308f0ef7d6cf11213bbc05858cb0cc1a55c36)) + +## [1.6.53](https://github.com/cube-js/cube/compare/v1.6.52...v1.6.53) (2026-06-02) + +### Bug Fixes + +- **cubejs-questdb-driver:** Unsupported HAVING clause, thanks [@puzpuzpuz](https://github.com/puzpuzpuz) ([#10285](https://github.com/cube-js/cube/issues/10285)) ([632620d](https://github.com/cube-js/cube/commit/632620d783927bd3a62af1b9b05ef658dba7a784)) + +### Features + +- **cubesql:** Improve UX for parsing errors ([#10984](https://github.com/cube-js/cube/issues/10984)) ([b18fd3d](https://github.com/cube-js/cube/commit/b18fd3d05b44625ff675a8539c9ec5e2d93a068d)) +- Links in the data model ([#10852](https://github.com/cube-js/cube/issues/10852)) ([34fa717](https://github.com/cube-js/cube/commit/34fa717591e7949a1440c0602bb0e36a1bde4ae3)) +- **tesseract:** native Rust time-series generation ([#10980](https://github.com/cube-js/cube/issues/10980)) ([48a3e41](https://github.com/cube-js/cube/commit/48a3e419b31b294b9980a35c229d54383c45726a)) +- **tesseract:** NativeRustHandle/NativeRustBox in cubenativeutils ([#10979](https://github.com/cube-js/cube/issues/10979)) ([852790f](https://github.com/cube-js/cube/commit/852790fcbdbfe4b23088861b5729b1ce6769a5a5)) + +## [1.6.52](https://github.com/cube-js/cube/compare/v1.6.51...v1.6.52) (2026-05-29) + +### Bug Fixes + +- **drivers:** athena custom-granularity pre-aggregation build ([#10950](https://github.com/cube-js/cube/issues/10950)) ([f39bcf0](https://github.com/cube-js/cube/commit/f39bcf07fa09ee3b8d07da7206b7d259b431987c)) +- **tesseract:** JOIN-model assembly for multi-stage reduce_by ([#10947](https://github.com/cube-js/cube/issues/10947)) ([eab34f2](https://github.com/cube-js/cube/commit/eab34f2f9d182833c6b5bfa46c4c42d363821938)) + +### Features + +- **cubesql:** Universally prefix all errors ([#10758](https://github.com/cube-js/cube/issues/10758)) ([6c13990](https://github.com/cube-js/cube/commit/6c139904509892ec5da464b1e753de14c37b0497)) +- support distributed query cancellation in query queue and cancellation promise for Athena ([#10953](https://github.com/cube-js/cube/issues/10953)) ([0c08a78](https://github.com/cube-js/cube/commit/0c08a78edc01e5979d5e6e483854f6b971e84ebb)) +- **tesseract:** Multi-stage filter directives ([#10827](https://github.com/cube-js/cube/issues/10827)) ([2c7a614](https://github.com/cube-js/cube/commit/2c7a61422454a8d7dc30076292f341a59084a483)) +- **tesseract:** multi-stage grain directive ([#10957](https://github.com/cube-js/cube/issues/10957)) ([76eb75b](https://github.com/cube-js/cube/commit/76eb75b5a99ab863a661bc5d93ea61c05ee58ae9)) + +## [1.6.51](https://github.com/cube-js/cube/compare/v1.6.50...v1.6.51) (2026-05-27) + +### Features + +- **cubesql:** expose pre-aggregation indicator ([#10944](https://github.com/cube-js/cube/issues/10944)) ([552a93e](https://github.com/cube-js/cube/commit/552a93ec9fd7a2fce7a93ef01769f1ca8b8d84f2)) +- **cubesql:** Flatten filter rules ([#10940](https://github.com/cube-js/cube/issues/10940)) ([6aa2699](https://github.com/cube-js/cube/commit/6aa2699ffe2edc96b72946078532cb366e1a0f78)) + +### Performance Improvements + +- **cubeorchestrator:** QueryResult - migrate to columnar storage ([#10829](https://github.com/cube-js/cube/issues/10829)) ([cfe7f38](https://github.com/cube-js/cube/commit/cfe7f38bbbc660ba6a8a6ff410e675031cdcd528)) + +## [1.6.50](https://github.com/cube-js/cube/compare/v1.6.49...v1.6.50) (2026-05-22) + +### Bug Fixes + +- **schema-compiler:** Throw error for duplicate cube and view names in JS models ([#10909](https://github.com/cube-js/cube/issues/10909)) ([06c16b4](https://github.com/cube-js/cube/commit/06c16b47d18f6bd31a240aba6a7b268e90d4763b)) + +### Features + +- Enable native orchestrator for all cases (don't allow to disable it) ([#10919](https://github.com/cube-js/cube/issues/10919)) ([9268376](https://github.com/cube-js/cube/commit/9268376f1aed7c280e15dea7d52449792270d350)) + +## [1.6.49](https://github.com/cube-js/cube/compare/v1.6.48...v1.6.49) (2026-05-21) + +### Bug Fixes + +- **cubestore-cli:** Incorrect reconnections ([#10914](https://github.com/cube-js/cube/issues/10914)) ([0fa472b](https://github.com/cube-js/cube/commit/0fa472bc28c89f5f36bc0e72febec58811f700ae)) +- **tesseract:** multi-stage pre-aggregation usage substitution and IS NOT DISTINCT FROM ([#10925](https://github.com/cube-js/cube/issues/10925)) ([81b9de0](https://github.com/cube-js/cube/commit/81b9de02799c829fa982539537ebf1af24ce3e62)) + +### Features + +- **cubesql:** Allow grouped joins with SQL push down ([#10234](https://github.com/cube-js/cube/issues/10234)) ([041d753](https://github.com/cube-js/cube/commit/041d753ca045d60453af6d5d737cff19ce411ca0)) +- **cubesql:** Support parsing extra timezone formats ([#10913](https://github.com/cube-js/cube/issues/10913)) ([346eb56](https://github.com/cube-js/cube/commit/346eb567808363efb39c623f25f056018ce5a981)) +- **cubestore-cli:** Support Arrow format for responses ([#10915](https://github.com/cube-js/cube/issues/10915)) ([e4c8c43](https://github.com/cube-js/cube/commit/e4c8c43d2e060acfddd4288fa356b25f0df150bd)) +- **cubestore:** Fold IS NOT DISTINCT FROM join predicates into HashJoin keys ([#10923](https://github.com/cube-js/cube/issues/10923)) ([858c1e4](https://github.com/cube-js/cube/commit/858c1e450f0279d1139088122746ea8253edbf6b)) +- **tesseract:** default value filters for views (CORE-357) ([#10892](https://github.com/cube-js/cube/issues/10892)) ([3477776](https://github.com/cube-js/cube/commit/34777768be099310e59fa02f0c2db6ef5e74aed4)) + +## [1.6.48](https://github.com/cube-js/cube/compare/v1.6.47...v1.6.48) (2026-05-19) + +### Features + +- Introduce cubestore-cli ([#10898](https://github.com/cube-js/cube/issues/10898)) ([6a28c44](https://github.com/cube-js/cube/commit/6a28c4483c4d82d856f129d8f9a362c0a4fbc494)) +- **presto/trino-driver:** Support custom headers ([#10902](https://github.com/cube-js/cube/issues/10902)) ([ea2cdae](https://github.com/cube-js/cube/commit/ea2cdaef138385444dd0a71aeed5af58df7a115e)) +- **trino-driver:** Use headers prefix specifically to Trino (X-Trino-) ([#10904](https://github.com/cube-js/cube/issues/10904)) ([9d73d1f](https://github.com/cube-js/cube/commit/9d73d1f42f2dcc976ee8d08ce25d9681537c420c)) + +## [1.6.47](https://github.com/cube-js/cube/compare/v1.6.46...v1.6.47) (2026-05-18) + +### Bug Fixes + +- **athena-driver:** propagate query cancellation to Athena via StopQueryExecution ([#10861](https://github.com/cube-js/cube/issues/10861)) ([233e86f](https://github.com/cube-js/cube/commit/233e86fba2d2b769deedcde54d0aaec3a1cb5936)) +- **cubesql:** Correctly escape/unescape LIKE patterns ([#10862](https://github.com/cube-js/cube/issues/10862)) ([43331cc](https://github.com/cube-js/cube/commit/43331cc4cc572c469809ecd4bf48bc06b473d55f)) +- **schema-compiler:** resolve time dimension granularity columns in pre-aggregation indexes ([#10894](https://github.com/cube-js/cube/issues/10894)) ([c164aab](https://github.com/cube-js/cube/commit/c164aab31ec106bcff8dd26c305c3129a205f851)) +- **tesseract:** align bridge member SQL with JS proxy reference ([#10850](https://github.com/cube-js/cube/issues/10850)) ([d5da121](https://github.com/cube-js/cube/commit/d5da121820e120d9a7012e5a787d3780953d915c)) +- **tesseract:** tautological FK-aggregate join for filtered PK counts ([#10762](https://github.com/cube-js/cube/issues/10762)) ([b647dd5](https://github.com/cube-js/cube/commit/b647dd5045fd9a01990e615631a322236885bb24)) +- **tesseract:** wrap composed expressions before timestamptz cast in convert_tz ([#10859](https://github.com/cube-js/cube/issues/10859)) ([cab0a18](https://github.com/cube-js/cube/commit/cab0a186175f1fb1e14d72d1f1c4281d0d4d77b3)) + +### Performance Improvements + +- **backend-native:** String interning for keys in get_cubestore_result ([#10869](https://github.com/cube-js/cube/issues/10869)) ([22031fb](https://github.com/cube-js/cube/commit/22031fb00b40fd553dc6aca5c2333064f04bf222)) +- **cubeorchestrator:** Improve performance of vanilla format ([#10876](https://github.com/cube-js/cube/issues/10876)) ([3975ae3](https://github.com/cube-js/cube/commit/3975ae3b41f81d29e50c3b3abd30e2d42db58b68)) +- **cubeorchestrator:** Resolve minimal-granularity for vanilla at planning ([#10874](https://github.com/cube-js/cube/issues/10874)) ([4814ae3](https://github.com/cube-js/cube/commit/4814ae3278cd0e416c8af8694d56d37bdce60745)) + +## [1.6.46](https://github.com/cube-js/cube/compare/v1.6.45...v1.6.46) (2026-05-11) + +### Performance Improvements + +- **cubeorchestrator:** Hand-written Deserialize for DBResponsePrimitive (-95%, ~20x parse) ([#10853](https://github.com/cube-js/cube/issues/10853)) ([f4eb034](https://github.com/cube-js/cube/commit/f4eb034b952dd1a07a188e8ca253b072d237e596)) + +## [1.6.45](https://github.com/cube-js/cube/compare/v1.6.44...v1.6.45) (2026-05-11) + +### Bug Fixes + +- **schema-compiler:** handle sqlTable in originalSql pre-aggregation ([#10824](https://github.com/cube-js/cube/issues/10824)) ([3d82f94](https://github.com/cube-js/cube/commit/3d82f94b384260f5676fabaee1544d7f8b4935c4)) +- **schema-compiler:** invalidate Jinja render cache when imported macro file changes ([#10818](https://github.com/cube-js/cube/issues/10818)) ([e60ad99](https://github.com/cube-js/cube/commit/e60ad99f9ddee99cfa8c1e528b8746e2ebb3ee17)) + +### Features + +- **cubestore:** add stale-while-revalidate timeout for SQL query cache ([#10822](https://github.com/cube-js/cube/issues/10822)) ([f050b10](https://github.com/cube-js/cube/commit/f050b103f58d40669b923ed9fdc651e50b93ee5e)) + +### Performance Improvements + +- **cubeorchestrator:** Drop DBResponseValue wrapper (-15% transform) ([#10844](https://github.com/cube-js/cube/issues/10844)) ([4e26c26](https://github.com/cube-js/cube/commit/4e26c26cd722cec721953ce7330d1f865d56ee5c)) +- **cubeorchestrator:** Use columnar format between JS->Rust data transport (-20%) ([#10837](https://github.com/cube-js/cube/issues/10837)) ([1a64945](https://github.com/cube-js/cube/commit/1a64945546a1ca5facc8ac3ff611be4daccf5c52)) + +## [1.6.44](https://github.com/cube-js/cube/compare/v1.6.43...v1.6.44) (2026-05-06) + +### Features + +- **api-gateway:** add support for onlyViews parameter in meta endpoint ([#10809](https://github.com/cube-js/cube/issues/10809)) ([e38fc38](https://github.com/cube-js/cube/commit/e38fc38007a5b0d547131b5a31953681bcc7ec14)) +- conditional data masking with row-level filters in access policies ([#10803](https://github.com/cube-js/cube/issues/10803)) ([4d3bcbe](https://github.com/cube-js/cube/commit/4d3bcbe064139d0d809b3d421dcec05d9e634778)) +- **cubestore:** Support Arrow IPC response format ([#10819](https://github.com/cube-js/cube/issues/10819)) ([3226a63](https://github.com/cube-js/cube/commit/3226a63e8854707cf2c8eb0b4b35462c3571c178)) + +### Performance Improvements + +- **cubeorchestrator:** Improve compact transform (-70%, 3x) ([#10830](https://github.com/cube-js/cube/issues/10830)) ([79f7a70](https://github.com/cube-js/cube/commit/79f7a70f944fabd131da51d179cf2665522628e1)) +- **cubesql:** Fast path for timespamp parsing for cube results ([#10826](https://github.com/cube-js/cube/issues/10826)) ([7f37faa](https://github.com/cube-js/cube/commit/7f37faa9409975ffc64e57c73991c1926513f88e)) +- **cubesql:** Migrate to columnar format in transport (~5x) ([#10805](https://github.com/cube-js/cube/issues/10805)) ([87f4dc1](https://github.com/cube-js/cube/commit/87f4dc1c2cc47b76c8b72cf96010e94d50a748bd)) + +## [1.6.43](https://github.com/cube-js/cube/compare/v1.6.42...v1.6.43) (2026-05-02) + +### Features + +- add view_group support to data model ([#10768](https://github.com/cube-js/cube/issues/10768)) ([6ebae55](https://github.com/cube-js/cube/commit/6ebae5570f92e56c802c6dd3b22ca8ed339b48c8)) + +## [1.6.42](https://github.com/cube-js/cube/compare/v1.6.41...v1.6.42) (2026-05-01) + +### Bug Fixes + +- **client-core:** make CJS consumers work for main entry and /format subpath ([#10796](https://github.com/cube-js/cube/issues/10796)) ([1b40ddc](https://github.com/cube-js/cube/commit/1b40ddcbc84f67c0c2d35d130dd715a19a5e72d8)), closes [#5917](https://github.com/cube-js/cube/issues/5917) [#9562](https://github.com/cube-js/cube/issues/9562) + +### Features + +- **client-core:** extend numeric formatting options with precision a… ([#10800](https://github.com/cube-js/cube/issues/10800)) ([dd50d32](https://github.com/cube-js/cube/commit/dd50d32af37fc8d4610618e50f449f080a2c4a11)) + +## [1.6.41](https://github.com/cube-js/cube/compare/v1.6.40...v1.6.41) (2026-05-01) + +### Bug Fixes + +- **schema-compiler:** preserve currency value in views ([#10793](https://github.com/cube-js/cube/issues/10793)) ([613af8d](https://github.com/cube-js/cube/commit/613af8d52dc711021ec564645e0cb86e7a4f2be3)) + +## [1.6.40](https://github.com/cube-js/cube/compare/v1.6.39...v1.6.40) (2026-04-30) + +### Bug Fixes + +- **backend-native:** Respect `isDataQuery` flag in `cubesql` endpoint ([#10774](https://github.com/cube-js/cube/issues/10774)) ([6f3c031](https://github.com/cube-js/cube/commit/6f3c031993a292acca7d7031b18e2e31c8523d1a)) +- **cubesql:** Do not throw error on empty peer based evaluation in window aggregates ([#10776](https://github.com/cube-js/cube/issues/10776)) ([d6ca598](https://github.com/cube-js/cube/commit/d6ca598d9080ffc960a63ac5ca4e7a02486385d6)) +- **cubesql:** Preserve errors when panicking ([#10771](https://github.com/cube-js/cube/issues/10771)) ([5d571d4](https://github.com/cube-js/cube/commit/5d571d4229a5419ddf5340739c6af64b87769b2e)) +- **schema-compiler:** remove AthenaQuery.convertTz override that produces wrong timestamps on engine v3 ([#10779](https://github.com/cube-js/cube/issues/10779)) ([f395432](https://github.com/cube-js/cube/commit/f395432ea7db963da345db32d3ede7bbd38d9c68)) +- Support not in access policy conditions ([#10767](https://github.com/cube-js/cube/issues/10767)) ([1f755a1](https://github.com/cube-js/cube/commit/1f755a10bd8140d52e9fa6c145185fd3b5835434)) +- **tesseract:** CASE handling fixes in multi-stage measures ([#10764](https://github.com/cube-js/cube/issues/10764)) ([cb66e8e](https://github.com/cube-js/cube/commit/cb66e8e755824319007f5ff90e1663c9d6f51137)) + +### Features + +- **snowflake-driver:** Upgrade snowflake-sdk to 2.4.0 ([#10765](https://github.com/cube-js/cube/issues/10765)) ([d9fa353](https://github.com/cube-js/cube/commit/d9fa353e1189d8594b74e8652b94413767088222)) +- Support columnar format in REST-API /v1/load ([#10775](https://github.com/cube-js/cube/issues/10775)) ([1f749cf](https://github.com/cube-js/cube/commit/1f749cf5c37d5f8dbe70fb6d785f66da02408507)) +- **tesseract:** Support separate pre-aggregations for different multi-fact subqueries ([#10718](https://github.com/cube-js/cube/issues/10718)) ([187ee17](https://github.com/cube-js/cube/commit/187ee17da2242bc2387545bbc0559620d537a443)) +- **tesseract:** Support separate pre-aggregations for different multi-stage subqueries ([#10684](https://github.com/cube-js/cube/issues/10684)) ([46b7106](https://github.com/cube-js/cube/commit/46b71064576beb17992ef5cdc500da7f17d9baf5)) +- update default number formats to trim insignificant trailing zeros ([#10782](https://github.com/cube-js/cube/issues/10782)) ([22694eb](https://github.com/cube-js/cube/commit/22694ebb25038c5089768f35d942cfa15aefb765)) + +### Performance Improvements + +- **cubeorchestrator:** Improve columnar transform (−77%, 4.4x) ([#10786](https://github.com/cube-js/cube/issues/10786)) ([9e8a6ad](https://github.com/cube-js/cube/commit/9e8a6add84689781c7b02debf3137430cf2ea57a)) +- **cubeorchestrator:** Improve performance of get_vanilla_row (−66.8%, 3x) ([#10783](https://github.com/cube-js/cube/issues/10783)) ([0c2cb89](https://github.com/cube-js/cube/commit/0c2cb89eb7b32fbce69dbe09b166a82ef6a1edf4)) +- **cubesql:** Avoid cloning row payload in convert_transport_response ([#10772](https://github.com/cube-js/cube/issues/10772)) ([388607c](https://github.com/cube-js/cube/commit/388607cf9737e5ddb5712e484fd8af4ac30cc4b4)) +- **cubestore-driver:** Enable sendable parameters by default ([#10763](https://github.com/cube-js/cube/issues/10763)) ([af206b4](https://github.com/cube-js/cube/commit/af206b4426e7cc6c57d7b325a6b9f0d82ac09cb3)) +- **snowflake-driver:** replace formatToTimeZone with UTC formatter (~12x) ([#10759](https://github.com/cube-js/cube/issues/10759)) ([af08537](https://github.com/cube-js/cube/commit/af08537f6f9774ed3152e9977cc97955cb60eee1)) + +## [1.6.39](https://github.com/cube-js/cube/compare/v1.6.38...v1.6.39) (2026-04-24) + +### Bug Fixes + +- **bigquery-driver:** Return int64/float64 as strings in query/stream ([#10738](https://github.com/cube-js/cube/issues/10738)) ([15626b1](https://github.com/cube-js/cube/commit/15626b1281dc5e09a28e1612c69f63ab68b9d7cc)) +- **tesseract:** mask.sql with cross-cube refs through prefixed views ([#10727](https://github.com/cube-js/cube/issues/10727)) ([e52f201](https://github.com/cube-js/cube/commit/e52f201e20bdd1ab3a7556049099d286397e29b9)) + +### Performance Improvements + +- **cubejs-backend-native:** Transfer ResultWrapper rawData as Buffer(JSON), ~10x faster ([#10728](https://github.com/cube-js/cube/issues/10728)) ([291205f](https://github.com/cube-js/cube/commit/291205f62b982be135ea153faaee9886e3fc4534)) +- **postgres-driver:** Fast date, timestamp/tz parsers ([#10737](https://github.com/cube-js/cube/issues/10737)) ([c3a5709](https://github.com/cube-js/cube/commit/c3a570989fa26cd14b00205e6fc62645c7dc0a6d)) + +## [1.6.38](https://github.com/cube-js/cube/compare/v1.6.37...v1.6.38) (2026-04-23) + +### Features + +- **cubestore-driver:** Upgrade flatbuffers to 25.9.23 ([#10717](https://github.com/cube-js/cube/issues/10717)) ([311a6a8](https://github.com/cube-js/cube/commit/311a6a8ca3d03ba88596f0664d3aabd7ce4182fc)) +- **cubestore:** Support passing parameters in protocol (cache/queue) ([#6225](https://github.com/cube-js/cube/issues/6225)) ([06f64cf](https://github.com/cube-js/cube/commit/06f64cf32e7d36bf6233c71e9cf8bc95d4e48aee)) +- **tesseract:** auto-parenthesize compound SqlCall substitutions ([#10724](https://github.com/cube-js/cube/issues/10724)) ([063d0ac](https://github.com/cube-js/cube/commit/063d0ac430457e7911decdcfc2b97d7363c51b63)) + +## [1.6.37](https://github.com/cube-js/cube/compare/v1.6.36...v1.6.37) (2026-04-20) + +### Features + +- **client-core:** Format API - expose formatDateByGranularity, getFormat ([#10704](https://github.com/cube-js/cube/issues/10704)) ([b6e5886](https://github.com/cube-js/cube/commit/b6e58860c7e7aa7d65527a89fa7acf0586a569c2)) +- **cubeshared:** Upgrade flatbuffers to 25.12.19 ([#10709](https://github.com/cube-js/cube/issues/10709)) ([107f339](https://github.com/cube-js/cube/commit/107f33931c6d18800c7d579ef5d33e8932f34ac3)) + +## [1.6.36](https://github.com/cube-js/cube/compare/v1.6.35...v1.6.36) (2026-04-16) + +### Bug Fixes + +- **backend-shared:** Exclude non-credential env vars from separate pre-agg credentials trigger ([#10699](https://github.com/cube-js/cube/issues/10699)) ([2f31cf4](https://github.com/cube-js/cube/commit/2f31cf4f3359862be5029eeca04e96f5ef917c5b)) +- **docs:** remove multiplication by 100 in percentage measure examples ([#10607](https://github.com/cube-js/cube/issues/10607)) ([bca52d9](https://github.com/cube-js/cube/commit/bca52d91dfdfbc252dd53d364b5958239161c56a)) + +### Features + +- **cubestore:** support AWS Web Identity Token File in S3RemoteFs ([#10687](https://github.com/cube-js/cube/issues/10687)) ([867a236](https://github.com/cube-js/cube/commit/867a2365a5885ef39c0ce18e51edb0406f6a9a7a)) + +## [1.6.35](https://github.com/cube-js/cube/compare/v1.6.34...v1.6.35) (2026-04-15) + +### Bug Fixes + +- **tesseract:** Issue with multistage rolling window without time dimension ([#10691](https://github.com/cube-js/cube/issues/10691)) ([78f80c9](https://github.com/cube-js/cube/commit/78f80c9c12b4fed628dd3b3b9678d86472d14109)) + +### Features + +- **api-gateway:** Introduce Query format Convertion API ([#10286](https://github.com/cube-js/cube/issues/10286)) ([9ba2897](https://github.com/cube-js/cube/commit/9ba289732c5d6c2545ce3ce086003d1caea3dd58)) +- **client-core:** Improve format API ([#10692](https://github.com/cube-js/cube/issues/10692)) ([9fee612](https://github.com/cube-js/cube/commit/9fee612f8d0e3d045a18edfa97283749beff760f)) +- **cubestore:** Sync tables cache instead of reset ([#10686](https://github.com/cube-js/cube/issues/10686)) ([d0617a0](https://github.com/cube-js/cube/commit/d0617a0158ebb504cef563f6185b096082fa9fd2)) + +## [1.6.34](https://github.com/cube-js/cube/compare/v1.6.33...v1.6.34) (2026-04-14) + +### Features + +- add format description handling ([#10688](https://github.com/cube-js/cube/issues/10688)) ([365bd74](https://github.com/cube-js/cube/commit/365bd74cdf420505ab073624462cd49127a4ca6a)) +- Generate unique names for pool with dataSource & preAggregation… ([#10680](https://github.com/cube-js/cube/issues/10680)) ([df1b7e7](https://github.com/cube-js/cube/commit/df1b7e70949b8db698a017ecc490c3788aa1d96f)) +- **postgres-driver:** improve DX with connection error messages ([#10679](https://github.com/cube-js/cube/issues/10679)) ([65fb8a8](https://github.com/cube-js/cube/commit/65fb8a847ef94f20b6b24bf8aa16f943932c1bcd)) +- **query-orchestrator:** Queue - support to use external_id (under flag) ([#10538](https://github.com/cube-js/cube/issues/10538)) ([810b776](https://github.com/cube-js/cube/commit/810b77609121fbec167dd6b97be95029bffb58f7)) +- Support pre-aggregation-specific data source configuration ([#10587](https://github.com/cube-js/cube/issues/10587)) ([04eed5d](https://github.com/cube-js/cube/commit/04eed5d5ba3c1ceb8cda3c13eebf7f354eb61f48)) + +## [1.6.33](https://github.com/cube-js/cube/compare/v1.6.32...v1.6.33) (2026-04-09) + +### Bug Fixes + +- **backend-native:** Fix `Continue wait` SQL API over HTTP event reporting ([#10649](https://github.com/cube-js/cube/issues/10649)) ([18d1e65](https://github.com/cube-js/cube/commit/18d1e65e7b7195de634dc74b17e2bc824ae0e3cf)) +- **bigquery:** Align time series output type to TIMESTAMP for tesseract planner, thanks [@tlangton3](https://github.com/tlangton3) ([#10645](https://github.com/cube-js/cube/issues/10645)) ([05ab975](https://github.com/cube-js/cube/commit/05ab9752a03cd9ca2095cf96133e3c896d5ed455)), closes [cube-js/cube#10642](https://github.com/cube-js/cube/issues/10642) +- **cubestore:** Typo in metric name, thanks [@borqq](https://github.com/borqq) ([#10637](https://github.com/cube-js/cube/issues/10637)) ([b91073e](https://github.com/cube-js/cube/commit/b91073e31cfaa312fa1e9971b9cc2bb6fccd712a)) +- **playground:** Multiple percent-formatted values by 100 before display, thanks [@hank-sq](https://github.com/hank-sq) ([#10624](https://github.com/cube-js/cube/issues/10624)) ([6f79820](https://github.com/cube-js/cube/commit/6f798204219bbb975fd3d7123f35e182f55fd9bb)), closes [#10623](https://github.com/cube-js/cube/issues/10623) +- **tesseract:** Issue with filters over multi-fact measure ([#10650](https://github.com/cube-js/cube/issues/10650)) ([7169d39](https://github.com/cube-js/cube/commit/7169d39b440e7cabe181cfecebd589880aee51ec)) + +### Features + +- **api-gateway:** propagate request ID for REST /cubesql endpoint ([#10633](https://github.com/cube-js/cube/issues/10633)) ([1bce74b](https://github.com/cube-js/cube/commit/1bce74bc1ec6dac8f3eae5cf9d76a2e9915123e3)) +- **client-core:** Introduce formating API ([#10653](https://github.com/cube-js/cube/issues/10653)) ([971b9f6](https://github.com/cube-js/cube/commit/971b9f66c77bff50428fa065ddb8d99f3065fc3a)) +- **cubestore:** add configurable compaction readiness threshold for table creation ([#10629](https://github.com/cube-js/cube/issues/10629)) ([cc9b488](https://github.com/cube-js/cube/commit/cc9b488c101d23b5746743653c53cb1617302af9)) +- **cubestore:** Queue - re-scope external_id uniqueness per path ([#10635](https://github.com/cube-js/cube/issues/10635)) ([4a9453b](https://github.com/cube-js/cube/commit/4a9453b3d42c44d0c2c2cc4bcdba9de4ccb26d81)) + +### Performance Improvements + +- **client-core:** Optimize pivot axisValues and add benchmarks ([#10648](https://github.com/cube-js/cube/issues/10648)) ([0f3a79b](https://github.com/cube-js/cube/commit/0f3a79bfd27a3f807aedb80dd73655b91d8fcbf1)) + +## [1.6.32](https://github.com/cube-js/cube/compare/v1.6.31...v1.6.32) (2026-04-06) + +### Bug Fixes + +- SECURITY_CONTEXT renders empty strings on filter with enabled Tesseract ([#10576](https://github.com/cube-js/cube/issues/10576)) ([6d9afac](https://github.com/cube-js/cube/commit/6d9afac3e16a5c8a948887270f0304f78a736c5f)) + +## [1.6.31](https://github.com/cube-js/cube/compare/v1.6.30...v1.6.31) (2026-04-02) + +### Bug Fixes + +- skip annotation check for filter-only time dimensions, thanks [@jwils](https://github.com/jwils) ([#10603](https://github.com/cube-js/cube/issues/10603)) ([98e3c19](https://github.com/cube-js/cube/commit/98e3c19e5d70cfdb1c705d58a87c88524e78d416)), closes [#10590](https://github.com/cube-js/cube/issues/10590) [#10601](https://github.com/cube-js/cube/issues/10601) + +### Features + +- **tesseract:** Support multiple time dimensions in pre-aggregations ([#10599](https://github.com/cube-js/cube/issues/10599)) ([c773953](https://github.com/cube-js/cube/commit/c77395389038f384a686a8f2cee3cc39249d51af)) + +## [1.6.30](https://github.com/cube-js/cube/compare/v1.6.29...v1.6.30) (2026-04-01) + +### Bug Fixes + +- cached GraphQL schema can result in missing members if used with access policies ([#10590](https://github.com/cube-js/cube/issues/10590)) ([c95317b](https://github.com/cube-js/cube/commit/c95317be96d51d381dfd4c782d88205b3f5730bb)) +- **cube:** Quarter intervals in postgres ([#10580](https://github.com/cube-js/cube/issues/10580)) ([defc186](https://github.com/cube-js/cube/commit/defc186c39d447a24914e7b1d924095c8761dabf)) +- **tesseract:** Filter by multi-stage measure ([#10579](https://github.com/cube-js/cube/issues/10579)) ([4a4b67f](https://github.com/cube-js/cube/commit/4a4b67f50fcf6ced8ddb493ec90b3dc9f4c93b1e)) +- **tesseract:** Tesseract should respect convertTzForRawTimeDimension ([#10585](https://github.com/cube-js/cube/issues/10585)) ([515eeae](https://github.com/cube-js/cube/commit/515eeaef4abf554a3291b8a4d2603240281915a3)) + +### Features + +- **cubesql:** Support PatchMeasure for view measures ([#10571](https://github.com/cube-js/cube/issues/10571)) ([3bfe812](https://github.com/cube-js/cube/commit/3bfe8121be684fb08e22e27efb59877734276dba)) +- **mssql-driver:** Support use named timezones ([#10582](https://github.com/cube-js/cube/issues/10582)) ([ee788f4](https://github.com/cube-js/cube/commit/ee788f4f843073eb26bf07e101f83084e653270f)) + +## [1.6.29](https://github.com/cube-js/cube/compare/v1.6.28...v1.6.29) (2026-03-27) + +### Features + +- **cubesql:** Expose format in /v1/cubesql schema response ([#10555](https://github.com/cube-js/cube/issues/10555)) ([f8d79a2](https://github.com/cube-js/cube/commit/f8d79a2e8c0e1fb291d7d55a21cb329c387605a4)) +- Expose alias for named numeric format ([#10568](https://github.com/cube-js/cube/issues/10568)) ([662bc58](https://github.com/cube-js/cube/commit/662bc581c38c87eddb40505dd1847f1f2c79bac9)) +- **schema-compiler:** Support currency for numeric measures and dimensions ([#10561](https://github.com/cube-js/cube/issues/10561)) ([5fc721f](https://github.com/cube-js/cube/commit/5fc721f98429cc46395673b03283c501a59c5cdd)) +- **schema-compiler:** Support predefined named numeric formats ([#10563](https://github.com/cube-js/cube/issues/10563)) ([f060f5c](https://github.com/cube-js/cube/commit/f060f5c6a8a8c5cfe1b06be79f4c189520d3453b)) + +### Reverts + +- Revert "chore: test td" ([5b6f8d6](https://github.com/cube-js/cube/commit/5b6f8d66cb3786cc27f6f693d5715b430437eeb1)) + +## [1.6.28](https://github.com/cube-js/cube/compare/v1.6.27...v1.6.28) (2026-03-25) + +### Bug Fixes + +- **cubestore:** Respect nulls for unique indexes with skip ([#10553](https://github.com/cube-js/cube/issues/10553)) ([e27868c](https://github.com/cube-js/cube/commit/e27868c62f46d94b958bf5a33718c15eaa7fdec8)) +- Value for custom-time/numeric format for /v1/load annotations ([#10554](https://github.com/cube-js/cube/issues/10554)) ([5f432d8](https://github.com/cube-js/cube/commit/5f432d8019bc7124542f74249ddf76adeb90c163)) + +### Features + +- **cubestore:** Partition distribution for join ([#10480](https://github.com/cube-js/cube/issues/10480)) ([9da75cd](https://github.com/cube-js/cube/commit/9da75cdf0ef42efeb9288ea8b76f3a9d7488082e)) + +## [1.6.27](https://github.com/cube-js/cube/compare/v1.6.26...v1.6.27) (2026-03-24) + +### Features + +- **cubestore:** Queue - allow path lookup, if there was miss on external_id ([#10543](https://github.com/cube-js/cube/issues/10543)) ([8fe8892](https://github.com/cube-js/cube/commit/8fe88921e22bbe2967d68c3a0ef379ae97533347)) + +## [1.6.26](https://github.com/cube-js/cube/compare/v1.6.25...v1.6.26) (2026-03-23) + +### Features + +- **cubestore:** Queue - allow to specify EXTERNAL_ID for RESULT ([#10536](https://github.com/cube-js/cube/issues/10536)) ([52a0c21](https://github.com/cube-js/cube/commit/52a0c21175a93c91ded63fecbe255b0d7c3252be)) + +## [1.6.25](https://github.com/cube-js/cube/compare/v1.6.24...v1.6.25) (2026-03-20) + +### Bug Fixes + +- **cubestore:** Queue - filter expired queue_results ([#10527](https://github.com/cube-js/cube/issues/10527)) ([fc51856](https://github.com/cube-js/cube/commit/fc5185672cab1199683422e5bddbaba663a1ef38)) +- **docs:** Prevent scroll jump on CodeTabs tab switch ([#10523](https://github.com/cube-js/cube/issues/10523)) ([2270e28](https://github.com/cube-js/cube/commit/2270e28ecee10a45605e92a22d76ee325923fee1)) +- **server-core:** Restore log level inheritance ([#10532](https://github.com/cube-js/cube/issues/10532)) ([703d631](https://github.com/cube-js/cube/commit/703d6312e49521eb188e0c3cd24af16400934b95)), closes [#10144](https://github.com/cube-js/cube/issues/10144) + +### Features + +- **cubestore:** Queue - introduce external_id support ([#10507](https://github.com/cube-js/cube/issues/10507)) ([73f17b7](https://github.com/cube-js/cube/commit/73f17b7117f740444e445cdfa6b96cc48ee00b44)) +- **cubestore:** Queue - support QUEUE RESULT by $id ([#10529](https://github.com/cube-js/cube/issues/10529)) ([ef98588](https://github.com/cube-js/cube/commit/ef9858857bd933559afe51d211a92fad9067bab0)) + +## [1.6.24](https://github.com/cube-js/cube/compare/v1.6.23...v1.6.24) (2026-03-18) + +### Bug Fixes + +- **cubesql:** Push `Distinct` down CubeScan with time dimensions ([#10518](https://github.com/cube-js/cube/issues/10518)) ([028eadc](https://github.com/cube-js/cube/commit/028eadcec1ce7aa294f29395cfb272448e9b08a1)) +- **query-orchestrator:** Return cached result when refreshKey changes during must-revalidate ([#10489](https://github.com/cube-js/cube/issues/10489)) ([e00fe12](https://github.com/cube-js/cube/commit/e00fe125a546926e85b5c1c1be70a46fabcd53ff)) +- **schema-compiler:** Use isNotDistinctFrom() for ClickHouse Tesseract multi-fact joins ([#10494](https://github.com/cube-js/cube/issues/10494)) ([43429eb](https://github.com/cube-js/cube/commit/43429eb59f941036f6e4a7fa22ca670544bb2193)), closes [#10493](https://github.com/cube-js/cube/issues/10493) +- **tesseract:** Incorrect ubounded rolling window without granularity ([#10508](https://github.com/cube-js/cube/issues/10508)) ([33a68a0](https://github.com/cube-js/cube/commit/33a68a02574c815c748dd5383c421621e220d68d)) +- **tesseract:** Measure with string type ends up with SUM aggregation ([#10516](https://github.com/cube-js/cube/issues/10516)) ([589d20f](https://github.com/cube-js/cube/commit/589d20fc5fb6b93c861e54b1df2901742146a75a)) +- **tesseract:** Pre-aggregations matching should respect join path ([#10500](https://github.com/cube-js/cube/issues/10500)) ([eec59a2](https://github.com/cube-js/cube/commit/eec59a2e4736d4b3a973abe98028fbfd3af54262)) +- **tesseract:** Subquery dimension in filter ([#10506](https://github.com/cube-js/cube/issues/10506)) ([58c0687](https://github.com/cube-js/cube/commit/58c06879b93110336740fc7792144ca1165239df)) +- **tesseract:** Tesseract should respect sql api aliases ([#10505](https://github.com/cube-js/cube/issues/10505)) ([d5f6351](https://github.com/cube-js/cube/commit/d5f635105de2e4e881f5ec8b6a073cb62b031295)) + +### Features + +- **tesseract:** ClickHouse support ([#10515](https://github.com/cube-js/cube/issues/10515)) ([cbdc6e8](https://github.com/cube-js/cube/commit/cbdc6e80108f15320a11b8cb6340251ea704c1db)) + +## [1.6.23](https://github.com/cube-js/cube/compare/v1.6.22...v1.6.23) (2026-03-13) + +### Bug Fixes + +- **api-gateway:** Returns null for all measures except the last one, fix [#10482](https://github.com/cube-js/cube/issues/10482) ([#10495](https://github.com/cube-js/cube/issues/10495)) ([cc0b93a](https://github.com/cube-js/cube/commit/cc0b93abd9457b20140101da045cbf15f52a03db)), closes [#10428](https://github.com/cube-js/cube/issues/10428) + +### Features + +- **cubestore-driver:** Queue - use exclusive flag with new Cube Store ([#10488](https://github.com/cube-js/cube/issues/10488)) ([c6462e4](https://github.com/cube-js/cube/commit/c6462e478bcb8a8b2caccc32787e52a8b2198852)) +- **cubestore:** Filter queue_list by process_id for exclusive items ([#10490](https://github.com/cube-js/cube/issues/10490)) ([8458998](https://github.com/cube-js/cube/commit/84589988b29410f07c213b81405a824f49c599bc)) +- Data access policy masking ([#10463](https://github.com/cube-js/cube/issues/10463)) ([4b0d1bf](https://github.com/cube-js/cube/commit/4b0d1bfe49d8dbd72a9df03718793179e20ed167)) + +## [1.6.22](https://github.com/cube-js/cube/compare/v1.6.21...v1.6.22) (2026-03-11) + +**Note:** Version bump only for package cubejs + +## [1.6.21](https://github.com/cube-js/cube/compare/v1.6.20...v1.6.21) (2026-03-10) + +### Bug Fixes + +- **cubesql:** Support per-column format codes (Tableau Desktop compatibility) ([#10484](https://github.com/cube-js/cube/issues/10484)) ([d6ad885](https://github.com/cube-js/cube/commit/d6ad885f384d675f25ca8405dad4ee5a559e98c3)), closes [#10418](https://github.com/cube-js/cube/issues/10418) + +### Features + +- **client-core:** Use `throwContinueWait` parameter in `cubeSql` method ([#10461](https://github.com/cube-js/cube/issues/10461)) ([53a80fd](https://github.com/cube-js/cube/commit/53a80fd159fb1655b5ac5b467414b4a5352fae90)) +- **cubesql:** Introduce `cube_cache` session variable ([#10483](https://github.com/cube-js/cube/issues/10483)) ([541aa34](https://github.com/cube-js/cube/commit/541aa3465f25cb55328249b95fa9c258c95f5e07)) +- **cubestore:** Logarithmic probabilistic increment of LFU counter ([#10478](https://github.com/cube-js/cube/issues/10478)) ([4b8ac6f](https://github.com/cube-js/cube/commit/4b8ac6ff81b0ee114cd0bc4a5e8235fe294c53a2)) +- **cubestore:** Queue - add exclusivity support ([#10479](https://github.com/cube-js/cube/issues/10479)) ([b5a0ec3](https://github.com/cube-js/cube/commit/b5a0ec32c061834af0c30bd7def9097ae27af32f)) + +## [1.6.20](https://github.com/cube-js/cube/compare/v1.6.19...v1.6.20) (2026-03-09) + +### Bug Fixes + +- **cube:** Issue with rollup pre-aggragations matching for views ([#10474](https://github.com/cube-js/cube/issues/10474)) ([7160283](https://github.com/cube-js/cube/commit/7160283c7dac5d5696cf683b8e59418e58453821)) +- **cubesql:** Do not panic when executing `MEASURE` function ([#10472](https://github.com/cube-js/cube/issues/10472)) ([3202d51](https://github.com/cube-js/cube/commit/3202d517dce747831ff2549f30f4888b11bb005b)) + +### Features + +- **backend-native:** Add `throwContinueWait` parameter to `/cubesql` API endpoint ([#10385](https://github.com/cube-js/cube/issues/10385)) ([3687c5f](https://github.com/cube-js/cube/commit/3687c5f422d6b265409a3e539fc77f37df207eb1)) +- **cubestore-driver:** Share process-id with Cube Store ([#10477](https://github.com/cube-js/cube/issues/10477)) ([36c4aa2](https://github.com/cube-js/cube/commit/36c4aa2736122d14098b1ca3ec15c0828b5527e4)) + +## [1.6.19](https://github.com/cube-js/cube/compare/v1.6.18...v1.6.19) (2026-03-03) + +### Bug Fixes + +- **api-gateway:** Accept `cache` parameter in WebSocket requests, fix [#10451](https://github.com/cube-js/cube/issues/10451) ([#10453](https://github.com/cube-js/cube/issues/10453)) ([5e8d0eb](https://github.com/cube-js/cube/commit/5e8d0ebf96e93afe5d8e7c1a5f2ae278b1671c17)) +- **api-gateway:** Remove Transfer-Encoding header on /cubesql error responses, fix [#10450](https://github.com/cube-js/cube/issues/10450) ([#10455](https://github.com/cube-js/cube/issues/10455)) ([1b4f137](https://github.com/cube-js/cube/commit/1b4f1375233cf3064f7d9cf909f053b9fc195541)) +- **query-orchestrator:** Queue - improve performance for high concurrency ([#9705](https://github.com/cube-js/cube/issues/9705)) ([7a3c1a6](https://github.com/cube-js/cube/commit/7a3c1a6dababeca87ec0279f168657c0742d9137)) + +## [1.6.18](https://github.com/cube-js/cube/compare/v1.6.17...v1.6.18) (2026-03-02) + +### Bug Fixes + +- **client-core:** return null instead of undefined when query is cancelled by mutex, fix [#10261](https://github.com/cube-js/cube/issues/10261) ([#10274](https://github.com/cube-js/cube/issues/10274)) ([ea6b3e7](https://github.com/cube-js/cube/commit/ea6b3e78afc1aea7f020d44c7505ea14cfc4fe02)) + +### Features + +- **client-core:** Add cache mode option to load method, thanks [@hannosgit](https://github.com/hannosgit) ([#10446](https://github.com/cube-js/cube/issues/10446)) ([aabbbc6](https://github.com/cube-js/cube/commit/aabbbc6d44408d368fd32a8f2c64b91c64d0437d)) +- **client-react:** Allow to pass cache mode as option ([#10447](https://github.com/cube-js/cube/issues/10447)) ([03e8ca5](https://github.com/cube-js/cube/commit/03e8ca53e8e92eb19a84587a475982a42261aba4)) +- **schema-compiler:** Add duplicate folder name and time shift validation ([#10423](https://github.com/cube-js/cube/issues/10423)) ([2000373](https://github.com/cube-js/cube/commit/200037317fc1f90edf169ce02d7967fa331a09f4)) + +## [1.6.17](https://github.com/cube-js/cube/compare/v1.6.16...v1.6.17) (2026-02-26) + +### Bug Fixes + +- **cube:** Issue with calculated measures in pre-aggragations ([#10429](https://github.com/cube-js/cube/issues/10429)) ([58bfe5e](https://github.com/cube-js/cube/commit/58bfe5e567e5999aba2e75e32a662fbba652bd02)) +- **cubestore:** Don't print all tables in error message ([#10442](https://github.com/cube-js/cube/issues/10442)) ([cbf40df](https://github.com/cube-js/cube/commit/cbf40dfe113cf9a836708cd3e9e7a219d982a459)) +- **docs:** Use VERCEL_GIT_PREVIOUS_SHA for deployment checks ([7be6536](https://github.com/cube-js/cube/commit/7be65365e07cabbe745094ba4db6ac25d7b274cf)) +- **schema-compiler:** Allow no-cache queries to use pre-aggregations ([#10440](https://github.com/cube-js/cube/issues/10440)) ([22286f5](https://github.com/cube-js/cube/commit/22286f50beeddadc93bcfba0b7055b114d06a824)) + +## [1.6.16](https://github.com/cube-js/cube/compare/v1.6.15...v1.6.16) (2026-02-25) + +### Bug Fixes + +- **api-gateway:** Return a clear error when SQL interface is not initialized ([#10419](https://github.com/cube-js/cube/issues/10419)) ([53e9d9e](https://github.com/cube-js/cube/commit/53e9d9e4543eda79499f004bf379b66137660b9a)) +- Cache must-revalidate fail on pre-aggregation hit ([#10432](https://github.com/cube-js/cube/issues/10432)) ([4a29a5e](https://github.com/cube-js/cube/commit/4a29a5e8e669f0ce5d9f36fdb9fb39c26fb04b1b)) +- **tesseract:** Issue with custom granularities for pre-aggregations ([#10424](https://github.com/cube-js/cube/issues/10424)) ([e79d10a](https://github.com/cube-js/cube/commit/e79d10a9569297798e44a61a31311fdf5ebd7cbb)) +- **tesseract:** Segment support in pre-aggregations ([#10422](https://github.com/cube-js/cube/issues/10422)) ([1756cdb](https://github.com/cube-js/cube/commit/1756cdbace8429cd0558353686eaf9b2a29cd13c)) + +### Features + +- **cubejs-client:** Add lastRefreshTime to CubeSqlResult and CubeSqlStreamChunk types; enhance CubeApi to parse and return lastRefreshTime from responses ([#10425](https://github.com/cube-js/cube/issues/10425)) ([45d1278](https://github.com/cube-js/cube/commit/45d12783d80fda143ce770a95e6477f4eab3cf0a)) +- **cubesql:** Improve Talend compatibility ([#10430](https://github.com/cube-js/cube/issues/10430)) ([e4f39e5](https://github.com/cube-js/cube/commit/e4f39e5cc016b5c0a15a5ca74fdac197bd0d4290)) +- **databricks-driver:** Don't use temporarly tables for export bucket ([#10431](https://github.com/cube-js/cube/issues/10431)) ([5ec48ce](https://github.com/cube-js/cube/commit/5ec48ce81398cad13ef20d6358b775645fac0a70)) +- GraphQL - exponse annotation/lastRefreshTime in extensions ([#10428](https://github.com/cube-js/cube/issues/10428)) ([fb45030](https://github.com/cube-js/cube/commit/fb4503017c3949439d153fc46bae8d442bb8899d)) + +### Reverts + +- Revert "feat(databricks-jdbc-driver): Support export bucket in read-only mode (#10420)" ([4c0f49a](https://github.com/cube-js/cube/commit/4c0f49a0b941ce72d7016bcf74b97a565f51dd45)), closes [#10420](https://github.com/cube-js/cube/issues/10420) + +## [1.6.15](https://github.com/cube-js/cube/compare/v1.6.14...v1.6.15) (2026-02-23) + +### Bug Fixes + +- **mssql-driver:** Correct conversion for Date objects, thanks [@karlsvan](https://github.com/karlsvan) ([#10406](https://github.com/cube-js/cube/issues/10406)) ([4380628](https://github.com/cube-js/cube/commit/4380628a3bd1291c5f53d78932ca0d8ee4c5aaef)) +- **mssql-driver:** Use UTC timestamps in responses ([#10411](https://github.com/cube-js/cube/issues/10411)) ([4cb9f78](https://github.com/cube-js/cube/commit/4cb9f782e0ec40f055f80d48c6049b9dcc500dc6)), closes [#9488](https://github.com/cube-js/cube/issues/9488) +- **tesseract:** Incorrect matching of calculated measures in pre-aggregations ([#10417](https://github.com/cube-js/cube/issues/10417)) ([8959b0d](https://github.com/cube-js/cube/commit/8959b0d9df6a8423ad75950f5611d2a4dfed781f)) + +### Features + +- **databricks-jdbc-driver:** Support export bucket in read-only mode ([#10420](https://github.com/cube-js/cube/issues/10420)) ([a9b6480](https://github.com/cube-js/cube/commit/a9b648073d8fe4f0266713953ac199508585bda3)) + +## [1.6.14](https://github.com/cube-js/cube/compare/v1.6.13...v1.6.14) (2026-02-18) + +### Bug Fixes + +- **cubesql:** Support date-only `TO_TIMESTAMP` formats ([#10409](https://github.com/cube-js/cube/issues/10409)) ([1ca4624](https://github.com/cube-js/cube/commit/1ca46240e7a200d0cd5d664065c15287a7252a62)) +- **cubestore:** bug with nulls in Decimal96 ([#10408](https://github.com/cube-js/cube/issues/10408)) ([048dd5f](https://github.com/cube-js/cube/commit/048dd5f53072d289820fd4b63e2309d778eecb38)) + +### Features + +- **cubesql:** Support SQL pushdown for `LAG`/`LEAD` functions ([#10407](https://github.com/cube-js/cube/issues/10407)) ([c968656](https://github.com/cube-js/cube/commit/c968656970a90e640548e6b0165e5f1327cf150a)) + +## [1.6.13](https://github.com/cube-js/cube/compare/v1.6.12...v1.6.13) (2026-02-17) + +### Bug Fixes + +- **docs:** pin next-mdx-remote to 4.2.1 to address CVE-2026-0969 ([#10397](https://github.com/cube-js/cube/issues/10397)) ([ed5d4df](https://github.com/cube-js/cube/commit/ed5d4df27c17f75492f3c7006aa71d66b29b3eed)) + +### Features + +- **schema-compiler:** Pass jinjaUsed flag to native transpileYaml ([#10402](https://github.com/cube-js/cube/issues/10402)) ([884811a](https://github.com/cube-js/cube/commit/884811a85ff940834722876b1570fa861f387ed5)) +- **schema-compiler:** Yaml - duplicate check for view/cube names ([#10400](https://github.com/cube-js/cube/issues/10400)) ([11a140f](https://github.com/cube-js/cube/commit/11a140f4183b8a44a8800549da22b588ecd5ac02)) +- **schema-compiler:** Yaml - validate duplicates ([#10399](https://github.com/cube-js/cube/issues/10399)) ([d711612](https://github.com/cube-js/cube/commit/d71161210cb24b4b0039c343a3f67d8fe4197f3a)) + +### Performance Improvements + +- **schema-compiler:** Remove JSON.stringify in cache key hashing ([#10404](https://github.com/cube-js/cube/issues/10404)) ([6aae245](https://github.com/cube-js/cube/commit/6aae245585fc8a654a264e34eaf7a47f860d1533)) + +## [1.6.12](https://github.com/cube-js/cube/compare/v1.6.11...v1.6.12) (2026-02-16) + +### Bug Fixes + +- **postgres-driver:** Don't expose PoolConfig as driver options ([#10393](https://github.com/cube-js/cube/issues/10393)) ([4f2e72f](https://github.com/cube-js/cube/commit/4f2e72fe17979013a50da06c8be5a69685c079ad)) +- **tesseract:** Allow paths for symbols in request ([#10392](https://github.com/cube-js/cube/issues/10392)) ([9dea1fc](https://github.com/cube-js/cube/commit/9dea1fc6735e7be86e76fcfd5fbc62d769257799)) + +### Features + +- **postgres-driver:** Migrate to our Pool implementation ([#10389](https://github.com/cube-js/cube/issues/10389)) ([a57cabe](https://github.com/cube-js/cube/commit/a57cabed6bab72a34c738cb9b0d6e65c9a72ec60)) +- **redshift-driver:** Support IAM auth ([#10391](https://github.com/cube-js/cube/issues/10391)) ([c711ca7](https://github.com/cube-js/cube/commit/c711ca7c3b781fd975b9b9e5325865b9d27710a4)) + +## [1.6.11](https://github.com/cube-js/cube/compare/v1.6.10...v1.6.11) (2026-02-12) + +### Bug Fixes + +- **bigquery-driver:** Pass precision and scale to decimal type, thanks [@lvauvillier](https://github.com/lvauvillier) ([#10368](https://github.com/cube-js/cube/issues/10368)) ([159f528](https://github.com/cube-js/cube/commit/159f5282e0d05647289e0f43138816ef8567ca0d)) +- **cubestore-driver:** Wrap ECONNRESET errors with ConnectionError ([#10388](https://github.com/cube-js/cube/issues/10388)) ([e952942](https://github.com/cube-js/cube/commit/e952942deeb0cbfb5239343179ce2740c2862ff2)) + +### Features + +- **cubejs-api-gateway:** Adds dataSource to the /v1/sql API response, thanks [@seshness](https://github.com/seshness) ([#10350](https://github.com/cube-js/cube/issues/10350)) ([6bfe75e](https://github.com/cube-js/cube/commit/6bfe75e106f8004fb2467e5e6d3caefa25cc7820)) +- **cubesql:** Support setting time zone with `SET TIMEZONE` ([#10364](https://github.com/cube-js/cube/issues/10364)) ([5bb1e7d](https://github.com/cube-js/cube/commit/5bb1e7d45c94cadd221a5b19c29f818c3d654e57)) + +## [1.6.10](https://github.com/cube-js/cube/compare/v1.6.9...v1.6.10) (2026-02-09) + +### Bug Fixes + +- **docker:** Set UTF-8 locale environment variables to fix Python UnicodeEncodeError ([#10378](https://github.com/cube-js/cube/issues/10378)) ([104ff5f](https://github.com/cube-js/cube/commit/104ff5f732c80fe54945c959736db5493b4d2575)) + +### Features + +- **cubesql:** Support forwards directions for FETCH statement ([#10377](https://github.com/cube-js/cube/issues/10377)) ([7cbafd5](https://github.com/cube-js/cube/commit/7cbafd541a88c1d244e67aa980c208ca7c0ea68a)) +- Unify pool to make named timeout errors ([#10375](https://github.com/cube-js/cube/issues/10375)) ([bac3cd0](https://github.com/cube-js/cube/commit/bac3cd0f2f3f572fac037686ffa16a2e687fbcdc)) + +## [1.6.9](https://github.com/cube-js/cube/compare/v1.6.8...v1.6.9) (2026-02-06) + +### Bug Fixes + +- Negative residual in version generation leads to endless loop during pre-aggregation refresh ([#10367](https://github.com/cube-js/cube/issues/10367)) ([d53ae5f](https://github.com/cube-js/cube/commit/d53ae5f3a2299d86ab221970d5909c146a5badac)) + +### Features + +- **cubestore-driver:** improve WebSocket connection error messages ([#10355](https://github.com/cube-js/cube/issues/10355)) ([76b7873](https://github.com/cube-js/cube/commit/76b78738955f4419ce35aeb9f6cd4b73305e79dc)) + +## [1.6.8](https://github.com/cube-js/cube/compare/v1.6.7...v1.6.8) (2026-02-04) + +### Bug Fixes + +- **cubesql:** Fix planning with `CASE` and `LIKE` ([#10346](https://github.com/cube-js/cube/issues/10346)) ([285185f](https://github.com/cube-js/cube/commit/285185f63380fc4a279fd2100f6e7a98beadadc3)) + +### Features + +- **schema-compiler:** Add join_path support in folder includes ([#10349](https://github.com/cube-js/cube/issues/10349)) ([f80ab56](https://github.com/cube-js/cube/commit/f80ab56cdc345e5d430a59f65e702f433516912d)) + +## [1.6.7](https://github.com/cube-js/cube/compare/v1.6.6...v1.6.7) (2026-01-29) + +### Bug Fixes + +- **mssql-driver:** Respect timezone for origin in custom granularities ([#10111](https://github.com/cube-js/cube/issues/10111)) ([eaa484a](https://github.com/cube-js/cube/commit/eaa484ae1f7ca3601d202fff03b44782c61b37cb)) +- **mssql-driver:** Support MS SQL dialect for Tesseract ([#10343](https://github.com/cube-js/cube/issues/10343)) ([0ec696f](https://github.com/cube-js/cube/commit/0ec696fdc726d5305a2c63a48b7b4f0be16eda83)) +- **mssql-driver:** Use parameter placeholders for Tesseract ([#10342](https://github.com/cube-js/cube/issues/10342)) ([24ed91f](https://github.com/cube-js/cube/commit/24ed91fbf807dc22aaba45795f2e630d74b9b5f4)) + +### Features + +- **backend-native:** Add JSON format logging for production environment ([#10338](https://github.com/cube-js/cube/issues/10338)) ([1bc88f9](https://github.com/cube-js/cube/commit/1bc88f9e2be8fbf1fe8099f58e66df25987b5549)) +- **cubestore:** backward compatibility of decimal ([#10344](https://github.com/cube-js/cube/issues/10344)) ([4ca813c](https://github.com/cube-js/cube/commit/4ca813c1131d37604f7b69fbb8e9890bd2d0cea2)) +- **server-core:** Add level field for log messages ([#10337](https://github.com/cube-js/cube/issues/10337)) ([1e7dcb6](https://github.com/cube-js/cube/commit/1e7dcb614dd6537b3bb2a1f9bd04e96c2374a673)) +- **server-core:** Exponential backoff in refresh scheduler ([#10302](https://github.com/cube-js/cube/issues/10302)) ([fe714bf](https://github.com/cube-js/cube/commit/fe714bf333dec59a3988d626fdd709062a163b4f)) + ## [1.6.6](https://github.com/cube-js/cube/compare/v1.6.5...v1.6.6) (2026-01-23) ### Bug Fixes diff --git a/CLAUDE.md b/CLAUDE.md index 9a4f718d7bd33..db985ff947ba3 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -50,13 +50,24 @@ yarn test ``` ### Documentation Development -The documentation is in `/docs` directory: + +**IMPORTANT: `/docs-mintlify` is the active documentation site. `/docs` is the legacy +docs site and is deprecated — do NOT add or edit content there.** When asked to write or +update documentation, work in `/docs-mintlify` unless the user explicitly says otherwise. + ```bash -cd docs -yarn dev # Start development server -yarn build # Build for production +cd docs-mintlify +yarn dev # Start the Mintlify dev server ``` +- Content is authored as `.mdx` under topic directories (e.g. `admin/ai/`, `docs/explore-analyze/`). +- Frontmatter uses `title` and `description` keys. +- Navigation is registered in `docs-mintlify/docs.json` (pages must be added to the + relevant `group` to appear in the sidebar). +- Use Mintlify components: ``, ``, ``, ``, ``/``, + ``/``. Internal links are root-relative (e.g. `/admin/ai/rules`). +- See `docs-mintlify/CLAUDE.md` for full conventions. + ## Architecture Overview ### Monorepo Structure @@ -66,7 +77,8 @@ yarn build # Build for production - Database drivers: `cubejs-postgres-driver`, `cubejs-bigquery-driver`, etc. - API layer: `cubejs-api-gateway` - **`/rust`**: Rust components including CubeSQL (SQL interface) and CubeStore (distributed storage) -- **`/docs`**: Next.js documentation site +- **`/docs-mintlify`**: Mintlify documentation site — **the active docs site** (author docs here) +- **`/docs`**: Legacy Next.js/Nextra documentation site — **deprecated**, do not edit - **`/examples`**: Example implementations and recipes ### Key Components @@ -75,6 +87,7 @@ yarn build # Build for production 3. **API Gateway**: Provides REST, GraphQL, and SQL APIs 4. **CubeSQL**: Postgres-compatible SQL interface (Rust) 5. **CubeStore**: Distributed OLAP storage engine (Rust) +6. **Tesseract**: Native SQL planner (Rust) located in `/rust/cube/cubesqlplanner` - enabled via `CUBESQL_SQL_PUSH_DOWN=true` environment variable ### Package Management - Uses Yarn workspaces with Lerna for package management @@ -111,6 +124,16 @@ yarn test 3. **Testing**: Run relevant tests for modified packages 4. **Linting**: Ensure code passes `yarn lint` before committing +## Git + +Use conventional commits with these prefixes: +- `feat:` — new features +- `fix:` — bug fixes +- `docs:` — documentation changes +- `refactor:` — code refactoring + +Include scope in parentheses when applicable, e.g., `fix(tesseract):` or `feat(databricks-jdbc-driver):`. + ## Common File Patterns - `*.test.ts/js`: Jest unit tests @@ -122,7 +145,8 @@ yarn test ## Important Notes -- This is documentation for the old Cube docs site structure (the existing `/docs/CLAUDE.md` refers to the documentation site) +- Documentation lives in `/docs-mintlify` (active, Mintlify). `/docs` is the legacy docs + site and is deprecated — do not add or edit content there. See `docs-mintlify/CLAUDE.md`. - The main Cube application development happens in `/packages` - For data model changes, focus on `cubejs-schema-compiler` package - For query execution changes, focus on `cubejs-query-orchestrator` package diff --git a/CODEOWNERS b/CODEOWNERS index d4b73a3fe7aa6..1b92f9b0a39aa 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -25,7 +25,8 @@ /packages/*-schema-extension/ @cube-js/schema-compiler # Doc reviewers -/docs/ @cube-js/doc-reviewers +/docs/ @cube-js/doc-reviewers +/docs-mintlify/ @keydunov # Developer Relations and Community /examples/ @cube-js/developer-relations-and-community diff --git a/README.md b/README.md index 2ac59b7cd4a4e..736b2222f5e70 100644 --- a/README.md +++ b/README.md @@ -10,9 +10,9 @@ [![GitHub Actions](https://github.com/cube-js/cube/workflows/Build/badge.svg)](https://github.com/cube-js/cube/actions?query=workflow%3ABuild+branch%3Amaster) [![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fcube-js%2Fcube.js.svg?type=shield)](https://app.fossa.io/projects/git%2Bgithub.com%2Fcube-js%2Fcube.js?ref=badge_shield) -__Cube Core is an open-source semantic layer.__ Cube Core can be used to build embedded analytics in your applications, create your own business intelligence tool or provide context about data to AI agents. Cube Core is headless and comes with multiple APIs for embedded analytics and BI: REST, GraphQL, and SQL. +__Cube Core is the open-source semantic layer.__ Define metrics, dimensions, joins, and access rules once in code, then expose them through SQL, REST, and GraphQL APIs to anything downstream — BI tools, custom applications, or AI agents. Cube Core is headless: it doesn't ship a UI, so you can build the analytics experience that fits your product. -If you are looking for a fully integrated platform, check out [Cube](https://cube.dev), a modern AI-first business intelligence platform. We use Cube Core to power it. +Cube Core works with all SQL data sources, including cloud data warehouses like Snowflake, Databricks, and BigQuery; query engines like Presto and Amazon Athena; and application databases like Postgres. It has a built-in relational caching engine to provide sub-second latency and high concurrency for API requests.

- Learn more about connecting Cube to data sources and analytics & visualization tools. + Learn more about connecting Cube to data sources and analytics & visualization tools.

-Cube Core was designed to work with all SQL data sources, including cloud data warehouses like Snowflake, Databricks, and BigQuery; query engines like Presto and Amazon Athena; and application databases like Postgres. Cube Core has a built-in relational caching engine to provide sub-second latency and high concurrency for API requests. - ## Why Cube Core? -Every business intelligence tool relies on a semantic layer as its core engine—a critical component that defines metrics, dimensions, and business logic while abstracting the complexity of underlying data sources. However, most semantic layers are proprietary, tightly coupled to specific BI platforms, and cannot be reused across different applications. +Every BI tool relies on a semantic layer as its core engine — the component that defines metrics, dimensions, and business logic and hides the complexity of the underlying data sources. Most semantic layers are proprietary, tightly coupled to a single BI platform, and can't be reused across other tools. -Cube Core is an open-source project that aims to create an open, modern semantic layer that can be used to power any analytics applications and AI agents. By decoupling the semantic layer from specific tools and making it accessible through standard APIs, Cube Core enables organizations to define their metrics once and use them everywhere—from BI tools to embedded analytics to AI agents. +Cube Core is an open, standalone semantic layer that any analytics application or AI agent can consume through standard APIs. Define your metrics once and use them everywhere — internal BI, embedded analytics, AI agents — without re-implementing the model in each place. -## Getting Started 🚀 +## Getting Started -You can get started with Cube locally or self-host it with [Docker](https://www.docker.com/). +You can run Cube Core locally or self-host it with [Docker](https://www.docker.com/). -Once Docker is installed, in a new folder for your project, run the following command: +Once Docker is installed, in a new folder for your project, run: ```bash docker run -p 4000:4000 \ @@ -46,22 +44,35 @@ docker run -p 4000:4000 \ cubejs/cube ``` -Then, open http://localhost:4000 in your browser to continue setup. +Then open http://localhost:4000 in your browser to continue setup. + +For a step-by-step guide, [see the docs](https://cube.dev/cube-core/getting-started/create-a-project?ref=github-readme). + +## Cube Core vs. Cube + +[Cube](https://cube.dev?ref=github-readme) is our commercial product — an agentic analytics platform built on Cube Core. Same semantic layer underneath, plus the rest of what makes it a full BI platform: Analytics Chat, workbooks and dashboards, embedded analytics surfaces, managed deployment, RBAC, multi-tenancy, and integrations with Tableau, Power BI, Excel, and Google Sheets. + +The data model is fully compatible both ways: a model you build in Cube Core runs unchanged in Cube, and vice versa. Cube Core stays open-source and is what we run inside Cube ourselves. + +- **Use Cube Core** when you want to own the stack — a custom BI experience, deeply integrated embedded analytics, or AI agents that need a governed semantic foundation. +- **Use Cube** when you want a managed, full-featured BI platform out of the box — internal analytics or customer-facing embedded analytics without building the surrounding platform yourself. -For a step-by-step guide, [see the docs](https://cube.dev/docs/getting-started-docker?ref=github-readme). +For more on how we think about the split, see [The Future of Cube Core and Cube](https://cube.dev/blog/cube-core-and-cube). -### Cube — Complete Modern BI Tool from Cube Core Creators +For a tour of what's in Cube today, watch the workshop: -[Cube](https://cube.dev?ref=github-readme) is a complete modern agentic analytics platform built on Cube Core. It provides a fully integrated solution with a user-friendly interface, advanced analytics capabilities, and managed infrastructure. + + Cube agentic analytics workshop on YouTube + -Get started now +Or [try Cube for free](https://cubecloud.dev/auth/signup?ref=github-readme). ## Resources - [Documentation](https://cube.dev/docs?ref=github-readme) -- [Getting Started](https://cube.dev/docs/getting-started?ref=github-readme) -- [Examples & Tutorials](https://cube.dev/docs/examples?ref=github-readme) -- [Architecture](https://cube.dev/docs/product/introduction#four-layers-of-semantic-layer) +- [Getting Started](https://cube.dev/cube-core/getting-started?ref=github-readme) +- [Examples & Tutorials](https://cube.dev/recipes?ref=github-readme) +- [Architecture](https://cube.dev/docs/introduction) ## Contributing diff --git a/docs-mintlify/CLAUDE.md b/docs-mintlify/CLAUDE.md new file mode 100644 index 0000000000000..f32dade7c0fce --- /dev/null +++ b/docs-mintlify/CLAUDE.md @@ -0,0 +1,314 @@ +# Cube Documentation (Mintlify) + +This is the **active** Cube documentation site, built with [Mintlify](https://mintlify.com). +All documentation work should happen here. + +> The `/docs` directory at the repo root is the **legacy** Nextra docs site and is +> **deprecated** — do not add or edit content there. + +## Local development + +```bash +cd docs-mintlify +yarn dev # Start the Mintlify dev server +``` + +## Naming conventions + +Product naming conventions (product names, taxonomy, deployment types, plan +tiers, API names) are defined below — follow them in all docs content. + +### Product Naming Conventions + +- **Cube Core** — our open-source product +- **Cube** — our commercial product (default name in most contexts) +- **Cube cloud platform** — use only when you need to explicitly differentiate the commercial product from Cube Core +- **Cube Cloud** — legacy naming, do not use in new content + +### Deployment Type Naming + +- **Development** — development deployment type (legacy: "Development instance") +- **Production** — production deployment type (legacy: "Production cluster") +- **Multi-cluster** — multi-cluster production deployment type (legacy: "Production multi-cluster") + +### Plan Tier Naming + +Cube's commercial plan tiers, in order: **Free**, **Starter**, **Premium**, +**Enterprise**. **Enterprise is the top tier — nothing is above it.** + +When describing plan availability: + +- ✅ "Available on the [Enterprise plan]" (single tier, top of stack) +- ✅ "Available on [Premium and above plans]" (Premium + Enterprise) +- ✅ "Available on [Starter and above plans]" (Starter + Premium + Enterprise) +- ❌ Do **not** write "Enterprise and above plans" — there is nothing above + Enterprise. Use "Enterprise plan" (singular) instead. +- For Enterprise-only features that require an additional purchase, use + "Available as an add-on on the [Enterprise plan]". +- For features that depend on another add-on, name the dependency: + "Available on the [Enterprise plan] with the [Single-tenant infrastructure] + add-on." + +#### Plan availability callouts + +Use Mintlify's `` (gray) component — **not** `` (blue) — for +plan-availability messages. `` is the catch-all blue callout used +heavily throughout the docs for general "by the way" notes; using a different +color for plan gating makes it visually distinct and scannable. + +```mdx + + +Available on the [Enterprise plan](https://cube.dev/pricing). + + +``` + +Place the callout immediately after the section heading it applies to. + +### Infrastructure Naming + +Infrastructure options are a separate, orthogonal concept from deployment types. +A deployment of any type runs on top of one of these infrastructure options: + +- **Multi-tenant infrastructure** — deployments share compute and network with + other customers. Legacy: "Shared infrastructure". +- **Single-tenant infrastructure** — deployments run in a dedicated VPC inside + a Cube Cloud account; not shared with any other customer. Legacy: "Dedicated + infrastructure". +- **Single-tenant infrastructure with CSPS** — same as single-tenant, but + data at-rest is stored in a customer-supplied object store. Legacy: + "Dedicated infrastructure with CSPS". +- **BYOC (Bring Your Own Cloud)** — Cube Cloud data plane is fully hosted in + the customer's cloud account. + +Guidance: + +- Always use **single-tenant** / **multi-tenant** in customer-facing prose, + headings, navigation labels, and card titles. These terms are an industry + standard and remove the naming collision with the **Shared** and **Dedicated** + deployment types. +- Do **not** rename URL anchors (`#shared-infrastructure`, + `#dedicated-infrastructure`, `#dedicated-infrastructure-with-csps`) or + internal link reference IDs (e.g., `[ref-dedicated-infra]`); keep these + stable so external inbound links keep working. Use Mintlify's explicit + anchor syntax (`## Single-tenant infrastructure {#dedicated-infrastructure}`) + to preserve them. +- Do **not** rename product/region identifier slugs that contain `shared`, + `dedicated`, or `byoc` (e.g., `aws-us-east-1-shared`, `aws-us-east-1-t-12345-prod`). + These are literal strings used by the product. +- Avoid bare adjectives like "dedicated infrastructure" when you mean a + Dedicated **deployment type** running on its own compute. Prefer phrases + like "compute dedicated to your deployment" to avoid implying single-tenant + infrastructure. + +### Product Taxonomy + +Make sure to use correct terms. On billing, pricing, and support pages, use **on-demand customers** for the on-demand payment plan (legacy billing copy: "self-serve customers") and **contract customers** for the commit payment plan (legacy: "order form customers"). Elsewhere, **self-serve** (e.g. self-serve analytics) describes end-user exploration, not the billing segment. + +- **Account** + - **Deployment** + - **Agent** (one per deployment by default; multi-agent is also supported) + - Rules + - Certified queries + - **Evals** + - Questions (the benchmark set) + - Eval run (one execution of the agent against the question set) + - **Analytics Chat** + - **Workbook** + - Tab + - Dashboard builder + - **Widget** + - Charts + - Text + - Controls + - Filter widget + - Time grain switcher + - AI summary + - **Dashboard** + - Scheduled refresh + - **Semantic Model** + - Semantic Model IDE (short: "IDE") + - Semantic Model Agent + - **Explore** + - Explorations + - **API** + - Embed APIs + - Core Data APIs + - SQL API + - DAX API + - REST (JSON) API (transitional name; previously "REST API", will eventually become "JSON API") + - GraphQL API + - Management APIs + - Orchestration API + - **Embedding** + - Iframe embedding (the integration approach where Cube content is embedded via iframes) + - What you can embed: + - Dashboards + - Analytics Chat + - Creator Mode + - Authentication: + - Private embedding (auth mode for internal users with Cube accounts) + - Signed embedding (auth mode for external/customer-facing applications; required for Creator Mode) + - SDK embedding (the integration approach using the React Embed SDK) + - Headless embedding (the integration approach using Cube APIs directly — Embed APIs and Core Data APIs) + +### Embedding Terminology + +When categorizing embedding approaches, use these three parallel terms: + +- **Iframe embedding** — drop-in via iframes; Cube ships the full UI +- **SDK embedding** — via the React Embed SDK; Cube ships components, you compose +- **Headless embedding** — via Embed APIs and Core Data APIs; you build the UI + +Notes: +- Do not use `-based` suffixes (e.g., "iframe-based embedding", "API-based embedding"). Prefer the bare terms above. +- Use **Iframe** (capitalized at sentence start, lowercase mid-sentence). Do not use "iFrame". +- "API-based embedding" is ambiguous because **API** has specific product meaning (Embed APIs, Core Data APIs, Management APIs, Orchestration API). Use **Headless embedding** instead. + +#### Iframe embedding axes + +Iframe embedding has two independent axes: + +- **What you embed** (primary axis): Dashboards, Analytics Chat, Creator Mode +- **Authentication** (secondary, cross-cutting axis): Private embedding, Signed embedding + +Compatibility matrix: + +| | Private embedding | Signed embedding | +|------------------|:-----------------:|:----------------:| +| Dashboards | ✓ | ✓ | +| Analytics Chat | ✓ | ✓ | +| Creator Mode | — | ✓ | + +Page naming inside the **Iframe embedding** group: + +- Do not prefix page titles with "Embed" or "Embedding" — it is redundant under the group label. + - Use **Dashboards**, **Analytics Chat**, **Creator Mode** (not "Embed a dashboard", "Embed Analytics Chat", etc.) + - Use **Private embedding**, **Signed embedding** for the auth-mode pages (the word "embedding" is part of the product term itself). + +### Core Data API Naming + +The Core Data APIs are: **SQL API**, **DAX API**, **REST (JSON) API**, and **GraphQL API**. + +#### REST (JSON) API + +We are transitioning the name of our HTTP/JSON-based Core Data API: + +- Previous name: **REST API** +- Current (transitional) name: **REST (JSON) API** — use this in all new and updated content +- Future name: **JSON API** + +Guidance for the transitional period: + +- In prose, link references, headings, navigation labels, and card titles, use **REST (JSON) API** in place of **REST API**. +- Do not change URL paths, route segments, file/directory names, code identifiers, env vars, or config option names (e.g., `/reference/core-data-apis/rest-api`, `rest-api/index.mdx`, the `rest` query format value, internal link slugs like `[ref-rest-api]`). +- Do not rewrite third-party UI literals where "REST API" is a verbatim label in another product (e.g., Retool's `"REST API"` resource type, Budibase's `"REST API"` data source). Quote them as the third-party tool spells them. +- Plural form ("REST APIs") is not currently used and should be avoided; refer to the API in the singular. + +### Agent Terminology + +Every [Deployment](#product-taxonomy) ships with **one agent** by default. The agent powers AI features (Analytics Chat, ad-hoc queries, etc.) and is configured per-deployment with rules, certified queries, and other customizations. Multi-agent (multiple agents per deployment) is also supported, but the documentation primarily covers the default single-agent setup; multi-agent docs will follow. + +#### Naming + +- **the agent** — default term in single-agent contexts. No qualifier needed because every deployment has exactly one by default. Example: "configure rules for the agent", "add a certified query to the agent". +- **Cube agent** — use only when referring to the agent feature in the abstract (product-level), not a specific instance. Example: "Cube agent supports certified queries." +- **Avoid "default agent"** — it implies non-default agents exist. Reserve this term for multi-agent docs where it contrasts with custom-created agents. +- **Avoid "deployment agent"** — wordy and doesn't add useful contrast in multi-agent contexts. + +#### In multi-agent contexts + +- Refer to specific agents by their user-given names. +- Use **default agent** to contrast against user-created agents within a deployment. +- Continue to use **Cube agent** for product-level / abstract references. + +### Evals Terminology + +Benchmarking the agent's answers against a known-correct ground truth. + +- **Evals** — the feature, the model IDE tab, and the runs sub-tab. Use this + everywhere the feature or its UI is named. +- **eval run** — a single execution of the agent against the question set. + Action label: **Run eval**; column label: **Eval run**. +- **Question** — a natural-language question plus its ground truth; lives under + the **Questions** sub-tab. +- **Avoid "Evaluate" / "Evaluation" / "Evaluations"** — legacy UI labels, + replaced by **Evals**. (Generic verb uses like "evaluate the expression" are + unrelated and fine.) + +## Writing style + +- **Tone**: professional, direct, instructive. Address the reader as "you" (second person). +- **Headings**: one H1 is provided by the frontmatter `title` — start body sections at H2 (`##`). +- **Code**: always specify a language fence (` ```yaml`, ` ```markdown`, ` ```text`). Use + inline backticks for identifiers (`accessible_views`, `agents/rules/`). +- **Paragraphs**: keep them short; use `-` bullet lists for multiple items. + +## File and frontmatter conventions + +- Content is `.mdx`, organized by topic directory (e.g. `admin/ai/`, `docs/explore-analyze/`). +- The file path maps to the URL: `admin/ai/rules.mdx` → `/admin/ai/rules`. +- Every page starts with YAML frontmatter using `title` and `description`: + + ```mdx + --- + title: Rules + description: One-sentence summary used for SEO and navigation previews. + --- + ``` + +- **Do not** add an H1 in the body — the `title` is the page heading. + +## Navigation + +Navigation is defined in `docs-mintlify/docs.json`. A new page only appears in the sidebar +once its path (without the `.mdx` extension) is added to the appropriate `group` in +`docs.json`. After adding a page, update `docs.json` and verify it is still valid JSON. + +## Components + +Mintlify provides these components (used throughout the docs): + +- Callouts: ``, ``, ``, ``, `` +- `` with nested `` for sequential instructions +- `` with nested `` +- `` / ``, `` / ``, `` for images + +Content inside callouts and steps is plain MDX. Internal links are root-relative +(`/admin/ai/skills`), not file paths. + +## Preview features + +Every page documenting a feature that is in **preview** must open with a `` +callout — placed right after the frontmatter, before the body — saying the feature is +in preview and that the user should reach out to the Cube support team to activate it +for their account: + +```mdx + + + is currently in preview, and the user experience and file format may +still change. Reach out to the [Cube support team](/admin/account-billing/support) +to activate this feature for your account. + + +``` + +Adapt the "may still change" sentence per feature; the "in preview" + "reach out to +the Cube support team to activate it for your account" parts are required. Do not +expose internal feature-flag names in public docs. + +## Images and screenshots + +Wrap screenshots in `` and store assets under `images/`. When a screenshot is +needed but not yet available, leave an MDX comment placeholder: `{/* TODO: screenshot — ... */}`. + +## AI / agent docs structure + +The agent configuration (code-first, developer-facing) lives under `admin/ai/`: +`rules.mdx`, `certified-queries.mdx`, `skills.mdx`, `memory-isolation.mdx`, +`multi-agent.mdx`, `bring-your-own-model.mdx`. The end-user chat experience +(explorer/viewer-facing) lives under `docs/explore-analyze/` (e.g. `analytics-chat.mdx`, +`skills.mdx`). Keep authoring docs in `admin/ai/` and usage docs in `docs/explore-analyze/`, +and cross-link the two. diff --git a/docs-mintlify/admin/account-billing/ai-tokens.mdx b/docs-mintlify/admin/account-billing/ai-tokens.mdx new file mode 100644 index 0000000000000..3dd3f0e8ed179 --- /dev/null +++ b/docs-mintlify/admin/account-billing/ai-tokens.mdx @@ -0,0 +1,122 @@ +--- +title: AI Tokens +sidebarTitle: AI Tokens +description: Understand how AI token usage works in Cube, including per-seat grants, token packages, and usage tracking. +--- + +AI features in Cube use a token-based system to measure and manage consumption. + +## Overview + +Cube's [AI-powered features][ref-ai-overview] consume tokens based on the +resources required to complete each request. Token allocation differs by +customer type: + +- **On-demand customers** receive [per-seat token grants](#per-seat-token-grants) + equal to half of their seat price, with optional + [on-demand consumption](#on-demand-consumption) beyond that +- **Contract customers** can purchase [pooled token packages](#token-packages) + +## Token consumption + +Token usage depends on several factors: + +- **Task complexity** — More complex questions, multi-step analysis, or larger + datasets consume more tokens than simple lookups. Each message in a session + carries prior context, so longer sessions compound usage. +- **Data model context** — Cube sends context from your data model to the LLM + to improve answer accuracy. Larger models with more fields and descriptions + use more tokens per request. +- **AI model** — More capable models consume more tokens per request than + lighter models. + +Not all AI features consume tokens. The list of features that consume tokens +is subject to change as the product evolves. + + +## Per-seat token grants + +On-demand customers on paid plans receive **per-seat token grants** equal to +**half of the seat price**. Each user is awarded an individual monthly token +allocation based on their role. + +Per-seat grants: + +- Are assigned to the individual user +- Reset each billing cycle +- Cannot be transferred, shared, or rolled over + +### On-demand consumption + +When a user on an on-demand plan exceeds their monthly per-seat grant, usage +automatically continues as **on-demand consumption**. On-demand usage is billed +through the credit card on file. + +Administrators can set a **monthly on-demand spending limit** to control +additional costs. This limit caps the total on-demand spend across the account +for each billing cycle. + +## Token packages + +Contract customers can purchase **pooled add-on token packages**. Token +packages are added to a shared pool accessible by all users in the account. + +- Each package is valid for the duration of the contract or until fully + consumed, whichever comes first +- Multiple active packages can be combined +- Packages do not auto-renew + +Contact your account executive for details on purchasing token packages. + +## Free tier + +Each user on a free plan receives an individual monthly token allowance. This +allowance resets at the start of each calendar month. + +## Tracking usage + +Administrators can monitor token consumption through the **AI Tokens Usage** +tab in the billing settings page. The dashboard shows: + +- Total token usage over time +- Remaining allocation from per-seat grants and token packages +- Breakdown by usage dimension + +## When limits are reached + +When a user exhausts all available token sources (per-seat grant and token +packages), AI requests will return an error indicating the token limit has been +exceeded. + +- **Administrators** are directed to the billing page to purchase additional + token packages +- **Non-admin users** are prompted to contact their account administrator to + increase token quotas + +## FAQ + +### Do tokens roll over? + +- **Per-seat grants** reset each billing cycle and do not roll over +- **Token packages** remain active for the duration of the contract + +### Can I bring my own AI model? + +Yes. When using a [Bring Your Own Model (BYOM)][ref-byom] configuration, AI +requests bypass the token quota system entirely — no tokens are consumed or +tracked for those requests. You are billed directly by your model provider. + +### Why does a single prompt sometimes use more tokens than expected? + +Cube's AI features use an agentic architecture. A single prompt may trigger +multiple internal steps — such as searching the data model, building a query, +and summarizing results — each of which consumes tokens independently. + +### Why does the same question use different amounts of tokens? + +Token usage can vary between identical prompts due to differences in +conversation context (earlier messages in the session) or the AI choosing a +different reasoning path. + +[ref-ai-overview]: /admin/ai/index +[ref-byom]: /admin/ai/bring-your-own-model diff --git a/docs-mintlify/admin/account-billing/api-keys.mdx b/docs-mintlify/admin/account-billing/api-keys.mdx new file mode 100644 index 0000000000000..9cb3c181b213c --- /dev/null +++ b/docs-mintlify/admin/account-billing/api-keys.mdx @@ -0,0 +1,49 @@ +--- +title: API keys +description: Admins can manage API keys through Admin → API Keys. +--- + +Create and revoke API keys for your Cube organization. + + + + +## Deployment scope + +By default, an API key is **not scoped** to any deployment—it can be used with +every deployment in your organization (the **All deployments** option). When +creating or editing a key, you can instead scope it to one or more **specific +deployments**. + +The scope determines which requests a key can authorize: + +- **Deployment-scoped endpoints**—such as generating an embed session for a + deployment—require the key to be scoped either to that deployment or to all + deployments. A request targeting a deployment outside the key's scope is + rejected. +- **Endpoints that aren't tied to a specific deployment** continue to work with + any key, regardless of its scope. + +Each key's scope—**All** or the specific deployments it's limited to—is shown in +the API keys table. + + + +Scoping is optional and backward compatible. Existing keys remain unscoped (**All +deployments**) until you change them. + + diff --git a/docs-mintlify/admin/account-billing/billing-faq.mdx b/docs-mintlify/admin/account-billing/billing-faq.mdx new file mode 100644 index 0000000000000..a87fed4de4ea7 --- /dev/null +++ b/docs-mintlify/admin/account-billing/billing-faq.mdx @@ -0,0 +1,75 @@ +--- +title: Billing FAQ +sidebarTitle: Billing FAQ +description: Frequently asked questions about Cube billing, pricing, payments, and invoices. +--- + +## Billing basics + +### How does the billing structure work? + +#### On-demand customers + +On-demand customers are billed monthly. The credit card on file is automatically +charged through Stripe upon invoice generation. + +- Invoices bill active seats in advance for the upcoming period +- Any seat count changes made during a previously billed period are charged in + arrears on a prorated basis on the next invoice, as well as billed in advance + on all subsequent invoices until the customer makes further adjustments + +#### Contract customers + +**Contract customers** are billed annually and upfront according to the terms +in their contract. + +- Committed seats are billed annually +- Overages for uncommitted seats and usage are billed in arrears separately on a + basis specified in the contract +- Standard payment terms are **Net 30**, unless otherwise specified in the agreement + +### What payment methods does Cube accept? + +#### On-demand customers + +On-demand subscriptions must be paid by credit card via Stripe. Your card is +automatically charged on a recurring subscription basis at the start of each +billing cycle. + + +Cube does **not** support ACH or wire transfer payments for on-demand payment plans. + + +#### Contract customers + +Contract customers can pay via: + +- **Invoice billing** (e.g., Net 30 terms) — Payment terms are defined in your + contract and reflected on your invoice. +- **ACH / wire transfer** — Bank details (Stripe-managed virtual accounts) are + listed directly on the invoice. Please reach out to + [support@cube.dev](mailto:support@cube.dev) if you require validation. +- **Credit card** (via Stripe) — Contract customers may also pay by credit card. + +### How can I update my payment information? + +To update your payment information, log in to your Cube account and navigate to +the billing settings page. + +If you need assistance confirming or updating your account email, please reach +out to [support@cube.dev](mailto:support@cube.dev). + +### What happens if my credit card payment fails? + +If your credit card payment fails: + +1. **We automatically retry the charge** — Stripe will automatically retry the + payment using the card on file. Sometimes failures are temporary (e.g., + insufficient funds, bank block, expired card). +2. **You may receive an email notification** — If the payment continues to fail, + you'll receive an email prompting you to update your payment method. +3. **Update your card** — You can update your card through the billing settings + page. Once updated, the system will automatically retry the charge. +4. **Continued failed payments** — If payment isn't resolved after multiple + attempts, your account may be restricted or suspended until the outstanding + balance is paid. diff --git a/docs-mintlify/admin/account-billing/budgets.mdx b/docs-mintlify/admin/account-billing/budgets.mdx new file mode 100644 index 0000000000000..5a34fe391569c --- /dev/null +++ b/docs-mintlify/admin/account-billing/budgets.mdx @@ -0,0 +1,81 @@ +--- +title: Budgets +description: Learn how usage thresholds trigger budget notifications and where to manage them in Cube Cloud billing. +--- + +As an account administrator, you can define rules which trigger notifications +when your account's usage exceeds a certain threshold. These rules are called +"budgets". + + + +Available on [Premium and above plans](https://cube.dev/pricing). + + + + + +## How budgets work + +Budgets are configured on a per-account basis. When a budget is triggered, any configured users +will receive an email notification. Budget notifications are sent immediately after being triggered. + +## List all budgets + +To see a list of all configured budgets in your account, first go to the Billing settings page by +clicking on your avatar in the top right corner, then clicking on **Billing**. + +On the Billing settings page, click the **Budgets** tab to see all configured budgets in your +account: + + + + + +## Create a budget + +To create a new budget, click the **Add Budget** button. Enter a name for the budget, +then select a time period (either 'Daily' or 'Monthly') and a corresponding target amount, which +is the amount of usage that will trigger a notification. + + + + + +### Threshold Rules + +You can also configure threshold rules, which allow you to trigger notifications when usage +exceeds a certain percentage of the target amount. For example, if you set a target amount of +\$1,000 and a threshold of 80%, you will also receive a notification when your usage exceeds \$800. + + + + + + + +A good rule-of-thumb for accounts that pay annually is to set a monthly budget of 1/12 (~8.3%) for your first budget. + + + +If you have multiple thresholds defined, some thresholds __may not be triggered__ if a higher threshold +is triggered first. For example, if you have a target amount of \$1,000 and thresholds of 80% and 90%, +and your usage hits 95%, you will only receive a notification when your usage exceeds \$900. + +### Managing Notifications + +When creating a new budget, by default, all users will receive email notifications. + + + + + +You can also specify particular users who should receive alerts by +toggling the **Specific users** option and selecting them. Optionally, +you can also add additional email addresses that should receive +email notifications by entering the email address in the **Custom email** field. diff --git a/docs-mintlify/admin/account-billing/distribution.mdx b/docs-mintlify/admin/account-billing/distribution.mdx new file mode 100644 index 0000000000000..9120951c2b663 --- /dev/null +++ b/docs-mintlify/admin/account-billing/distribution.mdx @@ -0,0 +1,127 @@ +--- +title: Distribution +description: Compares Cube Core versus Cube Cloud packaging, release artifacts, versioning, and long-term support policy. +--- + +This page explains the difference between [Cube Core and Cube Cloud](#cube-core-and-cube-cloud), +provides links to ready-to-use [artifacts](#artifacts), and explains the +[versioning model](#versions) and the release cycle, including the [long-term +support](#long-term-support) (LTS). + +## Cube Core and Cube Cloud + +_Cube Core_ is the universal semantic layer, developed by [Cube Dev][link-company] +and the community in open source under a permissive [Apache License 2.0][link-license]. +You can find its [source code][link-repo] on GitHub. + +_Cube Cloud_ is the managed platform for Cube Core, developed by Cube Dev as a +[commercial product][link-pricing]. It includes everything from Cube Core and +provides additional semantic layer features, [managed infrastructure][ref-infrastructure] +and [workspace tools][ref-workspace]. + +_Cube_ can be used to refer to both products if the distinction is not important +in a particular case. + + + +All Cube Cloud-specific features are marked with similar green boxes throughout +this documentation. + + + +You are welcome to either [sign up for Cube Cloud][link-sign-up] and start using it +for free. You can also [self-host][ref-deployment] a Cube Core deployment. + +## Artifacts + +Cube Core is packaged and distributed as Docker images that you can run in a +containerized environment. You can find images for [Cube][link-dockerhub-cube] +and [Cube Store][link-dockerhub-cubestore] on Docker Hub. + +Note that Cube Store images support the `linux/amd64` architecture while Cube +images support both `linux/amd64` and `linux/arm64`. The latter is convenient for +Mac computers with [Apple silicon][link-apple-silicon] that you might use to run +Cube locally. + +Notably, the following tags are used with Docker images: +- `v1.1.0` and similar, one tag per each released version. +- `latest`, always pointing to the latest release. +- `dev`, always pointing to the bleeding-edge image built for the latest commit. + +## Versions + +Cube is actively developed, and new versions are released frequently. + +Versions mostly follow [SemVer][link-semver] principles, with the only exception +that breaking changes can happen both in _major_ and _minor_ versions. Before +upgrading, it is recommended that you check the [release notes][link-releases] +on GitHub and read [changelog entries][link-changelog] in the blog. + + + +You can find a list of currently [deprecated features][link-github-deprecation] on GitHub. +Usually, there are also deprecation notices in the documentation that look similar to this one. + + + +Additionally, Cube Cloud provides **LTS** or **Regular** [update +channels][ref-update-channels]. + +### Long-term support + +To provide guarantees for the long-term support of Cube Core, some minor releases +are designated as _long-term support (LTS) releases_. + + + +Check the [long-term support announcement][link-lts-accouncement] in the blog. + + + +For 12 months after being marked as LTS, these releases receive fixes for defects +that significantly impact stability and functionality as well as the security +fixes for critical vulnerabilities. It is recommended to use the latest patch +version within an LTS release. + +List of LTS releases: + +| Version | Status | End-of-life date | +| --- | --- | --- | +| `v1.4.x` | Active | October 29, 2026 | +| `v1.0.x` | End-of-life | October 29, 2025 | + +### Documentation + +The documentation at [cube.dev/docs](https://cube.dev/docs) always reflects the +latest released version. + +To obtain the documentation for a specific version: +* Clone the [GitHub repository](https://github.com/cube-js/cube) at the desired tag. +* Navigate to the `docs` folder and start a local documentation server. +* Open [localhost:3000](http://localhost:3000) in your browser. + +```sh +git clone --depth 1 --branch v1.5.0 https://github.com/cube-js/cube.git +cd cube/docs +yarn && yarn dev +open http://localhost:3000 +``` + + +[link-repo]: https://github.com/cube-js/cube +[link-license]: https://github.com/cube-js/cube/blob/master/LICENSE +[link-releases]: https://github.com/cube-js/cube/releases +[link-company]: https://cube.dev/about +[link-pricing]: https://cube.dev/pricing +[link-sign-up]: https://cubecloud.dev/auth/signup +[link-changelog]: https://cube.dev/blog/category/changelog +[link-lts-accouncement]: https://cube.dev/blog/introducing-long-term-support-lts-for-cube-core +[link-dockerhub-cube]: https://hub.docker.com/r/cubejs/cube/tags +[link-dockerhub-cubestore]: https://hub.docker.com/r/cubejs/cubestore/tags +[link-apple-silicon]: https://support.apple.com/en-us/116943 +[link-semver]: https://semver.org +[link-github-deprecation]: https://github.com/cube-js/cube/blob/master/DEPRECATION.md +[ref-infrastructure]: /admin/deployment/infrastructure +[ref-workspace]: /admin/workspace +[ref-deployment]: /admin/deployment +[ref-update-channels]: /admin/deployment/index#update-channels \ No newline at end of file diff --git a/docs-mintlify/admin/account-billing/pricing.mdx b/docs-mintlify/admin/account-billing/pricing.mdx new file mode 100644 index 0000000000000..61cc54e6959bc --- /dev/null +++ b/docs-mintlify/admin/account-billing/pricing.mdx @@ -0,0 +1,335 @@ +--- +title: Pricing in Cube Cloud +description: Explains Cube Consumption Units, product tiers, and how Cube Cloud bills for infrastructure and features. +--- + +Cube Cloud pricing is based on resource consumption which we measure +using [Cube Consumption Units](#cube-consumption-unit) in 5 minute intervals. +Each [product tier](#product-tiers) has different features and functionality +that you should review as you think about what is right for your business. + +## Cube Consumption Unit + +_Cube Consumption Unit_ (CCU) is a way to measure resource consumption +used to run Cube Cloud infrastructure and [resources](#resources) within it. + +The price of a CCU is determined by the [product tier](#product-tiers) you're subscribed to. +Each product tier determines the features, scalability, availability, as well as +the [speed and scope of support][ref-support] you may receive for your deployment. + +You can also set [Budgets][ref-cloud-budgets] to make sure you know your usage +is on track and as expected. + +[ref-cloud-budgets]: /admin/account-billing/budgets +## Payment plans + +Payment plans determine whether you have a fixed-term contract or a recurring +subscription: + +* _On-demand payment plan_ allows you to subscribe at any time, add your credit +card, and start using Cube Cloud right away. [Starter](#starter) and [Premium](#premium) +product tiers are available on the on-demand payment plan. +* _Commit payment plan_ allows you to have a contract with a CCU amount specified +in that contract. [Premium](#premium) and [Enterprise](#enterprise) product tiers are available on the +commit payment plan. [Contact us][link-contact-us] to learn more. + +## Product tiers + +### Free + +**Free product tier is designed for development and testing purposes.** It is not +intended for production use. + +It offers up to two [Shared deployments][ref-cloud-deployment-dev-instance]. + +You can review its [support terms][ref-free-tier-support] and [limits][ref-cloud-limits]. + +### Starter + +**Starter product tier targets low-scale production that is not business-critical.** + +It offers a [Dedicated deployment][ref-cloud-deployment-prod-cluster], the ability +to use third-party packages from the npm registry, AWS and GCP support in select +regions, pre-aggregations of up to 150GB in size, auto-suspend controls, and +[Semantic Layer Sync][ref-sls] with a single BI tool (such as Preset or Metabase). + +You can review its [pricing][cube-pricing], [support +terms][ref-starter-tier-support], and [limits][ref-cloud-limits]. + +### Premium + +**Premium product tier is designed for basic small-scale production deployments.** + +It offers everything in the [Starter product tier](#starter) as well as enabling +the use of [Multi-cluster deployments][ref-cloud-deployment-prod-multicluster], +support for [custom domains][ref-cloud-custom-domains], AWS and GCP support +in all regions. Cube Cloud provides a 99.95% uptime SLA for this product tier. + +You can review its [pricing][cube-pricing], [support +terms][ref-premium-tier-support], and [limits][ref-cloud-limits]. + +### Enterprise + +**Enterprise product tier is suitable for high-scale or mission-critical production +deployments with more significant security and compliance needs.** + +It offers everything in the [Premium product tier](#premium) as well as [Semantic Layer +Sync][ref-sls] with unlimited supported BI tools, SAML +support for [single sign-on][ref-sso], Azure support for all regions, [dedicated +infrastructure][ref-dedicated-infra], [VPC peering][ref-cloud-vpc-peering], +[monitoring integrations][ref-monitoring-integrations], and [role-based access +control][ref-cloud-acl]. Cube Cloud provides a 99.99% uptime SLA for this product tier. + +You can review its [pricing][cube-pricing], [support +terms][ref-enterprise-tier-support], and [limits][ref-cloud-limits]. + +## Resources + +The following resource types incur CCU consumption and apply to _individual resources_ +of deployments within a Cube Cloud account. The consumption is measured in 5-minute intervals. + +| Resource type | CCUs per hour | Notes | +| --- | :---: | --- | +| [Dedicated deployment][ref-production-cluster] | 4..8 | Depends on a [chosen tier](#deployment-tiers) | +| [Shared deployment][ref-development-instance] | 1..2 | Depends on a [chosen tier](#deployment-tiers) | +| Cube API Instance | 1..2 | Depends on a [chosen tier](#deployment-tiers) | +| Cube Store Worker | 1..2 | Depends on a [chosen tier](#cube-store-worker-tiers) | +| [Query History][ref-query-history] | 0..20 | Depends on a [chosen tier](#query-history-tiers) | +| [Monitoring Integrations][ref-monitoring-integrations] | — | Available as an [add-on](#monitoring-integrations) on the Enterprise plan | + +The following resource types incur CCU consumption and apply to the _whole Cube Cloud +account_: + +| Resource type | CCUs per hour | Notes | +| --- | :---: | --- | +| [Single-tenant infrastructure][ref-dedicated-infra] | 3 | — | +| [Audit Log][ref-audit-log] | 4..6 | Depends on the [chosen tier](#audit-log-tiers) | + +The following resource types incur cost and apply to the _whole Cube Cloud account_: + +| Resource type | Cost per month | Notes | +| --- | :---: | --- | +| [AI tokens](#ai-tokens) | Varies | Depends on the number of tokens used | + +### Deployment tiers + +[Dedicated deployments][ref-production-cluster] (including individual API instances) +and [Shared deployments][ref-development-instance] are involved in serving +requests through [APIs & integrations][ref-apis] under the following tiers: + +| Tier | CCUs per hour | CPU and memory | Dependent features | +| ---- | :--- | --- | --- | +| S | 4 — _for Dedicated deployment_
1 — _for Shared deployment_
1 — _for Cube API Instance_ | 100% | — | +| M | 8 — _for Dedicated deployment_
2 — _for Shared deployment_
2 — _for Cube API Instance_ | 200% | [DAX API][ref-dax-api]| + +You can upgrade to a chosen tier in the +**Settings** of your deployment. +Upgrading to the M tier is only available on the [Enterprise][cube-pricing] product tier. + +### Cube Store Worker tiers + +[Cube Store workers][ref-cube-store-architecture] are involved in building +pre-aggregations and executing queries against them under the following tiers: + +| Tier | CCUs per hour | Throughput | Dependent features | +| ---- | :-----------: | ---------- | ------------------ | +| S | 1 | 100% | — | +| M | 2 | 200% | [Data-at-rest encryption][ref-data-at-rest-encryption] with [customer-managed keys][ref-customer-managed-keys] in Cube Store | + +You can upgrade to a chosen tier in the +**Settings** of your deployment. + +### Query History tiers + +[Query History][ref-query-history] and [Performance Insights][ref-performance-insights] +features analyze and visualize the data available under the following tiers: + +| Tier | CCUs per hour | API requests | Data retention | +| ---- | :-----------: | ------------------- | -------------- | +| XS | 0 | Up to 50,000/day | 1 day | +| S | 2 | Up to 100,000/day | 7 days | +| M | 5 | Up to 250,000/day | 14 days | +| L | 10 | Up to 500,000/day | 21 days | +| XL | 20 | Up to 1,000,000/day | 30 days | + +You can upgrade to a chosen tier in the +**Settings** of your deployment. + +### Monitoring Integrations + +[Monitoring Integrations][ref-monitoring-integrations], including [Query History +export][ref-query-history-export], are available as an add-on on the Enterprise +plan. [Contact us][cube-contact-us] for pricing. + +### Audit Log tiers + +[Audit Log][ref-audit-log] collects, stores, and displays security-related events +under the following tiers: + +| Tier | CCUs per hour | Dependent features | +| ---- | :------------------------: | ------------------ | +| S | 4 | — | +| M | 6 | Audit Log data export | + +### AI tokens + +The price of AI tokens is passed through from the underlying AI service provider without +any markup. The cost depends on the number of tokens processed by your Cube Cloud account +when using AI features. + +You can control the const by setting the token limit on the **Billing** page of +your Cube Cloud account. When the limit is [reached](#token-limit-exceeded), you can +increase it to continue using AI features. + +## Total cost examples + +The following examples provide insight into the total cost to use Cube Cloud: +- [Small-scale deployment](#small-scale-deployment) (Dedicated deployment, Premium product tier, S deployment tier). +- [Medium-scale deployment](#medium-scale-deployment) (Dedicated deployment with auto-scaling, Enterprise product tier, S deployment tier). +- [Large-scale deployment](#large-scale-deployment) (Multi-cluster deployment with single-tenant infrastructure, Enterprise product tier, M deployment tier). + +### Small-scale deployment + +Suppose a company uses Cube Cloud to power self-serve business intelligence for +a couple of teams in Eastern and Pacific time zones. + +This organization: +* Uses the Premium product tier of Cube Cloud. +* Runs a single Dedicated deployment (S tier) that is active 24/7 but never has to auto-scale +its API instances because the usage is spread evenly with no bursts. +* Operates on a small volume of data that requires the usage of just 2 Cube Store +Workers to run queries and refresh pre-aggregations mostly during working hours, +being active approximately 50% of the time. +* Updates its data model infrequently and without using a dedicated Shared +deployment for testing purposes, with 2 data engineers spending just 1 hour a day each, +in the development mode of the Dedicated deployment. + +| Resource | Usage per month | CCU per month | +| ---------------------------------------------- | ------------------------------------------------------------ | --------------------------------------------------- | +| Dedicated deployment | 1 Dedicated deployment ×
24 hours per day ×
30 days | 720 hours ×
4 CCUs per hour =
**2880 CCUs** | +| Additional Cube API Instance | — | — | +| Cube Store Worker | 2 Cube Store Workers ×
12 hours per day ×
30 days | 720 hours ×
1 CCU per hour =
**720 CCUs** | +| Shared deployment | — | — | +| Shared deployment
(for development mode) | 2 users ×
1 hour per day ×
30 days | 60 hours ×
1 CCU per hour =
**60 CCUs** | +| **Total** | | **3660 CCUs** | + +### Medium-scale deployment + +Suppose a company with a globally distributed workforce uses Cube Cloud to enable self-serve +exploration in multiple BI tools and AI agents; it also uses Cube Cloud to power embedded +analytics in its SaaS platform that caters to a vast worldwide customer base. + +This organization: +* Uses the Enterprise product tier of Cube Cloud. +* Runs two Dedicated deployments (S tier) that are active 24/7 and auto-scale up to 8 API instances +during a peak hour every day. +* Operates on a moderate volume of data that requires the usage of 4 Cube Store +Workers by both Dedicated deployments to run queries and refresh pre-aggregations 24/7, +being active approximately 50% of the time. +* Uses a dedicated Shared deployment (S tier) for testing purposes that is active 12 hours a day. +* Has a team of 5 data engineers who frequently update the data model, with each data engineer +spending about 4 hours a day in the development mode of the dedicated Shared deployment. + +| Resource | Usage per month | CCU per month | +| ---------------------------------------------- | ---------------------------------------------------------------------------------------- | ---------------------------------------------------- | +| Dedicated deployment | 2 Dedicated deployments ×
24 hours per day ×
30 days | 1440 hours ×
4 CCUs per hour =
**5760 CCUs** | +| Additional Cube API Instance | 2 Dedicated deployments ×
(8 – 2) API Instances ×
1 hour per day ×
30 days | 360 hours ×
1 CCU per hour =
**360 CCUs** | +| Cube Store Worker | 2 Dedicated deployments ×
4 Cube Store Workers ×
12 hours per day ×
30 days | 2880 hours ×
1 CCU per hour =
**2880 CCUs** | +| Shared deployment | 1 Shared deployment ×
12 hours per day ×
30 days | 360 hours ×
1 CCU per hour =
**360 CCUs** | +| Shared deployment
(for development mode) | 5 users ×
4 hours per day ×
30 days | 600 hours ×
1 CCU per hour =
**600 CCUs** | +| **Total** | | **9960 CCUs** | + +### Large-scale deployment + +Suppose a company uses Cube Cloud as a mission-critical part of their infrastructure to enable +its globally distributed workforce, customer base, and (or) partners to operate at scale. + +This organization: +* Uses the Enterprise product tier of Cube Cloud. +* Uses [single-tenant infrastructure][ref-dedicated-infra]. +* Runs a Multi-cluster deployment that is active 24/7, includes 3 Dedicated deployments (M tier), with each +Dedicated deployment auto-scaling up to 10 API instances during a few peak hours every day. +* Operates on a large volume of data that requires the usage of 16 Cube Store Workers to run +queries and refresh pre-aggregations 24/7, being active approximately 50% of the time. +* Uses a dedicated Shared deployment (M tier) for testing purposes that is active 24 hours a day. +* Has a team of 10 data engineers who frequently update the data model, with each data engineer +spending about 4 hours a day in the development mode of the dedicated Shared deployment. +* Uses a [Query History tier](#query-history-tiers) with 14-day data retention to inform the work +of data engineers. + +| Resource | Usage per month | CCU per month | +| ---------------------------------------------- | ---------------------------------------------------------------------------------------------- | ----------------------------------------------------- | +| Single-tenant infrastructure | 1 region ×
24 hours per day ×
30 days | 720 hours ×
3 CCUs per hour =
**2160 CCUs** | +| Multi-cluster deployment | 3 Dedicated deployments ×
24 hours per day ×
30 days | 2160 hours ×
8 CCUs per hour =
**17280 CCUs** | +| Additional Cube API Instance | 3 Dedicated deployments ×
(10 – 2) API Instances ×
4 hours per day ×
30 days | 2880 hours ×
2 CCU per hour =
**5760 CCUs** | +| Cube Store Worker | 1 Multi-cluster deployment ×
16 Cube Store Workers ×
12 hours per day ×
30 days | 5760 hours ×
1 CCU per hour =
**5760 CCUs** | +| Shared deployment | 1 Shared deployment ×
24 hours per day ×
30 days | 720 hours ×
2 CCU per hour =
**1440 CCUs** | +| Shared deployment
(for development mode) | 10 users ×
4 hours per day ×
30 days | 1200 hours ×
2 CCU per hour =
**2400 CCUs** | +| Query History (M tier) | 24 hours per day ×
30 days | 720 hours ×
5 CCUs per hour =
**3600 CCUs** | +| **Total** | | **38400 CCUs** | + +## Payment terms + +### Upgrades + +You may upgrade your CCUs to a higher-level product tier at any time by +paying the difference in per-Cube Consumption Unit pricing, or by asking to convert +the price paid for the remaining CCUs into CCUs for the higher product tier +at the CCU pricing for that product tier (resulting in a lower number of available CCUs +but upgraded to the higher product tier). + +### Terms + +If payment is not received within the contract terms (usually Net-30) or for +additional required payment for CCUs exceeding the balance of CCUs in your +account, services may degrade or be suspended until new CCUs are purchased. + +Future purchases and upgrades are subject to the pricing that is in effect at +the time of the order. No credit is allowed for downgrading CCUs to a lower +product tier level. Payments are non-refundable. + +## Troubleshooting + +### `Token limit exceeded` + +[On-demand](#payment-plans) customers may encounter the following error when their AI +usage exceeds the limit set for their Cube Cloud account: `Token limit exceeded. Please +purchase or allocate more tokens.` + +To resolve this issue, a user with administrative permissions needs to increase the limit +for the AI token consumption at the **Billing** page of their Cube Cloud account. + + + + + +[cube-pricing]: https://cube.dev/pricing +[link-contact-us]: https://cube.dev/contact +[ref-cloud-deployment-dev-instance]: /admin/deployment/deployment-types#shared +[ref-cloud-deployment-prod-cluster]: /admin/deployment/deployment-types#dedicated +[ref-cloud-limits]: /admin/deployment/limits +[ref-monitoring-integrations]: /docs/monitoring/integrations +[ref-cloud-acl]: /admin/users-and-permissions/custom-roles +[ref-cloud-deployment-prod-multicluster]: /admin/deployment/deployment-types#multi-cluster +[ref-cloud-custom-domains]: /admin/deployment/custom-domains +[ref-cloud-vpc-peering]: /admin/deployment/dedicated +[ref-sls]: /docs/integrations/semantic-layer-sync +[ref-support]: /admin/account-billing/support +[ref-free-tier-support]: /admin/account-billing/support#free +[ref-starter-tier-support]: /admin/account-billing/support#starter +[ref-premium-tier-support]: /admin/account-billing/support#premium +[ref-enterprise-tier-support]: /admin/account-billing/support#enterprise +[ref-query-history]: /admin/monitoring/query-history +[ref-performance-insights]: /admin/monitoring/performance +[ref-audit-log]: /admin/monitoring/audit-log +[ref-dedicated-infra]: /admin/deployment/infrastructure#dedicated-infrastructure +[ref-sso]: /admin/sso +[ref-production-cluster]: /admin/deployment/deployment-types#dedicated +[ref-development-instance]: /admin/deployment/deployment-types#shared +[ref-apis]: /reference +[ref-mdx-api]: /reference/mdx-api +[ref-dax-api]: /reference/dax-api +[ref-cube-store-architecture]: /docs/pre-aggregations/running-in-production#architecture +[ref-data-at-rest-encryption]: /docs/pre-aggregations/running-in-production#data-at-rest-encryption +[ref-customer-managed-keys]: /admin/deployment/encryption-keys +[ref-query-history-export]: /admin/monitoring/monitoring-integrations#query-history-export \ No newline at end of file diff --git a/docs-mintlify/admin/account-billing/support.mdx b/docs-mintlify/admin/account-billing/support.mdx new file mode 100644 index 0000000000000..a81102fafb300 --- /dev/null +++ b/docs-mintlify/admin/account-billing/support.mdx @@ -0,0 +1,98 @@ +--- +title: Support in Cube Cloud +sidebarTitle: Support +description: Summarizes support channels, coverage hours, and ticket allowances across Cube Cloud product tiers. +--- + +Cube Cloud [product tiers][ref-cloud-pricing] include different levels of support +in terms of speed and scope that you should review as you think about what is +right for your business. + +## Support by product tiers + +### Free + +* [Free product tier][ref-free-tier] offers support via **online resources** such as +[documentation][ref-docs-intro], [webinars][cube-webinars], and [community +Slack][cube-slack]. + +### Starter + +* [Starter product tier][ref-starter-tier] includes support via **online resources** such as +[documentation][ref-docs-intro], [webinars][cube-webinars], and [community +Slack][cube-slack]. +* You can also connect with our support team during [support hours](#support-hours) +with **2 support tickets per month** through the in-product chat feature. + +### Premium + +* [Premium product tier][ref-premium-tier] includes support via **online resources** such as +[documentation][ref-docs-intro], [webinars][cube-webinars], and [community +Slack][cube-slack]. +* It also includes **either 4 support tickets per month** (on-demand customers) +or **unlimited support tickets** (contract customers) for our support engineers during +[support hours](#support-hours) through our in-product chat. + +| Priority | Response time during support hours | +| -------- | ---------------------------------- | +| P0 | 60 minutes | +| P1 | 4 hours | +| P2 | 8 business hours | +| P3 | 2 business days | + +### Enterprise + +* [Enterprise product tier][ref-enterprise-tier] includes support via **online resources** such as +[documentation][ref-docs-intro], [webinars][cube-webinars], and [community +Slack][cube-slack]. +* It also includes **unlimited support tickets** for our support engineers during +[support hours](#support-hours) through our in-product chat with faster +response times as compared to the [Premium product tier](#premium). + +| Priority | Response Time during Support Hours | +| -------- | ---------------------------------- | +| P0 | 30 minutes | +| P1 | 2 hours | +| P2 | 8 business hours | +| P3 | 2 business days | + +* Enterprise product tier also includes a **dedicated customer success manager** (CSM) +who will provide quarterly reviews, sharing new features and training as well +as usage and optimization advice. + + +## Support hours + +Official support hours are weekdays (Monday through Friday) from 8am ET to 8pm +ET. The above response times are only during support hours. + +## Support priority definitions + +We prioritize support requests based on their severity, as follows: + +- **P0**: The platform is severely impacted or completely shut down. We will + assign specialists to work continuously to fix the issue, provide ongoing + updates, and start working on a temporary workaround or fix. + +- **P1**: The platform is functioning with limited capabilities or facing + critical issues preventing a production deployment. We will assign specialists + to fix the issue, provide ongoing updates, and start working on a temporary + workaround or fix. + +- **P2**: There are issues with workaround solutions or non-critical functions. + We will use resources during local business hours until the issue is resolved + or a workaround is in place. + +- **P3**: There is a need for clarification in the documentation, or a + suggestion for product enhancement. We will triage the request, provide + clarification when possible, and may include a resolution in a future update. + + +[ref-docs-intro]: /docs/introduction +[cube-webinars]: https://cube.dev/events +[cube-slack]: https://slack.cube.dev +[ref-cloud-pricing]: /admin/account-billing/pricing +[ref-free-tier]: /admin/account-billing/pricing#free +[ref-starter-tier]: /admin/account-billing/pricing#starter +[ref-premium-tier]: /admin/account-billing/pricing#premium +[ref-enterprise-tier]: /admin/account-billing/pricing#enterprise \ No newline at end of file diff --git a/docs-mintlify/admin/ai/bring-your-own-model.mdx b/docs-mintlify/admin/ai/bring-your-own-model.mdx new file mode 100644 index 0000000000000..a4340a6acd634 --- /dev/null +++ b/docs-mintlify/admin/ai/bring-your-own-model.mdx @@ -0,0 +1,139 @@ +--- +title: Bring Your Own Model +sidebarTitle: Bring Your Own Model +description: Configure custom LLM providers for AI agents in Cube, including supported providers, setup, and billing implications. +--- + + + +Available on the [Enterprise plan](https://cube.dev/pricing). + + + +Bring Your Own Model (BYOM) lets you connect your own LLM provider to power +AI agents in Cube, instead of using the built-in models. This gives you full +control over which models your agents use, where your data is processed, and +how you manage AI costs. + +## Supported providers + +| Provider | Chat models | Embedding models | +| --- | --- | --- | +| **Anthropic** | Yes | No | +| **OpenAI** | Yes | Yes | +| **AWS Bedrock** | Yes | Yes | +| **GCP Vertex AI** | Yes | No | +| **Databricks** | Yes | No | +| **Snowflake Cortex** | Yes | No | + +## Configuration + +### Step 1: Add a model + +Before assigning a BYOM model to an agent, you need to register it in the +admin panel: + +1. Navigate to **Admin > Models** +2. Click **Add Model** +3. Provide a **name** for the model +4. Select the **model type** (LLM or Embedding) +5. Choose a **provider** and **model** +6. Enter the required credentials for the provider + +### Step 2: Assign the model to an agent + +Once a model is registered, reference it in the agents YAML configuration by +name or ID: + +```yaml +agents: + - name: sales-analyst + llm: + byom: + name: "my-anthropic-model" + embedding_llm: + byom: + name: "my-bedrock-embeddings" +``` + +Each agent can use a different model. If no BYOM model is specified, the agent +uses the built-in default. + + + +Switching embedding models for an agent means existing memories stored with +the previous embedding model will not be compatible. Memories are tied to the +embedding model that created them. + + + +## Network configuration + +When using BYOM, Cube connects to your model provider from its control plane. +If your provider requires IP allowlisting, ensure the Cube outbound IP +addresses are added to your allowlist. + +For agents running in dedicated regions, additional per-region IP addresses +may also need to be allowlisted. + +## Billing + +When using a BYOM model, **Cube AI tokens are not consumed**. You are billed +directly by your model provider based on their pricing. + +This means: + +- No Cube token quota is deducted for BYOM chat requests +- No token usage is tracked in the AI Tokens Usage dashboard for BYOM requests +- Per-seat token grants and token packages do not apply + +See [AI Tokens][ref-ai-tokens] for details on how token billing works with +built-in models. + +## Provider-specific notes + +### Anthropic + +Supports extended thinking mode for compatible models. Configure this in the +model settings when creating the model. + +### AWS Bedrock + +- Credentials are optional — if left empty, the default AWS credential chain + is used (e.g., workload identity) +- Supports assume-role configuration for cross-account access +- Supports inference profiles + +### GCP Vertex AI + +Requires a service account JSON key for authentication. + +### Databricks + +Requires a workspace URL and access token. + +### Snowflake Cortex + +Supports two authentication methods: + +- JWT authentication +- Key-pair authentication (requires an encrypted PKCS#8 PEM private key) + +## Troubleshooting + +### Rate limit errors + +If you see rate limit errors, the limits are enforced by your model provider, +not by Cube. Check your provider's rate limits and usage quotas. + +### Authentication errors + +Verify that the API key or credentials configured for the model are valid and +have the necessary permissions. + +### Model not found + +Ensure the model ID configured in Cube matches a valid model offered by your +provider. Model availability may vary by region. + +[ref-ai-tokens]: /admin/account-billing/ai-tokens diff --git a/docs-mintlify/admin/ai/certified-queries.mdx b/docs-mintlify/admin/ai/certified-queries.mdx new file mode 100644 index 0000000000000..dafa741748e8f --- /dev/null +++ b/docs-mintlify/admin/ai/certified-queries.mdx @@ -0,0 +1,85 @@ +--- +title: Certified queries +description: Provide a library of trusted SQL queries that the agent uses as reference examples when answering user requests. +--- + +Certified queries are pre-approved SQL queries that the agent treats as a **library of trusted examples**. They guide the agent toward correct business logic and well-formed query patterns without restricting it to a fixed set of queries. + +Certified queries are configured as code in your [data model repository](/admin/ai#agent-configuration), alongside your cubes and views. + + +The agent is not limited to running only certified queries. When answering a user request, the agent may: + +- Use a certified query directly if it matches the request +- Use a certified query as a **starting point** and adapt it (e.g., add filters, dimensions, or measures) to fit the user's question +- Generate a new query independently if no certified query is relevant + +Certified queries help the agent toward trusted patterns and correct business logic, but the agent retains full flexibility to construct the query that best answers each question. + + +## Defining certified queries + +Certified queries are defined as Markdown files under `agents/certified_queries/`. Each query lives in its own file: the YAML frontmatter holds metadata, and the Markdown body is the SQL query. + +```markdown + +--- +description: "Get revenue by fiscal quarter" +user_request: "What is the revenue by quarter?" +--- +SELECT + DATE_TRUNC('quarter', order_date) AS quarter, + SUM(amount) AS revenue +FROM orders +WHERE status != 'cancelled' +GROUP BY 1 +ORDER BY 1 +``` + +Files placed under a `certified_queries/`, `certified-queries/`, or `queries/` directory are treated as certified queries automatically — no `kind` property is required. The `name` is inferred from the file name (e.g., `quarterly-revenue.md` → `quarterly-revenue`). + +### Frontmatter properties + +| Property | Type | Required | Description | +|-----------------|--------|:--------:|--------------------------------------------------------------------------------------| +| `name` | string | No | Unique identifier. Inferred from the file name if omitted. | +| `description` | string | No | Human-readable description. | +| `user_request` | string | Yes | The user request pattern this query answers. | +| `sql_query` | string | No | The SQL query. Falls back to the Markdown body if omitted. | + +### Inlining certified queries in YAML + +You can also inline certified queries directly in `agents/config.yml` under a `certified_queries` key: + +```yaml +# agents/config.yml +certified_queries: + - name: total-revenue + description: "Calculate total revenue" + user_request: "What is the total revenue?" + sql_query: "SELECT SUM(amount) AS total_revenue FROM orders WHERE status = 'completed'" + + - name: monthly-sales + description: "Monthly sales breakdown" + user_request: "Show me sales by month" + sql_query: | + SELECT + DATE_TRUNC('month', order_date) AS month, + SUM(amount) AS total_sales + FROM orders + GROUP BY 1 + ORDER BY 1 +``` + +Inline certified queries accept the same properties as Markdown ones — `name`, `description`, `user_request` (required), and `sql_query` (required). + + +Certified queries inlined at the root of `agents/config.yml` are attached to the implicit `auto` space and applied to the default agent in a [single-agent setup](/admin/ai). In a [multi-agent setup](/admin/ai/multi-agent), attach certified queries to a specific space by inlining them under that space's `certified_queries` key (or by placing Markdown files under `agents/certified_queries//`). + + +## Writing effective certified queries + +- **Phrase `user_request` like a real user question.** This is what the agent matches against incoming requests. +- **Keep queries focused.** A certified query should answer one well-defined question; the agent will adapt it for variations. +- **Use canonical business logic.** Certified queries are the reference for "the right way" to compute something — encode the definitions you want the agent to follow. +- **Cover common patterns first.** Start with the questions users ask most often, and grow the library based on usage. diff --git a/docs-mintlify/admin/ai/evals.mdx b/docs-mintlify/admin/ai/evals.mdx new file mode 100644 index 0000000000000..58bb432fa4ea0 --- /dev/null +++ b/docs-mintlify/admin/ai/evals.mdx @@ -0,0 +1,146 @@ +--- +title: Evals +description: Benchmark your agent's answers against a known-correct ground truth and track accuracy across data-model and agent changes. +--- + +Evals let you benchmark your agent's answers against a known-correct ground +truth, on any branch. You author a set of questions, each with the SQL or +[certified query](/admin/ai/certified-queries) that represents the right +answer, run your agent against them, and get a per-question pass/fail plus an +accuracy score for the run — so you can see, objectively, whether a data-model +or agent change made the agent better or worse. + +You'll find evals in the model IDE under the **Evals** tab, with two +sub-tabs: **Evals** (runs) and **Questions** (the benchmark set). + + + Eval run results showing the question list with pass/fail icons and a selected question's detail with the agent's SQL next to the ground truth SQL + + +## Concepts + +| Term | What it is | +|------|------------| +| **Question** | A natural-language question plus its **ground truth** (the correct answer, as SQL or a certified-query reference). Authored as code in your data model. | +| **Eval (run)** | One execution of the agent against the whole question set, on a specific branch and agent. | +| **Result** | The agent's answer to a single question in a run, graded against that question's ground truth. | +| **Accuracy** | `passed / total` for a run, shown as `NN% (passed/total)`. | + +## Authoring benchmark questions + +Questions live in your [data model repository](/admin/ai#agent-configuration), +versioned and branched like the rest of it. You can keep them in a single +top-level `agents/eval_questions.yml` file — the simplest place to start — or +split them across any number of `agents/eval_questions/*.yml` files as your set +grows. The parser picks up both and merges every file's `eval_questions` list +into one set, so you can move from one file to many at any time without changing +anything else. + +Each file has a top-level `eval_questions` list. A question needs a unique +`name`, a `question`, and exactly one ground truth: a `certifiedQuery` +reference **or** inline `sql`. + +```yaml +# agents/eval_questions.yml +eval_questions: + - name: revenue_by_quarter + question: What was our revenue by quarter over the last two years? + certifiedQuery: revenue_by_quarter # reference an existing certified query by name + + - name: arr_last_4_years + question: What was our ARR over the last 4 years? + sql: | # ...or inline SQL ground truth + SELECT date_trunc('year', created_at) AS year, SUM(arr) AS arr + FROM subscriptions GROUP BY 1 ORDER BY 1 +``` + +- `certifiedQuery` references a [certified query](/admin/ai/certified-queries) + by name. Define it under `agents/certified_queries/` (or via **Certify this + query** in chat). A reference that doesn't resolve to an existing certified + query is flagged as a validation error. +- `sql` is inline ground-truth SQL, run through the same Cube SQL API the agent + uses (so `MEASURE(...)` and friends work). +- Omitting both — or setting both — is a validation error. +- An optional top-level `space` key scopes a file's questions to a named space + (defaults to `auto`). Question names are unique per space. + + + +The **Questions** tab is a read-only view of these files. To add or edit +questions, edit the YAML in the IDE — there's no in-product question editor +yet. + + + +## Running an eval + +On the **Evals** tab, click **Run eval** and choose: + +- **Branch** — which branch's data model and agent configuration to run + against. Defaults to the active branch. +- **Agent** — `auto` (the implicit auto-agent) or a configured agent name. + +The run starts immediately and you can close the dialog — it executes in the +background. The run list shows live progress and then the outcome: + +| Column | Meaning | +|--------|---------| +| **Eval run** | When the run was created. | +| **Environment** | Where it ran — **dev** (your personal dev-mode branch, shown as "*Name* Dev Mode"), **staging**, or **prod** (the deploy branch, e.g. `master` or `main`). | +| **Agent** | The agent used. | +| **Execution status** | Running, Completed, or Failed. | +| **Accuracy** | `NN% (passed/total)`. | +| **Created by** | Who triggered the run. | +| **Last updated** | When it finished. | + +## Reading the results + +Open a run to see per-question results: the question list on the left, with a +pass/fail icon for each, and the selected question's detail on the right. + +- **Assessment** — `pass`, `fail`, `review`, or `error`. +- **Score reason** — when a question doesn't pass, a tag categorizing why: + **Row count mismatch**, **Missing columns**, **Value mismatch**, + **Unexpected rows**, **Query error**, **Ground truth query failed**, + **Ground truth not found**, or **Agent error**. +- **Failure analysis** — a plain-English explanation, e.g. *"The agent + returned 3 rows, but the ground truth has 5 rows."* +- **Model output · SQL** vs. **Ground truth SQL answer** — the agent's query + side-by-side with the ground truth, so you can spot the difference. +- **Response** — the agent's full text answer, rendered as Markdown. + +## How grading works + +Grading is execution-based, not text-based — the same approach used by +industry text-to-SQL benchmarks such as BIRD and Spider 2.0. The agent's SQL +and the ground-truth SQL are both executed, and their result sets are +compared. So an answer that's worded or written differently but produces the +same data still passes. + +The comparison is: + +- **Sort-invariant** — row order never matters. +- **Numeric-tolerant** — values are compared to 4 significant figures, so + float/representation noise (`6646` vs. `6646.0`) doesn't fail. +- **Column-name-agnostic and lenient on extra columns** — each ground-truth + column must be reproduced by some agent column, matched by its values, so + `revenue` vs. `total` aliases don't matter. Extra columns the agent adds are + ignored. +- **No standalone row-count gate** — row count falls out of the comparison: a + "top 5" question is enforced because the golden result has exactly 5 rows. + +Verdicts: + +| Verdict | When | +|---------|------| +| **pass** | The agent's result set matches the ground truth. | +| **fail** | It ran but the result set doesn't match (see the score reason). | +| **review** | Nothing to compare automatically — the question has no ground truth, or the agent didn't run a query. Compare manually. | +| **error** | The agent run failed, the ground-truth query failed, or a referenced certified query wasn't found. | + +## Limitations + +- Questions are authored as code only; the **Questions** tab is read-only. +- Very large question sets can be slow to run. +- Grading is execution-based on the result set; it does not semantically judge + prose answers. diff --git a/docs-mintlify/admin/ai/index.mdx b/docs-mintlify/admin/ai/index.mdx new file mode 100644 index 0000000000000..039005b93b78a --- /dev/null +++ b/docs-mintlify/admin/ai/index.mdx @@ -0,0 +1,147 @@ +--- +description: Configure the agent that ships with every Cube deployment — accessible views, LLM, runtime, and memory. +title: Overview +--- + +Every Cube deployment ships with an agent that powers AI features such as [Analytics Chat](/docs/explore-analyze/analytics-chat). You can customize the agent's behavior with rules, certified queries, accessible views, model selection, and memory configuration. + + + Configuring the agent in the UI is **deprecated** in favor of code-first configuration. Cube version 1.6.5 or above is required. + + Deployments created after **April 30, 2026** have code-first agent configuration enabled by default. Existing deployments need to opt in by setting `CUBE_CLOUD_AGENTS_CONFIG_ENABLED=true`. The directory path defaults to `agents` and can be overridden with `CUBE_CLOUD_AGENTS_CONFIG_PATH`. + + +## Agent configuration + +Agent configuration lives in your **Cube data model repository**, alongside your cubes and views. Configuration is defined as YAML and Markdown files under an `agents/` directory in your project: + +```text +your-cube-project/ +├── model/ +│ └── cubes/ +│ └── orders.yml +├── agents/ +│ ├── config.yml # Agent configuration +│ ├── rules/ # Rules as Markdown +│ │ └── fiscal-year.md +│ └── certified_queries/ # Certified queries as Markdown +│ └── quarterly-revenue.md +└── cube.py +``` + +Storing configuration as code in your repository enables version control, code review, and consistent behavior across environments. + +## Configure the agent + +Place agent properties at the root of `agents/config.yml`: + +```yaml +# agents/config.yml +llm: claude_4_sonnet +runtime: plain +accessible_views: + - orders_view + - customers_view +memory_mode: user +``` + +### Properties + +| Property | Type | Default | Description | +|---------------------|------------------|--------------------------|-------------------------------------------------------------------------------------------------------------------------| +| `llm` | string or object | `auto` | LLM provider — `auto`, a [predefined model](#llm) name, or a [BYOM](/admin/ai/bring-your-own-model) reference. | +| `embedding_llm` | string or object | `text-embedding-3-large` | Embedding model — a predefined name or a BYOM reference. | +| `runtime` | string | `plain` | [Runtime mode](#runtime) — `plain` or `reasoning`. | +| `accessible_views` | array | _all views_ | List of view names exposed to the agent as context guidance for which views to query. This is not a security control — if omitted or empty, all views are exposed. Use [access policies](/reference/data-modeling/data-access-policies) to enforce actual access restrictions. | +| `memory_mode` | string | `space` | [Memory isolation mode](#memory) — `space`, `user`, or `disabled`. | + +Rules and certified queries have their own dedicated pages: + +- [Rules](/admin/ai/rules) — instructions that guide the agent's behavior +- [Certified queries](/admin/ai/certified-queries) — a library of trusted SQL examples for the agent +- [Skills](/admin/ai/skills) — reusable, named agent workflows users can run on demand from chat + +## LLM + +The default value is `auto` — Cube picks a recommended model on your behalf and may change it as better models become available. Use `auto` unless you have a reason to pin a specific model. + +To pin a specific model, set the `llm` property to one of the predefined models: + +**Anthropic Claude:** +- `claude_3_5_sonnetv2` +- `claude_3_7_sonnet` +- `claude_3_7_sonnet_thinking` +- `claude_4_sonnet` +- `claude_4_5_sonnet` +- `claude_4_5_haiku` +- `claude_4_5_opus` +- `claude_4_6_sonnet` +- `claude_4_6_opus` +- `claude_4_7_opus` + +**OpenAI GPT:** +- `gpt_4o` +- `gpt_4_1` +- `gpt_4_1_mini` +- `gpt_5` +- `gpt_5_mini` +- `gpt_5_3` +- `gpt_5_4` +- `o3` +- `o4_mini` + +To use your own model, see [Bring your own model](/admin/ai/bring-your-own-model). + +### Embedding models + +Predefined embedding models for the `embedding_llm` property: + +- `text-embedding-3-large` +- `text-embedding-3-small` + +BYOM is also supported for embedding models. + +## Runtime + +The `runtime` property controls how the agent processes requests: + +| Mode | Description | +|--------------|--------------------------------------------------------------------------------------------| +| `plain` | Default. Optimized for speed and cost. Recommended for most use cases. | +| `reasoning` | Enables extended thinking for complex analysis. | + + + `reasoning` is **experimental**. It may be unstable and is not yet feature-complete. Stick with `plain` unless you have a specific need for extended reasoning. + + +## Memory + +The `memory_mode` property controls how the agent persists context across conversations: + +| Mode | Description | +|-------------|----------------------------------------------------------------------------------------------| +| `space` | Default. Memories are shared across all users — useful when the agent serves a single team. | +| `user` | Memories are isolated per user — useful when each user has private context. | +| `disabled` | The agent does not persist memory between conversations. | + +See [Memories](/admin/ai/memory-isolation) for details on how memories are stored and used. + +## Customize the agent + + + + Define instructions that guide how the agent responds and analyzes data. + + + Provide a library of trusted SQL queries for the agent to reference. + + + Package reusable, named agent workflows that users can run on demand from chat. + + + Configure the agent to use your own LLM provider or model. + + + Control how the agent persists context across conversations and users. + + diff --git a/docs-mintlify/admin/ai/mcp-connectors.mdx b/docs-mintlify/admin/ai/mcp-connectors.mdx new file mode 100644 index 0000000000000..ed3417f19bcde --- /dev/null +++ b/docs-mintlify/admin/ai/mcp-connectors.mdx @@ -0,0 +1,134 @@ +--- +title: MCP Connectors +description: Connect external MCP servers so the agent can use their tools — search Notion, file Linear issues, query Sentry, and more — from chat. +--- + + + +MCP Connectors are available on [Premium and Enterprise plans](https://cube.dev/pricing). + + + +MCP Connectors let the [agent](/admin/ai) use tools from external services. An +administrator connects an external [MCP](https://modelcontextprotocol.io) server — such as +Notion, Linear, Sentry, or Attio — and its tools become available to the agent in +[Analytics Chat](/docs/explore-analyze/analytics-chat). The agent can then search a Notion +workspace, file a Linear issue, look up a Sentry error, or call any tool a connected server +exposes, alongside the data it queries from your semantic model. + + + +**MCP Connectors are the inverse of the [MCP server](/docs/integrations/mcp-server).** A +connector lets the **Cube agent reach out** to an external MCP server and call its tools. +The MCP server lets **external MCP clients reach in** to Cube and query your data. One is +outbound, the other inbound — you can use either or both. + + + +## Concepts + +- A **connector** is a connection to one external MCP server. Each connector is configured + and authenticated once, at the organization level, by an administrator. +- Each connector exposes one or more **tools** — the individual actions the agent can call + (for example, "search pages" or "create issue"). A single connector typically exposes + many tools. +- Connectors are managed in the admin panel under **MCP Connectors** and apply across the + organization, so every agent can use the tools you enable. + +## Adding a connector + +Open the admin panel and go to **MCP Connectors**. You can add a connector from the +built-in directory or connect a custom MCP server. + +{/* TODO: screenshot — MCP Connectors admin page with the directory and connectors list */} + +### From the directory + +The connector directory includes vetted, first-party integrations with streamlined setup. + + + + Select **Browse directory** and choose a service (for example, Notion, Linear, Sentry, + or Attio). + + + Complete the connector's authentication flow (see [Authentication](#authentication) + below). For OAuth-based connectors you'll be redirected to the provider to authorize + access. + + + Review the tools the connector exposes and choose which ones are available to the + agent. See [Choosing which tools are available](#choosing-which-tools-are-available). + + + +### Custom connector + +Any service that exposes a remote MCP endpoint can be connected as a custom connector. + + + + Select **Add custom connector** and provide a name and the server's HTTPS endpoint URL + (for example, `https://mcp.example.com/mcp`). + + + Choose the authentication method the server requires — OAuth or a user-provided + credential such as an API key or token. + + + Once connected, the server's tools are discovered automatically. Choose which ones the + agent may call. + + + +## Authentication + +Connectors authenticate to the external service in one of two ways, depending on what the +service supports: + +| Method | How it works | +|--------|--------------| +| **OAuth** | You authorize Cube with the provider through a standard OAuth flow. The connector stores the resulting tokens and refreshes them as needed. Used by most directory connectors. | +| **User-provided credential** | You supply a credential — such as an API key or access token — that the connector uses to authenticate. Used when a service does not offer OAuth. | + +A connector's status indicator in the connectors list shows whether it is connected and +authenticated. + +## Choosing which tools are available + +Each connected server reports the full set of tools it exposes (shown as a count, for +example `16 / 16`). You control which of those tools the agent is allowed to call. +Enabling only the tools you need keeps the agent focused and limits what it can do through +each connector. + +## How the agent uses connector tools + +Once a connector is configured and its tools are enabled, the agent can call them in +[Analytics Chat](/docs/explore-analyze/analytics-chat) as part of answering a request — the +same way it queries your semantic model. The agent decides when a tool is relevant based on +the user's request and the tool's description. If a tool requires the user to authenticate +to the external service, the agent prompts for authorization in chat before the tool runs. + +## Permissions + +Managing MCP Connectors requires administrator access in Cube Cloud — the same access +needed to manage other organization-level settings in the admin panel. Connectors apply +across the organization; using the tools they expose is available to anyone with chat +access, subject to the tools you enable. + +## Related + + + + Let external MCP clients connect to Cube and query your data over HTTPS. + + + Configure the agent that powers Cube's AI features. + + + Package reusable, named agent workflows users can run on demand from chat. + + + Ask questions of your data in natural language. + + diff --git a/docs-mintlify/admin/ai/memory-isolation.mdx b/docs-mintlify/admin/ai/memory-isolation.mdx new file mode 100644 index 0000000000000..1680fbe4a8ce3 --- /dev/null +++ b/docs-mintlify/admin/ai/memory-isolation.mdx @@ -0,0 +1,48 @@ +--- +title: Memories +description: How the agent stores, retrieves, and isolates memories across tenants, spaces, and users. +--- + +Memory in Cube allows Agents to learn from and recall past interactions, user preferences, and contextual information. When users interact with Agents, relevant information is stored as memories that can be retrieved in future conversations, enabling more personalized and context-aware responses. Memories help Agents understand user preferences, remember previous decisions, and provide continuity across sessions. + +Memories are scoped and enforced at the Tenant/Space boundary. Cube applies both application-layer and (optionally) infrastructure-layer isolation so one customer's end users cannot see another customer's memories. + +## How It Works + +### Space-Scoped Memories + +Cube memories are stored at the Space level. Agents only learn from and retrieve memories within the current Space, ensuring no cross-Space exposure by design. + +### Tenant-Aware Security Context + +Every request carries a tenant-bound security context (JWT). Cube maps that context to an app/tenant ID and uses it across caching, orchestration, and query flows. This is the backbone of multi-tenancy isolation. + +### RBAC and Policy Guardrails + +Role-based access policies gate what entities and content are visible within a tenant. These same guardrails apply to what agents can read and write as memories. + +### Data Model and API Isolation + +Even when using the SQL API or custom views, hidden members and non-public entities remain inaccessible. Multitenancy configuration ensures queries and artifacts resolve only within the current tenant's scope. + +### Optional Infrastructure Isolation + +Many customers run in multi-tenant regions, but single-tenant infrastructure and BYOC (Bring Your Own Cloud) variants are available. These provide stronger blast-radius isolation at the cluster, storage, and key-management levels. + +## Practical Implications + +- **Tenant Separation**: An end user in Customer A can only create and retrieve memories in Customer A's Spaces +- **Cross-Tenant Protection**: Memories are not retrievable by Customer B's users or agents, because requests from B carry a different security context and resolve to different Space and tenant IDs +- **Intra-Tenant Controls**: Even within a customer, RBAC and policies can further restrict which users or agents can contribute to or benefit from memories + +## Technical Implementation + +Cube ensures memory isolation through multiple layers of security controls: + +1. **Tenant Isolation**: Every request is scoped to a specific tenant via JWT and middleware +2. **User Isolation**: Additional user-level filtering for user-mode memories +3. **Automatic Filtering**: Database queries are automatically filtered by tenant using decorators +4. **Vector Store Security**: All vector searches include tenant and user filters +5. **Container Isolation**: Each tenant gets its own dependency injection container +6. **JWT Security**: All security context comes from cryptographically signed JWT tokens +7. **Memory Mode Controls**: Configurable memory isolation levels (user/space/disabled) diff --git a/docs-mintlify/admin/ai/multi-agent.mdx b/docs-mintlify/admin/ai/multi-agent.mdx new file mode 100644 index 0000000000000..8c2254e849eeb --- /dev/null +++ b/docs-mintlify/admin/ai/multi-agent.mdx @@ -0,0 +1,189 @@ +--- +title: Multi-agent +description: Configure multiple agents within a single deployment, each with its own model, accessible views, rules, and certified queries. +--- + +Every Cube deployment ships with a single agent by default — see the [Overview](/admin/ai) for the standard configuration. For more advanced setups, you can configure **multiple agents** within the same deployment, each with its own model, accessible views, rules, and certified queries. + +Multi-agent is useful when: + +- Different teams need agents tuned to their own domain (e.g., a Sales Assistant and a Marketing Analyst). +- You want specialized agents with distinct instructions or tool access in the same deployment. +- You need to isolate context (rules, certified queries, memories) between user groups. + + + Spaces and agents must first be created through the Cube Cloud UI before they can be configured via YAML. The system matches YAML entries to UI-created spaces and agents by their `name` field. + + +## Architecture + +A multi-agent setup introduces one new concept on top of the single-agent model: **spaces**. + +- A **deployment** can contain one or more **spaces**. +- A **space** is an isolated context. It owns its **rules**, **certified queries**, and **memories** — they are not shared across spaces. +- Each **agent** belongs to exactly one space and inherits everything that space owns. Multiple agents can live in the same space and share the same rules, certified queries, and memories. + +This means you choose a space's boundary based on what context should be shared. Two agents serving the same team usually live in one space; agents serving different domains (Sales vs. Marketing) live in different spaces so their context stays separate. + +```mermaid +flowchart LR + classDef deployment fill:#4f46e5,stroke:#3730a3,color:#fff + classDef space fill:#e0e7ff,stroke:#6366f1,color:#1e1b4b + classDef agent fill:#10b981,stroke:#047857,color:#fff + classDef resource fill:#fef3c7,stroke:#d97706,color:#78350f + + D[Deployment]:::deployment + + SA[Space
sales-analytics]:::space + SM[Space
marketing-analytics]:::space + + SAR[Rules]:::resource + SAC[Certified queries]:::resource + SAM[Memories]:::resource + A1[Agent
sales-assistant]:::agent + A2[Agent
sales-reporter]:::agent + + SMR[Rules]:::resource + SMC[Certified queries]:::resource + SMM[Memories]:::resource + A3[Agent
marketing-analyst]:::agent + + D --> SA + D --> SM + + SA --- SAR + SA --- SAC + SA --- SAM + SA --> A1 + SA --> A2 + + SM --- SMR + SM --- SMC + SM --- SMM + SM --> A3 +``` + +In the [single-agent setup](/admin/ai), there is an implicit `auto` space that holds all rules, certified queries, and memories — you don't need to think about it. In a multi-agent setup, you define spaces explicitly and attach rules and certified queries to specific spaces. + +## What changes from the single-agent setup + +The [`agents/` file structure](/admin/ai#agent-configuration) is the same. What's different is how `agents/config.yml` is shaped: + +1. **Agents are defined as an array.** Each agent gets a unique `name` and an optional `description`, in addition to the standard agent [properties](/admin/ai#properties) (`llm`, `runtime`, `accessible_views`, `memory_mode`, etc.). +2. **Spaces are introduced.** A `spaces` array defines the contexts agents operate in. Each space gets a unique `name`. +3. **Rules and certified queries attach to spaces.** Use the `space` property in the frontmatter of each rule or certified query Markdown file to attach it to a specific space. + + + You cannot mix flat root-level properties (the single-agent style) with `spaces` or `agents` arrays in the same file. Use one style per file. + + +## Agents + +Replace the flat root-level agent properties with an `agents` array: + +```yaml +# agents/config.yml +agents: + - name: sales-assistant # Required + description: "AI assistant for sales analytics" + space: sales-analytics # Required: reference to a space + llm: claude_4_6_sonnet + accessible_views: + - orders_view + - customers_view + memory_mode: user + + - name: marketing-analyst # Required + description: "AI assistant for marketing analytics" + space: marketing-analytics # Required + llm: gpt_5 +``` + +The properties available on each agent are the same as in the [single-agent setup](/admin/ai#properties), plus: + +| Property | Type | Required | Description | +|---------------|--------|:--------:|------------------------------------------------------------| +| `name` | string | Yes | Unique identifier for the agent. | +| `description` | string | No | Human-readable description. | +| `space` | string | Yes | Name of the [space](#spaces) this agent belongs to. | + +## Spaces + +A space is the context an agent operates in. Spaces own the rules, certified queries, and memories that the agents inside them share. Define spaces alongside agents: + +```yaml +# agents/config.yml +spaces: + - name: sales-analytics # Required + description: "Space for sales team analytics and reporting" + + - name: marketing-analytics # Required + description: "Space for marketing team analytics" +``` + +| Property | Type | Required | Description | +|---------------|--------|:--------:|--------------------------------------------| +| `name` | string | Yes | Unique identifier for the space. | +| `description` | string | No | Human-readable description. | + +Each agent must reference exactly one space via its `space` property. Multiple agents can share the same space and inherit its rules, certified queries, and memories. + +## Attaching rules and certified queries to a space + +In the single-agent setup, [rules](/admin/ai/rules) and [certified queries](/admin/ai/certified-queries) belong to the implicit `auto` space. In a multi-agent setup, you must attach each rule and certified query to a specific space using the `space` property in the Markdown frontmatter: + +```markdown + +--- +space: sales-analytics +type: always +--- +Always use fiscal year starting April 1st when analyzing dates. +``` + +```markdown + +--- +space: sales-analytics +description: "Apply when the user asks about quarterly revenue" +user_request: "What is the revenue by quarter?" +--- +SELECT + DATE_TRUNC('quarter', order_date) AS quarter, + SUM(amount) AS revenue +FROM orders +WHERE status != 'cancelled' +GROUP BY 1 +ORDER BY 1 +``` + +You can also organize rules and certified queries into space-named subdirectories. Files placed under `agents/rules//` or `agents/certified_queries//` are attached to that space automatically — no `space` frontmatter required. + +## Complete example + +```yaml +# agents/config.yml +spaces: + - name: sales-analytics + description: "Space for sales team analytics and reporting" + + - name: marketing-analytics + description: "Space for marketing team analytics" + +agents: + - name: sales-assistant + description: "AI assistant for sales analytics and reporting" + space: sales-analytics + llm: claude_4_6_sonnet + accessible_views: + - orders_view + - customers_view + - products_view + memory_mode: user + + - name: marketing-analyst + description: "AI assistant for marketing analytics" + space: marketing-analytics + llm: gpt_5 + memory_mode: user +``` diff --git a/docs-mintlify/admin/ai/rules.mdx b/docs-mintlify/admin/ai/rules.mdx new file mode 100644 index 0000000000000..85432a8d5aebb --- /dev/null +++ b/docs-mintlify/admin/ai/rules.mdx @@ -0,0 +1,140 @@ +--- +title: Rules +description: Define instructions in your data model repository that guide the agent's behavior. +--- + +Rules are instructions that guide the agent's behavior — encoding business definitions, calculation methods, domain terminology, and analytical approaches the agent should follow when answering questions. + +Rules are configured as code in your [data model repository](/admin/ai#agent-configuration), alongside your cubes and views. This enables version control, code review, and consistent behavior across environments. + +## Rule types + +| Type | When applied | Best for | +|-------------------|-----------------------------------------------------------------------------------------------|------------------------------------------------------------------------| +| `always` | Injected into every agent interaction. | Fundamental business definitions, default calculations, domain terms. | +| `agent_requested` | Conditionally applied when the agent determines the rule is relevant to the current request. | Scenario-specific guidance, specialized analysis methods. | + +For `agent_requested` rules, the `description` field is what the agent matches against the user's request to decide whether the rule is relevant — write it as a short summary of when this rule applies. `always` rules don't need a `description` since they're injected into every interaction regardless. + +## Defining rules + +Rules are defined as Markdown files under `agents/rules/`. Each rule lives in its own file: the YAML frontmatter holds metadata, and the Markdown body is the rule prompt. + +```markdown + +--- +type: always +--- +Always use fiscal year starting April 1st when analyzing dates. +Q1 is April–June, Q2 is July–September, Q3 is October–December, Q4 is January–March. +``` + +For `agent_requested` rules, add a `description` so the agent can decide when the rule applies: + +```markdown + +--- +description: "Apply when the user asks about cart abandonment" +type: agent_requested +--- +For cart abandonment analysis, segment by device type and traffic source. +``` + +Files placed under a `rules/` directory are treated as rules automatically — no `kind` property is required. The `name` is inferred from the file name (e.g., `fiscal-year.md` → `fiscal-year`). + +### Frontmatter properties + +| Property | Type | Required | Description | +|---------------|--------|:--------:|----------------------------------------------------------------------------------------------------------------------------------| +| `name` | string | No | Unique identifier. Inferred from the file name if omitted. | +| `description` | string | No | Required for `agent_requested` rules — used by the agent to decide when the rule applies. Optional and unused for `always` rules. | +| `type` | string | Yes | Either `always` or `agent_requested`. | +| `prompt` | string | No | Rule prompt. Falls back to the Markdown body if omitted. | + +### Inlining rules in YAML + +You can also inline rules directly in `agents/config.yml` under a `rules` key: + +```yaml +# agents/config.yml +rules: + - name: fiscal-year + prompt: "Always use fiscal year starting April 1st when analyzing dates." + type: always + + - name: efficiency-analysis + description: "Apply when the user asks about sales efficiency" + prompt: "When analyzing sales efficiency, calculate as deal size divided by sales cycle length." + type: agent_requested +``` + +Inline rules accept the same properties as Markdown rules — `name`, `description`, `prompt` (required), and `type` (required). + + +Rules inlined at the root of `agents/config.yml` are attached to the implicit `auto` space and applied to the default agent in a [single-agent setup](/admin/ai). In a [multi-agent setup](/admin/ai/multi-agent), attach rules to a specific space by inlining them under that space's `rules` key (or by placing Markdown files under `agents/rules//`). + + +## Writing effective rules + +Good rules are specific, actionable, and encode context the agent wouldn't otherwise know about your business. + +**Do:** +- "Customer churn rate is customers lost ÷ total customers at the start of the period." +- "When analyzing quarterly performance, always compare against the same quarter of the previous year." +- "Our fiscal year starts in October." + +**Don't:** +- "Be helpful." (too vague) +- "Always be accurate." (redundant) +- "Consider all factors." (too broad) + +### Domain examples + +**E-commerce:** + +```markdown + +--- +type: always +--- +Customer lifetime value equals average order value × purchase frequency × customer lifespan. +``` + +```markdown + +--- +description: "Apply when the user asks about cart abandonment" +type: agent_requested +--- +For cart abandonment analysis, segment by device type and traffic source. +``` + +**SaaS:** + +```markdown + +--- +type: always +--- +MRR growth rate excludes one-time charges and setup fees. +``` + +```markdown + +--- +description: "Apply when the user asks about churn analysis" +type: agent_requested +--- +When analyzing churn, distinguish between voluntary and involuntary churn. +``` + +## Resolving conflicts + +When multiple rules could apply, follow these guidelines: + +1. **Review existing rules** before adding new ones to avoid contradictions. +2. **Use specific triggers** in `agent_requested` rules so the agent knows when each rule applies. +3. **Prefer specificity over breadth** — narrowly scoped rules override broader defaults more cleanly. +4. **Test rule combinations** with sample queries before relying on them. + +If two `always` rules directly contradict each other, the agent will surface the conflict in its response. Resolve such conflicts by editing the rules in your repository and redeploying. diff --git a/docs-mintlify/admin/ai/skills.mdx b/docs-mintlify/admin/ai/skills.mdx new file mode 100644 index 0000000000000..de1e9c42eca6f --- /dev/null +++ b/docs-mintlify/admin/ai/skills.mdx @@ -0,0 +1,135 @@ +--- +title: Skills +description: Package reusable, named agent workflows in your data model repository that users can run on demand from chat. +--- + +Skills are reusable, named instruction packages for the agent — saved workflows a user +can run on demand wherever they work with the agent, including +[Analytics Chat](/docs/explore-analyze/analytics-chat), Workbooks, dashboards, and the +IDE. Instead of re-typing the same multi-step request ("produce a weekly revenue report, +broken down by region, with week-over-week trends…"), a user picks a skill and the agent +follows the workflow you've defined. + +Skills are configured as code in your [data model repository](/admin/ai#agent-configuration), +alongside your cubes and views, so they're versioned, reviewed, and deployed like the rest +of your Cube project. + + +A skill guides what the agent does using the same data access the agent already has. The +first version of skills is instructions-only — `title`, `description`, and instructions. +There is no per-skill data scoping or external actions yet. + + +## Defining skills + +Skills are defined as Markdown files under `agents/skills/`. Each skill lives in its own +file: the YAML frontmatter holds metadata, and the Markdown body is the instructions the +agent follows. + +```markdown + +--- +title: "Weekly revenue report" +description: "Use when the user asks for a weekly revenue summary, a weekly revenue report, or week-over-week revenue trends." +--- +Produce a weekly revenue report: + +1. Report total revenue for the requested week, alongside the prior week and the + week-over-week percentage change. +2. Break revenue down by region, sorted from highest to lowest. +3. Highlight any region whose revenue changed by more than 10% week over week. +4. If the user names a region or a time range, scope the report accordingly. +``` + +Files placed under a `skills/` directory are treated as skills automatically — no `kind` +property is required. The `name` is inferred from the file name (e.g., +`weekly-revenue-report.md` → `weekly-revenue-report`). Nested folders are allowed for +organization but do not namespace the skill — skill names must be unique across the +entire `skills/` directory. + +### Frontmatter properties + +| Property | Type | Required | Description | +|-----------------|--------|:--------:|-----------------------------------------------------------------------------------| +| `title` | string | Yes | User-facing label shown on the skill button and in the `/` menu. | +| `description` | string | Yes | What the agent matches free-text requests against to auto-select the skill. | +| `name` | string | No | Unique identifier. Inferred from the file name if omitted. | + +The Markdown body is the skill's instructions. + +### Inlining skills in YAML + +You can also inline skills directly in `agents/config.yml` under a `skills` key: + +```yaml +# agents/config.yml +skills: + - name: weekly-revenue-report + title: "Weekly revenue report" + description: "Use when the user asks for a weekly revenue summary or week-over-week trends." + instructions: | + Produce a weekly revenue report: + 1. Total revenue for the requested week, with the week-over-week change. + 2. A breakdown by region, sorted by revenue descending. + 3. Highlight any region that moved more than 10% week over week. +``` + +Inline skills use the same `name`, `title` (required), and `description` (required) as +Markdown skills. Since there is no Markdown body in YAML, provide the instructions inline +via the `instructions` key. + + +Skills inlined at the root of `agents/config.yml` are attached to the implicit `auto` +space and applied to the default agent in a [single-agent setup](/admin/ai). In a +[multi-agent setup](/admin/ai/multi-agent), attach skills to a specific space by inlining +them under that space's `skills` key (or by placing Markdown files under +`agents/skills//`). + + +## How skills are surfaced + +Skills use **progressive disclosure**. The agent is given a compact catalog of every +available skill — just the `name`, `title`, and `description` — so it knows what each +skill is for without carrying the full instructions. When a skill is run, the agent loads +its complete instructions on demand. + +- The chat UI only ever receives a skill's `name`, `title`, and `description`. The full + instruction body stays server-side and is never sent to the browser. +- Skills are surfaced through a viewer-accessible deployment endpoint, so they work for + any configured agent as well as the default `auto` agent. +- Because the agent matches against `description`, a well-written description makes + automatic matching more reliable. + +For how skills appear and run in chat — buttons, the `/` menu, and automatic matching — +see [Agent skills](/docs/explore-analyze/skills). + +## Deploying and testing + +Skills ship through the normal Cube development flow: author the skill on a development +branch, commit, and merge to your production branch. Because skills live on the branch, a +skill on a development branch is testable before it reaches production — open chat against +the dev branch and run the skill to confirm it behaves as intended. + +## Permissions + +Authoring skills requires data-model edit access — the same access needed to define +[rules](/admin/ai/rules) and [certified queries](/admin/ai/certified-queries). In Cube +Cloud's built-in roles, that means the **Admin** or **Developer** +[roles](/admin/users-and-permissions/roles-and-permissions), or a custom role with +semantic-model edit access. + +Running skills is available to anyone with chat access, including **Explorer** and +**Viewer** roles. In-product tips that promote authoring skills, rules, and certified +queries are role-aware and shown only to developers. + +## Writing effective skills + +- **Phrase `description` as a "use when…" statement.** This is what the agent matches + against incoming requests, so describe the situations the skill applies to. +- **Write instructions as an explicit workflow.** Number the steps and state the output + you expect, the same way you'd brief an analyst. +- **Account for added context.** Users can add specifics after selecting a skill (e.g., + `/weekly-revenue-report for EMEA, last 6 weeks`), so instruct the agent to honor a + named region or time range when provided. +- **Keep each skill focused.** One skill should cover one well-defined workflow; create + separate skills for distinct tasks. diff --git a/docs-mintlify/admin/connect-to-data/concurrency.mdx b/docs-mintlify/admin/connect-to-data/concurrency.mdx new file mode 100644 index 0000000000000..9b0a9b33ace6d --- /dev/null +++ b/docs-mintlify/admin/connect-to-data/concurrency.mdx @@ -0,0 +1,90 @@ +--- +title: Querying concurrency +description: "All queries to data APIs are processed asynchronously via a query queue. It allows to optimize the load and increase querying performance." +--- + +## Query queue + +The query queue allows to deduplicate queries to API instances and insulate upstream +data sources from query spikes. It also allows to execute queries to data sources +concurrently for increased performance. + +By default, Cube uses a _single_ query queue for queries from all API instances and +the refresh worker to all configured data sources. + + + +You can read more about the query queue in the [this blog post](https://cube.dev/blog/how-you-win-by-using-cube-store-part-1#query-queue-in-cube). + + + +### Multiple query queues + +You can use the [`context_to_orchestrator_id`][ref-context-to-orchestrator-id] +configuration option to route queries to multiple queues based on the security +context. + + + +If you're configuring multiple connections to data sources via the [`driver_factory` +configuration option][ref-driver-factory], you __must__ also configure +`context_to_orchestrator_id` to ensure that queries are routed to correct queues. + + + +## Data sources + +Cube supports various kinds of [data sources][ref-data-sources], ranging from cloud +data warehouses to embedded databases. Each data source scales differently, +therefore Cube provides sound defaults for each kind of data source out-of-the-box. + +### Data source concurrency + +By default, Cube uses the following concurrency settings for data sources: + +| Data source | Default concurrency | +| --- | --- | +| [Amazon Athena][ref-athena] | 10 | +| [Amazon Redshift][ref-redshift] | 5 | +| [Apache Pinot][ref-pinot] | 10 | +| [ClickHouse][ref-clickhouse] | 10 | +| [Databricks][ref-databricks] | 10 | +| [Firebolt][ref-firebolt] | 10 | +| [Google BigQuery][ref-bigquery] | 10 | +| [Snowflake][ref-snowflake] | 8 | +| All other data sources | 5 or [less, if specified in the driver][link-github-data-source-concurrency] | + +You can use the [`CUBEJS_CONCURRENCY`](/reference/configuration/environment-variables#cubejs_concurrency) environment variable to adjust the maximum +number of concurrent queries to a data source. It's recommended to use the default +configuration unless you're sure that your data source can handle more concurrent +queries. + +### Connection pooling + +For data sources that support connection pooling, the maximum number of concurrent +connections to the database can also be set by using the [`CUBEJS_DB_MAX_POOL`](/reference/configuration/environment-variables#cubejs_db_max_pool) +environment variable. If changing this from the default, you must ensure that the +new value is greater than the number of concurrent connections used by Cube's query +queues and the refresh worker. + +## Refresh worker + +By default, the refresh worker uses the same concurrency settings as API instances. +However, you can override this behvaior in the refresh worker +[configuration][ref-preagg-refresh]. + + +[ref-data-apis]: /reference +[ref-data-sources]: /admin/connect-to-data/data-sources +[ref-context-to-orchestrator-id]: /reference/configuration/config#context_to_orchestrator_id +[ref-driver-factory]: /reference/configuration/config#driver_factory +[ref-preagg-refresh]: /docs/pre-aggregations/refreshing-pre-aggregations#configuration +[ref-athena]: /admin/connect-to-data/data-sources/aws-athena +[ref-clickhouse]: /admin/connect-to-data/data-sources/clickhouse +[ref-databricks]: /admin/connect-to-data/data-sources/databricks-jdbc +[ref-firebolt]: /admin/connect-to-data/data-sources/firebolt +[ref-pinot]: /admin/connect-to-data/data-sources/pinot +[ref-redshift]: /admin/connect-to-data/data-sources/aws-redshift +[ref-snowflake]: /admin/connect-to-data/data-sources/snowflake +[ref-bigquery]: /admin/connect-to-data/data-sources/google-bigquery +[link-github-data-source-concurrency]: https://github.com/search?q=repo%3Acube-js%2Fcube+getDefaultConcurrency+path%3Apackages%2Fcubejs-&type=code \ No newline at end of file diff --git a/docs-mintlify/admin/connect-to-data/data-sources/aws-athena.mdx b/docs-mintlify/admin/connect-to-data/data-sources/aws-athena.mdx new file mode 100644 index 0000000000000..37891d45bfe4d --- /dev/null +++ b/docs-mintlify/admin/connect-to-data/data-sources/aws-athena.mdx @@ -0,0 +1,194 @@ +--- +title: Amazon Athena +description: Give Cube IAM access to Athena, an S3 query-results path, region and catalog settings, plus optional assumed-role credentials. +--- + +## Prerequisites + +- [A set of IAM credentials][aws-docs-athena-access] which allow access to [AWS + Athena][aws-athena] +- [The AWS region][aws-docs-regions] +- [The S3 bucket][aws-s3] on AWS to [store query results][aws-docs-athena-query] + +## Setup + +### Manual + +Add the following to a `.env` file in your Cube project: + +#### Static Credentials + +```dotenv +CUBEJS_DB_TYPE=athena +CUBEJS_AWS_KEY=AKIA************ +CUBEJS_AWS_SECRET=**************************************** +CUBEJS_AWS_REGION=us-east-1 +CUBEJS_AWS_S3_OUTPUT_LOCATION=s3://my-athena-output-bucket +CUBEJS_AWS_ATHENA_WORKGROUP=primary +CUBEJS_DB_NAME=my_non_default_athena_database +CUBEJS_AWS_ATHENA_CATALOG=AwsDataCatalog +``` + +#### IAM Role Assumption + +For enhanced security, you can configure Cube to assume an IAM role to access Athena: + +```dotenv +CUBEJS_DB_TYPE=athena +CUBEJS_AWS_ATHENA_ASSUME_ROLE_ARN=arn:aws:iam::123456789012:role/AthenaAccessRole +CUBEJS_AWS_REGION=us-east-1 +CUBEJS_AWS_S3_OUTPUT_LOCATION=s3://my-athena-output-bucket +CUBEJS_AWS_ATHENA_WORKGROUP=primary +# Optional: if the role requires an external ID +CUBEJS_AWS_ATHENA_ASSUME_ROLE_EXTERNAL_ID=unique-external-id +``` + +When using role assumption: +- If running in AWS (EC2, ECS, EKS with IRSA), the driver will use the instance's IAM role or service account to assume the target role +- You can also provide [`CUBEJS_AWS_KEY`](/reference/configuration/environment-variables#cubejs_aws_key) and [`CUBEJS_AWS_SECRET`](/reference/configuration/environment-variables#cubejs_aws_secret) as master credentials for the role assumption + +### Cube Cloud + + + +In some cases you'll need to allow connections from your Cube Cloud deployment +IP address to your database. You can copy the IP address from either the +Database Setup step in deployment creation, or from **Settings → +Configuration** in your deployment. + + + +In Cube Cloud, select **AWS Athena** when creating a new deployment and fill in +the required fields: + + + Cube Cloud AWS Athena Configuration Screen + + +#### OIDC workload identity + +Instead of static credentials, Cube Cloud deployments can authenticate to +Athena with [OIDC workload identity][ref-oidc-aws-athena]: an IAM role in +your account trusts Cube's OIDC issuer, and the driver assumes it through +the AWS SDK's default credential chain — no access keys to provision or +rotate. + +```dotenv +CUBEJS_DB_TYPE=athena +AWS_ROLE_ARN=arn:aws:iam::123456789012:role/cube-deployment-acme +CUBEJS_AWS_REGION=us-east-1 +CUBEJS_AWS_S3_OUTPUT_LOCATION=s3://my-athena-output-bucket +``` + +See the [AWS OIDC guide][ref-oidc-aws-athena] for the IAM role, trust +policy, and permissions setup. + +Cube Cloud also supports connecting to data sources within private VPCs +if [single-tenant infrastructure][ref-dedicated-infra] is used. Check out the +[VPC connectivity guide][ref-cloud-conf-vpc] for details. + +[ref-dedicated-infra]: /admin/deployment/infrastructure#dedicated-infrastructure +[ref-cloud-conf-vpc]: /admin/deployment/dedicated +## Environment Variables + +| Environment Variable | Description | Possible Values | Required | +| ----------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------ | :------: | +| [`CUBEJS_AWS_KEY`](/reference/configuration/environment-variables#cubejs_aws_key) | The AWS Access Key ID to use for database connections | A valid AWS Access Key ID | ❌1 | +| [`CUBEJS_AWS_SECRET`](/reference/configuration/environment-variables#cubejs_aws_secret) | The AWS Secret Access Key to use for database connections | A valid AWS Secret Access Key | ❌1 | +| [`CUBEJS_AWS_REGION`](/reference/configuration/environment-variables#cubejs_aws_region) | The AWS region of the Cube deployment | [A valid AWS region][aws-docs-regions] | ✅ | +| `CUBEJS_AWS_S3_OUTPUT_LOCATION` | The S3 path to store query results made by the Cube deployment | A valid S3 path | ❌ | +| [`CUBEJS_AWS_ATHENA_WORKGROUP`](/reference/configuration/environment-variables#cubejs_aws_athena_workgroup) | The name of the workgroup in which the query is being started | [A valid Athena Workgroup][aws-athena-workgroup] | ❌ | +| [`CUBEJS_AWS_ATHENA_CATALOG`](/reference/configuration/environment-variables#cubejs_aws_athena_catalog) | The name of the catalog to use by default | [A valid Athena Catalog name][awsdatacatalog] | ❌ | +| [`CUBEJS_AWS_ATHENA_ASSUME_ROLE_ARN`](/reference/configuration/environment-variables#cubejs_aws_athena_assume_role_arn) | The ARN of the IAM role to assume for Athena access | A valid IAM role ARN | ❌ | +| [`CUBEJS_AWS_ATHENA_ASSUME_ROLE_EXTERNAL_ID`](/reference/configuration/environment-variables#cubejs_aws_athena_assume_role_external_id) | The external ID to use when assuming the IAM role (if required by the role's trust policy) | A string | ❌ | +| [`CUBEJS_DB_NAME`](/reference/configuration/environment-variables#cubejs_db_name) | The name of the database to use by default | A valid Athena Database name | ❌ | +| [`CUBEJS_DB_SCHEMA`](/reference/configuration/environment-variables#cubejs_db_schema) | The name of the schema to use as `information_schema` filter. Reduces count of tables loaded during schema generation. | A valid schema name | ❌ | +| [`CUBEJS_CONCURRENCY`](/reference/configuration/environment-variables#cubejs_concurrency) | The number of [concurrent queries][ref-data-source-concurrency] to the data source | A valid number | ❌ | + +1 Either provide [`CUBEJS_AWS_KEY`](/reference/configuration/environment-variables#cubejs_aws_key) and [`CUBEJS_AWS_SECRET`](/reference/configuration/environment-variables#cubejs_aws_secret) for static credentials, or use [`CUBEJS_AWS_ATHENA_ASSUME_ROLE_ARN`](/reference/configuration/environment-variables#cubejs_aws_athena_assume_role_arn) for role-based authentication. When using role assumption without static credentials, the driver will use the AWS SDK's default credential chain (IAM instance profile, EKS IRSA, or [OIDC workload identity][ref-oidc-aws-athena] in Cube Cloud). + +[ref-data-source-concurrency]: /admin/connect-to-data/concurrency#data-source-concurrency +## Pre-Aggregation Feature Support + +### count_distinct_approx + +Measures of type +[`count_distinct_approx`][ref-schema-ref-types-formats-countdistinctapprox] can +be used in pre-aggregations when using AWS Athena as a source database. To learn +more about AWS Athena's support for approximate aggregate functions, [click +here][aws-athena-docs-approx-agg-fns]. + +## Pre-Aggregation Build Strategies + + + +To learn more about pre-aggregation build strategies, [head +here][ref-caching-using-preaggs-build-strats]. + + + +| Feature | Works with read-only mode? | Is default? | +| ------------- | :------------------------: | :---------: | +| Batching | ❌ | ✅ | +| Export Bucket | ❌ | ❌ | + +By default, AWS Athena uses a [batching][self-preaggs-batching] strategy to +build pre-aggregations. + +### Batching + +No extra configuration is required to configure batching for AWS Athena. + +### Export Bucket + + + +AWS Athena **only** supports using AWS S3 for export buckets. + + + +#### AWS S3 + +For [improved pre-aggregation performance with large +datasets][ref-caching-large-preaggs], enable export bucket functionality by +configuring Cube with the following environment variables: + + + +Ensure the AWS credentials are correctly configured in IAM to allow reads and +writes to the export bucket in S3. + + + +```dotenv +CUBEJS_DB_EXPORT_BUCKET_TYPE=s3 +CUBEJS_DB_EXPORT_BUCKET=my.bucket.on.s3 +CUBEJS_DB_EXPORT_BUCKET_AWS_KEY= +CUBEJS_DB_EXPORT_BUCKET_AWS_SECRET= +CUBEJS_DB_EXPORT_BUCKET_AWS_REGION= +``` + +## SSL + +Cube does not require any additional configuration to enable SSL as AWS Athena +connections are made over HTTPS. + +[aws-athena]: https://aws.amazon.com/athena +[aws-athena-workgroup]: + https://docs.aws.amazon.com/athena/latest/ug/workgroups-benefits.html +[awsdatacatalog]: + https://docs.aws.amazon.com/athena/latest/ug/understanding-tables-databases-and-the-data-catalog.html +[aws-s3]: https://aws.amazon.com/s3/ +[aws-docs-athena-access]: + https://docs.aws.amazon.com/athena/latest/ug/security-iam-athena.html +[aws-docs-athena-query]: + https://docs.aws.amazon.com/athena/latest/ug/querying.html +[aws-docs-regions]: + https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-regions-availability-zones.html#concepts-available-regions +[aws-athena-docs-approx-agg-fns]: + https://prestodb.io/docs/current/functions/aggregate.html#approximate-aggregate-functions +[ref-caching-large-preaggs]: /docs/pre-aggregations/using-pre-aggregations#export-bucket +[ref-caching-using-preaggs-build-strats]: /docs/pre-aggregations/using-pre-aggregations#pre-aggregation-build-strategies +[ref-oidc-aws-athena]: /admin/deployment/oidc/aws#athena +[ref-schema-ref-types-formats-countdistinctapprox]: /reference/data-modeling/measures#type +[self-preaggs-batching]: #batching diff --git a/docs-mintlify/admin/connect-to-data/data-sources/aws-redshift.mdx b/docs-mintlify/admin/connect-to-data/data-sources/aws-redshift.mdx new file mode 100644 index 0000000000000..dd9b927b76bc4 --- /dev/null +++ b/docs-mintlify/admin/connect-to-data/data-sources/aws-redshift.mdx @@ -0,0 +1,224 @@ +--- +title: AWS Redshift +description: Authenticate Cube to Amazon Redshift with database passwords or IAM roles and ensure network reachability from your deployment. +--- + +## Prerequisites + +- The [hostname][aws-redshift-docs-connection-string] for the [AWS + Redshift][aws-redshift] cluster +- The [username/password][aws-redshift-docs-users] for the [AWS + Redshift][aws-redshift] cluster **or** IAM credentials with + `redshift:GetClusterCredentialsWithIAM` and `redshift:DescribeClusters` + permissions +- The name of the database to use within the [AWS Redshift][aws-redshift] + cluster + + + +If the cluster is configured within a [VPC][aws-vpc], then Cube **must** have a +network route to the cluster. + + + +## Setup + +### Manual + +Add the following to a `.env` file in your Cube project: + +#### Password Authentication + +```dotenv +CUBEJS_DB_TYPE=redshift +CUBEJS_DB_HOST=my-redshift-cluster.cfbs3dkw1io8.eu-west-1.redshift.amazonaws.com +CUBEJS_DB_NAME=my_redshift_database +CUBEJS_DB_USER= +CUBEJS_DB_PASS= +``` + +#### IAM Authentication + +For enhanced security, you can configure Cube to use IAM authentication +instead of username and password. When running in AWS (EC2, ECS, EKS with +IRSA), the driver can use the instance's IAM role to obtain temporary +database credentials automatically. + +Omit [`CUBEJS_DB_USER`](/reference/configuration/environment-variables#cubejs_db_user) and [`CUBEJS_DB_PASS`](/reference/configuration/environment-variables#cubejs_db_pass) to enable IAM authentication: + +```dotenv +CUBEJS_DB_TYPE=redshift +CUBEJS_DB_HOST=my-redshift-cluster.xxx.eu-west-1.redshift.amazonaws.com +CUBEJS_DB_NAME=my_redshift_database +CUBEJS_DB_SSL=true +CUBEJS_DB_REDSHIFT_AWS_REGION=eu-west-1 +CUBEJS_DB_REDSHIFT_CLUSTER_IDENTIFIER=my-redshift-cluster +``` + +The driver uses the AWS SDK's default credential chain (IAM instance profile, +EKS IRSA, etc.) to obtain temporary database credentials via the +`redshift:GetClusterCredentialsWithIAM` API. + +#### IAM Role Assumption + +For cross-account access or enhanced security, you can configure Cube to assume +an IAM role: + +```dotenv +CUBEJS_DB_REDSHIFT_AWS_REGION=eu-west-1 +CUBEJS_DB_REDSHIFT_CLUSTER_IDENTIFIER=my-redshift-cluster +CUBEJS_DB_REDSHIFT_ASSUME_ROLE_ARN=arn:aws:iam::123456789012:role/RedshiftAccessRole +CUBEJS_DB_REDSHIFT_ASSUME_ROLE_EXTERNAL_ID=unique-external-id +``` + +### Cube Cloud + + + +In some cases you'll need to allow connections from your Cube Cloud deployment +IP address to your database. You can copy the IP address from either the +Database Setup step in deployment creation, or from **Settings → +Configuration** in your deployment. + + + +The following fields are required when creating an AWS Redshift connection: + + + Cube Cloud AWS Redshift Configuration Screen + + +#### OIDC workload identity + +Instead of a database password, Cube Cloud deployments can authenticate to +Redshift with [OIDC workload identity][ref-oidc-aws-redshift]: an IAM role +in your account trusts Cube's OIDC issuer, and the driver uses it to obtain +temporary database credentials via [IAM authentication](#iam-authentication). +Set `AWS_ROLE_ARN` alongside the IAM authentication variables and omit +`CUBEJS_DB_USER` / `CUBEJS_DB_PASS`: + +```dotenv +CUBEJS_DB_TYPE=redshift +AWS_ROLE_ARN=arn:aws:iam::123456789012:role/cube-deployment-acme +CUBEJS_DB_HOST=my-redshift-cluster.xxx.eu-west-1.redshift.amazonaws.com +CUBEJS_DB_NAME=my_redshift_database +CUBEJS_DB_SSL=true +CUBEJS_DB_REDSHIFT_AWS_REGION=eu-west-1 +CUBEJS_DB_REDSHIFT_CLUSTER_IDENTIFIER=my-redshift-cluster +``` + +See the [AWS OIDC guide][ref-oidc-aws-redshift] for the IAM role, trust +policy, and permissions setup. + +Cube Cloud also supports connecting to data sources within private VPCs +if [single-tenant infrastructure][ref-dedicated-infra] is used. Check out the +[VPC connectivity guide][ref-cloud-conf-vpc] for details. + +[ref-dedicated-infra]: /admin/deployment/infrastructure#dedicated-infrastructure +[ref-cloud-conf-vpc]: /admin/deployment/dedicated +## Environment Variables + +| Environment Variable | Description | Possible Values | Required | +| ------------------------------------------- | ----------------------------------------------------------------------------------- | ------------------------- | :------: | +| [`CUBEJS_DB_HOST`](/reference/configuration/environment-variables#cubejs_db_host) | The host URL for a database | A valid database host URL | ✅ | +| [`CUBEJS_DB_PORT`](/reference/configuration/environment-variables#cubejs_db_port) | The port for the database connection | A valid port number | ❌ | +| [`CUBEJS_DB_NAME`](/reference/configuration/environment-variables#cubejs_db_name) | The name of the database to connect to | A valid database name | ✅ | +| [`CUBEJS_DB_USER`](/reference/configuration/environment-variables#cubejs_db_user) | The username used to connect to the database | A valid database username | ✅1 | +| [`CUBEJS_DB_PASS`](/reference/configuration/environment-variables#cubejs_db_pass) | The password used to connect to the database | A valid database password | ✅1 | +| [`CUBEJS_DB_SSL`](/reference/configuration/environment-variables#cubejs_db_ssl) | If `true`, enables SSL encryption for database connections from Cube | `true`, `false` | ❌ | +| [`CUBEJS_DB_MAX_POOL`](/reference/configuration/environment-variables#cubejs_db_max_pool) | The maximum number of concurrent database connections to pool. Default is `16` | A valid number | ❌ | +| [`CUBEJS_DB_REDSHIFT_CLUSTER_IDENTIFIER`](/reference/configuration/environment-variables#cubejs_db_redshift_cluster_identifier) | The Redshift cluster identifier. Required for IAM authentication | A valid cluster identifier | ❌ | +| [`CUBEJS_DB_REDSHIFT_AWS_REGION`](/reference/configuration/environment-variables#cubejs_db_redshift_aws_region) | The AWS region of the Redshift cluster. Required for IAM authentication | [A valid AWS region][aws-docs-regions] | ❌ | +| [`CUBEJS_DB_REDSHIFT_ASSUME_ROLE_ARN`](/reference/configuration/environment-variables#cubejs_db_redshift_assume_role_arn) | The ARN of the IAM role to assume for cross-account access | A valid IAM role ARN | ❌ | +| [`CUBEJS_DB_REDSHIFT_ASSUME_ROLE_EXTERNAL_ID`](/reference/configuration/environment-variables#cubejs_db_redshift_assume_role_external_id)| The external ID for the assumed role's trust policy | A string | ❌ | +| [`CUBEJS_DB_EXPORT_BUCKET_REDSHIFT_ARN`](/reference/configuration/environment-variables#cubejs_db_export_bucket_redshift_arn) | | | ❌ | +| [`CUBEJS_CONCURRENCY`](/reference/configuration/environment-variables#cubejs_concurrency) | The number of [concurrent queries][ref-data-source-concurrency] to the data source | A valid number | ❌ | + +1 Required when using password-based authentication. When using IAM authentication, omit these and set [`CUBEJS_DB_REDSHIFT_CLUSTER_IDENTIFIER`](/reference/configuration/environment-variables#cubejs_db_redshift_cluster_identifier) and [`CUBEJS_DB_REDSHIFT_AWS_REGION`](/reference/configuration/environment-variables#cubejs_db_redshift_aws_region) instead. The driver uses the AWS SDK's default credential chain (IAM instance profile, EKS IRSA, or [OIDC workload identity][ref-oidc-aws-redshift] in Cube Cloud) to obtain temporary database credentials. + +[ref-data-source-concurrency]: /admin/connect-to-data/concurrency#data-source-concurrency +## Pre-Aggregation Feature Support + +### count_distinct_approx + +Measures of type +[`count_distinct_approx`][ref-schema-ref-types-formats-countdistinctapprox] can +not be used in pre-aggregations when using AWS Redshift as a source database. + +## Pre-Aggregation Build Strategies + + + +To learn more about pre-aggregation build strategies, [head +here][ref-caching-using-preaggs-build-strats]. + + + +| Feature | Works with read-only mode? | Is default? | +| ------------- | :------------------------: | :---------: | +| Batching | ❌ | ✅ | +| Export Bucket | ❌ | ❌ | + +By default, AWS Redshift uses [batching][self-preaggs-batching] to build +pre-aggregations. + +### Batching + +Cube requires the Redshift user to have ownership of a schema in Redshift to +support pre-aggregations. By default, the schema name is `prod_pre_aggregations`. +It can be set using the [`pre_aggregations_schema` configration +option][ref-conf-preaggs-schema]. + +No extra configuration is required to configure batching for AWS Redshift. + +### Export bucket + + + +AWS Redshift **only** supports using AWS S3 for export buckets. + + + +#### AWS S3 + +For [improved pre-aggregation performance with large +datasets][ref-caching-large-preaggs], enable export bucket functionality by +configuring Cube with the following environment variables: + + + +Ensure the AWS credentials are correctly configured in IAM to allow reads and +writes to the export bucket in S3. + + + +```dotenv +CUBEJS_DB_EXPORT_BUCKET_TYPE=s3 +CUBEJS_DB_EXPORT_BUCKET=my.bucket.on.s3 +CUBEJS_DB_EXPORT_BUCKET_AWS_KEY= +CUBEJS_DB_EXPORT_BUCKET_AWS_SECRET= +CUBEJS_DB_EXPORT_BUCKET_AWS_REGION= +``` + +## SSL + +To enable SSL-encrypted connections between Cube and AWS Redshift, set the +[`CUBEJS_DB_SSL`](/reference/configuration/environment-variables#cubejs_db_ssl) environment variable to `true`. For more information on how to +configure custom certificates, please check out [Enable SSL Connections to the +Database][ref-recipe-enable-ssl]. + +[aws-redshift-docs-connection-string]: + https://docs.aws.amazon.com/redshift/latest/mgmt/configuring-connections.html#connecting-drivers +[aws-redshift-docs-users]: + https://docs.aws.amazon.com/redshift/latest/dg/r_Users.html +[aws-redshift]: https://aws.amazon.com/redshift/ +[aws-vpc]: https://aws.amazon.com/vpc/ +[aws-docs-regions]: + https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-regions-availability-zones.html#concepts-available-regions +[ref-caching-large-preaggs]: /docs/pre-aggregations/using-pre-aggregations#export-bucket +[ref-caching-using-preaggs-build-strats]: /docs/pre-aggregations/using-pre-aggregations#pre-aggregation-build-strategies +[ref-oidc-aws-redshift]: /admin/deployment/oidc/aws#redshift +[ref-recipe-enable-ssl]: /recipes/configuration/using-ssl-connections-to-data-source +[ref-schema-ref-types-formats-countdistinctapprox]: /reference/data-modeling/measures#type +[self-preaggs-batching]: #batching +[ref-conf-preaggs-schema]: /reference/configuration/config#pre_aggregations_schema \ No newline at end of file diff --git a/docs-mintlify/admin/connect-to-data/data-sources/clickhouse.mdx b/docs-mintlify/admin/connect-to-data/data-sources/clickhouse.mdx new file mode 100644 index 0000000000000..fe1b8210f64b5 --- /dev/null +++ b/docs-mintlify/admin/connect-to-data/data-sources/clickhouse.mdx @@ -0,0 +1,220 @@ +--- +title: ClickHouse +description: Connect Cube to ClickHouse for low-latency analytics, including host credentials and driver-specific connection options. +--- + +[ClickHouse](https://clickhouse.com) is a fast and resource efficient +[open-source database](https://github.com/ClickHouse/ClickHouse) for real-time +applications and analytics. + +## Prerequisites + +- The hostname for the [ClickHouse][clickhouse] database server +- The [username/password][clickhouse-docs-users] for the + [ClickHouse][clickhouse] database server + +## Setup + +### Manual + +Add the following to a `.env` file in your Cube project: + +```dotenv +CUBEJS_DB_TYPE=clickhouse +CUBEJS_DB_HOST=my.clickhouse.host +CUBEJS_DB_NAME=my_clickhouse_database +CUBEJS_DB_USER=clickhouse_user +CUBEJS_DB_PASS=********** +``` + +## Environment Variables + +| Environment Variable | Description | Possible Values | Required | +| ---------------------------------- | ----------------------------------------------------------------------------------- | ------------------------- | :------: | +| [`CUBEJS_DB_HOST`](/reference/configuration/environment-variables#cubejs_db_host) | The host URL for a database | A valid database host URL | ✅ | +| [`CUBEJS_DB_PORT`](/reference/configuration/environment-variables#cubejs_db_port) | The port for the database connection | A valid port number | ❌ | +| [`CUBEJS_DB_NAME`](/reference/configuration/environment-variables#cubejs_db_name) | The name of the database to connect to | A valid database name | ✅ | +| [`CUBEJS_DB_USER`](/reference/configuration/environment-variables#cubejs_db_user) | The username used to connect to the database | A valid database username | ✅ | +| [`CUBEJS_DB_PASS`](/reference/configuration/environment-variables#cubejs_db_pass) | The password used to connect to the database | A valid database password | ✅ | +| [`CUBEJS_DB_CLICKHOUSE_READONLY`](/reference/configuration/environment-variables#cubejs_db_clickhouse_readonly) | Whether the ClickHouse user has read-only access or not | `true`, `false` | ❌ | +| [`CUBEJS_DB_CLICKHOUSE_COMPRESSION`](/reference/configuration/environment-variables#cubejs_db_clickhouse_compression) | Whether the ClickHouse client has compression enabled or not | `true`, `false` | ❌ | +| [`CUBEJS_DB_MAX_POOL`](/reference/configuration/environment-variables#cubejs_db_max_pool) | The maximum number of concurrent database connections to pool. Default is `20` | A valid number | ❌ | +| [`CUBEJS_CONCURRENCY`](/reference/configuration/environment-variables#cubejs_concurrency) | The number of [concurrent queries][ref-data-source-concurrency] to the data source | A valid number | ❌ | + +[ref-data-source-concurrency]: /admin/connect-to-data/concurrency#data-source-concurrency +## Pre-Aggregation Feature Support + +When using [pre-aggregations][ref-preaggs] with ClickHouse, you have to define +[indexes][ref-preaggs-indexes] in pre-aggregations. Otherwise, you might get +the following error: `ClickHouse doesn't support pre-aggregations without indexes`. + +### `count_distinct_approx` + +Measures of type +[`count_distinct_approx`][ref-schema-ref-types-formats-countdistinctapprox] can +not be used in pre-aggregations when using ClickHouse as a source database. + +### `rollup_join` + +You can use [`rollup_join` pre-aggregations][ref-preaggs-rollup-join] to join +data from ClickHouse and other data sources inside Cube Store. + +Alternatively, you can leverage ClickHouse support for [integration table +engines](https://clickhouse.com/docs/en/engines/table-engines#integration-engines) +to join data from ClickHouse and other data sources inside ClickHouse. +To do so, define table engines in ClickHouse and connect your ClickHouse as the +only data source to Cube. + +## Pre-Aggregation Build Strategies + + + +To learn more about pre-aggregation build strategies, [head +here][ref-caching-using-preaggs-build-strats]. + + + +| Feature | Works with read-only mode? | Is default? | +| ------------- | :------------------------: | :---------: | +| Batching | ✅ | ✅ | +| Export Bucket | ✅ | - | + +By default, ClickHouse uses [batching][self-preaggs-batching] to build +pre-aggregations. + +### Batching + +No extra configuration is required to configure batching for ClickHouse. + +### Export Bucket + + + + Clickhouse driver **only** supports using AWS S3 for export buckets. + + + +#### AWS S3 + +For [improved pre-aggregation performance with large +datasets][ref-caching-large-preaggs], enable export bucket functionality by +configuring Cube with the following environment variables: + + + + Ensure the AWS credentials are correctly configured in IAM to allow reads and + writes to the export bucket in S3. + + + +```dotenv +CUBEJS_DB_EXPORT_BUCKET_TYPE=s3 +CUBEJS_DB_EXPORT_BUCKET=my.bucket.on.s3 +CUBEJS_DB_EXPORT_BUCKET_AWS_KEY= +CUBEJS_DB_EXPORT_BUCKET_AWS_SECRET= +CUBEJS_DB_EXPORT_BUCKET_AWS_REGION= +``` + +## SSL + +To enable SSL-encrypted connections between Cube and ClickHouse, set the +[`CUBEJS_DB_SSL`](/reference/configuration/environment-variables#cubejs_db_ssl) environment variable to `true`. For more information on how to +configure custom certificates, please check out [Enable SSL Connections to the +Database][ref-recipe-enable-ssl]. + +## Custom headers + +The ClickHouse driver supports forwarding custom HTTP headers on every request to +the ClickHouse server. This is useful when requests pass through a proxy or gateway +that expects additional headers (e.g., for routing or tracing). See the [ClickHouse +JavaScript client configuration][clickhouse-docs-js-config] for more details. + +Custom headers can't be configured via environment variables. Instead, use the +[`driver_factory`](/reference/configuration/config#driver_factory) configuration +option to pass a `headers` object to the driver: + + + +```python title="Python" +from cube import config + +@config('driver_factory') +def driver_factory(ctx: dict) -> dict: + return { + 'type': 'clickhouse', + 'headers': { + 'X-Custom-Header': 'value', + 'X-Routing-Group': 'analytics' + } + } +``` + +```javascript title="JavaScript" +module.exports = { + driverFactory: ({ dataSource }) => ({ + type: "clickhouse", + headers: { + "X-Custom-Header": "value", + "X-Routing-Group": "analytics" + } + }) +}; +``` + + + +In multitenant deployments, you can use the [security +context](/embedding/authentication/security-context) to pass per-tenant headers, for example +to forward a user token from the API request down to ClickHouse: + + + +```python title="Python" +from cube import config + +@config('driver_factory') +def driver_factory(ctx: dict) -> dict: + security_context = ctx['securityContext'] + return { + 'type': 'clickhouse', + 'headers': { + 'X-Custom-User-Token': security_context['token'] + } + } +``` + +```javascript title="JavaScript" +module.exports = { + driverFactory: ({ securityContext }) => ({ + type: "clickhouse", + headers: { + "X-Custom-User-Token": securityContext.token + } + }) +}; +``` + + + +## Additional Configuration + +You can connect to a ClickHouse database when your user's permissions are +[restricted][clickhouse-readonly] to read-only, by setting +[`CUBEJS_DB_CLICKHOUSE_READONLY`](/reference/configuration/environment-variables#cubejs_db_clickhouse_readonly) to `true`. + +You can connect to a ClickHouse database with compression enabled, by setting +[`CUBEJS_DB_CLICKHOUSE_COMPRESSION`](/reference/configuration/environment-variables#cubejs_db_clickhouse_compression) to `true`. + +[clickhouse]: https://clickhouse.tech/ +[clickhouse-docs-users]: + https://clickhouse.tech/docs/en/operations/settings/settings-users/ +[clickhouse-docs-js-config]: https://clickhouse.com/docs/integrations/javascript#configuration +[clickhouse-readonly]: https://clickhouse.com/docs/en/operations/settings/permissions-for-queries#readonly +[ref-caching-using-preaggs-build-strats]: /docs/pre-aggregations/using-pre-aggregations#pre-aggregation-build-strategies +[ref-recipe-enable-ssl]: /recipes/configuration/using-ssl-connections-to-data-source +[ref-caching-large-preaggs]: /docs/pre-aggregations/using-pre-aggregations#export-bucket +[ref-schema-ref-types-formats-countdistinctapprox]: /reference/data-modeling/measures#type +[self-preaggs-batching]: #batching +[ref-preaggs]: /docs/pre-aggregations/using-pre-aggregations +[ref-preaggs-indexes]: /reference/data-modeling/pre-aggregations#indexes +[ref-preaggs-rollup-join]: /reference/data-modeling/pre-aggregations#rollup_join \ No newline at end of file diff --git a/docs-mintlify/admin/connect-to-data/data-sources/databricks-jdbc.mdx b/docs-mintlify/admin/connect-to-data/data-sources/databricks-jdbc.mdx new file mode 100644 index 0000000000000..ae3dcabdcd650 --- /dev/null +++ b/docs-mintlify/admin/connect-to-data/data-sources/databricks-jdbc.mdx @@ -0,0 +1,207 @@ +--- +title: Databricks +description: Databricks is a unified data intelligence platform. +--- + +[Databricks](https://www.databricks.com) is a unified data intelligence platform. + +## Prerequisites + +- [A JDK installation][gh-cubejs-jdbc-install] +- The [JDBC URL][databricks-docs-jdbc-url] for the [Databricks][databricks] + cluster + +## Setup + +### Environment Variables + +Add the following to a `.env` file in your Cube project: + +```dotenv +CUBEJS_DB_TYPE=databricks-jdbc +# CUBEJS_DB_NAME is optional +CUBEJS_DB_NAME=default +# You can find this inside the cluster's configuration +CUBEJS_DB_DATABRICKS_URL=jdbc:databricks://dbc-XXXXXXX-XXXX.cloud.databricks.com:443/default;transportMode=http;ssl=1;httpPath=sql/protocolv1/o/XXXXX/XXXXX;AuthMech=3;UID=token +# You can specify the personal access token separately from [`CUBEJS_DB_DATABRICKS_URL`](/reference/configuration/environment-variables#cubejs_db_databricks_url) by doing this: +CUBEJS_DB_DATABRICKS_TOKEN=XXXXX +# This accepts the Databricks usage policy and must be set to `true` to use the Databricks JDBC driver +CUBEJS_DB_DATABRICKS_ACCEPT_POLICY=true +``` + +### Docker + +Create a `.env` file [as above](#environment-variables), then extend the +`cubejs/cube:jdk` Docker image tag to build a Cube image with the JDBC driver: + +```dockerfile +FROM cubejs/cube:jdk + +COPY . . +RUN npm install +``` + +You can then build and run the image using the following commands: + +```bash +docker build -t cube-jdk . +docker run -it -p 4000:4000 --env-file=.env cube-jdk +``` + +## Environment Variables + +| Environment Variable | Description | Possible Values | Required | +| ------------------------------------ | ----------------------------------------------------------------------------------------------- | --------------------- | :------: | +| [`CUBEJS_DB_NAME`](/reference/configuration/environment-variables#cubejs_db_name) | The name of the database to connect to | A valid database name | ✅ | +| [`CUBEJS_DB_DATABRICKS_URL`](/reference/configuration/environment-variables#cubejs_db_databricks_url) | The URL for a JDBC connection | A valid JDBC URL | ✅ | +| [`CUBEJS_DB_DATABRICKS_ACCEPT_POLICY`](/reference/configuration/environment-variables#cubejs_db_databricks_accept_policy) | Whether or not to accept the license terms for the Databricks JDBC driver | `true`, `false` | ✅ | +| [`CUBEJS_DB_DATABRICKS_OAUTH_CLIENT_ID`](/reference/configuration/environment-variables#cubejs_db_databricks_oauth_client_id) | The OAuth client ID for [service principal][ref-databricks-m2m-oauth] authentication | A valid client ID | ❌ | +| [`CUBEJS_DB_DATABRICKS_OAUTH_CLIENT_SECRET`](/reference/configuration/environment-variables#cubejs_db_databricks_oauth_client_secret) | The OAuth client secret for [service principal][ref-databricks-m2m-oauth] authentication | A valid client secret | ❌ | +| [`CUBEJS_DB_DATABRICKS_TOKEN`](/reference/configuration/environment-variables#cubejs_db_databricks_token) | The [personal access token][databricks-docs-pat] used to authenticate the Databricks connection | A valid token | ❌ | +| [`CUBEJS_DB_DATABRICKS_CATALOG`](/reference/configuration/environment-variables#cubejs_db_databricks_catalog) | The name of the [Databricks catalog][databricks-catalog] to connect to | A valid catalog name | ❌ | +| [`CUBEJS_DB_EXPORT_BUCKET_MOUNT_DIR`](/reference/configuration/environment-variables#cubejs_db_export_bucket_mount_dir) | The path for the [Databricks DBFS mount][databricks-docs-dbfs] (Not needed if using Unity Catalog connection) | A valid mount path | ❌ | +| [`CUBEJS_DB_MAX_POOL`](/reference/configuration/environment-variables#cubejs_db_max_pool) | The maximum number of concurrent database connections to pool. Default is `8` | A valid number | ❌ | +| [`CUBEJS_CONCURRENCY`](/reference/configuration/environment-variables#cubejs_concurrency) | The number of [concurrent queries][ref-data-source-concurrency] to the data source | A valid number | ❌ | + +[ref-data-source-concurrency]: /admin/connect-to-data/concurrency#data-source-concurrency +## Pre-Aggregation Feature Support + +### count_distinct_approx + +Measures of type +[`count_distinct_approx`][ref-schema-ref-types-formats-countdistinctapprox] can +be used in pre-aggregations when using Databricks as a source database. To learn +more about Databricks's support for approximate aggregate functions, [click +here][databricks-docs-approx-agg-fns]. + +## Pre-Aggregation Build Strategies + + + +To learn more about pre-aggregation build strategies, [head +here][ref-caching-using-preaggs-build-strats]. + + + +| Feature | Works with read-only mode? | Is default? | +| ------------- | :------------------------: | :---------: | +| Simple | ✅ | ✅ | +| Export Bucket | ✅ | ❌ | + +By default, Databricks JDBC uses a [simple][self-preaggs-simple] strategy to +build pre-aggregations. + +### Simple + +No extra configuration is required to configure simple pre-aggregation builds +for Databricks. + +### Export Bucket + +Databricks supports using both [AWS S3][aws-s3] and [Azure Blob +Storage][azure-bs] for export bucket functionality. + +#### AWS S3 + +To use AWS S3 as an export bucket, first complete [the Databricks guide on +connecting to cloud object storage using Unity Catalog][databricks-docs-uc-s3]. + + + +Ensure the AWS credentials are correctly configured in IAM to allow reads and +writes to the export bucket in S3. + + + +```dotenv +CUBEJS_DB_EXPORT_BUCKET_TYPE=s3 +CUBEJS_DB_EXPORT_BUCKET=s3://my.bucket.on.s3 +CUBEJS_DB_EXPORT_BUCKET_AWS_KEY= +CUBEJS_DB_EXPORT_BUCKET_AWS_SECRET= +CUBEJS_DB_EXPORT_BUCKET_AWS_REGION= +``` + +#### Google Cloud Storage + + + +When using an export bucket, remember to assign the **Storage Object Admin** +role to your Google Cloud credentials ([`CUBEJS_DB_EXPORT_GCS_CREDENTIALS`](/reference/configuration/environment-variables#cubejs_db_export_gcs_credentials)). + + + +To use Google Cloud Storage as an export bucket, first complete [the Databricks guide on +connecting to cloud object storage using Unity Catalog][databricks-docs-uc-gcs]. + +```dotenv +CUBEJS_DB_EXPORT_BUCKET=gs://databricks-export-bucket +CUBEJS_DB_EXPORT_BUCKET_TYPE=gcs +CUBEJS_DB_EXPORT_GCS_CREDENTIALS= +``` + +#### Azure Blob Storage + +To use Azure Blob Storage as an export bucket, follow [the Databricks guide on +connecting to Azure Data Lake Storage Gen2 and Blob Storage][databricks-docs-azure]. + +[Retrieve the storage account access key][azure-bs-docs-get-key] from your Azure +account and use as follows: + +```dotenv +CUBEJS_DB_EXPORT_BUCKET_TYPE=azure +CUBEJS_DB_EXPORT_BUCKET=wasbs://my-container@my-storage-account.blob.core.windows.net +CUBEJS_DB_EXPORT_BUCKET_AZURE_KEY= +``` + +Access key provides full access to the configuration and data, +to use a fine-grained control over access to storage resources, follow [the Databricks guide on authorize with Azure Active Directory][authorize-with-azure-active-directory]. + +[Create the service principal][azure-authentication-with-service-principal] and replace the access key as follows: + +```dotenv +CUBEJS_DB_EXPORT_BUCKET_AZURE_TENANT_ID= +CUBEJS_DB_EXPORT_BUCKET_AZURE_CLIENT_ID= +CUBEJS_DB_EXPORT_BUCKET_AZURE_CLIENT_SECRET= +``` + +## SSL/TLS + +Cube does not require any additional configuration to enable SSL/TLS for +Databricks JDBC connections. + +## Additional Configuration + +### Cube Cloud + +To accurately show partition sizes in the Cube Cloud APM, [an export +bucket][self-preaggs-export-bucket] **must be** configured. + +[aws-s3]: https://aws.amazon.com/s3/ +[azure-bs]: https://azure.microsoft.com/en-gb/services/storage/blobs/ +[azure-bs-docs-get-key]: + https://docs.microsoft.com/en-us/azure/storage/common/storage-account-keys-manage?toc=%2Fazure%2Fstorage%2Fblobs%2Ftoc.json&tabs=azure-portal#view-account-access-keys +[authorize-with-azure-active-directory]: + https://learn.microsoft.com/en-us/rest/api/storageservices/authorize-with-azure-active-directory +[azure-authentication-with-service-principal]: + https://learn.microsoft.com/en-us/azure/developer/java/sdk/identity-service-principal-auth +[databricks]: https://databricks.com/ +[databricks-docs-dbfs]: https://docs.databricks.com/en/dbfs/mounts.html +[databricks-docs-azure]: + https://docs.databricks.com/data/data-sources/azure/azure-storage.html +[databricks-docs-uc-s3]: + https://docs.databricks.com/en/connect/unity-catalog/index.html +[databricks-docs-uc-gcs]: + https://docs.databricks.com/gcp/en/connect/unity-catalog/cloud-storage.html +[databricks-docs-jdbc-url]: + https://docs.databricks.com/integrations/bi/jdbc-odbc-bi.html#get-server-hostname-port-http-path-and-jdbc-url +[databricks-docs-pat]: + https://docs.databricks.com/dev-tools/api/latest/authentication.html#token-management +[databricks-catalog]: https://docs.databricks.com/en/data-governance/unity-catalog/create-catalogs.html +[gh-cubejs-jdbc-install]: + https://github.com/cube-js/cube/blob/master/packages/cubejs-jdbc-driver/README.md#java-installation +[ref-caching-using-preaggs-build-strats]: /docs/pre-aggregations/using-pre-aggregations#pre-aggregation-build-strategies +[ref-schema-ref-types-formats-countdistinctapprox]: /reference/data-modeling/measures#type +[databricks-docs-approx-agg-fns]: https://docs.databricks.com/en/sql/language-manual/functions/approx_count_distinct.html +[self-preaggs-simple]: #simple +[self-preaggs-export-bucket]: #export-bucket +[ref-databricks-m2m-oauth]: https://docs.databricks.com/aws/en/dev-tools/auth/oauth-m2m \ No newline at end of file diff --git a/docs-mintlify/admin/connect-to-data/data-sources/druid.mdx b/docs-mintlify/admin/connect-to-data/data-sources/druid.mdx new file mode 100644 index 0000000000000..24a38471ed7aa --- /dev/null +++ b/docs-mintlify/admin/connect-to-data/data-sources/druid.mdx @@ -0,0 +1,46 @@ +--- +title: Druid +description: The driver for Druid is community-supported and is not maintained by Cube or the database vendor. +--- + + + +The driver for Druid is community-supported and is not maintained by Cube or the database vendor. + + + +## Prerequisites + +- The URL for the [Druid][druid] database +- The username/password for the [Druid][druid] database server + +## Setup + +### Manual + +Add the following to a `.env` file in your Cube project: + +```dotenv +CUBEJS_DB_TYPE=druid +CUBEJS_DB_URL=https://my.druid.host:8082 +CUBEJS_DB_USER=druid +CUBEJS_DB_PASS=********** +``` + +## Environment Variables + +| Environment Variable | Description | Possible Values | Required | +| -------------------- | ----------------------------------------------------------------------------------- | ------------------------------ | :------: | +| [`CUBEJS_DB_URL`](/reference/configuration/environment-variables#cubejs_db_url) | The URL for a database | A valid database URL for Druid | ✅ | +| [`CUBEJS_DB_USER`](/reference/configuration/environment-variables#cubejs_db_user) | The username used to connect to the database | A valid database username | ✅ | +| [`CUBEJS_DB_PASS`](/reference/configuration/environment-variables#cubejs_db_pass) | The password used to connect to the database | A valid database password | ✅ | +| [`CUBEJS_DB_MAX_POOL`](/reference/configuration/environment-variables#cubejs_db_max_pool) | The maximum number of concurrent database connections to pool. Default is `8` | A valid number | ❌ | +| [`CUBEJS_CONCURRENCY`](/reference/configuration/environment-variables#cubejs_concurrency) | The number of [concurrent queries][ref-data-source-concurrency] to the data source | A valid number | ❌ | + +[ref-data-source-concurrency]: /admin/connect-to-data/concurrency#data-source-concurrency +## SSL + +Cube does not require any additional configuration to enable SSL as Druid +connections are made over HTTPS. + +[druid]: https://druid.apache.org/ diff --git a/docs-mintlify/admin/connect-to-data/data-sources/duckdb.mdx b/docs-mintlify/admin/connect-to-data/data-sources/duckdb.mdx new file mode 100644 index 0000000000000..01e8e43f69ffe --- /dev/null +++ b/docs-mintlify/admin/connect-to-data/data-sources/duckdb.mdx @@ -0,0 +1,140 @@ +--- +title: DuckDB +description: Set up Cube with DuckDB for cloud object storage, local database files, or MotherDuck-backed hybrid query execution. +--- + +[DuckDB][duckdb] is an in-process SQL OLAP database management system, and has +support for querying data in CSV, JSON and Parquet formats from an AWS +S3-compatible blob storage. This means you can [query data stored in AWS S3, +Google Cloud Storage, or Cloudflare R2][duckdb-docs-s3-import]. +You can also use the [`CUBEJS_DB_DUCKDB_DATABASE_PATH`](/reference/configuration/environment-variables#cubejs_db_duckdb_database_path) environment variable to +connect to a local DuckDB database. + + + + + +Cube can also connect to [MotherDuck][motherduck], a cloud-based serverless +analytics platform built on DuckDB. When connected to MotherDuck, DuckDB uses +[hybrid execution][motherduck-docs-architecture] and routes queries to S3 +through MotherDuck for better performance. + + + + + +## Prerequisites + +- A set of IAM credentials which allow access to the S3-compatible data source. + Credentials are only required for private S3 buckets. +- The region of the bucket +- The name of a bucket to query data from + +## Setup + +### Manual + +Add the following to a `.env` file in your Cube project: + +```dotenv +CUBEJS_DB_TYPE=duckdb +``` + +### Cube Cloud + +In Cube Cloud, select **DuckDB** when creating a new deployment +and fill in the required fields: + + + Cube Cloud DuckDB Configuration Screen + + + + +If you are not using MotherDuck, leave the **MotherDuck Token** +field blank. + + + + + +You can also explore how DuckDB works with Cube if you create a [demo +deployment][ref-demo-deployment] in Cube Cloud. + + + +## Environment Variables + +| Environment Variable | Description | Possible Values | Required | +|--------------------------------------------|-----------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------|:--------:| +| [`CUBEJS_DB_DUCKDB_MEMORY_LIMIT`](/reference/configuration/environment-variables#cubejs_db_duckdb_memory_limit) | The maximum memory limit for DuckDB. Equivalent to `SET memory_limit=`. Default is 75% of available RAM | A valid memory limit | ❌ | +| [`CUBEJS_DB_DUCKDB_SCHEMA`](/reference/configuration/environment-variables#cubejs_db_duckdb_schema) | The [default search schema][link-duckdb-configuration-ref] | A valid schema name | ❌ | +| [`CUBEJS_DB_DUCKDB_MOTHERDUCK_TOKEN`](/reference/configuration/environment-variables#cubejs_db_duckdb_motherduck_token) | The service token to use for connections to MotherDuck | A valid [MotherDuck service token][motherduck-docs-svc-token] | ❌ | +| [`CUBEJS_DB_DUCKDB_DATABASE_PATH`](/reference/configuration/environment-variables#cubejs_db_duckdb_database_path) | The database filepath to use for connection to a local database. | A valid duckdb database file path | ❌ | +| `CUBEJS_DB_DUCKDB_S3_ACCESS_KEY_ID` | The Access Key ID to use for database connections | A valid Access Key ID | ❌ | +| `CUBEJS_DB_DUCKDB_S3_SECRET_ACCESS_KEY` | The Secret Access Key to use for database connections | A valid Secret Access Key | ❌ | +| `CUBEJS_DB_DUCKDB_S3_ENDPOINT` | The S3 endpoint | A valid [S3 endpoint][duckdb-docs-s3-import] | ❌ | +| `CUBEJS_DB_DUCKDB_S3_REGION` | The [region of the bucket][duckdb-docs-s3-import] | A valid AWS region | ❌ | +| `CUBEJS_DB_DUCKDB_S3_USE_SSL` | Use SSL for connection | A boolean | ❌ | +| `CUBEJS_DB_DUCKDB_S3_URL_STYLE` | To choose the S3 URL style(vhost or path) | `vhost` or `path` | ❌ | +| `CUBEJS_DB_DUCKDB_S3_SESSION_TOKEN` | The token for the S3 session | A valid Session Token | ❌ | +| [`CUBEJS_DB_DUCKDB_EXTENSIONS`](/reference/configuration/environment-variables#cubejs_db_duckdb_extensions) | A comma-separated list of DuckDB extensions to install and load | A comma-separated list of DuckDB extensions | ❌ | +| [`CUBEJS_DB_DUCKDB_COMMUNITY_EXTENSIONS`](/reference/configuration/environment-variables#cubejs_db_duckdb_community_extensions) | A comma-separated list of DuckDB community extensions to install and load | A comma-separated list of DuckDB community extensions | ❌ | +| `CUBEJS_DB_DUCKDB_S3_USE_CREDENTIAL_CHAIN` | A flag to use credentials chain for secrets for S3 connections | `true`, `false`. Defaults to `false` | ❌ | +| [`CUBEJS_CONCURRENCY`](/reference/configuration/environment-variables#cubejs_concurrency) | The number of [concurrent queries][ref-data-source-concurrency] to the data source | A valid number | ❌ | + +[ref-data-source-concurrency]: /admin/connect-to-data/concurrency#data-source-concurrency +## Pre-Aggregation Feature Support + +### count_distinct_approx + +Measures of type +[`count_distinct_approx`][ref-schema-ref-types-formats-countdistinctapprox] can +be used in pre-aggregations when using DuckDB as a source database. To learn +more about DuckDB's support for approximate aggregate functions, [click +here][duckdb-docs-approx-agg-fns]. + +## Pre-Aggregation Build Strategies + + + +To learn more about pre-aggregation build strategies, [head +here][ref-caching-using-preaggs-build-strats]. + + + +| Feature | Works with read-only mode? | Is default? | +| ------------- | :------------------------: | :---------: | +| Batching | ❌ | ✅ | +| Export Bucket | - | - | + +By default, DuckDB uses a [batching][self-preaggs-batching] strategy to build +pre-aggregations. + +### Batching + +No extra configuration is required to configure batching for DuckDB. + +### Export Bucket + +DuckDB does not support export buckets. + +## SSL + +Cube does not require any additional configuration to enable SSL as DuckDB +connections are made over HTTPS. + +[duckdb]: https://duckdb.org/ +[duckdb-docs-approx-agg-fns]: + https://duckdb.org/docs/sql/aggregates.html#approximate-aggregates +[duckdb-docs-s3-import]: https://duckdb.org/docs/guides/import/s3_import +[link-duckdb-configuration-ref]: https://duckdb.org/docs/sql/configuration.html#configuration-reference +[motherduck]: https://motherduck.com/ +[motherduck-docs-architecture]: + https://motherduck.com/docs/architecture-and-capabilities#hybrid-execution +[motherduck-docs-svc-token]: + https://motherduck.com/docs/authenticating-to-motherduck/#authentication-using-a-service-token +[ref-caching-using-preaggs-build-strats]: /docs/pre-aggregations/using-pre-aggregations#pre-aggregation-build-strategies +[ref-schema-ref-types-formats-countdistinctapprox]: /reference/data-modeling/measures#type +[self-preaggs-batching]: #batching +[ref-demo-deployment]: /admin/deployment#demo-deployments \ No newline at end of file diff --git a/docs-mintlify/admin/connect-to-data/data-sources/elasticsearch.mdx b/docs-mintlify/admin/connect-to-data/data-sources/elasticsearch.mdx new file mode 100644 index 0000000000000..ec4544d7707f0 --- /dev/null +++ b/docs-mintlify/admin/connect-to-data/data-sources/elasticsearch.mdx @@ -0,0 +1,75 @@ +--- +title: Elasticsearch +description: The driver for Elasticsearch is community-supported and is not maintained by Cube or the database vendor. +--- + + + +The driver for Elasticsearch is community-supported and is not maintained by Cube or the database vendor. + + + + + +Elasticsearch driver is deprecated and will be removed in a future release. + + + +## Prerequisites + +To connect to an [Elasticsearch][elasticsearch] database, use [`CUBEJS_DB_URL`](/reference/configuration/environment-variables#cubejs_db_url) +with the username and password embedded in the URL, if required. + + + +If you're not using [Elastic Cloud][elastic-cloud], you **must** specify +[`CUBEJS_DB_ELASTIC_QUERY_FORMAT`](/reference/configuration/environment-variables#cubejs_db_elastic_query_format). + + + +## Setup + +### Manual + +For a self-hosted Elasticsearch instance, add the following to a `.env` file in +your Cube project: + +```dotenv +CUBEJS_DB_TYPE=elasticsearch +CUBEJS_DB_URL=https://my.elasticsearch.host:9200 +CUBEJS_DB_ELASTIC_QUERY_FORMAT=json +``` + +For an Elasticsearch instanced hosted by [Elastic.co][elastic-co], add the +following to a `.env` file in your Cube project: + +```dotenv +CUBEJS_DB_TYPE=elasticsearch +CUBEJS_DB_URL=https://my.elasticsearch.host:9200 +CUBEJS_DB_ELASTIC_APIKEY_ID=VuaCfGcBCdbkQm-e5aOx +CUBEJS_DB_ELASTIC_APIKEY_KEY=ui2lp2axTNmsyakw9tvNnw +``` + +## Environment Variables + +| Environment Variable | Description | Possible Values | Required | +| -------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------- | :------: | +| [`CUBEJS_DB_URL`](/reference/configuration/environment-variables#cubejs_db_url) | The URL for a database | A valid database URL for Elasticsearch | ✅ | +| [`CUBEJS_DB_ELASTIC_QUERY_FORMAT`](/reference/configuration/environment-variables#cubejs_db_elastic_query_format) | By default, queries return data in JDBC format, but you can also return data in standard Elasticsearch JDBC, JSON, CSV, YAML or raw formats (only JSON and JDBC are currently supported) | `json`, `jdbc` | ❌ | +| [`CUBEJS_DB_ELASTIC_OPENDISTRO`](/reference/configuration/environment-variables#cubejs_db_elastic_opendistro) | If `true`, then use the Open Distro for Elasticsearch | `true`, `false` | ❌ | +| [`CUBEJS_DB_ELASTIC_APIKEY_ID`](/reference/configuration/environment-variables#cubejs_db_elastic_apikey_id) | [ID of the API key from elastic.co][elastic-docs-api-keys] | A valid Elastic.co API key ID | ❌ | +| [`CUBEJS_DB_ELASTIC_APIKEY_KEY`](/reference/configuration/environment-variables#cubejs_db_elastic_apikey_key) | [Value of the API key from elastic.co][elastic-docs-api-keys] | A valid Elastic.co API key value | ❌ | +| [`CUBEJS_DB_MAX_POOL`](/reference/configuration/environment-variables#cubejs_db_max_pool) | The maximum number of concurrent database connections to pool. Default is `8` | A valid number | ❌ | +| [`CUBEJS_CONCURRENCY`](/reference/configuration/environment-variables#cubejs_concurrency) | The number of [concurrent queries][ref-data-source-concurrency] to the data source | A valid number | ❌ | + +[ref-data-source-concurrency]: /admin/connect-to-data/concurrency#data-source-concurrency +## SSL + +Cube does not require any additional configuration to enable SSL as +Elasticsearch connections are made over HTTPS. + +[elastic-co]: https://elastic.co/ +[elastic-cloud]: https://cloud.elastic.co/ +[elasticsearch]: https://www.elastic.co/elasticsearch/ +[elastic-docs-api-keys]: + https://www.elastic.co/guide/en/kibana/master/api-keys.html#create-api-key diff --git a/docs-mintlify/admin/connect-to-data/data-sources/firebolt.mdx b/docs-mintlify/admin/connect-to-data/data-sources/firebolt.mdx new file mode 100644 index 0000000000000..a18696380a2f9 --- /dev/null +++ b/docs-mintlify/admin/connect-to-data/data-sources/firebolt.mdx @@ -0,0 +1,47 @@ +--- +title: Firebolt +description: "The driver for Firebolt is supported by its vendor. Please report any issues to their Help Center." +--- + + + +The driver for Firebolt is supported by its vendor. Please report any issues to +their [Help Center][firebolt-help]. + + + +## Prerequisites + +- The id/secret (client id/client secret) for your [Firebolt][firebolt] [service account][firebolt-service-accounts] + +## Setup + +### Manual + +Add the following to a `.env` file in your Cube project: + +```dotenv +CUBEJS_DB_NAME=firebolt_database +CUBEJS_DB_USER=aaaa-bbb-3244-wwssd +CUBEJS_DB_PASS=********** +CUBEJS_FIREBOLT_ACCOUNT=cube +CUBEJS_FIREBOLT_ENGINE_NAME=engine_name +``` + +## Environment Variables + +| Environment Variable | Description | Possible Values | Required | +| ------------------------------ | ----------------------------------------------------------------------------------- | ----------------------------------------------------------------------- | :------: | +| [`CUBEJS_DB_NAME`](/reference/configuration/environment-variables#cubejs_db_name) | The name of the database to connect to | A valid database name | ✅ | +| [`CUBEJS_DB_USER`](/reference/configuration/environment-variables#cubejs_db_user) | A service account ID for accessing Firebolt programmatically | A valid service id | ✅ | +| [`CUBEJS_DB_PASS`](/reference/configuration/environment-variables#cubejs_db_pass) | A service account secret for accessing Firebolt programmatically | A valid service secret | ✅ | +| [`CUBEJS_FIREBOLT_ACCOUNT`](/reference/configuration/environment-variables#cubejs_firebolt_account) | Account name | An account name | ✅ | +| [`CUBEJS_FIREBOLT_ENGINE_NAME`](/reference/configuration/environment-variables#cubejs_firebolt_engine_name) | Engine name to connect to | A valid engine name | ✅ | +| [`CUBEJS_FIREBOLT_API_ENDPOINT`](/reference/configuration/environment-variables#cubejs_firebolt_api_endpoint) | Firebolt API endpoint. Used for authentication | `api.dev.firebolt.io`, `api.staging.firebolt.io`, `api.app.firebolt.io` | - | +| [`CUBEJS_DB_MAX_POOL`](/reference/configuration/environment-variables#cubejs_db_max_pool) | The maximum number of concurrent database connections to pool. Default is `20` | A valid number | ❌ | +| [`CUBEJS_CONCURRENCY`](/reference/configuration/environment-variables#cubejs_concurrency) | The number of [concurrent queries][ref-data-source-concurrency] to the data source | A valid number | ❌ | + +[ref-data-source-concurrency]: /admin/connect-to-data/concurrency#data-source-concurrency +[firebolt]: https://www.firebolt.io/ +[firebolt-help]: https://help.firebolt.io/ +[firebolt-service-accounts]: https://docs.firebolt.io/godocs/Guides/managing-your-organization/service-accounts.html diff --git a/docs-mintlify/admin/connect-to-data/data-sources/google-bigquery.mdx b/docs-mintlify/admin/connect-to-data/data-sources/google-bigquery.mdx new file mode 100644 index 0000000000000..2419eabdbb7d9 --- /dev/null +++ b/docs-mintlify/admin/connect-to-data/data-sources/google-bigquery.mdx @@ -0,0 +1,188 @@ +--- +title: Google BigQuery +description: Grant a Google Cloud service account the right BigQuery IAM roles, then point Cube at your project, region, and key material. +--- + +## Prerequisites + + + +In order to connect Google BigQuery to Cube, you need to provide service account +credentials. Cube requires the service account to have **BigQuery Data Viewer** +and **BigQuery Job User** roles enabled. If you plan to use pre-aggregations, +the account will need the **BigQuery Data Editor** role instead of **BigQuery Data Viewer**. +You can learn more about acquiring +Google BigQuery credentials [here][bq-docs-getting-started]. +In Cube Cloud, you can authenticate with [OIDC workload identity +federation][ref-oidc-gcp-bigquery] instead of a key file — the same roles +apply to the impersonated service account. + + + +- The [Google Cloud Project ID][google-cloud-docs-projects] for the + [BigQuery][bq] project +- A set of [Google Cloud service credentials][google-support-create-svc-account] + which [allow access][bq-docs-getting-started] to the [BigQuery][bq] project +- The [Google Cloud region][bq-docs-regional-locations] for the [BigQuery][bq] + project + +## Setup + +### Manual + +Add the following to a `.env` file in your Cube project: + +```dotenv +CUBEJS_DB_TYPE=bigquery +CUBEJS_DB_BQ_PROJECT_ID=my-bigquery-project-12345 +CUBEJS_DB_BQ_KEY_FILE=/path/to/my/keyfile.json +``` + +You could also encode the key file using Base64 and set the result to +[`CUBEJS_DB_BQ_CREDENTIALS`](/reference/configuration/environment-variables#cubejs_db_bq_credentials): + +```dotenv +CUBEJS_DB_BQ_CREDENTIALS=$(cat /path/to/my/keyfile.json | base64) +``` + +### Cube Cloud + + + +In some cases you'll need to allow connections from your Cube Cloud deployment +IP address to your database. You can copy the IP address from either the +Database Setup step in deployment creation, or from **Settings → +Configuration** in your deployment. + + + +The following fields are required when creating a BigQuery connection: + + + Cube Cloud BigQuery Configuration Screen + + +#### OIDC workload identity federation + +Instead of a service account key file, Cube Cloud deployments can +authenticate to BigQuery with [OIDC workload identity +federation][ref-oidc-gcp-bigquery]: a Workload Identity Federation provider +in your GCP project trusts Cube's OIDC issuer, and the driver authenticates +through the GCP default credential chain — no JSON key to provision or +rotate. Select **OIDC workload identity federation** in the connection +wizard, or set the equivalent environment variables: + +```dotenv +CUBEJS_DB_TYPE=bigquery +CUBEJS_DB_BQ_PROJECT_ID=my-bigquery-project-12345 +GCP_POOL_AUDIENCE=//iam.googleapis.com/projects/123456789/locations/global/workloadIdentityPools/cube-pool/providers/cube +GCP_SERVICE_ACCOUNT_EMAIL=cube-deployment@my-bigquery-project-12345.iam.gserviceaccount.com +``` + +`GCP_SERVICE_ACCOUNT_EMAIL` selects the service account Cube impersonates; +leave it unset to authenticate as the federated principal directly. See the +[GCP OIDC guide][ref-oidc-gcp-bigquery] for the Workload Identity Pool, +provider, and IAM setup. + +Cube Cloud also supports connecting to data sources within private VPCs +if [single-tenant infrastructure][ref-dedicated-infra] is used. Check out the +[VPC connectivity guide][ref-cloud-conf-vpc] for details. + +[ref-dedicated-infra]: /admin/deployment/infrastructure#dedicated-infrastructure +[ref-cloud-conf-vpc]: /admin/deployment/dedicated +## Environment Variables + +| Environment Variable | Description | Possible Values | Required | +| ------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------- | :------: | +| [`CUBEJS_DB_BQ_PROJECT_ID`](/reference/configuration/environment-variables#cubejs_db_bq_project_id) | The Google BigQuery project ID to connect to | A valid Google BigQuery Project ID | ✅ | +| [`CUBEJS_DB_BQ_KEY_FILE`](/reference/configuration/environment-variables#cubejs_db_bq_key_file) | The path to a JSON key file for connecting to Google BigQuery | A valid Google BigQuery JSON key file | ✅1 | +| [`CUBEJS_DB_BQ_CREDENTIALS`](/reference/configuration/environment-variables#cubejs_db_bq_credentials) | A Base64 encoded JSON key file for connecting to Google BigQuery | A valid Google BigQuery JSON key file encoded as a Base64 string | ❌ | +| [`CUBEJS_DB_BQ_LOCATION`](/reference/configuration/environment-variables#cubejs_db_bq_location) | The Google BigQuery dataset location to connect to. Required if used with pre-aggregations outside of US. If not set then BQ driver will fail with `Dataset was not found in location US` error | [A valid Google BigQuery regional location][bq-docs-regional-locations] | ⚠️ | +| [`CUBEJS_DB_EXPORT_BUCKET`](/reference/configuration/environment-variables#cubejs_db_export_bucket) | The name of a bucket in cloud storage | A valid bucket name from cloud storage | ❌ | +| [`CUBEJS_DB_EXPORT_BUCKET_TYPE`](/reference/configuration/environment-variables#cubejs_db_export_bucket_type) | The cloud provider where the bucket is hosted | `gcp` | ❌ | +| [`CUBEJS_DB_MAX_POOL`](/reference/configuration/environment-variables#cubejs_db_max_pool) | The maximum number of concurrent database connections to pool. Default is `40` | A valid number | ❌ | +| [`CUBEJS_CONCURRENCY`](/reference/configuration/environment-variables#cubejs_concurrency) | The number of [concurrent queries][ref-data-source-concurrency] to the data source | A valid number | ❌ | + +1 Not required when authenticating with [OIDC workload identity +federation][ref-oidc-gcp-bigquery] in Cube Cloud, or when providing the key +material via [`CUBEJS_DB_BQ_CREDENTIALS`](/reference/configuration/environment-variables#cubejs_db_bq_credentials). + +[ref-data-source-concurrency]: /admin/connect-to-data/concurrency#data-source-concurrency +## Pre-Aggregation Feature Support + +### count_distinct_approx + +Measures of type +[`count_distinct_approx`][ref-schema-ref-types-formats-countdistinctapprox] can +be used in pre-aggregations when using Google BigQuery as a source database. To +learn more about Google BigQuery's support for approximate aggregate functions, +[click here][bq-docs-approx-agg-fns]. + +## Pre-Aggregation Build Strategies + + + +To learn more about pre-aggregation build strategies, [head +here][ref-caching-using-preaggs-build-strats]. + + + +| Feature | Works with read-only mode? | Is default? | +| ------------- | :------------------------: | :---------: | +| Batching | ❌ | ✅ | +| Export Bucket | ❌ | ❌ | + +By default, Google BigQuery uses [batching][self-preaggs-batching] to build +pre-aggregations. + +### Batching + +No extra configuration is required to configure batching for Google BigQuery. + +### Export bucket + + + +BigQuery only supports using Google Cloud Storage for export buckets. + + + +#### Google Cloud Storage + +For [improved pre-aggregation performance with large +datasets][ref-caching-large-preaggs], enable export bucket functionality by +configuring Cube with the following environment variables: + + + +When using an export bucket, remember to assign the **BigQuery Data Editor** and +**Storage Object Admin** role to your BigQuery service account. + + + +```dotenv +CUBEJS_DB_EXPORT_BUCKET=export_data_58148478376 +CUBEJS_DB_EXPORT_BUCKET_TYPE=gcp +``` + +## SSL + +Cube does not require any additional configuration to enable SSL as Google +BigQuery connections are made over HTTPS. + +[bq]: https://cloud.google.com/bigquery +[bq-docs-getting-started]: + https://cloud.google.com/docs/authentication/getting-started +[bq-docs-regional-locations]: + https://cloud.google.com/bigquery/docs/locations#regional-locations +[bq-docs-approx-agg-fns]: + https://cloud.google.com/bigquery/docs/reference/standard-sql/approximate_aggregate_functions +[google-cloud-docs-projects]: + https://cloud.google.com/resource-manager/docs/creating-managing-projects#before_you_begin +[google-support-create-svc-account]: + https://support.google.com/a/answer/7378726?hl=en +[ref-caching-large-preaggs]: /docs/pre-aggregations/using-pre-aggregations#export-bucket +[ref-caching-using-preaggs-build-strats]: /docs/pre-aggregations/using-pre-aggregations#pre-aggregation-build-strategies +[ref-oidc-gcp-bigquery]: /admin/deployment/oidc/gcp#bigquery +[ref-schema-ref-types-formats-countdistinctapprox]: /reference/data-modeling/measures#type +[self-preaggs-batching]: #batching diff --git a/docs-mintlify/admin/connect-to-data/data-sources/hive.mdx b/docs-mintlify/admin/connect-to-data/data-sources/hive.mdx new file mode 100644 index 0000000000000..0c36c2ba341e0 --- /dev/null +++ b/docs-mintlify/admin/connect-to-data/data-sources/hive.mdx @@ -0,0 +1,48 @@ +--- +title: Hive / SparkSQL +description: The driver for Hive / SparkSQL is community-supported and is not maintained by Cube or the database vendor. +--- + + + +The driver for Hive / SparkSQL is community-supported and is not maintained by Cube or the database vendor. + + + +## Prerequisites + +- The hostname for the [Hive][hive] database server +- The username/password for the [Hive][hive] database server + +## Setup + +### Manual + +Add the following to a `.env` file in your Cube project: + +```dotenv +CUBEJS_DB_TYPE=hive +CUBEJS_DB_HOST=my.hive.host +CUBEJS_DB_NAME=my_hive_database +CUBEJS_DB_USER=hive_user +CUBEJS_DB_PASS=********** +``` + +## Environment Variables + +| Environment Variable | Description | Possible Values | Required | +| --------------------------- | ----------------------------------------------------------------------------------- | ------------------------- | :------: | +| [`CUBEJS_DB_HOST`](/reference/configuration/environment-variables#cubejs_db_host) | The host URL for a database | A valid database host URL | ✅ | +| [`CUBEJS_DB_PORT`](/reference/configuration/environment-variables#cubejs_db_port) | The port for the database connection | A valid port number | ❌ | +| [`CUBEJS_DB_NAME`](/reference/configuration/environment-variables#cubejs_db_name) | The name of the database to connect to | A valid database name | ✅ | +| [`CUBEJS_DB_USER`](/reference/configuration/environment-variables#cubejs_db_user) | The username used to connect to the database | A valid database username | ✅ | +| [`CUBEJS_DB_PASS`](/reference/configuration/environment-variables#cubejs_db_pass) | The password used to connect to the database | A valid database password | ✅ | +| [`CUBEJS_DB_HIVE_TYPE`](/reference/configuration/environment-variables#cubejs_db_hive_type) | | | ❌ | +| [`CUBEJS_DB_HIVE_VER`](/reference/configuration/environment-variables#cubejs_db_hive_ver) | | | ❌ | +| [`CUBEJS_DB_HIVE_THRIFT_VER`](/reference/configuration/environment-variables#cubejs_db_hive_thrift_ver) | | | ❌ | +| [`CUBEJS_DB_HIVE_CDH_VER`](/reference/configuration/environment-variables#cubejs_db_hive_cdh_ver) | | | ❌ | +| [`CUBEJS_DB_MAX_POOL`](/reference/configuration/environment-variables#cubejs_db_max_pool) | The maximum number of concurrent database connections to pool. Default is `8` | A valid number | ❌ | +| [`CUBEJS_CONCURRENCY`](/reference/configuration/environment-variables#cubejs_concurrency) | The number of [concurrent queries][ref-data-source-concurrency] to the data source | A valid number | ❌ | + +[ref-data-source-concurrency]: /admin/connect-to-data/concurrency#data-source-concurrency +[hive]: https://hive.apache.org/ diff --git a/docs-mintlify/admin/connect-to-data/data-sources/index.mdx b/docs-mintlify/admin/connect-to-data/data-sources/index.mdx new file mode 100644 index 0000000000000..49fa42ffbcc8b --- /dev/null +++ b/docs-mintlify/admin/connect-to-data/data-sources/index.mdx @@ -0,0 +1,187 @@ +--- +description: Choose and configure a data warehouse, query engine, or other data source to connect to Cube. +title: Data Sources +sidebarTitle: Overview +mode: wide +--- + +Cube connects directly to your data warehouse or database. Select your data +source below to get started with the setup process. + +You can also connect [multiple data sources][ref-config-multi-data-src] at the same +time and adjust the [concurrency settings][ref-data-source-concurrency] for data +sources. + +## Data warehouses + + + + Connect to Amazon Redshift. + + + Connect to Google BigQuery. + + + Connect to Snowflake. + + + Connect to Databricks. + + + Connect to Microsoft Fabric. + + + Connect to ClickHouse. + + + Connect to SingleStore. + + + Connect to Apache Pinot. + + + Connect to Firebolt. + + + Connect to Vertica. + + + +## Query engines + + + + Connect to Amazon Athena. + + + Connect to DuckDB or MotherDuck. + + + Connect to Hive or SparkSQL. + + + Connect to Presto. + + + Connect to Trino. + + + +## Transactional databases + + + + Connect to Postgres. + + + Connect to Microsoft SQL Server. + + + Connect to MySQL. + + + Connect to Oracle. + + + Connect to SQLite. + + + +## Time series & streaming + + + + Connect to QuestDB. + + + Connect to ksqlDB. + + + Connect to Materialize. + + + Connect to RisingWave. + + + +## Other data sources + + + + Connect to Elasticsearch. + + + Connect to MongoDB. + + + Connect to Apache Druid. + + + Query Parquet files via DuckDB. + + + Query CSV files via DuckDB. + + + Query JSON files via DuckDB. + + + +### API endpoints + +Cube is designed to work with data sources that allow querying them with SQL. + +Cube is not designed to access data files directly or fetch data from REST, +or GraphQL, or any other API. To use Cube in that way, you either need to use +a supported data source (e.g., use [DuckDB][ref-duckdb] to query Parquet files +on Amazon S3) or create a [custom data source driver](#currently-unsupported-data-sources). + +## Data source drivers + +### Driver support + +Most of the drivers for data sources are supported either directly by the Cube +team or by their vendors. The rest are community-supported and will be +highlighted as such in their respective pages. + +You can find the [source code][link-github-packages] of the drivers that are part +of the Cube distribution in `cubejs-*-driver` folders on GitHub. + +### Third-party drivers + +The following drivers were contributed by the Cube community. They are not part +of the Cube distribution, however, they can still be used with Cube: + +- [ArangoDB](https://www.npmjs.com/package/arangodb-cubejs-driver) +- [CosmosDB](https://www.npmjs.com/package/cosmosdb-cubejs-driver) +- [CrateDB](https://www.npmjs.com/package/cratedb-cubejs-driver) +- [Dremio](https://www.npmjs.com/package/mydremio-cubejs-driver) +- [Dremio ODBC](https://www.npmjs.com/package/dremio-odbc-cubejs-driver) +- [OpenDistro Elastic](https://www.npmjs.com/package/opendistro-cubejs-driver) +- [SAP Hana](https://www.npmjs.com/package/cubejs-hana-driver) +- [Trino](https://www.npmjs.com/package/trino-cubejs-driver) +- [Vertica](https://www.npmjs.com/package/@knowitall/vertica-driver) + +You need to configure [`driver_factory`][ref-driver-factory] to use a third-party +driver. + +### Currently unsupported data sources + +If you'd like to connect to a data source which is not yet listed on this page, +please see the list of [requested drivers](https://github.com/cube-js/cube/issues/7076) +and [file an issue](https://github.com/cube-js/cube/issues) on GitHub. + +You're more than welcome to contribute new drivers as well as new features and +patches to +[existing drivers](https://github.com/cube-js/cube/tree/master/packages). Please +check the +[contribution guidelines](https://github.com/cube-js/cube/blob/master/CONTRIBUTING.md#contributing-database-drivers) +and join the `#contributing-to-cube` channel in our +[Slack community](https://slack.cube.dev). + + +[ref-config-multi-data-src]: /admin/connect-to-data/multiple-data-sources +[ref-driver-factory]: /reference/configuration/config#driver_factory +[ref-duckdb]: /admin/connect-to-data/data-sources/duckdb +[link-github-packages]: https://github.com/cube-js/cube/tree/master/packages +[ref-data-source-concurrency]: /admin/connect-to-data/concurrency#data-sources diff --git a/docs-mintlify/admin/connect-to-data/data-sources/ksqldb.mdx b/docs-mintlify/admin/connect-to-data/data-sources/ksqldb.mdx new file mode 100644 index 0000000000000..0d93eb80436c8 --- /dev/null +++ b/docs-mintlify/admin/connect-to-data/data-sources/ksqldb.mdx @@ -0,0 +1,995 @@ +--- +title: ksqlDB +description: ksqlDB is a purpose-built database for stream processing applications, ingesting data from Apache Kafka. +--- + +[ksqlDB](https://ksqldb.io) is a purpose-built database for stream processing +applications, ingesting data from [Apache Kafka](https://kafka.apache.org). + + + +Available on the [Enterprise plan](https://cube.dev/pricing). +[Contact us](https://cube.dev/contact) for details. + + + +See how you can use ksqlDB and Cube Cloud to power real-time analytics in Power BI: + + +``` + +Users will be prompted to sign in with their Cube credentials when accessing the embedded chat. See [Private embedding](/embedding/iframe/auth/private) for details on the auth model. + +## Embed with signed embedding + +To embed Analytics Chat for external/customer-facing applications, generate a session on your backend and pass the session ID into the iframe: + +```html + +``` + +See [Signed embedding](/embedding/iframe/auth/signed) for the full session generation flow, API key setup, and a complete working example. + +## Personalize chat with user attributes + +When using signed embedding, you can pass [user attributes](/embedding/iframe/auth/signed#user-attributes) during session generation to personalize chat responses for each user — for example, scoping answers to a specific region, department, or tenant. diff --git a/docs-mintlify/embedding/iframe/auth/private.mdx b/docs-mintlify/embedding/iframe/auth/private.mdx new file mode 100644 index 0000000000000..ac434356fae5c --- /dev/null +++ b/docs-mintlify/embedding/iframe/auth/private.mdx @@ -0,0 +1,70 @@ +--- +title: Private embedding +description: Authenticate iframe-embedded Cube content with users' existing Cube accounts. +--- + + + Private embedding is available on [Premium and Enterprise plans](https://cube.dev/pricing). + + +Private embedding is designed for **internal use cases** where team members already have Cube accounts. Simply drop an iframe into your internal tools — no API keys or session generation required. Users authenticate with their existing Cube credentials when accessing embedded content. + +Use private embedding to embed: + +- [Dashboards](/embedding/iframe/dashboards) +- [Analytics Chat](/embedding/iframe/analytics-chat) + + + Private embedding does not support [Creator Mode](/embedding/iframe/creator-mode) — use [Signed embedding](/embedding/iframe/auth/signed) instead. + + +## How it works + +To embed Cube content with private embedding, paste an ` + +``` + +## Security + +Private embedding uses Cube's built-in authentication. Users must: + +- Have an active Cube account +- Be signed in to Cube (or will be prompted to sign in) +- Have appropriate permissions to view the embedded content + +Access control is managed through your existing Cube [roles and permissions](/admin/users-and-permissions/roles-and-permissions) settings. diff --git a/docs-mintlify/embedding/iframe/auth/signed.mdx b/docs-mintlify/embedding/iframe/auth/signed.mdx new file mode 100644 index 0000000000000..b4051680a7ed6 --- /dev/null +++ b/docs-mintlify/embedding/iframe/auth/signed.mdx @@ -0,0 +1,186 @@ +--- +title: Signed embedding +description: Authenticate iframe-embedded Cube content with secure, server-generated sessions. +--- + + + Signed embedding is available on [Premium and Enterprise plans](https://cube.dev/pricing). + + +Signed embedding is designed for **external, customer-facing analytics**. It uses secure, server-generated sessions for authentication, making it ideal for: + +- Embedding analytics in your SaaS application for customers +- White-label analytics solutions +- Multi-tenant applications where each customer sees their own data +- Public-facing dashboards with controlled access + +Users authenticate through your application without needing Cube accounts, providing a seamless experience. The session tokens are cryptographically signed to ensure secure access with user-specific permissions. + +Use signed embedding to embed: + +- [Dashboards](/embedding/iframe/dashboards) +- [Analytics Chat](/embedding/iframe/analytics-chat) +- [Creator Mode](/embedding/iframe/creator-mode) (signed embedding is required) + +## How it works + +Signed embedding works through a two-step authentication flow: + +1. **Generate a session** – Your backend generates a temporary session using the Cube API +2. **Exchange for a token** – The iframe automatically exchanges the session for a long-lived access token + +**Session lifecycle:** +- **Sessions** are valid for **5 minutes** and must be exchanged within this window +- **Tokens** are valid for **24 hours** after exchange +- Sessions are single-use and expire after being exchanged + +This ensures secure authentication while maintaining a smooth user experience. + +## Getting started + +### Get your API key + +To use signed embedding, you need an [API key][ref-api-keys]: + +- Go to **Access → API Keys** in your Cube admin panel +- Generate or copy your existing API key +- You'll use this key to authenticate API calls for generating embed sessions + +### Generate an embed session + +Use the [Generate Session API][ref-generate-session] to create a session for your user. This endpoint will automatically create (insert) or update the external user based on the `externalId` provided. + + + Accounts are limited to 10,000 external users. To increase this limit, please + contact support. + + +#### Example (JavaScript) + +```javascript +const API_KEY = "YOUR_API_KEY"; +const DEPLOYMENT_ID = 32; + +const session = await fetch( + "https://your-account.cubecloud.dev/api/v1/embed/generate-session", + { + method: "POST", + headers: { + "Content-Type": "application/json", + Authorization: "Api-Key ${API_KEY}", + }, + body: JSON.stringify({ + deploymentId: DEPLOYMENT_ID, + externalId: "user@example.com", + userAttributes: [ + // optional - enables row-level security + { + name: "city", + value: "San Francisco", + }, + { + name: "department", + value: "Sales", + }, + ], + }), + }, +); + +const data = await session.json(); +const sessionId = data.sessionId; +``` + +### Embed via iframe + +Use the session ID to embed the dashboard or chat UI in your application. See [Dashboards](/embedding/iframe/dashboards) and [Analytics Chat](/embedding/iframe/analytics-chat) for the full iframe snippets. + +#### Complete example + +Here's a complete HTML example that demonstrates the full flow for embedding a dashboard: + +```html + + + + + + + + + +``` + +## User attributes + +User attributes enable row-level security and personalized chat responses by filtering data based on user permissions. The attributes you pass during session generation automatically filter data queries and responses. + + + User attributes must first be configured in your Cube admin panel. See the + [User Attributes documentation](/admin/users-and-permissions/user-attributes) for + setup instructions. + + +**How it works:** + +1. **Configure attributes** in your admin panel (e.g., `city`, `department`) +2. **Pass attributes** during session generation +3. **Data is automatically filtered** based on user permissions through access policies +4. **AI responses are personalized** to the user's context + +**Example use cases:** + +- Sales reps only see data for their assigned territory +- Regional managers see data filtered by their city +- Department heads see only their department's metrics + +## Example application + +For a complete working example of signed embedding, check out the [cube-embedding-demo](https://github.com/cubedevinc/cube-embedding-demo) repository. This demo application provides: + +- A full working example of iframe embedding +- Implementation of signed iframe embedding with session generation +- A React-based UI for testing embedding functionality +- Backend server that securely handles API key authentication + +You can clone the repository, configure it with your Cube credentials, and run it locally to test embedding functionality or use it as a reference implementation for your own application. + +[ref-api-keys]: /admin/account-billing/api-keys +[ref-generate-session]: /reference/embed-apis/generate-session diff --git a/docs-mintlify/embedding/iframe/creator-mode.mdx b/docs-mintlify/embedding/iframe/creator-mode.mdx new file mode 100644 index 0000000000000..d4d5f49736c96 --- /dev/null +++ b/docs-mintlify/embedding/iframe/creator-mode.mdx @@ -0,0 +1,99 @@ +--- +title: Creator Mode +description: Embed the full Cube application so users can build and modify their own dashboards. +--- + + + Creator Mode is available on the [Enterprise plan](https://cube.dev/pricing). + + +Creator Mode embeds the full Cube application instead of an individual dashboard or chat. Users can create and modify workbooks, dashboards, and reports inside the iframe. + +To enable it, pass `creatorMode: true` to the [Generate Session API][ref-generate-session]. + + + Creator Mode requires [Signed embedding](/embedding/iframe/auth/signed). Private embedding is not supported. + + +## Embed tenant scoping + +In Creator Mode, content (workbooks, dashboards) and the groups/user attributes referenced by the session are scoped to an **embed tenant**. Pass `embedTenantName` to isolate content per customer; omit it to use the current tenant. + +`embedTenantName` must be lowercase, 5–36 chars, start with a letter, end with a letter or digit, and contain only `a-z`, `0-9`, or `-`. + +## Provisioning groups and user attributes + +In Creator Mode, `groups` and `userAttributes` resolve against the embed tenant's scoped catalog (separate from the tenant-wide one used by read-only embedding). To define those entries from your backend in the same call, pass `groupDefinitions` and `userAttributeDefinitions` — they are idempotent and validated before memberships and values are applied. + +See [Generate Session → Creator mode bootstrap][ref-bootstrap] for the input shape, value types, and the immutable-`type` rule on attribute definitions. + +## Default dashboards + +You can pre-populate every embed user's workspace with ready-made content so they see useful dashboards the first time they open the embedded app, instead of an empty workspace. This is a good way to ship templates or starter reports that your users can explore and build on. + +Default dashboards are shared from your **main workspace** with the **All embed users** (`all_embed_users`) group — a system group that Cube creates automatically once Creator Mode is enabled. Sharing is read-only: embed users can open and explore the shared content but can't edit it. + +To set up default dashboards: + +1. Build the workbooks, dashboards, folders, and reports you want everyone to see in your main workspace. +2. Open the share dialog for a workbook or folder and share it with **All embed users**. The only available access level is **Can view**. +3. Embed users in Creator Mode now see the shared items at the root of their workspace as soon as they open the app. + + + **All embed users** is a system group: it can't be renamed or deleted, and it can only be granted read-only (**Can view**) access. It appears automatically in **Admin → User Groups** and in the share dialog once Creator Mode is enabled for your workspace. + + +Keep the following behavior in mind: + +- **Sharing a folder** shares everything inside it — all nested folders, workbooks, and reports become available to embed users. +- **Sharing a single workbook or report** exposes that item plus the folders above it (so users can navigate to it), but not the other contents of those folders. +- All embed users see the **same** default dashboards, regardless of their [groups](/admin/users-and-permissions/user-groups) or user attributes. The shared set applies across every embed tenant that belongs to your account. +- Embed users can't edit content shared from the main workspace. Opening a shared workbook shows its published dashboard, so a workbook must have a published dashboard for users to open it. +- Removing the share from the **All embed users** group removes those items from embed users' workspaces immediately. + +## Sharing workbooks and dashboards + +Embed users in Creator Mode can share the workbooks and dashboards they build with other users, the same way they would in the full Cube app. + + + Sharing is scoped to the [embed tenant](#embed-tenant-scoping): users can only share with others in the same tenant, never across tenants. + + +## Example + +```javascript +const session = await fetch( + "https://your-account.cubecloud.dev/api/v1/embed/generate-session", + { + method: "POST", + headers: { + "Content-Type": "application/json", + Authorization: `Api-Key ${API_KEY}`, + }, + body: JSON.stringify({ + deploymentId: 32, + externalId: "user@example.com", + embedTenantName: "acme-corp", + creatorMode: true, + }), + }, +); + +const { sessionId } = await session.json(); +``` + +Embed the app with the returned session ID: + +```html + +``` + +For a complete working example, see the [cube-embedding-demo](https://github.com/cubedevinc/cube-embedding-demo) repository. + +[ref-generate-session]: /reference/embed-apis/generate-session +[ref-bootstrap]: /reference/embed-apis/generate-session#creator-mode-bootstrapping-groups-and-user-attributes diff --git a/docs-mintlify/embedding/iframe/customization.mdx b/docs-mintlify/embedding/iframe/customization.mdx new file mode 100644 index 0000000000000..3bcece8cf2cfd --- /dev/null +++ b/docs-mintlify/embedding/iframe/customization.mdx @@ -0,0 +1,76 @@ +--- +title: Customization +description: Customize the appearance of embedded dashboards and the embedded Cube app. +--- + +You can customize the appearance of iframe-embedded Cube content in two ways: + +- **[Dashboard customization](#dashboard-customization)** — style an individual [dashboard](/embedding/iframe/dashboards) using the Styling panel in the Dashboard Builder +- **[App customization](#app-customization)** — pass theme parameters to the [Generate Session API](/reference/embed-apis/generate-session) when embedding the full Cube app in [Creator Mode](/embedding/iframe/creator-mode) + + + Customization options will expand over time. This page documents what is supported today. + + + + To set the language of embedded surfaces — account-wide, per embed, or at runtime — see [Localization](/embedding/iframe/localization). + + + + To brand the whole embedded experience — accent color, background, text, logo, and fonts — at the account level, configure the [app theme](/admin/customization/app-theme). It applies to all embedded surfaces automatically (and, optionally, to the entire Cube Cloud console). + + +## Dashboard customization + +Style an individual dashboard from the **Styling** panel in the Dashboard Builder. Settings are saved per-dashboard and apply equally to the dashboard in Cube and to its embedded view. + +See [Dashboards → Styling](/docs/explore-analyze/dashboards/styling) for the full list of options. + +## App customization + +When embedding the full Cube app in [Creator Mode](/embedding/iframe/creator-mode), pass an `embedTheme` object to the [Generate Session API](/reference/embed-apis/generate-session) to customize the appearance of the embedded experience. + +The `embedTheme` is scoped to the embed session — it is applied while the user is viewing the embedded app and reset on the next session generation. + +### Example + +```javascript +const session = await fetch( + "https://your-account.cubecloud.dev/api/v1/embed/generate-session", + { + method: "POST", + headers: { + "Content-Type": "application/json", + Authorization: `Api-Key ${API_KEY}`, + }, + body: JSON.stringify({ + deploymentId: DEPLOYMENT_ID, + externalId: "user@example.com", + creatorMode: true, + tenantId: "tenant-123", + tenantName: "Acme Corporation", + embedTheme: { + analyticsChat: { + backgroundColor: "#f4f4f5", + chatInput: { + backgroundColor: "#ffffff", + borderColor: "#e4e4e7", + }, + }, + }, + }), + }, +); +``` + +### Parameters + +The following `embedTheme` parameters are currently supported: + +| Parameter | Type | Description | Example | +|-------------------------------------------------|----------|--------------------------------------------------------|---------------| +| `analyticsChat.backgroundColor` | `string` | Background color of the Analytics Chat panel. | `"#f4f4f5"` | +| `analyticsChat.chatInput.backgroundColor` | `string` | Background color of the chat input field. | `"#ffffff"` | +| `analyticsChat.chatInput.borderColor` | `string` | Border color of the chat input field. | `"#e4e4e7"` | + +All values accept standard CSS color formats (hex, `rgb()`, named colors). diff --git a/docs-mintlify/embedding/iframe/dashboards.mdx b/docs-mintlify/embedding/iframe/dashboards.mdx new file mode 100644 index 0000000000000..e8430459fda47 --- /dev/null +++ b/docs-mintlify/embedding/iframe/dashboards.mdx @@ -0,0 +1,100 @@ +--- +title: Dashboards +description: Embed Cube dashboards into your applications via iframe. +--- + + + Iframe embedding is available on [Premium and Enterprise plans](https://cube.dev/pricing). + + +Embed any [dashboard](/docs/explore-analyze/dashboards) into your application using an iframe. Dashboards can be embedded with either authentication mode: + +- **[Private embedding](/embedding/iframe/auth/private)** — for internal users with Cube accounts (e.g., embedding in Notion, Salesforce, internal tools) +- **[Signed embedding](/embedding/iframe/auth/signed)** — for external/customer-facing applications using server-generated sessions + +## Embed with private embedding + +To embed a dashboard for internal users: + +1. Open your dashboard in Cube +2. Click **Share** → **Embed** +3. Copy the generated iframe code + +Share embed dialog + +Then paste the iframe code into your application: + +```html + +``` + +Users will be prompted to sign in with their Cube credentials when accessing the embedded dashboard. See [Private embedding](/embedding/iframe/auth/private) for details on the auth model and integration examples (Notion, Salesforce). + +## Embed with signed embedding + +To embed a dashboard for external/customer-facing applications, generate a session on your backend and pass the session ID into the iframe: + +```html + +``` + +See [Signed embedding](/embedding/iframe/auth/signed) for the full session generation flow, API key setup, and a complete working example. + +## Pre-set dashboard filters via URL + +You can pre-set dashboard filter values by adding URL parameters in the format +`?f_.=`. The `` and `` +must match the internal names (not display titles) of the semantic view and +dimension configured on the filter widget. If the filter type is omitted, it +defaults to `equals`. + +Example: + +```text +https://your-tenant.cubecloud.dev/embed/dashboard/YOUR_DASHBOARD_PUBLIC_ID?session=YOUR_SESSION_ID&f_orders_transactions.users_country={"value":"USA"} +``` + +This works on both regular and published (embedded) dashboards. The filter is +only applied if a matching filter widget for that dimension already exists on the +dashboard. + +## Allow CSV export + +By default, embedded dashboards do not expose a download action on individual +widgets. To let viewers download a chart widget's data as a CSV file, add the +`allowExport=true` query parameter to the embed URL: + +```text +https://your-tenant.cubecloud.dev/embed/dashboard/YOUR_DASHBOARD_PUBLIC_ID?session=YOUR_SESSION_ID&allowExport=true +``` + +When enabled, each chart widget's ⋮ menu shows a **Download as CSV** action. The +CSV is generated client-side from the data already loaded into the widget, so no +additional query is issued. The parameter is opt-in — omit it (the default) to +keep the download action hidden. + +## Set the language + +Embedded dashboards render their UI in the account's default language, which you can +override per embed by adding the `?locale=` query parameter: + +```text +https://your-tenant.cubecloud.dev/embed/dashboard/YOUR_DASHBOARD_PUBLIC_ID?session=YOUR_SESSION_ID&locale=es-MX +``` + +See [Localization](/embedding/iframe/localization) for the list of supported languages +and the other ways to set the language. + +## Customize appearance + +You can style an embedded dashboard — background, padding, widget borders, titles, and fonts — from the **Styling** panel in the Dashboard Builder. See [Dashboards → Styling](/docs/explore-analyze/dashboards/styling) for the full list of options. diff --git a/docs-mintlify/embedding/iframe/events.mdx b/docs-mintlify/embedding/iframe/events.mdx new file mode 100644 index 0000000000000..1aa5aa0fc3b04 --- /dev/null +++ b/docs-mintlify/embedding/iframe/events.mdx @@ -0,0 +1,468 @@ +--- +title: Events & actions +description: Listen to user-interaction events from an embedded Cube iframe and send actions back into it, over the browser postMessage API. +--- + + + +Available on [Premium and above plans](https://cube.dev/pricing). + + + +Embedded Cube surfaces communicate with your host page over the browser +[`postMessage`](https://developer.mozilla.org/docs/Web/API/Window/postMessage) +API, in both directions: + +- **Events** (`cube:event:*`) travel **embed → host**. Subscribe to them to learn + how a viewer interacts with the embed — when it loads, what they view, + download, drill into, search for with AI, and any errors they hit. Feed them + into your own analytics / event bus. +- **Actions** (`cube:action:*`) travel **host → embed**. Send them to drive the + embed from your app — switch the color scheme, set a filter, navigate, or + refresh the data. + +No SDK is required — it's plain `window.postMessage` and a `message` listener. + +## Message envelope + +Every message — in either direction — is a single object with the same shape: + +```ts +{ + source: "cube-embed", // discriminator — always this string + direction: "event" | "action", // "event" = embed→host, "action" = host→embed + type: string, // e.g. "cube:event:download" / "cube:action:set-filter" + payload: object, // shape depends on `type` (see catalogs below) + timestamp: number, // epoch milliseconds + surface?: "dashboard" | "app" | "chat" // always on events; never on actions +} +``` + +| Field | Description | +| --- | --- | +| `source` | Always `"cube-embed"`. Check this first to tell Cube messages apart from other `postMessage` traffic on the page (browser extensions, other libraries, your own app). | +| `direction` | `"event"` for messages emitted by the embed, `"action"` for messages you send into it. | +| `type` | The event or action name (see the catalogs below). | +| `payload` | Event/action-specific data. | +| `timestamp` | When the message was created, in epoch milliseconds. | +| `surface` | Which embedded surface the message relates to. **Always present on events**; never sent on actions — so event listeners never need to handle a missing `surface`. | + +## Listening to events + +Attach a single `message` listener to `window`. Always validate `event.origin` +against your tenant's origin and check `data.source === "cube-embed"` before +trusting a message. + +```js +const CUBE_ORIGIN = "https://your-tenant.cubecloud.dev"; + +window.addEventListener("message", (event) => { + // 1. Only trust messages from your Cube tenant. + if (event.origin !== CUBE_ORIGIN) return; + + const data = event.data; + + // 2. Only handle Cube embed events. + if (!data || data.source !== "cube-embed" || data.direction !== "event") return; + + // 3. Dispatch on the event type. + switch (data.type) { + case "cube:event:ready": + console.log("Embed ready", data.payload.embedTenant, data.payload.deploymentId); + break; + case "cube:event:download": + myAnalytics.track("embed_download", data.payload); + break; + case "cube:event:ai-query": + myAnalytics.track("embed_ai_query", { query: data.payload.query }); + break; + case "cube:event:error": + console.error("Embed error", data.payload.message); + break; + default: + // ready, view, navigate, dashboard-loaded, drilldown, … + myAnalytics.track(data.type, { surface: data.surface, ...data.payload }); + } +}); +``` + +### Event catalog + +| Event | Fires when | Surfaces | +| --- | --- | --- | +| [`cube:event:ready`](#cube-event-ready) | The embed has authenticated and mounted (the handshake) | all | +| [`cube:event:view`](#cube-event-view) | A surface is viewed, on load and on each in-embed navigation | all | +| [`cube:event:navigate`](#cube-event-navigate) | The viewer navigates within the embed | all | +| [`cube:event:dashboard-loaded`](#cube-event-dashboard-loaded) | All widgets on a dashboard have rendered | dashboard | +| [`cube:event:download`](#cube-event-download) | The viewer exports data or an image | dashboard | +| [`cube:event:drilldown`](#cube-event-drilldown) | The viewer drills into a measure | dashboard | +| [`cube:event:ai-query`](#cube-event-ai-query) | The viewer runs an AI / natural-language query | all | +| [`cube:event:error`](#cube-event-error) | The embed surfaces an error | all | + + + Every event payload is also delivered with the envelope's `surface` field, so + you can always tell which surface (`dashboard`, `app`, or `chat`) it came from + — including AI queries, which report `app` when run inside the embedded app and + `chat` on the standalone chat surface. + + +#### `cube:event:ready` + +Emitted once per session, as soon as the embed authenticates and mounts. The +handshake — the first event you receive, and the moment to record an +"embed opened". + +| Field | Type | Description | +| --- | --- | --- | +| `embedTenant` | `string \| null` | The embed tenant the iframe resolved to, when known. | +| `deploymentId` | `number \| null` | The deployment the embed is bound to, when known. | +| `mode` | `"signed" \| "private"` | How the viewer was authenticated. | +| `surface` | `"dashboard" \| "app" \| "chat"` | The surface that mounted. | +| `publicId` | `string` _(optional)_ | The dashboard's public id, for the dashboard surface. | + +```json +{ + "embedTenant": "acme", + "deploymentId": 42, + "mode": "signed", + "surface": "dashboard", + "publicId": "a1b2c3d4" +} +``` + +#### `cube:event:view` + +Emitted when a surface is viewed — on the initial load and again whenever the +viewer navigates within the embed. + +| Field | Type | Description | +| --- | --- | --- | +| `surface` | `"dashboard" \| "app" \| "chat"` | The surface viewed. | +| `path` | `string` | The in-embed route path that was viewed. | +| `publicId` | `string` _(optional)_ | The dashboard's public id, when applicable. | +| `title` | `string` _(optional)_ | Human-readable title of the surface, when available. | + +```json +{ + "surface": "app", + "path": "/embed/d/42/app/workbook/130" +} +``` + +#### `cube:event:navigate` + +Emitted when the viewer navigates within the embed (a route change). Use it to +mirror the embed's location in your own router or analytics. + +| Field | Type | Description | +| --- | --- | --- | +| `path` | `string` | The new path. | +| `previousPath` | `string` _(optional)_ | The path navigated away from. | + +```json +{ + "path": "/embed/d/42/app/workbook/130", + "previousPath": "/embed/d/42/app" +} +``` + +#### `cube:event:dashboard-loaded` + +Emitted when a dashboard has finished rendering all of its widgets — the "fully +painted" signal (distinct from `ready`, which fires at mount, before data loads). + +| Field | Type | Description | +| --- | --- | --- | +| `publicId` | `string` _(optional)_ | The dashboard's public id. | +| `widgetCount` | `number` _(optional)_ | Number of widgets on the dashboard. | +| `loadDurationMs` | `number` _(optional)_ | Milliseconds from mount to all widgets loaded, when measurable. | + +```json +{ + "publicId": "a1b2c3d4", + "widgetCount": 6 +} +``` + +#### `cube:event:download` + +Emitted when a viewer exports something — a widget's data as CSV, or (in future) +a dashboard image. Reports _that_ an export happened and its shape — never the +exported rows themselves. + +| Field | Type | Description | +| --- | --- | --- | +| `format` | `"csv" \| "xlsx" \| "png" \| "pdf"` | The file format produced. | +| `target` | `"widget" \| "dashboard"` | Whether a single widget or the whole dashboard was exported. | +| `widgetId` | `string` _(optional)_ | Id of the source widget, when `target` is `"widget"`. | +| `title` | `string` _(optional)_ | Title of the exported widget / dashboard. | +| `rowCount` | `number` _(optional)_ | Rows exported, for data exports (`csv` / `xlsx`). | + +```json +{ + "format": "csv", + "target": "widget", + "widgetId": "37", + "title": "Revenue by month", + "rowCount": 128 +} +``` + + + The CSV download action on a dashboard widget only appears when the embed URL + includes `allowExport=true` (see [Dashboards → Allow CSV + export](/embedding/iframe/dashboards#allow-csv-export)). The event fires when a + viewer uses it. + + +#### `cube:event:drilldown` + +Emitted when a viewer drills into a measure (clicks a chart mark or table cell to +see its detail rows). + +| Field | Type | Description | +| --- | --- | --- | +| `member` | `string` | The fully-qualified measure that was drilled into. | +| `value` | `unknown` _(optional)_ | The clicked value, when the click carried one. | +| `widgetId` | `string` _(optional)_ | Id of the originating widget. | + +```json +{ + "member": "orders.count", + "value": "completed", + "widgetId": "37" +} +``` + +#### `cube:event:ai-query` + +Emitted around an AI / natural-language query — capturing _what_ the viewer asked +and the lifecycle stage. Fires wherever AI chat is used: the standalone chat +surface, the dashboard agent, and the embedded app. + +| Field | Type | Description | +| --- | --- | --- | +| `query` | `string` | The natural-language query the viewer submitted. | +| `status` | `"submitted" \| "completed" \| "error"` | Lifecycle stage of the query. | +| `chatId` | `string` _(optional)_ | The chat/session id, when applicable. | +| `agentId` | `string` _(optional)_ | The agent that answered, when applicable. | + +```json +{ + "query": "top 10 customers by revenue this quarter", + "status": "submitted", + "agentId": "1" +} +``` + +#### `cube:event:error` + +Emitted when the embed surfaces an error (a render error, a query failure, an +auth/session problem). `fatal` distinguishes an error that took the whole surface +down from a recoverable one. + +| Field | Type | Description | +| --- | --- | --- | +| `message` | `string` | Human-readable message. | +| `name` | `string` _(optional)_ | Error name/class, e.g. `"TypeError"`. | +| `context` | `string` _(optional)_ | Where it originated, e.g. `"embed-render"`. | +| `fatal` | `boolean` _(optional)_ | `true` when the error took down the whole surface. | + +```json +{ + "message": "Failed to load data", + "context": "embed-render", + "fatal": true +} +``` + +## Sending actions + +Send actions into the embed by posting a message to the iframe's +`contentWindow`. Always target your tenant's origin (not `"*"`) so the message +can't leak to another document if the iframe navigates away. + +```js +const iframe = document.querySelector("iframe#cube"); +const CUBE_ORIGIN = "https://your-tenant.cubecloud.dev"; + +function sendAction(type, payload = {}) { + iframe.contentWindow.postMessage( + { + source: "cube-embed", + direction: "action", + type, + payload, + timestamp: Date.now(), + }, + CUBE_ORIGIN + ); +} + +// Examples +sendAction("cube:action:set-color-scheme", { scheme: "dark" }); +sendAction("cube:action:set-filter", { + filterUrlParameter: 'f_orders.status={"value":"completed"}', +}); +sendAction("cube:action:refresh"); +``` + +### Action catalog + +| Action | Effect | Payload | +| --- | --- | --- | +| [`cube:action:set-color-scheme`](#cube-action-set-color-scheme) | Switch light / dark / auto | `{ scheme }` | +| [`cube:action:set-theme`](#cube-action-set-theme) | Apply a brand theme (colors, fonts) | `embedTheme` object | +| [`cube:action:set-locale`](#cube-action-set-locale) | Switch the UI language | `{ locale }` | +| [`cube:action:set-filter`](#cube-action-set-filter) | Push a filter into a dashboard | `{ filterUrlParameter }` | +| [`cube:action:navigate`](#cube-action-navigate) | Navigate the embed to a path | `{ path }` | +| [`cube:action:refresh`](#cube-action-refresh) | Re-run the embed's queries | _none_ | + +#### `cube:action:set-color-scheme` + +Switch the embed's color scheme at runtime. + +| Field | Type | Description | +| --- | --- | --- | +| `scheme` | `"light" \| "dark" \| "auto"` | `"auto"` follows the viewer's OS preference. | + +```js +sendAction("cube:action:set-color-scheme", { scheme: "dark" }); +``` + +#### `cube:action:set-theme` + +Apply a brand theme (colors, fonts) to the embed at runtime. The payload is an +`embedTheme` object — the same shape the [Generate Session API](/reference/embed-apis/generate-session) +accepts. Common fields are `primaryColor`, `borderRadius`, and `font`; see +[App customization](/embedding/iframe/customization#app-customization) for the +full list. + +```js +sendAction("cube:action:set-theme", { + primaryColor: "#7c5cff", + borderRadius: 8, +}); +``` + +#### `cube:action:set-locale` + +Switch the embed's UI language. Accepts a full code (`es-ES`), a short code +(`es`), or a regional variant. See [Localization](/embedding/iframe/localization) +for the list of supported languages and the other ways to set the language. + +| Field | Type | Description | +| --- | --- | --- | +| `locale` | `string` | The locale to switch to. | + +```js +sendAction("cube:action:set-locale", { locale: "es" }); +``` + +#### `cube:action:set-filter` + +Push a filter into a dashboard. The `filterUrlParameter` is the same +`f_.=` form used to +[pre-set filters via URL](/embedding/iframe/dashboards#pre-set-dashboard-filters-via-url), +so you can capture a viewer's filters and restore them later. + +| Field | Type | Description | +| --- | --- | --- | +| `filterUrlParameter` | `string` | Filter(s) in URL-query form, e.g. `f_orders.status={"value":"completed"}`. | + +```js +sendAction("cube:action:set-filter", { + filterUrlParameter: 'f_orders.status={"value":"completed"}', +}); +``` + +#### `cube:action:navigate` + +Navigate the embed to an in-embed path. + +| Field | Type | Description | +| --- | --- | --- | +| `path` | `string` | The in-embed path to navigate to. | + +```js +sendAction("cube:action:navigate", { path: "/embed/d/42/app/workbook/130" }); +``` + +#### `cube:action:refresh` + +Re-run the embed's queries and refresh its data. No payload. + +```js +sendAction("cube:action:refresh"); +``` + +## Surfaces + +Events come from one of three customer-facing surfaces, reported in the envelope's +`surface` field: + +- `dashboard` — a [published dashboard](/embedding/iframe/dashboards). +- `app` — the [Creator-mode app](/embedding/iframe/creator-mode) (workbooks, + folders, in-app dashboards). AI chat run _inside_ the app reports `app`. +- `chat` — the standalone [analytics chat](/embedding/iframe/analytics-chat). + +## Security + +- **Always validate `event.origin`** against your tenant's origin in your + `message` listener, and check `data.source === "cube-embed"`. Never act on a + message that fails either check. +- **Target your tenant's origin when sending actions** (`iframe.contentWindow.postMessage(msg, CUBE_ORIGIN)`), + not `"*"`, so an action can't be delivered to an unexpected document. + +## Complete example + +A minimal host page that loads a signed dashboard embed, logs every event, and +exposes buttons to drive it. Generate the `session` on your backend with the +[Generate Session API](/reference/embed-apis/generate-session) — see +[Signed embedding](/embedding/iframe/auth/signed) for the full flow. + +```html + + + + + + + + + + + +``` diff --git a/docs-mintlify/embedding/iframe/localization.mdx b/docs-mintlify/embedding/iframe/localization.mdx new file mode 100644 index 0000000000000..d1d86fe2f5d6d --- /dev/null +++ b/docs-mintlify/embedding/iframe/localization.mdx @@ -0,0 +1,90 @@ +--- +title: Localization +description: Set the language for embedded Cube surfaces — account-wide, per embed via URL, or at runtime. +--- + +Embedded Cube surfaces — dashboards, [Analytics Chat](/embedding/iframe/analytics-chat), +and the full app in [Creator Mode](/embedding/iframe/creator-mode) — can render their +UI in any of the supported languages. You can set a default language for the whole +account, override it per embed with a URL parameter, or switch it at runtime from the +host page. + + + Available on [Premium and Enterprise plans](https://cube.dev/pricing). + + +## Supported languages + +| Language | Locale code | +| -------------------------- | ----------- | +| English (US) | `en-US` | +| Deutsch (Deutschland) | `de-DE` | +| Español (España) | `es-ES` | +| Español (Latinoamérica) | `es-MX` | +| Français (France) | `fr-FR` | +| Italiano (Italia) | `it-IT` | +| 日本語 (日本) | `ja-JP` | +| Norsk bokmål (Norge) | `nb-NO` | +| Português (Brasil) | `pt-BR` | +| Português (Portugal) | `pt-PT` | +| Svenska (Sverige) | `sv-SE` | +| Tiếng Việt (Việt Nam) | `vi-VN` | + +English (`en-US`) is the default and the fallback when no language is configured. + +A locale value can be a full code (`es-ES`), a short language code (`es`), or a regional +variant that isn't shipped (`es-AR`). Short codes and unsupported regional variants +resolve to the first supported locale for that language — for example, both `es` and +`es-AR` resolve to `es-ES`. A value that doesn't match any supported language is ignored. + +## How the language is resolved + +The language of an embedded surface is resolved from the following sources, highest +priority first: + +1. **Runtime override** — a [`cube:action:set-locale`](/embedding/iframe/events#cube-action-set-locale) + message sent from the host page (see [At runtime](#at-runtime)). +2. **URL parameter** — the `?locale=` query parameter on the embed URL (see + [Per embed via URL](#per-embed-via-url)). +3. **Account default** — the language configured in **Embed → Settings** (see + [Account-wide default](#account-wide-default)). +4. **Fallback** — `en-US`. + +## Account-wide default + +Set a default language for all embedded surfaces from the Cube Cloud console: + +1. Go to **Embed → Settings**. +2. In the **Language** card, pick a language from the dropdown. + +The selected language applies to every embedded surface across the account, unless a +specific embed overrides it with a `?locale=` URL parameter or a runtime +`cube:action:set-locale` message. + +Clearing the setting removes the stored default, and embeds fall back to `en-US` (or to +whatever a per-embed override specifies). + +## Per embed via URL + +Override the account default for an individual embed by adding the `?locale=` query +parameter to the embed URL: + +```text +https://your-tenant.cubecloud.dev/embed/dashboard/YOUR_DASHBOARD_PUBLIC_ID?session=YOUR_SESSION_ID&locale=es-MX +``` + +The parameter is read once when the embed loads and pinned for the session, so in-app +navigation won't drop it. + +## At runtime + +Switch the language after the embed has loaded by sending a +[`cube:action:set-locale`](/embedding/iframe/events#cube-action-set-locale) message from +the host page. This takes precedence over both the URL parameter and the account default: + +```js +sendAction("cube:action:set-locale", { locale: "es" }); +``` + +See [Events and actions](/embedding/iframe/events) for the full host ↔ embed messaging +contract. diff --git a/docs-mintlify/embedding/index.mdx b/docs-mintlify/embedding/index.mdx new file mode 100644 index 0000000000000..97dc86c1def87 --- /dev/null +++ b/docs-mintlify/embedding/index.mdx @@ -0,0 +1,40 @@ +--- +description: Embed AI-powered analytics into your applications using iframes, the React Embed SDK, or a headless approach. +title: Overview +--- + +Cube provides multiple approaches for embedding AI-powered analytics into your applications — from iframe embeds to fully custom embedded analytics experiences built on Cube's APIs. + +## Iframe embedding + + + Available on [Premium and Enterprise plans](https://cube.dev/pricing). + + +Embed Cube content using iframes for the fastest integration with minimal code. This approach works with any frontend framework and requires no additional dependencies. + +Iframe embedding supports [dashboards](/embedding/iframe/dashboards), [Analytics Chat](/embedding/iframe/analytics-chat), and the full Cube application in [Creator Mode](/embedding/iframe/creator-mode). + +**Authentication options:** +- **[Private embedding](/embedding/iframe/auth/private)** – For internal use cases where users authenticate with their Cube accounts +- **[Signed embedding](/embedding/iframe/auth/signed)** – For customer-facing applications using secure, server-generated sessions for authentication + +## SDK embedding + + + Available on [Premium and Enterprise plans](https://cube.dev/pricing). + + +Embed Cube using the [React Embed SDK](/embedding/react-embed-sdk) for tighter integration with your React applications. Components provide more control over styling, theming, and user interactions. + +## Headless embedding + +Build fully custom embedded analytics experiences using Cube APIs directly. This headless approach gives you complete control over data fetching, visualization, and user interface. + +### Chat API + +Use the [Chat API](/reference/embed-apis/chat-api) to build custom conversational analytics experiences. Let your users ask questions in plain language and get trusted answers powered by your semantic layer — without building your own AI infrastructure. + +### Core Data APIs + +Use the [Core Data APIs](/reference/core-data-apis) to build fully custom visualization, reporting, and dashboarding experiences. diff --git a/docs-mintlify/embedding/multitenancy.mdx b/docs-mintlify/embedding/multitenancy.mdx new file mode 100644 index 0000000000000..64c9771f7ed20 --- /dev/null +++ b/docs-mintlify/embedding/multitenancy.mdx @@ -0,0 +1,401 @@ +--- +title: Multitenancy +description: Reference for tenant-aware Cube configuration—per-tenant drivers, schemas, repositories, refresh, and query rewrite driven by security context. +--- + +Cube supports multitenancy out of the box, both on database and data model +levels. Multiple drivers are also supported, meaning that you can have one +customer’s data in MongoDB and others in Postgres with one Cube instance. + +There are several [configuration options][ref-config-opts] you can leverage for +your multitenancy setup. You can use all of them or just a couple, depending on +your specific case. The options are: + +- `context_to_app_id` +- `schema_version` +- `repository_factory` +- `driver_factory` +- `context_to_orchestrator_id` +- `pre_aggregations_schema` +- `query_rewrite` +- `scheduled_refresh_contexts` +- `scheduled_refresh_time_zones` + +All of the above options are functions, which you provide in the +[configuration file][ref-config]. The functions accept one argument: +a context object, which has a [`securityContext`][ref-config-security-ctx] +property where you can provide all the necessary data to identify a user e.g., +organization, app, etc. By default, the +[`securityContext`][ref-config-security-ctx] is defined by [Cube API +Token][ref-security]. + +There are several multitenancy setup scenarios that can be achieved by using +combinations of these configuration options. + + + +See the following recipes: +- If you'd like to provide a [custom data source][ref-per-tenant-data-source-recipe] for each tenant. +- If you'd like to provide a [custom data model][ref-per-tenant-data-model-recipe] for each tenant. + + + +## Multitenancy vs Multiple Data Sources + +In cases where your Cube data model is spread across multiple different data +sources, consider using the [`data_source` cube property][ref-cube-datasource] +instead of multitenancy. Multitenancy is designed for cases where you need to +serve different datasets for multiple users, or tenants which aren't related to +each other. + +On the other hand, multitenancy can be used for scenarios where users need to +access the same data but from different databases. The multitenancy and multiple +data sources features aren't mutually exclusive and can be used together. + + + +A `default` data source **must** exist and be configured. It is used to resolve +target query data source for now. This behavior **will** be changed in future +releases. + + + +A simple configuration with two data sources might look like: + +**cube.js:** + +```javascript +module.exports = { + driverFactory: ({ dataSource } = {}) => { + if (dataSource === "db1") { + return { + type: "postgres", + database: process.env.DB1_NAME, + host: process.env.DB1_HOST, + user: process.env.DB1_USER, + password: process.env.DB1_PASS, + port: process.env.DB1_PORT + } + } else { + return { + type: "postgres", + database: process.env.DB2_NAME, + host: process.env.DB2_HOST, + user: process.env.DB2_USER, + password: process.env.DB2_PASS, + port: process.env.DB2_PORT + } + } + } +} +``` + +A more advanced example that uses multiple [data sources][ref-config-db] could +look like: + +**cube.js:** + +```javascript +module.exports = { + driverFactory: ({ dataSource } = {}) => { + if (dataSource === "web") { + return { + type: "athena", + database: dataSource, + + // ... + } + } else if (dataSource === "googleAnalytics") { + return { + type: "bigquery", + + // ... + } + } else if (dataSource === "financials") { + return { + type: "postgres", + database: "financials", + host: "financials-db.acme.com", + user: process.env.FINANCIALS_DB_USER, + password: process.env.FINANCIALS_DB_PASS + } + } else { + return { + type: "postgres", + + // ... + } + } + } +} +``` + +More information can be found on the [Multiple Data Sources +page][ref-config-multi-data-src]. + +### queryRewrite vs Multitenant Compile Context + +As a rule of thumb, the [`queryRewrite`][ref-config-query-rewrite] should be +used in scenarios when you want to define row-level security within the same +database for different users of such database. For example, to separate access +of two e-commerce administrators who work on different product categories within +the same e-commerce store, you could configure your project as follows. + +Use the following `cube.js` configuration file: + +```javascript +module.exports = { + queryRewrite: (query, { securityContext }) => { + if (securityContext.categoryId) { + query.filters.push({ + member: "products.category_id", + operator: "equals", + values: [securityContext.categoryId] + }) + } + return query + } +} +``` + +Also, you can use a data model like this: + + + +```yaml title="YAML" +cubes: + - name: products + sql_table: products +``` + +```javascript title="JavaScript" +cube(`products`, { + sql_table: `products` +}) +``` + + + +On the other hand, multi-tenant [`COMPILE_CONTEXT`][ref-cube-security-ctx] +should be used when users need access to different databases. For example, if +you provide SaaS ecommerce hosting and each of your customers have a separate +database, then each e-commerce store should be modeled as a separate tenant. + + + +```yaml title="YAML" +cubes: + - name: products + sql_table: "{COMPILE_CONTEXT.security_context.userId}.products" +``` + +```javascript title="JavaScript" +cube(`products`, { + sql_table: `${COMPILE_CONTEXT.security_context.userId}.products` +}) +``` + + + +### Running in Production + +Each unique id generated by `contextToAppId` or `contextToOrchestratorId` will +generate a dedicated set of resources, including data model compile cache, SQL +compile cache, query queues, in-memory result caching, etc. Depending on your +data model complexity and usage patterns, those resources can have a pretty +sizable memory footprint ranging from single-digit MBs on the lower end and +dozens of MBs on the higher end. So you should make sure Node VM has enough +memory reserved for that. + +There're multiple strategies in terms of memory resource utilization here. The +first one is to bucket your actual tenants into variable-size buckets with +assigned `contextToAppId` or `contextToOrchestratorId` by some bucketing rule. +For example, you can bucket your biggest tenants in separate buckets and all the +smaller ones into a single bucket. This way, you'll end up with a very small +count of buckets that will easily fit a single node. + +Another strategy is to split all your tenants between different Cube nodes and +route traffic between them so that each Cube API node serves only its own set of +tenants and never serves traffic for another node. In that case, memory usage is +limited by the number of tenants served by each node. Cube Cloud utilizes +precisely this approach for scaling. Please note that in this case, you should +also split refresh workers and assign appropriate `scheduledRefreshContexts` to +them. + +## Same DB Instance with per Tenant Row Level Security + +Per tenant row-level security can be achieved by configuring +[`queryRewrite`][ref-config-query-rewrite], which adds a tenant identifier +filter to the original query. It uses the +[`securityContext`][ref-config-security-ctx] to determine which tenant is +requesting data. This way, every tenant starts to see their own data. However, +resources such as query queue and pre-aggregations are shared between all +tenants. + +**cube.js:** + +```javascript +module.exports = { + queryRewrite: (query, { securityContext }) => { + const user = securityContext + if (user.id) { + query.filters.push({ + member: "users.id", + operator: "equals", + values: [user.id] + }) + } + return query + } +} +``` + +## Multiple DB Instances with Same Data Model + +Let's consider an example where we store data for different users in different +databases, but on the same Postgres host. The database name format is +`my_app__`, so `my_app_1_2` is a valid database name. + +To make it work with Cube, first we need to pass the `appId` and `userId` as +context to every query. We should first ensure our JWTs contain those properties +so we can access them through the [security context][ref-config-security-ctx]. + +```javascript +const jwt = require("jsonwebtoken") +const CUBE_API_SECRET = "secret" + +const cubeToken = jwt.sign({ appId: "1", userId: "2" }, CUBE_API_SECRET, { + expiresIn: "30d" +}) +``` + +Now, we can access them through the [`securityContext`][ref-config-security-ctx] +property inside the context object. Let's use +[`contextToAppId`][ref-config-ctx-to-appid] and +[`contextToOrchestratorId`][ref-config-ctx-to-orch-id] to create a dynamic Cube +App ID and Orchestrator ID for every combination of `appId` and `userId`, as +well as defining [`driverFactory`][ref-config-driverfactory] to dynamically +select the database, based on the `appId` and `userId`: + + + +The App ID (the result of [`contextToAppId`][ref-config-ctx-to-appid]) is used +as a caching key for various in-memory structures like data model compilation +results, connection pool. The Orchestrator ID (the result of +[`contextToOrchestratorId`][ref-config-ctx-to-orch-id]) is used as a caching key +for database connections, execution queues and pre-aggregation table caches. Not +declaring these properties will result in unexpected caching issues such as the +data model or data of one tenant being used for another. + + + +**cube.js:** + +```javascript +module.exports = { + contextToAppId: ({ securityContext }) => + `CUBE_APP_${securityContext.appId}_${securityContext.userId}`, + contextToOrchestratorId: ({ securityContext }) => + `CUBE_APP_${securityContext.appId}_${securityContext.userId}`, + driverFactory: ({ securityContext }) => ({ + type: "postgres", + database: `my_app_${securityContext.appId}_${securityContext.userId}` + }) +} +``` + +## Same DB Instance with per Tenant Pre-Aggregations + +To support per-tenant pre-aggregation of data within the same database instance, +you should configure the [`preAggregationsSchema`][ref-config-preagg-schema] +option in your `cube.js` configuration file. You should use also +[`securityContext`][ref-config-security-ctx] to determine which tenant is +requesting data. + +**cube.js:** + +```javascript +module.exports = { + contextToAppId: ({ securityContext }) => + `CUBE_APP_${securityContext.userId}`, + preAggregationsSchema: ({ securityContext }) => + `pre_aggregations_${securityContext.userId}` +} +``` + +## Multiple Data Models and Drivers + +What if for application with ID 3, the data is stored not in Postgres, but in +MongoDB? + +We can instruct Cube to connect to MongoDB in that case, instead of Postgres. To +do this, we'll use the [`driverFactory`][ref-config-driverfactory] option to +dynamically set database type. We will also need to modify our +[`securityContext`][ref-config-security-ctx] to determine which tenant is +requesting data. Finally, we want to have separate data models for every +application. We can use the [`repositoryFactory`][ref-config-repofactory] option +to dynamically set a repository with data model files depending on the `appId`: + +**cube.js:** + +```javascript +const { FileRepository } = require("@cubejs-backend/server-core") + +module.exports = { + contextToAppId: ({ securityContext }) => + `CUBE_APP_${securityContext.appId}_${securityContext.userId}`, + contextToOrchestratorId: ({ securityContext }) => + `CUBE_APP_${securityContext.appId}_${securityContext.userId}`, + driverFactory: ({ securityContext }) => { + if (securityContext.appId === 3) { + return { + type: "mongobi", + database: `my_app_${securityContext.appId}_${securityContext.userId}`, + port: 3307 + } + } else { + return { + type: "postgres", + database: `my_app_${securityContext.appId}_${securityContext.userId}` + } + } + }, + repositoryFactory: ({ securityContext }) => + new FileRepository(`model/${securityContext.appId}`) +} +``` + +## Scheduled Refreshes for Pre-Aggregations + +If you need scheduled refreshes for your pre-aggregations in a multi-tenant +deployment, ensure you have configured +[`scheduled_refresh_contexts`][ref-config-refresh-ctx] correctly. You may also +need to configure [`scheduled_refresh_time_zones`][ref-config-refresh-tz]. + + + +Leaving [`scheduled_refresh_contexts`][ref-config-refresh-ctx] unconfigured will +lead to issues where the security context will be `undefined`. This is because +there is no way for Cube to know how to generate a context without the required +input. + + + +[ref-config]: /admin/connect-to-data#configuration-options +[ref-config-opts]: /reference/configuration/config +[ref-config-db]: /admin/connect-to-data/data-sources +[ref-config-driverfactory]: /reference/configuration/config#driver_factory +[ref-config-repofactory]: /reference/configuration/config#repository_factory +[ref-config-preagg-schema]: /reference/configuration/config#pre_aggregations_schema +[ref-config-ctx-to-appid]: /reference/configuration/config#context_to_app_id +[ref-config-ctx-to-orch-id]: /reference/configuration/config#context_to_orchestrator_id +[ref-config-multi-data-src]: /admin/connect-to-data/multiple-data-sources +[ref-config-query-rewrite]: /reference/configuration/config#query_rewrite +[ref-config-refresh-ctx]: /reference/configuration/config#scheduled_refresh_contexts +[ref-config-refresh-tz]: /reference/configuration/config#scheduled_refresh_timezones +[ref-config-security-ctx]: /docs/data-modeling/access-control/context +[ref-security]: /docs/data-modeling/access-control +[ref-cube-datasource]: /reference/data-modeling/cube#data_source +[ref-cube-security-ctx]: /reference/data-modeling/context-variables#compile_context +[ref-per-tenant-data-source-recipe]: /recipes/configuration/multiple-sources-same-schema +[ref-per-tenant-data-model-recipe]: /recipes/configuration/custom-data-model-per-tenant \ No newline at end of file diff --git a/docs-mintlify/embedding/react-embed-sdk.mdx b/docs-mintlify/embedding/react-embed-sdk.mdx new file mode 100644 index 0000000000000..13f910d29d201 --- /dev/null +++ b/docs-mintlify/embedding/react-embed-sdk.mdx @@ -0,0 +1,50 @@ +--- +title: React Embed SDK +description: React Embed SDK is currently in public preview. The API may change in future releases. +--- + + + React Embed SDK is currently in **public preview**. The API may change in future releases. + + +The React Embed SDK provides React components for embedding Cube analytics directly into your React applications. It offers tighter integration with React's component model, giving you more control over styling, theming, and user interactions compared to iframe embedding. + +## Installation + +```bash +npm install @cube-dev/embed-sdk +# or +yarn add @cube-dev/embed-sdk +``` + +## Quick Start + +The SDK requires [TanStack Query](https://tanstack.com/query) as a peer dependency. Wrap your application with `QueryClientProvider`, then add `CubeEmbedProvider` inside it: + +```jsx +import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; +import { CubeEmbedProvider } from "@cube-dev/embed-sdk"; + +const queryClient = new QueryClient(); + +function App() { + return ( + + + {/* Your embedded analytics components go here */} + + + ); +} +``` + +## Authentication + +The React Embed SDK uses the same session-based authentication as [signed embedding](/embedding/iframe/auth/signed). Generate a session using the [Generate Session API](/reference/embed-apis/generate-session) and pass the `sessionId` to the provider. + +## Example + +For a complete working implementation, see the [antd-cube-embed-sdk example](https://github.com/cubedevinc/cube-agent-examples/tree/main/examples/antd-cube-embed-sdk) on GitHub. diff --git a/docs-mintlify/embedding/vizard.mdx b/docs-mintlify/embedding/vizard.mdx new file mode 100644 index 0000000000000..fa1cea6c08b6a --- /dev/null +++ b/docs-mintlify/embedding/vizard.mdx @@ -0,0 +1,79 @@ +--- +title: Chart Prototyping +description: Turn a Playground query into starter front-end code that charts REST (JSON) API results for embedded analytics prototypes. +--- + +Chart Prototyping generates code of a front-end application that works with +the [REST (JSON) API][ref-rest-api] and visualizes data on charts. It's convenient +for boostrapping a new embedded analytics application or copying and pasting +code to an existing one. + + + +Chart Prototyping is part of [Playground][ref-playground]. + + + +To access Chart Prototyping from Playground, compose and run a query, expand +the **Chart** pane, and click **Code** on the right: + + + +## Getting Started + +You can install Cube JavaScript Client and the Angular package with npm or Yarn: + +```bash +# npm +npm install --save @cubejs-client/core @cubejs-client/ngx + +# Yarn +yarn add @cubejs-client/core @cubejs-client/ngx +``` + +Now you can build your application from scratch or connect to one of our +[supported data visualization tools](/admin/connect-to-data/visualization-tools). + + +[ref-compare-date-range]: /reference/core-data-apis/queries#compare-date-range-query \ No newline at end of file diff --git a/docs-mintlify/reference/javascript-sdk/index.mdx b/docs-mintlify/reference/javascript-sdk/index.mdx new file mode 100644 index 0000000000000..7b6407bd2c62f --- /dev/null +++ b/docs-mintlify/reference/javascript-sdk/index.mdx @@ -0,0 +1,132 @@ +--- +title: npm +description: "Use Cube's JavaScript client and React, Vue, or Angular bindings to build data-driven UIs." +--- + + JavaScript SDK + +Cube is visualization-agnostic, so you can build any user interface for your +application. + +You can directly query Cube using the +JSON [query format](/reference/core-data-apis/rest-api/query-format) via the [REST (JSON) API](/reference/core-data-apis/rest-api/reference) +or +[WebSockets](/recipes/core-data-api/real-time-data-fetch) +and visualize analytical data with tools of your choice. However, it's much +easier to use the Cube JavaScript client and bindings for popular frameworks +such as React, Angular, and Vue. + +The client has methods to communicate with Cube API Gateway and retrieve and +process data. It is designed to work with existing charting libraries including +Chart.js, D3.js, and more. + +## Cube JavaScript Client + +The client provides methods to solve common tasks: + +**Abstract from the transport and query data.** You can +[fetch data](/reference/javascript-sdk/reference/cubejs-client-core#load) from Cube Backend or +subscribe to +[real-time updates](/recipes/core-data-api/real-time-data-fetch) +regardless of the protocol, be it HTTP or WebSockets. + +**Transform data for visualization.** You can +[pivot](/reference/javascript-sdk/reference/cubejs-client-core#pivot) the result set to display +as a [chart](/reference/javascript-sdk/reference/cubejs-client-core#chartpivot) or as a +[table](/reference/javascript-sdk/reference/cubejs-client-core#tablepivot), split into +[series](/reference/javascript-sdk/reference/cubejs-client-core#series) or +[table columns](/reference/javascript-sdk/reference/cubejs-client-core#tablecolumns). + +**Simplify work with complex query types.** You can build +[drill down](/reference/javascript-sdk/reference/cubejs-client-core#drilldown) queries and +[decompose](/reference/javascript-sdk/reference/cubejs-client-core#decompose) the results of +[compare date range queries][ref-compare-date-range] +or [data blending](/docs/data-modeling/concepts/data-blending) queries. + +[Learn more](/reference/javascript-sdk/reference/cubejs-client-core) in the documentation for +the `@cubejs-client/core` package. + +## Example Usage + +Here are the typical steps to query and visualize analytical data: + +- **Import the `@cubejs-client/core` package.** This package provides all the + necessary methods. +- **Create an instance of Cube JavaScript Client.** The client is initialized + with Cube API URL. In development mode, the default URL is + [http://localhost:4000/cubejs-api/v1](http://localhost:4000/cubejs-api/v1). + The client is also initialized with an [API token](/docs/data-modeling/access-control), but it + takes effect only in [production](/cube-core/running-in-production). +- **Query data from Cube Backend.** The client accepts a query, which is a plain + JavaScript object. See + [Query Format](/reference/core-data-apis/rest-api/query-format) for details. +- **Transform data for visualization.** The result set has convenient methods, + such as `series` and `chartPivot`, to prepare data for charting. +- **Visualize the data.** Use tools of your choice to draw charts and create + visualizations. + +See an example of using Cube with vanilla JavaScript and Chart.js library. Note +that you can always use a different charting library that suits your needs: + + + +## Getting Started + +You can install Cube JavaScript Client with npm or Yarn: + +```bash +# npm +npm install --save @cubejs-client/core + +# Yarn +yarn add @cubejs-client/core +``` + +Now you can build your application from scratch or connect to one of our +[supported data visualization tools](/admin/connect-to-data/visualization-tools). + +## Data format + +The [REST (JSON) API][ref-rest-api] uses JSON to serialize and transfer result sets. +Numbers, e.g., values of numeric measures, are represented as strings. + +By default, JavaScript SDK also returns numbers as strings because an automatic +conversion might lead to a precision loss. In JavaScript, only numbers between +[`Number.MAX_SAFE_INTEGER`][link-max-safe-int] and `Number.MIN_SAFE_INTEGER` +can be safely parsed from strings. However, there's no guarantee that a measure +value or a column value from a supported [data source][ref-data-sources] would +not be outside of this range. + +If you'd like Cube to convert strings to numbers anyway, you can use the +[`castNumerics` option][ref-ref-loadmethodoptions] for that: + +```javascript +import cube from '@cubejs-client/core' + +const cubeApi = cube(CUBE_API_TOKEN, { + apiUrl: CUBE_API_URL +}) + +const resultSet = await cubeApi.load(query, { + castNumerics: true +}) + +console.log(resultSet.tablePivot()) +``` + + +[ref-compare-date-range]: /reference/core-data-apis/queries#compare-date-range-query +[ref-rest-api]: /reference/core-data-apis/rest-api +[link-max-safe-int]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/MAX_SAFE_INTEGER +[ref-data-sources]: /admin/connect-to-data/data-sources +[ref-ref-loadmethodoptions]: /reference/javascript-sdk/reference/cubejs-client-core#loadmethodoptions \ No newline at end of file diff --git a/docs-mintlify/reference/javascript-sdk/react.mdx b/docs-mintlify/reference/javascript-sdk/react.mdx new file mode 100644 index 0000000000000..f5c26463d76f1 --- /dev/null +++ b/docs-mintlify/reference/javascript-sdk/react.mdx @@ -0,0 +1,112 @@ +--- +title: React +description: Cube is visualization-agnostic, so you can build any user interface for your application. +--- + +You can directly query Cube using the +JSON [query format](/reference/core-data-apis/rest-api/query-format) via the [REST (JSON) API](/reference/core-data-apis/rest-api/reference) +or +[WebSockets](/recipes/core-data-api/real-time-data-fetch) +and visualize analytical data with tools of your choice. However, it's much +easier to use the Cube JavaScript client and bindings for popular frameworks +such as React, Angular, and Vue. + +The client has methods to communicate with Cube API Gateway and retrieve and +process data. It is designed to work with existing charting libraries including +Chart.js, D3.js, and more. + +## Cube JavaScript Client + +The client provides methods to solve common tasks: + +**Abstract from the transport and query data.** You can +[fetch data](/reference/javascript-sdk/reference/cubejs-client-core#load) from Cube Backend or +subscribe to +[real-time updates](/recipes/core-data-api/real-time-data-fetch) +regardless of the protocol, be it HTTP or WebSockets. + +**Transform data for visualization.** You can +[pivot](/reference/javascript-sdk/reference/cubejs-client-core#pivot) the result set to display +as a [chart](/reference/javascript-sdk/reference/cubejs-client-core#chartpivot) or as a +[table](/reference/javascript-sdk/reference/cubejs-client-core#tablepivot), split into +[series](/reference/javascript-sdk/reference/cubejs-client-core#series) or +[table columns](/reference/javascript-sdk/reference/cubejs-client-core#tablecolumns). + +**Simplify work with complex query types.** You can build +[drill down](/reference/javascript-sdk/reference/cubejs-client-core#drilldown) queries and +[decompose](/reference/javascript-sdk/reference/cubejs-client-core#decompose) the results of +[compare date range queries][ref-compare-date-range] +or [data blending](/docs/data-modeling/concepts/data-blending) queries. + +[Learn more](/reference/javascript-sdk/reference/cubejs-client-core) in the documentation for +the `@cubejs-client/core` package. + +## Cube React Package + +The package provides convenient tools to work with Cube in React: + +**Hooks.** You can add the +[useCubeQuery hook](/reference/javascript-sdk/reference/cubejs-client-react#usecubequery) to +functional React components to execute Cube queries. + +**Components.** You can use +[`QueryBuilder`](/reference/javascript-sdk/reference/cubejs-client-react#querybuilder) and +[`QueryRenderer`](/reference/javascript-sdk/reference/cubejs-client-react#queryrenderer) +components to separate state management and API calls from your rendering code. +You can also use +[`CubeProvider`](/reference/javascript-sdk/reference/cubejs-client-react#cubeprovider) and +[`CubeContext`](/reference/javascript-sdk/reference/cubejs-client-react#cubecontext) components +for direct access to Cube client anywhere in your application. + +## Example Usage + +Here are the typical steps to query and visualize analytical data in React: + +- **Import `@cubejs-client/core` and `@cubejs-client/react` packages.** These + packages provide all the necessary methods and convenient React tools. +- **Create an instance of Cube JavaScript Client.** The client is initialized + with Cube API URL. In development mode, the default URL is + [http://localhost:4000/cubejs-api/v1](http://localhost:4000/cubejs-api/v1). + The client is also initialized with an [API token](/docs/data-modeling/access-control), but it + takes effect only in [production](/cube-core/running-in-production). +- **Query data from Cube Backend.** In functional React components, use the + `useCubeQuery` hook to execute a query, which is a plain JavaScript object. + See [Query Format](/reference/core-data-apis/rest-api/query-format) for + details. +- **Transform data for visualization.** The result set has convenient methods, + such as `series` and `chartPivot`, to prepare data for charting. +- **Visualize the data.** Use tools of your choice to draw charts and create + visualizations. + +See an example of using Cube with React and Chart.js library. Note that you can +always use a different charting library that suits your needs: + + + +## Getting Started + +You can install Cube JavaScript Client and the React package with npm or Yarn: + +```bash +# npm +npm install --save @cubejs-client/core @cubejs-client/react + +# Yarn +yarn add @cubejs-client/core @cubejs-client/react +``` + +Now you can build your application from scratch or connect to one of our +[supported data visualization tools](/admin/connect-to-data/visualization-tools). + + +[ref-compare-date-range]: /reference/core-data-apis/queries#compare-date-range-query \ No newline at end of file diff --git a/docs-mintlify/reference/javascript-sdk/reference/cubejs-client-core.mdx b/docs-mintlify/reference/javascript-sdk/reference/cubejs-client-core.mdx new file mode 100644 index 0000000000000..dd34fc532d727 --- /dev/null +++ b/docs-mintlify/reference/javascript-sdk/reference/cubejs-client-core.mdx @@ -0,0 +1,1169 @@ +--- +title: "`@cubejs-client/core`" +description: Vanilla JavaScript client for Cube. +--- + +## `cube` + +> **cube**(**apiToken**: string | () => *Promise‹string›*, **options**: [CubeApiOptions](#cubeapioptions)): *[CubeApi](#cubeapi)* + +Creates an instance of the `CubeApi`. The API entry point. + +```js +import cube from '@cubejs-client/core'; +const cubeApi = cube( + 'CUBE-API-TOKEN', + { apiUrl: 'http://localhost:4000/cubejs-api/v1' } +); +``` + +You can also pass an async function or a promise that will resolve to the API token + +```js +import cube from '@cubejs-client/core'; +const cubeApi = cube( + async () => await Auth.getJwtToken(), + { apiUrl: 'http://localhost:4000/cubejs-api/v1' } +); +``` + +If you need to set up cancellation for all requests made by this API instance: + +```js +import cube from '@cubejs-client/core'; + +// Create a controller for managing request cancellation +const controller = new AbortController(); +const { signal } = controller; + +const cubeApi = cube( + 'CUBE-API-TOKEN', + { + apiUrl: 'http://localhost:4000/cubejs-api/v1', + signal: signal + } +); + +// Later when you need to cancel all pending requests: +// controller.abort(); +``` + +**Parameters:** + +Name | Type | Description | +------ | ------ | ------ | +apiToken | string | () => *Promise‹string›* | [API token][ref-security] is used to authorize requests and determine SQL database you're accessing. In the development mode, Cube will print the API token to the console on startup. In case of async function `authorization` is updated for `options.transport` on each request. | +options | [CubeApiOptions](#cubeapioptions) | - | + +> **cube**(**options**: [CubeApiOptions](#cubeapioptions)): *[CubeApi](#cubeapi)* + +## `defaultHeuristics` + +> **defaultHeuristics**(**newQuery**: [Query](#query-2), **oldQuery**: [Query](#query-2), **options**: [TDefaultHeuristicsOptions](#tdefaultheuristicsoptions)): *any* + +## `defaultOrder` + +> **defaultOrder**(**query**: [Query](#query-2)): *object* + +## `movePivotItem` + +> **movePivotItem**(**pivotConfig**: [PivotConfig](#pivotconfig), **sourceIndex**: number, **destinationIndex**: number, **sourceAxis**: TSourceAxis, **destinationAxis**: TSourceAxis): *[PivotConfig](#pivotconfig)* + +## Format API + +A set of helpers for formatting member values on the client, consistently with how +Cube formats them. They are imported from the `@cubejs-client/core/format` subpath: + +```js +import { formatValue, getFormat, formatDateByGranularity } from '@cubejs-client/core/format'; +``` + +### `formatValue` + +> **formatValue**(**value**: any, **options**: FormatValueOptions): *string* + +Formats a single value according to a member's `type` and `format`. `options` extends the +member's metadata (`type`, `format`, `currency`, `granularity`) with an optional `locale` +(e.g. `'en-US'`, `'de-DE'`) and an `emptyPlaceholder` for empty values. Numeric formats use +[d3-format](https://d3js.org/d3-format) specifiers, and the precision of named formats (e.g. +`currency_2`) is treated as an upper bound — insignificant trailing zeros are trimmed. + +```js +import { formatValue } from '@cubejs-client/core/format'; + +formatValue(1234.5, { type: 'number', format: 'currency_2', currency: 'EUR', locale: 'de-DE' }); +``` + +### `getFormat` + +> **getFormat**(**member**: FormatValueMember, **options?**: GetFormatOptions): *GetFormatResult* + +Returns a reusable formatter for a member. `options` accepts an optional `locale`. The result +has two properties: `formatString` (the resolved format specifier, or `null` for non-numeric +formats) and `formatFunc`, a function that formats a value. Use it when formatting many values +for the same member. + +### `formatDateByGranularity` + +> **formatDateByGranularity**(**value**: Date | string | number, **granularity?**: string): *string* + +Formats a date value for a given time dimension `granularity` (e.g. `'day'`, `'month'`, +`'year'`). + +## `CubeApi` + +Main class for accessing Cube API + +### `dryRun` + +> **dryRun**(**query**: [Query](#query-2) | [Query](#query-2)[], **options?**: [LoadMethodOptions](#loadmethodoptions)): *Promise‹[TDryRunResponse](#tdryrunresponse)›* + +> **dryRun**(**query**: [Query](#query-2) | [Query](#query-2)[], **options**: [LoadMethodOptions](#loadmethodoptions), **callback?**: [LoadMethodCallback](#loadmethodcallback)‹[TDryRunResponse](#tdryrunresponse)›): *void* + +Get query related meta without query execution + +### `load` + +> **load**(**query**: [Query](#query-2) | [Query](#query-2)[], **options?**: [LoadMethodOptions](#loadmethodoptions)): *Promise‹[ResultSet](#resultset)›* + +> **load**(**query**: [Query](#query-2) | [Query](#query-2)[], **options?**: [LoadMethodOptions](#loadmethodoptions), **callback?**: [LoadMethodCallback](#loadmethodcallback)‹[ResultSet](#resultset)›): *void* + +Fetch data for the passed `query`. + +```js +import cube from '@cubejs-client/core'; +import Chart from 'chart.js'; +import chartjsConfig from './toChartjsData'; + +const cubeApi = cube('CUBE_TOKEN'); + +const resultSet = await cubeApi.load({ + measures: ['Stories.count'], + timeDimensions: [{ + dimension: 'Stories.time', + dateRange: ['2015-01-01', '2015-12-31'], + granularity: 'month' + }] +}); + +const context = document.getElementById('myChart'); +new Chart(context, chartjsConfig(resultSet)); +``` + +You can also use AbortController to cancel a request: + +```js +import cube from '@cubejs-client/core'; + +const cubeApi = cube('CUBE_TOKEN'); + +// Create an AbortController instance +const controller = new AbortController(); +const { signal } = controller; + +try { + // Pass the signal to the load method + const resultSetPromise = cubeApi.load( + { + measures: ['Orders.count'], + dimensions: ['Orders.status'] + }, + { signal } + ); + + // To cancel the request at any time: + // controller.abort(); + + const resultSet = await resultSetPromise; + // Process the result +} catch (error) { + if (error.name === 'AbortError') { + console.log('Request was cancelled'); + } else { + console.error('Error loading data:', error); + } +} +``` + +**Parameters:** + +Name | Type | Description | +------ | ------ | ------ | +query | [Query](#query-2) | [Query](#query-2)[] | [Query object][ref-query-format] | +options? | [LoadMethodOptions](#loadmethodoptions) | - | +callback? | [LoadMethodCallback](#loadmethodcallback)‹[ResultSet](#resultset)› | - | + +### `meta` + +> **meta**(**options?**: [LoadMethodOptions](#loadmethodoptions)): *Promise‹[Meta](#meta-2)›* + +> **meta**(**options?**: [LoadMethodOptions](#loadmethodoptions), **callback?**: [LoadMethodCallback](#loadmethodcallback)‹[Meta](#meta-2)›): *void* + +Get meta description of cubes available for querying. + +### `sql` + +> **sql**(**query**: [Query](#query-2) | [Query](#query-2)[], **options?**: [LoadMethodOptions](#loadmethodoptions)): *Promise‹[SqlQuery](#sqlquery)›* + +> **sql**(**query**: [Query](#query-2) | [Query](#query-2)[], **options?**: [LoadMethodOptions](#loadmethodoptions), **callback?**: [LoadMethodCallback](#loadmethodcallback)‹[SqlQuery](#sqlquery)›): *void* + +Get generated SQL string for the given `query`. + +**Parameters:** + +Name | Type | Description | +------ | ------ | ------ | +query | [Query](#query-2) | [Query](#query-2)[] | [Query object][ref-query-format] | +options? | [LoadMethodOptions](#loadmethodoptions) | - | +callback? | [LoadMethodCallback](#loadmethodcallback)‹[SqlQuery](#sqlquery)› | - | + +### `subscribe` + +> **subscribe**(**query**: [Query](#query-2) | [Query](#query-2)[], **options**: [LoadMethodOptions](#loadmethodoptions) | null, **callback**: [LoadMethodCallback](#loadmethodcallback)‹[ResultSet](#resultset)›): *void* + +Allows you to fetch data and receive updates over time. See [Real-Time Data Fetch](/recipes/core-data-api/real-time-data-fetch) + +```js +cubeApi.subscribe( + { + measures: ['Logs.count'], + timeDimensions: [ + { + dimension: 'Logs.time', + granularity: 'hour', + dateRange: 'last 1440 minutes', + }, + ], + }, + options, + (error, resultSet) => { + if (!error) { + // handle the update + } + } +); +``` + +## `HttpTransport` + +Default transport implementation. + +### constructor + +> **new HttpTransport**(**options**: [TransportOptions](#transportoptions)): *[HttpTransport](#httptransport)* + +### `request` + +> **request**(**method**: string, **params**: any): () => *Promise‹any›* + +*Implementation of ITransport* + +## `Meta` + +Contains information about available cubes and it's members. + +### `defaultTimeDimensionNameFor` + +> **defaultTimeDimensionNameFor**(**memberName**: string): *string* + +### `filterOperatorsForMember` + +> **filterOperatorsForMember**(**memberName**: string, **memberType**: [MemberType](#membertype) | [MemberType](#membertype)[]): *any* + +### `membersForQuery` + +> **membersForQuery**(**query**: [Query](#query-2) | null, **memberType**: [MemberType](#membertype)): *[TCubeMeasure](#tcubemeasure)[] | [TCubeDimension](#tcubedimension)[] | [TCubeMember](#tcubemember)[]* + +Get all members of a specific type for a given query. +If empty query is provided no filtering is done based on query context and all available members are retrieved. + +**Parameters:** + +Name | Type | Description | +------ | ------ | ------ | +query | [Query](#query-2) | null | context query to provide filtering of members available to add to this query | +memberType | [MemberType](#membertype) | - | + +### `resolveMember` + +> **resolveMember**‹**T**›(**memberName**: string, **memberType**: T | T[]): *object | [TCubeMemberByType](#tcubememberbytype)‹T›* + +Get meta information for a cube member +Member meta information contains: +```javascript +{ + name, + title, + shortTitle, + type, + description, + format +} +``` + +**Type parameters:** + +- **T**: *[MemberType](#membertype)* + +**Parameters:** + +Name | Type | Description | +------ | ------ | ------ | +memberName | string | Fully qualified member name in a form `Cube.memberName` | +memberType | T | T[] | - | + +## `ProgressResult` + +### `stage` + +> **stage**(): *string* + +### `timeElapsed` + +> **timeElapsed**(): *string* + +## `ResultSet` + +Provides a convenient interface for data manipulation. + +### `annotation` + +> **annotation**(): *[QueryAnnotations](#queryannotations)* + +### `chartPivot` + +> **chartPivot**(**pivotConfig?**: [PivotConfig](#pivotconfig)): *[ChartPivotRow](#chartpivotrow)[]* + +Returns normalized query result data in the following format. + +You can find the examples of using the `pivotConfig` [here](#pivotconfig) +```js +// For the query +{ + measures: ['Stories.count'], + timeDimensions: [{ + dimension: 'Stories.time', + dateRange: ['2015-01-01', '2015-12-31'], + granularity: 'month' + }] +} + +// ResultSet.chartPivot() will return +[ + { "x":"2015-01-01T00:00:00", "Stories.count": 27120, "xValues": ["2015-01-01T00:00:00"] }, + { "x":"2015-02-01T00:00:00", "Stories.count": 25861, "xValues": ["2015-02-01T00:00:00"] }, + { "x":"2015-03-01T00:00:00", "Stories.count": 29661, "xValues": ["2015-03-01T00:00:00"] }, + //... +] + +``` +When using `chartPivot()` or `seriesNames()`, you can pass `aliasSeries` in the [pivotConfig](#pivotconfig) +to give each series a unique prefix. This is useful for `blending queries` which use the same measure multiple times. + +```js +// For the queries +{ + measures: ['Stories.count'], + timeDimensions: [ + { + dimension: 'Stories.time', + dateRange: ['2015-01-01', '2015-12-31'], + granularity: 'month', + }, + ], +}, +{ + measures: ['Stories.count'], + timeDimensions: [ + { + dimension: 'Stories.time', + dateRange: ['2015-01-01', '2015-12-31'], + granularity: 'month', + }, + ], + filters: [ + { + member: 'Stores.read', + operator: 'equals', + values: ['true'], + }, + ], +}, + +// ResultSet.chartPivot({ aliasSeries: ['one', 'two'] }) will return +[ + { + x: '2015-01-01T00:00:00', + 'one,Stories.count': 27120, + 'two,Stories.count': 8933, + xValues: ['2015-01-01T00:00:00'], + }, + { + x: '2015-02-01T00:00:00', + 'one,Stories.count': 25861, + 'two,Stories.count': 8344, + xValues: ['2015-02-01T00:00:00'], + }, + { + x: '2015-03-01T00:00:00', + 'one,Stories.count': 29661, + 'two,Stories.count': 9023, + xValues: ['2015-03-01T00:00:00'], + }, + //... +]; +``` + +### `decompose` + +> **decompose**(): *Object* + +Can be used when you need access to the methods that can't be used with some query types (eg `compareDateRangeQuery` or `blendingQuery`) +```js +resultSet.decompose().forEach((currentResultSet) => { + console.log(currentResultSet.rawData()); +}); +``` + +### `drillDown` + +> **drillDown**(**drillDownLocator**: [DrillDownLocator](#drilldownlocator), **pivotConfig?**: [PivotConfig](#pivotconfig)): *[Query](#query-2) | null* + +Returns a measure drill down query. + +Provided you have a measure with the defined `drillMemebers` on the `Orders` cube +```js +measures: { + count: { + type: `count`, + drillMembers: [Orders.status, Users.city, count], + }, + // ... +} +``` + +Then you can use the `drillDown` method to see the rows that contribute to that metric +```js +resultSet.drillDown( + { + xValues, + yValues, + }, + // you should pass the `pivotConfig` if you have used it for axes manipulation + pivotConfig +) +``` + +the result will be a query with the required filters applied and the dimensions/measures filled out +```js +{ + measures: ['Orders.count'], + dimensions: ['Orders.status', 'Users.city'], + filters: [ + // dimension and measure filters + ], + timeDimensions: [ + //... + ] +} +``` + +In case when you want to add `order` or `limit` to the query, you can simply spread it + +```js +// An example for React +const drillDownResponse = useCubeQuery( + { + ...drillDownQuery, + limit: 30, + order: { + 'Orders.ts': 'desc' + } + }, + { + skip: !drillDownQuery + } + ); +``` + +### `pivot` + +> **pivot**(**pivotConfig?**: [PivotConfig](#pivotconfig)): *[PivotRow](#pivotrow)[]* + +Base method for pivoting [ResultSet](#resultset) data. +Most of the times shouldn't be used directly and [`chartPivot`](#chartpivot) +or [`tablePivot`](#tablepivot) should be used instead. + +You can find the examples of using the `pivotConfig` [here](#pivotconfig) +```js +// For query +{ + measures: ['Stories.count'], + timeDimensions: [{ + dimension: 'Stories.time', + dateRange: ['2015-01-01', '2015-03-31'], + granularity: 'month' + }] +} + +// ResultSet.pivot({ x: ['Stories.time'], y: ['measures'] }) will return +[ + { + xValues: ["2015-01-01T00:00:00"], + yValuesArray: [ + [['Stories.count'], 27120] + ] + }, + { + xValues: ["2015-02-01T00:00:00"], + yValuesArray: [ + [['Stories.count'], 25861] + ] + }, + { + xValues: ["2015-03-01T00:00:00"], + yValuesArray: [ + [['Stories.count'], 29661] + ] + } +] +``` + +### `query` + +> **query**(): *[Query](#query-2)* + +### `rawData` + +> **rawData**(): *T[]* + +### `serialize` + +> **serialize**(): *Object* + +Can be used to stash the `ResultSet` in a storage and restored later with [deserialize](#deserialize) + +### `series` + +> **series**‹**SeriesItem**›(**pivotConfig?**: [PivotConfig](#pivotconfig)): *[Series](#series-2)‹SeriesItem›[]* + +Returns an array of series with key, title and series data. +```js +// For the query +{ + measures: ['Stories.count'], + timeDimensions: [{ + dimension: 'Stories.time', + dateRange: ['2015-01-01', '2015-12-31'], + granularity: 'month' + }] +} + +// ResultSet.series() will return +[ + { + key: 'Stories.count', + title: 'Stories Count', + series: [ + { x: '2015-01-01T00:00:00', value: 27120 }, + { x: '2015-02-01T00:00:00', value: 25861 }, + { x: '2015-03-01T00:00:00', value: 29661 }, + //... + ], + }, +] +``` + +**Type parameters:** + +- **SeriesItem** + +### `seriesNames` + +> **seriesNames**(**pivotConfig?**: [PivotConfig](#pivotconfig)): *[SeriesNamesColumn](#seriesnamescolumn)[]* + +Returns an array of series objects, containing `key` and `title` parameters. +```js +// For query +{ + measures: ['Stories.count'], + timeDimensions: [{ + dimension: 'Stories.time', + dateRange: ['2015-01-01', '2015-12-31'], + granularity: 'month' + }] +} + +// ResultSet.seriesNames() will return +[ + { + key: 'Stories.count', + title: 'Stories Count', + yValues: ['Stories.count'], + }, +] +``` + +### `tableColumns` + +> **tableColumns**(**pivotConfig?**: [PivotConfig](#pivotconfig)): *[TableColumn](#tablecolumn)[]* + +Returns an array of column definitions for `tablePivot`. + +For example: +```js +// For the query +{ + measures: ['Stories.count'], + timeDimensions: [{ + dimension: 'Stories.time', + dateRange: ['2015-01-01', '2015-12-31'], + granularity: 'month' + }] +} + +// ResultSet.tableColumns() will return +[ + { + key: 'Stories.time', + dataIndex: 'Stories.time', + title: 'Stories Time', + shortTitle: 'Time', + type: 'time', + format: undefined, + }, + { + key: 'Stories.count', + dataIndex: 'Stories.count', + title: 'Stories Count', + shortTitle: 'Count', + type: 'count', + format: undefined, + }, + //... +] +``` + +In case we want to pivot the table axes +```js +// Let's take this query as an example +{ + measures: ['Orders.count'], + dimensions: ['Users.country', 'Users.gender'] +} + +// and put the dimensions on `y` axis +resultSet.tableColumns({ + x: [], + y: ['Users.country', 'Users.gender', 'measures'] +}) +``` + +then `tableColumns` will group the table head and return +```js +{ + key: 'Germany', + type: 'string', + title: 'Users Country Germany', + shortTitle: 'Germany', + meta: undefined, + format: undefined, + children: [ + { + key: 'male', + type: 'string', + title: 'Users Gender male', + shortTitle: 'male', + meta: undefined, + format: undefined, + children: [ + { + // ... + dataIndex: 'Germany.male.Orders.count', + shortTitle: 'Count', + }, + ], + }, + { + // ... + shortTitle: 'female', + children: [ + { + // ... + dataIndex: 'Germany.female.Orders.count', + shortTitle: 'Count', + }, + ], + }, + ], +}, +// ... +``` + +### `tablePivot` + +> **tablePivot**(**pivotConfig?**: [PivotConfig](#pivotconfig)): *Array‹object›* + +Returns normalized query result data prepared for visualization in the table format. + +You can find the examples of using the `pivotConfig` [here](#pivotconfig) + +For example: +```js +// For the query +{ + measures: ['Stories.count'], + timeDimensions: [{ + dimension: 'Stories.time', + dateRange: ['2015-01-01', '2015-12-31'], + granularity: 'month' + }] +} + +// ResultSet.tablePivot() will return +[ + { "Stories.time": "2015-01-01T00:00:00", "Stories.count": 27120 }, + { "Stories.time": "2015-02-01T00:00:00", "Stories.count": 25861 }, + { "Stories.time": "2015-03-01T00:00:00", "Stories.count": 29661 }, + //... +] +``` + +### `deserialize` + +> `static` **deserialize**‹**TData**›(**data**: Object, **options?**: Object): *[ResultSet](#resultset)‹TData›* + +```js +import { ResultSet } from '@cubejs-client/core'; + +const resultSet = await cubeApi.load(query); +// You can store the result somewhere +const tmp = resultSet.serialize(); + +// and restore it later +const resultSet = ResultSet.deserialize(tmp); +``` + +**Type parameters:** + +- **TData** + +**Parameters:** + +Name | Type | Description | +------ | ------ | ------ | +data | Object | the result of [serialize](#serialize) | +options? | Object | - | + +### `getNormalizedPivotConfig` + +> `static` **getNormalizedPivotConfig**(**query**: [PivotQuery](#pivotquery), **pivotConfig?**: Partial‹[PivotConfig](#pivotconfig)›): *[PivotConfig](#pivotconfig)* + +## `SqlQuery` + +### `rawQuery` + +> **rawQuery**(): *[SqlData](#sqldata)* + +### `sql` + +> **sql**(): *string* + +## `ITransport` + +### `request` + +> **request**(**method**: string, **params**: any): () => *Promise‹void›* + +## Types + +### `Annotation` + +Name | Type | +------ | ------ | +format? | "currency" | "percent" | "number" | +shortTitle | string | +title | string | +type | string | + +### `CacheMode` + +> **CacheMode**: *"stale-if-slow" | "stale-while-revalidate" | "must-revalidate" | "no-cache"* + +Cache mode options for query execution. See [cache control][ref-cache-control] for details on available strategies. + +### `BinaryFilter` + +Name | Type | +------ | ------ | +and? | [BinaryFilter](#binaryfilter)[] | +dimension? | string | +member? | string | +operator | [BinaryOperator](#binaryoperator) | +or? | [BinaryFilter](#binaryfilter)[] | +values | string[] | + +### `BinaryOperator` + +> **BinaryOperator**: *"equals" | "notEquals" | "contains" | "notContains" | "gt" | "gte" | "lt" | "lte" | "inDateRange" | "notInDateRange" | "beforeDate" | "afterDate"* + +### `ChartPivotRow` + +Name | Type | +------ | ------ | +x | string | +xValues | string[] | + +### `Column` + +Name | Type | +------ | ------ | +key | string | +series | [] | +title | string | + +### `CubeApiOptions` + +Name | Type | Description | +------ | ------ | ------ | +apiUrl | string | URL of your Cube API. By default, in the development environment it is `http://localhost:4000/cubejs-api/v1` | +credentials? | "omit" | "same-origin" | "include" | - | +headers? | Record‹string, string› | - | +parseDateMeasures? | boolean | - | +pollInterval? | number | - | +transport? | [ITransport](#itransport) | Transport implementation to use. [HttpTransport](#httptransport) will be used by default. | +signal? | AbortSignal | AbortSignal to cancel requests | + +### `DateRange` + +> **DateRange**: *string | [string, string]* + +### `DrillDownLocator` + +Name | Type | +------ | ------ | +xValues | string[] | +yValues? | string[] | + +### `Filter` + +> **Filter**: *[BinaryFilter](#binaryfilter) | [UnaryFilter](#unaryfilter)* + +### `LoadMethodCallback` + +> **LoadMethodCallback**: *function* + +### `LoadMethodOptions` + +Name | Type | Optional? | Description | +------ | ------ | ------ | --- | +`cache` | [`CacheMode`](#cachemode) | ✅ Yes | Server-side cache policy for query execution. Does not control client-side caching. See [cache control][ref-cache-control] for details on available strategies. | +`castNumerics` | `boolean` | ✅ Yes | Pass `true` if you'd like all members with the `number` type to be automatically converted to JavaScript `Number` type. Note that this is a potentially unsafe operation since numbers more than [`Number.MAX_SAFE_INTEGER`][link-mdn-max-safe-integer] or less than `Number.MIN_SAFE_INTEGER` can't be represented as JavaScript `Number` | +`mutexKey` | `string` | ✅ Yes | Key to store the current request's MUTEX inside the `mutexObj`. MUTEX object is used to reject orphaned queries results when new queries are sent. For example: if two queries are sent with the same `mutexKey` only the last one will return results. | +`mutexObj` | `Object` | ✅ Yes | Object to store MUTEX | +`progressCallback` | | ✅ Yes | | +`subscribe` | `boolean` | ✅ Yes | Pass `true` to use continuous fetch behavior. | +`signal` | `AbortSignal` | ✅ Yes | AbortSignal to cancel the request. This allows you to manually abort requests using AbortController. | +`baseRequestId` | `string` | ✅ Yes | Base request ID ([`spanId`](https://cube.dev/docs/product/apis-integrations/core-data-apis/rest-api#request-span-annotation)) to be used for the request. If not provided a random request ID will be generated. | + +### `LoadResponse` + +Name | Type | +------ | ------ | +pivotQuery | [PivotQuery](#pivotquery) | +queryType | [QueryType](#querytype) | +results | [LoadResponseResult](#loadresponseresult)‹T›[] | + +### `LoadResponseResult` + +Name | Type | +------ | ------ | +annotation | [QueryAnnotations](#queryannotations) | +data | T[] | +lastRefreshTime | string | +query | [Query](#query-2) | + +### `MemberType` + +> **MemberType**: *"measures" | "dimensions" | "segments"* + +### `PivotConfig` + +Configuration object that contains information about pivot axes and other options. + +Let's apply `pivotConfig` and see how it affects the axes +```js +// Example query +{ + measures: ['Orders.count'], + dimensions: ['Users.country', 'Users.gender'] +} +``` +If we put the `Users.gender` dimension on **y** axis +```js +resultSet.tablePivot({ + x: ['Users.country'], + y: ['Users.gender', 'measures'] +}) +``` + +The resulting table will look the following way + +| Users Country | male, Orders.count | female, Orders.count | +| ------------- | ------------------ | -------------------- | +| Australia | 3 | 27 | +| Germany | 10 | 12 | +| US | 5 | 7 | + +Now let's put the `Users.country` dimension on **y** axis instead +```js +resultSet.tablePivot({ + x: ['Users.gender'], + y: ['Users.country', 'measures'], +}); +``` + +in this case the `Users.country` values will be laid out on **y** or **columns** axis + +| Users Gender | Australia, Orders.count | Germany, Orders.count | US, Orders.count | +| ------------ | ----------------------- | --------------------- | ---------------- | +| male | 3 | 10 | 5 | +| female | 27 | 12 | 7 | + +It's also possible to put the `measures` on **x** axis. But in either case it should always be the last item of the array. +```js +resultSet.tablePivot({ + x: ['Users.gender', 'measures'], + y: ['Users.country'], +}); +``` + +| Users Gender | measures | Australia | Germany | US | +| ------------ | ------------ | --------- | ------- | --- | +| male | Orders.count | 3 | 10 | 5 | +| female | Orders.count | 27 | 12 | 7 | + +Name | Type | Description | +------ | ------ | ------ | +aliasSeries? | string[] | Give each series a prefix alias. Should have one entry for each query:measure. See [chartPivot](#chartpivot) | +fillMissingDates? | boolean | null | **`true` by default.** If set to `true`, missing dates on the time dimensions will be filled with `fillWithValue` or `0` by default for all measures. Note: setting this option to `true` will override any `order` applied to the query. | +fillWithValue? | string | null | Value to autofill all the missing date's measure. | +x? | string[] | Dimensions to put on **x** or **rows** axis. | +y? | string[] | Dimensions to put on **y** or **columns** axis. | + +### `PivotQuery` + +> **PivotQuery**: *[Query](#query-2) & object* + +### `PivotRow` + +Name | Type | +------ | ------ | +xValues | Array‹string | number› | +yValuesArray | Array‹[string[], number]› | + +### `ProgressResponse` + +Name | Type | +------ | ------ | +stage | string | +timeElapsed | number | + +### `Query` + +Name | Type | +------ | ------ | +dimensions? | string[] | +filters? | [Filter](#filter)[] | +limit? | number | +measures? | string[] | +offset? | number | +order? | [TQueryOrderObject](#tqueryorderobject) | [TQueryOrderArray](#tqueryorderarray) | +renewQuery? | boolean | +segments? | string[] | +timeDimensions? | [TimeDimension](#timedimension)[] | +timezone? | string | +ungrouped? | boolean | + +### `QueryAnnotations` + +Name | Type | +------ | ------ | +dimensions | Record‹string, [Annotation](#annotation-2)› | +measures | Record‹string, [Annotation](#annotation-2)› | +timeDimensions | Record‹string, [Annotation](#annotation-2)› | + +### `QueryOrder` + +> **QueryOrder**: *"asc" | "desc"* + +### `QueryType` + +> **QueryType**: *"regularQuery" | "compareDateRangeQuery" | "blendingQuery"* + +### `Series` + +Name | Type | +------ | ------ | +key | string | +series | T[] | +title | string | + +### `SeriesNamesColumn` + +Name | Type | +------ | ------ | +key | string | +title | string | +yValues | string[] | + +### `SqlApiResponse` + +Name | Type | +------ | ------ | +sql | [SqlData](#sqldata) | + +### `SqlData` + +Name | Type | +------ | ------ | +aliasNameToMember | Record‹string, string› | +cacheKeyQueries | object | +dataSource | boolean | +external | boolean | +sql | [SqlQueryTuple](#sqlquerytuple) | + +### `SqlQueryTuple` + +> **SqlQueryTuple**: *[string, boolean | string | number]* + +### `TCubeDimension` + +> **TCubeDimension**: *[TCubeMember](#tcubemember) & object* + +### `TCubeMeasure` + +> **TCubeMeasure**: *[TCubeMember](#tcubemember) & object* + +### `TCubeMember` + +Name | Type | +------ | ------ | +name | string | +shortTitle | string | +title | string | +isVisible? | boolean | +meta? | any | +type | [TCubeMemberType](#tcubemembertype) | + +### `TCubeMemberByType` + +> **TCubeMemberByType**: *T extends "measures" ? TCubeMeasure : T extends "dimensions" ? TCubeDimension : T extends "segments" ? TCubeSegment : never* + +### `TCubeMemberType` + +> **TCubeMemberType**: *"time" | "number" | "string" | "boolean"* + +### `TCubeSegment` + +> **TCubeSegment**: *Pick‹[TCubeMember](#tcubemember), "name" | "shortTitle" | "title"›* + +### `TDefaultHeuristicsOptions` + +Name | Type | +------ | ------ | +meta | [Meta](#meta-2) | +sessionGranularity? | [TimeDimensionGranularity](#timedimensiongranularity) | + +### `TDryRunResponse` + +Name | Type | +------ | ------ | +normalizedQueries | [Query](#query-2)[] | +pivotQuery | [PivotQuery](#pivotquery) | +queryOrder | Array‹object› | +queryType | [QueryType](#querytype) | + +### `TFlatFilter` + +Name | Type | +------ | ------ | +dimension? | string | +member? | string | +operator | [BinaryOperator](#binaryoperator) | +values | string[] | + +### `TQueryOrderArray` + +> **TQueryOrderArray**: *Array‹[string, [QueryOrder](#queryorder)]›* + +### `TQueryOrderObject` + +### `TableColumn` + +Name | Type | +------ | ------ | +children? | [TableColumn](#tablecolumn)[] | +dataIndex | string | +format? | any | +key | string | +meta | any | +shortTitle | string | +title | string | +type | string | number | + +### `TimeDimension` + +> **TimeDimension**: *[TimeDimensionComparison](#timedimensioncomparison) | [TimeDimensionRanged](#timedimensionranged)* + +### `TimeDimensionBase` + +Name | Type | +------ | ------ | +dimension | string | +granularity? | [TimeDimensionGranularity](#timedimensiongranularity) | + +### `TimeDimensionComparison` + +> **TimeDimensionComparison**: *[TimeDimensionBase](#timedimensionbase) & object* + +### `TimeDimensionGranularity` + +> **TimeDimensionGranularity**: *"second" | "minute" | "hour" | "day" | "week" | "month" | "year"* + +### `TimeDimensionRanged` + +> **TimeDimensionRanged**: *[TimeDimensionBase](#timedimensionbase) & object* + +### `TransportOptions` + +Name | Type | Description | +------ | ------ | ------ | +apiUrl | string | path to `/cubejs-api/v1` | +authorization | string | [jwt auth token][ref-security] | +credentials? | "omit" | "same-origin" | "include" | - | +headers? | Record‹string, string› | custom headers | +signal? | AbortSignal | AbortSignal to cancel requests | + +### `UnaryFilter` + +Name | Type | +------ | ------ | +and? | [UnaryFilter](#unaryfilter)[] | +dimension? | string | +member? | string | +operator | [UnaryOperator](#unaryoperator) | +or? | [UnaryFilter](#unaryfilter)[] | +values? | never | + +### `UnaryOperator` + +> **UnaryOperator**: *"set" | "notSet"* + + + +[link-mdn-max-safe-integer]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/MAX_SAFE_INTEGER + +[ref-query-format]: /reference/core-data-apis/rest-api/query-format +[ref-security]: /docs/data-modeling/access-control +[ref-cache-control]: /reference/core-data-apis/rest-api#cache-control \ No newline at end of file diff --git a/docs-mintlify/reference/javascript-sdk/reference/cubejs-client-ngx.mdx b/docs-mintlify/reference/javascript-sdk/reference/cubejs-client-ngx.mdx new file mode 100644 index 0000000000000..3ada4c073bd8e --- /dev/null +++ b/docs-mintlify/reference/javascript-sdk/reference/cubejs-client-ngx.mdx @@ -0,0 +1,101 @@ +--- +title: "`@cubejs-client/ngx`" +description: "@cubejs-client/ngx provides Angular Module for easy integration Cube into an Angular app." +--- + +## Installation + +First, install `@cubejs-client/ngx` using npm or yarn: + +```bash +npm install --save @cubejs-client/ngx +# or +yarn add @cubejs-client/ngx +``` + +Now you can add `CubeClientModule` to your **app.module.ts** file: + +```typescript +import { CubeClientModule } from '@cubejs-client/ngx'; +import { environment } from '../../environments/environment'; + +const cubeOptions = { + token: environment.CUBE_API_TOKEN, + options: { apiUrl: environment.CUBE_API_URL } +}; + +@NgModule({ + declarations: [ + ... + ], + imports: [ + ..., + CubeClientModule.forRoot(cubeOptions) + ], + providers: [...], + bootstrap: [...] +}) +export class AppModule { } +``` + +The `options` object is passed directly to +[`@cubejs-client/core`](/reference/javascript-sdk/reference/cubejs-client-core). + +`CubeClientModule` provides `CubeClient`, which you can inject into your +components or services: + +```typescript +import { CubeClient } from "@cubejs-client/ngx"; + +export class AppComponent { + constructor(private cube: CubeClient) {} + + ngOnInit() { + this.cube + .load({ + measures: ["some_measure"], + }) + .subscribe( + (resultSet) => { + this.data = resultSet.chartPivot(); + }, + (err) => console.log("HTTP Error", err) + ); + } +} +``` + +## API + +`CubeClient` provides the same API methods as +[`@cubejs-client/core`](/reference/javascript-sdk/reference/cubejs-client-core#cubeapi). The +difference is that instead of Promise it returns an +[Observable](http://reactivex.io/rxjs/class/es6/Observable.js~Observable.html), +which passes [`resultSet`](/reference/javascript-sdk/reference/cubejs-client-core#resultset) into the +callback function. + +Also you can use [RxJS Subject](https://rxjs-dev.firebaseapp.com/guide/subject) +with a query using `watch` method: + +```typescript +private query; + +ngOnInit() { + this.query = new Subject(); + this.cube.watch(this.query).subscribe( + resultSet => { + console.log(resultSet.chartPivot()[0].x); + console.log(resultSet.seriesNames()[0]); + }, + err => console.log('HTTP Error', err) + ); +} + +button1ClickHandler() { + this.query.next({ query_1 }); +} + +button2ClickHandler() { + this.query.next({ query_2 }); +} +``` diff --git a/docs-mintlify/reference/javascript-sdk/reference/cubejs-client-react.mdx b/docs-mintlify/reference/javascript-sdk/reference/cubejs-client-react.mdx new file mode 100644 index 0000000000000..24e15b476d1c4 --- /dev/null +++ b/docs-mintlify/reference/javascript-sdk/reference/cubejs-client-react.mdx @@ -0,0 +1,384 @@ +--- +title: "`@cubejs-client/react`" +description: "@cubejs-client/react provides React Components for easy Cube integration in a React app." +--- + +## `useCubeQuery` + +> **useCubeQuery**‹**TData**›(**query**: Query | Query[], **options?**: [UseCubeQueryOptions](#usecubequeryoptions)): *[UseCubeQueryResult](#usecubequeryresult)‹Query, TData›* + +A React hook for executing Cube queries +```js +import React from 'react'; +import { Table } from 'antd'; +import { useCubeQuery } from '@cubejs-client/react'; + +export default function App() { + const { resultSet, isLoading, error, progress } = useCubeQuery({ + measures: ['Orders.count'], + dimensions: ['Orders.createdAt.month'], + }); + + if (isLoading) { + return
{progress && progress.stage && progress.stage.stage || 'Loading...'}
; + } + + if (error) { + return
{error.toString()}
; + } + + if (!resultSet) { + return null; + } + + const dataSource = resultSet.tablePivot(); + const columns = resultSet.tableColumns(); + + return ; +} + +``` + +**Type parameters:** + +- **TData** + +### `UseCubeQueryOptions` + +Name | Type | Description | Optional? | +------ | ------ | ------ | --- | +`cubeApi` | `CubeApi` | A `CubeApi` instance to use. Taken from the context if the param is not passed | ✅ Yes | +`resetResultSetOnChange` | `boolean` | When `true` the resultSet will be reset to `null` first | ✅ Yes | +`skip` | `boolean` | Query execution will be skipped when `skip` is set to `true`. You can use this flag to avoid sending incomplete queries. | ✅ Yes | +`subscribe` | `boolean` | Use continuous fetch behavior. See [Real-Time Data Fetch](/recipes/core-data-api/real-time-data-fetch) | ✅ Yes | +`cache` | [`CacheMode`](/reference/javascript-sdk/reference/cubejs-client-core#cachemode) | Server-side cache policy for query execution. Does not control client-side caching. See [cache control][ref-cache-control] for details on available strategies. | ✅ Yes | +`castNumerics` | `boolean` | Pass `true` if you'd like all members with the `number` type to be automatically converted to JavaScript `Number` type. Note that this is a potentially unsafe operation since numbers more than [`Number.MAX_SAFE_INTEGER`][link-mdn-max-safe-integer] or less than `Number.MIN_SAFE_INTEGER` can't be represented as JavaScript `Number` | ✅ Yes | + +### `UseCubeQueryResult` + +Name | Type | +------ | ------ | +error | Error | null | +isLoading | boolean | +previousQuery | TQuery | +progress | ProgressResponse | +resultSet | ResultSet‹TData› | null | + +## `isQueryPresent` + +> **isQueryPresent**(**query**: Query | Query[]): *boolean* + +Checks whether the query is ready + +## `QueryBuilder` + +> **QueryBuilder** extends **React.Component** ‹[QueryBuilderProps](#querybuilderprops), [QueryBuilderState](#querybuilderstate)›: + +`` is used to build interactive analytics query builders. It abstracts state management and API calls to Cube API. It uses render prop technique and doesn’t render anything itself, but calls the render function instead. + +**Example** + +[Open in CodeSandbox](https://codesandbox.io/s/z6r7qj8wm) +```js +import React from 'react'; +import ReactDOM from 'react-dom'; +import { Layout, Divider, Empty, Select } from 'antd'; +import { QueryBuilder } from '@cubejs-client/react'; +import cube from '@cubejs-client/core'; +import 'antd/dist/antd.css'; + +import ChartRenderer from './ChartRenderer'; + +const cubeApi = cube('YOUR-CUBE-API-TOKEN', { + apiUrl: 'http://localhost:4000/cubejs-api/v1', +}); + +const App = () => ( + ( + + + + {measures.length > 0 ? ( + + ) : ( + + )} + + )} + /> +); + +const rootElement = document.getElementById("root"); +ReactDOM.render(, rootElement); +``` + +### `QueryBuilderProps` + +Name | Type | Description | +------ | ------ | ------ | +cubeApi | CubeApi | `CubeApi` instance to use | +defaultChartType? | [ChartType](#charttype) | - | +disableHeuristics? | boolean | Defaults to `false`. This means that the default heuristics will be applied. For example: when the query is empty and you select a measure that has a default time dimension it will be pushed to the query. | +query? | Query | Default query | +render | (**renderProps**: [QueryBuilderRenderProps](#querybuilderrenderprops)) => *React.ReactNode* | - | +setQuery? | (**query**: Query) => *void* | Called by the `QueryBuilder` when the query state has changed. Use it when state is maintained outside of the `QueryBuilder` component. | +setVizState? | (**vizState**: [VizState](#vizstate)) => *void* | - | +stateChangeHeuristics? | (**state**: [QueryBuilderState](#querybuilderstate)) => *[QueryBuilderState](#querybuilderstate)* | A function that accepts the `newState` just before it's applied. You can use it to override the **defaultHeuristics** or to tweak the query or the vizState in any way. | +vizState? | [VizState](#vizstate) | - | +wrapWithQueryRenderer? | boolean | Defaults to `true`. Use QueryRenderer to render. Set this to `false` to use your own QueryRenderer. | + +### `QueryBuilderRenderProps` + +Name | Type | Description | +------ | ------ | ------ | +availableDimensions | TCubeDimension[] | An array of available dimensions to select. They are loaded via the API from Cube. | +availableMeasures | TCubeMeasure[] | An array of available measures to select. They are loaded via the API from Cube. | +availableSegments | TCubeMember[] | An array of available segments to select. They are loaded via the API from Cube. | +availableTimeDimensions | TCubeDimension[] | An array of available time dimensions to select. They are loaded via the API from Cube. | +dimensions | string[] | - | +error? | Error | null | - | +isQueryPresent | boolean | Indicates whether the query is ready to be displayed or not | +loadingState? | [TLoadingState](#tloadingstate) | - | +measures | string[] | - | +resultSet? | ResultSet | null | - | +segments | string[] | - | +timeDimensions | Filter[] | - | +updateDimensions | [MemberUpdater](#memberupdater) | - | +updateMeasures | [MemberUpdater](#memberupdater) | - | +updateQuery | (**query**: Query) => *void* | Used for partial of full query update | +updateSegments | [MemberUpdater](#memberupdater) | - | +updateTimeDimensions | [MemberUpdater](#memberupdater) | - | + +### `QueryBuilderState` + +> **QueryBuilderState**: *[VizState](#vizstate) & object* + +## `QueryRenderer` + +> **QueryRenderer** extends **React.Component** ‹[QueryRendererProps](#queryrendererprops)›: + +`` a react component that accepts a query, fetches the given query, and uses the render prop to render the resulting data + +### `QueryRendererProps` + +Name | Type | Description | +------ | ------ | ------ | +cache? | [`CacheMode`](/reference/javascript-sdk/reference/cubejs-client-core#cachemode) | Server-side cache policy for query execution. Does not control client-side caching. See [cache control][ref-cache-control] for details on available strategies. | +cubeApi | CubeApi | `CubeApi` instance to use | +loadSql? | "only" | boolean | Indicates whether the SQL Code generated by Cube should be requested. See [rest-api#sql](/reference/core-data-apis/rest-api/reference#base_path/v1/sql). When set to `only` then only the request to [/v1/sql](/reference/core-data-apis/rest-api/reference#base_path/v1/sql) will be performed. When set to `true` the sql request will be performed along with the query request. Will not be performed if set to `false` | +queries? | object | - | +query | Query | Analytic query. [Learn more about it's format](/reference/core-data-apis/rest-api/query-format) | +render | (**renderProps**: [QueryRendererRenderProps](#queryrendererrenderprops)) => *void* | Output of this function will be rendered by the `QueryRenderer` | +resetResultSetOnChange? | boolean | When `true` the **resultSet** will be reset to `null` first on every state change | +updateOnlyOnStateChange? | boolean | - | + +### `QueryRendererRenderProps` + +Name | Type | +------ | ------ | +error | Error | null | +loadingState | [TLoadingState](#tloadingstate) | +resultSet | ResultSet | null | + +## `CubeProvider` + +> **CubeProvider**: *React.FC‹[CubeProviderProps](#cubeproviderprops)›* + +Cube context provider +```js +import React from 'react'; +import cube from '@cubejs-client/core'; +import { CubeProvider } from '@cubejs-client/react'; + +const API_URL = 'https://harsh-eel.aws-us-east-2.cubecloudapp.dev'; +const CUBE_TOKEN = + 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.* eyJpYXQiOjE1OTE3MDcxNDgsImV4cCI6MTU5NDI5OTE0OH0.* n5jGLQJ14igg6_Hri_Autx9qOIzVqp4oYxmX27V-4T4'; + +const cubeApi = cube(CUBE_TOKEN, { + apiUrl: `${API_URL}/cubejs-api/v1`, +}); + +export default function App() { + return ( + + //... + + ) +} +``` + +## `CubeContext` + +> **CubeContext**: *Context‹[CubeContextProps](#cubecontextprops)›* + +In case when you need direct access to `cubeApi` you can use `CubeContext` anywhere in your app + +```js +import React from 'react'; +import { CubeContext } from '@cubejs-client/react'; + +export default function DisplayComponent() { + const { cubeApi } = React.useContext(CubeContext); + const [rawResults, setRawResults] = React.useState([]); + const query = { + ... + }; + + React.useEffect(() => { + cubeApi.load(query).then((resultSet) => { + setRawResults(resultSet.rawData()); + }); + }, [query]); + + return ( + <> + {rawResults.map(row => ( + ... + ))} + + ) +} +``` + +## Types + +### `ChartType` + +> **ChartType**: *"line" | "bar" | "table" | "area"* + +### `CubeContextProps` + +Name | Type | Optional? | +------ | ------ | --- | +`cubeApi` | `CubeApi` | ❌ No | +`options` | `CubeProviderOptions` | ✅ Yes | + +### `CubeProviderProps` + +Name | Type | Optional? | +------ | ------ | --- | +`cubeApi` | `CubeApi` | ❌ No | +`children` | `React.ReactNode` | ❌ No | +`options` | `CubeProviderOptions` | ✅ Yes | + +### `CubeProviderOptions` + +Name | Type | Optional? | +------ | ------ | --- | +`castNumerics` | `boolean` | ✅ Yes | + +### `MemberUpdater` + +You can use the following methods for member manipulaltion +```js + { + return ( + // ... + + ); + }} +/> +``` + +NOTE: if you need to add or remove more than one member at a time you should use `updateQuery` prop of [QueryBuilderRenderProps](#querybuilderrenderprops) +```js + { + // ... + return ( + <> + // WRONG: This code will not work properly + + + // CORRECT: Using `updateQuery` for removing all measures + + + ); + }} +/> +``` + +Name | Type | +------ | ------ | +add | (**member**: MemberType) => *void* | +remove | (**member**: MemberType) => *void* | +update | (**member**: MemberType, **updateWith**: MemberType) => *void* | + +### `TLoadingState` + +Name | Type | +------ | ------ | +isLoading | boolean | + +### `VizState` + +Name | Type | +------ | ------ | +chartType? | [ChartType](#charttype) | +pivotConfig? | PivotConfig | +shouldApplyHeuristicOrder? | boolean | + + +[link-mdn-max-safe-integer]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/MAX_SAFE_INTEGER +[ref-cache-control]: /reference/core-data-apis/rest-api#cache-control \ No newline at end of file diff --git a/docs-mintlify/reference/javascript-sdk/reference/cubejs-client-vue.mdx b/docs-mintlify/reference/javascript-sdk/reference/cubejs-client-vue.mdx new file mode 100644 index 0000000000000..5d49edf22229f --- /dev/null +++ b/docs-mintlify/reference/javascript-sdk/reference/cubejs-client-vue.mdx @@ -0,0 +1,278 @@ +--- +title: "`@cubejs-client/vue3`" +description: "@cubejs-client/vue3 provides Vue Components to easily integrate Cube within a Vue.js app." +--- + +## QueryBuilder + +`` is used to build interactive analytics query builders. It +abstracts state management and API calls to Cube Backend. It uses scoped slot +props technique. + +### Props + +| Name | Type | Description | +| ---------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| cubeApi | [`CubeApi`](/reference/javascript-sdk/reference/cubejs-client-core#cubeapi) | `CubeApi` instance to use | +| initialChartType? | [ChartType](#charttype) | The type of chart to display initially. Default is `line`. | +| disableHeuristics? | boolean | Defaults to `false`. This means that the default heuristics will be applied. For example: when the query is empty and you select a measure that has a default time dimension it will be pushed to the query. | +| query? | Query | Query parameters ([learn more about the format](/reference/core-data-apis/rest-api/query-format)). This property is reactive - if you change the object here, the internal query values will be overwritten. This is not two-way. | +| stateChangeHeuristics? | (**state**: [QueryBuilderState](#querybuilderstate)) => _[QueryBuilderState](#querybuilderstate)_ | A function that accepts the `newState` just before it's applied. You can use it to override the **defaultHeuristics** or to tweak the query or the vizState in any way. | +| initialVizState? | [VizState](#vizstate) | - | +| wrapWithQueryRenderer? | boolean | Defaults to `true`. Use QueryRenderer to render. Set this to `false` to use your own QueryRenderer. | + +### Slots + +#### Default Slot + +##### Slot Props + +- `resultSet`: A `resultSet` is an object containing data obtained from the + query. [`ResultSet`](/reference/javascript-sdk/reference/cubejs-client-core#resultset) object + provides a convenient interface for data manipulation. + +#### Empty Slot + +This slot functions as an empty/loading state; when the query is loading or +empty, you can show something in the meantime. + +#### Error Slot + +This slot will be rendered if any error happens while the query is loading or +rendering. + +##### Slot Props + +- `error`: the error. +- `sqlQuery`: the attempted query. + +#### Builder Slot + +- `measures`, `dimensions`, `segments`, `timeDimensions`, `filters` - arrays + containing the selected query builder members. +- `availableMeasures`, `availableDimensions`, `availableTimeDimensions`, + `availableSegments` - arrays containing available members to select. They are + loaded via API from Cube Backend. +- `addMeasures`, `addDimensions`, `addSegments`, `addTimeDimensions` - functions + to control the adding of new members to query builder. +- `removeMeasures`, `removeDimensions`, `removeSegments`, + `removeTimeDimensions` - functions to control the removing of members to query + builder. +- `setMeasures`, `setDimensions`, `setSegments`, `setTimeDimensions` - functions + to control the setting of members to query builder. +- `updateMeasures`, `updateDimensions`, `updateSegments`, + `updateTimeDimensions` - functions to control the updating of members to query + builder. +- `chartType` - string containing currently selected chart type. +- `updateChartType` - function-setter for chart type. +- `isQueryPresent` - bool indicating whether is query ready to be displayed or + not. +- `query` - current query, based on selected members. +- `setLimit`, `removeLimit` - functions to control the number of results + returned. +- `setOffset`, `removeOffset` - functions to control the number of rows skipped + before results returned. Use with limit to control pagination. + +### Example + + + Open in CodeSandbox + + +```html + + + +``` + +## QueryRenderer + +`` Vue component takes a query, fetches the given query, and +uses the slot scoped props to render the resulting data. + +### Props + +| Name | Type | Description | +| -------- | --------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| cubeApi | CubeApi | `CubeApi` instance to use | +| loadSql? | "only" | boolean | Indicates whether the generated by Cube SQL Code should be requested. See [rest-api#sql](/reference/core-data-apis/rest-api/reference#base_path/v1/sql). When set to `only` then only the request to [/v1/sql](/reference/core-data-apis/rest-api/reference#base_path/v1/sql) will be performed. When set to `true` the sql request will be performed along with the query request. Will not be performed if set to `false` | +| queries? | object | - | +| query | Query | Analytic query. [Learn more about it's format](/reference/core-data-apis/rest-api/query-format) | + +### Slots + +#### Default Slot + +##### Slot Props + +- `resultSet`: A `resultSet` is an object containing data obtained from the + query. [`ResultSet`](/reference/javascript-sdk/reference/cubejs-client-core#resultset) object + provides a convenient interface for data manipulation. + +#### Empty Slot + +This slot functions as an empty/loading state; when the query is loading or +empty, you can show something in the meantime. + +#### Error Slot + +This slot will be rendered if any error happens while the query is loading or +rendering. + +##### Slot Props + +- `error`: the error. +- `sqlQuery`: the attempted query. + +### Example + +```html + + + + + + +``` + +## Types + +### ChartType + +> **ChartType**: _"line" | "bar" | "table" | "area" | "number" | "pie"_ + +### QueryBuilderState + +| Name | Type | +| ---------- | ----------------------------------------------------- | +| query | [`Query`](/reference/javascript-sdk/reference/cubejs-client-core#query-2) | +| chartType? | [ChartType](#charttype) | + +### VizState + +| Name | Type | +| -------------------------- | ------------------------------------------------------------------ | +| chartType? | [ChartType](#charttype) | +| pivotConfig? | [`PivotConfig`](/reference/javascript-sdk/reference/cubejs-client-core#pivotconfig) | +| shouldApplyHeuristicOrder? | boolean | diff --git a/docs-mintlify/reference/javascript-sdk/reference/cubejs-client-ws-transport.mdx b/docs-mintlify/reference/javascript-sdk/reference/cubejs-client-ws-transport.mdx new file mode 100644 index 0000000000000..715e1679483b5 --- /dev/null +++ b/docs-mintlify/reference/javascript-sdk/reference/cubejs-client-ws-transport.mdx @@ -0,0 +1,97 @@ +--- +title: "`@cubejs-client/ws-transport`" +description: WebSocket transport for Cube client +--- + +## `WebSocketTransport` + +### constructor + +> **new WebSocketTransport**(**__namedParameters**: object): *[WebSocketTransport](#websockettransport)* + +### `apiUrl` + +> **apiUrl**: *string* + +### `hearBeatInterval` + +> **hearBeatInterval**: *number* + +### `messageCounter` + +> **messageCounter**: *number* + +### `messageIdToSubscription` + +> **messageIdToSubscription**: *Record‹number, [Subscription](#subscription)›* + +### `messageQueue` + +> **messageQueue**: *[Message](#message)[]* + +### `token` + +> **token**: *string* + +### `ws` + +> **ws**: *any* + +### `authorization` + +### `initSocket` + +> **initSocket**(): *any* + +### `request` + +> **request**(**method**: string, **__namedParameters**: object): *object* + +### `sendMessage` + +> `protected` **sendMessage**(**message**: any): *void* + +## `WebSocketTransportResult` + +### constructor + +> **new WebSocketTransportResult**(**__namedParameters**: object): *[WebSocketTransportResult](#result)* + +### `result` + +> **result**: *unknown* + +### `status` + +> **status**: *unknown* + +### `json` + +> **json**(): *Promise‹unknown›* + +## Types + +### `Message` + +Name | Type | +------ | ------ | +messageId | number | +method | string | +params | string | +requestId | any | + +### `Subscription` + +Name | Type | +------ | ------ | +callback | (**result**: [WebSocketTransportResult](#result)) => *void* | +message | [Message](#message) | + +### `WebSocketTransportOptions` + +Name | Type | +------ | ------ | +apiUrl | string | +authorization | string | +hearBeatInterval? | number | +heartBeatInterval? | number | \ No newline at end of file diff --git a/docs-mintlify/reference/javascript-sdk/vue.mdx b/docs-mintlify/reference/javascript-sdk/vue.mdx new file mode 100644 index 0000000000000..ba4a230129c8c --- /dev/null +++ b/docs-mintlify/reference/javascript-sdk/vue.mdx @@ -0,0 +1,108 @@ +--- +title: Vue +description: Cube is visualization-agnostic, so you can build any user interface for your application. +--- + +You can directly query Cube using the +JSON [query format](/reference/core-data-apis/rest-api/query-format) via the [REST (JSON) API](/reference/core-data-apis/rest-api/reference) +or +[WebSockets](/recipes/core-data-api/real-time-data-fetch) +and visualize analytical data with tools of your choice. However, it's much +easier to use the Cube JavaScript client and bindings for popular frameworks +such as React, Angular, and Vue. + +The client has methods to communicate with Cube API Gateway and retrieve and +process data. It is designed to work with existing charting libraries including +Chart.js, D3.js, and more. + +## Cube JavaScript Client + +The client provides methods to solve common tasks: + +**Abstract from the transport and query data.** You can +[fetch data](/reference/javascript-sdk/reference/cubejs-client-core#load) from Cube Backend or +subscribe to +[real-time updates](/recipes/core-data-api/real-time-data-fetch) +regardless of the protocol, be it HTTP or WebSockets. + +**Transform data for visualization.** You can +[pivot](/reference/javascript-sdk/reference/cubejs-client-core#pivot) the result set to display +as a [chart](/reference/javascript-sdk/reference/cubejs-client-core#chartpivot) or as a +[table](/reference/javascript-sdk/reference/cubejs-client-core#tablepivot), split into +[series](/reference/javascript-sdk/reference/cubejs-client-core#series) or +[table columns](/reference/javascript-sdk/reference/cubejs-client-core#tablecolumns). + +**Simplify work with complex query types.** You can build +[drill down](/reference/javascript-sdk/reference/cubejs-client-core#drilldown) queries and +[decompose](/reference/javascript-sdk/reference/cubejs-client-core#decompose) the results of +[compare date range queries][ref-compare-date-range] +or [data blending](/docs/data-modeling/concepts/data-blending) queries. + +[Learn more](/reference/javascript-sdk/reference/cubejs-client-core) in the documentation for +the `@cubejs-client/core` package. + +## Cube Vue Package + +The package provides convenient tools to work with Cube in Vue: + +**Components.** You can use +[`QueryBuilder`](/reference/javascript-sdk/reference/cubejs-client-vue#querybuilder) and +[`QueryRenderer`](/reference/javascript-sdk/reference/cubejs-client-vue#queryrenderer) components +to abstract state management and API calls from your rendering code. + +## Example Usage + +Here are the typical steps to query and visualize analytical data in Vue: + +- **Import `@cubejs-client/core` and `@cubejs-client/vue3` packages.** These + packages provide all the necessary methods and convenient Vue tools. +- **Create an instance of Cube JavaScript Client.** The client is initialized + with Cube API URL. In development mode, the default URL is + [http://localhost:4000/cubejs-api/v1](http://localhost:4000/cubejs-api/v1). + The client is also initialized with an [API token](/docs/data-modeling/access-control), but it + takes effect only in [production](/cube-core/running-in-production). +- **Query data from Cube Backend.** Use + [`QueryBuilder`](/reference/javascript-sdk/reference/cubejs-client-vue#querybuilder) or + [`QueryRenderer`](/reference/javascript-sdk/reference/cubejs-client-vue#queryrenderer) and + their props to execute a query and transform the result set. See + [Query Format](/reference/core-data-apis/rest-api/query-format) for details. +- **Transform data for visualization.** Use + [`QueryBuilder`](/reference/javascript-sdk/reference/cubejs-client-vue#querybuilder) and + [`QueryRenderer`](/reference/javascript-sdk/reference/cubejs-client-vue#queryrenderer) slots + props to transform the result set. Furthermore, the result set has convenient + methods, such as `series` and `chartPivot`, to prepare data for charting. +- **Visualize the data.** Use tools of your choice to draw charts and create + visualizations. + +See an example of using Cube with Vue and Chart.js library. Note that you can +always use a different charting library that suits your needs: + + + +## Getting Started + +You can install Cube JavaScript Client and the Vue package with npm or Yarn: + +```bash +# npm +npm install --save @cubejs-client/core @cubejs-client/vue3 + +# Yarn +yarn add @cubejs-client/core @cubejs-client/vue3 +``` + +Now you can build your application from scratch or connect to one of our +[supported data visualization tools](/admin/connect-to-data/visualization-tools). + + +[ref-compare-date-range]: /reference/core-data-apis/queries#compare-date-range-query \ No newline at end of file diff --git a/docs-mintlify/reference/orchestration-api/airflow.mdx b/docs-mintlify/reference/orchestration-api/airflow.mdx new file mode 100644 index 0000000000000..de28a9fd26ea6 --- /dev/null +++ b/docs-mintlify/reference/orchestration-api/airflow.mdx @@ -0,0 +1,213 @@ +--- +title: Integration with Apache Airflow +description: Pair Airflow (including Astro) with Cube using `airflow-provider-cube` operators for loads, pre-aggregations, and orchestration triggers. +--- + +[Apache Airflow][airflow] is a popular open-source workflow scheduler commonly +used for data orchestration. [Astro][astro] is a fully managed service for +Airflow by [Astronomer][astro]. + +This guide demonstrates how to setup Cube and Airflow to work together so that +Airflow can push changes from upstream data sources to Cube via the +[Orchestration API][ref-orchestration-api]. + +## Tasks + +In Airflow, pipelines are represented by directed acyclic graphs (DAGs), Python +function decorated with a `@dag` decorator. DAGs include calls to tasks, +implemented as instances of the `Operator` class. Operators can perform various +tasks: poll for some precondition, perform extract-load-transform (ETL), or +trigger external systems like Cube. + +Integration between Cube and Airflow is enabled by the +[`airflow-provider-cube`][github-airflow-provider-cube] package that provides +the following operators. + +### CubeQueryOperator + +`CubeQueryOperator` is used to query Cube via the +[`/v1/load`][ref-load-endpoint] endpoint of the [REST (JSON) API][ref-rest-api]. + +It supports the following options: + +| Option | Type | Default | Description | +| -------------- | -------- | -------------- | ---------------------------------------- | +| `cube_conn_id` | `string` | `cube_default` | Airflow connection name. | +| `headers` | `dict` | | HTTP headers to be added to the request. | +| `query` | `dict` | | Cube query object. | +| `timeout` | `int` | 30 | Response wait timeout in seconds. | +| `wait` | `int` | 10 | Interval between API calls in seconds. | + +### CubeBuildOperator + +`CubeBuildOperator` is used to trigger pre-aggregation builds and check their +status via the [`/v1/pre-aggregations/jobs`][ref-ref-jobs-endpoint] endpoint of +the [Orchestration API][ref-orchestration-api]. + +It supports the following options: + +| Option | Type | Default | Description | +| -------------- | -------- | -------------- | -------------------------------------------------------------- | +| `cube_conn_id` | `string` | `cube_default` | Airflow connection name. | +| `headers` | `dict` | | HTTP headers to be added to the request. | +| `selector` | `dict` | | [`/v1/pre-aggregations/jobs`][ref-ref-jobs-endpoint] selector. | +| `complete` | `bool` | `False` | Whether a task should wait for builds to complete or not. | +| `wait` | `int` | 10 | Interval between API calls in seconds. | + +## Installation + +Install [Astro CLI installed][astro-cli]. + +Create a new directory and [initialize][astro-cli-dev-init] a new Astro project: + +```bash +mkdir cube-astro +cd cube-astro +astro dev init +``` + +Add the integration package to `requirements.txt`: + +```bash +echo "airflow-provider-cube" >> ./requirements.txt +``` + +## Configuration + +### Connection + +Create an Airflow connection via the web console or by adding the following +contents to the `airflow_settings.yaml` file: + +```yaml +airflow: + connections: + - conn_id: cube_default + conn_type: generic + conn_host: https://awesome-ecom.gcp-us-central1.cubecloudapp.dev + conn_schema: + conn_login: + conn_password: SECRET + conn_port: + conn_extra: + security_context: {} +``` + +Let's break the options down: + +- By default, Cube operators use `cube_default` as an Airflow connection name. +- The connection shoud be of the `generic` type. +- `conn_host` should be set to the URL of your Cube deployment. +- `conn_password` should be set to the value of the [`CUBEJS_API_SECRET`](/reference/configuration/environment-variables#cubejs_api_secret) + environment variable. +- `conn_extra` should contain a security context (as `security_context`) that + will be sent with API requests. + +### DAGs + +Create a new DAG named `cube_query.py` in the `dags` subdirectory with the +following contents. As you can see, the `CubeQueryOperator` accepts a Cube query +via the `query` option. + +```python +from typing import Any +from pendulum import datetime +from airflow.decorators import dag, task +from cube_provider.operators.cube import CubeQueryOperator + +@dag( + start_date=datetime(2023, 6, 1), + schedule='*/1 * * * *', + max_active_runs=1, + concurrency=1, + default_args={"retries": 1, "cube_conn_id": "cube_default"}, + tags=["cube"], +) +def cube_query_workflow(): + query_op = CubeQueryOperator( + task_id="query_op", + query={ + "measures": ["Orders.count"], + "dimensions": ["Orders.status"] + } + ) + + @task() + def print_op(data: Any): + print(f"Result: {data}") + + print_op(query_op.output) + +cube_query_workflow() +``` + +Create a new DAG named `cube_build.py` in the `dags` subdirectory with the +following contents. As you can see, the `CubeBuildOperator` accepts a +pre-aggregation selector via the `selector` option. + +```python +from typing import Any +from pendulum import datetime +from airflow.decorators import dag, task +from cube_provider.operators.cube import CubeBuildOperator + +@dag( + start_date=datetime(2023, 6, 1), + schedule='*/1 * * * *', + max_active_runs=1, + concurrency=1, + default_args={"retries": 1, "cube_conn_id": "cube_default"}, + tags=["cube"], +) +def cube_build_workflow(): + build_op = CubeBuildOperator( + task_id="build_op", + selector={ + "contexts": [ + {"securityContext": {}} + ], + "timezones": ["UTC"] + }, + complete=True, + wait=10, + ) + + @task() + def print_op(data: Any): + print(f"Result: {data}") + + print_op(build_op.output) + +cube_build_workflow() +``` + +Pay attention to the `complete` option. When it's set to `True`, the operator +will wait for pre-aggregation builds to complete before allowing downstream +tasks to run. + +## Running workflows + +Now, you can run these DAGs: + +```bash +astro run cube_query_workflow +astro run cube_build_workflow +``` + +Alternatively, you can run Airflow and navigate to the web console at +[`localhost:8080`](http://localhost:8080) (use `admin`/`admin` to authenticate): + +```bash +astro dev start +``` + +[airflow]: https://airflow.apache.org +[astro]: https://www.astronomer.io +[astro-cli]: https://docs.astronomer.io/astro/cli/overview +[astro-cli-dev-init]: https://docs.astronomer.io/astro/cli/astro-dev-init +[github-airflow-provider-cube]: + https://github.com/cube-js/airflow-provider-cube/ +[ref-load-endpoint]: /reference/core-data-apis/rest-api/reference#v1load +[ref-ref-jobs-endpoint]: /reference/core-data-apis/rest-api/reference#base_path/v1/pre-aggregations/jobs +[ref-rest-api]: /reference/core-data-apis/rest-api +[ref-orchestration-api]: /reference/orchestration-api \ No newline at end of file diff --git a/docs-mintlify/reference/orchestration-api/dagster.mdx b/docs-mintlify/reference/orchestration-api/dagster.mdx new file mode 100644 index 0000000000000..56b7070db5cf3 --- /dev/null +++ b/docs-mintlify/reference/orchestration-api/dagster.mdx @@ -0,0 +1,141 @@ +--- +title: Integration with Dagster +description: "Dagster is a popular open-source data pipeline orchestrator. Dagster Cloud is a fully managed service for Dagster." +--- + +[Dagster][dagster] is a popular open-source data pipeline orchestrator. [Dagster +Cloud][dagster-cloud] is a fully managed service for Dagster. + +This guide demonstrates how to setup Cube and Dagster to work together so that +Dagster can push changes from upstream data sources to Cube via the +[Orchestration API][ref-orchestration-api]. + +## Resources + +In Dagster, each workflow is represented by jobs, Python functions decorated +with a `@job` decorator. Jobs include calls to ops, Python functions decorated +with an `@op` decorator. Ops represent distinct pieces of work executed within a +job. They can perform various jobs: poll for some precondition, perform +extract-load-transform (ETL), or trigger external systems like Cube. + +Integration between Cube and Dagster is enabled by the +[`dagster_cube`][github-dagster-cube] package. + + + +Cube and Dagster integration package was originally contributed by +[Olivier Dupuis](https://github.com/olivierdupuis), founder of +[discursus.io](https://www.discursus.io), for which we're very grateful. + + + +The package provides the `CubeResource` class: + +- For querying Cube via the [`/v1/load`][ref-load-endpoint] endpoint of the + [REST (JSON) API][ref-rest-api]. +- For triggering pre-aggregation builds via the + [`/v1/pre-aggregations/jobs`][ref-ref-jobs-endpoint] endpoint of the + [Orchestration API][ref-orchestration-api]. + +Please refer to the [package documentation][github-dagster-cube-docs] for +details and options reference. + +## Installation + +Install [Dagster][dagster-docs-install]. + +Create a new directory: + +```bash +mkdir cube-dagster +cd cube-dagster +``` + +Install the integration package: + +```bash +pip install dagster_cube +``` + +## Configuration + +Create a new file named `cube.py` with the following contents: + +```python +from dagster import asset +from dagster_cube.cube_resource import CubeResource + +@asset +def cube_query_workflow(): + my_cube_resource = CubeResource( + instance_url="https://awesome-ecom.gcp-us-central1.cubecloudapp.dev/cubejs-api/v1/", + api_key="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjEwMDAwMDAwMDAsImV4cCI6NTAwMDAwMDAwMH0.OHZOpOBVKr-sCwn8sbZ5UFsqI3uCs6e4omT7P6WVMFw" + ) + + response = my_cube_resource.make_request( + method="POST", + endpoint="load", + data={ + 'query': { + 'measures': ['Orders.count'], + 'dimensions': ['Orders.status'] + } + } + ) + + return response + +@asset +def cube_build_workflow(): + my_cube_resource = CubeResource( + instance_url="https://awesome-ecom.gcp-us-central1.cubecloudapp.dev/cubejs-api/v1/", + api_key="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjEwMDAwMDAwMDAsImV4cCI6NTAwMDAwMDAwMH0.OHZOpOBVKr-sCwn8sbZ5UFsqI3uCs6e4omT7P6WVMFw" + ) + + response = my_cube_resource.make_request( + method="POST", + endpoint="pre-aggregations/jobs", + data={ + 'action': 'post', + 'selector': { + 'timezones': ['UTC'], + 'contexts': [{'securityContext': {}}] + } + } + ) + + return response +``` + +As you can see, the `make_request` method for the `load` endpoint accepts a Cube +query via the `query` option and the `make_request` method for the +`pre-aggregations/jobs` endpoint accepts a pre-aggregation selector via the +`selector` option. + +## Running jobs + +Now, you can load these jobs to Dagster: + +```bash +dagster dev -f cube.py +``` + +Navigate to [Dagit UI][dagster-docs-dagit] at +[localhost:3000](http://localhost:3000) and click **Materialize all** to +run both jobs: + + + + + +[dagster]: https://dagster.io +[dagster-cloud]: https://dagster.io/cloud +[dagster-docs-install]: https://docs.dagster.io/getting-started/install +[dagster-docs-dagit]: https://docs.dagster.io/concepts/webserver/ui +[github-dagster-cube]: https://github.com/discursus-data/dagster-cube +[github-dagster-cube-docs]: + https://github.com/discursus-data/dagster-cube/blob/main/README.md +[ref-load-endpoint]: /reference/core-data-apis/rest-api/reference#v1load +[ref-ref-jobs-endpoint]: /reference/core-data-apis/rest-api/reference#base_path/v1/pre-aggregations/jobs +[ref-rest-api]: /reference/core-data-apis/rest-api +[ref-orchestration-api]: /reference/orchestration-api \ No newline at end of file diff --git a/docs-mintlify/reference/orchestration-api/index.mdx b/docs-mintlify/reference/orchestration-api/index.mdx new file mode 100644 index 0000000000000..2a627f464f78a --- /dev/null +++ b/docs-mintlify/reference/orchestration-api/index.mdx @@ -0,0 +1,76 @@ +--- +title: Orchestration API +description: "Trigger pre-aggregation refreshes from Airflow, Dagster, or Prefect instead of relying on Cube's scheduled refresh." +--- + +Orchestration API enables Cube to work with data orchestration tools and let +them _push_ changes from upstream data sources to Cube, as opposed to letting +Cube _pull_ changes from upstream data sources via the +[`scheduledRefresh`][ref-scheduled-refresh] configration option of +pre-aggregations. + + + + + +Orchestration API can be used to implement both [embedded analytics][cube-ea] +and internal or self-serve [business intelligence][cube-issbi] use cases. When +implementing [real-time analytics][cube-rta], consider pulling data from +upstream data sources with [lambda pre-aggregations][ref-lambda-pre-aggs]. + +Under the hood, the Orchestration API is exposed via the +[`/v1/pre-aggregations/jobs`][ref-ref-jobs-endpoint] endpoint of the +[REST (JSON) API][ref-rest-api]. + +## Supported tools + +Orchestration API has integration packages to work with popular data +orchestration tools. Check the following guides to get tool-specific +instructions: + + + + Trigger pre-aggregation builds from Apache Airflow DAGs. + + + Trigger pre-aggregation builds from Dagster assets and jobs. + + + Trigger pre-aggregation builds from Prefect flows. + + + +## Configuration + +Orchestration API is enabled by default but inaccessible due to the default [API +scopes][ref-api-scopes] configuration. To allow access to the Orchestration API, +enable the `jobs` scope, e.g., by setting the [`CUBEJS_DEFAULT_API_SCOPES`](/reference/configuration/environment-variables#cubejs_default_api_scopes) +environment variable to `meta,data,graphql,jobs`. + +## Building pre-aggregations + +Orchestration API allows to trigger pre-aggregation builds programmatically. It +can be useful for data orchestration tools to push changes from upstream data +sources to Cube or for any third parties to invalidate and rebuild +pre-aggregations on demand. + +You can trigger pre-aggregation builds and check build statuses using the +[`/v1/pre-aggregations/jobs`][ref-ref-jobs-endpoint] endpoint. It is possible to +rebuild all pre-aggregations or specify the ones to be rebuilt: + +* Particular pre-aggregations. +* Pre-aggregations that reference particular cubes. +* Pre-aggregations that reference cubes from particular data sources. +* For [partitioned pre-aggregations][ref-pre-agg-partitions], only partitions that contain +data from a particular date range. + + +[ref-scheduled-refresh]: /reference/data-modeling/pre-aggregations#scheduled_refresh +[cube-ea]: https://cube.dev/use-cases/embedded-analytics +[cube-issbi]: https://cube.dev/use-cases/semantic-layer +[cube-rta]: https://cube.dev/use-cases/real-time-analytics +[ref-lambda-pre-aggs]: /docs/pre-aggregations/lambda-pre-aggregations +[ref-rest-api]: /reference/core-data-apis/rest-api +[ref-api-scopes]: /reference/core-data-apis/rest-api#configuration-api-scopes +[ref-ref-jobs-endpoint]: /reference/core-data-apis/rest-api/reference#base_path/v1/pre-aggregations/jobs +[ref-pre-agg-partitions]: /docs/pre-aggregations/using-pre-aggregations#partitioning \ No newline at end of file diff --git a/docs-mintlify/reference/orchestration-api/prefect.mdx b/docs-mintlify/reference/orchestration-api/prefect.mdx new file mode 100644 index 0000000000000..a52e55a7ddd3b --- /dev/null +++ b/docs-mintlify/reference/orchestration-api/prefect.mdx @@ -0,0 +1,135 @@ +--- +title: Integration with Prefect +description: "Prefect is a popular open-source orchestrator for data-intensive workflows. Prefect Cloud is a fully managed service for Prefect." +--- + +[Prefect][prefect] is a popular open-source orchestrator for data-intensive +workflows. [Prefect Cloud][prefect-cloud] is a fully managed service for +Prefect. + +This guide demonstrates how to setup Cube and Prefect to work together so that +Prefect can push changes from upstream data sources to Cube via the +[Orchestration API][ref-orchestration-api]. + +## Tasks + +In Prefect, each workflow is represented by flows, Python functions decorated +with a `@flow` decorator. Flows include calls to tasks, Python functions +decorated with a `@task` decorator, as well as to child flows. Tasks represent +distinct pieces of work executed within a flow. They can perform various jobs: +poll for some precondition, perform extract-load-transform (ETL), or trigger +external systems like Cube. + +Integration between Cube and Prefect is enabled by the +[`prefect-cubejs`][github-prefect-cubejs] package. + + + +Cube and Prefect integration package was originally contributed by +[Alessandro Lollo](https://github.com/AlessandroLollo), Data Engineering Manager +at Cloud Academy +([case study](https://cube.dev/case-studies/cloud-academy-and-cube)), for which +we're very grateful. + + + +The package provides the following tasks: + +- `run_query` for querying Cube via the [`/v1/load`][ref-load-endpoint] endpoint + of the [REST (JSON) API][ref-rest-api]. +- `build_pre_aggregations` for triggering pre-aggregation builds via the + [`/v1/pre-aggregations/jobs`][ref-ref-jobs-endpoint] endpoint of the + [Orchestration API][ref-orchestration-api]. + +Please refer to the [package documentation][github-prefect-cubejs-docs] for +details and options reference. + +## Installation + +Install [Prefect][prefect-docs-install]. + +Create a new directory: + +```bash +mkdir cube-prefect +cd cube-prefect +``` + +Install the integration package: + +```bash +pip install prefect-cubejs +``` + +## Configuration + +Create a new workflow named `cube_query.py` with the following contents. As you +can see, the `run_query` task accepts a Cube query via the `query` option. + +```python +from prefect import flow +from prefect_cubejs.tasks import ( + run_query +) + +@flow +def cube_query_workflow(): + run_query( + url="https://awesome-ecom.gcp-us-central1.cubecloudapp.dev/cubejs-api", + api_secret="SECRET", + query="""{ + "measures": ["Orders.count"], + "dimensions": ["Orders.status"] + }""" + ) + +cube_query_workflow() +``` + +Create a new workflow named `cube_build.py` with the following contents. As you +can see, the `build_pre_aggregations` task accepts a pre-aggregation selector +via the `selector` option. + +```python +from prefect import flow +from prefect_cubejs.tasks import ( + build_pre_aggregations +) + +@flow +def cube_build_workflow(): + build_pre_aggregations( + url="https://awesome-ecom.gcp-us-central1.cubecloudapp.dev/cubejs-api", + api_secret="SECRET", + selector={ + "contexts": [ + {"securityContext": {}} + ], + "timezones": ["UTC"] + }, + wait_for_job_run_completion=True + ) + +cube_build_workflow() +``` + +## Running workflows + +Now, you can run these workflows: + +```bash +python cube_query.py +python cube_build.py +``` + +[prefect]: https://www.prefect.io +[prefect-cloud]: https://www.prefect.io/cloud/ +[prefect-docs-install]: + https://docs.prefect.io/2.10.13/getting-started/installation/#install-prefect +[github-prefect-cubejs]: https://github.com/AlessandroLollo/prefect-cubejs +[github-prefect-cubejs-docs]: + https://alessandrolollo.github.io/prefect-cubejs/tasks/ +[ref-load-endpoint]: /reference/core-data-apis/rest-api/reference#v1load +[ref-ref-jobs-endpoint]: /reference/core-data-apis/rest-api/reference#base_path/v1/pre-aggregations/jobs +[ref-rest-api]: /reference/core-data-apis/rest-api +[ref-orchestration-api]: /reference/orchestration-api \ No newline at end of file diff --git a/docs-mintlify/scripts/README.md b/docs-mintlify/scripts/README.md new file mode 100644 index 0000000000000..5b93625ff8a21 --- /dev/null +++ b/docs-mintlify/scripts/README.md @@ -0,0 +1,107 @@ +# Scripts + +## `upload-asset.sh` + +Uploads a static asset to the `cube-dev-websites-shared` S3 bucket and prints +the resulting `https://static.cube.dev/` URL (also copied to clipboard on +macOS). Use this for images and other binaries referenced from `.mdx` / `.md` +files in the Mintlify docs. + +### One-time setup + +1. Install the AWS CLI: + + ```bash + brew install awscli + ``` + +2. Configure a local profile (name it `cube-static` so the script picks it up + automatically; or use any name and export `AWS_PROFILE` before running): + + ```bash + aws configure --profile cube-static + # AWS Access Key ID: + # AWS Secret Access Key: + # Default region name: us-west-2 + # Default output format: json + ``` + + You need credentials that can `s3:PutObject` and `s3:HeadObject` on + `cube-dev-websites-shared`. Ask whoever manages Cube's AWS account if you + don't have them yet. + +3. Verify: + + ```bash + aws sts get-caller-identity --profile cube-static + aws s3 ls s3://cube-dev-websites-shared/icons/ --profile cube-static | head + ``` + +### Usage + +Run from the `docs-mintlify/` directory: + +```bash +./scripts/upload-asset.sh [--force] +``` + +Examples: + +```bash +./scripts/upload-asset.sh ./snowflake.svg icons/snowflake.svg +./scripts/upload-asset.sh ./architecture.png docs/getting-started/architecture.png +./scripts/upload-asset.sh ./flow.svg diagrams/pre-aggregations-flow.svg +``` + +Output: + +``` +→ bucket: s3://cube-dev-websites-shared/icons/snowflake.svg +→ region: us-west-2 +→ profile: cube-static +→ content-type: image/svg+xml +→ cache: public, max-age=31536000, immutable + +✓ uploaded + https://static.cube.dev/icons/snowflake.svg + (copied to clipboard) +``` + +Paste the URL into the relevant `.mdx` file and commit. + +### Path conventions + +Assets are grouped by content domain so the same asset can be reused across +pages. Use kebab-case filenames. + +| Prefix | Purpose | +| --------------------------------- | -------------------------------------------------- | +| `icons/.svg` | Provider / integration / vendor logos for `` | +| `icons/-light.svg` | Logo, light variant (use on dark backgrounds) | +| `icons/-dark.svg` | Logo, dark variant (use on light backgrounds) | +| `docs/
//` | Screenshots & images for a specific docs page | +| `diagrams/.svg` | Architecture / flow diagrams | +| `recipes//` | Recipe-specific screenshots | + +For provider logos, prefer SVG. For UI screenshots, prefer PNG (or WebP for +larger images). Compress before uploading — the bucket is cached aggressively. + +### Immutability + +Paths are **immutable by convention**. The script refuses to overwrite an +existing key. If an asset needs to change: + +1. Upload a new key with a version suffix: `snowflake-v2.svg`. +2. Update the `.mdx` reference in the same PR. + +This keeps `Cache-Control: public, max-age=31536000, immutable` safe and makes +rollbacks trivial (just revert the Markdown change). + +If you genuinely need to overwrite (e.g. you uploaded a corrupt file in the +same session and the CDN hasn't cached it yet), pass `--force`: + +```bash +./scripts/upload-asset.sh ./fixed.svg icons/snowflake.svg --force +``` + +Avoid `--force` for anything already live. diff --git a/docs-mintlify/scripts/build_old_site_redirects.py b/docs-mintlify/scripts/build_old_site_redirects.py new file mode 100644 index 0000000000000..da3a2a415958d --- /dev/null +++ b/docs-mintlify/scripts/build_old_site_redirects.py @@ -0,0 +1,347 @@ +#!/usr/bin/env python3 +""" +Build the cross-domain redirect table for the OLD docs site (Next.js/Nextra, +served at cube.dev/docs) so that every legacy URL 301s to the NEW Mintlify docs +at docs.cube.dev. + +Why this is content-driven (and not a simple prefix rewrite) +------------------------------------------------------------ +An earlier version of this script reused ``rewrite_links.PATH_REWRITES`` to map +old ``/product/...`` paths to new ones. That table described an INTERMEDIATE +migration layout (``/access-security``, ``/api-reference``, ``/analytics`` tabs +and ``/docs/data-modeling/reference/...`` pages) that no longer exists — the +content was later consolidated into the live tabs (``admin``, ``reference``, +``docs``, ``recipes``, ``embedding``, ``configuration``, ``cube-core``). As a +result ~76% of the generated destinations 404'd (e.g. +``/docs/data-modeling/reference/pre-aggregations`` instead of the real +``/reference/data-modeling/pre-aggregations``). + +To stay correct as the layout evolves, destinations are derived by MATCHING the +old page's body text against the new Mintlify pages (the new files were copied +from the old ones during migration, so the prose is preserved even though +front matter and links were rewritten). Pages that cannot be matched reliably +(short/list pages, or pages consolidated/removed during migration) are pinned +explicitly in ``OVERRIDES``. + +Every emitted destination is validated against the on-disk Mintlify tree; the +script exits non-zero if any destination would 404, so a broken table can never +be committed silently. + +Layers produced, in first-match-wins order: + + 1. Specific redirects — every entry from the old ``redirects.json`` (legacy + aliases) plus one direct redirect per canonical old ``/product/...`` page, + each pointing at its verified new home. + + 2. A final ``/product/:path*`` catch-all so any legacy ``/product`` URL that + isn't enumerated still lands on the new docs instead of 404ing. + +``basePath: false`` is intentionally omitted in next.config.mjs. Next.js +prefixes a redirect's ``source`` with the configured ``basePath`` (``/docs``) +only when ``basePath`` is not false, while absolute (http/https) destinations +are treated as external and never get the basePath prepended. Omitting it +therefore matches legacy URLs under ``/docs`` and keeps the cross-domain +destination intact. + +Usage: + python build_old_site_redirects.py \ + --redirects ../docs/redirects.json \ + --old-content ../docs/content/product \ + --new-root .. \ + -o ../docs/redirects-new-docs.json +""" + +import argparse +import json +import re +import sys +from pathlib import Path + +NEW_DOCS_ORIGIN = "https://docs.cube.dev" + +# Tabs/dirs that hold real Mintlify pages. Anything else under docs-mintlify/ +# (scripts, images, node_modules, ...) is ignored when indexing/validating. +NEW_CONTENT_DIRS = { + "admin", "configuration", "cube-core", "docs", + "embedding", "recipes", "reference", +} + +# Content-match tuning. Shingle = sliding window of N normalized words; the +# match score is Jaccard overlap of the old and new shingle sets. +SHINGLE_N = 4 + +# Pages whose new home cannot be recovered reliably by content matching: +# - short/list pages with little distinctive prose, or +# - pages consolidated into another page or removed during migration. +# Keys are old (legacy) URLs; values are root-relative new Mintlify paths that +# are verified to exist. These take precedence over the content match. +OVERRIDES = { + # AI admin pages renamed/consolidated (mirrors docs.json internal redirects). + "/product/administration/ai": "/admin/ai", + "/product/administration/ai/agent-rules": "/admin/ai/rules", + "/product/administration/ai/spaces-agents-models": "/admin/ai/multi-agent", + "/product/administration/ai/yaml-config": "/admin/ai", + + # Monitoring landing (no standalone monitoring index in the new tree). + "/product/administration/monitoring": "/admin/monitoring/query-history", + + # Dedicated-infrastructure (old "vpc"/"byoc") networking pages. + "/product/administration/deployment/byoc/aws/privatelink": "/admin/deployment/dedicated/aws/private-link", + "/product/administration/deployment/vpc": "/admin/deployment/dedicated", + "/product/administration/deployment/vpc/aws": "/admin/deployment/dedicated/aws", + "/product/administration/deployment/vpc/azure": "/admin/deployment/dedicated/azure", + "/product/administration/deployment/vpc/gcp": "/admin/deployment/dedicated/gcp", + + # Okta SSO landing -> SAML page (no standalone Okta index in the new tree). + "/product/administration/sso/okta": "/admin/sso/okta/saml", + + # Workspace pages consolidated/removed; fall back to the closest live home. + "/product/administration/workspace": "/admin", + "/product/administration/workspace/cli": "/admin", + "/product/administration/workspace/cli/reference": "/admin", + "/product/administration/workspace/preferences": "/admin", + "/product/administration/workspace/maintenance-window": "/admin", + "/product/administration/workspace/semantic-catalog": "/admin", + "/product/administration/workspace/integrations": "/admin/connect-to-data/visualization-tools", + "/product/administration/workspace/saved-reports": "/docs/explore-analyze/workbooks", + + # Auth methods moved under the Embedding tab's authentication section; + # provider-specific pages without a dedicated new page go to the SSO/auth + # landing rather than 404. + "/product/auth/methods": "/embedding/authentication/jwt", + "/product/auth/methods/identity-provider": "/admin/sso", + "/product/auth/methods/name-password": "/embedding/authentication/jwt", + + # Data-modeling concepts landing/short pages. + "/product/data-modeling/concepts": "/docs/data-modeling/overview", + "/product/data-modeling/concepts/calculated-members": "/docs/data-modeling/measures", + "/product/data-modeling/dynamic": "/docs/data-modeling/dynamic", + "/product/data-modeling/advanced/code-reusability-export-and-import": "/docs/data-modeling/dynamic/code-reusability-export-and-import", + "/product/data-modeling/advanced/polymorphic-cubes": "/recipes/data-modeling/polymorphic-cubes", + + # Data-model reference landing and the removed types-and-formats page. + "/product/data-modeling/reference": "/reference", + "/product/data-modeling/reference/types-and-formats": "/reference/data-modeling/dimensions", + + # FAQ section removed; send to the docs entry point. + "/product/faqs/general": "/docs/introduction", + "/product/faqs/tips-and-tricks": "/docs/introduction", + "/product/faqs/troubleshooting": "/docs/introduction", + + # Legacy guide alias whose canonical page no longer exists under /product. + "/guides/recipes/code-reusability/using-dynamic-measures": "/recipes/data-modeling/using-dynamic-measures", + + # Migrate-from-Core landing (no index; point at the most common path). + "/product/getting-started/migrate-from-core": "/docs/getting-started/migrate-from-core/import-github-repository", + + # Metabase semantic-layer sync was removed; send to the sync overview. + "/product/apis-integrations/semantic-layer-sync/metabase": "/docs/integrations/semantic-layer-sync", +} + +# Where to send any /product/* URL that matches nothing else. +PRODUCT_CATCH_ALL = "/docs/introduction" + + +# --------------------------------------------------------------------------- # +# Content matching +# --------------------------------------------------------------------------- # + +def normalize(text: str) -> str: + """Reduce MDX to a bag of prose words, ignoring front matter/markup/links.""" + text = re.sub(r"^---\n.*?\n---\n", "", text, flags=re.S) # front matter + text = re.sub(r"^(import|export)\s.*$", "", text, flags=re.M) # JS imports + text = re.sub(r"<[^>]+>", " ", text) # JSX tags + text = re.sub(r"\[([^\]]*)\]\([^)]*\)", r"\1", text) # [t](url)->t + text = re.sub(r"^\[[^\]]+\]:\s*\S+\s*$", "", text, flags=re.M) # ref links + text = text.replace("`", "") + text = re.sub(r"[#>*_\-]", " ", text) + return re.sub(r"\s+", " ", text).lower().strip() + + +def shingles(text: str) -> set: + words = normalize(text).split() + if len(words) < SHINGLE_N: + return set(words) + return {" ".join(words[i:i + SHINGLE_N]) for i in range(len(words) - SHINGLE_N + 1)} + + +def file_to_url(path: Path, root: Path) -> str: + """Map a Mintlify .mdx file to its served URL path (root-relative).""" + rel = str(path.relative_to(root)).removesuffix(".mdx") + rel = re.sub(r"/index$", "", rel) + return "/" + rel + + +def index_new_pages(new_root: Path) -> list: + """Return [(url, shingle_set, valid_path_set_entry)] for every new page.""" + pages = [] + for d in sorted(NEW_CONTENT_DIRS): + base = new_root / d + if not base.is_dir(): + continue + for f in sorted(base.rglob("*.mdx")): + text = f.read_text(encoding="utf-8", errors="ignore") + pages.append((file_to_url(f, new_root), shingles(text))) + return pages + + +def build_page_map(old_content: Path, new_root: Path, new_pages: list) -> dict: + """Map each canonical old /product/... URL to its verified new URL.""" + page_map = {} + for f in sorted(old_content.rglob("*.mdx")): + rel = str(f.relative_to(old_content)).removesuffix(".mdx") + rel = re.sub(r"/index$", "", rel) + old_url = "/product/" + rel if rel else "/product" + + if old_url in OVERRIDES: + page_map[old_url] = OVERRIDES[old_url] + continue + + osh = shingles(f.read_text(encoding="utf-8", errors="ignore")) + best_url, best_score = None, 0.0 + for nurl, nsh in new_pages: + if not osh or not nsh: + continue + inter = len(osh & nsh) + if not inter: + continue + score = inter / len(osh | nsh) + if score > best_score: + best_score, best_url = score, nurl + if best_url is not None: + page_map[old_url] = best_url + return page_map + + +# --------------------------------------------------------------------------- # +# Redirect table assembly +# --------------------------------------------------------------------------- # + +def to_absolute(path: str) -> str: + if path.startswith(("http://", "https://")): + return path + return NEW_DOCS_ORIGIN + path + + +def split_fragment(url: str): + if "#" in url: + base, frag = url.split("#", 1) + return base, "#" + frag + return url, "" + + +def resolve_destination(old_dest: str, page_map: dict) -> str: + """Resolve a legacy redirect destination to a new (absolute) URL.""" + if old_dest.startswith(("http://", "https://")): + return old_dest # already external (e.g. blog links) + + base, frag = split_fragment(old_dest) + if base in OVERRIDES: + new_base = OVERRIDES[base] + elif base in page_map: + new_base = page_map[base] + elif base.startswith("/product/"): + new_base = PRODUCT_CATCH_ALL + else: + new_base = PRODUCT_CATCH_ALL + return to_absolute(new_base + frag) + + +def build_redirects(old_redirects: list, page_map: dict) -> list: + out, seen = [], set() + + def add(source: str, dest: str): + if source in seen: + return + seen.add(source) + out.append({"source": source, "destination": dest, "permanent": True}) + + # 1. Legacy aliases from the old redirects.json. + for r in old_redirects: + add(r.get("source", ""), resolve_destination(r.get("destination", ""), page_map)) + + # 2. Direct redirects for every canonical old /product page. + for old_url, new_url in sorted(page_map.items()): + add(old_url, to_absolute(new_url)) + + # 3. Catch-all so unmatched /product URLs never 404. + add("/product/:path*", to_absolute(PRODUCT_CATCH_ALL)) + + return out + + +def valid_url_set(new_root: Path) -> set: + urls = set() + for d in sorted(NEW_CONTENT_DIRS): + base = new_root / d + if not base.is_dir(): + continue + for f in base.rglob("*.mdx"): + urls.add(file_to_url(f, new_root)) + return urls + + +def validate(redirects: list, valid: set) -> list: + """Return a list of redirects whose destination would 404.""" + broken = [] + for r in redirects: + dest = r["destination"] + if not dest.startswith(NEW_DOCS_ORIGIN): + continue # external destination, not ours to validate + path = dest[len(NEW_DOCS_ORIGIN):] + base = split_fragment(path)[0] + if base.endswith("/:path*"): + base = base[:-len("/:path*")] + if base in ("", "/"): + continue + if base not in valid: + broken.append((r["source"], path)) + return broken + + +def main(): + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("--redirects", default="../docs/redirects.json") + parser.add_argument("--old-content", default="../docs/content/product") + parser.add_argument("--new-root", default="..") + parser.add_argument("-o", "--output", default="../docs/redirects-new-docs.json") + args = parser.parse_args() + + redirects_path = Path(args.redirects) + old_content = Path(args.old_content) + new_root = Path(args.new_root) + + for p in (redirects_path, old_content, new_root): + if not p.exists(): + print(f"Error: {p} not found", file=sys.stderr) + sys.exit(1) + + old_redirects = json.loads(redirects_path.read_text(encoding="utf-8")) + + print("Indexing new Mintlify pages...", file=sys.stderr) + new_pages = index_new_pages(new_root) + print(f" {len(new_pages)} new pages", file=sys.stderr) + + print("Content-matching old pages to new pages...", file=sys.stderr) + page_map = build_page_map(old_content, new_root, new_pages) + print(f" mapped {len(page_map)} old pages", file=sys.stderr) + + redirects = build_redirects(old_redirects, page_map) + + valid = valid_url_set(new_root) + broken = validate(redirects, valid) + if broken: + print(f"\nERROR: {len(broken)} redirect destinations do not resolve:", + file=sys.stderr) + for s, d in broken[:50]: + print(f" {s} -> {d}", file=sys.stderr) + sys.exit(2) + + Path(args.output).write_text( + json.dumps(redirects, indent=2) + "\n", encoding="utf-8") + print(f"\nWrote {len(redirects)} redirects to {args.output} " + f"(all destinations validated against the live tree).", file=sys.stderr) + + +if __name__ == "__main__": + main() diff --git a/docs-mintlify/scripts/check_links.py b/docs-mintlify/scripts/check_links.py new file mode 100755 index 0000000000000..dddf20bd7f144 --- /dev/null +++ b/docs-mintlify/scripts/check_links.py @@ -0,0 +1,132 @@ +#!/usr/bin/env python3 +""" +Verify all internal links in Mintlify docs resolve to existing files. + +Checks: + - Inline links: [text](/docs/something) + - Reference-style links: [ref]: /docs/something + - href/url attributes: href="/docs/something" + +Usage: + python check_links.py /path/to/docs-mintlify/ + python check_links.py /path/to/docs-mintlify/ --verbose +""" + +import argparse +import re +import sys +from pathlib import Path + + +def extract_internal_links(content: str, filepath: Path) -> list[tuple[int, str]]: + """Extract all internal links from MDX content. Returns [(line_number, path), ...].""" + links = [] + + for i, line in enumerate(content.splitlines(), 1): + # Inline links: [text](/path) + for match in re.finditer(r"\[([^\]]*)\]\((/[^)#\s]+)", line): + links.append((i, match.group(2))) + + # Reference-style definitions: [ref]: /path + ref_match = re.match(r"^\[([^\]]+)\]:\s*(/[^\s#]+)", line) + if ref_match: + links.append((i, ref_match.group(2))) + + # href attributes: href="/path" + for match in re.finditer(r'href="(/[^"#]+)"', line): + links.append((i, match.group(1))) + + # url attributes: url="/path" + for match in re.finditer(r'url="(/[^"#]+)"', line): + path = match.group(1) + # Skip external-looking URLs + if not path.startswith("http"): + links.append((i, path)) + + return links + + +def resolve_link(link_path: str, docs_root: Path) -> bool: + """Check if an internal link resolves to an existing file.""" + # Remove leading slash + relative = link_path.lstrip("/") + + # Try exact match with .mdx extension + candidates = [ + docs_root / f"{relative}.mdx", + docs_root / relative / "index.mdx", + docs_root / relative, # exact file (e.g., if it has extension) + ] + + return any(c.exists() for c in candidates) + + +def check_directory(docs_root: Path, verbose: bool = False) -> tuple[int, int, list]: + """Check all MDX files in directory. Returns (total_links, broken_count, broken_list).""" + total_links = 0 + broken = [] + + for mdx_file in sorted(docs_root.rglob("*.mdx")): + # Skip scripts directory + if "scripts" in mdx_file.parts: + continue + + content = mdx_file.read_text(encoding="utf-8") + links = extract_internal_links(content, mdx_file) + total_links += len(links) + + for line_num, link_path in links: + # Skip external links + if link_path.startswith("http"): + continue + + if not resolve_link(link_path, docs_root): + relative_file = mdx_file.relative_to(docs_root) + broken.append((str(relative_file), line_num, link_path)) + + if verbose: + print(f" BROKEN: {relative_file}:{line_num} -> {link_path}") + + return total_links, len(broken), broken + + +def main(): + parser = argparse.ArgumentParser( + description="Check internal links in Mintlify docs." + ) + parser.add_argument( + "docs_root", + help="Root directory of Mintlify docs", + ) + parser.add_argument( + "--verbose", "-v", + action="store_true", + help="Show each broken link as it's found", + ) + + args = parser.parse_args() + docs_root = Path(args.docs_root).resolve() + + if not docs_root.is_dir(): + print(f"Error: {docs_root} not found", file=sys.stderr) + sys.exit(1) + + print(f"Checking links in {docs_root}...\n") + + total, broken_count, broken = check_directory(docs_root, verbose=args.verbose) + + print(f"\nResults:") + print(f" Total internal links: {total}") + print(f" Broken links: {broken_count}") + + if broken and not args.verbose: + print(f"\nBroken links:") + for filepath, line, link in broken: + print(f" {filepath}:{line} -> {link}") + + if broken_count > 0: + sys.exit(1) + + +if __name__ == "__main__": + main() diff --git a/docs-mintlify/scripts/copy_content.py b/docs-mintlify/scripts/copy_content.py new file mode 100755 index 0000000000000..2b4785d6f4187 --- /dev/null +++ b/docs-mintlify/scripts/copy_content.py @@ -0,0 +1,383 @@ +#!/usr/bin/env python3 +""" +Copy and restructure content from Nextra docs to Mintlify folder layout. + +Copies MDX files from docs/content/product/ to the new tab-based structure +in docs-mintlify/, preserving directory hierarchy and renaming as needed. + +Usage: + # Full migration (copies all content): + python copy_content.py --source ../docs/content/product --dest .. + + # Migrate a single section: + python copy_content.py --source ../docs/content/product --dest .. --section getting-started + + # Migrate late-arriving content (only new/changed files): + python copy_content.py --source ../docs/content/product --dest .. --incremental + + # Dry run: + python copy_content.py --source ../docs/content/product --dest .. --dry-run +""" + +import argparse +import hashlib +import shutil +import sys +from pathlib import Path + + +# Section -> (destination tab folder, destination subfolder) +# If subfolder is None, files go directly into the tab folder +SECTION_MAP = { + # Docs tab + "introduction.mdx": ("docs", None), + "getting-started": ("docs", "getting-started"), + "configuration": ("docs", "configuration"), + "data-modeling": ("docs", "data-modeling"), + "caching": ("docs", "caching"), + + # Analytics tab (merged exploration + presentation) + "exploration": ("analytics", None), + "presentation": ("analytics", None), + + # Embedding tab + "embedding": ("embedding", None), + + # Access & Security tab (from auth/ + parts of administration/) + "auth": ("access-security", None), + + # Administration tab (most of administration/) + "administration": ("admin", None), + + # APIs & Integrations -> split across tabs + "apis-integrations": ("_split", None), # Special handling +} + +# Within apis-integrations, these go to api-reference/ +API_REFERENCE_DIRS = { + "core-data-apis", + "embed-apis", + "control-plane-api.mdx", + "orchestration-api", + "javascript-sdk", + "mcp-server.mdx", + "recipes", +} + +# Within apis-integrations, these go to docs/integrations/ +INTEGRATION_FILES = { + "microsoft-excel.mdx", + "google-sheets.mdx", + "tableau.mdx", + "power-bi.mdx", + "semantic-layer-sync", + "snowflake-semantic-views.mdx", +} + +# Within administration/, these go to access-security/ instead of admin/ +ACCESS_SECURITY_DIRS = { + "sso", + "users-and-permissions", +} + + +def file_hash(filepath: Path) -> str: + """Compute MD5 hash of a file for incremental comparison.""" + return hashlib.md5(filepath.read_bytes()).hexdigest() + + +def should_copy(src: Path, dest: Path, incremental: bool) -> bool: + """Determine if a file should be copied.""" + if not incremental: + return True + if not dest.exists(): + return True + return file_hash(src) != file_hash(dest) + + +def copy_file(src: Path, dest: Path, dry_run: bool = False) -> bool: + """Copy a single file, creating parent dirs as needed.""" + if dry_run: + print(f" [WOULD COPY] {src.name} -> {dest}") + return True + + dest.parent.mkdir(parents=True, exist_ok=True) + shutil.copy2(src, dest) + return True + + +def copy_directory(src_dir: Path, dest_dir: Path, dry_run: bool, incremental: bool) -> int: + """Recursively copy a directory of MDX files. Returns count of files copied.""" + count = 0 + for src_file in sorted(src_dir.rglob("*.mdx")): + relative = src_file.relative_to(src_dir) + dest_file = dest_dir / relative + + if should_copy(src_file, dest_file, incremental): + copy_file(src_file, dest_file, dry_run) + count += 1 + + return count + + +def migrate_apis_integrations( + src_dir: Path, dest_root: Path, dry_run: bool, incremental: bool +) -> int: + """Split apis-integrations into api-reference/ and docs/integrations/.""" + count = 0 + + for item in sorted(src_dir.iterdir()): + name = item.name + + if name == "_meta.js": + continue + + if name == "index.mdx": + # The index page goes to api-reference/ + dest = dest_root / "api-reference" / "index.mdx" + if should_copy(item, dest, incremental): + copy_file(item, dest, dry_run) + count += 1 + continue + + if name in API_REFERENCE_DIRS: + if item.is_dir(): + count += copy_directory( + item, + dest_root / "api-reference" / name, + dry_run, + incremental, + ) + else: + dest = dest_root / "api-reference" / name + if should_copy(item, dest, incremental): + copy_file(item, dest, dry_run) + count += 1 + + elif name in INTEGRATION_FILES: + if item.is_dir(): + count += copy_directory( + item, + dest_root / "docs" / "integrations" / name, + dry_run, + incremental, + ) + else: + dest = dest_root / "docs" / "integrations" / name + if should_copy(item, dest, incremental): + copy_file(item, dest, dry_run) + count += 1 + + else: + # Default: goes to api-reference/ + if item.is_dir(): + count += copy_directory( + item, + dest_root / "api-reference" / name, + dry_run, + incremental, + ) + elif item.suffix == ".mdx": + dest = dest_root / "api-reference" / name + if should_copy(item, dest, incremental): + copy_file(item, dest, dry_run) + count += 1 + + return count + + +def migrate_administration( + src_dir: Path, dest_root: Path, dry_run: bool, incremental: bool +) -> int: + """Split administration/ into admin/ and access-security/.""" + count = 0 + + for item in sorted(src_dir.iterdir()): + name = item.name + + if name == "_meta.js": + continue + + if name in ACCESS_SECURITY_DIRS: + if item.is_dir(): + count += copy_directory( + item, + dest_root / "access-security" / name, + dry_run, + incremental, + ) + continue + + # Everything else goes to admin/ + if item.is_dir(): + count += copy_directory( + item, + dest_root / "admin" / name, + dry_run, + incremental, + ) + elif item.suffix == ".mdx": + dest = dest_root / "admin" / name + if should_copy(item, dest, incremental): + copy_file(item, dest, dry_run) + count += 1 + + return count + + +def migrate_auth( + src_dir: Path, dest_root: Path, dry_run: bool, incremental: bool +) -> int: + """Copy auth/ to access-security/access-control/ with methods/ -> authentication/.""" + count = 0 + + for item in sorted(src_dir.iterdir()): + name = item.name + + if name == "_meta.js": + continue + + if name == "methods": + # auth/methods/ -> access-security/authentication/ + if item.is_dir(): + count += copy_directory( + item, + dest_root / "access-security" / "authentication", + dry_run, + incremental, + ) + elif item.is_dir(): + count += copy_directory( + item, + dest_root / "access-security" / "access-control" / name, + dry_run, + incremental, + ) + elif item.suffix == ".mdx": + dest = dest_root / "access-security" / "access-control" / name + if should_copy(item, dest, incremental): + copy_file(item, dest, dry_run) + count += 1 + + return count + + +def migrate_section( + section_name: str, + src_root: Path, + dest_root: Path, + dry_run: bool, + incremental: bool, +) -> int: + """Migrate a single section. Returns count of files copied.""" + src_path = src_root / section_name + + # Special cases + if section_name == "apis-integrations": + return migrate_apis_integrations(src_path, dest_root, dry_run, incremental) + + if section_name == "administration": + return migrate_administration(src_path, dest_root, dry_run, incremental) + + if section_name == "auth": + return migrate_auth(src_path, dest_root, dry_run, incremental) + + # Standard section mapping + mapping = SECTION_MAP.get(section_name) + if not mapping: + print(f" [SKIP] Unknown section: {section_name}", file=sys.stderr) + return 0 + + tab_folder, subfolder = mapping + + if subfolder: + dest_dir = dest_root / tab_folder / subfolder + else: + dest_dir = dest_root / tab_folder + + # Handle single file (e.g., introduction.mdx) + if section_name.endswith(".mdx"): + src_file = src_root / section_name + if src_file.exists(): + dest_file = dest_root / tab_folder / section_name + if should_copy(src_file, dest_file, incremental): + copy_file(src_file, dest_file, dry_run) + return 1 + return 0 + + if not src_path.is_dir(): + print(f" [SKIP] Source not found: {src_path}", file=sys.stderr) + return 0 + + return copy_directory(src_path, dest_dir, dry_run, incremental) + + +def main(): + parser = argparse.ArgumentParser( + description="Copy and restructure Nextra docs to Mintlify folder layout." + ) + parser.add_argument( + "--source", + required=True, + help="Source directory (e.g., ../docs/content/product)", + ) + parser.add_argument( + "--dest", + required=True, + help="Destination root (e.g., .. for docs-mintlify/)", + ) + parser.add_argument( + "--section", + help="Migrate only a specific section (e.g., getting-started, configuration)", + ) + parser.add_argument( + "--dry-run", + action="store_true", + help="Show what would be copied without copying", + ) + parser.add_argument( + "--incremental", + action="store_true", + help="Only copy new or changed files (compares by hash)", + ) + + args = parser.parse_args() + + src_root = Path(args.source).resolve() + dest_root = Path(args.dest).resolve() + + if not src_root.is_dir(): + print(f"Error: Source directory not found: {src_root}", file=sys.stderr) + sys.exit(1) + + total_copied = 0 + + if args.section: + sections = [args.section] + else: + # All sections in order + sections = [ + "introduction.mdx", + "getting-started", + "configuration", + "data-modeling", + "caching", + "exploration", + "presentation", + "embedding", + "auth", + "administration", + "apis-integrations", + ] + + for section in sections: + print(f"\nMigrating: {section}") + count = migrate_section(section, src_root, dest_root, args.dry_run, args.incremental) + total_copied += count + print(f" {count} files {'would be ' if args.dry_run else ''}copied") + + print(f"\nTotal: {total_copied} files {'would be ' if args.dry_run else ''}copied") + + +if __name__ == "__main__": + main() diff --git a/docs-mintlify/scripts/extract-api.mjs b/docs-mintlify/scripts/extract-api.mjs new file mode 100644 index 0000000000000..995b1086fe8e3 --- /dev/null +++ b/docs-mintlify/scripts/extract-api.mjs @@ -0,0 +1,298 @@ +/* eslint-disable */ +// Extractor: turns the Console Server *public* OpenAPI spec into a standalone +// api.yaml covering the whole v1 REST surface for the Mintlify API docs. Unlike +// the old deployments-only extractor, this includes every /api/v1 endpoint the +// public spec exposes (deployments and everything scoped to them, plus account, +// embed, AI, and workspace areas) and auto-discovers tags, so new public +// endpoints show up without editing this script. +// +// SCIM (/api/scim/v2) is intentionally NOT included: its docs are hand-curated +// in api-reference/scim.yaml. (Both the REST API and SCIM authenticate with a +// Bearer token; see the securityScheme override below.) +// +// The source spec lives in the (private) cubejs-enterprise repo and is NOT in +// this repo, so there is no hardcoded path — point the script at the spec via +// the SRC_SPEC env var (a CLI path arg is also accepted), or set it in +// docs-mintlify/.env: +// +// SRC_SPEC=/path/to/open-api-spec-public-v3.1.yaml node scripts/extract-api.mjs +// node scripts/extract-api.mjs /path/to/open-api-spec-public-v3.1.yaml +// +// The spec is generated in cubejs-enterprise/packages/console-server via +// `yarn generate:open-api:spec-public`. +import fs from 'fs'; +import path from 'path'; +import yaml from 'js-yaml'; + +// Load docs-mintlify/.env (SRC_SPEC etc.) if present. A real env var or CLI arg +// still wins, since loadEnvFile does not clobber already-set process.env keys. +const envPath = path.join(import.meta.dirname, '..', '.env'); +if (fs.existsSync(envPath)) process.loadEnvFile(envPath); + +const srcArg = process.argv[2] || process.env.SRC_SPEC; +if (!srcArg) { + console.error( + 'No source spec provided. Set the SRC_SPEC env var (or pass a path arg):\n' + + ' SRC_SPEC=/path/to/open-api-spec-public-v3.1.yaml node scripts/extract-api.mjs\n' + + ' node scripts/extract-api.mjs /path/to/open-api-spec-public-v3.1.yaml\n\n' + + 'The spec is generated in cubejs-enterprise/packages/console-server via\n' + + '`yarn generate:open-api:spec-public` and is not committed to this repo.' + ); + process.exit(1); +} +const SRC = path.resolve(srcArg); +if (!fs.existsSync(SRC)) { + console.error(`Source spec not found: ${SRC}`); + process.exit(1); +} +const OUT = path.join(import.meta.dirname, '..', 'api-reference', 'api.yaml'); + +// Only the v1 REST API. SCIM lives in the hand-curated scim.yaml (different auth). +const INCLUDE_PREFIX = '/api/v1/'; +const METHODS = ['get', 'post', 'put', 'patch', 'delete']; + +// Operations to hide from the public docs even though the source spec exposes +// them — e.g. stray/internal admin routes that surface a single, incomplete +// endpoint. Listed as "METHOD /path" using the normalized path (no /api prefix, +// no trailing slash). Kept here so re-pulling an updated upstream spec does NOT +// resurface them. If a path's only operations are excluded, the whole path (and +// its now-empty nav group) is dropped automatically. +const EXCLUDE_OPERATIONS = new Set([ + // Stray/incomplete admin routes. + 'DELETE /v1/groups/{id}', + 'GET /v1/user-groups', + // Account-level / internal admin APIs kept out of the public docs. + 'GET /v1/deployments/{deploymentId}/agent-skills', + 'GET /v1/deployments/{deploymentId}/agents', + 'POST /v1/meta', + 'GET /v1/users', + 'GET /v1/users/embed-theme', + 'GET /v1/users/me', + 'DELETE /v1/user-attributes/{id}', + 'GET /v1/resource-policies', + 'PUT /v1/resource-policies/group', + 'PUT /v1/resource-policies/user', + 'GET /v1/app-theme', + 'GET /v1/ai-engineer/active-region', + 'GET /v1/ai-engineer/settings', + // Report folders listing — not part of the public docs surface. + 'GET /v1/deployments/{deploymentId}/report-folders', +]); + +// Explicit display names for tags whose auto-cleaned form would be unclear or +// collide. Everything else is cleaned by cleanTag() below. +const TAG_MAP = { + 'Deployment Environment Public': 'Environments', + 'Embed Tenant Admin Public': 'Embed Tenants', +}; +// Preferred nav order. Tags not listed here are appended alphabetically, so the +// docs stay complete even when the upstream spec adds new areas. +const TAG_ORDER = [ + 'Deployments', 'Environments', 'Folders', 'Reports', 'Workbooks', + 'Notifications', 'Workspace', 'Agents', 'Metadata', + 'Users', 'Groups', 'User Groups', 'User Attributes', 'Resource Policies', + 'App Theme', 'AI Engineer', 'Embed', 'Embed Tenants', +]; + +// Mintlify renders the OpenAPI operation `description` as a plain-text node — it +// does NOT process Markdown or HTML there, so `**bold**` and `` `code` `` show up +// literally on the page (verified by headless-rendering with Mintlify CLI 4.2.x). +// The fix is to move the prose into the `x-mint.content` extension instead, which +// Mintlify DOES render as MDX (so bold/italic/code render), and drop the plain +// `description` so it isn't also shown unformatted. See applyDescription() below. +// (Parameter/schema descriptions render fine via a different component, so they +// are left alone.) + +// x-mint.content is MDX, where `{...}` is a JS expression — unescaped prose braces +// (e.g. `Copy of {original name}`) break the page. Escape braces OUTSIDE inline +// code spans (inside backticks they're literal and must stay as-is). `**bold**` +// and `` `code` `` are valid MDX and pass through untouched. +function toMintContent(s) { + return s + .split(/(`[^`]*`)/) // keep code spans as their own (odd-index) segments + .map((seg, i) => (i % 2 === 1 ? seg : seg.replace(/[{}]/g, (c) => '\\' + c))) + .join(''); +} + +// Move an operation's Markdown description into x-mint.content (rendered as MDX) +// and remove the plain `description` so it is not also rendered unformatted. +// +// NB: do NOT also set x-mint.metadata.description — Mintlify injects that into the +// generated page's MDX frontmatter, where prose containing `"`, `:` or `{` breaks +// the YAML parse (500 / "multiline key may not be an implicit key"). The page just +// loses its ``, which is an acceptable trade for not +// crashing the page. +function applyDescription(op) { + if (typeof op.description !== 'string') return; + op['x-mint'] = { content: toMintContent(op.description) }; + delete op.description; +} + +// Strip the " Public" suffix the source appends to every tag and normalize a few +// acronyms; TAG_MAP overrides win. +function cleanTag(raw) { + if (TAG_MAP[raw]) return TAG_MAP[raw]; + return raw + .replace(/\s+Public$/, '') + .replace(/\bScim\b/g, 'SCIM') + .replace(/\bAi\b/g, 'AI'); +} + +const src = yaml.load(fs.readFileSync(SRC, 'utf8')); + +// 1. Filter to v1 REST paths, normalize keys (strip leading /api; drop trailing +// slash — a trailing slash breaks Mintlify dev), and clean tags + operationIds. +const paths = {}; +for (const [key, val] of Object.entries(src.paths)) { + if (!key.startsWith(INCLUDE_PREFIX)) continue; + let newKey = key.replace(/^\/api/, ''); + if (newKey.length > 1) newKey = newKey.replace(/\/$/, ''); // drop trailing slash + let kept = 0; + for (const m of METHODS) { + if (!val[m]) continue; + // Drop explicitly hidden operations before they reach the spec or nav. + if (EXCLUDE_OPERATIONS.has(`${m.toUpperCase()} ${newKey}`)) { + delete val[m]; + continue; + } + kept++; + if (Array.isArray(val[m].tags)) { + val[m].tags = val[m].tags.map(cleanTag); + } + // Mintlify shows the operation description as plain text, so move the prose + // into x-mint.content (rendered as MDX) and keep a plain copy for SEO. + applyDescription(val[m]); + // strip "XxxController." prefix from operationId for clean page slugs + if (typeof val[m].operationId === 'string') { + val[m].operationId = val[m].operationId.replace(/^[^.]*\./, ''); + } + } + if (!kept) continue; // every operation on this path was excluded + if (paths[newKey]) { + console.error(`Aborting: path collision after normalization: ${newKey} (from ${key}).`); + process.exit(1); + } + paths[newKey] = val; +} + +if (!Object.keys(paths).length) { + console.error(`Aborting: no paths matched ${INCLUDE_PREFIX}. Check the source spec.`); + process.exit(1); +} + +// 2. Transitive $ref schema closure. +function collectRefs(node, acc) { + if (Array.isArray(node)) { node.forEach((n) => collectRefs(n, acc)); return; } + if (node && typeof node === 'object') { + for (const [k, v] of Object.entries(node)) { + if (k === '$ref' && typeof v === 'string') { + const m = v.match(/^#\/components\/schemas\/(.+)$/); + if (m) acc.add(m[1]); + } else collectRefs(v, acc); + } + } +} +const wanted = new Set(); +collectRefs(paths, wanted); +const schemas = {}; +const missing = []; +const queue = [...wanted]; +while (queue.length) { + const name = queue.shift(); + if (schemas[name]) continue; + const def = src.components.schemas[name]; + if (!def) { missing.push(name); continue; } + schemas[name] = def; + const sub = new Set(); + collectRefs(def, sub); + for (const s of sub) if (!schemas[s]) queue.push(s); +} +// Hard-fail rather than shipping api.yaml with dangling $refs (broken docs). +if (missing.length) { + console.error( + 'Aborting: referenced schemas not found in the source spec (broken $refs):\n ' + + missing.sort().join('\n ') + + '\nThe upstream spec likely renamed or removed these. Fix the mapping and re-run.' + ); + process.exit(1); +} + +// 3. Determine tag set + order (preferred order first, then any extras A–Z). +const presentTags = new Set(); +for (const val of Object.values(paths)) { + for (const m of METHODS) { + if (val[m] && Array.isArray(val[m].tags) && val[m].tags[0]) presentTags.add(val[m].tags[0]); + } +} +const extras = [...presentTags].filter((t) => !TAG_ORDER.includes(t)).sort(); +if (extras.length) { + console.log('Note: tags not in TAG_ORDER (appended A–Z):', extras.join(', ')); +} +const orderedTags = [...TAG_ORDER.filter((t) => presentTags.has(t)), ...extras]; + +// 4. Assemble output doc (sorted schemas for stable diff). +const sortedSchemas = {}; +Object.keys(schemas).sort().forEach((k) => { sortedSchemas[k] = schemas[k]; }); + +const out = { + openapi: '3.1.0', + info: { + title: 'Cube Cloud REST API', + version: '1.0.0', + description: + 'Programmatically manage Cube Cloud: deployments and everything scoped to them\n' + + '(environments, folders, reports, workbooks, notifications, workspace, and agents),\n' + + 'plus account-level users, groups, policies, embedding, and AI settings.', + }, + servers: [ + { + url: 'https://{tenant}.cubecloud.dev/api', + description: 'Cube Cloud API base URL. Replace the whole host if you use a custom domain.', + variables: { tenant: { default: 'your-tenant', description: 'Your Cube Cloud tenant subdomain' } }, + }, + ], + security: [{ bearerAuth: [] }], + tags: orderedTags.map((t) => ({ name: t })), + paths, + components: { + // The public REST API authenticates with a token sent as + // `Authorization: Bearer ` (an API key or an OAuth access token). The + // source spec's scheme does not reflect the primary runtime auth, so override. + securitySchemes: { + bearerAuth: { + type: 'http', + scheme: 'bearer', + description: 'Token authentication. Send `Authorization: Bearer `.', + }, + }, + schemas: sortedSchemas, + }, +}; + +fs.writeFileSync(OUT, yaml.dump(out, { lineWidth: 100, noRefs: true })); +console.log('Wrote', OUT); +console.log('paths:', Object.keys(paths).length, '| schemas:', Object.keys(schemas).length, '| tags:', orderedTags.length); + +// 5. Emit nav fragment (groups in tag order; pages in source order within a tag) +// + index rows for the introduction table. +const byTag = {}; +const firstPathForTag = {}; +for (const [p, val] of Object.entries(paths)) { + for (const m of METHODS) { + if (!val[m]) continue; + const tag = (val[m].tags && val[m].tags[0]) || 'Other'; + (byTag[tag] = byTag[tag] || []).push(`${m.toUpperCase()} ${p}`); + if (!firstPathForTag[tag]) firstPathForTag[tag] = p; + } +} +const groups = orderedTags.filter((t) => byTag[t]).map((t) => ({ + group: t, + openapi: '/api-reference/api.yaml', + pages: byTag[t], +})); +console.log('\n=== NAV GROUPS (paste into docs.json API tab) ==='); +console.log(JSON.stringify(groups, null, 2)); +console.log('\n=== INDEX ROWS (entity | resource | version) ==='); +for (const t of orderedTags) { + if (firstPathForTag[t]) console.log(`${t} | ${firstPathForTag[t]} | v1`); +} diff --git a/docs-mintlify/scripts/extract-changelog.mjs b/docs-mintlify/scripts/extract-changelog.mjs new file mode 100644 index 0000000000000..58d622c84e6b1 --- /dev/null +++ b/docs-mintlify/scripts/extract-changelog.mjs @@ -0,0 +1,123 @@ +/* eslint-disable */ +// Extractor: turns the hand-written "Keep a Changelog"-style CHANGELOG.md of the +// platform client package (in the private cube cloud monorepo) into the Mintlify +// changelog page api-reference/changelog.mdx (a vertical timeline with +// an RSS feed). Run it in the same step where you re-extract the OpenAPI spec +// (extract-api.mjs) so the API reference and its changelog ship together. +// +// The source CHANGELOG.md is NOT in this repo, so there is no hardcoded path — +// point the script at it via the SRC_CHANGELOG env var (a CLI path arg also works): +// +// SRC_CHANGELOG=/path/to/platform-client/CHANGELOG.md node scripts/extract-changelog.mjs +// node scripts/extract-changelog.mjs /path/to/platform-client/CHANGELOG.md +// +// Expected source format (Keep a Changelog, https://keepachangelog.com): +// +// # Changelog +// +// ## [1.2.0] - 2026-06-06 +// ### Added +// - New workbook publish endpoint. +// ### Fixed +// - Corrected report refresh response. +// +// ## [1.1.0] - 2026-05-20 +// ... +// +// Each `## [version] - date` release becomes one block; its `### Added` +// / `### Fixed` / ... subsection names become the entry's tags. +import fs from 'fs'; +import path from 'path'; + +// Load docs-mintlify/.env (SRC_CHANGELOG etc.) if present. A real env var or CLI +// arg still wins, since loadEnvFile does not clobber already-set process.env keys. +const envPath = path.join(import.meta.dirname, '..', '.env'); +if (fs.existsSync(envPath)) process.loadEnvFile(envPath); + +const srcArg = process.argv[2] || process.env.SRC_CHANGELOG; +if (!srcArg) { + console.error( + 'No source changelog provided. Set the SRC_CHANGELOG env var (or pass a path arg):\n' + + ' SRC_CHANGELOG=/path/to/platform-client/CHANGELOG.md node scripts/extract-changelog.mjs\n' + + ' node scripts/extract-changelog.mjs /path/to/platform-client/CHANGELOG.md\n\n' + + 'The CHANGELOG.md lives in the platform client package in the cube cloud\n' + + 'monorepo and is not committed to this repo.' + ); + process.exit(1); +} +const SRC = path.resolve(srcArg); +if (!fs.existsSync(SRC)) { + console.error(`Source changelog not found: ${SRC}`); + process.exit(1); +} +const OUT = path.join(import.meta.dirname, '..', 'api-reference', 'changelog.mdx'); + +const raw = fs.readFileSync(SRC, 'utf8'); +const lines = raw.split(/\r?\n/); + +// Parse `## [version] - date` (or `## version - date`) release headings and the +// lines that follow up to the next release heading. +const RELEASE_RE = /^##\s+\[?([^\]\s]+)\]?\s*[-–—]\s*(\d{4}-\d{2}-\d{2})\s*$/; +const releases = []; +let current = null; +for (const line of lines) { + const m = line.match(RELEASE_RE); + if (m) { + current = { version: m[1], date: m[2], body: [] }; + releases.push(current); + } else if (current) { + current.body.push(line); + } +} + +if (!releases.length) { + console.error( + 'Aborting: no releases parsed from the source changelog.\n' + + 'Expected headings like `## [1.2.0] - 2026-06-06`. Check the source format.' + ); + process.exit(1); +} + +// Collect `### Section` names within a release body to use as tags. +function tagsFor(body) { + const tags = []; + for (const line of body) { + const m = line.match(/^###\s+(.+?)\s*$/); + if (m && !tags.includes(m[1])) tags.push(m[1]); + } + return tags; +} + +// Trim leading/trailing blank lines and indent body two spaces so it nests +// cleanly inside the JSX block. +function indentBody(body) { + const trimmed = [...body]; + while (trimmed.length && trimmed[0].trim() === '') trimmed.shift(); + while (trimmed.length && trimmed[trimmed.length - 1].trim() === '') trimmed.pop(); + return trimmed.map((l) => (l.trim() === '' ? '' : ` ${l}`)).join('\n'); +} + +const blocks = releases.map((r) => { + const tags = tagsFor(r.body); + const tagsAttr = tags.length ? ` tags={${JSON.stringify(tags)}}` : ''; + return ( + `\n` + + `${indentBody(r.body)}\n` + + `` + ); +}); + +const out = + `---\n` + + `title: Changelog\n` + + `description: Release notes for the Cube Cloud platform client and management API.\n` + + `rss: true\n` + + `---\n\n` + + `{/* GENERATED FILE — do not edit by hand. */}\n` + + `{/* Run scripts/extract-changelog.js against the platform client CHANGELOG.md. */}\n\n` + + blocks.join('\n\n') + + `\n`; + +fs.writeFileSync(OUT, out); +console.log('Wrote', OUT); +console.log('releases:', releases.length, '| latest:', releases[0].version, releases[0].date); diff --git a/docs-mintlify/scripts/extract-chat.js b/docs-mintlify/scripts/extract-chat.js new file mode 100644 index 0000000000000..552a7b243e4ec --- /dev/null +++ b/docs-mintlify/scripts/extract-chat.js @@ -0,0 +1,162 @@ +/* eslint-disable */ +// Extractor: pulls the /api/chat/stream-chat-state path (+ its transitive schema +// closure) out of the AI Engineer OpenAPI spec into a standalone chat.yaml for +// the Mintlify API docs. +// +// The source spec lives in the (private) cubejs-enterprise repo and is NOT in +// this repo, so there is no hardcoded path — point the script at the spec via +// the SRC_SPEC env var (a CLI path arg is also accepted): +// +// SRC_SPEC=/path/to/ai-engineer/open-api-spec.yaml node scripts/extract-chat.js +// node scripts/extract-chat.js /path/to/ai-engineer/open-api-spec.yaml +// +// The spec is generated in cubejs-enterprise/packages/ai-engineer via +// `yarn generate:open-api:spec`. +const fs = require('fs'); +const path = require('path'); +const yaml = require('js-yaml'); + +const srcArg = process.argv[2] || process.env.SRC_SPEC; +if (!srcArg) { + console.error( + 'No source spec provided. Set the SRC_SPEC env var (or pass a path arg):\n' + + ' SRC_SPEC=/path/to/ai-engineer/open-api-spec.yaml node scripts/extract-chat.js\n' + + ' node scripts/extract-chat.js /path/to/ai-engineer/open-api-spec.yaml\n\n' + + 'The spec is generated in cubejs-enterprise/packages/ai-engineer via\n' + + '`yarn generate:open-api:spec` and is not committed to this repo.' + ); + process.exit(1); +} +const SRC = path.resolve(srcArg); +if (!fs.existsSync(SRC)) { + console.error(`Source spec not found: ${SRC}`); + process.exit(1); +} +const OUT = path.join(__dirname, '..', 'api-reference', 'chat.yaml'); + +// Source path(s) to include. The public endpoint is served under +// .../agents/{agentId}, so strip the leading /api (the server URL holds it). +const SRC_PATHS = ['/api/chat/stream-chat-state']; +const TAG = 'Chat'; +const METHODS = ['get', 'post', 'put', 'patch', 'delete']; + +const src = yaml.load(fs.readFileSync(SRC, 'utf8')); + +// 1. Filter + rewrite chat paths (strip leading /api -> server holds it), +// retag to a clean name, and clean up operationIds for nice page slugs. +const paths = {}; +for (const srcKey of SRC_PATHS) { + const val = src.paths[srcKey]; + if (!val) { + console.error(`Aborting: source path not found in spec: ${srcKey}`); + process.exit(1); + } + const newKey = srcKey.replace(/^\/api/, ''); + for (const m of METHODS) { + if (!val[m]) continue; + val[m].tags = [TAG]; + if (typeof val[m].operationId === 'string') { + val[m].operationId = val[m].operationId.replace(/^[^.]*\./, ''); + } + // The public endpoint authenticates with an API key, not the JWT scheme + // baked into the source spec. Override per-operation security. + val[m].security = [{ apiKey: [] }]; + } + paths[newKey] = val; +} + +// 2. Transitive $ref schema closure. +function collectRefs(node, acc) { + if (Array.isArray(node)) { node.forEach((n) => collectRefs(n, acc)); return; } + if (node && typeof node === 'object') { + for (const [k, v] of Object.entries(node)) { + if (k === '$ref' && typeof v === 'string') { + const m = v.match(/^#\/components\/schemas\/(.+)$/); + if (m) acc.add(m[1]); + } else collectRefs(v, acc); + } + } +} +const wanted = new Set(); +collectRefs(paths, wanted); +const schemas = {}; +const missing = []; +const queue = [...wanted]; +while (queue.length) { + const name = queue.shift(); + if (schemas[name]) continue; + const def = src.components.schemas[name]; + if (!def) { missing.push(name); continue; } + schemas[name] = def; + const sub = new Set(); + collectRefs(def, sub); + for (const s of sub) if (!schemas[s]) queue.push(s); +} +// Hard-fail rather than shipping chat.yaml with dangling $refs (broken docs). +if (missing.length) { + console.error( + 'Aborting: referenced schemas not found in the source spec (broken $refs):\n ' + + missing.sort().join('\n ') + + '\nThe upstream spec likely renamed or removed these. Fix the mapping and re-run.' + ); + process.exit(1); +} + +// 3. Assemble output doc (sorted schemas for stable diff). +const sortedSchemas = {}; +Object.keys(schemas).sort().forEach((k) => { sortedSchemas[k] = schemas[k]; }); + +const out = { + openapi: '3.1.0', + info: { + title: 'Cube Cloud Chat API', + version: '1.0.0', + description: + 'Real-time streaming conversations with Cube Cloud AI agents for analytics and\n' + + 'data exploration. Copy the exact Chat API URL from your agent settings\n' + + '(Admin → Agents → Chat API URL).', + }, + servers: [ + { + url: 'https://ai.{cloudRegion}.cubecloud.dev/api/v1/public/{accountName}/agents/{agentId}', + description: + 'Chat API base URL. Copy the exact URL from your agent settings ' + + '(Admin → Agents → Chat API URL).', + variables: { + cloudRegion: { default: 'gcp-us-central1', description: 'Cloud region identifier' }, + accountName: { default: 'your-account', description: 'Your Cube Cloud account/tenant name' }, + agentId: { default: '1', description: 'AI agent identifier (Admin → Agents)' }, + }, + }, + ], + security: [{ apiKey: [] }], + tags: [{ name: TAG }], + paths, + components: { + securitySchemes: { + apiKey: { + type: 'apiKey', + in: 'header', + name: 'Authorization', + description: 'API key authentication. Send `Authorization: Api-Key `.', + }, + }, + schemas: sortedSchemas, + }, +}; + +fs.writeFileSync(OUT, yaml.dump(out, { lineWidth: 100, noRefs: true })); +console.log('Wrote', OUT); +console.log('paths:', Object.keys(paths).length, '| schemas:', Object.keys(schemas).length); + +// 4. Emit nav fragment (pages in file order). +const pages = []; +for (const [p, val] of Object.entries(paths)) { + for (const m of METHODS) { + if (!val[m]) continue; + pages.push(`${m.toUpperCase()} ${p}`); + } +} +const group = { group: TAG, openapi: '/api-reference/chat.yaml', pages }; +console.log('\n=== NAV GROUP ==='); +console.log(JSON.stringify(group, null, 2)); diff --git a/docs-mintlify/scripts/extract-core-data.js b/docs-mintlify/scripts/extract-core-data.js new file mode 100644 index 0000000000000..a1231438e7016 --- /dev/null +++ b/docs-mintlify/scripts/extract-core-data.js @@ -0,0 +1,271 @@ +/* eslint-disable */ +// Extractor: builds the Core Data REST (JSON) API reference for the Mintlify docs +// from the OSS gateway OpenAPI spec. +// +// Unlike the Platform API specs (which live in the private cubejs-enterprise +// repo), the source for the Core Data REST API is in THIS monorepo at +// packages/cubejs-api-gateway/openspec.yml, so the default path points there. +// Override with the SRC_SPEC env var or a CLI path arg if needed: +// +// node scripts/extract-core-data.js +// SRC_SPEC=/path/to/openspec.yml node scripts/extract-core-data.js +// +// Scope (minimal): the upstream spec currently documents POST /v1/load and +// GET /v1/meta. The remaining REST endpoints (sql, convert-query, cubesql, +// running-query, pre-aggregations/jobs, metadata, health) stay as prose in +// reference/core-data-apis/rest-api/reference.mdx until the upstream spec covers +// them — add them to PATHS below as the spec grows. +const fs = require('fs'); +const path = require('path'); +const yaml = require('js-yaml'); + +const DEFAULT_SRC = path.join( + __dirname, '..', '..', 'packages', 'cubejs-api-gateway', 'openspec.yml' +); +const srcArg = process.argv[2] || process.env.SRC_SPEC || DEFAULT_SRC; +const SRC = path.resolve(srcArg); +if (!fs.existsSync(SRC)) { + console.error(`Source spec not found: ${SRC}`); + process.exit(1); +} +const OUT = path.join(__dirname, '..', 'api-reference', 'core-data.yaml'); + +// Allowlist of source paths to extract from the upstream spec. +const PATHS = ['/v1/load', '/v1/meta']; +const TAG = 'Data'; +const METHODS = ['get', 'post', 'put', 'patch', 'delete']; + +// Cleaner page titles than the upstream summaries (keyed by "METHOD path"). +const SUMMARY_OVERRIDES = { + 'POST /v1/load': 'JSON query', +}; + +// Final output order of paths (extracted + hand-authored). +const PATH_ORDER = ['/v1/load', '/v1/cubesql', '/v1/meta']; + +// Endpoints not yet in the upstream openspec.yml, hand-authored here. Keep them +// in sync with reference/core-data-apis/rest-api/reference.mdx; remove an entry +// once the upstream spec covers it (then add its path to PATHS instead). +const EXTRA_PATHS = { + '/v1/cubesql': { + post: { + operationId: 'cubesqlV1', + summary: 'SQL query', + description: + 'Run a SQL query against the Cube [SQL API](/reference/core-data-apis/sql-api) ' + + 'and stream the results. The response is newline-delimited JSON: the first line ' + + 'carries the `schema` (column names and types) and optionally `lastRefreshTime`; ' + + 'each subsequent line carries a `data` chunk with one or more result rows.', + requestBody: { + required: true, + content: { + 'application/json': { + schema: { + type: 'object', + required: ['query'], + properties: { + query: { type: 'string', description: 'The SQL query to run.' }, + timezone: { + type: 'string', + description: + 'Time zone for the query in TZ database name format, e.g. America/Los_Angeles.', + }, + cache: { + type: 'string', + enum: ['stale-if-slow', 'stale-while-revalidate', 'must-revalidate', 'no-cache'], + default: 'stale-if-slow', + description: + 'In-memory cache strategy (see ' + + '[Cache control](/reference/core-data-apis/rest-api#cache-control)):\n\n' + + '- `stale-if-slow` (default): if refresh keys are up to date, return the cached ' + + 'value; if expired, fetch fresh data but fall back to the stale value when the ' + + 'source query is slow.\n' + + '- `stale-while-revalidate`: if expired, return stale data immediately and ' + + 'refresh the cache in the background.\n' + + '- `must-revalidate`: if expired, always wait for fresh data from the source, ' + + 'even if slow.\n' + + '- `no-cache`: skip refresh-key checks and always query the data source.', + }, + }, + }, + }, + }, + }, + responses: { + '200': { + description: + 'Newline-delimited JSON stream. The first line carries `schema` (and optionally ' + + '`lastRefreshTime`); subsequent lines carry `data` chunks.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + schema: { + type: 'array', + items: { + type: 'object', + properties: { + name: { type: 'string' }, + column_type: { type: 'string' }, + }, + }, + }, + lastRefreshTime: { type: 'string', format: 'date-time' }, + data: { type: 'array', items: { type: 'array', items: {} } }, + }, + }, + examples: { + schemaLine: { + summary: 'First line (schema)', + value: { + schema: [{ name: 'value', column_type: 'Int64' }], + lastRefreshTime: '2025-01-13T12:00:00.000Z', + }, + }, + dataLine: { summary: 'Data chunk', value: { data: [['123']] } }, + }, + }, + }, + }, + }, + }, + }, +}; + +const src = yaml.load(fs.readFileSync(SRC, 'utf8')); + +// 1. Collect extracted + hand-authored paths, retag, override auth and summaries. +const collected = {}; +for (const key of PATHS) { + const val = src.paths[key]; + if (!val) { + console.error(`Aborting: source path not found in spec: ${key}`); + process.exit(1); + } + collected[key] = val; +} +Object.assign(collected, EXTRA_PATHS); + +for (const [key, val] of Object.entries(collected)) { + for (const m of METHODS) { + if (!val[m]) continue; + val[m].tags = [TAG]; + // The data API authenticates with a Cube API token sent directly in the + // Authorization header (no "Bearer" prefix), not the http-bearer scheme the + // upstream spec declares. Pin each operation to the apiToken scheme. + val[m].security = [{ apiToken: [] }]; + const override = SUMMARY_OVERRIDES[`${m.toUpperCase()} ${key}`]; + if (override) val[m].summary = override; + } +} + +// Assemble in the desired output order. +const paths = {}; +for (const key of PATH_ORDER) { + if (collected[key]) paths[key] = collected[key]; +} + +// 2. Transitive $ref schema closure. +function collectRefs(node, acc) { + if (Array.isArray(node)) { node.forEach((n) => collectRefs(n, acc)); return; } + if (node && typeof node === 'object') { + for (const [k, v] of Object.entries(node)) { + if (k === '$ref' && typeof v === 'string') { + const m = v.match(/^#\/components\/schemas\/(.+)$/); + if (m) acc.add(m[1]); + } else collectRefs(v, acc); + } + } +} +const wanted = new Set(); +collectRefs(paths, wanted); +const schemas = {}; +const missing = []; +const queue = [...wanted]; +while (queue.length) { + const name = queue.shift(); + if (schemas[name]) continue; + const def = src.components.schemas[name]; + if (!def) { missing.push(name); continue; } + schemas[name] = def; + const sub = new Set(); + collectRefs(def, sub); + for (const s of sub) if (!schemas[s]) queue.push(s); +} +// Hard-fail rather than shipping core-data.yaml with dangling $refs. +if (missing.length) { + console.error( + 'Aborting: referenced schemas not found in the source spec (broken $refs):\n ' + + missing.sort().join('\n ') + ); + process.exit(1); +} + +// 3. Assemble output doc (sorted schemas for stable diff). +const sortedSchemas = {}; +Object.keys(schemas).sort().forEach((k) => { sortedSchemas[k] = schemas[k]; }); + +const out = { + openapi: '3.0.0', + info: { + title: 'Cube Core Data REST (JSON) API', + version: '1.0.0', + description: + 'Deliver data from Cube over HTTP. Run queries with `POST /v1/load` and\n' + + 'retrieve the data model with `GET /v1/meta`. The `{base_path}` segment\n' + + '(`/cubejs-api` by default) is configurable.', + }, + servers: [ + { + url: 'https://{deployment}.{region}.cubecloudapp.dev/cubejs-api', + description: + 'Cube Cloud deployment REST API. The host includes your deployment slug and ' + + 'region; copy the exact URL from your deployment\'s API settings. The ' + + '/cubejs-api base path is configurable.', + variables: { + deployment: { default: 'your-deployment', description: 'Your Cube Cloud deployment slug' }, + region: { + default: 'aws-us-east-1', + description: 'Cloud region of your deployment, e.g. aws-us-east-1, aws-eu-central-1, gcp-us-central1', + }, + }, + }, + { + url: 'http://localhost:4000/cubejs-api', + description: 'Self-hosted Cube (default port and base path).', + }, + ], + security: [{ apiToken: [] }], + tags: [{ name: TAG }], + paths, + components: { + securitySchemes: { + apiToken: { + type: 'apiKey', + in: 'header', + name: 'Authorization', + description: + 'Cube API token (a JWT). Sent directly in the Authorization header, ' + + 'e.g. `Authorization: ` (no "Bearer" prefix).', + }, + }, + schemas: sortedSchemas, + }, +}; + +fs.writeFileSync(OUT, yaml.dump(out, { lineWidth: 100, noRefs: true })); +console.log('Wrote', OUT); +console.log('paths:', Object.keys(paths).length, '| schemas:', Object.keys(schemas).length); + +// 4. Emit nav fragment (pages in allowlist order). +const pages = []; +for (const p of Object.keys(paths)) { + for (const m of METHODS) { + if (!paths[p][m]) continue; + pages.push(`${m.toUpperCase()} ${p}`); + } +} +const group = { group: 'REST (JSON) API', openapi: '/api-reference/core-data.yaml', pages }; +console.log('\n=== NAV PAGES ==='); +console.log(JSON.stringify(group, null, 2)); diff --git a/docs-mintlify/scripts/migrate.py b/docs-mintlify/scripts/migrate.py new file mode 100755 index 0000000000000..3cf9210c48812 --- /dev/null +++ b/docs-mintlify/scripts/migrate.py @@ -0,0 +1,182 @@ +#!/usr/bin/env python3 +""" +Main migration orchestrator. Runs all migration steps in sequence. + +Usage: + # Full migration (all steps): + python migrate.py --source ../../docs/content/product --dest ../../docs-mintlify + + # Dry run (preview everything): + python migrate.py --source ../../docs/content/product --dest ../../docs-mintlify --dry-run + + # Run specific steps only: + python migrate.py --source ../../docs/content/product --dest ../../docs-mintlify --steps copy,transform,links + + # Incremental (for late-arriving content): + python migrate.py --source ../../docs/content/product --dest ../../docs-mintlify --incremental + + # Migrate a single section: + python migrate.py --source ../../docs/content/product --dest ../../docs-mintlify --section getting-started +""" + +import argparse +import subprocess +import sys +from pathlib import Path + + +SCRIPTS_DIR = Path(__file__).parent.resolve() + +STEPS = { + "copy": { + "description": "Copy and restructure content files", + "script": "copy_content.py", + }, + "transform": { + "description": "Transform Nextra components to Mintlify", + "script": "transform_components.py", + }, + "frontmatter": { + "description": "Update frontmatter for Mintlify", + "script": "update_frontmatter.py", + }, + "links": { + "description": "Rewrite internal links", + "script": "rewrite_links.py", + }, + "check": { + "description": "Verify all internal links", + "script": "check_links.py", + }, +} + +DEFAULT_STEPS = ["copy", "transform", "frontmatter", "links", "check"] + + +def run_step( + step_name: str, + source: Path, + dest: Path, + dry_run: bool, + incremental: bool, + section, +) -> bool: + """Run a single migration step. Returns True on success.""" + step = STEPS[step_name] + script = SCRIPTS_DIR / step["script"] + + print(f"\n{'='*60}") + print(f"Step: {step_name} — {step['description']}") + print(f"{'='*60}") + + cmd = [sys.executable, str(script)] + + if step_name == "copy": + cmd.extend(["--source", str(source), "--dest", str(dest)]) + if dry_run: + cmd.append("--dry-run") + if incremental: + cmd.append("--incremental") + if section: + cmd.extend(["--section", section]) + + elif step_name in ("transform", "frontmatter", "links"): + # These operate on the destination directory + cmd.append(str(dest)) + if dry_run: + cmd.append("--dry-run") + + elif step_name == "check": + cmd.append(str(dest)) + cmd.append("--verbose") + + result = subprocess.run(cmd, cwd=SCRIPTS_DIR) + + if result.returncode != 0: + if step_name == "check": + print(f"\n⚠ Link check found broken links (expected during migration)") + return True # Don't fail the pipeline on broken links + print(f"\n✗ Step '{step_name}' failed with exit code {result.returncode}") + return False + + print(f"\n✓ Step '{step_name}' completed successfully") + return True + + +def main(): + parser = argparse.ArgumentParser( + description="Orchestrate the full Nextra-to-Mintlify migration." + ) + parser.add_argument( + "--source", + required=True, + help="Source directory (docs/content/product/)", + ) + parser.add_argument( + "--dest", + required=True, + help="Destination directory (docs-mintlify/)", + ) + parser.add_argument( + "--dry-run", + action="store_true", + help="Preview all changes without writing", + ) + parser.add_argument( + "--incremental", + action="store_true", + help="Only process new/changed files", + ) + parser.add_argument( + "--section", + help="Migrate only a specific section", + ) + parser.add_argument( + "--steps", + help=f"Comma-separated list of steps to run. Available: {','.join(DEFAULT_STEPS)}", + ) + + args = parser.parse_args() + + source = Path(args.source).resolve() + dest = Path(args.dest).resolve() + + if not source.is_dir(): + print(f"Error: Source not found: {source}", file=sys.stderr) + sys.exit(1) + + steps = args.steps.split(",") if args.steps else DEFAULT_STEPS + + # Validate steps + for step in steps: + if step not in STEPS: + print(f"Error: Unknown step '{step}'. Available: {', '.join(STEPS.keys())}", file=sys.stderr) + sys.exit(1) + + print(f"Migration: {source} -> {dest}") + print(f"Steps: {', '.join(steps)}") + if args.dry_run: + print("Mode: DRY RUN") + if args.incremental: + print("Mode: INCREMENTAL") + if args.section: + print(f"Section: {args.section}") + + failed = [] + for step in steps: + success = run_step(step, source, dest, args.dry_run, args.incremental, args.section) + if not success: + failed.append(step) + print(f"\nStopping due to failure in step '{step}'") + break + + print(f"\n{'='*60}") + if failed: + print(f"Migration completed with failures: {', '.join(failed)}") + sys.exit(1) + else: + print(f"Migration completed successfully! ({len(steps)} steps)") + + +if __name__ == "__main__": + main() diff --git a/docs-mintlify/scripts/migrate_redirects.py b/docs-mintlify/scripts/migrate_redirects.py new file mode 100755 index 0000000000000..5ffe85befd169 --- /dev/null +++ b/docs-mintlify/scripts/migrate_redirects.py @@ -0,0 +1,231 @@ +#!/usr/bin/env python3 +""" +Migrate redirects from Nextra's redirects.json to Mintlify's mint.json format. + +Also generates new redirects for pages that changed paths during migration +(e.g., /product/auth/... -> /access-security/...). + +Usage: + # Generate Mintlify redirects from existing redirects.json: + python migrate_redirects.py /path/to/docs/redirects.json + + # Also generate path-migration redirects: + python migrate_redirects.py /path/to/docs/redirects.json --with-migration-redirects + + # Output as JSON (for pasting into mint.json): + python migrate_redirects.py /path/to/docs/redirects.json --format json + + # Output as a standalone redirects array file: + python migrate_redirects.py /path/to/docs/redirects.json -o redirects.json +""" + +import argparse +import json +import sys +from pathlib import Path + +# Import path rewriting logic from sibling script +# If running standalone, define the rules inline +try: + from rewrite_links import rewrite_path, PATH_REWRITES +except ImportError: + PATH_REWRITES = [ + ("/product/apis-integrations/core-data-apis", "/api-reference/core-data-apis"), + ("/product/apis-integrations/embed-apis", "/api-reference/embed-apis"), + ("/product/apis-integrations/control-plane-api", "/api-reference/control-plane-api"), + ("/product/apis-integrations/orchestration-api", "/api-reference/orchestration-api"), + ("/product/apis-integrations/javascript-sdk", "/api-reference/javascript-sdk"), + ("/product/apis-integrations/mcp-server", "/api-reference/mcp-server"), + ("/product/apis-integrations/recipes", "/api-reference/recipes"), + ("/product/apis-integrations/microsoft-excel", "/docs/integrations/microsoft-excel"), + ("/product/apis-integrations/google-sheets", "/docs/integrations/google-sheets"), + ("/product/apis-integrations/tableau", "/docs/integrations/tableau"), + ("/product/apis-integrations/power-bi", "/docs/integrations/power-bi"), + ("/product/apis-integrations/semantic-layer-sync", "/docs/integrations/semantic-layer-sync"), + ("/product/apis-integrations/snowflake-semantic-views", "/docs/integrations/snowflake-semantic-views"), + ("/product/apis-integrations", "/api-reference"), + ("/product/auth/methods", "/access-security/authentication"), + ("/product/auth", "/access-security/access-control"), + ("/product/administration/sso", "/access-security/sso"), + ("/product/administration/users-and-permissions", "/access-security/users-and-permissions"), + ("/product/administration", "/admin"), + ("/product/exploration", "/analytics"), + ("/product/presentation", "/analytics"), + ("/product/embedding", "/embedding"), + ("/product/getting-started", "/docs/getting-started"), + ("/product/configuration", "/docs/configuration"), + ("/product/data-modeling", "/docs/data-modeling"), + ("/product/caching", "/docs/caching"), + ("/product/introduction", "/docs/introduction"), + ] + + def rewrite_path(old_path: str) -> str: + for old_prefix, new_prefix in PATH_REWRITES: + if old_path == old_prefix or old_path.startswith(old_prefix + "/") or old_path.startswith(old_prefix + "#"): + remainder = old_path[len(old_prefix):] + return new_prefix + remainder + if old_path.startswith("/product/"): + return "/docs/" + old_path[len("/product/"):] + return old_path + + +def load_nextra_redirects(filepath: Path) -> list[dict]: + """Load redirects from Nextra's redirects.json.""" + with open(filepath, "r", encoding="utf-8") as f: + data = json.load(f) + + # Nextra format: [{"source": "/old", "destination": "/new", "permanent": true}, ...] + if isinstance(data, list): + return data + # Some formats nest under a key + if isinstance(data, dict) and "redirects" in data: + return data["redirects"] + return data + + +def convert_redirect(redirect: dict) -> dict: + """Convert a single Nextra redirect to Mintlify format.""" + source = redirect.get("source", "") + destination = redirect.get("destination", "") + + # Rewrite both source and destination to new paths + new_destination = rewrite_path(destination) + + # Mintlify format: {"source": "/old", "destination": "/new"} + return { + "source": source, + "destination": new_destination, + } + + +def generate_migration_redirects() -> list[dict]: + """ + Generate redirects for all pages that moved during migration. + + Creates /product/X -> /new-tab/X redirects so old URLs still work. + """ + redirects = [] + + # Generate wildcard-style redirects for each path prefix change + for old_prefix, new_prefix in PATH_REWRITES: + # Exact match redirect + redirects.append({ + "source": old_prefix, + "destination": new_prefix, + }) + # Wildcard redirect for all subpaths + # Mintlify does not support true wildcards, but we can add + # the prefix redirect and rely on specific page redirects + # for known subpaths + + return redirects + + +def deduplicate_redirects(redirects: list[dict]) -> list[dict]: + """Remove duplicate redirects, keeping the last one for each source.""" + seen = {} + for r in redirects: + source = r["source"] + seen[source] = r + + return list(seen.values()) + + +def validate_redirects(redirects: list[dict]) -> list[str]: + """Check for redirect loops and chains.""" + warnings = [] + dest_set = {r["destination"] for r in redirects} + source_set = {r["source"] for r in redirects} + + for r in redirects: + # Self-redirect + if r["source"] == r["destination"]: + warnings.append(f"Self-redirect: {r['source']}") + + # Chain: destination is also a source + if r["destination"] in source_set: + warnings.append(f"Redirect chain: {r['source']} -> {r['destination']} -> ...") + + return warnings + + +def main(): + parser = argparse.ArgumentParser( + description="Migrate redirects from Nextra to Mintlify format." + ) + parser.add_argument( + "redirects_file", + help="Path to Nextra's redirects.json", + ) + parser.add_argument( + "--with-migration-redirects", + action="store_true", + help="Also generate redirects for path changes from migration", + ) + parser.add_argument( + "--format", + choices=["json", "jsonl"], + default="json", + help="Output format (default: json)", + ) + parser.add_argument( + "-o", "--output", + help="Output file path (default: stdout)", + ) + parser.add_argument( + "--validate", + action="store_true", + help="Validate redirects for loops and chains", + ) + + args = parser.parse_args() + + # Load existing redirects + redirects_path = Path(args.redirects_file) + if not redirects_path.exists(): + print(f"Error: {redirects_path} not found", file=sys.stderr) + sys.exit(1) + + nextra_redirects = load_nextra_redirects(redirects_path) + print(f"Loaded {len(nextra_redirects)} existing redirects", file=sys.stderr) + + # Convert to Mintlify format + mintlify_redirects = [convert_redirect(r) for r in nextra_redirects] + + # Add migration redirects if requested + if args.with_migration_redirects: + migration_redirects = generate_migration_redirects() + print(f"Generated {len(migration_redirects)} migration redirects", file=sys.stderr) + mintlify_redirects = migration_redirects + mintlify_redirects + + # Deduplicate + original_count = len(mintlify_redirects) + mintlify_redirects = deduplicate_redirects(mintlify_redirects) + if original_count != len(mintlify_redirects): + print( + f"Deduplicated: {original_count} -> {len(mintlify_redirects)}", + file=sys.stderr, + ) + + # Validate + if args.validate: + warnings = validate_redirects(mintlify_redirects) + if warnings: + print(f"\n{len(warnings)} warnings:", file=sys.stderr) + for w in warnings: + print(f" - {w}", file=sys.stderr) + else: + print("No redirect issues found.", file=sys.stderr) + + # Output + output = json.dumps(mintlify_redirects, indent=2) + + if args.output: + Path(args.output).write_text(output, encoding="utf-8") + print(f"Wrote {len(mintlify_redirects)} redirects to {args.output}", file=sys.stderr) + else: + print(output) + + +if __name__ == "__main__": + main() diff --git a/docs-mintlify/scripts/rewrite_links.py b/docs-mintlify/scripts/rewrite_links.py new file mode 100755 index 0000000000000..0b8da535dedc9 --- /dev/null +++ b/docs-mintlify/scripts/rewrite_links.py @@ -0,0 +1,227 @@ +#!/usr/bin/env python3 +""" +Rewrite internal links from Nextra /product/ paths to Mintlify tab-based paths. + +Handles: + - Inline links: [text](/product/configuration/...) + - Reference-style definitions: [ref-name]: /product/configuration/... + - Relative links within the same section + +Usage: + # Rewrite a single file (in-place): + python rewrite_links.py path/to/file.mdx + + # Rewrite a directory recursively: + python rewrite_links.py path/to/docs/ + + # Dry run: + python rewrite_links.py --dry-run path/to/docs/ + + # Pipe mode: + cat file.mdx | python rewrite_links.py --stdin +""" + +import argparse +import re +import sys +from pathlib import Path + + +# Maps old /product/... paths to new tab-based paths. +# Order matters: more specific prefixes must come first. +PATH_REWRITES = [ + # APIs & Integrations -> split between api-reference/ and docs/integrations/ + # API reference pages + ("/product/apis-integrations/core-data-apis", "/api-reference/core-data-apis"), + ("/product/apis-integrations/embed-apis", "/api-reference/embed-apis"), + ("/product/apis-integrations/control-plane-api", "/api-reference/control-plane-api"), + ("/product/apis-integrations/orchestration-api", "/api-reference/orchestration-api"), + ("/product/apis-integrations/javascript-sdk", "/api-reference/javascript-sdk"), + ("/product/apis-integrations/mcp-server", "/api-reference/mcp-server"), + ("/product/apis-integrations/recipes", "/api-reference/recipes"), + # Integration pages -> stay in docs + ("/product/apis-integrations/microsoft-excel", "/docs/integrations/microsoft-excel"), + ("/product/apis-integrations/google-sheets", "/docs/integrations/google-sheets"), + ("/product/apis-integrations/tableau", "/docs/integrations/tableau"), + ("/product/apis-integrations/power-bi", "/docs/integrations/power-bi"), + ("/product/apis-integrations/semantic-layer-sync", "/docs/integrations/semantic-layer-sync"), + ("/product/apis-integrations/snowflake-semantic-views", "/docs/integrations/snowflake-semantic-views"), + # Catch-all for any remaining apis-integrations + ("/product/apis-integrations", "/api-reference"), + + # Access control -> access-security/ + ("/product/auth/methods", "/access-security/authentication"), + ("/product/auth", "/access-security/access-control"), + + # Administration -> split between admin/ and access-security/ + ("/product/administration/sso", "/access-security/sso"), + ("/product/administration/users-and-permissions", "/access-security/users-and-permissions"), + ("/product/administration", "/admin"), + + # Exploration -> analytics/ + ("/product/exploration", "/analytics"), + + # Presentation -> analytics/ + ("/product/presentation", "/analytics"), + + # Embedding -> embedding/ + ("/product/embedding", "/embedding"), + + # Core docs sections -> docs/ + ("/product/getting-started", "/docs/getting-started"), + ("/product/configuration", "/docs/configuration"), + ("/product/data-modeling", "/docs/data-modeling"), + ("/product/caching", "/docs/caching"), + ("/product/introduction", "/docs/introduction"), +] + + +def rewrite_path(old_path: str) -> str: + """Rewrite a single path from Nextra to Mintlify structure.""" + for old_prefix, new_prefix in PATH_REWRITES: + if old_path == old_prefix or old_path.startswith(old_prefix + "/") or old_path.startswith(old_prefix + "#"): + # Preserve the rest of the path after the prefix + remainder = old_path[len(old_prefix):] + return new_prefix + remainder + + # If no rewrite rule matches but starts with /product/, strip it + if old_path.startswith("/product/"): + return "/docs/" + old_path[len("/product/"):] + + return old_path + + +def rewrite_links_in_content(content: str) -> str: + """Rewrite all internal links in MDX content.""" + + # 1. Inline markdown links: [text](/product/...) + def inline_link_replacer(match): + text = match.group(1) + path = match.group(2) + if path.startswith("/product/"): + new_path = rewrite_path(path) + return f"[{text}]({new_path})" + return match.group(0) + + content = re.sub( + r"\[([^\]]*)\]\((/product/[^)]+)\)", + inline_link_replacer, + content, + ) + + # 2. Reference-style link definitions: [ref-name]: /product/... + def reflink_replacer(match): + ref_name = match.group(1) + path = match.group(2) + if path.startswith("/product/"): + new_path = rewrite_path(path) + return f"[{ref_name}]: {new_path}" + return match.group(0) + + content = re.sub( + r"^\[([^\]]+)\]:\s*(/product/[^\s]+)\s*$", + reflink_replacer, + content, + flags=re.MULTILINE, + ) + + # 3. href attributes in JSX: href="/product/..." + def href_replacer(match): + path = match.group(1) + if path.startswith("/product/"): + new_path = rewrite_path(path) + return f'href="{new_path}"' + return match.group(0) + + content = re.sub( + r'href="(/product/[^"]+)"', + href_replacer, + content, + ) + + # 4. url attributes in JSX (used in GridItem): url="/product/..." + def url_replacer(match): + path = match.group(1) + if path.startswith("/product/"): + new_path = rewrite_path(path) + return f'url="{new_path}"' + return match.group(0) + + content = re.sub( + r'url="(/product/[^"]+)"', + url_replacer, + content, + ) + + return content + + +def process_file(filepath: Path, dry_run: bool = False) -> bool: + """Process a single file. Returns True if changes were made.""" + content = filepath.read_text(encoding="utf-8") + transformed = rewrite_links_in_content(content) + + if content == transformed: + return False + + if dry_run: + print(f"[WOULD CHANGE] {filepath}") + orig_lines = content.splitlines() + new_lines = transformed.splitlines() + changes = 0 + for i, (old, new) in enumerate(zip(orig_lines, new_lines)): + if old != new: + changes += 1 + if changes <= 15: + print(f" L{i+1}:") + print(f" - {old.strip()}") + print(f" + {new.strip()}") + if changes > 15: + print(f" ... and {changes - 15} more changes") + print() + else: + filepath.write_text(transformed, encoding="utf-8") + print(f"[UPDATED] {filepath}") + + return True + + +def main(): + parser = argparse.ArgumentParser( + description="Rewrite internal links from Nextra /product/ paths to Mintlify tab-based paths." + ) + parser.add_argument("path", nargs="?", help="File or directory to process") + parser.add_argument("--dry-run", action="store_true", help="Show changes without writing") + parser.add_argument("--stdin", action="store_true", help="Read from stdin, write to stdout") + + args = parser.parse_args() + + if args.stdin: + content = sys.stdin.read() + sys.stdout.write(rewrite_links_in_content(content)) + return + + if not args.path: + parser.error("Either --stdin or a path is required") + + target = Path(args.path) + + if target.is_file(): + changed = process_file(target, dry_run=args.dry_run) + if not changed: + print(f"[NO CHANGES] {target}") + elif target.is_dir(): + changed_count = 0 + total_count = 0 + for mdx_file in sorted(target.rglob("*.mdx")): + total_count += 1 + if process_file(mdx_file, dry_run=args.dry_run): + changed_count += 1 + print(f"\nProcessed {total_count} files, {changed_count} changed.") + else: + print(f"Error: {target} not found", file=sys.stderr) + sys.exit(1) + + +if __name__ == "__main__": + main() diff --git a/docs-mintlify/scripts/transform_components.py b/docs-mintlify/scripts/transform_components.py new file mode 100755 index 0000000000000..ccdef015b7acc --- /dev/null +++ b/docs-mintlify/scripts/transform_components.py @@ -0,0 +1,569 @@ +#!/usr/bin/env python3 +""" +Transform Nextra custom MDX components to Mintlify equivalents. + +Usage: + # Transform a single file (in-place): + python transform_components.py path/to/file.mdx + + # Transform a directory recursively: + python transform_components.py path/to/docs/ + + # Dry run (show changes without writing): + python transform_components.py --dry-run path/to/docs/ + + # Pipe mode (stdin/stdout): + cat file.mdx | python transform_components.py --stdin +""" + +import argparse +import os +import re +import sys +from pathlib import Path + + +def transform_alert_boxes(content: str) -> str: + """InfoBox -> Info, WarningBox -> Warning, SuccessBox -> Tip, ReferenceBox -> Note.""" + replacements = { + "InfoBox": "Info", + "WarningBox": "Warning", + "SuccessBox": "Tip", + "ReferenceBox": "Note", + } + for nextra, mintlify in replacements.items(): + content = content.replace(f"<{nextra}>", f"<{mintlify}>") + content = content.replace(f"", f"") + # Also handle tags with attributes: -> + content = re.sub( + rf"<{nextra}\s+[^>]*>", + f"<{mintlify}>", + content, + ) + return content + + +def transform_codetabs(content: str) -> str: + """ + Transform to . + + Mintlify's CodeGroup requires a title on each code block. + We add title attributes based on the language or filename. + """ + content = content.replace("", "") + content = content.replace("", "") + + # Language display names + lang_names = { + "yaml": "YAML", + "yml": "YAML", + "javascript": "JavaScript", + "js": "JavaScript", + "typescript": "TypeScript", + "ts": "TypeScript", + "python": "Python", + "py": "Python", + "bash": "Bash", + "sh": "Shell", + "shell": "Shell", + "sql": "SQL", + "json": "JSON", + "jsx": "JSX", + "tsx": "TSX", + "graphql": "GraphQL", + "ruby": "Ruby", + "go": "Go", + "rust": "Rust", + "java": "Java", + "toml": "TOML", + "ini": "INI", + "text": "Text", + "plaintext": "Text", + "csv": "CSV", + "xml": "XML", + "html": "HTML", + "css": "CSS", + "scss": "SCSS", + "dockerfile": "Dockerfile", + "docker": "Docker", + "nginx": "Nginx", + "env": ".env", + "dotenv": ".env", + "r": "R", + "swift": "Swift", + "kotlin": "Kotlin", + "php": "PHP", + "lua": "Lua", + "dart": "Dart", + "c": "C", + "cpp": "C++", + "csharp": "C#", + } + + def add_code_block_title(match): + """Add title to code blocks inside CodeGroup sections.""" + backticks = match.group(1) + lang = match.group(2) or "" + rest = match.group(3) or "" + + # If there's already a filename attribute, use it as the title + filename_match = re.search(r'filename="([^"]+)"', rest) + if filename_match: + # Mintlify uses title= instead of filename= + filename = filename_match.group(1) + rest_without_filename = re.sub(r'\s*filename="[^"]+"', "", rest) + return f'{backticks}{lang} title="{filename}"{rest_without_filename}' + + # If already has a title, leave it alone + if "title=" in rest: + return match.group(0) + + # Add title based on language + title = lang_names.get(lang.strip(), lang.strip().capitalize() if lang.strip() else "") + if title: + return f'{backticks}{lang} title="{title}"{rest}' + + return match.group(0) + + # Priority order for code blocks: YAML first, then Python, then rest + LANG_PRIORITY = {"yaml": 0, "yml": 0, "python": 1, "py": 1} + + def reorder_code_blocks(group_content): + """Reorder code blocks so YAML comes first, then Python, then others.""" + # Split into individual code blocks + block_pattern = re.compile(r"(```+\w*.*?```+)", re.DOTALL) + blocks = block_pattern.findall(group_content) + if len(blocks) <= 1: + return group_content + + def block_sort_key(block): + lang_match = re.match(r"```+(\w+)", block) + lang = lang_match.group(1).lower() if lang_match else "" + return LANG_PRIORITY.get(lang, 99) + + sorted_blocks = sorted(blocks, key=block_sort_key) + if sorted_blocks == blocks: + return group_content + + # Rebuild with sorted blocks + result = "\n\n".join(sorted_blocks) + return "\n\n" + result + "\n\n" + + # Only add titles to code blocks that are inside sections + def process_codegroup(match): + group_content = match.group(1) + # Reorder so YAML is first + group_content = reorder_code_blocks(group_content) + # Add title to code fences inside the group + group_content = re.sub( + r"(```+)(\w+)?(.*?)$", + add_code_block_title, + group_content, + flags=re.MULTILINE, + ) + return f"{group_content}" + + content = re.sub( + r"(.*?)", + process_codegroup, + content, + flags=re.DOTALL, + ) + + return content + + +def transform_screenshot(content: str) -> str: + """ + Transform to . + + Handles both self-closing and multiline forms: + + + """ + + def screenshot_replacer(match): + tag_content = match.group(1) + src_match = re.search(r'src="([^"]+)"', tag_content) + alt_match = re.search(r'alt="([^"]+)"', tag_content) + + src = src_match.group(1) if src_match else "" + alt = alt_match.group(1) if alt_match else "" + + if alt: + return f'\n {alt}\n' + else: + return f'\n \n' + + # Match self-closing and multiline Screenshot tags + content = re.sub( + r"", + screenshot_replacer, + content, + flags=re.DOTALL, + ) + + return content + + +def transform_diagram(content: str) -> str: + """Transform to .""" + + def diagram_replacer(match): + tag_content = match.group(1) + src_match = re.search(r'src="([^"]+)"', tag_content) + alt_match = re.search(r'alt="([^"]+)"', tag_content) + + src = src_match.group(1) if src_match else "" + alt = alt_match.group(1) if alt_match else "" + + if alt: + return f'\n {alt}\n' + else: + return f'\n \n' + + content = re.sub( + r"", + diagram_replacer, + content, + flags=re.DOTALL, + ) + + return content + + +def transform_youtube(content: str) -> str: + """Transform to an iframe.""" + + def youtube_replacer(match): + tag_content = match.group(1) + url_match = re.search(r'url="([^"]+)"', tag_content) + url = url_match.group(1) if url_match else "" + + return ( + f'' + ) + + content = re.sub( + r"", + youtube_replacer, + content, + flags=re.DOTALL, + ) + + return content + + +def transform_loom(content: str) -> str: + """Transform to an iframe.""" + + def loom_replacer(match): + tag_content = match.group(1) + url_match = re.search(r'url="([^"]+)"', tag_content) + url = url_match.group(1) if url_match else "" + + return ( + f'' + ) + + content = re.sub( + r"", + loom_replacer, + content, + flags=re.DOTALL, + ) + + return content + + +def transform_grid(content: str) -> str: + """ + Transform / to /. + + + + + + becomes: + + + + + + """ + + def grid_replacer(match): + tag_attrs = match.group(1) + inner = match.group(2) + + # Extract cols + cols_match = re.search(r"cols=\{(\d+)\}", tag_attrs) + cols = cols_match.group(1) if cols_match else "2" + + # Transform GridItems inside + def griditem_replacer(gi_match): + gi_content = gi_match.group(1) + url_match = re.search(r'url="([^"]+)"', gi_content) + title_match = re.search(r'title="([^"]+)"', gi_content) + img_match = re.search(r'imageUrl="([^"]+)"', gi_content) + + url = url_match.group(1) if url_match else "" + title = title_match.group(1) if title_match else "" + img = img_match.group(1) if img_match else "" + + parts = [f'\n ") + return "".join(parts) + + inner = re.sub( + r"", + griditem_replacer, + inner, + flags=re.DOTALL, + ) + + return f"{inner}" + + content = re.sub( + r"(.*?)", + grid_replacer, + content, + flags=re.DOTALL, + ) + + return content + + +def transform_envvar(content: str) -> str: + """ + Transform VAR_NAME to a code-linked reference. + + Becomes: [`VAR_NAME`](/docs/configuration/reference/environment-variables#var_name) + """ + + def envvar_replacer(match): + var_name = match.group(1) + anchor = var_name.lower().replace("_", "_") + return f"[`{var_name}`](/docs/configuration/reference/environment-variables#{anchor})" + + content = re.sub( + r"([^<]+)", + envvar_replacer, + content, + ) + + return content + + +def transform_btn(content: str) -> str: + """Transform Settings → Configuration to **Settings → Configuration**.""" + content = re.sub( + r"([^<]+)", + r"**\1**", + content, + ) + return content + + +def transform_community_driver(content: str) -> str: + """ + Transform to a Warning callout. + """ + + def driver_replacer(match): + datasource = match.group(1) + return ( + f"\n\n" + f"The driver for {datasource} is community-supported and is not " + f"maintained by Cube or the database vendor.\n\n" + f"" + ) + + content = re.sub( + r'', + driver_replacer, + content, + ) + + return content + + +def transform_product_video(content: str) -> str: + """Transform to an iframe.""" + + def video_replacer(match): + tag_content = match.group(1) + url_match = re.search(r'url="([^"]+)"', tag_content) + url = url_match.group(1) if url_match else "" + + return ( + f'' + ) + + content = re.sub( + r"", + video_replacer, + content, + flags=re.DOTALL, + ) + + return content + + +def transform_filename_to_title(content: str) -> str: + """ + Transform filename= attribute on code blocks to title= for Mintlify. + + ```python filename="cube.py" -> ```python title="cube.py" + + Only applies to code blocks NOT inside a CodeGroup (those are handled + by transform_codetabs). + """ + # Find code blocks that are NOT inside CodeGroup + # We do a simple replacement since CodeGroup blocks are already processed + # and their filename= attrs are already converted + + def replacer(match): + prefix = match.group(1) + filename = match.group(2) + rest = match.group(3) + return f'{prefix}title="{filename}"{rest}' + + content = re.sub( + r'(```\w+)\s+filename="([^"]+)"(.*?)$', + replacer, + content, + flags=re.MULTILINE, + ) + + return content + + +def transform_all(content: str) -> str: + """Apply all component transformations in order.""" + content = transform_alert_boxes(content) + content = transform_codetabs(content) + content = transform_screenshot(content) + content = transform_diagram(content) + content = transform_youtube(content) + content = transform_loom(content) + content = transform_product_video(content) + content = transform_grid(content) + content = transform_envvar(content) + content = transform_btn(content) + content = transform_community_driver(content) + content = transform_filename_to_title(content) + return content + + +def process_file(filepath: Path, dry_run: bool = False) -> bool: + """Process a single MDX file. Returns True if changes were made.""" + content = filepath.read_text(encoding="utf-8") + transformed = transform_all(content) + + if content == transformed: + return False + + if dry_run: + print(f"[WOULD CHANGE] {filepath}") + # Show a unified-diff-like summary + orig_lines = content.splitlines() + new_lines = transformed.splitlines() + changes = 0 + for i, (old, new) in enumerate(zip(orig_lines, new_lines)): + if old != new: + changes += 1 + if changes <= 10: + print(f" L{i+1}:") + print(f" - {old.strip()}") + print(f" + {new.strip()}") + if changes > 10: + print(f" ... and {changes - 10} more changes") + print() + else: + filepath.write_text(transformed, encoding="utf-8") + print(f"[UPDATED] {filepath}") + + return True + + +def main(): + parser = argparse.ArgumentParser( + description="Transform Nextra MDX components to Mintlify equivalents." + ) + parser.add_argument( + "path", + nargs="?", + help="File or directory to transform", + ) + parser.add_argument( + "--dry-run", + action="store_true", + help="Show what would change without writing files", + ) + parser.add_argument( + "--stdin", + action="store_true", + help="Read from stdin, write to stdout", + ) + + args = parser.parse_args() + + if args.stdin: + content = sys.stdin.read() + sys.stdout.write(transform_all(content)) + return + + if not args.path: + parser.error("Either --stdin or a path is required") + + target = Path(args.path) + + if target.is_file(): + changed = process_file(target, dry_run=args.dry_run) + if not changed: + print(f"[NO CHANGES] {target}") + elif target.is_dir(): + changed_count = 0 + total_count = 0 + for mdx_file in sorted(target.rglob("*.mdx")): + total_count += 1 + if process_file(mdx_file, dry_run=args.dry_run): + changed_count += 1 + print(f"\nProcessed {total_count} files, {changed_count} changed.") + else: + print(f"Error: {target} not found", file=sys.stderr) + sys.exit(1) + + +if __name__ == "__main__": + main() diff --git a/docs-mintlify/scripts/update_frontmatter.py b/docs-mintlify/scripts/update_frontmatter.py new file mode 100755 index 0000000000000..e814ef7e3b045 --- /dev/null +++ b/docs-mintlify/scripts/update_frontmatter.py @@ -0,0 +1,225 @@ +#!/usr/bin/env python3 +""" +Update MDX frontmatter for Mintlify compatibility. + +Transforms: + - Removes `asIndexPage: true` (not needed in Mintlify) + - Converts `toc: false` to `hideTableOfContents: true` + - Adds `title` from the first H1 heading if not present + - Adds `description` from first paragraph if not present + - Removes `redirectFrom` (handled by mint.json redirects) + +Usage: + python update_frontmatter.py path/to/file.mdx + python update_frontmatter.py path/to/docs/ + python update_frontmatter.py --dry-run path/to/docs/ + cat file.mdx | python update_frontmatter.py --stdin +""" + +import argparse +import re +import sys +from pathlib import Path + + +def extract_h1(content_body: str) -> str: + """Extract the first H1 heading from MDX content.""" + match = re.search(r"^#\s+(.+)$", content_body, re.MULTILINE) + return match.group(1).strip() if match else "" + + +def extract_first_paragraph(content_body: str) -> str: + """Extract the first non-empty paragraph after the H1.""" + # Skip the H1 line, find the next non-empty text block + lines = content_body.split("\n") + in_paragraph = False + paragraph_lines = [] + + for line in lines: + stripped = line.strip() + # Skip headings, empty lines before paragraph, and components + if stripped.startswith("#") or stripped.startswith("<"): + if in_paragraph: + break + continue + if not stripped: + if in_paragraph: + break + continue + + in_paragraph = True + paragraph_lines.append(stripped) + + paragraph = " ".join(paragraph_lines) + + # Truncate to ~160 chars for SEO + if len(paragraph) > 160: + paragraph = paragraph[:157].rsplit(" ", 1)[0] + "..." + + # Remove markdown links but keep text + paragraph = re.sub(r"\[([^\]]+)\]\([^)]+\)", r"\1", paragraph) + # Remove inline code backticks + paragraph = paragraph.replace("`", "") + # Remove bold/italic + paragraph = re.sub(r"\*+([^*]+)\*+", r"\1", paragraph) + + return paragraph + + +def parse_frontmatter(content: str): + """ + Parse YAML frontmatter from MDX content. + + Returns (frontmatter_dict, frontmatter_raw, body). + If no frontmatter, returns (None, "", content). + """ + if not content.startswith("---"): + return None, "", content + + end_match = re.search(r"\n---\s*\n", content[3:]) + if not end_match: + return None, "", content + + fm_end = end_match.start() + 3 # offset from content[3:] + fm_raw = content[3:fm_end + 3].strip() + body = content[fm_end + 3 + 4:] # skip past closing ---\n + + # Simple YAML parsing (key: value pairs) + fm_dict = {} + for line in fm_raw.split("\n"): + line = line.strip() + if ":" in line: + key, _, value = line.partition(":") + fm_dict[key.strip()] = value.strip() + + return fm_dict, fm_raw, body + + +def build_frontmatter(fm_dict: dict) -> str: + """Build YAML frontmatter string from dict.""" + lines = ["---"] + for key, value in fm_dict.items(): + # Quote string values that contain special chars + if isinstance(value, str) and value and value != "true" and value != "false": + # Already quoted + if value.startswith('"') and value.endswith('"'): + lines.append(f"{key}: {value}") + elif value.startswith("'") and value.endswith("'"): + lines.append(f"{key}: {value}") + # Needs quoting if contains special YAML chars + elif any(c in value for c in ":#{}[]|>&*!%@`"): + escaped = value.replace('"', '\\"') + lines.append(f'{key}: "{escaped}"') + else: + lines.append(f"{key}: {value}") + else: + lines.append(f"{key}: {value}") + lines.append("---") + return "\n".join(lines) + + +def update_frontmatter(content: str) -> str: + """Update frontmatter for Mintlify compatibility.""" + fm_dict, fm_raw, body = parse_frontmatter(content) + + if fm_dict is None: + fm_dict = {} + + # Remove Nextra-specific fields + fm_dict.pop("asIndexPage", None) + fm_dict.pop("redirectFrom", None) + + # Convert toc: false -> hideTableOfContents: true + if fm_dict.get("toc") == "false": + fm_dict.pop("toc") + fm_dict["hideTableOfContents"] = "true" + + # Add title from H1 if missing + if "title" not in fm_dict: + h1 = extract_h1(body) + if h1: + fm_dict["title"] = h1 + + # Add description if missing + if "description" not in fm_dict: + desc = extract_first_paragraph(body) + if desc: + fm_dict["description"] = desc + + # Reorder: title first, then description, then rest + ordered = {} + if "title" in fm_dict: + ordered["title"] = fm_dict.pop("title") + if "description" in fm_dict: + ordered["description"] = fm_dict.pop("description") + if "sidebarTitle" in fm_dict: + ordered["sidebarTitle"] = fm_dict.pop("sidebarTitle") + ordered.update(fm_dict) + + new_fm = build_frontmatter(ordered) + return new_fm + "\n\n" + body.lstrip("\n") + + +def process_file(filepath: Path, dry_run: bool = False) -> bool: + """Process a single file. Returns True if changes were made.""" + content = filepath.read_text(encoding="utf-8") + transformed = update_frontmatter(content) + + if content == transformed: + return False + + if dry_run: + # Show the new frontmatter + fm_end = transformed.index("\n---\n", 4) + new_fm = transformed[:fm_end + 4] + print(f"[WOULD CHANGE] {filepath}") + print(f" New frontmatter:") + for line in new_fm.splitlines(): + print(f" {line}") + print() + else: + filepath.write_text(transformed, encoding="utf-8") + print(f"[UPDATED] {filepath}") + + return True + + +def main(): + parser = argparse.ArgumentParser( + description="Update MDX frontmatter for Mintlify compatibility." + ) + parser.add_argument("path", nargs="?", help="File or directory to process") + parser.add_argument("--dry-run", action="store_true", help="Show changes without writing") + parser.add_argument("--stdin", action="store_true", help="Read from stdin, write to stdout") + + args = parser.parse_args() + + if args.stdin: + content = sys.stdin.read() + sys.stdout.write(update_frontmatter(content)) + return + + if not args.path: + parser.error("Either --stdin or a path is required") + + target = Path(args.path) + + if target.is_file(): + changed = process_file(target, dry_run=args.dry_run) + if not changed: + print(f"[NO CHANGES] {target}") + elif target.is_dir(): + changed_count = 0 + total_count = 0 + for mdx_file in sorted(target.rglob("*.mdx")): + total_count += 1 + if process_file(mdx_file, dry_run=args.dry_run): + changed_count += 1 + print(f"\nProcessed {total_count} files, {changed_count} changed.") + else: + print(f"Error: {target} not found", file=sys.stderr) + sys.exit(1) + + +if __name__ == "__main__": + main() diff --git a/docs-mintlify/scripts/upload-asset.sh b/docs-mintlify/scripts/upload-asset.sh new file mode 100755 index 0000000000000..19e319df7e239 --- /dev/null +++ b/docs-mintlify/scripts/upload-asset.sh @@ -0,0 +1,116 @@ +#!/usr/bin/env bash +# Upload a static asset to the cube-dev-websites-shared S3 bucket and print +# the resulting https://static.cube.dev/ URL. +# +# Usage: +# ./scripts/upload-asset.sh [--force] +# +# Examples: +# ./scripts/upload-asset.sh ./snowflake.svg icons/snowflake.svg +# ./scripts/upload-asset.sh ./architecture.png docs/getting-started/architecture.png +# ./scripts/upload-asset.sh ./diagram.svg diagrams/pre-aggregations-flow.svg +# +# Conventions (see scripts/README.md): +# icons/.{svg,png} — provider / integration logos +# docs/
// — screenshots & images per page +# diagrams/.{svg,png} — architecture / flow diagrams +# recipes// — recipe-specific assets +# +# Paths are meant to be IMMUTABLE. If you need to change an image, upload a +# new key (e.g. logo-v2.svg) and update the Markdown reference. + +set -euo pipefail + +BUCKET="cube-dev-websites-shared" +REGION="us-west-2" +PUBLIC_BASE="https://static.cube.dev" +PROFILE="${AWS_PROFILE:-cube-static}" + +usage() { + sed -n '2,20p' "$0" | sed 's/^# \{0,1\}//' + exit 1 +} + +if [[ $# -lt 2 ]]; then + usage +fi + +SRC="$1" +KEY="$2" +FORCE="${3:-}" + +if [[ ! -f "$SRC" ]]; then + echo "error: source file not found: $SRC" >&2 + exit 1 +fi + +if [[ "$KEY" == /* || "$KEY" == *..* ]]; then + echo "error: dest key must be a relative path without '..': $KEY" >&2 + exit 1 +fi + +if ! command -v aws >/dev/null 2>&1; then + echo "error: aws CLI is not installed. Run: brew install awscli" >&2 + exit 1 +fi + +guess_content_type() { + local f + f="$(printf '%s' "$1" | tr '[:upper:]' '[:lower:]')" + case "$f" in + *.svg) echo "image/svg+xml" ;; + *.png) echo "image/png" ;; + *.jpg|*.jpeg) echo "image/jpeg" ;; + *.gif) echo "image/gif" ;; + *.webp) echo "image/webp" ;; + *.avif) echo "image/avif" ;; + *.ico) echo "image/x-icon" ;; + *.mp4) echo "video/mp4" ;; + *.webm) echo "video/webm" ;; + *.pdf) echo "application/pdf" ;; + *.json) echo "application/json" ;; + *.txt|*.md) echo "text/plain; charset=utf-8" ;; + *) file --mime-type -b "$1" 2>/dev/null || echo "application/octet-stream" ;; + esac +} + +CONTENT_TYPE="$(guess_content_type "$SRC")" +CACHE_CONTROL="public, max-age=31536000, immutable" + +echo "→ bucket: s3://${BUCKET}/${KEY}" +echo "→ region: ${REGION}" +echo "→ profile: ${PROFILE}" +echo "→ content-type: ${CONTENT_TYPE}" +echo "→ cache: ${CACHE_CONTROL}" +echo + +# Refuse to overwrite unless --force is passed. +if [[ "$FORCE" != "--force" ]]; then + if aws s3api head-object \ + --bucket "$BUCKET" \ + --key "$KEY" \ + --region "$REGION" \ + --profile "$PROFILE" >/dev/null 2>&1; then + echo "error: key already exists in bucket: ${KEY}" >&2 + echo " Our convention is immutable paths. Pick a new key (e.g. add -v2)," >&2 + echo " or pass --force if you really mean to overwrite." >&2 + exit 1 + fi +fi + +aws s3 cp "$SRC" "s3://${BUCKET}/${KEY}" \ + --region "$REGION" \ + --profile "$PROFILE" \ + --content-type "$CONTENT_TYPE" \ + --cache-control "$CACHE_CONTROL" + +URL="${PUBLIC_BASE}/${KEY}" +echo +echo "✓ uploaded" +echo " ${URL}" + +# Copy URL to clipboard on macOS. +if command -v pbcopy >/dev/null 2>&1; then + printf '%s' "$URL" | pbcopy + echo " (copied to clipboard)" +fi diff --git a/docs-mintlify/style.css b/docs-mintlify/style.css new file mode 100644 index 0000000000000..df403aca7300c --- /dev/null +++ b/docs-mintlify/style.css @@ -0,0 +1,4 @@ +#content-area table, +.mdx-content table { + width: 100% !important; +} diff --git a/docs-mintlify/yarn.lock b/docs-mintlify/yarn.lock new file mode 100644 index 0000000000000..f98ad0c82d673 --- /dev/null +++ b/docs-mintlify/yarn.lock @@ -0,0 +1,7197 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@alcalzone/ansi-tokenize@^0.2.0": + version "0.2.5" + resolved "https://registry.yarnpkg.com/@alcalzone/ansi-tokenize/-/ansi-tokenize-0.2.5.tgz#046ef25e46c8d1f0a4b190cb0d64343093a0eebd" + integrity sha512-3NX/MpTdroi0aKz134A6RC2Gb2iXVECN4QaAXnvCIxxIm3C3AVB1mkUe8NaaiyvOpDfsrqWhYtj+Q6a62RrTsw== + dependencies: + ansi-styles "^6.2.1" + is-fullwidth-code-point "^5.0.0" + +"@alloc/quick-lru@^5.2.0": + version "5.2.0" + resolved "https://registry.yarnpkg.com/@alloc/quick-lru/-/quick-lru-5.2.0.tgz#7bf68b20c0a350f936915fcae06f58e32007ce30" + integrity sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw== + +"@ark/schema@0.55.0": + version "0.55.0" + resolved "https://registry.yarnpkg.com/@ark/schema/-/schema-0.55.0.tgz#017abe2afe1a959086abcf5aae05acee5f14b3b2" + integrity sha512-IlSIc0FmLKTDGr4I/FzNHauMn0MADA6bCjT1wauu4k6MyxhC1R9gz0olNpIRvK7lGGDwtc/VO0RUDNvVQW5WFg== + dependencies: + "@ark/util" "0.55.0" + +"@ark/schema@0.56.0": + version "0.56.0" + resolved "https://registry.yarnpkg.com/@ark/schema/-/schema-0.56.0.tgz#62126c285e372fa7f0be5c7419dd24728b090ab2" + integrity sha512-ECg3hox/6Z/nLajxXqNhgPtNdHWC9zNsDyskwO28WinoFEnWow4IsERNz9AnXRhTZJnYIlAJ4uGn3nlLk65vZA== + dependencies: + "@ark/util" "0.56.0" + +"@ark/util@0.55.0": + version "0.55.0" + resolved "https://registry.yarnpkg.com/@ark/util/-/util-0.55.0.tgz#b991da6998ba942e4cb81db2772ad23ea3586bde" + integrity sha512-aWFNK7aqSvqFtVsl1xmbTjGbg91uqtJV7Za76YGNEwIO4qLjMfyY8flmmbhooYMuqPCO2jyxu8hve943D+w3bA== + +"@ark/util@0.56.0": + version "0.56.0" + resolved "https://registry.yarnpkg.com/@ark/util/-/util-0.56.0.tgz#d110f1c55ea934f0fba930deada16254791d7fe3" + integrity sha512-BghfRC8b9pNs3vBoDJhcta0/c1J1rsoS1+HgVUreMFPdhz/CRAKReAu57YEllNaSy98rWAdY1gE+gFup7OXpgA== + +"@asyncapi/parser@3.4.0": + version "3.4.0" + resolved "https://registry.yarnpkg.com/@asyncapi/parser/-/parser-3.4.0.tgz#b5a5aca565125579eb76c092c21ef357bcedd805" + integrity sha512-Sxn74oHiZSU6+cVeZy62iPZMFMvKp4jupMFHelSICCMw1qELmUHPvuZSr+ZHDmNGgHcEpzJM5HN02kR7T4g+PQ== + dependencies: + "@asyncapi/specs" "^6.8.0" + "@openapi-contrib/openapi-schema-to-json-schema" "~3.2.0" + "@stoplight/json" "3.21.0" + "@stoplight/json-ref-readers" "^1.2.2" + "@stoplight/json-ref-resolver" "^3.1.5" + "@stoplight/spectral-core" "^1.18.3" + "@stoplight/spectral-functions" "^1.7.2" + "@stoplight/spectral-parsers" "^1.0.2" + "@stoplight/spectral-ref-resolver" "^1.0.3" + "@stoplight/types" "^13.12.0" + "@types/json-schema" "^7.0.11" + "@types/urijs" "^1.19.19" + ajv "^8.17.1" + ajv-errors "^3.0.0" + ajv-formats "^2.1.1" + avsc "^5.7.5" + js-yaml "^4.1.0" + jsonpath-plus "^10.0.0" + node-fetch "2.6.7" + +"@asyncapi/specs@6.8.1": + version "6.8.1" + resolved "https://registry.yarnpkg.com/@asyncapi/specs/-/specs-6.8.1.tgz#ba7dcd73f0260a6d4041cc854a491e70ff594cd1" + integrity sha512-czHoAk3PeXTLR+X8IUaD+IpT+g+zUvkcgMDJVothBsan+oHN3jfcFcFUNdOPAAFoUCQN1hXF1dWuphWy05THlA== + dependencies: + "@types/json-schema" "^7.0.11" + +"@asyncapi/specs@^6.8.0": + version "6.11.1" + resolved "https://registry.yarnpkg.com/@asyncapi/specs/-/specs-6.11.1.tgz#c629fe962a241a983f883a56b0e9c901a311becb" + integrity sha512-A3WBLqAKGoJ2+6FWFtpjBlCQ1oFCcs4GxF7zsIGvNqp/klGUHjlA3aAcZ9XMMpLGE8zPeYDz2x9FmO6DSuKraQ== + dependencies: + "@types/json-schema" "^7.0.11" + +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.29.0": + version "7.29.0" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.29.0.tgz#7cd7a59f15b3cc0dcd803038f7792712a7d0b15c" + integrity sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw== + dependencies: + "@babel/helper-validator-identifier" "^7.28.5" + js-tokens "^4.0.0" + picocolors "^1.1.1" + +"@babel/helper-validator-identifier@^7.28.5": + version "7.28.5" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz#010b6938fab7cb7df74aa2bbc06aa503b8fe5fb4" + integrity sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q== + +"@canvas/image-data@^1.0.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@canvas/image-data/-/image-data-1.1.0.tgz#ead4e594515f144cc372892cacb4b24ec6d43629" + integrity sha512-QdObRRjRbcXGmM1tmJ+MrHcaz1MftF2+W7YI+MsphnsCrmtyfS0d5qJbk0MeSbUeyM/jCb0hmnkXPsy026L7dA== + +"@emnapi/runtime@^1.2.0", "@emnapi/runtime@^1.7.0": + version "1.10.0" + resolved "https://registry.yarnpkg.com/@emnapi/runtime/-/runtime-1.10.0.tgz#4b260c0d3534204e98c6110b8db1a987d26ec87c" + integrity sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA== + dependencies: + tslib "^2.4.0" + +"@img/colour@^1.0.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@img/colour/-/colour-1.1.0.tgz#b0c2c2fa661adf75effd6b4964497cd80010bb9d" + integrity sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ== + +"@img/sharp-darwin-arm64@0.33.5": + version "0.33.5" + resolved "https://registry.yarnpkg.com/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.33.5.tgz#ef5b5a07862805f1e8145a377c8ba6e98813ca08" + integrity sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ== + optionalDependencies: + "@img/sharp-libvips-darwin-arm64" "1.0.4" + +"@img/sharp-darwin-arm64@0.34.5": + version "0.34.5" + resolved "https://registry.yarnpkg.com/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.5.tgz#6e0732dcade126b6670af7aa17060b926835ea86" + integrity sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w== + optionalDependencies: + "@img/sharp-libvips-darwin-arm64" "1.2.4" + +"@img/sharp-darwin-x64@0.33.5": + version "0.33.5" + resolved "https://registry.yarnpkg.com/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.33.5.tgz#e03d3451cd9e664faa72948cc70a403ea4063d61" + integrity sha512-fyHac4jIc1ANYGRDxtiqelIbdWkIuQaI84Mv45KvGRRxSAa7o7d1ZKAOBaYbnepLC1WqxfpimdeWfvqqSGwR2Q== + optionalDependencies: + "@img/sharp-libvips-darwin-x64" "1.0.4" + +"@img/sharp-darwin-x64@0.34.5": + version "0.34.5" + resolved "https://registry.yarnpkg.com/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.5.tgz#19bc1dd6eba6d5a96283498b9c9f401180ee9c7b" + integrity sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw== + optionalDependencies: + "@img/sharp-libvips-darwin-x64" "1.2.4" + +"@img/sharp-libvips-darwin-arm64@1.0.4": + version "1.0.4" + resolved "https://registry.yarnpkg.com/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.0.4.tgz#447c5026700c01a993c7804eb8af5f6e9868c07f" + integrity sha512-XblONe153h0O2zuFfTAbQYAX2JhYmDHeWikp1LM9Hul9gVPjFY427k6dFEcOL72O01QxQsWi761svJ/ev9xEDg== + +"@img/sharp-libvips-darwin-arm64@1.2.4": + version "1.2.4" + resolved "https://registry.yarnpkg.com/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.2.4.tgz#2894c0cb87d42276c3889942e8e2db517a492c43" + integrity sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g== + +"@img/sharp-libvips-darwin-x64@1.0.4": + version "1.0.4" + resolved "https://registry.yarnpkg.com/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.0.4.tgz#e0456f8f7c623f9dbfbdc77383caa72281d86062" + integrity sha512-xnGR8YuZYfJGmWPvmlunFaWJsb9T/AO2ykoP3Fz/0X5XV2aoYBPkX6xqCQvUTKKiLddarLaxpzNe+b1hjeWHAQ== + +"@img/sharp-libvips-darwin-x64@1.2.4": + version "1.2.4" + resolved "https://registry.yarnpkg.com/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.2.4.tgz#e63681f4539a94af9cd17246ed8881734386f8cc" + integrity sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg== + +"@img/sharp-libvips-linux-arm64@1.0.4": + version "1.0.4" + resolved "https://registry.yarnpkg.com/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.0.4.tgz#979b1c66c9a91f7ff2893556ef267f90ebe51704" + integrity sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA== + +"@img/sharp-libvips-linux-arm64@1.2.4": + version "1.2.4" + resolved "https://registry.yarnpkg.com/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.2.4.tgz#b1b288b36864b3bce545ad91fa6dadcf1a4ad318" + integrity sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw== + +"@img/sharp-libvips-linux-arm@1.0.5": + version "1.0.5" + resolved "https://registry.yarnpkg.com/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.0.5.tgz#99f922d4e15216ec205dcb6891b721bfd2884197" + integrity sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g== + +"@img/sharp-libvips-linux-arm@1.2.4": + version "1.2.4" + resolved "https://registry.yarnpkg.com/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.2.4.tgz#b9260dd1ebe6f9e3bdbcbdcac9d2ac125f35852d" + integrity sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A== + +"@img/sharp-libvips-linux-ppc64@1.2.4": + version "1.2.4" + resolved "https://registry.yarnpkg.com/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.2.4.tgz#4b83ecf2a829057222b38848c7b022e7b4d07aa7" + integrity sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA== + +"@img/sharp-libvips-linux-riscv64@1.2.4": + version "1.2.4" + resolved "https://registry.yarnpkg.com/@img/sharp-libvips-linux-riscv64/-/sharp-libvips-linux-riscv64-1.2.4.tgz#880b4678009e5a2080af192332b00b0aaf8a48de" + integrity sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA== + +"@img/sharp-libvips-linux-s390x@1.0.4": + version "1.0.4" + resolved "https://registry.yarnpkg.com/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.0.4.tgz#f8a5eb1f374a082f72b3f45e2fb25b8118a8a5ce" + integrity sha512-u7Wz6ntiSSgGSGcjZ55im6uvTrOxSIS8/dgoVMoiGE9I6JAfU50yH5BoDlYA1tcuGS7g/QNtetJnxA6QEsCVTA== + +"@img/sharp-libvips-linux-s390x@1.2.4": + version "1.2.4" + resolved "https://registry.yarnpkg.com/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.2.4.tgz#74f343c8e10fad821b38f75ced30488939dc59ec" + integrity sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ== + +"@img/sharp-libvips-linux-x64@1.0.4": + version "1.0.4" + resolved "https://registry.yarnpkg.com/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.0.4.tgz#d4c4619cdd157774906e15770ee119931c7ef5e0" + integrity sha512-MmWmQ3iPFZr0Iev+BAgVMb3ZyC4KeFc3jFxnNbEPas60e1cIfevbtuyf9nDGIzOaW9PdnDciJm+wFFaTlj5xYw== + +"@img/sharp-libvips-linux-x64@1.2.4": + version "1.2.4" + resolved "https://registry.yarnpkg.com/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.2.4.tgz#df4183e8bd8410f7d61b66859a35edeab0a531ce" + integrity sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw== + +"@img/sharp-libvips-linuxmusl-arm64@1.0.4": + version "1.0.4" + resolved "https://registry.yarnpkg.com/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.0.4.tgz#166778da0f48dd2bded1fa3033cee6b588f0d5d5" + integrity sha512-9Ti+BbTYDcsbp4wfYib8Ctm1ilkugkA/uscUn6UXK1ldpC1JjiXbLfFZtRlBhjPZ5o1NCLiDbg8fhUPKStHoTA== + +"@img/sharp-libvips-linuxmusl-arm64@1.2.4": + version "1.2.4" + resolved "https://registry.yarnpkg.com/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.2.4.tgz#c8d6b48211df67137541007ee8d1b7b1f8ca8e06" + integrity sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw== + +"@img/sharp-libvips-linuxmusl-x64@1.0.4": + version "1.0.4" + resolved "https://registry.yarnpkg.com/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.0.4.tgz#93794e4d7720b077fcad3e02982f2f1c246751ff" + integrity sha512-viYN1KX9m+/hGkJtvYYp+CCLgnJXwiQB39damAO7WMdKWlIhmYTfHjwSbQeUK/20vY154mwezd9HflVFM1wVSw== + +"@img/sharp-libvips-linuxmusl-x64@1.2.4": + version "1.2.4" + resolved "https://registry.yarnpkg.com/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.2.4.tgz#be11c75bee5b080cbee31a153a8779448f919f75" + integrity sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg== + +"@img/sharp-linux-arm64@0.33.5": + version "0.33.5" + resolved "https://registry.yarnpkg.com/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.33.5.tgz#edb0697e7a8279c9fc829a60fc35644c4839bb22" + integrity sha512-JMVv+AMRyGOHtO1RFBiJy/MBsgz0x4AWrT6QoEVVTyh1E39TrCUpTRI7mx9VksGX4awWASxqCYLCV4wBZHAYxA== + optionalDependencies: + "@img/sharp-libvips-linux-arm64" "1.0.4" + +"@img/sharp-linux-arm64@0.34.5": + version "0.34.5" + resolved "https://registry.yarnpkg.com/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.5.tgz#7aa7764ef9c001f15e610546d42fce56911790cc" + integrity sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg== + optionalDependencies: + "@img/sharp-libvips-linux-arm64" "1.2.4" + +"@img/sharp-linux-arm@0.33.5": + version "0.33.5" + resolved "https://registry.yarnpkg.com/@img/sharp-linux-arm/-/sharp-linux-arm-0.33.5.tgz#422c1a352e7b5832842577dc51602bcd5b6f5eff" + integrity sha512-JTS1eldqZbJxjvKaAkxhZmBqPRGmxgu+qFKSInv8moZ2AmT5Yib3EQ1c6gp493HvrvV8QgdOXdyaIBrhvFhBMQ== + optionalDependencies: + "@img/sharp-libvips-linux-arm" "1.0.5" + +"@img/sharp-linux-arm@0.34.5": + version "0.34.5" + resolved "https://registry.yarnpkg.com/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.5.tgz#5fb0c3695dd12522d39c3ff7a6bc816461780a0d" + integrity sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw== + optionalDependencies: + "@img/sharp-libvips-linux-arm" "1.2.4" + +"@img/sharp-linux-ppc64@0.34.5": + version "0.34.5" + resolved "https://registry.yarnpkg.com/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.34.5.tgz#9c213a81520a20caf66978f3d4c07456ff2e0813" + integrity sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA== + optionalDependencies: + "@img/sharp-libvips-linux-ppc64" "1.2.4" + +"@img/sharp-linux-riscv64@0.34.5": + version "0.34.5" + resolved "https://registry.yarnpkg.com/@img/sharp-linux-riscv64/-/sharp-linux-riscv64-0.34.5.tgz#cdd28182774eadbe04f62675a16aabbccb833f60" + integrity sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw== + optionalDependencies: + "@img/sharp-libvips-linux-riscv64" "1.2.4" + +"@img/sharp-linux-s390x@0.33.5": + version "0.33.5" + resolved "https://registry.yarnpkg.com/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.33.5.tgz#f5c077926b48e97e4a04d004dfaf175972059667" + integrity sha512-y/5PCd+mP4CA/sPDKl2961b+C9d+vPAveS33s6Z3zfASk2j5upL6fXVPZi7ztePZ5CuH+1kW8JtvxgbuXHRa4Q== + optionalDependencies: + "@img/sharp-libvips-linux-s390x" "1.0.4" + +"@img/sharp-linux-s390x@0.34.5": + version "0.34.5" + resolved "https://registry.yarnpkg.com/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.5.tgz#93eac601b9f329bb27917e0e19098c722d630df7" + integrity sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg== + optionalDependencies: + "@img/sharp-libvips-linux-s390x" "1.2.4" + +"@img/sharp-linux-x64@0.33.5": + version "0.33.5" + resolved "https://registry.yarnpkg.com/@img/sharp-linux-x64/-/sharp-linux-x64-0.33.5.tgz#d806e0afd71ae6775cc87f0da8f2d03a7c2209cb" + integrity sha512-opC+Ok5pRNAzuvq1AG0ar+1owsu842/Ab+4qvU879ippJBHvyY5n2mxF1izXqkPYlGuP/M556uh53jRLJmzTWA== + optionalDependencies: + "@img/sharp-libvips-linux-x64" "1.0.4" + +"@img/sharp-linux-x64@0.34.5": + version "0.34.5" + resolved "https://registry.yarnpkg.com/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.5.tgz#55abc7cd754ffca5002b6c2b719abdfc846819a8" + integrity sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ== + optionalDependencies: + "@img/sharp-libvips-linux-x64" "1.2.4" + +"@img/sharp-linuxmusl-arm64@0.33.5": + version "0.33.5" + resolved "https://registry.yarnpkg.com/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.33.5.tgz#252975b915894fb315af5deea174651e208d3d6b" + integrity sha512-XrHMZwGQGvJg2V/oRSUfSAfjfPxO+4DkiRh6p2AFjLQztWUuY/o8Mq0eMQVIY7HJ1CDQUJlxGGZRw1a5bqmd1g== + optionalDependencies: + "@img/sharp-libvips-linuxmusl-arm64" "1.0.4" + +"@img/sharp-linuxmusl-arm64@0.34.5": + version "0.34.5" + resolved "https://registry.yarnpkg.com/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.5.tgz#d6515ee971bb62f73001a4829b9d865a11b77086" + integrity sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg== + optionalDependencies: + "@img/sharp-libvips-linuxmusl-arm64" "1.2.4" + +"@img/sharp-linuxmusl-x64@0.33.5": + version "0.33.5" + resolved "https://registry.yarnpkg.com/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.33.5.tgz#3f4609ac5d8ef8ec7dadee80b560961a60fd4f48" + integrity sha512-WT+d/cgqKkkKySYmqoZ8y3pxx7lx9vVejxW/W4DOFMYVSkErR+w7mf2u8m/y4+xHe7yY9DAXQMWQhpnMuFfScw== + optionalDependencies: + "@img/sharp-libvips-linuxmusl-x64" "1.0.4" + +"@img/sharp-linuxmusl-x64@0.34.5": + version "0.34.5" + resolved "https://registry.yarnpkg.com/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.5.tgz#d97978aec7c5212f999714f2f5b736457e12ee9f" + integrity sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q== + optionalDependencies: + "@img/sharp-libvips-linuxmusl-x64" "1.2.4" + +"@img/sharp-wasm32@0.33.5": + version "0.33.5" + resolved "https://registry.yarnpkg.com/@img/sharp-wasm32/-/sharp-wasm32-0.33.5.tgz#6f44f3283069d935bb5ca5813153572f3e6f61a1" + integrity sha512-ykUW4LVGaMcU9lu9thv85CbRMAwfeadCJHRsg2GmeRa/cJxsVY9Rbd57JcMxBkKHag5U/x7TSBpScF4U8ElVzg== + dependencies: + "@emnapi/runtime" "^1.2.0" + +"@img/sharp-wasm32@0.34.5": + version "0.34.5" + resolved "https://registry.yarnpkg.com/@img/sharp-wasm32/-/sharp-wasm32-0.34.5.tgz#2f15803aa626f8c59dd7c9d0bbc766f1ab52cfa0" + integrity sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw== + dependencies: + "@emnapi/runtime" "^1.7.0" + +"@img/sharp-win32-arm64@0.34.5": + version "0.34.5" + resolved "https://registry.yarnpkg.com/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.34.5.tgz#3706e9e3ac35fddfc1c87f94e849f1b75307ce0a" + integrity sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g== + +"@img/sharp-win32-ia32@0.33.5": + version "0.33.5" + resolved "https://registry.yarnpkg.com/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.33.5.tgz#1a0c839a40c5351e9885628c85f2e5dfd02b52a9" + integrity sha512-T36PblLaTwuVJ/zw/LaH0PdZkRz5rd3SmMHX8GSmR7vtNSP5Z6bQkExdSK7xGWyxLw4sUknBuugTelgw2faBbQ== + +"@img/sharp-win32-ia32@0.34.5": + version "0.34.5" + resolved "https://registry.yarnpkg.com/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.5.tgz#0b71166599b049e032f085fb9263e02f4e4788de" + integrity sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg== + +"@img/sharp-win32-x64@0.33.5": + version "0.33.5" + resolved "https://registry.yarnpkg.com/@img/sharp-win32-x64/-/sharp-win32-x64-0.33.5.tgz#56f00962ff0c4e0eb93d34a047d29fa995e3e342" + integrity sha512-MpY/o8/8kj+EcnxwvrP4aTJSWw/aZ7JIGR4aBeZkZw5B7/Jn+tY9/VNwtcoGmdT7GfggGIU4kygOMSbYnOrAbg== + +"@img/sharp-win32-x64@0.34.5": + version "0.34.5" + resolved "https://registry.yarnpkg.com/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.5.tgz#a81ffb00e69267cd0a1d626eaedb8a8430b2b2f8" + integrity sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw== + +"@inquirer/ansi@^1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@inquirer/ansi/-/ansi-1.0.2.tgz#674a4c4d81ad460695cb2a1fc69d78cd187f337e" + integrity sha512-S8qNSZiYzFd0wAcyG5AXCvUHC5Sr7xpZ9wZ2py9XR88jUz8wooStVx5M6dRzczbBWjic9NP7+rY0Xi7qqK/aMQ== + +"@inquirer/checkbox@^4.3.0", "@inquirer/checkbox@^4.3.2": + version "4.3.2" + resolved "https://registry.yarnpkg.com/@inquirer/checkbox/-/checkbox-4.3.2.tgz#e1483e6519d6ffef97281a54d2a5baa0d81b3f3b" + integrity sha512-VXukHf0RR1doGe6Sm4F0Em7SWYLTHSsbGfJdS9Ja2bX5/D5uwVOEjr07cncLROdBvmnvCATYEWlHqYmXv2IlQA== + dependencies: + "@inquirer/ansi" "^1.0.2" + "@inquirer/core" "^10.3.2" + "@inquirer/figures" "^1.0.15" + "@inquirer/type" "^3.0.10" + yoctocolors-cjs "^2.1.3" + +"@inquirer/confirm@^5.1.19", "@inquirer/confirm@^5.1.21": + version "5.1.21" + resolved "https://registry.yarnpkg.com/@inquirer/confirm/-/confirm-5.1.21.tgz#610c4acd7797d94890a6e2dde2c98eb1e891dd12" + integrity sha512-KR8edRkIsUayMXV+o3Gv+q4jlhENF9nMYUZs9PA2HzrXeHI8M5uDag70U7RJn9yyiMZSbtF5/UexBtAVtZGSbQ== + dependencies: + "@inquirer/core" "^10.3.2" + "@inquirer/type" "^3.0.10" + +"@inquirer/core@^10.1.2", "@inquirer/core@^10.3.2": + version "10.3.2" + resolved "https://registry.yarnpkg.com/@inquirer/core/-/core-10.3.2.tgz#535979ff3ff4fe1e7cc4f83e2320504c743b7e20" + integrity sha512-43RTuEbfP8MbKzedNqBrlhhNKVwoK//vUFNW3Q3vZ88BLcrs4kYpGg+B2mm5p2K/HfygoCxuKwJJiv8PbGmE0A== + dependencies: + "@inquirer/ansi" "^1.0.2" + "@inquirer/figures" "^1.0.15" + "@inquirer/type" "^3.0.10" + cli-width "^4.1.0" + mute-stream "^2.0.0" + signal-exit "^4.1.0" + wrap-ansi "^6.2.0" + yoctocolors-cjs "^2.1.3" + +"@inquirer/editor@^4.2.21", "@inquirer/editor@^4.2.23": + version "4.2.23" + resolved "https://registry.yarnpkg.com/@inquirer/editor/-/editor-4.2.23.tgz#fe046a3bfdae931262de98c1052437d794322e0b" + integrity sha512-aLSROkEwirotxZ1pBaP8tugXRFCxW94gwrQLxXfrZsKkfjOYC1aRvAZuhpJOb5cu4IBTJdsCigUlf2iCOu4ZDQ== + dependencies: + "@inquirer/core" "^10.3.2" + "@inquirer/external-editor" "^1.0.3" + "@inquirer/type" "^3.0.10" + +"@inquirer/expand@^4.0.21", "@inquirer/expand@^4.0.23": + version "4.0.23" + resolved "https://registry.yarnpkg.com/@inquirer/expand/-/expand-4.0.23.tgz#a38b5f32226d75717c370bdfed792313b92bdc05" + integrity sha512-nRzdOyFYnpeYTTR2qFwEVmIWypzdAx/sIkCMeTNTcflFOovfqUk+HcFhQQVBftAh9gmGrpFj6QcGEqrDMDOiew== + dependencies: + "@inquirer/core" "^10.3.2" + "@inquirer/type" "^3.0.10" + yoctocolors-cjs "^2.1.3" + +"@inquirer/external-editor@^1.0.3": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@inquirer/external-editor/-/external-editor-1.0.3.tgz#c23988291ee676290fdab3fd306e64010a6d13b8" + integrity sha512-RWbSrDiYmO4LbejWY7ttpxczuwQyZLBUyygsA9Nsv95hpzUWwnNTVQmAq3xuh7vNwCp07UTmE5i11XAEExx4RA== + dependencies: + chardet "^2.1.1" + iconv-lite "^0.7.0" + +"@inquirer/figures@^1.0.15": + version "1.0.15" + resolved "https://registry.yarnpkg.com/@inquirer/figures/-/figures-1.0.15.tgz#dbb49ed80df11df74268023b496ac5d9acd22b3a" + integrity sha512-t2IEY+unGHOzAaVM5Xx6DEWKeXlDDcNPeDyUpsRc6CUhBfU3VQOEl+Vssh7VNp1dR8MdUJBWhuObjXCsVpjN5g== + +"@inquirer/input@^4.2.5", "@inquirer/input@^4.3.1": + version "4.3.1" + resolved "https://registry.yarnpkg.com/@inquirer/input/-/input-4.3.1.tgz#778683b4c4c4d95d05d4b05c4a854964b73565b4" + integrity sha512-kN0pAM4yPrLjJ1XJBjDxyfDduXOuQHrBB8aLDMueuwUGn+vNpF7Gq7TvyVxx8u4SHlFFj4trmj+a2cbpG4Jn1g== + dependencies: + "@inquirer/core" "^10.3.2" + "@inquirer/type" "^3.0.10" + +"@inquirer/number@^3.0.21", "@inquirer/number@^3.0.23": + version "3.0.23" + resolved "https://registry.yarnpkg.com/@inquirer/number/-/number-3.0.23.tgz#3fdec2540d642093fd7526818fd8d4bdc7335094" + integrity sha512-5Smv0OK7K0KUzUfYUXDXQc9jrf8OHo4ktlEayFlelCjwMXz0299Y8OrI+lj7i4gCBY15UObk76q0QtxjzFcFcg== + dependencies: + "@inquirer/core" "^10.3.2" + "@inquirer/type" "^3.0.10" + +"@inquirer/password@^4.0.21", "@inquirer/password@^4.0.23": + version "4.0.23" + resolved "https://registry.yarnpkg.com/@inquirer/password/-/password-4.0.23.tgz#b9f5187c8c92fd7aa9eceb9d8f2ead0d7e7b000d" + integrity sha512-zREJHjhT5vJBMZX/IUbyI9zVtVfOLiTO66MrF/3GFZYZ7T4YILW5MSkEYHceSii/KtRk+4i3RE7E1CUXA2jHcA== + dependencies: + "@inquirer/ansi" "^1.0.2" + "@inquirer/core" "^10.3.2" + "@inquirer/type" "^3.0.10" + +"@inquirer/prompts@7.9.0": + version "7.9.0" + resolved "https://registry.yarnpkg.com/@inquirer/prompts/-/prompts-7.9.0.tgz#497718b2ac43b15cac636d8f7b501efd1574e1cd" + integrity sha512-X7/+dG9SLpSzRkwgG5/xiIzW0oMrV3C0HOa7YHG1WnrLK+vCQHfte4k/T80059YBdei29RBC3s+pSMvPJDU9/A== + dependencies: + "@inquirer/checkbox" "^4.3.0" + "@inquirer/confirm" "^5.1.19" + "@inquirer/editor" "^4.2.21" + "@inquirer/expand" "^4.0.21" + "@inquirer/input" "^4.2.5" + "@inquirer/number" "^3.0.21" + "@inquirer/password" "^4.0.21" + "@inquirer/rawlist" "^4.1.9" + "@inquirer/search" "^3.2.0" + "@inquirer/select" "^4.4.0" + +"@inquirer/prompts@^7.2.1": + version "7.10.1" + resolved "https://registry.yarnpkg.com/@inquirer/prompts/-/prompts-7.10.1.tgz#e1436c0484cf04c22548c74e2cd239e989d5f847" + integrity sha512-Dx/y9bCQcXLI5ooQ5KyvA4FTgeo2jYj/7plWfV5Ak5wDPKQZgudKez2ixyfz7tKXzcJciTxqLeK7R9HItwiByg== + dependencies: + "@inquirer/checkbox" "^4.3.2" + "@inquirer/confirm" "^5.1.21" + "@inquirer/editor" "^4.2.23" + "@inquirer/expand" "^4.0.23" + "@inquirer/input" "^4.3.1" + "@inquirer/number" "^3.0.23" + "@inquirer/password" "^4.0.23" + "@inquirer/rawlist" "^4.1.11" + "@inquirer/search" "^3.2.2" + "@inquirer/select" "^4.4.2" + +"@inquirer/rawlist@^4.1.11", "@inquirer/rawlist@^4.1.9": + version "4.1.11" + resolved "https://registry.yarnpkg.com/@inquirer/rawlist/-/rawlist-4.1.11.tgz#313c8c3ffccb7d41e990c606465726b4a898a033" + integrity sha512-+LLQB8XGr3I5LZN/GuAHo+GpDJegQwuPARLChlMICNdwW7OwV2izlCSCxN6cqpL0sMXmbKbFcItJgdQq5EBXTw== + dependencies: + "@inquirer/core" "^10.3.2" + "@inquirer/type" "^3.0.10" + yoctocolors-cjs "^2.1.3" + +"@inquirer/search@^3.2.0", "@inquirer/search@^3.2.2": + version "3.2.2" + resolved "https://registry.yarnpkg.com/@inquirer/search/-/search-3.2.2.tgz#4cc6fd574dcd434e4399badc37c742c3fd534ac8" + integrity sha512-p2bvRfENXCZdWF/U2BXvnSI9h+tuA8iNqtUKb9UWbmLYCRQxd8WkvwWvYn+3NgYaNwdUkHytJMGG4MMLucI1kA== + dependencies: + "@inquirer/core" "^10.3.2" + "@inquirer/figures" "^1.0.15" + "@inquirer/type" "^3.0.10" + yoctocolors-cjs "^2.1.3" + +"@inquirer/select@^4.4.0", "@inquirer/select@^4.4.2": + version "4.4.2" + resolved "https://registry.yarnpkg.com/@inquirer/select/-/select-4.4.2.tgz#2ac8fca960913f18f1d1b35323ed8fcd27d89323" + integrity sha512-l4xMuJo55MAe+N7Qr4rX90vypFwCajSakx59qe/tMaC1aEHWLyw68wF4o0A4SLAY4E0nd+Vt+EyskeDIqu1M6w== + dependencies: + "@inquirer/ansi" "^1.0.2" + "@inquirer/core" "^10.3.2" + "@inquirer/figures" "^1.0.15" + "@inquirer/type" "^3.0.10" + yoctocolors-cjs "^2.1.3" + +"@inquirer/type@^3.0.10", "@inquirer/type@^3.0.2": + version "3.0.10" + resolved "https://registry.yarnpkg.com/@inquirer/type/-/type-3.0.10.tgz#11ed564ec78432a200ea2601a212d24af8150d50" + integrity sha512-BvziSRxfz5Ov8ch0z/n3oijRSEcEsHnhggm4xFZe93DHcUCTlutlq9Ox4SVENAfcRD22UQq7T/atg9Wr3k09eA== + +"@jridgewell/gen-mapping@^0.3.2": + version "0.3.13" + resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz#6342a19f44347518c93e43b1ac69deb3c4656a1f" + integrity sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA== + dependencies: + "@jridgewell/sourcemap-codec" "^1.5.0" + "@jridgewell/trace-mapping" "^0.3.24" + +"@jridgewell/resolve-uri@^3.1.0": + version "3.1.2" + resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz#7a0ee601f60f99a20c7c7c5ff0c80388c1189bd6" + integrity sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw== + +"@jridgewell/sourcemap-codec@^1.4.14", "@jridgewell/sourcemap-codec@^1.5.0": + version "1.5.5" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz#6912b00d2c631c0d15ce1a7ab57cd657f2a8f8ba" + integrity sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og== + +"@jridgewell/trace-mapping@^0.3.24": + version "0.3.31" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz#db15d6781c931f3a251a3dac39501c98a6082fd0" + integrity sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw== + dependencies: + "@jridgewell/resolve-uri" "^3.1.0" + "@jridgewell/sourcemap-codec" "^1.4.14" + +"@jsep-plugin/assignment@^1.3.0": + version "1.3.0" + resolved "https://registry.yarnpkg.com/@jsep-plugin/assignment/-/assignment-1.3.0.tgz#fcfc5417a04933f7ceee786e8ab498aa3ce2b242" + integrity sha512-VVgV+CXrhbMI3aSusQyclHkenWSAm95WaiKrMxRFam3JSUiIaQjoMIw2sEs/OX4XifnqeQUN4DYbJjlA8EfktQ== + +"@jsep-plugin/regex@^1.0.1", "@jsep-plugin/regex@^1.0.4": + version "1.0.4" + resolved "https://registry.yarnpkg.com/@jsep-plugin/regex/-/regex-1.0.4.tgz#cb2fc423220fa71c609323b9ba7f7d344a755fcc" + integrity sha512-q7qL4Mgjs1vByCaTnDFcBnV9HS7GVPJX5vyVoCgZHNSC9rjwIlmbXG5sUuorR5ndfHAIlJ8pVStxvjXHbNvtUg== + +"@jsep-plugin/ternary@^1.0.2": + version "1.1.4" + resolved "https://registry.yarnpkg.com/@jsep-plugin/ternary/-/ternary-1.1.4.tgz#1ac778bee799137f116cc108f3bf58b9615c45c3" + integrity sha512-ck5wiqIbqdMX6WRQztBL7ASDty9YLgJ3sSAK5ZpBzXeySvFGCzIvM6UiAI4hTZ22fEcYQVV/zhUbNscggW+Ukg== + +"@leichtgewicht/ip-codec@^2.0.1": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@leichtgewicht/ip-codec/-/ip-codec-2.0.5.tgz#4fc56c15c580b9adb7dc3c333a134e540b44bfb1" + integrity sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw== + +"@mdx-js/mdx@^3.1.1": + version "3.1.1" + resolved "https://registry.yarnpkg.com/@mdx-js/mdx/-/mdx-3.1.1.tgz#c5ffd991a7536b149e17175eee57a1a2a511c6d1" + integrity sha512-f6ZO2ifpwAQIpzGWaBQT2TXxPv6z3RBzQKpVftEWN78Vl/YweF1uwussDx8ECAXVtr3Rs89fKyG9YlzUs9DyGQ== + dependencies: + "@types/estree" "^1.0.0" + "@types/estree-jsx" "^1.0.0" + "@types/hast" "^3.0.0" + "@types/mdx" "^2.0.0" + acorn "^8.0.0" + collapse-white-space "^2.0.0" + devlop "^1.0.0" + estree-util-is-identifier-name "^3.0.0" + estree-util-scope "^1.0.0" + estree-walker "^3.0.0" + hast-util-to-jsx-runtime "^2.0.0" + markdown-extensions "^2.0.0" + recma-build-jsx "^1.0.0" + recma-jsx "^1.0.0" + recma-stringify "^1.0.0" + rehype-recma "^1.0.0" + remark-mdx "^3.0.0" + remark-parse "^11.0.0" + remark-rehype "^11.0.0" + source-map "^0.7.0" + unified "^11.0.0" + unist-util-position-from-estree "^2.0.0" + unist-util-stringify-position "^4.0.0" + unist-util-visit "^5.0.0" + vfile "^6.0.0" + +"@mdx-js/react@^3.1.1": + version "3.1.1" + resolved "https://registry.yarnpkg.com/@mdx-js/react/-/react-3.1.1.tgz#24bda7fffceb2fe256f954482123cda1be5f5fef" + integrity sha512-f++rKLQgUVYDAtECQ6fn/is15GkEH9+nZPM3MS0RcxVqoTfawHvDlSCH7JbMhAM6uJ32v3eXLvLmLvjGu7PTQw== + dependencies: + "@types/mdx" "^2.0.0" + +"@mintlify/cli@4.0.1130": + version "4.0.1130" + resolved "https://registry.yarnpkg.com/@mintlify/cli/-/cli-4.0.1130.tgz#322fb4f172048d4c5fdf3df430468bb7384dbb6f" + integrity sha512-pwWqCu+JqwYZKQGlVlUJO8Gh46f5ahQIVw2/8C5hgx0Wv0qW51/QlWb6Z6Uyn+a9EKbEDGGkrBlh3jw3LZ7kew== + dependencies: + "@inquirer/prompts" "7.9.0" + "@mintlify/common" "1.0.861" + "@mintlify/link-rot" "3.0.1039" + "@mintlify/prebuild" "1.0.1004" + "@mintlify/previewing" "4.0.1065" + "@mintlify/validation" "0.1.672" + adm-zip "0.5.16" + chalk "5.2.0" + color "4.2.3" + detect-port "1.5.1" + front-matter "4.0.2" + fs-extra "11.2.0" + ink "6.3.0" + inquirer "12.3.0" + js-yaml "4.1.0" + mdast-util-mdx-jsx "3.2.0" + open "^8.4.2" + openid-client "^6.8.2" + posthog-node "5.17.2" + react "19.2.3" + semver "7.7.2" + unist-util-visit "5.0.0" + yargs "17.7.1" + zod "^4.3.6" + optionalDependencies: + keytar "^7.9.0" + +"@mintlify/common@1.0.661": + version "1.0.661" + resolved "https://registry.yarnpkg.com/@mintlify/common/-/common-1.0.661.tgz#a09c70e1469a55e5956c9642b393b9250350c86d" + integrity sha512-/Hdiblzaomp+AWStQ4smhVMgesQhffzQjC9aYBnmLReNdh2Js+ccQFUaWL3TNIxwiS2esaZvsHSV/D+zyRS3hg== + dependencies: + "@asyncapi/parser" "3.4.0" + "@mintlify/mdx" "^3.0.4" + "@mintlify/models" "0.0.255" + "@mintlify/openapi-parser" "^0.0.8" + "@mintlify/validation" "0.1.555" + "@sindresorhus/slugify" "2.2.0" + "@types/mdast" "4.0.4" + acorn "8.11.2" + acorn-jsx "5.3.2" + color-blend "4.0.0" + estree-util-to-js "2.0.0" + estree-walker "3.0.3" + front-matter "4.0.2" + hast-util-from-html "2.0.3" + hast-util-to-html "9.0.4" + hast-util-to-text "4.0.2" + hex-rgb "5.0.0" + ignore "7.0.5" + js-yaml "4.1.0" + lodash "4.17.21" + mdast-util-from-markdown "2.0.2" + mdast-util-gfm "3.0.0" + mdast-util-mdx "3.0.0" + mdast-util-mdx-jsx "3.1.3" + micromark-extension-gfm "3.0.0" + micromark-extension-mdx-jsx "3.0.1" + micromark-extension-mdxjs "3.0.0" + openapi-types "12.1.3" + postcss "8.5.6" + rehype-stringify "10.0.1" + remark "15.0.1" + remark-frontmatter "5.0.0" + remark-gfm "4.0.0" + remark-math "6.0.0" + remark-mdx "3.1.0" + remark-parse "11.0.0" + remark-rehype "11.1.1" + remark-stringify "11.0.0" + tailwindcss "3.4.4" + unified "11.0.5" + unist-builder "4.0.0" + unist-util-map "4.0.0" + unist-util-remove "4.0.0" + unist-util-remove-position "5.0.0" + unist-util-visit "5.0.0" + unist-util-visit-parents "6.0.1" + vfile "6.0.3" + +"@mintlify/common@1.0.861": + version "1.0.861" + resolved "https://registry.yarnpkg.com/@mintlify/common/-/common-1.0.861.tgz#786519f578f52e9aaf9cb0fc3d5f9a067866f32e" + integrity sha512-Mf42N8A1RVp7K8qdS94xLldzTrw/X8tSymcpD+MLLldE5DGzCOrQ5+cfUHC+XPdHvNnP0OGSORz+hf5egABBAA== + dependencies: + "@asyncapi/parser" "3.4.0" + "@asyncapi/specs" "6.8.1" + "@mintlify/mdx" "^3.0.4" + "@mintlify/models" "0.0.292" + "@mintlify/openapi-parser" "^0.0.8" + "@mintlify/validation" "0.1.672" + "@sindresorhus/slugify" "2.2.0" + "@types/mdast" "4.0.4" + acorn "8.11.2" + acorn-jsx "5.3.2" + color-blend "4.0.0" + estree-util-to-js "2.0.0" + estree-walker "3.0.3" + front-matter "4.0.2" + hast-util-from-html "2.0.3" + hast-util-to-html "9.0.4" + hast-util-to-text "4.0.2" + hex-rgb "5.0.0" + ignore "7.0.5" + js-yaml "4.1.0" + lodash "4.18.1" + mdast-util-from-markdown "2.0.2" + mdast-util-gfm "3.0.0" + mdast-util-mdx "3.0.0" + mdast-util-mdx-jsx "3.1.3" + micromark-extension-gfm "3.0.0" + micromark-extension-mdx-jsx "3.0.1" + micromark-extension-mdxjs "3.0.0" + openapi-types "12.1.3" + postcss "8.5.6" + rehype-stringify "10.0.1" + remark "15.0.1" + remark-frontmatter "5.0.0" + remark-gfm "4.0.0" + remark-math "6.0.0" + remark-mdx "3.1.0" + remark-parse "11.0.0" + remark-rehype "11.1.1" + remark-stringify "11.0.0" + sucrase "^3.34.0" + tailwindcss "^3.4.17" + unified "11.0.5" + unist-builder "4.0.0" + unist-util-map "4.0.0" + unist-util-remove "4.0.0" + unist-util-remove-position "5.0.0" + unist-util-visit "5.0.0" + unist-util-visit-parents "6.0.1" + vfile "6.0.3" + xss "1.0.15" + +"@mintlify/link-rot@3.0.1039": + version "3.0.1039" + resolved "https://registry.yarnpkg.com/@mintlify/link-rot/-/link-rot-3.0.1039.tgz#84a7e54246bb71f28f3760574a9350b5dcb3eacf" + integrity sha512-5on/uvYl0pwcKm/gkhBADy/uSXFMqztA57Qz422DvZj6PKVX8tVsnyrepsMp/QUgSPFeUpayKYMlEWZ00TOXLQ== + dependencies: + "@mintlify/common" "1.0.861" + "@mintlify/models" "0.0.292" + "@mintlify/prebuild" "1.0.1004" + "@mintlify/previewing" "4.0.1065" + "@mintlify/scraping" "4.0.522" + "@mintlify/validation" "0.1.672" + fs-extra "11.1.0" + unist-util-visit "4.1.2" + +"@mintlify/mdx@^3.0.4": + version "3.0.4" + resolved "https://registry.yarnpkg.com/@mintlify/mdx/-/mdx-3.0.4.tgz#11fa9f4cac0bd24dcaea5d0a99a68d08db5c453a" + integrity sha512-tJhdpnM5ReJLNJ2fuDRIEr0zgVd6id7/oAIfs26V46QlygiLsc8qx4Rz3LWIX51rUXW/cfakjj0EATxIciIw+g== + dependencies: + "@shikijs/transformers" "^3.11.0" + "@shikijs/twoslash" "^3.12.2" + arktype "^2.1.26" + hast-util-to-string "^3.0.1" + mdast-util-from-markdown "^2.0.2" + mdast-util-gfm "^3.1.0" + mdast-util-mdx-jsx "^3.2.0" + mdast-util-to-hast "^13.2.0" + next-mdx-remote-client "^1.0.3" + rehype-katex "^7.0.1" + remark-gfm "^4.0.0" + remark-math "^6.0.0" + remark-smartypants "^3.0.2" + shiki "^3.11.0" + unified "^11.0.0" + unist-util-visit "^5.0.0" + +"@mintlify/models@0.0.255": + version "0.0.255" + resolved "https://registry.yarnpkg.com/@mintlify/models/-/models-0.0.255.tgz#34347052d742c81430d9ad3e0b1b9ddf9533c5e9" + integrity sha512-LIUkfA7l7ypHAAuOW74ZJws/NwNRqlDRD/U466jarXvvSlGhJec/6J4/I+IEcBvWDnc9anLFKmnGO04jPKgAsg== + dependencies: + axios "1.10.0" + openapi-types "12.1.3" + +"@mintlify/models@0.0.292": + version "0.0.292" + resolved "https://registry.yarnpkg.com/@mintlify/models/-/models-0.0.292.tgz#a8768f41011f49fef2ef0f99dcd0d2ae69d75106" + integrity sha512-j89c57C3H79Av9ivzV0+MbAHHWB4ZgcGqwFTIX91EjwyVhQIFVtKx6Bo+T/XGzJlbbt8JTlEqs4l9tz/KJwP2A== + dependencies: + axios "1.13.2" + openapi-types "12.1.3" + +"@mintlify/openapi-parser@^0.0.8": + version "0.0.8" + resolved "https://registry.yarnpkg.com/@mintlify/openapi-parser/-/openapi-parser-0.0.8.tgz#09cf5fab762956dddc91dddfb818f076fe1aea81" + integrity sha512-9MBRq9lS4l4HITYCrqCL7T61MOb20q9IdU7HWhqYMNMM1jGO1nHjXasFy61yZ8V6gMZyyKQARGVoZ0ZrYN48Og== + dependencies: + ajv "^8.17.1" + ajv-draft-04 "^1.0.0" + ajv-formats "^3.0.1" + jsonpointer "^5.0.1" + leven "^4.0.0" + yaml "^2.4.5" + +"@mintlify/prebuild@1.0.1004": + version "1.0.1004" + resolved "https://registry.yarnpkg.com/@mintlify/prebuild/-/prebuild-1.0.1004.tgz#f48bed9f0b8619d161c6175320a066631de17857" + integrity sha512-thgMO0/iSFu/Rfff+SXhP1HQu1VPz1FMHTV6lOUC2iPdKSztqMfT52HEyH41Z90kkO2hz3bCjNmhSI9ZegDCkA== + dependencies: + "@mintlify/common" "1.0.861" + "@mintlify/openapi-parser" "^0.0.8" + "@mintlify/scraping" "4.0.725" + "@mintlify/validation" "0.1.672" + chalk "5.3.0" + favicons "7.2.0" + front-matter "4.0.2" + fs-extra "11.1.0" + js-yaml "4.1.0" + openapi-types "12.1.3" + sharp "0.33.5" + sharp-ico "0.1.5" + unist-util-visit "4.1.2" + uuid "11.1.0" + +"@mintlify/previewing@4.0.1065": + version "4.0.1065" + resolved "https://registry.yarnpkg.com/@mintlify/previewing/-/previewing-4.0.1065.tgz#6387f42fd2d2502c99fe5c5e127eb1e7dd920add" + integrity sha512-wP1+/NnVMHFCbt5TbQk3auWYVv2hfP4zrMFBpT+DsFoos0BJ3FHuu6AQQmErRzBklNdB8/ZWnG5NaB8+Buq37A== + dependencies: + "@mintlify/common" "1.0.861" + "@mintlify/prebuild" "1.0.1004" + "@mintlify/validation" "0.1.672" + adm-zip "0.5.16" + better-opn "3.0.2" + chalk "5.2.0" + chokidar "3.5.3" + express "4.18.2" + front-matter "4.0.2" + fs-extra "11.1.0" + got "13.0.0" + ink "6.3.0" + ink-spinner "5.0.0" + is-online "10.0.0" + js-yaml "4.1.0" + openapi-types "12.1.3" + react "19.2.3" + socket.io "4.7.2" + tar "6.1.15" + unist-util-visit "4.1.2" + yargs "17.7.1" + +"@mintlify/scraping@4.0.522": + version "4.0.522" + resolved "https://registry.yarnpkg.com/@mintlify/scraping/-/scraping-4.0.522.tgz#8a4a2ad68b73d83c3719258c48c21cd5d2649680" + integrity sha512-PL2k52WT5S5OAgnT2K13bP7J2El6XwiVvQlrLvxDYw5KMMV+y34YVJI8ZscKb4trjitWDgyK0UTq2KN6NQgn6g== + dependencies: + "@mintlify/common" "1.0.661" + "@mintlify/openapi-parser" "^0.0.8" + fs-extra "11.1.1" + hast-util-to-mdast "10.1.0" + js-yaml "4.1.0" + mdast-util-mdx-jsx "3.1.3" + neotraverse "0.6.18" + puppeteer "22.14.0" + rehype-parse "9.0.1" + remark-gfm "4.0.0" + remark-mdx "3.0.1" + remark-parse "11.0.0" + remark-stringify "11.0.0" + unified "11.0.5" + unist-util-visit "5.0.0" + yargs "17.7.1" + zod "3.21.4" + +"@mintlify/scraping@4.0.725": + version "4.0.725" + resolved "https://registry.yarnpkg.com/@mintlify/scraping/-/scraping-4.0.725.tgz#dc2773d0ad57bde1b2c49ab078da0105f4d7dcdf" + integrity sha512-PEFWetdSzozJS24ZqRqRKczF3Y+x6oUJ6EPVVzfE4CLou1xqlehJRwCzv2GO25NTaGosQLlZaG20brVAwNBtow== + dependencies: + "@mintlify/common" "1.0.861" + "@mintlify/openapi-parser" "^0.0.8" + fs-extra "11.1.1" + hast-util-to-mdast "10.1.0" + js-yaml "4.1.0" + mdast-util-mdx-jsx "3.1.3" + neotraverse "0.6.18" + puppeteer "22.14.0" + rehype-parse "9.0.1" + remark-gfm "4.0.0" + remark-mdx "3.0.1" + remark-parse "11.0.0" + remark-stringify "11.0.0" + unified "11.0.5" + unist-util-visit "5.0.0" + yargs "17.7.1" + zod "3.24.0" + +"@mintlify/validation@0.1.555": + version "0.1.555" + resolved "https://registry.yarnpkg.com/@mintlify/validation/-/validation-0.1.555.tgz#f27d454f357d2814383c55c8dd9db937a807bc22" + integrity sha512-11QVUReL4N5u8wSCgZt4RN7PA0jYQoMEBZ5IrUp5pgb5ZJBOoGV/vPsQrxPPa1cxsUDAuToNhtGxRQtOav/w8w== + dependencies: + "@mintlify/mdx" "^3.0.4" + "@mintlify/models" "0.0.255" + arktype "2.1.27" + js-yaml "4.1.0" + lcm "0.0.3" + lodash "4.17.21" + object-hash "3.0.0" + openapi-types "12.1.3" + uuid "11.1.0" + zod "3.21.4" + zod-to-json-schema "3.20.4" + +"@mintlify/validation@0.1.672": + version "0.1.672" + resolved "https://registry.yarnpkg.com/@mintlify/validation/-/validation-0.1.672.tgz#b8fbae7c0ef44d13f6ecd89a26da573f1fd1f370" + integrity sha512-8l3+gZEi4o82g1LWh3RUL25xKdYV2RJsMbfmYW/4kydMpfBZdgiSeVkkTNykPsPi2CymYXEijqeiROtxA4Vkjg== + dependencies: + "@mintlify/mdx" "^3.0.4" + "@mintlify/models" "0.0.292" + arktype "2.1.27" + js-yaml "4.1.0" + lcm "0.0.3" + lodash "4.18.1" + neotraverse "0.6.18" + object-hash "3.0.0" + openapi-types "12.1.3" + uuid "11.1.0" + zod "3.24.0" + zod-to-json-schema "3.20.4" + +"@nodelib/fs.scandir@2.1.5": + version "2.1.5" + resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" + integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== + dependencies: + "@nodelib/fs.stat" "2.0.5" + run-parallel "^1.1.9" + +"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" + integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== + +"@nodelib/fs.walk@^1.2.3": + version "1.2.8" + resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" + integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== + dependencies: + "@nodelib/fs.scandir" "2.1.5" + fastq "^1.6.0" + +"@openapi-contrib/openapi-schema-to-json-schema@~3.2.0": + version "3.2.0" + resolved "https://registry.yarnpkg.com/@openapi-contrib/openapi-schema-to-json-schema/-/openapi-schema-to-json-schema-3.2.0.tgz#c4c92edd4478b5ecb3d99c29ecb355118259dccc" + integrity sha512-Gj6C0JwCr8arj0sYuslWXUBSP/KnUlEGnPW4qxlXvAl543oaNQgMgIgkQUA6vs5BCCvwTEiL8m/wdWzfl4UvSw== + dependencies: + fast-deep-equal "^3.1.3" + +"@posthog/core@1.7.1": + version "1.7.1" + resolved "https://registry.yarnpkg.com/@posthog/core/-/core-1.7.1.tgz#ec45a3b13acbe4fbf453625c83bcd38da21beeb7" + integrity sha512-kjK0eFMIpKo9GXIbts8VtAknsoZ18oZorANdtuTj1CbgS28t4ZVq//HAWhnxEuXRTrtkd+SUJ6Ux3j2Af8NCuA== + dependencies: + cross-spawn "^7.0.6" + +"@puppeteer/browsers@2.3.0": + version "2.3.0" + resolved "https://registry.yarnpkg.com/@puppeteer/browsers/-/browsers-2.3.0.tgz#791ea7d80450fea24eb19fb1d70c367ad4e08cae" + integrity sha512-ioXoq9gPxkss4MYhD+SFaU9p1IHFUX0ILAWFPyjGaBdjLsYAlZw6j1iLA0N/m12uVHLFDfSYNF7EQccjinIMDA== + dependencies: + debug "^4.3.5" + extract-zip "^2.0.1" + progress "^2.0.3" + proxy-agent "^6.4.0" + semver "^7.6.3" + tar-fs "^3.0.6" + unbzip2-stream "^1.4.3" + yargs "^17.7.2" + +"@shikijs/core@3.23.0": + version "3.23.0" + resolved "https://registry.yarnpkg.com/@shikijs/core/-/core-3.23.0.tgz#79248ec4ad3de4fd5c12993f5c30cb071ec04812" + integrity sha512-NSWQz0riNb67xthdm5br6lAkvpDJRTgB36fxlo37ZzM2yq0PQFFzbd8psqC2XMPgCzo1fW6cVi18+ArJ44wqgA== + dependencies: + "@shikijs/types" "3.23.0" + "@shikijs/vscode-textmate" "^10.0.2" + "@types/hast" "^3.0.4" + hast-util-to-html "^9.0.5" + +"@shikijs/engine-javascript@3.23.0": + version "3.23.0" + resolved "https://registry.yarnpkg.com/@shikijs/engine-javascript/-/engine-javascript-3.23.0.tgz#eae89a47913f486e5a05130d13b965c424c33b21" + integrity sha512-aHt9eiGFobmWR5uqJUViySI1bHMqrAgamWE1TYSUoftkAeCCAiGawPMwM+VCadylQtF4V3VNOZ5LmfItH5f3yA== + dependencies: + "@shikijs/types" "3.23.0" + "@shikijs/vscode-textmate" "^10.0.2" + oniguruma-to-es "^4.3.4" + +"@shikijs/engine-oniguruma@3.23.0": + version "3.23.0" + resolved "https://registry.yarnpkg.com/@shikijs/engine-oniguruma/-/engine-oniguruma-3.23.0.tgz#789421048d66ac1b33613169d6d18b9cc6e340ed" + integrity sha512-1nWINwKXxKKLqPibT5f4pAFLej9oZzQTsby8942OTlsJzOBZ0MWKiwzMsd+jhzu8YPCHAswGnnN1YtQfirL35g== + dependencies: + "@shikijs/types" "3.23.0" + "@shikijs/vscode-textmate" "^10.0.2" + +"@shikijs/langs@3.23.0": + version "3.23.0" + resolved "https://registry.yarnpkg.com/@shikijs/langs/-/langs-3.23.0.tgz#00959d8b16c7f671221ae79b3ad8cde7e6a5c112" + integrity sha512-2Ep4W3Re5aB1/62RSYQInK9mM3HsLeB91cHqznAJMuylqjzNVAVCMnNWRHFtcNHXsoNRayP9z1qj4Sq3nMqYXg== + dependencies: + "@shikijs/types" "3.23.0" + +"@shikijs/themes@3.23.0": + version "3.23.0" + resolved "https://registry.yarnpkg.com/@shikijs/themes/-/themes-3.23.0.tgz#fd96ca5ad52639057995bc2093682884e1846f27" + integrity sha512-5qySYa1ZgAT18HR/ypENL9cUSGOeI2x+4IvYJu4JgVJdizn6kG4ia5Q1jDEOi7gTbN4RbuYtmHh0W3eccOrjMA== + dependencies: + "@shikijs/types" "3.23.0" + +"@shikijs/transformers@^3.11.0": + version "3.23.0" + resolved "https://registry.yarnpkg.com/@shikijs/transformers/-/transformers-3.23.0.tgz#a4f1a593e4f91fa3034f7ec02094deefdadab98b" + integrity sha512-F9msZVxdF+krQNSdQ4V+Ja5QemeAoTQ2jxt7nJCwhDsdF1JWS3KxIQXA3lQbyKwS3J61oHRUSv4jYWv3CkaKTQ== + dependencies: + "@shikijs/core" "3.23.0" + "@shikijs/types" "3.23.0" + +"@shikijs/twoslash@^3.12.2": + version "3.23.0" + resolved "https://registry.yarnpkg.com/@shikijs/twoslash/-/twoslash-3.23.0.tgz#50785a52bab98059aeca973e4701dbd17bd14a9f" + integrity sha512-pNaLJWMA3LU7PhT8tm9OQBZ1epy0jmdgeJzntBtr1EVXLbHxGzTj3mnf9vOdcl84l96qnlJXkJ/NGXZYBpXl5g== + dependencies: + "@shikijs/core" "3.23.0" + "@shikijs/types" "3.23.0" + twoslash "^0.3.6" + +"@shikijs/types@3.23.0": + version "3.23.0" + resolved "https://registry.yarnpkg.com/@shikijs/types/-/types-3.23.0.tgz#d441571a058641926018ae3de99866f39e5bbdf2" + integrity sha512-3JZ5HXOZfYjsYSk0yPwBrkupyYSLpAE26Qc0HLghhZNGTZg/SKxXIIgoxOpmmeQP0RRSDJTk1/vPfw9tbw+jSQ== + dependencies: + "@shikijs/vscode-textmate" "^10.0.2" + "@types/hast" "^3.0.4" + +"@shikijs/vscode-textmate@^10.0.2": + version "10.0.2" + resolved "https://registry.yarnpkg.com/@shikijs/vscode-textmate/-/vscode-textmate-10.0.2.tgz#a90ab31d0cc1dfb54c66a69e515bf624fa7b2224" + integrity sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg== + +"@sindresorhus/is@^5.2.0": + version "5.6.0" + resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-5.6.0.tgz#41dd6093d34652cddb5d5bdeee04eafc33826668" + integrity sha512-TV7t8GKYaJWsn00tFDqBw8+Uqmr8A0fRU1tvTQhyZzGv0sJCGRQL3JGMI3ucuKo3XIZdUP+Lx7/gh2t3lewy7g== + +"@sindresorhus/slugify@2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@sindresorhus/slugify/-/slugify-2.2.0.tgz#42738974ff19a9a306d3523a8595152998cc758e" + integrity sha512-9Vybc/qX8Kj6pxJaapjkFbiUJPk7MAkCh/GFCxIBnnsuYCFPIXKvnLidG8xlepht3i24L5XemUmGtrJ3UWrl6w== + dependencies: + "@sindresorhus/transliterate" "^1.0.0" + escape-string-regexp "^5.0.0" + +"@sindresorhus/transliterate@^1.0.0": + version "1.6.0" + resolved "https://registry.yarnpkg.com/@sindresorhus/transliterate/-/transliterate-1.6.0.tgz#2309fff65a868047e6d2dd70dec747c5b36a8327" + integrity sha512-doH1gimEu3A46VX6aVxpHTeHrytJAG6HgdxntYnCFiIFHEM/ZGpG8KiZGBChchjQmG0XFIBL552kBTjVcMZXwQ== + dependencies: + escape-string-regexp "^5.0.0" + +"@socket.io/component-emitter@~3.1.0": + version "3.1.2" + resolved "https://registry.yarnpkg.com/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz#821f8442f4175d8f0467b9daf26e3a18e2d02af2" + integrity sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA== + +"@stoplight/better-ajv-errors@1.0.3": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@stoplight/better-ajv-errors/-/better-ajv-errors-1.0.3.tgz#d74a5c4da5d786c17188d7f4edec505f089885fa" + integrity sha512-0p9uXkuB22qGdNfy3VeEhxkU5uwvp/KrBTAbrLBURv6ilxIVwanKwjMc41lQfIVgPGcOkmLbTolfFrSsueu7zA== + dependencies: + jsonpointer "^5.0.0" + leven "^3.1.0" + +"@stoplight/json-ref-readers@1.2.2", "@stoplight/json-ref-readers@^1.2.2": + version "1.2.2" + resolved "https://registry.yarnpkg.com/@stoplight/json-ref-readers/-/json-ref-readers-1.2.2.tgz#e5992bae597f228f988f362a4c0304c03a92008b" + integrity sha512-nty0tHUq2f1IKuFYsLM4CXLZGHdMn+X/IwEUIpeSOXt0QjMUbL0Em57iJUDzz+2MkWG83smIigNZ3fauGjqgdQ== + dependencies: + node-fetch "^2.6.0" + tslib "^1.14.1" + +"@stoplight/json-ref-resolver@^3.1.5", "@stoplight/json-ref-resolver@~3.1.6": + version "3.1.6" + resolved "https://registry.yarnpkg.com/@stoplight/json-ref-resolver/-/json-ref-resolver-3.1.6.tgz#dcf8724472b7d54e8e8952510f39b8ee901dcf56" + integrity sha512-YNcWv3R3n3U6iQYBsFOiWSuRGE5su1tJSiX6pAPRVk7dP0L7lqCteXGzuVRQ0gMZqUl8v1P0+fAKxF6PLo9B5A== + dependencies: + "@stoplight/json" "^3.21.0" + "@stoplight/path" "^1.3.2" + "@stoplight/types" "^12.3.0 || ^13.0.0" + "@types/urijs" "^1.19.19" + dependency-graph "~0.11.0" + fast-memoize "^2.5.2" + immer "^9.0.6" + lodash "^4.17.21" + tslib "^2.6.0" + urijs "^1.19.11" + +"@stoplight/json@3.21.0": + version "3.21.0" + resolved "https://registry.yarnpkg.com/@stoplight/json/-/json-3.21.0.tgz#c0dff9c478f3365d7946cb6e34c17cc2fa84250b" + integrity sha512-5O0apqJ/t4sIevXCO3SBN9AHCEKKR/Zb4gaj7wYe5863jme9g02Q0n/GhM7ZCALkL+vGPTe4ZzTETP8TFtsw3g== + dependencies: + "@stoplight/ordered-object-literal" "^1.0.3" + "@stoplight/path" "^1.3.2" + "@stoplight/types" "^13.6.0" + jsonc-parser "~2.2.1" + lodash "^4.17.21" + safe-stable-stringify "^1.1" + +"@stoplight/json@^3.17.0", "@stoplight/json@^3.17.1", "@stoplight/json@^3.20.1", "@stoplight/json@^3.21.0", "@stoplight/json@~3.21.0": + version "3.21.7" + resolved "https://registry.yarnpkg.com/@stoplight/json/-/json-3.21.7.tgz#102f5fd11921984c96672ce4307850daa1cbfc7b" + integrity sha512-xcJXgKFqv/uCEgtGlPxy3tPA+4I+ZI4vAuMJ885+ThkTHFVkC+0Fm58lA9NlsyjnkpxFh4YiQWpH+KefHdbA0A== + dependencies: + "@stoplight/ordered-object-literal" "^1.0.3" + "@stoplight/path" "^1.3.2" + "@stoplight/types" "^13.6.0" + jsonc-parser "~2.2.1" + lodash "^4.17.21" + safe-stable-stringify "^1.1" + +"@stoplight/ordered-object-literal@^1.0.3", "@stoplight/ordered-object-literal@^1.0.5": + version "1.0.5" + resolved "https://registry.yarnpkg.com/@stoplight/ordered-object-literal/-/ordered-object-literal-1.0.5.tgz#06689095a4f1a53e9d9a5f0055f707c387af966a" + integrity sha512-COTiuCU5bgMUtbIFBuyyh2/yVVzlr5Om0v5utQDgBCuQUOPgU1DwoffkTfg4UBQOvByi5foF4w4T+H9CoRe5wg== + +"@stoplight/path@1.3.2", "@stoplight/path@^1.3.2": + version "1.3.2" + resolved "https://registry.yarnpkg.com/@stoplight/path/-/path-1.3.2.tgz#96e591496b72fde0f0cdae01a61d64f065bd9ede" + integrity sha512-lyIc6JUlUA8Ve5ELywPC8I2Sdnh1zc1zmbYgVarhXIp9YeAB0ReeqmGEOWNtlHkbP2DAA1AL65Wfn2ncjK/jtQ== + +"@stoplight/spectral-core@^1.18.3", "@stoplight/spectral-core@^1.19.2", "@stoplight/spectral-core@^1.19.4": + version "1.22.0" + resolved "https://registry.yarnpkg.com/@stoplight/spectral-core/-/spectral-core-1.22.0.tgz#2b224e992fdff1cf8edadb86621e200cbe89239a" + integrity sha512-4hTxMDs4TFUG4/jKjaZttA65gNuV2PCKI9+51I+J4nL6ylo17DlbW+sl6byKnBuV/85HxaV33ri5fEGlp8lTSA== + dependencies: + "@stoplight/better-ajv-errors" "1.0.3" + "@stoplight/json" "~3.21.0" + "@stoplight/path" "1.3.2" + "@stoplight/spectral-parsers" "^1.0.0" + "@stoplight/spectral-ref-resolver" "^1.0.4" + "@stoplight/spectral-runtime" "^1.1.2" + "@stoplight/types" "~13.6.0" + "@types/es-aggregate-error" "^1.0.2" + "@types/json-schema" "^7.0.11" + ajv "^8.18.0" + ajv-errors "~3.0.0" + ajv-formats "~2.1.1" + es-aggregate-error "^1.0.7" + expr-eval-fork "^3.0.1" + jsonpath-plus "^10.3.0" + lodash "^4.18.1" + lodash.topath "^4.5.2" + minimatch "^3.1.4" + nimma "0.2.3" + pony-cause "^1.1.1" + tslib "^2.8.1" + +"@stoplight/spectral-formats@^1.8.1": + version "1.8.2" + resolved "https://registry.yarnpkg.com/@stoplight/spectral-formats/-/spectral-formats-1.8.2.tgz#d5bbdb5d0802b118c9b8f8bbf72d6f34f4248b54" + integrity sha512-c06HB+rOKfe7tuxg0IdKDEA5XnjL2vrn/m/OVIIxtINtBzphZrOgtRn7epQ5bQF5SWp84Ue7UJWaGgDwVngMFw== + dependencies: + "@stoplight/json" "^3.17.0" + "@stoplight/spectral-core" "^1.19.2" + "@types/json-schema" "^7.0.7" + tslib "^2.8.1" + +"@stoplight/spectral-functions@^1.7.2": + version "1.10.2" + resolved "https://registry.yarnpkg.com/@stoplight/spectral-functions/-/spectral-functions-1.10.2.tgz#d9e965301d124fbd59ddb71d2558ed168cce7572" + integrity sha512-PIfPUgTRo8EtAnL1MIrzhHoUuojSaE8shGSMaHS3BxGyc8d079BE5+TqJa1/WLUb9YT9JQnZ0Aj4xfi8NcJOIw== + dependencies: + "@stoplight/better-ajv-errors" "1.0.3" + "@stoplight/json" "^3.17.1" + "@stoplight/spectral-core" "^1.19.4" + "@stoplight/spectral-formats" "^1.8.1" + "@stoplight/spectral-runtime" "^1.1.2" + ajv "^8.18.0" + ajv-draft-04 "~1.0.0" + ajv-errors "~3.0.0" + ajv-formats "~2.1.1" + lodash "^4.18.1" + tslib "^2.8.1" + +"@stoplight/spectral-parsers@^1.0.0", "@stoplight/spectral-parsers@^1.0.2": + version "1.0.5" + resolved "https://registry.yarnpkg.com/@stoplight/spectral-parsers/-/spectral-parsers-1.0.5.tgz#2febd979b2917465759c97fe7375145f86574ff2" + integrity sha512-ANDTp2IHWGvsQDAY85/jQi9ZrF4mRrA5bciNHX+PUxPr4DwS6iv4h+FVWJMVwcEYdpyoIdyL+SRmHdJfQEPmwQ== + dependencies: + "@stoplight/json" "~3.21.0" + "@stoplight/types" "^14.1.1" + "@stoplight/yaml" "~4.3.0" + tslib "^2.8.1" + +"@stoplight/spectral-ref-resolver@^1.0.3", "@stoplight/spectral-ref-resolver@^1.0.4": + version "1.0.5" + resolved "https://registry.yarnpkg.com/@stoplight/spectral-ref-resolver/-/spectral-ref-resolver-1.0.5.tgz#2462ae79bbb90b7fcc76b014118a0beeee5e64d5" + integrity sha512-gj3TieX5a9zMW29z3mBlAtDOCgN3GEc1VgZnCVlr5irmR4Qi5LuECuFItAq4pTn5Zu+sW5bqutsCH7D4PkpyAA== + dependencies: + "@stoplight/json-ref-readers" "1.2.2" + "@stoplight/json-ref-resolver" "~3.1.6" + "@stoplight/spectral-runtime" "^1.1.2" + dependency-graph "0.11.0" + tslib "^2.8.1" + +"@stoplight/spectral-runtime@^1.1.2": + version "1.1.5" + resolved "https://registry.yarnpkg.com/@stoplight/spectral-runtime/-/spectral-runtime-1.1.5.tgz#02b05c439fa35ec28c2a534b2f473887f7b5d034" + integrity sha512-6/HSCQBKnI4M5qonCKos2W7oggXv+U/ml+m/cAd4eJAYfIVEmaLUo03qSWIIl4cBc5ujJPmn2WnCiRrz1++P7Q== + dependencies: + "@stoplight/json" "^3.20.1" + "@stoplight/path" "^1.3.2" + "@stoplight/types" "^13.6.0" + abort-controller "^3.0.0" + lodash "^4.18.1" + node-fetch "^2.7.0" + tslib "^2.8.1" + +"@stoplight/types@^12.3.0 || ^13.0.0", "@stoplight/types@^13.12.0", "@stoplight/types@^13.6.0": + version "13.20.0" + resolved "https://registry.yarnpkg.com/@stoplight/types/-/types-13.20.0.tgz#d42682f1e3a14a3c60bdf0df08bff4023518763d" + integrity sha512-2FNTv05If7ib79VPDA/r9eUet76jewXFH2y2K5vuge6SXbRHtWBhcaRmu+6QpF4/WRNoJj5XYRSwLGXDxysBGA== + dependencies: + "@types/json-schema" "^7.0.4" + utility-types "^3.10.0" + +"@stoplight/types@^14.1.1": + version "14.1.1" + resolved "https://registry.yarnpkg.com/@stoplight/types/-/types-14.1.1.tgz#0dd5761aac25673a951955e984c724c138368b7a" + integrity sha512-/kjtr+0t0tjKr+heVfviO9FrU/uGLc+QNX3fHJc19xsCNYqU7lVhaXxDmEID9BZTjG+/r9pK9xP/xU02XGg65g== + dependencies: + "@types/json-schema" "^7.0.4" + utility-types "^3.10.0" + +"@stoplight/types@~13.6.0": + version "13.6.0" + resolved "https://registry.yarnpkg.com/@stoplight/types/-/types-13.6.0.tgz#96c6aaae05858b36f589821cd52c95aa9b205ce7" + integrity sha512-dzyuzvUjv3m1wmhPfq82lCVYGcXG0xUYgqnWfCq3PCVR4BKFhjdkHrnJ+jIDoMKvXb05AZP/ObQF6+NpDo29IQ== + dependencies: + "@types/json-schema" "^7.0.4" + utility-types "^3.10.0" + +"@stoplight/yaml-ast-parser@0.0.50": + version "0.0.50" + resolved "https://registry.yarnpkg.com/@stoplight/yaml-ast-parser/-/yaml-ast-parser-0.0.50.tgz#ed625a1d9ae63eb61980446e058fa745386ab61e" + integrity sha512-Pb6M8TDO9DtSVla9yXSTAxmo9GVEouq5P40DWXdOie69bXogZTkgvopCq+yEvTMA0F6PEvdJmbtTV3ccIp11VQ== + +"@stoplight/yaml@~4.3.0": + version "4.3.0" + resolved "https://registry.yarnpkg.com/@stoplight/yaml/-/yaml-4.3.0.tgz#ca403157472509812ccec6f277185e7e65d7bd7d" + integrity sha512-JZlVFE6/dYpP9tQmV0/ADfn32L9uFarHWxfcRhReKUnljz1ZiUM5zpX+PH8h5CJs6lao3TuFqnPm9IJJCEkE2w== + dependencies: + "@stoplight/ordered-object-literal" "^1.0.5" + "@stoplight/types" "^14.1.1" + "@stoplight/yaml-ast-parser" "0.0.50" + tslib "^2.2.0" + +"@szmarczak/http-timer@^5.0.1": + version "5.0.1" + resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-5.0.1.tgz#c7c1bf1141cdd4751b0399c8fc7b8b664cd5be3a" + integrity sha512-+PmQX0PiAYPMeVYe237LJAYvOMYW1j2rH5YROyS3b4CTVJum34HfRvKvAzozHAQG0TnHNdUfY9nCeUyRAs//cw== + dependencies: + defer-to-connect "^2.0.1" + +"@tootallnate/quickjs-emscripten@^0.23.0": + version "0.23.0" + resolved "https://registry.yarnpkg.com/@tootallnate/quickjs-emscripten/-/quickjs-emscripten-0.23.0.tgz#db4ecfd499a9765ab24002c3b696d02e6d32a12c" + integrity sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA== + +"@types/acorn@^4.0.0": + version "4.0.6" + resolved "https://registry.yarnpkg.com/@types/acorn/-/acorn-4.0.6.tgz#d61ca5480300ac41a7d973dd5b84d0a591154a22" + integrity sha512-veQTnWP+1D/xbxVrPC3zHnCZRjSrKfhbMUlEA43iMZLu7EsnTtkJklIuwrCPbOi8YkvDQAiW05VQQFvvz9oieQ== + dependencies: + "@types/estree" "*" + +"@types/cookie@^0.4.1": + version "0.4.1" + resolved "https://registry.yarnpkg.com/@types/cookie/-/cookie-0.4.1.tgz#bfd02c1f2224567676c1545199f87c3a861d878d" + integrity sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q== + +"@types/cors@^2.8.12": + version "2.8.19" + resolved "https://registry.yarnpkg.com/@types/cors/-/cors-2.8.19.tgz#d93ea2673fd8c9f697367f5eeefc2bbfa94f0342" + integrity sha512-mFNylyeyqN93lfe/9CSxOGREz8cpzAhH+E93xJ4xWQf62V8sQ/24reV2nyzUWM6H6Xji+GGHpkbLe7pVoUEskg== + dependencies: + "@types/node" "*" + +"@types/debug@^4.0.0": + version "4.1.13" + resolved "https://registry.yarnpkg.com/@types/debug/-/debug-4.1.13.tgz#22d1cc9d542d3593caea764f974306ab36286ee7" + integrity sha512-KSVgmQmzMwPlmtljOomayoR89W4FynCAi3E8PPs7vmDVPe84hT+vGPKkJfThkmXs0x0jAaa9U8uW8bbfyS2fWw== + dependencies: + "@types/ms" "*" + +"@types/es-aggregate-error@^1.0.2": + version "1.0.6" + resolved "https://registry.yarnpkg.com/@types/es-aggregate-error/-/es-aggregate-error-1.0.6.tgz#1472dfb0fb1cb4c3f2bd3b2a7b7e19f60a1d66c0" + integrity sha512-qJ7LIFp06h1QE1aVxbVd+zJP2wdaugYXYfd6JxsyRMrYHaxb6itXPogW2tz+ylUJ1n1b+JF1PHyYCfYHm0dvUg== + dependencies: + "@types/node" "*" + +"@types/estree-jsx@^1.0.0": + version "1.0.5" + resolved "https://registry.yarnpkg.com/@types/estree-jsx/-/estree-jsx-1.0.5.tgz#858a88ea20f34fe65111f005a689fa1ebf70dc18" + integrity sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg== + dependencies: + "@types/estree" "*" + +"@types/estree@*", "@types/estree@^1.0.0": + version "1.0.8" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.8.tgz#958b91c991b1867ced318bedea0e215ee050726e" + integrity sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w== + +"@types/hast@^3.0.0", "@types/hast@^3.0.4": + version "3.0.4" + resolved "https://registry.yarnpkg.com/@types/hast/-/hast-3.0.4.tgz#1d6b39993b82cea6ad783945b0508c25903e15aa" + integrity sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ== + dependencies: + "@types/unist" "*" + +"@types/http-cache-semantics@^4.0.2": + version "4.2.0" + resolved "https://registry.yarnpkg.com/@types/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz#f6a7788f438cbfde15f29acad46512b4c01913b3" + integrity sha512-L3LgimLHXtGkWikKnsPg0/VFx9OGZaC+eN1u4r+OB1XRqH3meBIAVC2zr1WdMH+RHmnRkqliQAOHNJ/E0j/e0Q== + +"@types/json-schema@^7.0.11", "@types/json-schema@^7.0.4", "@types/json-schema@^7.0.7": + version "7.0.15" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841" + integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA== + +"@types/katex@^0.16.0": + version "0.16.8" + resolved "https://registry.yarnpkg.com/@types/katex/-/katex-0.16.8.tgz#80bf3e0814d09a846412a0b0f140946b79c36c3e" + integrity sha512-trgaNyfU+Xh2Tc+ABIb44a5AYUpicB3uwirOioeOkNPPbmgRNtcWyDeeFRzjPZENO9Vq8gvVqfhaaXWLlevVwg== + +"@types/mdast@4.0.4", "@types/mdast@^4.0.0", "@types/mdast@^4.0.4": + version "4.0.4" + resolved "https://registry.yarnpkg.com/@types/mdast/-/mdast-4.0.4.tgz#7ccf72edd2f1aa7dd3437e180c64373585804dd6" + integrity sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA== + dependencies: + "@types/unist" "*" + +"@types/mdx@^2.0.0": + version "2.0.13" + resolved "https://registry.yarnpkg.com/@types/mdx/-/mdx-2.0.13.tgz#68f6877043d377092890ff5b298152b0a21671bd" + integrity sha512-+OWZQfAYyio6YkJb3HLxDrvnx6SWWDbC0zVPfBRzUk0/nqoDyf6dNxQi3eArPe8rJ473nobTMQ/8Zk+LxJ+Yuw== + +"@types/ms@*": + version "2.1.0" + resolved "https://registry.yarnpkg.com/@types/ms/-/ms-2.1.0.tgz#052aa67a48eccc4309d7f0191b7e41434b90bb78" + integrity sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA== + +"@types/nlcst@^2.0.0": + version "2.0.3" + resolved "https://registry.yarnpkg.com/@types/nlcst/-/nlcst-2.0.3.tgz#31cad346eaab48a9a8a58465d3d05e2530dda762" + integrity sha512-vSYNSDe6Ix3q+6Z7ri9lyWqgGhJTmzRjZRqyq15N0Z/1/UnVsno9G/N40NBijoYx2seFDIl0+B2mgAb9mezUCA== + dependencies: + "@types/unist" "*" + +"@types/node@*", "@types/node@>=10.0.0": + version "25.6.0" + resolved "https://registry.yarnpkg.com/@types/node/-/node-25.6.0.tgz#4e09bad9b469871f2d0f68140198cbd714f4edca" + integrity sha512-+qIYRKdNYJwY3vRCZMdJbPLJAtGjQBudzZzdzwQYkEPQd+PJGixUL5QfvCLDaULoLv+RhT3LDkwEfKaAkgSmNQ== + dependencies: + undici-types "~7.19.0" + +"@types/unist@*", "@types/unist@^3.0.0": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@types/unist/-/unist-3.0.3.tgz#acaab0f919ce69cce629c2d4ed2eb4adc1b6c20c" + integrity sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q== + +"@types/unist@^2.0.0": + version "2.0.11" + resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.11.tgz#11af57b127e32487774841f7a4e54eab166d03c4" + integrity sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA== + +"@types/urijs@^1.19.19": + version "1.19.26" + resolved "https://registry.yarnpkg.com/@types/urijs/-/urijs-1.19.26.tgz#500fc9912e0ba01d635480970bdc9ba0f45d7bc6" + integrity sha512-wkXrVzX5yoqLnndOwFsieJA7oKM8cNkOKJtf/3vVGSUFkWDKZvFHpIl9Pvqb/T9UsawBBFMTTD8xu7sK5MWuvg== + +"@types/yauzl@^2.9.1": + version "2.10.3" + resolved "https://registry.yarnpkg.com/@types/yauzl/-/yauzl-2.10.3.tgz#e9b2808b4f109504a03cda958259876f61017999" + integrity sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q== + dependencies: + "@types/node" "*" + +"@typescript/vfs@^1.6.4": + version "1.6.4" + resolved "https://registry.yarnpkg.com/@typescript/vfs/-/vfs-1.6.4.tgz#7543a3bd961727eb51c8bdafc3ed5e0fb5f56dff" + integrity sha512-PJFXFS4ZJKiJ9Qiuix6Dz/OwEIqHD7Dme1UwZhTK11vR+5dqW2ACbdndWQexBzCx+CPuMe5WBYQWCsFyGlQLlQ== + dependencies: + debug "^4.4.3" + +"@ungap/structured-clone@^1.0.0": + version "1.3.0" + resolved "https://registry.yarnpkg.com/@ungap/structured-clone/-/structured-clone-1.3.0.tgz#d06bbb384ebcf6c505fde1c3d0ed4ddffe0aaff8" + integrity sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g== + +abort-controller@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/abort-controller/-/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392" + integrity sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg== + dependencies: + event-target-shim "^5.0.0" + +accepts@~1.3.4, accepts@~1.3.8: + version "1.3.8" + resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" + integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw== + dependencies: + mime-types "~2.1.34" + negotiator "0.6.3" + +acorn-jsx@5.3.2, acorn-jsx@^5.0.0: + version "5.3.2" + resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" + integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== + +acorn@8.11.2: + version "8.11.2" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.11.2.tgz#ca0d78b51895be5390a5903c5b3bdcdaf78ae40b" + integrity sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w== + +acorn@^8.0.0: + version "8.16.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.16.0.tgz#4ce79c89be40afe7afe8f3adb902a1f1ce9ac08a" + integrity sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw== + +address@^1.0.1: + version "1.2.2" + resolved "https://registry.yarnpkg.com/address/-/address-1.2.2.tgz#2b5248dac5485a6390532c6a517fda2e3faac89e" + integrity sha512-4B/qKCfeE/ODUaAUpSwfzazo5x29WD4r3vXiWsB7I2mSDAihwEqKO+g8GELZUQSSAo5e1XTYh3ZVfLyxBc12nA== + +adm-zip@0.5.16: + version "0.5.16" + resolved "https://registry.yarnpkg.com/adm-zip/-/adm-zip-0.5.16.tgz#0b5e4c779f07dedea5805cdccb1147071d94a909" + integrity sha512-TGw5yVi4saajsSEgz25grObGHEUaDrniwvA2qwSC060KfqGPdglhvPMA2lPIoxs3PQIItj2iag35fONcQqgUaQ== + +agent-base@^7.1.0, agent-base@^7.1.2: + version "7.1.4" + resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-7.1.4.tgz#e3cd76d4c548ee895d3c3fd8dc1f6c5b9032e7a8" + integrity sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ== + +aggregate-error@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-4.0.1.tgz#25091fe1573b9e0be892aeda15c7c66a545f758e" + integrity sha512-0poP0T7el6Vq3rstR8Mn4V/IQrpBLO6POkUSrN7RhyY+GF/InCFShQzsQ39T25gkHhLgSLByyAz+Kjb+c2L98w== + dependencies: + clean-stack "^4.0.0" + indent-string "^5.0.0" + +ajv-draft-04@^1.0.0, ajv-draft-04@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/ajv-draft-04/-/ajv-draft-04-1.0.0.tgz#3b64761b268ba0b9e668f0b41ba53fce0ad77fc8" + integrity sha512-mv00Te6nmYbRp5DCwclxtt7yV/joXJPGS7nM+97GdxvuttCOfgI3K4U25zboyeX0O+myI8ERluxQe5wljMmVIw== + +ajv-errors@^3.0.0, ajv-errors@~3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/ajv-errors/-/ajv-errors-3.0.0.tgz#e54f299f3a3d30fe144161e5f0d8d51196c527bc" + integrity sha512-V3wD15YHfHz6y0KdhYFjyy9vWtEVALT9UrxfN3zqlI6dMioHnJrqOYfyPKol3oqrnCM9uwkcdCwkJ0WUcbLMTQ== + +ajv-formats@^2.1.1, ajv-formats@~2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ajv-formats/-/ajv-formats-2.1.1.tgz#6e669400659eb74973bbf2e33327180a0996b520" + integrity sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA== + dependencies: + ajv "^8.0.0" + +ajv-formats@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/ajv-formats/-/ajv-formats-3.0.1.tgz#3d5dc762bca17679c3c2ea7e90ad6b7532309578" + integrity sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ== + dependencies: + ajv "^8.0.0" + +ajv@^8.0.0, ajv@^8.17.1, ajv@^8.18.0: + version "8.18.0" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.18.0.tgz#8864186b6738d003eb3a933172bb3833e10cefbc" + integrity sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A== + dependencies: + fast-deep-equal "^3.1.3" + fast-uri "^3.0.1" + json-schema-traverse "^1.0.0" + require-from-string "^2.0.2" + +ansi-escapes@^4.3.2: + version "4.3.2" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" + integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ== + dependencies: + type-fest "^0.21.3" + +ansi-escapes@^7.0.0: + version "7.3.0" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-7.3.0.tgz#5395bb74b2150a4a1d6e3c2565f4aeca78d28627" + integrity sha512-BvU8nYgGQBxcmMuEeUEmNTvrMVjJNSH7RgW24vXexN4Ven6qCvy4TntnvlnwnMLTVlcRQQdbRY8NKnaIoeWDNg== + dependencies: + environment "^1.0.0" + +ansi-regex@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" + integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== + +ansi-regex@^6.2.2: + version "6.2.2" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.2.2.tgz#60216eea464d864597ce2832000738a0589650c1" + integrity sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg== + +ansi-styles@^4.0.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" + integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== + dependencies: + color-convert "^2.0.1" + +ansi-styles@^6.0.0, ansi-styles@^6.2.1: + version "6.2.3" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.3.tgz#c044d5dcc521a076413472597a1acb1f103c4041" + integrity sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg== + +any-promise@^1.0.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f" + integrity sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A== + +anymatch@~3.1.2: + version "3.1.3" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" + integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== + dependencies: + normalize-path "^3.0.0" + picomatch "^2.0.4" + +arg@^5.0.2: + version "5.0.2" + resolved "https://registry.yarnpkg.com/arg/-/arg-5.0.2.tgz#c81433cc427c92c4dcf4865142dbca6f15acd59c" + integrity sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg== + +argparse@^1.0.7: + version "1.0.10" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" + integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== + dependencies: + sprintf-js "~1.0.2" + +argparse@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" + integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== + +arkregex@0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/arkregex/-/arkregex-0.0.3.tgz#2e2bdce5223e737cc134e4b0c9f228111d8cca57" + integrity sha512-bU21QJOJEFJK+BPNgv+5bVXkvRxyAvgnon75D92newgHxkBJTgiFwQxusyViYyJkETsddPlHyspshDQcCzmkNg== + dependencies: + "@ark/util" "0.55.0" + +arkregex@0.0.5: + version "0.0.5" + resolved "https://registry.yarnpkg.com/arkregex/-/arkregex-0.0.5.tgz#0a2d5f6ae11de6b6200f2326f65960f85dac62fb" + integrity sha512-ncYjBdLlh5/QnVsAA8De16Tc9EqmYM7y/WU9j+236KcyYNUXogpz3sC4ATIZYzzLxwI+0sEOaQLEmLmRleaEXw== + dependencies: + "@ark/util" "0.56.0" + +arktype@2.1.27: + version "2.1.27" + resolved "https://registry.yarnpkg.com/arktype/-/arktype-2.1.27.tgz#882f5ef93d05d292a10db0ad31cd37fa46efe048" + integrity sha512-enctOHxI4SULBv/TDtCVi5M8oLd4J5SVlPUblXDzSsOYQNMzmVbUosGBnJuZDKmFlN5Ie0/QVEuTE+Z5X1UhsQ== + dependencies: + "@ark/schema" "0.55.0" + "@ark/util" "0.55.0" + arkregex "0.0.3" + +arktype@^2.1.26: + version "2.2.0" + resolved "https://registry.yarnpkg.com/arktype/-/arktype-2.2.0.tgz#883788f0e8948e4242e17e36ecdf0c066d9ed0e8" + integrity sha512-t54MZ7ti5BhOEvzEkgKnWvqj+UbDfWig+DHr5I34xatymPusKLS0lQpNJd8M6DzmIto2QGszHfNKoFIT8tMCZQ== + dependencies: + "@ark/schema" "0.56.0" + "@ark/util" "0.56.0" + arkregex "0.0.5" + +array-buffer-byte-length@^1.0.1, array-buffer-byte-length@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz#384d12a37295aec3769ab022ad323a18a51ccf8b" + integrity sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw== + dependencies: + call-bound "^1.0.3" + is-array-buffer "^3.0.5" + +array-flatten@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" + integrity sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg== + +array-iterate@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/array-iterate/-/array-iterate-2.0.1.tgz#6efd43f8295b3fee06251d3d62ead4bd9805dd24" + integrity sha512-I1jXZMjAgCMmxT4qxXfPXa6SthSoE8h6gkSI9BGGNv8mP8G/v0blc+qFnZu6K42vTOiuME596QaLO0TP3Lk0xg== + +arraybuffer.prototype.slice@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.4.tgz#9d760d84dbdd06d0cbf92c8849615a1a7ab3183c" + integrity sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ== + dependencies: + array-buffer-byte-length "^1.0.1" + call-bind "^1.0.8" + define-properties "^1.2.1" + es-abstract "^1.23.5" + es-errors "^1.3.0" + get-intrinsic "^1.2.6" + is-array-buffer "^3.0.4" + +ast-types@^0.13.4: + version "0.13.4" + resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.13.4.tgz#ee0d77b343263965ecc3fb62da16e7222b2b6782" + integrity sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w== + dependencies: + tslib "^2.0.1" + +astring@^1.8.0, astring@^1.8.1: + version "1.9.0" + resolved "https://registry.yarnpkg.com/astring/-/astring-1.9.0.tgz#cc73e6062a7eb03e7d19c22d8b0b3451fd9bfeef" + integrity sha512-LElXdjswlqjWrPpJFg1Fx4wpkOCxj1TDHlSV4PlaRxHGWko024xICaa97ZkMfs6DRKlCguiAI+rbXv5GWwXIkg== + +async-function@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/async-function/-/async-function-1.0.0.tgz#509c9fca60eaf85034c6829838188e4e4c8ffb2b" + integrity sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA== + +asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== + +auto-bind@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/auto-bind/-/auto-bind-5.0.1.tgz#50d8e63ea5a1dddcb5e5e36451c1a8266ffbb2ae" + integrity sha512-ooviqdwwgfIfNmDwo94wlshcdzfO64XV0Cg6oDsDYBJfITDz1EngD2z7DkbvCWn+XIMsIqW27sEVF6qcpJrRcg== + +available-typed-arrays@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz#a5cc375d6a03c2efc87a553f3e0b1522def14846" + integrity sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ== + dependencies: + possible-typed-array-names "^1.0.0" + +avsc@^5.7.5: + version "5.7.9" + resolved "https://registry.yarnpkg.com/avsc/-/avsc-5.7.9.tgz#8532cd47b2fbff95be4bc470c6780c258d86680a" + integrity sha512-yOA4wFeI7ET3v32Di/sUybQ+ttP20JHSW3mxLuNGeO0uD6PPcvLrIQXSvy/rhJOWU5JrYh7U4OHplWMmtAtjMg== + +axios@1.10.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/axios/-/axios-1.10.0.tgz#af320aee8632eaf2a400b6a1979fa75856f38d54" + integrity sha512-/1xYAC4MP/HEG+3duIhFr4ZQXR4sQXOIe+o6sdqzeykGLx6Upp/1p8MHqhINOvGeP7xyNHe7tsiJByc4SSVUxw== + dependencies: + follow-redirects "^1.15.6" + form-data "^4.0.0" + proxy-from-env "^1.1.0" + +axios@1.13.2: + version "1.13.2" + resolved "https://registry.yarnpkg.com/axios/-/axios-1.13.2.tgz#9ada120b7b5ab24509553ec3e40123521117f687" + integrity sha512-VPk9ebNqPcy5lRGuSlKx752IlDatOjT9paPlm8A7yOuW2Fbvp4X3JznJtT4f0GzGLLiWE9W8onz51SqLYwzGaA== + dependencies: + follow-redirects "^1.15.6" + form-data "^4.0.4" + proxy-from-env "^1.1.0" + +b4a@^1.6.4: + version "1.8.0" + resolved "https://registry.yarnpkg.com/b4a/-/b4a-1.8.0.tgz#1ca3ba0edc9469aaabef5647e769a83d50180b1a" + integrity sha512-qRuSmNSkGQaHwNbM7J78Wwy+ghLEYF1zNrSeMxj4Kgw6y33O3mXcQ6Ie9fRvfU/YnxWkOchPXbaLb73TkIsfdg== + +bail@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/bail/-/bail-2.0.2.tgz#d26f5cd8fe5d6f832a31517b9f7c356040ba6d5d" + integrity sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw== + +balanced-match@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" + integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== + +bare-events@^2.5.4, bare-events@^2.7.0: + version "2.8.2" + resolved "https://registry.yarnpkg.com/bare-events/-/bare-events-2.8.2.tgz#7b3e10bd8e1fc80daf38bb516921678f566ab89f" + integrity sha512-riJjyv1/mHLIPX4RwiK+oW9/4c3TEUeORHKefKAKnZ5kyslbN+HXowtbaVEqt4IMUB7OXlfixcs6gsFeo/jhiQ== + +bare-fs@^4.0.1, bare-fs@^4.5.5: + version "4.7.1" + resolved "https://registry.yarnpkg.com/bare-fs/-/bare-fs-4.7.1.tgz#6e81f784761102867c13f0823aa48c942d160f00" + integrity sha512-WDRsyVN52eAx/lBamKD6uyw8H4228h/x0sGGGegOamM2cd7Pag88GfMQalobXI+HaEUxpCkbKQUDOQqt9wawRw== + dependencies: + bare-events "^2.5.4" + bare-path "^3.0.0" + bare-stream "^2.6.4" + bare-url "^2.2.2" + fast-fifo "^1.3.2" + +bare-os@^3.0.1: + version "3.9.0" + resolved "https://registry.yarnpkg.com/bare-os/-/bare-os-3.9.0.tgz#59b1dd75c231067526f811c0e3d985257bd35747" + integrity sha512-JTjuZyNIDpw+GytMO4a6TK1VXdVKKJr6DRxEHasyuYyShV2deuiHJK/ahGZlebc+SG0/wJCB9XK8gprBGDFi/Q== + +bare-path@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/bare-path/-/bare-path-3.0.0.tgz#b59d18130ba52a6af9276db3e96a2e3d3ea52178" + integrity sha512-tyfW2cQcB5NN8Saijrhqn0Zh7AnFNsnczRcuWODH0eYAXBsJ5gVxAUuNr7tsHSC6IZ77cA0SitzT+s47kot8Mw== + dependencies: + bare-os "^3.0.1" + +bare-stream@^2.6.4: + version "2.13.0" + resolved "https://registry.yarnpkg.com/bare-stream/-/bare-stream-2.13.0.tgz#dea59458dcf2689e9387134efccec015dfdbe3cf" + integrity sha512-3zAJRZMDFGjdn+RVnNpF9kuELw+0Fl3lpndM4NcEOhb9zwtSo/deETfuIwMSE5BXanA0FrN1qVjffGwAg2Y7EA== + dependencies: + streamx "^2.25.0" + teex "^1.0.1" + +bare-url@^2.2.2: + version "2.4.2" + resolved "https://registry.yarnpkg.com/bare-url/-/bare-url-2.4.2.tgz#1faab7d8f1780f6e51d5db03711dc390460874c0" + integrity sha512-/9a2j4ac6ckpmAHvod/ob7x439OAHst/drc2Clnq+reRYd/ovddwcF4LfoxHyNk5AuGBnPg+HqFjmE/Zpq6v0A== + dependencies: + bare-path "^3.0.0" + +base64-js@^1.3.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" + integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== + +base64id@2.0.0, base64id@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/base64id/-/base64id-2.0.0.tgz#2770ac6bc47d312af97a8bf9a634342e0cd25cb6" + integrity sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog== + +basic-ftp@^5.0.2: + version "5.3.0" + resolved "https://registry.yarnpkg.com/basic-ftp/-/basic-ftp-5.3.0.tgz#88f057d1ba8442643c505c4c83bbaa4442b15cfd" + integrity sha512-5K9eNNn7ywHPsYnFwjKgYH8Hf8B5emh7JKcPaVjjrMJFQQwGpwowEnZNEtHs7DfR7hCZsmaK3VA4HUK0YarT+w== + +better-opn@3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/better-opn/-/better-opn-3.0.2.tgz#f96f35deaaf8f34144a4102651babcf00d1d8817" + integrity sha512-aVNobHnJqLiUelTaHat9DZ1qM2w0C0Eym4LPI/3JxOnSokGVdsl1T1kN7TFvsEAD8G47A6VKQ0TVHqbBnYMJlQ== + dependencies: + open "^8.0.4" + +binary-extensions@^2.0.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.3.0.tgz#f6e14a97858d327252200242d4ccfe522c445522" + integrity sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw== + +bl@^4.0.3: + version "4.1.0" + resolved "https://registry.yarnpkg.com/bl/-/bl-4.1.0.tgz#451535264182bec2fbbc83a62ab98cf11d9f7b3a" + integrity sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w== + dependencies: + buffer "^5.5.0" + inherits "^2.0.4" + readable-stream "^3.4.0" + +body-parser@1.20.1: + version "1.20.1" + resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.1.tgz#b1812a8912c195cd371a3ee5e66faa2338a5c668" + integrity sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw== + dependencies: + 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.11.0" + raw-body "2.5.1" + type-is "~1.6.18" + unpipe "1.0.0" + +brace-expansion@^1.1.7: + version "1.1.14" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.14.tgz#d9de602370d91347cd9ddad1224d4fd701eb348b" + integrity sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g== + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +braces@^3.0.3, braces@~3.0.2: + version "3.0.3" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789" + integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA== + dependencies: + fill-range "^7.1.1" + +buffer-crc32@~0.2.3: + version "0.2.13" + resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242" + integrity sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ== + +buffer@^5.2.1, buffer@^5.5.0: + version "5.7.1" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" + integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== + dependencies: + base64-js "^1.3.1" + ieee754 "^1.1.13" + +bytes@3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" + integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== + +cacheable-lookup@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/cacheable-lookup/-/cacheable-lookup-7.0.0.tgz#3476a8215d046e5a3202a9209dd13fec1f933a27" + integrity sha512-+qJyx4xiKra8mZrcwhjMRMUhD5NR1R8esPkzIYxX96JiecFoxAXFuz/GpR3+ev4PE1WamHip78wV0vcmPQtp8w== + +cacheable-request@^10.2.8: + version "10.2.14" + resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-10.2.14.tgz#eb915b665fda41b79652782df3f553449c406b9d" + integrity sha512-zkDT5WAF4hSSoUgyfg5tFIxz8XQK+25W/TLVojJTMKBaxevLBBtLxgqguAuVQB8PVW79FVjHcU+GJ9tVbDZ9mQ== + dependencies: + "@types/http-cache-semantics" "^4.0.2" + get-stream "^6.0.1" + http-cache-semantics "^4.1.1" + keyv "^4.5.3" + mimic-response "^4.0.0" + normalize-url "^8.0.0" + responselike "^3.0.0" + +call-bind-apply-helpers@^1.0.1, call-bind-apply-helpers@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz#4b5428c222be985d79c3d82657479dbe0b59b2d6" + integrity sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ== + dependencies: + es-errors "^1.3.0" + function-bind "^1.1.2" + +call-bind@^1.0.7, call-bind@^1.0.8, call-bind@^1.0.9: + version "1.0.9" + resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.9.tgz#39a644700c80bc7d0ca9102fc6d1d43b2fd7eee7" + integrity sha512-a/hy+pNsFUTR+Iz8TCJvXudKVLAnz/DyeSUo10I5yvFDQJBFU2s9uqQpoSrJlroHUKoKqzg+epxyP9lqFdzfBQ== + dependencies: + call-bind-apply-helpers "^1.0.2" + es-define-property "^1.0.1" + get-intrinsic "^1.3.0" + set-function-length "^1.2.2" + +call-bound@^1.0.2, call-bound@^1.0.3, call-bound@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/call-bound/-/call-bound-1.0.4.tgz#238de935d2a2a692928c538c7ccfa91067fd062a" + integrity sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg== + dependencies: + call-bind-apply-helpers "^1.0.2" + get-intrinsic "^1.3.0" + +callsites@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" + integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== + +camelcase-css@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/camelcase-css/-/camelcase-css-2.0.1.tgz#ee978f6947914cc30c6b44741b6ed1df7f043fd5" + integrity sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA== + +ccount@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/ccount/-/ccount-2.0.1.tgz#17a3bf82302e0870d6da43a01311a8bc02a3ecf5" + integrity sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg== + +chalk@5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-5.2.0.tgz#249623b7d66869c673699fb66d65723e54dfcfb3" + integrity sha512-ree3Gqw/nazQAPuJJEy+avdl7QfZMcUvmHIKgEZkGL+xOBzRvup5Hxo6LHuMceSxOabuJLJm5Yp/92R9eMmMvA== + +chalk@5.3.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-5.3.0.tgz#67c20a7ebef70e7f3970a01f90fa210cb6860385" + integrity sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w== + +chalk@^5.6.0: + version "5.6.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-5.6.2.tgz#b1238b6e23ea337af71c7f8a295db5af0c158aea" + integrity sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA== + +character-entities-html4@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/character-entities-html4/-/character-entities-html4-2.1.0.tgz#1f1adb940c971a4b22ba39ddca6b618dc6e56b2b" + integrity sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA== + +character-entities-legacy@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz#76bc83a90738901d7bc223a9e93759fdd560125b" + integrity sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ== + +character-entities@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/character-entities/-/character-entities-2.0.2.tgz#2d09c2e72cd9523076ccb21157dff66ad43fcc22" + integrity sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ== + +character-reference-invalid@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/character-reference-invalid/-/character-reference-invalid-2.0.1.tgz#85c66b041e43b47210faf401278abf808ac45cb9" + integrity sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw== + +chardet@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/chardet/-/chardet-2.1.1.tgz#5c75593704a642f71ee53717df234031e65373c8" + integrity sha512-PsezH1rqdV9VvyNhxxOW32/d75r01NY7TQCmOqomRo15ZSOKbpTFVsfjghxo6JloQUCGnH4k1LGu0R4yCLlWQQ== + +chokidar@3.5.3: + version "3.5.3" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" + integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== + dependencies: + anymatch "~3.1.2" + braces "~3.0.2" + glob-parent "~5.1.2" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.6.0" + optionalDependencies: + fsevents "~2.3.2" + +chokidar@^3.5.3, chokidar@^3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.6.0.tgz#197c6cc669ef2a8dc5e7b4d97ee4e092c3eb0d5b" + integrity sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw== + dependencies: + anymatch "~3.1.2" + braces "~3.0.2" + glob-parent "~5.1.2" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.6.0" + optionalDependencies: + fsevents "~2.3.2" + +chownr@^1.1.1: + version "1.1.4" + resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b" + integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg== + +chownr@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/chownr/-/chownr-2.0.0.tgz#15bfbe53d2eab4cf70f18a8cd68ebe5b3cb1dece" + integrity sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ== + +chromium-bidi@0.6.2: + version "0.6.2" + resolved "https://registry.yarnpkg.com/chromium-bidi/-/chromium-bidi-0.6.2.tgz#91f9daa20984833b52221084480fbe0465b29c67" + integrity sha512-4WVBa6ijmUTVr9cZD4eicQD8Mdy/HCX3bzEIYYpmk0glqYLoWH+LqQEvV9RpDRzoQSbY1KJHloYXbDMXMbDPhg== + dependencies: + mitt "3.0.1" + urlpattern-polyfill "10.0.0" + zod "3.23.8" + +clean-stack@^4.0.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-4.2.0.tgz#c464e4cde4ac789f4e0735c5d75beb49d7b30b31" + integrity sha512-LYv6XPxoyODi36Dp976riBtSY27VmFo+MKqEU9QCCWyTrdEPDog+RWA7xQWHi6Vbp61j5c4cdzzX1NidnwtUWg== + dependencies: + escape-string-regexp "5.0.0" + +cli-boxes@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-3.0.0.tgz#71a10c716feeba005e4504f36329ef0b17cf3145" + integrity sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g== + +cli-cursor@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-4.0.0.tgz#3cecfe3734bf4fe02a8361cbdc0f6fe28c6a57ea" + integrity sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg== + dependencies: + restore-cursor "^4.0.0" + +cli-spinners@^2.7.0: + version "2.9.2" + resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.9.2.tgz#1773a8f4b9c4d6ac31563df53b3fc1d79462fe41" + integrity sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg== + +cli-truncate@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/cli-truncate/-/cli-truncate-4.0.0.tgz#6cc28a2924fee9e25ce91e973db56c7066e6172a" + integrity sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA== + dependencies: + slice-ansi "^5.0.0" + string-width "^7.0.0" + +cli-width@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-4.1.0.tgz#42daac41d3c254ef38ad8ac037672130173691c5" + integrity sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ== + +cliui@^8.0.1: + version "8.0.1" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-8.0.1.tgz#0c04b075db02cbfe60dc8e6cf2f5486b1a3608aa" + integrity sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.1" + wrap-ansi "^7.0.0" + +code-excerpt@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/code-excerpt/-/code-excerpt-4.0.0.tgz#2de7d46e98514385cb01f7b3b741320115f4c95e" + integrity sha512-xxodCmBen3iy2i0WtAK8FlFNrRzjUqjRsMfho58xT/wvZU1YTM3fCnRjcy1gJPMepaRlgm/0e6w8SpWHpn3/cA== + dependencies: + convert-to-spaces "^2.0.1" + +collapse-white-space@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/collapse-white-space/-/collapse-white-space-2.1.0.tgz#640257174f9f42c740b40f3b55ee752924feefca" + integrity sha512-loKTxY1zCOuG4j9f6EPnuyyYkf58RnhhWTvRoZEokgB+WbdXehfjFviyOVYkqzEWz1Q5kRiZdBYS5SwxbQYwzw== + +color-blend@4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/color-blend/-/color-blend-4.0.0.tgz#e9950e9fa5d6e552ff8bb107c39f7e83a0c1a3bb" + integrity sha512-fYODTHhI/NG+B5GnzvuL3kiFrK/UnkUezWFTgEPBTY5V+kpyfAn95Vn9sJeeCX6omrCOdxnqCL3CvH+6sXtIbw== + +color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + dependencies: + color-name "~1.1.4" + +color-name@^1.0.0, color-name@~1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" + integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + +color-string@^1.9.0: + version "1.9.1" + resolved "https://registry.yarnpkg.com/color-string/-/color-string-1.9.1.tgz#4467f9146f036f855b764dfb5bf8582bf342c7a4" + integrity sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg== + dependencies: + color-name "^1.0.0" + simple-swizzle "^0.2.2" + +color@4.2.3, color@^4.2.3: + version "4.2.3" + resolved "https://registry.yarnpkg.com/color/-/color-4.2.3.tgz#d781ecb5e57224ee43ea9627560107c0e0c6463a" + integrity sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A== + dependencies: + color-convert "^2.0.1" + color-string "^1.9.0" + +combined-stream@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" + integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== + dependencies: + delayed-stream "~1.0.0" + +comma-separated-tokens@^2.0.0: + version "2.0.3" + resolved "https://registry.yarnpkg.com/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz#4e89c9458acb61bc8fef19f4529973b2392839ee" + integrity sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg== + +commander@^2.20.3: + version "2.20.3" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" + integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== + +commander@^4.0.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/commander/-/commander-4.1.1.tgz#9fd602bd936294e9e9ef46a3f4d6964044b18068" + integrity sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA== + +commander@^8.3.0: + version "8.3.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-8.3.0.tgz#4837ea1b2da67b9c616a67afbb0fafee567bca66" + integrity sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww== + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== + +content-disposition@0.5.4: + version "0.5.4" + resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.4.tgz#8b82b4efac82512a02bb0b1dcec9d2c5e8eb5bfe" + integrity sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ== + dependencies: + safe-buffer "5.2.1" + +content-type@~1.0.4: + version "1.0.5" + resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.5.tgz#8b773162656d1d1086784c8f23a54ce6d73d7918" + integrity sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA== + +convert-to-spaces@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/convert-to-spaces/-/convert-to-spaces-2.0.1.tgz#61a6c98f8aa626c16b296b862a91412a33bceb6b" + integrity sha512-rcQ1bsQO9799wq24uE5AM2tAILy4gXGIK/njFWcVQkGNZ96edlpY+A7bjwvzjYvLDyzmG1MmMLZhpcsb+klNMQ== + +cookie-signature@1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" + integrity sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ== + +cookie@0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.5.0.tgz#d1f5d71adec6558c58f389987c366aa47e994f8b" + integrity sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw== + +cookie@~0.4.1: + version "0.4.2" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.2.tgz#0e41f24de5ecf317947c82fc789e06a884824432" + integrity sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA== + +cors@~2.8.5: + version "2.8.6" + resolved "https://registry.yarnpkg.com/cors/-/cors-2.8.6.tgz#ff5dd69bd95e547503820d29aba4f8faf8dfec96" + integrity sha512-tJtZBBHA6vjIAaF6EnIaq6laBBP9aq/Y3ouVJjEfoHbRBcHBAHYcMh/w8LDrk2PvIMMq8gmopa5D4V8RmbrxGw== + dependencies: + object-assign "^4" + vary "^1" + +cosmiconfig@^9.0.0: + version "9.0.1" + resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-9.0.1.tgz#df110631a8547b5d1a98915271986f06e3011379" + integrity sha512-hr4ihw+DBqcvrsEDioRO31Z17x71pUYoNe/4h6Z0wB72p7MU7/9gH8Q3s12NFhHPfYBBOV3qyfUxmr/Yn3shnQ== + dependencies: + env-paths "^2.2.1" + import-fresh "^3.3.0" + js-yaml "^4.1.0" + parse-json "^5.2.0" + +cross-spawn@^7.0.6: + version "7.0.6" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.6.tgz#8a58fe78f00dcd70c370451759dfbfaf03e8ee9f" + integrity sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA== + dependencies: + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" + +cssesc@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee" + integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg== + +cssfilter@0.0.10: + version "0.0.10" + resolved "https://registry.yarnpkg.com/cssfilter/-/cssfilter-0.0.10.tgz#c6d2672632a2e5c83e013e6864a42ce8defd20ae" + integrity sha512-FAaLDaplstoRsDR8XGYH51znUN0UY7nMc6Z9/fvE8EXGwvJE9hu7W2vHwx1+bd6gCYnln9nLbzxFTrcO9YQDZw== + +data-uri-to-buffer@^6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/data-uri-to-buffer/-/data-uri-to-buffer-6.0.2.tgz#8a58bb67384b261a38ef18bea1810cb01badd28b" + integrity sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw== + +data-view-buffer@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/data-view-buffer/-/data-view-buffer-1.0.2.tgz#211a03ba95ecaf7798a8c7198d79536211f88570" + integrity sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ== + dependencies: + call-bound "^1.0.3" + es-errors "^1.3.0" + is-data-view "^1.0.2" + +data-view-byte-length@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/data-view-byte-length/-/data-view-byte-length-1.0.2.tgz#9e80f7ca52453ce3e93d25a35318767ea7704735" + integrity sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ== + dependencies: + call-bound "^1.0.3" + es-errors "^1.3.0" + is-data-view "^1.0.2" + +data-view-byte-offset@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz#068307f9b71ab76dbbe10291389e020856606191" + integrity sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ== + dependencies: + call-bound "^1.0.2" + es-errors "^1.3.0" + is-data-view "^1.0.1" + +debug@2.6.9: + version "2.6.9" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" + integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== + dependencies: + ms "2.0.0" + +debug@4, debug@^4.0.0, debug@^4.1.1, debug@^4.3.4, debug@^4.3.5, debug@^4.4.3, debug@~4.4.1: + version "4.4.3" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.3.tgz#c6ae432d9bd9662582fce08709b038c58e9e3d6a" + integrity sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA== + dependencies: + ms "^2.1.3" + +debug@~4.3.1, debug@~4.3.2: + version "4.3.7" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.7.tgz#87945b4151a011d76d95a198d7111c865c360a52" + integrity sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ== + dependencies: + ms "^2.1.3" + +decode-bmp@^0.2.0: + version "0.2.1" + resolved "https://registry.yarnpkg.com/decode-bmp/-/decode-bmp-0.2.1.tgz#cec3e0197ec3b6c60f02220f50e8757030ff2427" + integrity sha512-NiOaGe+GN0KJqi2STf24hfMkFitDUaIoUU3eKvP/wAbLe8o6FuW5n/x7MHPR0HKvBokp6MQY/j7w8lewEeVCIA== + dependencies: + "@canvas/image-data" "^1.0.0" + to-data-view "^1.1.0" + +decode-ico@*: + version "0.4.1" + resolved "https://registry.yarnpkg.com/decode-ico/-/decode-ico-0.4.1.tgz#e0f7373081532c7b8495bd51fb225d354e14de25" + integrity sha512-69NZfbKIzux1vBOd31al3XnMnH+2mqDhEgLdpygErm4d60N+UwA5Sq5WFjmEDQzumgB9fElojGwWG0vybVfFmA== + dependencies: + "@canvas/image-data" "^1.0.0" + decode-bmp "^0.2.0" + to-data-view "^1.1.0" + +decode-named-character-reference@^1.0.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/decode-named-character-reference/-/decode-named-character-reference-1.3.0.tgz#3e40603760874c2e5867691b599d73a7da25b53f" + integrity sha512-GtpQYB283KrPp6nRw50q3U9/VfOutZOe103qlN7BPP6Ad27xYnOIWv4lPzo8HCAL+mMZofJ9KEy30fq6MfaK6Q== + dependencies: + character-entities "^2.0.0" + +decompress-response@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-6.0.0.tgz#ca387612ddb7e104bd16d85aab00d5ecf09c66fc" + integrity sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ== + dependencies: + mimic-response "^3.1.0" + +deep-extend@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" + integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== + +defer-to-connect@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-2.0.1.tgz#8016bdb4143e4632b77a3449c6236277de520587" + integrity sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg== + +define-data-property@^1.0.1, define-data-property@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/define-data-property/-/define-data-property-1.1.4.tgz#894dc141bb7d3060ae4366f6a0107e68fbe48c5e" + integrity sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A== + dependencies: + es-define-property "^1.0.0" + es-errors "^1.3.0" + gopd "^1.0.1" + +define-lazy-prop@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz#3f7ae421129bcaaac9bc74905c98a0009ec9ee7f" + integrity sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og== + +define-properties@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.2.1.tgz#10781cc616eb951a80a034bafcaa7377f6af2b6c" + integrity sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg== + dependencies: + define-data-property "^1.0.1" + has-property-descriptors "^1.0.0" + object-keys "^1.1.1" + +degenerator@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/degenerator/-/degenerator-5.0.1.tgz#9403bf297c6dad9a1ece409b37db27954f91f2f5" + integrity sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ== + dependencies: + ast-types "^0.13.4" + escodegen "^2.1.0" + esprima "^4.0.1" + +delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== + +depd@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" + integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== + +dependency-graph@0.11.0, dependency-graph@~0.11.0: + version "0.11.0" + resolved "https://registry.yarnpkg.com/dependency-graph/-/dependency-graph-0.11.0.tgz#ac0ce7ed68a54da22165a85e97a01d53f5eb2e27" + integrity sha512-JeMq7fEshyepOWDfcfHK06N3MhyPhz++vtqWhMT5O9A3K42rdsEDpfdVqjaqaAhsw6a+ZqeDvQVtD0hFHQWrzg== + +dequal@^2.0.0: + version "2.0.3" + resolved "https://registry.yarnpkg.com/dequal/-/dequal-2.0.3.tgz#2644214f1997d39ed0ee0ece72335490a7ac67be" + integrity sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA== + +destroy@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015" + integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg== + +detect-libc@^2.0.0, detect-libc@^2.0.3, detect-libc@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-2.1.2.tgz#689c5dcdc1900ef5583a4cb9f6d7b473742074ad" + integrity sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ== + +detect-port@1.5.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/detect-port/-/detect-port-1.5.1.tgz#451ca9b6eaf20451acb0799b8ab40dff7718727b" + integrity sha512-aBzdj76lueB6uUst5iAs7+0H/oOjqI5D16XUWxlWMIMROhcM0rfsNVk93zTngq1dDNpoXRr++Sus7ETAExppAQ== + dependencies: + address "^1.0.1" + debug "4" + +devlop@^1.0.0, devlop@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/devlop/-/devlop-1.1.0.tgz#4db7c2ca4dc6e0e834c30be70c94bbc976dc7018" + integrity sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA== + dependencies: + dequal "^2.0.0" + +devtools-protocol@0.0.1312386: + version "0.0.1312386" + resolved "https://registry.yarnpkg.com/devtools-protocol/-/devtools-protocol-0.0.1312386.tgz#5ab824d6f1669ec6c6eb0fba047e73601d969052" + integrity sha512-DPnhUXvmvKT2dFA/j7B+riVLUt9Q6RKJlcppojL5CoRywJJKLDYnRlw0gTFKfgDPHP5E04UoB71SxoJlVZy8FA== + +didyoumean@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/didyoumean/-/didyoumean-1.2.2.tgz#989346ffe9e839b4555ecf5666edea0d3e8ad037" + integrity sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw== + +dlv@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/dlv/-/dlv-1.1.3.tgz#5c198a8a11453596e751494d49874bc7732f2e79" + integrity sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA== + +dns-packet@^5.2.4: + version "5.6.1" + resolved "https://registry.yarnpkg.com/dns-packet/-/dns-packet-5.6.1.tgz#ae888ad425a9d1478a0674256ab866de1012cf2f" + integrity sha512-l4gcSouhcgIKRvyy99RNVOgxXiicE+2jZoNmaNmZ6JXiGajBOJAesk1OBlJuM5k2c+eudGdLxDqXuPCKIj6kpw== + dependencies: + "@leichtgewicht/ip-codec" "^2.0.1" + +dns-socket@^4.2.2: + version "4.2.2" + resolved "https://registry.yarnpkg.com/dns-socket/-/dns-socket-4.2.2.tgz#58b0186ec053ea0731feb06783c7eeac4b95b616" + integrity sha512-BDeBd8najI4/lS00HSKpdFia+OvUMytaVjfzR9n5Lq8MlZRSvtbI+uLtx1+XmQFls5wFU9dssccTmQQ6nfpjdg== + dependencies: + dns-packet "^5.2.4" + +dunder-proto@^1.0.0, dunder-proto@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/dunder-proto/-/dunder-proto-1.0.1.tgz#d7ae667e1dc83482f8b70fd0f6eefc50da30f58a" + integrity sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A== + dependencies: + call-bind-apply-helpers "^1.0.1" + es-errors "^1.3.0" + gopd "^1.2.0" + +ee-first@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" + integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== + +emoji-regex@^10.3.0: + version "10.6.0" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-10.6.0.tgz#bf3d6e8f7f8fd22a65d9703475bc0147357a6b0d" + integrity sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A== + +emoji-regex@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" + integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== + +encodeurl@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" + integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w== + +end-of-stream@^1.1.0, end-of-stream@^1.4.1: + version "1.4.5" + resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.5.tgz#7344d711dea40e0b74abc2ed49778743ccedb08c" + integrity sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg== + dependencies: + once "^1.4.0" + +engine.io-parser@~5.2.1: + version "5.2.3" + resolved "https://registry.yarnpkg.com/engine.io-parser/-/engine.io-parser-5.2.3.tgz#00dc5b97b1f233a23c9398d0209504cf5f94d92f" + integrity sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q== + +engine.io@~6.5.2: + version "6.5.5" + resolved "https://registry.yarnpkg.com/engine.io/-/engine.io-6.5.5.tgz#430b80d8840caab91a50e9e23cb551455195fc93" + integrity sha512-C5Pn8Wk+1vKBoHghJODM63yk8MvrO9EWZUfkAt5HAqIgPE4/8FF0PEGHXtEd40l223+cE5ABWuPzm38PHFXfMA== + dependencies: + "@types/cookie" "^0.4.1" + "@types/cors" "^2.8.12" + "@types/node" ">=10.0.0" + accepts "~1.3.4" + base64id "2.0.0" + cookie "~0.4.1" + cors "~2.8.5" + debug "~4.3.1" + engine.io-parser "~5.2.1" + ws "~8.17.1" + +entities@^6.0.0: + version "6.0.1" + resolved "https://registry.yarnpkg.com/entities/-/entities-6.0.1.tgz#c28c34a43379ca7f61d074130b2f5f7020a30694" + integrity sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g== + +env-paths@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-2.2.1.tgz#420399d416ce1fbe9bc0a07c62fa68d67fd0f8f2" + integrity sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A== + +environment@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/environment/-/environment-1.1.0.tgz#8e86c66b180f363c7ab311787e0259665f45a9f1" + integrity sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q== + +error-ex@^1.3.1: + version "1.3.4" + resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.4.tgz#b3a8d8bb6f92eecc1629e3e27d3c8607a8a32414" + integrity sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ== + dependencies: + is-arrayish "^0.2.1" + +es-abstract@^1.23.5, es-abstract@^1.23.9, es-abstract@^1.24.0: + version "1.24.2" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.24.2.tgz#2dbd38c180735ee983f77585140a2706a963ed9a" + integrity sha512-2FpH9Q5i2RRwyEP1AylXe6nYLR5OhaJTZwmlcP0dL/+JCbgg7yyEo/sEK6HeGZRf3dFpWwThaRHVApXSkW3xeg== + dependencies: + array-buffer-byte-length "^1.0.2" + arraybuffer.prototype.slice "^1.0.4" + available-typed-arrays "^1.0.7" + call-bind "^1.0.8" + call-bound "^1.0.4" + data-view-buffer "^1.0.2" + data-view-byte-length "^1.0.2" + data-view-byte-offset "^1.0.1" + es-define-property "^1.0.1" + es-errors "^1.3.0" + es-object-atoms "^1.1.1" + es-set-tostringtag "^2.1.0" + es-to-primitive "^1.3.0" + function.prototype.name "^1.1.8" + get-intrinsic "^1.3.0" + get-proto "^1.0.1" + get-symbol-description "^1.1.0" + globalthis "^1.0.4" + gopd "^1.2.0" + has-property-descriptors "^1.0.2" + has-proto "^1.2.0" + has-symbols "^1.1.0" + hasown "^2.0.2" + internal-slot "^1.1.0" + is-array-buffer "^3.0.5" + is-callable "^1.2.7" + is-data-view "^1.0.2" + is-negative-zero "^2.0.3" + is-regex "^1.2.1" + is-set "^2.0.3" + is-shared-array-buffer "^1.0.4" + is-string "^1.1.1" + is-typed-array "^1.1.15" + is-weakref "^1.1.1" + math-intrinsics "^1.1.0" + object-inspect "^1.13.4" + object-keys "^1.1.1" + object.assign "^4.1.7" + own-keys "^1.0.1" + regexp.prototype.flags "^1.5.4" + safe-array-concat "^1.1.3" + safe-push-apply "^1.0.0" + safe-regex-test "^1.1.0" + set-proto "^1.0.0" + stop-iteration-iterator "^1.1.0" + string.prototype.trim "^1.2.10" + string.prototype.trimend "^1.0.9" + string.prototype.trimstart "^1.0.8" + typed-array-buffer "^1.0.3" + typed-array-byte-length "^1.0.3" + typed-array-byte-offset "^1.0.4" + typed-array-length "^1.0.7" + unbox-primitive "^1.1.0" + which-typed-array "^1.1.19" + +es-aggregate-error@^1.0.7: + version "1.0.14" + resolved "https://registry.yarnpkg.com/es-aggregate-error/-/es-aggregate-error-1.0.14.tgz#f1a24f833d25056c2ebc92a8c04449374f8f9f65" + integrity sha512-3YxX6rVb07B5TV11AV5wsL7nQCHXNwoHPsQC8S4AmBiqYhyNCJ5BRKXkXyDJvs8QzXN20NgRtxe3dEEQD9NLHA== + dependencies: + define-data-property "^1.1.4" + define-properties "^1.2.1" + es-abstract "^1.24.0" + es-errors "^1.3.0" + function-bind "^1.1.2" + globalthis "^1.0.4" + has-property-descriptors "^1.0.2" + set-function-name "^2.0.2" + +es-define-property@^1.0.0, es-define-property@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/es-define-property/-/es-define-property-1.0.1.tgz#983eb2f9a6724e9303f61addf011c72e09e0b0fa" + integrity sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g== + +es-errors@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/es-errors/-/es-errors-1.3.0.tgz#05f75a25dab98e4fb1dcd5e1472c0546d5057c8f" + integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw== + +es-object-atoms@^1.0.0, es-object-atoms@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/es-object-atoms/-/es-object-atoms-1.1.1.tgz#1c4f2c4837327597ce69d2ca190a7fdd172338c1" + integrity sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA== + dependencies: + es-errors "^1.3.0" + +es-set-tostringtag@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz#f31dbbe0c183b00a6d26eb6325c810c0fd18bd4d" + integrity sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA== + dependencies: + es-errors "^1.3.0" + get-intrinsic "^1.2.6" + has-tostringtag "^1.0.2" + hasown "^2.0.2" + +es-to-primitive@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.3.0.tgz#96c89c82cc49fd8794a24835ba3e1ff87f214e18" + integrity sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g== + dependencies: + is-callable "^1.2.7" + is-date-object "^1.0.5" + is-symbol "^1.0.4" + +es-toolkit@^1.39.10: + version "1.46.0" + resolved "https://registry.yarnpkg.com/es-toolkit/-/es-toolkit-1.46.0.tgz#40f79f4a491cf3e890a1f397889de89f02332977" + integrity sha512-IToJ6ct9OLl5zz6WsC/1vZEwfSZ7Myil+ygl5Tf30Xjn9AEkzNB4kqp2G7VUJKF1DtTx/ra5M5KLlXvzOg51BA== + +esast-util-from-estree@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/esast-util-from-estree/-/esast-util-from-estree-2.0.0.tgz#8d1cfb51ad534d2f159dc250e604f3478a79f1ad" + integrity sha512-4CyanoAudUSBAn5K13H4JhsMH6L9ZP7XbLVe/dKybkxMO7eDyLsT8UHl9TRNrU2Gr9nz+FovfSIjuXWJ81uVwQ== + dependencies: + "@types/estree-jsx" "^1.0.0" + devlop "^1.0.0" + estree-util-visit "^2.0.0" + unist-util-position-from-estree "^2.0.0" + +esast-util-from-js@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/esast-util-from-js/-/esast-util-from-js-2.0.1.tgz#5147bec34cc9da44accf52f87f239a40ac3e8225" + integrity sha512-8Ja+rNJ0Lt56Pcf3TAmpBZjmx8ZcK5Ts4cAzIOjsjevg9oSXJnl6SUQ2EevU8tv3h6ZLWmoKL5H4fgWvdvfETw== + dependencies: + "@types/estree-jsx" "^1.0.0" + acorn "^8.0.0" + esast-util-from-estree "^2.0.0" + vfile-message "^4.0.0" + +escalade@^3.1.1: + version "3.2.0" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.2.0.tgz#011a3f69856ba189dffa7dc8fcce99d2a87903e5" + integrity sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA== + +escape-html@^1.0.3, escape-html@~1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" + integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow== + +escape-string-regexp@5.0.0, escape-string-regexp@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz#4683126b500b61762f2dbebace1806e8be31b1c8" + integrity sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw== + +escape-string-regexp@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz#a30304e99daa32e23b2fd20f51babd07cffca344" + integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w== + +escodegen@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-2.1.0.tgz#ba93bbb7a43986d29d6041f99f5262da773e2e17" + integrity sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w== + dependencies: + esprima "^4.0.1" + estraverse "^5.2.0" + esutils "^2.0.2" + optionalDependencies: + source-map "~0.6.1" + +esprima@^4.0.0, esprima@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" + integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== + +estraverse@^5.2.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" + integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== + +estree-util-attach-comments@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/estree-util-attach-comments/-/estree-util-attach-comments-3.0.0.tgz#344bde6a64c8a31d15231e5ee9e297566a691c2d" + integrity sha512-cKUwm/HUcTDsYh/9FgnuFqpfquUbwIqwKM26BVCGDPVgvaCl/nDCCjUfiLlx6lsEZ3Z4RFxNbOQ60pkaEwFxGw== + dependencies: + "@types/estree" "^1.0.0" + +estree-util-build-jsx@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/estree-util-build-jsx/-/estree-util-build-jsx-3.0.1.tgz#b6d0bced1dcc4f06f25cf0ceda2b2dcaf98168f1" + integrity sha512-8U5eiL6BTrPxp/CHbs2yMgP8ftMhR5ww1eIKoWRMlqvltHF8fZn5LRDvTKuxD3DUn+shRbLGqXemcP51oFCsGQ== + dependencies: + "@types/estree-jsx" "^1.0.0" + devlop "^1.0.0" + estree-util-is-identifier-name "^3.0.0" + estree-walker "^3.0.0" + +estree-util-is-identifier-name@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/estree-util-is-identifier-name/-/estree-util-is-identifier-name-3.0.0.tgz#0b5ef4c4ff13508b34dcd01ecfa945f61fce5dbd" + integrity sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg== + +estree-util-scope@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/estree-util-scope/-/estree-util-scope-1.0.0.tgz#9cbdfc77f5cb51e3d9ed4ad9c4adbff22d43e585" + integrity sha512-2CAASclonf+JFWBNJPndcOpA8EMJwa0Q8LUFJEKqXLW6+qBvbFZuF5gItbQOs/umBUkjviCSDCbBwU2cXbmrhQ== + dependencies: + "@types/estree" "^1.0.0" + devlop "^1.0.0" + +estree-util-to-js@2.0.0, estree-util-to-js@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/estree-util-to-js/-/estree-util-to-js-2.0.0.tgz#10a6fb924814e6abb62becf0d2bc4dea51d04f17" + integrity sha512-WDF+xj5rRWmD5tj6bIqRi6CkLIXbbNQUcxQHzGysQzvHmdYG2G7p/Tf0J0gpxGgkeMZNTIjT/AoSvC9Xehcgdg== + dependencies: + "@types/estree-jsx" "^1.0.0" + astring "^1.8.0" + source-map "^0.7.0" + +estree-util-visit@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/estree-util-visit/-/estree-util-visit-2.0.0.tgz#13a9a9f40ff50ed0c022f831ddf4b58d05446feb" + integrity sha512-m5KgiH85xAhhW8Wta0vShLcUvOsh3LLPI2YVwcbio1l7E09NTLL1EyMZFM1OyWowoH0skScNbhOPl4kcBgzTww== + dependencies: + "@types/estree-jsx" "^1.0.0" + "@types/unist" "^3.0.0" + +estree-walker@3.0.3, estree-walker@^3.0.0: + version "3.0.3" + resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-3.0.3.tgz#67c3e549ec402a487b4fc193d1953a524752340d" + integrity sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g== + dependencies: + "@types/estree" "^1.0.0" + +esutils@^2.0.2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" + integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== + +etag@~1.8.1: + version "1.8.1" + resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" + integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg== + +event-target-shim@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-5.0.1.tgz#5d4d3ebdf9583d63a5333ce2deb7480ab2b05789" + integrity sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ== + +events-universal@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/events-universal/-/events-universal-1.0.1.tgz#b56a84fd611b6610e0a2d0f09f80fdf931e2dfe6" + integrity sha512-LUd5euvbMLpwOF8m6ivPCbhQeSiYVNb8Vs0fQ8QjXo0JTkEHpz8pxdQf0gStltaPpw0Cca8b39KxvK9cfKRiAw== + dependencies: + bare-events "^2.7.0" + +expand-template@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/expand-template/-/expand-template-2.0.3.tgz#6e14b3fcee0f3a6340ecb57d2e8918692052a47c" + integrity sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg== + +expr-eval-fork@^3.0.1: + version "3.0.3" + resolved "https://registry.yarnpkg.com/expr-eval-fork/-/expr-eval-fork-3.0.3.tgz#82a3291db3835af9dfe05f519e4901f2b72219fb" + integrity sha512-BhC+hbc5lIVjygr840n5DEkW3MQq7H9o+mc1/N7Z5uIiCFVyESLL5DIE7LNq4CYUNxy+XjA+3jRrL/h0Kt2xcg== + +express@4.18.2: + version "4.18.2" + resolved "https://registry.yarnpkg.com/express/-/express-4.18.2.tgz#3fabe08296e930c796c19e3c516979386ba9fd59" + integrity sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ== + dependencies: + accepts "~1.3.8" + array-flatten "1.1.1" + body-parser "1.20.1" + 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.11.0" + 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" + +extend@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" + integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== + +extract-zip@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/extract-zip/-/extract-zip-2.0.1.tgz#663dca56fe46df890d5f131ef4a06d22bb8ba13a" + integrity sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg== + dependencies: + debug "^4.1.1" + get-stream "^5.1.0" + yauzl "^2.10.0" + optionalDependencies: + "@types/yauzl" "^2.9.1" + +fast-deep-equal@^3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" + integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== + +fast-fifo@^1.2.0, fast-fifo@^1.3.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/fast-fifo/-/fast-fifo-1.3.2.tgz#286e31de96eb96d38a97899815740ba2a4f3640c" + integrity sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ== + +fast-glob@^3.3.0, fast-glob@^3.3.2: + version "3.3.3" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.3.tgz#d06d585ce8dba90a16b0505c543c3ccfb3aeb818" + integrity sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg== + 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.8" + +fast-memoize@^2.5.2: + version "2.5.2" + resolved "https://registry.yarnpkg.com/fast-memoize/-/fast-memoize-2.5.2.tgz#79e3bb6a4ec867ea40ba0e7146816f6cdce9b57e" + integrity sha512-Ue0LwpDYErFbmNnZSF0UH6eImUwDmogUO1jyE+JbN2gsQz/jICm1Ve7t9QT0rNSsfJt+Hs4/S3GnsDVjL4HVrw== + +fast-uri@^3.0.1: + version "3.1.0" + resolved "https://registry.yarnpkg.com/fast-uri/-/fast-uri-3.1.0.tgz#66eecff6c764c0df9b762e62ca7edcfb53b4edfa" + integrity sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA== + +fastq@^1.6.0: + version "1.20.1" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.20.1.tgz#ca750a10dc925bc8b18839fd203e3ef4b3ced675" + integrity sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw== + dependencies: + reusify "^1.0.4" + +fault@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/fault/-/fault-2.0.1.tgz#d47ca9f37ca26e4bd38374a7c500b5a384755b6c" + integrity sha512-WtySTkS4OKev5JtpHXnib4Gxiurzh5NCGvWrFaZ34m6JehfTUhKZvn9njTfw48t6JumVQOmrKqpmGcdwxnhqBQ== + dependencies: + format "^0.2.0" + +favicons@7.2.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/favicons/-/favicons-7.2.0.tgz#1f1662f1f69e5637c19275209003b7b822c24250" + integrity sha512-k/2rVBRIRzOeom3wI9jBPaSEvoTSQEW4iM0EveBmBBKFxO8mSyyRWtDlfC3VnEfu0avmjrMzy8/ZFPSe6F71Hw== + dependencies: + escape-html "^1.0.3" + sharp "^0.33.1" + xml2js "^0.6.1" + +fd-slicer@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.1.0.tgz#25c7c89cb1f9077f8891bbe61d8f390eae256f1e" + integrity sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g== + dependencies: + pend "~1.2.0" + +fdir@^6.5.0: + version "6.5.0" + resolved "https://registry.yarnpkg.com/fdir/-/fdir-6.5.0.tgz#ed2ab967a331ade62f18d077dae192684d50d350" + integrity sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg== + +fill-range@^7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292" + integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg== + dependencies: + to-regex-range "^5.0.1" + +finalhandler@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.2.0.tgz#7d23fe5731b207b4640e4fcd00aec1f9207a7b32" + integrity sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg== + dependencies: + 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" + +follow-redirects@^1.15.6: + version "1.16.0" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.16.0.tgz#28474a159d3b9d11ef62050a14ed60e4df6d61bc" + integrity sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw== + +for-each@^0.3.3, for-each@^0.3.5: + version "0.3.5" + resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.5.tgz#d650688027826920feeb0af747ee7b9421a41d47" + integrity sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg== + dependencies: + is-callable "^1.2.7" + +form-data-encoder@^2.1.2: + version "2.1.4" + resolved "https://registry.yarnpkg.com/form-data-encoder/-/form-data-encoder-2.1.4.tgz#261ea35d2a70d48d30ec7a9603130fa5515e9cd5" + integrity sha512-yDYSgNMraqvnxiEXO4hi88+YZxaHC6QKzb5N84iRCTDeRO7ZALpir/lVmf/uXUhnwUr2O4HU8s/n6x+yNjQkHw== + +form-data@^4.0.0, form-data@^4.0.4: + version "4.0.5" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.5.tgz#b49e48858045ff4cbf6b03e1805cebcad3679053" + integrity sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.8" + es-set-tostringtag "^2.1.0" + hasown "^2.0.2" + mime-types "^2.1.12" + +format@^0.2.0: + version "0.2.2" + resolved "https://registry.yarnpkg.com/format/-/format-0.2.2.tgz#d6170107e9efdc4ed30c9dc39016df942b5cb58b" + integrity sha512-wzsgA6WOq+09wrU1tsJ09udeR/YZRaeArL9e1wPbFg3GG2yDnC2ldKpxs4xunpFF9DgqCqOIra3bc1HWrJ37Ww== + +forwarded@0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811" + integrity sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow== + +fresh@0.5.2: + version "0.5.2" + resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" + integrity sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q== + +front-matter@4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/front-matter/-/front-matter-4.0.2.tgz#b14e54dc745cfd7293484f3210d15ea4edd7f4d5" + integrity sha512-I8ZuJ/qG92NWX8i5x1Y8qyj3vizhXS31OxjKDu3LKP+7/qBgfIKValiZIEwoVoJKUHlhWtYrktkxV1XsX+pPlg== + dependencies: + js-yaml "^3.13.1" + +fs-constants@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad" + integrity sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow== + +fs-extra@11.1.0: + version "11.1.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-11.1.0.tgz#5784b102104433bb0e090f48bfc4a30742c357ed" + integrity sha512-0rcTq621PD5jM/e0a3EJoGC/1TC5ZBCERW82LQuwfGnCa1V8w7dpYH1yNu+SLb6E5dkeCBzKEyLGlFrnr+dUyw== + dependencies: + graceful-fs "^4.2.0" + jsonfile "^6.0.1" + universalify "^2.0.0" + +fs-extra@11.1.1: + version "11.1.1" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-11.1.1.tgz#da69f7c39f3b002378b0954bb6ae7efdc0876e2d" + integrity sha512-MGIE4HOvQCeUCzmlHs0vXpih4ysz4wg9qiSAu6cd42lVwPbTM1TjV7RusoyQqMmk/95gdQZX72u+YW+c3eEpFQ== + dependencies: + graceful-fs "^4.2.0" + jsonfile "^6.0.1" + universalify "^2.0.0" + +fs-extra@11.2.0: + version "11.2.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-11.2.0.tgz#e70e17dfad64232287d01929399e0ea7c86b0e5b" + integrity sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw== + dependencies: + graceful-fs "^4.2.0" + jsonfile "^6.0.1" + universalify "^2.0.0" + +fs-minipass@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-2.1.0.tgz#7f5036fdbf12c63c169190cbe4199c852271f9fb" + integrity sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg== + dependencies: + minipass "^3.0.0" + +fsevents@~2.3.2: + version "2.3.3" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" + integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== + +function-bind@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" + integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== + +function.prototype.name@^1.1.6, function.prototype.name@^1.1.8: + version "1.1.8" + resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.8.tgz#e68e1df7b259a5c949eeef95cdbde53edffabb78" + integrity sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q== + dependencies: + call-bind "^1.0.8" + call-bound "^1.0.3" + define-properties "^1.2.1" + functions-have-names "^1.2.3" + hasown "^2.0.2" + is-callable "^1.2.7" + +functions-have-names@^1.2.3: + version "1.2.3" + resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834" + integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ== + +gcd@^0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/gcd/-/gcd-0.0.1.tgz#41e0bb60bcc9245635419860a22544b230ba2f75" + integrity sha512-VNx3UEGr+ILJTiMs1+xc5SX1cMgJCrXezKPa003APUWNqQqaF6n25W8VcR7nHN6yRWbvvUTwCpZCFJeWC2kXlw== + +generator-function@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/generator-function/-/generator-function-2.0.1.tgz#0e75dd410d1243687a0ba2e951b94eedb8f737a2" + integrity sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g== + +get-caller-file@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" + integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== + +get-east-asian-width@^1.0.0, get-east-asian-width@^1.3.1: + version "1.5.0" + resolved "https://registry.yarnpkg.com/get-east-asian-width/-/get-east-asian-width-1.5.0.tgz#ce7008fe345edcf5497a6f557cfa54bc318a9ce7" + integrity sha512-CQ+bEO+Tva/qlmw24dCejulK5pMzVnUOFOijVogd3KQs07HnRIgp8TGipvCCRT06xeYEbpbgwaCxglFyiuIcmA== + +get-intrinsic@^1.2.4, get-intrinsic@^1.2.5, get-intrinsic@^1.2.6, get-intrinsic@^1.2.7, get-intrinsic@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.3.0.tgz#743f0e3b6964a93a5491ed1bffaae054d7f98d01" + integrity sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ== + dependencies: + call-bind-apply-helpers "^1.0.2" + es-define-property "^1.0.1" + es-errors "^1.3.0" + es-object-atoms "^1.1.1" + function-bind "^1.1.2" + get-proto "^1.0.1" + gopd "^1.2.0" + has-symbols "^1.1.0" + hasown "^2.0.2" + math-intrinsics "^1.1.0" + +get-proto@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/get-proto/-/get-proto-1.0.1.tgz#150b3f2743869ef3e851ec0c49d15b1d14d00ee1" + integrity sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g== + dependencies: + dunder-proto "^1.0.1" + es-object-atoms "^1.0.0" + +get-stream@^5.1.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.2.0.tgz#4966a1795ee5ace65e706c4b7beb71257d6e22d3" + integrity sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA== + dependencies: + pump "^3.0.0" + +get-stream@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" + integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== + +get-symbol-description@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/get-symbol-description/-/get-symbol-description-1.1.0.tgz#7bdd54e0befe8ffc9f3b4e203220d9f1e881b6ee" + integrity sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg== + dependencies: + call-bound "^1.0.3" + es-errors "^1.3.0" + get-intrinsic "^1.2.6" + +get-uri@^6.0.1: + version "6.0.5" + resolved "https://registry.yarnpkg.com/get-uri/-/get-uri-6.0.5.tgz#714892aa4a871db671abc5395e5e9447bc306a16" + integrity sha512-b1O07XYq8eRuVzBNgJLstU6FYc1tS6wnMtF1I1D9lE8LxZSOGZ7LhxN54yPP6mGw5f2CkXY2BQUL9Fx41qvcIg== + dependencies: + basic-ftp "^5.0.2" + data-uri-to-buffer "^6.0.2" + debug "^4.3.4" + +github-from-package@0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/github-from-package/-/github-from-package-0.0.0.tgz#97fb5d96bfde8973313f20e8288ef9a167fa64ce" + integrity sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw== + +glob-parent@^5.1.2, glob-parent@~5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" + integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== + dependencies: + is-glob "^4.0.1" + +glob-parent@^6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3" + integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A== + dependencies: + is-glob "^4.0.3" + +globalthis@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/globalthis/-/globalthis-1.0.4.tgz#7430ed3a975d97bfb59bcce41f5cabbafa651236" + integrity sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ== + dependencies: + define-properties "^1.2.1" + gopd "^1.0.1" + +gopd@^1.0.1, gopd@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.2.0.tgz#89f56b8217bdbc8802bd299df6d7f1081d7e51a1" + integrity sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg== + +got@13.0.0: + version "13.0.0" + resolved "https://registry.yarnpkg.com/got/-/got-13.0.0.tgz#a2402862cef27a5d0d1b07c0fb25d12b58175422" + integrity sha512-XfBk1CxOOScDcMr9O1yKkNaQyy865NbYs+F7dr4H0LZMVgCj2Le59k6PqbNHoL5ToeaEQUYh6c6yMfVcc6SJxA== + dependencies: + "@sindresorhus/is" "^5.2.0" + "@szmarczak/http-timer" "^5.0.1" + cacheable-lookup "^7.0.0" + cacheable-request "^10.2.8" + decompress-response "^6.0.0" + form-data-encoder "^2.1.2" + get-stream "^6.0.1" + http2-wrapper "^2.1.10" + lowercase-keys "^3.0.0" + p-cancelable "^3.0.0" + responselike "^3.0.0" + +got@^12.0.0, got@^12.1.0: + version "12.6.1" + resolved "https://registry.yarnpkg.com/got/-/got-12.6.1.tgz#8869560d1383353204b5a9435f782df9c091f549" + integrity sha512-mThBblvlAF1d4O5oqyvN+ZxLAYwIJK7bpMxgYqPD9okW0C3qm5FFn7k811QrcuEBwaogR3ngOFoCfs6mRv7teQ== + dependencies: + "@sindresorhus/is" "^5.2.0" + "@szmarczak/http-timer" "^5.0.1" + cacheable-lookup "^7.0.0" + cacheable-request "^10.2.8" + decompress-response "^6.0.0" + form-data-encoder "^2.1.2" + get-stream "^6.0.1" + http2-wrapper "^2.1.10" + lowercase-keys "^3.0.0" + p-cancelable "^3.0.0" + responselike "^3.0.0" + +graceful-fs@^4.1.6, graceful-fs@^4.2.0: + version "4.2.11" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" + integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== + +has-bigints@^1.0.2: + version "1.1.0" + resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.1.0.tgz#28607e965ac967e03cd2a2c70a2636a1edad49fe" + integrity sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg== + +has-property-descriptors@^1.0.0, has-property-descriptors@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz#963ed7d071dc7bf5f084c5bfbe0d1b6222586854" + integrity sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg== + dependencies: + es-define-property "^1.0.0" + +has-proto@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.2.0.tgz#5de5a6eabd95fdffd9818b43055e8065e39fe9d5" + integrity sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ== + dependencies: + dunder-proto "^1.0.0" + +has-symbols@^1.0.3, has-symbols@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.1.0.tgz#fc9c6a783a084951d0b971fe1018de813707a338" + integrity sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ== + +has-tostringtag@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.2.tgz#2cdc42d40bef2e5b4eeab7c01a73c54ce7ab5abc" + integrity sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw== + dependencies: + has-symbols "^1.0.3" + +hasown@^2.0.2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.3.tgz#5e5c2b15b60370a4c7930c383dfb76bf17bc403c" + integrity sha512-ej4AhfhfL2Q2zpMmLo7U1Uv9+PyhIZpgQLGT1F9miIGmiCJIoCgSmczFdrc97mWT4kVY72KA+WnnhJ5pghSvSg== + dependencies: + function-bind "^1.1.2" + +hast-util-embedded@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/hast-util-embedded/-/hast-util-embedded-3.0.0.tgz#be4477780fbbe079cdba22982e357a0de4ba853e" + integrity sha512-naH8sld4Pe2ep03qqULEtvYr7EjrLK2QHY8KJR6RJkTUjPGObe1vnx585uzem2hGra+s1q08DZZpfgDVYRbaXA== + dependencies: + "@types/hast" "^3.0.0" + hast-util-is-element "^3.0.0" + +hast-util-from-dom@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/hast-util-from-dom/-/hast-util-from-dom-5.0.1.tgz#c3c92fbd8d4e1c1625edeb3a773952b9e4ad64a8" + integrity sha512-N+LqofjR2zuzTjCPzyDUdSshy4Ma6li7p/c3pA78uTwzFgENbgbUrm2ugwsOdcjI1muO+o6Dgzp9p8WHtn/39Q== + dependencies: + "@types/hast" "^3.0.0" + hastscript "^9.0.0" + web-namespaces "^2.0.0" + +hast-util-from-html-isomorphic@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/hast-util-from-html-isomorphic/-/hast-util-from-html-isomorphic-2.0.0.tgz#b31baee386a899a2472326a3c5692f29f86d1d3c" + integrity sha512-zJfpXq44yff2hmE0XmwEOzdWin5xwH+QIhMLOScpX91e/NSGPsAzNCvLQDIEPyO2TXi+lBmU6hjLIhV8MwP2kw== + dependencies: + "@types/hast" "^3.0.0" + hast-util-from-dom "^5.0.0" + hast-util-from-html "^2.0.0" + unist-util-remove-position "^5.0.0" + +hast-util-from-html@2.0.3, hast-util-from-html@^2.0.0: + version "2.0.3" + resolved "https://registry.yarnpkg.com/hast-util-from-html/-/hast-util-from-html-2.0.3.tgz#485c74785358beb80c4ba6346299311ac4c49c82" + integrity sha512-CUSRHXyKjzHov8yKsQjGOElXy/3EKpyX56ELnkHH34vDVw1N1XSQ1ZcAvTyAPtGqLTuKP/uxM+aLkSPqF/EtMw== + dependencies: + "@types/hast" "^3.0.0" + devlop "^1.1.0" + hast-util-from-parse5 "^8.0.0" + parse5 "^7.0.0" + vfile "^6.0.0" + vfile-message "^4.0.0" + +hast-util-from-parse5@^8.0.0: + version "8.0.3" + resolved "https://registry.yarnpkg.com/hast-util-from-parse5/-/hast-util-from-parse5-8.0.3.tgz#830a35022fff28c3fea3697a98c2f4cc6b835a2e" + integrity sha512-3kxEVkEKt0zvcZ3hCRYI8rqrgwtlIOFMWkbclACvjlDw8Li9S2hk/d51OI0nr/gIpdMHNepwgOKqZ/sy0Clpyg== + dependencies: + "@types/hast" "^3.0.0" + "@types/unist" "^3.0.0" + devlop "^1.0.0" + hastscript "^9.0.0" + property-information "^7.0.0" + vfile "^6.0.0" + vfile-location "^5.0.0" + web-namespaces "^2.0.0" + +hast-util-has-property@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/hast-util-has-property/-/hast-util-has-property-3.0.0.tgz#4e595e3cddb8ce530ea92f6fc4111a818d8e7f93" + integrity sha512-MNilsvEKLFpV604hwfhVStK0usFY/QmM5zX16bo7EjnAEGofr5YyI37kzopBlZJkHD4t887i+q/C8/tr5Q94cA== + dependencies: + "@types/hast" "^3.0.0" + +hast-util-is-body-ok-link@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/hast-util-is-body-ok-link/-/hast-util-is-body-ok-link-3.0.1.tgz#ef63cb2f14f04ecf775139cd92bda5026380d8b4" + integrity sha512-0qpnzOBLztXHbHQenVB8uNuxTnm/QBFUOmdOSsEn7GnBtyY07+ENTWVFBAnXd/zEgd9/SUG3lRY7hSIBWRgGpQ== + dependencies: + "@types/hast" "^3.0.0" + +hast-util-is-element@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/hast-util-is-element/-/hast-util-is-element-3.0.0.tgz#6e31a6532c217e5b533848c7e52c9d9369ca0932" + integrity sha512-Val9mnv2IWpLbNPqc/pUem+a7Ipj2aHacCwgNfTiK0vJKl0LF+4Ba4+v1oPHFpf3bLYmreq0/l3Gud9S5OH42g== + dependencies: + "@types/hast" "^3.0.0" + +hast-util-minify-whitespace@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/hast-util-minify-whitespace/-/hast-util-minify-whitespace-1.0.1.tgz#7588fd1a53f48f1d30406b81959dffc3650daf55" + integrity sha512-L96fPOVpnclQE0xzdWb/D12VT5FabA7SnZOUMtL1DbXmYiHJMXZvFkIZfiMmTCNJHUeO2K9UYNXoVyfz+QHuOw== + dependencies: + "@types/hast" "^3.0.0" + hast-util-embedded "^3.0.0" + hast-util-is-element "^3.0.0" + hast-util-whitespace "^3.0.0" + unist-util-is "^6.0.0" + +hast-util-parse-selector@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/hast-util-parse-selector/-/hast-util-parse-selector-4.0.0.tgz#352879fa86e25616036037dd8931fb5f34cb4a27" + integrity sha512-wkQCkSYoOGCRKERFWcxMVMOcYE2K1AaNLU8DXS9arxnLOUEWbOXKXiJUNzEpqZ3JOKpnha3jkFrumEjVliDe7A== + dependencies: + "@types/hast" "^3.0.0" + +hast-util-phrasing@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/hast-util-phrasing/-/hast-util-phrasing-3.0.1.tgz#fa284c0cd4a82a0dd6020de8300a7b1ebffa1690" + integrity sha512-6h60VfI3uBQUxHqTyMymMZnEbNl1XmEGtOxxKYL7stY2o601COo62AWAYBQR9lZbYXYSBoxag8UpPRXK+9fqSQ== + dependencies: + "@types/hast" "^3.0.0" + hast-util-embedded "^3.0.0" + hast-util-has-property "^3.0.0" + hast-util-is-body-ok-link "^3.0.0" + hast-util-is-element "^3.0.0" + +hast-util-to-estree@^3.0.0: + version "3.1.3" + resolved "https://registry.yarnpkg.com/hast-util-to-estree/-/hast-util-to-estree-3.1.3.tgz#e654c1c9374645135695cc0ab9f70b8fcaf733d7" + integrity sha512-48+B/rJWAp0jamNbAAf9M7Uf//UVqAoMmgXhBdxTDJLGKY+LRnZ99qcG+Qjl5HfMpYNzS5v4EAwVEF34LeAj7w== + dependencies: + "@types/estree" "^1.0.0" + "@types/estree-jsx" "^1.0.0" + "@types/hast" "^3.0.0" + comma-separated-tokens "^2.0.0" + devlop "^1.0.0" + estree-util-attach-comments "^3.0.0" + estree-util-is-identifier-name "^3.0.0" + hast-util-whitespace "^3.0.0" + mdast-util-mdx-expression "^2.0.0" + mdast-util-mdx-jsx "^3.0.0" + mdast-util-mdxjs-esm "^2.0.0" + property-information "^7.0.0" + space-separated-tokens "^2.0.0" + style-to-js "^1.0.0" + unist-util-position "^5.0.0" + zwitch "^2.0.0" + +hast-util-to-html@9.0.4: + version "9.0.4" + resolved "https://registry.yarnpkg.com/hast-util-to-html/-/hast-util-to-html-9.0.4.tgz#d689c118c875aab1def692c58603e34335a0f5c5" + integrity sha512-wxQzXtdbhiwGAUKrnQJXlOPmHnEehzphwkK7aluUPQ+lEc1xefC8pblMgpp2w5ldBTEfveRIrADcrhGIWrlTDA== + dependencies: + "@types/hast" "^3.0.0" + "@types/unist" "^3.0.0" + ccount "^2.0.0" + comma-separated-tokens "^2.0.0" + hast-util-whitespace "^3.0.0" + html-void-elements "^3.0.0" + mdast-util-to-hast "^13.0.0" + property-information "^6.0.0" + space-separated-tokens "^2.0.0" + stringify-entities "^4.0.0" + zwitch "^2.0.4" + +hast-util-to-html@^9.0.0, hast-util-to-html@^9.0.5: + version "9.0.5" + resolved "https://registry.yarnpkg.com/hast-util-to-html/-/hast-util-to-html-9.0.5.tgz#ccc673a55bb8e85775b08ac28380f72d47167005" + integrity sha512-OguPdidb+fbHQSU4Q4ZiLKnzWo8Wwsf5bZfbvu7//a9oTYoqD/fWpe96NuHkoS9h0ccGOTe0C4NGXdtS0iObOw== + dependencies: + "@types/hast" "^3.0.0" + "@types/unist" "^3.0.0" + ccount "^2.0.0" + comma-separated-tokens "^2.0.0" + hast-util-whitespace "^3.0.0" + html-void-elements "^3.0.0" + mdast-util-to-hast "^13.0.0" + property-information "^7.0.0" + space-separated-tokens "^2.0.0" + stringify-entities "^4.0.0" + zwitch "^2.0.4" + +hast-util-to-jsx-runtime@^2.0.0: + version "2.3.6" + resolved "https://registry.yarnpkg.com/hast-util-to-jsx-runtime/-/hast-util-to-jsx-runtime-2.3.6.tgz#ff31897aae59f62232e21594eac7ef6b63333e98" + integrity sha512-zl6s8LwNyo1P9uw+XJGvZtdFF1GdAkOg8ujOw+4Pyb76874fLps4ueHXDhXWdk6YHQ6OgUtinliG7RsYvCbbBg== + dependencies: + "@types/estree" "^1.0.0" + "@types/hast" "^3.0.0" + "@types/unist" "^3.0.0" + comma-separated-tokens "^2.0.0" + devlop "^1.0.0" + estree-util-is-identifier-name "^3.0.0" + hast-util-whitespace "^3.0.0" + mdast-util-mdx-expression "^2.0.0" + mdast-util-mdx-jsx "^3.0.0" + mdast-util-mdxjs-esm "^2.0.0" + property-information "^7.0.0" + space-separated-tokens "^2.0.0" + style-to-js "^1.0.0" + unist-util-position "^5.0.0" + vfile-message "^4.0.0" + +hast-util-to-mdast@10.1.0: + version "10.1.0" + resolved "https://registry.yarnpkg.com/hast-util-to-mdast/-/hast-util-to-mdast-10.1.0.tgz#906c80fc263a9f09a33462317ffc6ad94f4ee3db" + integrity sha512-DsL/SvCK9V7+vfc6SLQ+vKIyBDXTk2KLSbfBYkH4zeF/uR1yBajHRhkzuaUSGOB1WJSTieJBdHwxlC+HLKvZZw== + dependencies: + "@types/hast" "^3.0.0" + "@types/mdast" "^4.0.0" + "@ungap/structured-clone" "^1.0.0" + hast-util-phrasing "^3.0.0" + hast-util-to-html "^9.0.0" + hast-util-to-text "^4.0.0" + hast-util-whitespace "^3.0.0" + mdast-util-phrasing "^4.0.0" + mdast-util-to-hast "^13.0.0" + mdast-util-to-string "^4.0.0" + rehype-minify-whitespace "^6.0.0" + trim-trailing-lines "^2.0.0" + unist-util-position "^5.0.0" + unist-util-visit "^5.0.0" + +hast-util-to-string@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/hast-util-to-string/-/hast-util-to-string-3.0.1.tgz#a4f15e682849326dd211c97129c94b0c3e76527c" + integrity sha512-XelQVTDWvqcl3axRfI0xSeoVKzyIFPwsAGSLIsKdJKQMXDYJS4WYrBNF/8J7RdhIcFI2BOHgAifggsvsxp/3+A== + dependencies: + "@types/hast" "^3.0.0" + +hast-util-to-text@4.0.2, hast-util-to-text@^4.0.0: + version "4.0.2" + resolved "https://registry.yarnpkg.com/hast-util-to-text/-/hast-util-to-text-4.0.2.tgz#57b676931e71bf9cb852453678495b3080bfae3e" + integrity sha512-KK6y/BN8lbaq654j7JgBydev7wuNMcID54lkRav1P0CaE1e47P72AWWPiGKXTJU271ooYzcvTAn/Zt0REnvc7A== + dependencies: + "@types/hast" "^3.0.0" + "@types/unist" "^3.0.0" + hast-util-is-element "^3.0.0" + unist-util-find-after "^5.0.0" + +hast-util-whitespace@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz#7778ed9d3c92dd9e8c5c8f648a49c21fc51cb621" + integrity sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw== + dependencies: + "@types/hast" "^3.0.0" + +hastscript@^9.0.0: + version "9.0.1" + resolved "https://registry.yarnpkg.com/hastscript/-/hastscript-9.0.1.tgz#dbc84bef6051d40084342c229c451cd9dc567dff" + integrity sha512-g7df9rMFX/SPi34tyGCyUBREQoKkapwdY/T04Qn9TDWfHhAYt4/I0gMVirzK5wEzeUqIjEB+LXC/ypb7Aqno5w== + dependencies: + "@types/hast" "^3.0.0" + comma-separated-tokens "^2.0.0" + hast-util-parse-selector "^4.0.0" + property-information "^7.0.0" + space-separated-tokens "^2.0.0" + +hex-rgb@5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/hex-rgb/-/hex-rgb-5.0.0.tgz#e2c9eb6a37498d66c5a350a221ed4c2c7d1a92d6" + integrity sha512-NQO+lgVUCtHxZ792FodgW0zflK+ozS9X9dwGp9XvvmPlH7pyxd588cn24TD3rmPm/N0AIRXF10Otah8yKqGw4w== + +html-void-elements@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/html-void-elements/-/html-void-elements-3.0.0.tgz#fc9dbd84af9e747249034d4d62602def6517f1d7" + integrity sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg== + +http-cache-semantics@^4.1.1: + version "4.2.0" + resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz#205f4db64f8562b76a4ff9235aa5279839a09dd5" + integrity sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ== + +http-errors@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3" + 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" + +http-proxy-agent@^7.0.0, http-proxy-agent@^7.0.1: + version "7.0.2" + resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz#9a8b1f246866c028509486585f62b8f2c18c270e" + integrity sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig== + dependencies: + agent-base "^7.1.0" + debug "^4.3.4" + +http2-wrapper@^2.1.10: + version "2.2.1" + resolved "https://registry.yarnpkg.com/http2-wrapper/-/http2-wrapper-2.2.1.tgz#310968153dcdedb160d8b72114363ef5fce1f64a" + integrity sha512-V5nVw1PAOgfI3Lmeaj2Exmeg7fenjhRUgz1lPSezy1CuhPYbgQtbQj4jZfEAEMlaL+vupsvhjqCyjzob0yxsmQ== + dependencies: + quick-lru "^5.1.1" + resolve-alpn "^1.2.0" + +https-proxy-agent@^7.0.6: + version "7.0.6" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz#da8dfeac7da130b05c2ba4b59c9b6cd66611a6b9" + integrity sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw== + dependencies: + agent-base "^7.1.2" + debug "4" + +ico-endec@*: + version "0.1.6" + resolved "https://registry.yarnpkg.com/ico-endec/-/ico-endec-0.1.6.tgz#9b320cc3ed0a0c779f54e998a8db49002abd7c6e" + integrity sha512-ZdLU38ZoED3g1j3iEyzcQj+wAkY2xfWNkymszfJPoxucIUhK7NayQ+/C4Kv0nDFMIsbtbEHldv3V8PU494/ueQ== + +iconv-lite@0.4.24: + version "0.4.24" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" + integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== + dependencies: + safer-buffer ">= 2.1.2 < 3" + +iconv-lite@^0.7.0: + version "0.7.2" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.7.2.tgz#d0bdeac3f12b4835b7359c2ad89c422a4d1cc72e" + integrity sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw== + dependencies: + safer-buffer ">= 2.1.2 < 3.0.0" + +ieee754@^1.1.13: + version "1.2.1" + resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" + integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== + +ignore@7.0.5: + version "7.0.5" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-7.0.5.tgz#4cb5f6cd7d4c7ab0365738c7aea888baa6d7efd9" + integrity sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg== + +immer@^9.0.6: + version "9.0.21" + resolved "https://registry.yarnpkg.com/immer/-/immer-9.0.21.tgz#1e025ea31a40f24fb064f1fef23e931496330176" + integrity sha512-bc4NBHqOqSfRW7POMkHd51LvClaeMXpm8dx0e8oE2GORbq5aRK7Bxl4FyzVLdGtLmvLKL7BTDBG5ACQm4HWjTA== + +import-fresh@^3.3.0: + version "3.3.1" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.1.tgz#9cecb56503c0ada1f2741dbbd6546e4b13b57ccf" + integrity sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ== + dependencies: + parent-module "^1.0.0" + resolve-from "^4.0.0" + +indent-string@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-5.0.0.tgz#4fd2980fccaf8622d14c64d694f4cf33c81951a5" + integrity sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg== + +inherits@2.0.4, inherits@^2.0.3, inherits@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +ini@~1.3.0: + version "1.3.8" + resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" + integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== + +ink-spinner@5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/ink-spinner/-/ink-spinner-5.0.0.tgz#32ec318ef8ebb0ace8f595451f8e93280623429f" + integrity sha512-EYEasbEjkqLGyPOUc8hBJZNuC5GvXGMLu0w5gdTNskPc7Izc5vO3tdQEYnzvshucyGCBXc86ig0ujXPMWaQCdA== + dependencies: + cli-spinners "^2.7.0" + +ink@6.3.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/ink/-/ink-6.3.0.tgz#9be9c3f550bd4e356249653504f6d974a0cddd13" + integrity sha512-2CbJAa7XeziZYe6pDS5RVLirRY28iSGMQuEV8jRU5NQsONQNfcR/BZHHc9vkMg2lGYTHTM2pskxC1YmY28p6bQ== + dependencies: + "@alcalzone/ansi-tokenize" "^0.2.0" + ansi-escapes "^7.0.0" + ansi-styles "^6.2.1" + auto-bind "^5.0.1" + chalk "^5.6.0" + cli-boxes "^3.0.0" + cli-cursor "^4.0.0" + cli-truncate "^4.0.0" + code-excerpt "^4.0.0" + es-toolkit "^1.39.10" + indent-string "^5.0.0" + is-in-ci "^2.0.0" + patch-console "^2.0.0" + react-reconciler "^0.32.0" + signal-exit "^3.0.7" + slice-ansi "^7.1.0" + stack-utils "^2.0.6" + string-width "^7.2.0" + type-fest "^4.27.0" + widest-line "^5.0.0" + wrap-ansi "^9.0.0" + ws "^8.18.0" + yoga-layout "~3.2.1" + +inline-style-parser@0.2.7: + version "0.2.7" + resolved "https://registry.yarnpkg.com/inline-style-parser/-/inline-style-parser-0.2.7.tgz#b1fc68bfc0313b8685745e4464e37f9376b9c909" + integrity sha512-Nb2ctOyNR8DqQoR0OwRG95uNWIC0C1lCgf5Naz5H6Ji72KZ8OcFZLz2P5sNgwlyoJ8Yif11oMuYs5pBQa86csA== + +inquirer@12.3.0: + version "12.3.0" + resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-12.3.0.tgz#c5142f49362f1347aa49a18e652db460f14092e6" + integrity sha512-3NixUXq+hM8ezj2wc7wC37b32/rHq1MwNZDYdvx+d6jokOD+r+i8Q4Pkylh9tISYP114A128LCX8RKhopC5RfQ== + dependencies: + "@inquirer/core" "^10.1.2" + "@inquirer/prompts" "^7.2.1" + "@inquirer/type" "^3.0.2" + ansi-escapes "^4.3.2" + mute-stream "^2.0.0" + run-async "^3.0.0" + rxjs "^7.8.1" + +internal-slot@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.1.0.tgz#1eac91762947d2f7056bc838d93e13b2e9604961" + integrity sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw== + dependencies: + es-errors "^1.3.0" + hasown "^2.0.2" + side-channel "^1.1.0" + +ip-address@^10.0.1: + version "10.1.0" + resolved "https://registry.yarnpkg.com/ip-address/-/ip-address-10.1.0.tgz#d8dcffb34d0e02eb241427444a6e23f5b0595aa4" + integrity sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q== + +ip-regex@^4.0.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/ip-regex/-/ip-regex-4.3.0.tgz#687275ab0f57fa76978ff8f4dddc8a23d5990db5" + integrity sha512-B9ZWJxHHOHUhUjCPrMpLD4xEq35bUTClHM1S6CBU5ixQnkZmwipwgc96vAd7AAGM9TGHvJR+Uss+/Ak6UphK+Q== + +ipaddr.js@1.9.1: + version "1.9.1" + resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" + integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== + +is-alphabetical@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/is-alphabetical/-/is-alphabetical-2.0.1.tgz#01072053ea7c1036df3c7d19a6daaec7f19e789b" + integrity sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ== + +is-alphanumerical@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/is-alphanumerical/-/is-alphanumerical-2.0.1.tgz#7c03fbe96e3e931113e57f964b0a368cc2dfd875" + integrity sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw== + dependencies: + is-alphabetical "^2.0.0" + is-decimal "^2.0.0" + +is-array-buffer@^3.0.4, is-array-buffer@^3.0.5: + version "3.0.5" + resolved "https://registry.yarnpkg.com/is-array-buffer/-/is-array-buffer-3.0.5.tgz#65742e1e687bd2cc666253068fd8707fe4d44280" + integrity sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A== + dependencies: + call-bind "^1.0.8" + call-bound "^1.0.3" + get-intrinsic "^1.2.6" + +is-arrayish@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" + integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg== + +is-arrayish@^0.3.1: + version "0.3.4" + resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.3.4.tgz#1ee5553818511915685d33bb13d31bf854e5059d" + integrity sha512-m6UrgzFVUYawGBh1dUsWR5M2Clqic9RVXC/9f8ceNlv2IcO9j9J/z8UoCLPqtsPBFNzEpfR3xftohbfqDx8EQA== + +is-async-function@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-async-function/-/is-async-function-2.1.1.tgz#3e69018c8e04e73b738793d020bfe884b9fd3523" + integrity sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ== + dependencies: + async-function "^1.0.0" + call-bound "^1.0.3" + get-proto "^1.0.1" + has-tostringtag "^1.0.2" + safe-regex-test "^1.1.0" + +is-bigint@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.1.0.tgz#dda7a3445df57a42583db4228682eba7c4170672" + integrity sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ== + dependencies: + has-bigints "^1.0.2" + +is-binary-path@~2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" + integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== + dependencies: + binary-extensions "^2.0.0" + +is-boolean-object@^1.2.1: + version "1.2.2" + resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.2.2.tgz#7067f47709809a393c71ff5bb3e135d8a9215d9e" + integrity sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A== + dependencies: + call-bound "^1.0.3" + has-tostringtag "^1.0.2" + +is-callable@^1.2.7: + version "1.2.7" + resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055" + integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA== + +is-core-module@^2.16.1: + version "2.16.1" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.16.1.tgz#2a98801a849f43e2add644fbb6bc6229b19a4ef4" + integrity sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w== + dependencies: + hasown "^2.0.2" + +is-data-view@^1.0.1, is-data-view@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-data-view/-/is-data-view-1.0.2.tgz#bae0a41b9688986c2188dda6657e56b8f9e63b8e" + integrity sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw== + dependencies: + call-bound "^1.0.2" + get-intrinsic "^1.2.6" + is-typed-array "^1.1.13" + +is-date-object@^1.0.5, is-date-object@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.1.0.tgz#ad85541996fc7aa8b2729701d27b7319f95d82f7" + integrity sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg== + dependencies: + call-bound "^1.0.2" + has-tostringtag "^1.0.2" + +is-decimal@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/is-decimal/-/is-decimal-2.0.1.tgz#9469d2dc190d0214fd87d78b78caecc0cc14eef7" + integrity sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A== + +is-docker@^2.0.0, is-docker@^2.1.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.2.1.tgz#33eeabe23cfe86f14bde4408a02c0cfb853acdaa" + integrity sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ== + +is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== + +is-finalizationregistry@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz#eefdcdc6c94ddd0674d9c85887bf93f944a97c90" + integrity sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg== + dependencies: + call-bound "^1.0.3" + +is-fullwidth-code-point@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" + integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== + +is-fullwidth-code-point@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz#fae3167c729e7463f8461ce512b080a49268aa88" + integrity sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ== + +is-fullwidth-code-point@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-5.1.0.tgz#046b2a6d4f6b156b2233d3207d4b5a9783999b98" + integrity sha512-5XHYaSyiqADb4RnZ1Bdad6cPp8Toise4TzEjcOYDHZkTCbKgiUl7WTUCpNWHuxmDt91wnsZBc9xinNzopv3JMQ== + dependencies: + get-east-asian-width "^1.3.1" + +is-generator-function@^1.0.10: + version "1.1.2" + resolved "https://registry.yarnpkg.com/is-generator-function/-/is-generator-function-1.1.2.tgz#ae3b61e3d5ea4e4839b90bad22b02335051a17d5" + integrity sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA== + dependencies: + call-bound "^1.0.4" + generator-function "^2.0.0" + get-proto "^1.0.1" + has-tostringtag "^1.0.2" + safe-regex-test "^1.1.0" + +is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: + version "4.0.3" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" + integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== + dependencies: + is-extglob "^2.1.1" + +is-hexadecimal@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/is-hexadecimal/-/is-hexadecimal-2.0.1.tgz#86b5bf668fca307498d319dfc03289d781a90027" + integrity sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg== + +is-in-ci@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-in-ci/-/is-in-ci-2.0.0.tgz#e4b3471c555b47509a8311869c377c234967079f" + integrity sha512-cFeerHriAnhrQSbpAxL37W1wcJKUUX07HyLWZCW1URJT/ra3GyUTzBgUnh24TMVfNTV2Hij2HLxkPHFZfOZy5w== + +is-ip@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/is-ip/-/is-ip-3.1.0.tgz#2ae5ddfafaf05cb8008a62093cf29734f657c5d8" + integrity sha512-35vd5necO7IitFPjd/YBeqwWnyDWbuLH9ZXQdMfDA8TEo7pv5X8yfrvVO3xbJbLUlERCMvf6X0hTUamQxCYJ9Q== + dependencies: + ip-regex "^4.0.0" + +is-map@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/is-map/-/is-map-2.0.3.tgz#ede96b7fe1e270b3c4465e3a465658764926d62e" + integrity sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw== + +is-negative-zero@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.3.tgz#ced903a027aca6381b777a5743069d7376a49747" + integrity sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw== + +is-number-object@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.1.1.tgz#144b21e95a1bc148205dcc2814a9134ec41b2541" + integrity sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw== + dependencies: + call-bound "^1.0.3" + has-tostringtag "^1.0.2" + +is-number@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== + +is-online@10.0.0: + version "10.0.0" + resolved "https://registry.yarnpkg.com/is-online/-/is-online-10.0.0.tgz#5e02cee9f822fd9c19b060f0ecbdc798d37295a3" + integrity sha512-WCPdKwNDjXJJmUubf2VHLMDBkUZEtuOvpXUfUnUFbEnM6In9ByiScL4f4jKACz/fsb2qDkesFerW3snf/AYz3A== + dependencies: + got "^12.1.0" + p-any "^4.0.0" + p-timeout "^5.1.0" + public-ip "^5.0.0" + +is-plain-obj@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-4.1.0.tgz#d65025edec3657ce032fd7db63c97883eaed71f0" + integrity sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg== + +is-regex@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.2.1.tgz#76d70a3ed10ef9be48eb577887d74205bf0cad22" + integrity sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g== + dependencies: + call-bound "^1.0.2" + gopd "^1.2.0" + has-tostringtag "^1.0.2" + hasown "^2.0.2" + +is-set@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/is-set/-/is-set-2.0.3.tgz#8ab209ea424608141372ded6e0cb200ef1d9d01d" + integrity sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg== + +is-shared-array-buffer@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz#9b67844bd9b7f246ba0708c3a93e34269c774f6f" + integrity sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A== + dependencies: + call-bound "^1.0.3" + +is-string@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.1.1.tgz#92ea3f3d5c5b6e039ca8677e5ac8d07ea773cbb9" + integrity sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA== + dependencies: + call-bound "^1.0.3" + has-tostringtag "^1.0.2" + +is-symbol@^1.0.4, is-symbol@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.1.1.tgz#f47761279f532e2b05a7024a7506dbbedacd0634" + integrity sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w== + dependencies: + call-bound "^1.0.2" + has-symbols "^1.1.0" + safe-regex-test "^1.1.0" + +is-typed-array@^1.1.13, is-typed-array@^1.1.14, is-typed-array@^1.1.15: + version "1.1.15" + resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.15.tgz#4bfb4a45b61cee83a5a46fba778e4e8d59c0ce0b" + integrity sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ== + dependencies: + which-typed-array "^1.1.16" + +is-weakmap@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/is-weakmap/-/is-weakmap-2.0.2.tgz#bf72615d649dfe5f699079c54b83e47d1ae19cfd" + integrity sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w== + +is-weakref@^1.0.2, is-weakref@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.1.1.tgz#eea430182be8d64174bd96bffbc46f21bf3f9293" + integrity sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew== + dependencies: + call-bound "^1.0.3" + +is-weakset@^2.0.3: + version "2.0.4" + resolved "https://registry.yarnpkg.com/is-weakset/-/is-weakset-2.0.4.tgz#c9f5deb0bc1906c6d6f1027f284ddf459249daca" + integrity sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ== + dependencies: + call-bound "^1.0.3" + get-intrinsic "^1.2.6" + +is-wsl@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271" + integrity sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww== + dependencies: + is-docker "^2.0.0" + +isarray@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.5.tgz#8af1e4c1221244cc62459faf38940d4e644a5723" + integrity sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw== + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== + +jiti@^1.21.0, jiti@^1.21.7: + version "1.21.7" + resolved "https://registry.yarnpkg.com/jiti/-/jiti-1.21.7.tgz#9dd81043424a3d28458b193d965f0d18a2300ba9" + integrity sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A== + +jose@^6.2.2: + version "6.2.2" + resolved "https://registry.yarnpkg.com/jose/-/jose-6.2.2.tgz#d6b5279b89b3e88d531c202e3fbe351f39a44aac" + integrity sha512-d7kPDd34KO/YnzaDOlikGpOurfF0ByC2sEV4cANCtdqLlTfBlw2p14O/5d/zv40gJPbIQxfES3nSx1/oYNyuZQ== + +js-tokens@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== + +js-yaml@4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" + integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== + dependencies: + argparse "^2.0.1" + +js-yaml@^3.13.1: + version "3.14.2" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.2.tgz#77485ce1dd7f33c061fd1b16ecea23b55fcb04b0" + integrity sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg== + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + +js-yaml@^4.1.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.1.tgz#854c292467705b699476e1a2decc0c8a3458806b" + integrity sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA== + dependencies: + argparse "^2.0.1" + +jsep@^1.2.0, jsep@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/jsep/-/jsep-1.4.0.tgz#19feccbfa51d8a79f72480b4b8e40ce2e17152f0" + integrity sha512-B7qPcEVE3NVkmSJbaYxvv4cHkVW7DQsZz13pUMrfS8z8Q/BuShN+gcTXrUlPiGqM2/t/EEaI030bpxMqY8gMlw== + +json-buffer@3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13" + integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ== + +json-parse-even-better-errors@^2.3.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" + integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== + +json-schema-traverse@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" + integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== + +jsonc-parser@~2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-2.2.1.tgz#db73cd59d78cce28723199466b2a03d1be1df2bc" + integrity sha512-o6/yDBYccGvTz1+QFevz6l6OBZ2+fMVu2JZ9CIhzsYRX4mjaK5IyX9eldUdCmga16zlgQxyrj5pt9kzuj2C02w== + +jsonfile@^6.0.1: + version "6.2.1" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.2.1.tgz#b6e31717f22cc37330b081ce0051ed5de53af2f6" + integrity sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q== + dependencies: + universalify "^2.0.0" + optionalDependencies: + graceful-fs "^4.1.6" + +jsonpath-plus@^10.0.0, jsonpath-plus@^10.3.0, "jsonpath-plus@^6.0.1 || ^10.1.0": + version "10.4.0" + resolved "https://registry.yarnpkg.com/jsonpath-plus/-/jsonpath-plus-10.4.0.tgz#73cf545c231afda21452150b7a2a58e48e109702" + integrity sha512-T92WWatJXmhBbKsgH/0hl+jxjdXrifi5IKeMY02DWggRxX0UElcbVzPlmgLTbvsPeW1PasQ6xE2Q75stkhGbsA== + dependencies: + "@jsep-plugin/assignment" "^1.3.0" + "@jsep-plugin/regex" "^1.0.4" + jsep "^1.4.0" + +jsonpointer@^5.0.0, jsonpointer@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/jsonpointer/-/jsonpointer-5.0.1.tgz#2110e0af0900fd37467b5907ecd13a7884a1b559" + integrity sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ== + +katex@^0.16.0: + version "0.16.45" + resolved "https://registry.yarnpkg.com/katex/-/katex-0.16.45.tgz#ba60d39c54746b6b8d39ce0e7f6eace07143149c" + integrity sha512-pQpZbdBu7wCTmQUh7ufPmLr0pFoObnGUoL/yhtwJDgmmQpbkg/0HSVti25Fu4rmd1oCR6NGWe9vqTWuWv3GcNA== + dependencies: + commander "^8.3.0" + +keytar@^7.9.0: + version "7.9.0" + resolved "https://registry.yarnpkg.com/keytar/-/keytar-7.9.0.tgz#4c6225708f51b50cbf77c5aae81721964c2918cb" + integrity sha512-VPD8mtVtm5JNtA2AErl6Chp06JBfy7diFQ7TQQhdpWOl6MrCRB+eRbvAZUsbGQS9kiMq0coJsy0W0vHpDCkWsQ== + dependencies: + node-addon-api "^4.3.0" + prebuild-install "^7.0.1" + +keyv@^4.5.3: + version "4.5.4" + resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.4.tgz#a879a99e29452f942439f2a405e3af8b31d4de93" + integrity sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw== + dependencies: + json-buffer "3.0.1" + +lcm@0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/lcm/-/lcm-0.0.3.tgz#4a3b11ce0363e297010806080ffeca02f77f8280" + integrity sha512-TB+ZjoillV6B26Vspf9l2L/vKaRY/4ep3hahcyVkCGFgsTNRUQdc24bQeNFiZeoxH0vr5+7SfNRMQuPHv/1IrQ== + dependencies: + gcd "^0.0.1" + +leven@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" + integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A== + +leven@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/leven/-/leven-4.1.0.tgz#1e37150e1711d18bb14e380a5c779995235a710e" + integrity sha512-KZ9W9nWDT7rF7Dazg8xyLHGLrmpgq2nVNFUckhqdW3szVP6YhCpp/RAnpmVExA9JvrMynjwSLVrEj3AepHR6ew== + +lilconfig@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-2.1.0.tgz#78e23ac89ebb7e1bfbf25b18043de756548e7f52" + integrity sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ== + +lilconfig@^3.0.0, lilconfig@^3.1.1, lilconfig@^3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-3.1.3.tgz#a1bcfd6257f9585bf5ae14ceeebb7b559025e4c4" + integrity sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw== + +lines-and-columns@^1.1.6: + version "1.2.4" + resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" + integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== + +lodash.topath@^4.5.2: + version "4.5.2" + resolved "https://registry.yarnpkg.com/lodash.topath/-/lodash.topath-4.5.2.tgz#3616351f3bba61994a0931989660bd03254fd009" + integrity sha512-1/W4dM+35DwvE/iEd1M9ekewOSTlpFekhw9mhAtrwjVqUr83/ilQiyAvmg4tVX7Unkcfl1KC+i9WdaT4B6aQcg== + +lodash@4.17.21: + version "4.17.21" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" + integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== + +lodash@4.18.1, lodash@^4.17.21, lodash@^4.18.1: + version "4.18.1" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.18.1.tgz#ff2b66c1f6326d59513de2407bf881439812771c" + integrity sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q== + +longest-streak@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/longest-streak/-/longest-streak-3.1.0.tgz#62fa67cd958742a1574af9f39866364102d90cd4" + integrity sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g== + +lowercase-keys@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-3.0.0.tgz#c5e7d442e37ead247ae9db117a9d0a467c89d4f2" + integrity sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ== + +lru-cache@^7.14.1: + version "7.18.3" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-7.18.3.tgz#f793896e0fd0e954a59dfdd82f0773808df6aa89" + integrity sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA== + +markdown-extensions@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/markdown-extensions/-/markdown-extensions-2.0.0.tgz#34bebc83e9938cae16e0e017e4a9814a8330d3c4" + integrity sha512-o5vL7aDWatOTX8LzaS1WMoaoxIiLRQJuIKKe2wAw6IeULDHaqbiqiggmx+pKvZDb1Sj+pE46Sn1T7lCqfFtg1Q== + +markdown-table@^3.0.0: + version "3.0.4" + resolved "https://registry.yarnpkg.com/markdown-table/-/markdown-table-3.0.4.tgz#fe44d6d410ff9d6f2ea1797a3f60aa4d2b631c2a" + integrity sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw== + +math-intrinsics@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/math-intrinsics/-/math-intrinsics-1.1.0.tgz#a0dd74be81e2aa5c2f27e65ce283605ee4e2b7f9" + integrity sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g== + +mdast-util-find-and-replace@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/mdast-util-find-and-replace/-/mdast-util-find-and-replace-3.0.2.tgz#70a3174c894e14df722abf43bc250cbae44b11df" + integrity sha512-Tmd1Vg/m3Xz43afeNxDIhWRtFZgM2VLyaf4vSTYwudTyeuTneoL3qtWMA5jeLyz/O1vDJmmV4QuScFCA2tBPwg== + dependencies: + "@types/mdast" "^4.0.0" + escape-string-regexp "^5.0.0" + unist-util-is "^6.0.0" + unist-util-visit-parents "^6.0.0" + +mdast-util-from-markdown@2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.2.tgz#4850390ca7cf17413a9b9a0fbefcd1bc0eb4160a" + integrity sha512-uZhTV/8NBuw0WHkPTrCqDOl0zVe1BIng5ZtHoDk49ME1qqcjYmmLmOf0gELgcRMxN4w2iuIeVso5/6QymSrgmA== + dependencies: + "@types/mdast" "^4.0.0" + "@types/unist" "^3.0.0" + decode-named-character-reference "^1.0.0" + devlop "^1.0.0" + mdast-util-to-string "^4.0.0" + micromark "^4.0.0" + micromark-util-decode-numeric-character-reference "^2.0.0" + micromark-util-decode-string "^2.0.0" + micromark-util-normalize-identifier "^2.0.0" + micromark-util-symbol "^2.0.0" + micromark-util-types "^2.0.0" + unist-util-stringify-position "^4.0.0" + +mdast-util-from-markdown@^2.0.0, mdast-util-from-markdown@^2.0.2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.3.tgz#c95822b91aab75f18a4cbe8b2f51b873ed2cf0c7" + integrity sha512-W4mAWTvSlKvf8L6J+VN9yLSqQ9AOAAvHuoDAmPkz4dHf553m5gVj2ejadHJhoJmcmxEnOv6Pa8XJhpxE93kb8Q== + dependencies: + "@types/mdast" "^4.0.0" + "@types/unist" "^3.0.0" + decode-named-character-reference "^1.0.0" + devlop "^1.0.0" + mdast-util-to-string "^4.0.0" + micromark "^4.0.0" + micromark-util-decode-numeric-character-reference "^2.0.0" + micromark-util-decode-string "^2.0.0" + micromark-util-normalize-identifier "^2.0.0" + micromark-util-symbol "^2.0.0" + micromark-util-types "^2.0.0" + unist-util-stringify-position "^4.0.0" + +mdast-util-frontmatter@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/mdast-util-frontmatter/-/mdast-util-frontmatter-2.0.1.tgz#f5f929eb1eb36c8a7737475c7eb438261f964ee8" + integrity sha512-LRqI9+wdgC25P0URIJY9vwocIzCcksduHQ9OF2joxQoyTNVduwLAFUzjoopuRJbJAReaKrNQKAZKL3uCMugWJA== + dependencies: + "@types/mdast" "^4.0.0" + devlop "^1.0.0" + escape-string-regexp "^5.0.0" + mdast-util-from-markdown "^2.0.0" + mdast-util-to-markdown "^2.0.0" + micromark-extension-frontmatter "^2.0.0" + +mdast-util-gfm-autolink-literal@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/mdast-util-gfm-autolink-literal/-/mdast-util-gfm-autolink-literal-2.0.1.tgz#abd557630337bd30a6d5a4bd8252e1c2dc0875d5" + integrity sha512-5HVP2MKaP6L+G6YaxPNjuL0BPrq9orG3TsrZ9YXbA3vDw/ACI4MEsnoDpn6ZNm7GnZgtAcONJyPhOP8tNJQavQ== + dependencies: + "@types/mdast" "^4.0.0" + ccount "^2.0.0" + devlop "^1.0.0" + mdast-util-find-and-replace "^3.0.0" + micromark-util-character "^2.0.0" + +mdast-util-gfm-footnote@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/mdast-util-gfm-footnote/-/mdast-util-gfm-footnote-2.1.0.tgz#7778e9d9ca3df7238cc2bd3fa2b1bf6a65b19403" + integrity sha512-sqpDWlsHn7Ac9GNZQMeUzPQSMzR6Wv0WKRNvQRg0KqHh02fpTz69Qc1QSseNX29bhz1ROIyNyxExfawVKTm1GQ== + dependencies: + "@types/mdast" "^4.0.0" + devlop "^1.1.0" + mdast-util-from-markdown "^2.0.0" + mdast-util-to-markdown "^2.0.0" + micromark-util-normalize-identifier "^2.0.0" + +mdast-util-gfm-strikethrough@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/mdast-util-gfm-strikethrough/-/mdast-util-gfm-strikethrough-2.0.0.tgz#d44ef9e8ed283ac8c1165ab0d0dfd058c2764c16" + integrity sha512-mKKb915TF+OC5ptj5bJ7WFRPdYtuHv0yTRxK2tJvi+BDqbkiG7h7u/9SI89nRAYcmap2xHQL9D+QG/6wSrTtXg== + dependencies: + "@types/mdast" "^4.0.0" + mdast-util-from-markdown "^2.0.0" + mdast-util-to-markdown "^2.0.0" + +mdast-util-gfm-table@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/mdast-util-gfm-table/-/mdast-util-gfm-table-2.0.0.tgz#7a435fb6223a72b0862b33afbd712b6dae878d38" + integrity sha512-78UEvebzz/rJIxLvE7ZtDd/vIQ0RHv+3Mh5DR96p7cS7HsBhYIICDBCu8csTNWNO6tBWfqXPWekRuj2FNOGOZg== + dependencies: + "@types/mdast" "^4.0.0" + devlop "^1.0.0" + markdown-table "^3.0.0" + mdast-util-from-markdown "^2.0.0" + mdast-util-to-markdown "^2.0.0" + +mdast-util-gfm-task-list-item@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/mdast-util-gfm-task-list-item/-/mdast-util-gfm-task-list-item-2.0.0.tgz#e68095d2f8a4303ef24094ab642e1047b991a936" + integrity sha512-IrtvNvjxC1o06taBAVJznEnkiHxLFTzgonUdy8hzFVeDun0uTjxxrRGVaNFqkU1wJR3RBPEfsxmU6jDWPofrTQ== + dependencies: + "@types/mdast" "^4.0.0" + devlop "^1.0.0" + mdast-util-from-markdown "^2.0.0" + mdast-util-to-markdown "^2.0.0" + +mdast-util-gfm@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/mdast-util-gfm/-/mdast-util-gfm-3.0.0.tgz#3f2aecc879785c3cb6a81ff3a243dc11eca61095" + integrity sha512-dgQEX5Amaq+DuUqf26jJqSK9qgixgd6rYDHAv4aTBuA92cTknZlKpPfa86Z/s8Dj8xsAQpFfBmPUHWJBWqS4Bw== + dependencies: + mdast-util-from-markdown "^2.0.0" + mdast-util-gfm-autolink-literal "^2.0.0" + mdast-util-gfm-footnote "^2.0.0" + mdast-util-gfm-strikethrough "^2.0.0" + mdast-util-gfm-table "^2.0.0" + mdast-util-gfm-task-list-item "^2.0.0" + mdast-util-to-markdown "^2.0.0" + +mdast-util-gfm@^3.0.0, mdast-util-gfm@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/mdast-util-gfm/-/mdast-util-gfm-3.1.0.tgz#2cdf63b92c2a331406b0fb0db4c077c1b0331751" + integrity sha512-0ulfdQOM3ysHhCJ1p06l0b0VKlhU0wuQs3thxZQagjcjPrlFRqY215uZGHHJan9GEAXd9MbfPjFJz+qMkVR6zQ== + dependencies: + mdast-util-from-markdown "^2.0.0" + mdast-util-gfm-autolink-literal "^2.0.0" + mdast-util-gfm-footnote "^2.0.0" + mdast-util-gfm-strikethrough "^2.0.0" + mdast-util-gfm-table "^2.0.0" + mdast-util-gfm-task-list-item "^2.0.0" + mdast-util-to-markdown "^2.0.0" + +mdast-util-math@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/mdast-util-math/-/mdast-util-math-3.0.0.tgz#8d79dd3baf8ab8ac781f62b8853768190b9a00b0" + integrity sha512-Tl9GBNeG/AhJnQM221bJR2HPvLOSnLE/T9cJI9tlc6zwQk2nPk/4f0cHkOdEixQPC/j8UtKDdITswvLAy1OZ1w== + dependencies: + "@types/hast" "^3.0.0" + "@types/mdast" "^4.0.0" + devlop "^1.0.0" + longest-streak "^3.0.0" + mdast-util-from-markdown "^2.0.0" + mdast-util-to-markdown "^2.1.0" + unist-util-remove-position "^5.0.0" + +mdast-util-mdx-expression@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/mdast-util-mdx-expression/-/mdast-util-mdx-expression-2.0.1.tgz#43f0abac9adc756e2086f63822a38c8d3c3a5096" + integrity sha512-J6f+9hUp+ldTZqKRSg7Vw5V6MqjATc+3E4gf3CFNcuZNWD8XdyI6zQ8GqH7f8169MM6P7hMBRDVGnn7oHB9kXQ== + dependencies: + "@types/estree-jsx" "^1.0.0" + "@types/hast" "^3.0.0" + "@types/mdast" "^4.0.0" + devlop "^1.0.0" + mdast-util-from-markdown "^2.0.0" + mdast-util-to-markdown "^2.0.0" + +mdast-util-mdx-jsx@3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/mdast-util-mdx-jsx/-/mdast-util-mdx-jsx-3.1.3.tgz#76b957b3da18ebcfd0de3a9b4451dcd6fdec2320" + integrity sha512-bfOjvNt+1AcbPLTFMFWY149nJz0OjmewJs3LQQ5pIyVGxP4CdOqNVJL6kTaM5c68p8q82Xv3nCyFfUnuEcH3UQ== + dependencies: + "@types/estree-jsx" "^1.0.0" + "@types/hast" "^3.0.0" + "@types/mdast" "^4.0.0" + "@types/unist" "^3.0.0" + ccount "^2.0.0" + devlop "^1.1.0" + mdast-util-from-markdown "^2.0.0" + mdast-util-to-markdown "^2.0.0" + parse-entities "^4.0.0" + stringify-entities "^4.0.0" + unist-util-stringify-position "^4.0.0" + vfile-message "^4.0.0" + +mdast-util-mdx-jsx@3.2.0, mdast-util-mdx-jsx@^3.0.0, mdast-util-mdx-jsx@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/mdast-util-mdx-jsx/-/mdast-util-mdx-jsx-3.2.0.tgz#fd04c67a2a7499efb905a8a5c578dddc9fdada0d" + integrity sha512-lj/z8v0r6ZtsN/cGNNtemmmfoLAFZnjMbNyLzBafjzikOM+glrjNHPlf6lQDOTccj9n5b0PPihEBbhneMyGs1Q== + dependencies: + "@types/estree-jsx" "^1.0.0" + "@types/hast" "^3.0.0" + "@types/mdast" "^4.0.0" + "@types/unist" "^3.0.0" + ccount "^2.0.0" + devlop "^1.1.0" + mdast-util-from-markdown "^2.0.0" + mdast-util-to-markdown "^2.0.0" + parse-entities "^4.0.0" + stringify-entities "^4.0.0" + unist-util-stringify-position "^4.0.0" + vfile-message "^4.0.0" + +mdast-util-mdx@3.0.0, mdast-util-mdx@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/mdast-util-mdx/-/mdast-util-mdx-3.0.0.tgz#792f9cf0361b46bee1fdf1ef36beac424a099c41" + integrity sha512-JfbYLAW7XnYTTbUsmpu0kdBUVe+yKVJZBItEjwyYJiDJuZ9w4eeaqks4HQO+R7objWgS2ymV60GYpI14Ug554w== + dependencies: + mdast-util-from-markdown "^2.0.0" + mdast-util-mdx-expression "^2.0.0" + mdast-util-mdx-jsx "^3.0.0" + mdast-util-mdxjs-esm "^2.0.0" + mdast-util-to-markdown "^2.0.0" + +mdast-util-mdxjs-esm@^2.0.0, mdast-util-mdxjs-esm@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/mdast-util-mdxjs-esm/-/mdast-util-mdxjs-esm-2.0.1.tgz#019cfbe757ad62dd557db35a695e7314bcc9fa97" + integrity sha512-EcmOpxsZ96CvlP03NghtH1EsLtr0n9Tm4lPUJUBccV9RwUOneqSycg19n5HGzCf+10LozMRSObtVr3ee1WoHtg== + dependencies: + "@types/estree-jsx" "^1.0.0" + "@types/hast" "^3.0.0" + "@types/mdast" "^4.0.0" + devlop "^1.0.0" + mdast-util-from-markdown "^2.0.0" + mdast-util-to-markdown "^2.0.0" + +mdast-util-phrasing@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/mdast-util-phrasing/-/mdast-util-phrasing-4.1.0.tgz#7cc0a8dec30eaf04b7b1a9661a92adb3382aa6e3" + integrity sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w== + dependencies: + "@types/mdast" "^4.0.0" + unist-util-is "^6.0.0" + +mdast-util-to-hast@^13.0.0, mdast-util-to-hast@^13.2.0: + version "13.2.1" + resolved "https://registry.yarnpkg.com/mdast-util-to-hast/-/mdast-util-to-hast-13.2.1.tgz#d7ff84ca499a57e2c060ae67548ad950e689a053" + integrity sha512-cctsq2wp5vTsLIcaymblUriiTcZd0CwWtCbLvrOzYCDZoWyMNV8sZ7krj09FSnsiJi3WVsHLM4k6Dq/yaPyCXA== + dependencies: + "@types/hast" "^3.0.0" + "@types/mdast" "^4.0.0" + "@ungap/structured-clone" "^1.0.0" + devlop "^1.0.0" + micromark-util-sanitize-uri "^2.0.0" + trim-lines "^3.0.0" + unist-util-position "^5.0.0" + unist-util-visit "^5.0.0" + vfile "^6.0.0" + +mdast-util-to-markdown@^2.0.0, mdast-util-to-markdown@^2.1.0: + version "2.1.2" + resolved "https://registry.yarnpkg.com/mdast-util-to-markdown/-/mdast-util-to-markdown-2.1.2.tgz#f910ffe60897f04bb4b7e7ee434486f76288361b" + integrity sha512-xj68wMTvGXVOKonmog6LwyJKrYXZPvlwabaryTjLh9LuvovB/KAH+kvi8Gjj+7rJjsFi23nkUxRQv1KqSroMqA== + dependencies: + "@types/mdast" "^4.0.0" + "@types/unist" "^3.0.0" + longest-streak "^3.0.0" + mdast-util-phrasing "^4.0.0" + mdast-util-to-string "^4.0.0" + micromark-util-classify-character "^2.0.0" + micromark-util-decode-string "^2.0.0" + unist-util-visit "^5.0.0" + zwitch "^2.0.0" + +mdast-util-to-string@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/mdast-util-to-string/-/mdast-util-to-string-4.0.0.tgz#7a5121475556a04e7eddeb67b264aae79d312814" + integrity sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg== + dependencies: + "@types/mdast" "^4.0.0" + +media-typer@0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" + integrity sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ== + +merge-descriptors@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" + integrity sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w== + +merge2@^1.3.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" + integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== + +methods@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" + integrity sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w== + +micromark-core-commonmark@^2.0.0: + version "2.0.3" + resolved "https://registry.yarnpkg.com/micromark-core-commonmark/-/micromark-core-commonmark-2.0.3.tgz#c691630e485021a68cf28dbc2b2ca27ebf678cd4" + integrity sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg== + dependencies: + decode-named-character-reference "^1.0.0" + devlop "^1.0.0" + micromark-factory-destination "^2.0.0" + micromark-factory-label "^2.0.0" + micromark-factory-space "^2.0.0" + micromark-factory-title "^2.0.0" + micromark-factory-whitespace "^2.0.0" + micromark-util-character "^2.0.0" + micromark-util-chunked "^2.0.0" + micromark-util-classify-character "^2.0.0" + micromark-util-html-tag-name "^2.0.0" + micromark-util-normalize-identifier "^2.0.0" + micromark-util-resolve-all "^2.0.0" + micromark-util-subtokenize "^2.0.0" + micromark-util-symbol "^2.0.0" + micromark-util-types "^2.0.0" + +micromark-extension-frontmatter@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/micromark-extension-frontmatter/-/micromark-extension-frontmatter-2.0.0.tgz#651c52ffa5d7a8eeed687c513cd869885882d67a" + integrity sha512-C4AkuM3dA58cgZha7zVnuVxBhDsbttIMiytjgsM2XbHAB2faRVaHRle40558FBN+DJcrLNCoqG5mlrpdU4cRtg== + dependencies: + fault "^2.0.0" + micromark-util-character "^2.0.0" + micromark-util-symbol "^2.0.0" + micromark-util-types "^2.0.0" + +micromark-extension-gfm-autolink-literal@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/micromark-extension-gfm-autolink-literal/-/micromark-extension-gfm-autolink-literal-2.1.0.tgz#6286aee9686c4462c1e3552a9d505feddceeb935" + integrity sha512-oOg7knzhicgQ3t4QCjCWgTmfNhvQbDDnJeVu9v81r7NltNCVmhPy1fJRX27pISafdjL+SVc4d3l48Gb6pbRypw== + dependencies: + micromark-util-character "^2.0.0" + micromark-util-sanitize-uri "^2.0.0" + micromark-util-symbol "^2.0.0" + micromark-util-types "^2.0.0" + +micromark-extension-gfm-footnote@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/micromark-extension-gfm-footnote/-/micromark-extension-gfm-footnote-2.1.0.tgz#4dab56d4e398b9853f6fe4efac4fc9361f3e0750" + integrity sha512-/yPhxI1ntnDNsiHtzLKYnE3vf9JZ6cAisqVDauhp4CEHxlb4uoOTxOCJ+9s51bIB8U1N1FJ1RXOKTIlD5B/gqw== + dependencies: + devlop "^1.0.0" + micromark-core-commonmark "^2.0.0" + micromark-factory-space "^2.0.0" + micromark-util-character "^2.0.0" + micromark-util-normalize-identifier "^2.0.0" + micromark-util-sanitize-uri "^2.0.0" + micromark-util-symbol "^2.0.0" + micromark-util-types "^2.0.0" + +micromark-extension-gfm-strikethrough@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/micromark-extension-gfm-strikethrough/-/micromark-extension-gfm-strikethrough-2.1.0.tgz#86106df8b3a692b5f6a92280d3879be6be46d923" + integrity sha512-ADVjpOOkjz1hhkZLlBiYA9cR2Anf8F4HqZUO6e5eDcPQd0Txw5fxLzzxnEkSkfnD0wziSGiv7sYhk/ktvbf1uw== + dependencies: + devlop "^1.0.0" + micromark-util-chunked "^2.0.0" + micromark-util-classify-character "^2.0.0" + micromark-util-resolve-all "^2.0.0" + micromark-util-symbol "^2.0.0" + micromark-util-types "^2.0.0" + +micromark-extension-gfm-table@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/micromark-extension-gfm-table/-/micromark-extension-gfm-table-2.1.1.tgz#fac70bcbf51fe65f5f44033118d39be8a9b5940b" + integrity sha512-t2OU/dXXioARrC6yWfJ4hqB7rct14e8f7m0cbI5hUmDyyIlwv5vEtooptH8INkbLzOatzKuVbQmAYcbWoyz6Dg== + dependencies: + devlop "^1.0.0" + micromark-factory-space "^2.0.0" + micromark-util-character "^2.0.0" + micromark-util-symbol "^2.0.0" + micromark-util-types "^2.0.0" + +micromark-extension-gfm-tagfilter@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/micromark-extension-gfm-tagfilter/-/micromark-extension-gfm-tagfilter-2.0.0.tgz#f26d8a7807b5985fba13cf61465b58ca5ff7dc57" + integrity sha512-xHlTOmuCSotIA8TW1mDIM6X2O1SiX5P9IuDtqGonFhEK0qgRI4yeC6vMxEV2dgyr2TiD+2PQ10o+cOhdVAcwfg== + dependencies: + micromark-util-types "^2.0.0" + +micromark-extension-gfm-task-list-item@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/micromark-extension-gfm-task-list-item/-/micromark-extension-gfm-task-list-item-2.1.0.tgz#bcc34d805639829990ec175c3eea12bb5b781f2c" + integrity sha512-qIBZhqxqI6fjLDYFTBIa4eivDMnP+OZqsNwmQ3xNLE4Cxwc+zfQEfbs6tzAo2Hjq+bh6q5F+Z8/cksrLFYWQQw== + dependencies: + devlop "^1.0.0" + micromark-factory-space "^2.0.0" + micromark-util-character "^2.0.0" + micromark-util-symbol "^2.0.0" + micromark-util-types "^2.0.0" + +micromark-extension-gfm@3.0.0, micromark-extension-gfm@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/micromark-extension-gfm/-/micromark-extension-gfm-3.0.0.tgz#3e13376ab95dd7a5cfd0e29560dfe999657b3c5b" + integrity sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w== + dependencies: + micromark-extension-gfm-autolink-literal "^2.0.0" + micromark-extension-gfm-footnote "^2.0.0" + micromark-extension-gfm-strikethrough "^2.0.0" + micromark-extension-gfm-table "^2.0.0" + micromark-extension-gfm-tagfilter "^2.0.0" + micromark-extension-gfm-task-list-item "^2.0.0" + micromark-util-combine-extensions "^2.0.0" + micromark-util-types "^2.0.0" + +micromark-extension-math@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/micromark-extension-math/-/micromark-extension-math-3.1.0.tgz#c42ee3b1dd5a9a03584e83dd8f08e3de510212c1" + integrity sha512-lvEqd+fHjATVs+2v/8kg9i5Q0AP2k85H0WUOwpIVvUML8BapsMvh1XAogmQjOCsLpoKRCVQqEkQBB3NhVBcsOg== + dependencies: + "@types/katex" "^0.16.0" + devlop "^1.0.0" + katex "^0.16.0" + micromark-factory-space "^2.0.0" + micromark-util-character "^2.0.0" + micromark-util-symbol "^2.0.0" + micromark-util-types "^2.0.0" + +micromark-extension-mdx-expression@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/micromark-extension-mdx-expression/-/micromark-extension-mdx-expression-3.0.1.tgz#43d058d999532fb3041195a3c3c05c46fa84543b" + integrity sha512-dD/ADLJ1AeMvSAKBwO22zG22N4ybhe7kFIZ3LsDI0GlsNr2A3KYxb0LdC1u5rj4Nw+CHKY0RVdnHX8vj8ejm4Q== + dependencies: + "@types/estree" "^1.0.0" + devlop "^1.0.0" + micromark-factory-mdx-expression "^2.0.0" + micromark-factory-space "^2.0.0" + micromark-util-character "^2.0.0" + micromark-util-events-to-acorn "^2.0.0" + micromark-util-symbol "^2.0.0" + micromark-util-types "^2.0.0" + +micromark-extension-mdx-jsx@3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/micromark-extension-mdx-jsx/-/micromark-extension-mdx-jsx-3.0.1.tgz#5abb83da5ddc8e473a374453e6ea56fbd66b59ad" + integrity sha512-vNuFb9czP8QCtAQcEJn0UJQJZA8Dk6DXKBqx+bg/w0WGuSxDxNr7hErW89tHUY31dUW4NqEOWwmEUNhjTFmHkg== + dependencies: + "@types/acorn" "^4.0.0" + "@types/estree" "^1.0.0" + devlop "^1.0.0" + estree-util-is-identifier-name "^3.0.0" + micromark-factory-mdx-expression "^2.0.0" + micromark-factory-space "^2.0.0" + micromark-util-character "^2.0.0" + micromark-util-events-to-acorn "^2.0.0" + micromark-util-symbol "^2.0.0" + micromark-util-types "^2.0.0" + vfile-message "^4.0.0" + +micromark-extension-mdx-jsx@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/micromark-extension-mdx-jsx/-/micromark-extension-mdx-jsx-3.0.2.tgz#ffc98bdb649798902fa9fc5689f67f9c1c902044" + integrity sha512-e5+q1DjMh62LZAJOnDraSSbDMvGJ8x3cbjygy2qFEi7HCeUT4BDKCvMozPozcD6WmOt6sVvYDNBKhFSz3kjOVQ== + dependencies: + "@types/estree" "^1.0.0" + devlop "^1.0.0" + estree-util-is-identifier-name "^3.0.0" + micromark-factory-mdx-expression "^2.0.0" + micromark-factory-space "^2.0.0" + micromark-util-character "^2.0.0" + micromark-util-events-to-acorn "^2.0.0" + micromark-util-symbol "^2.0.0" + micromark-util-types "^2.0.0" + vfile-message "^4.0.0" + +micromark-extension-mdx-md@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/micromark-extension-mdx-md/-/micromark-extension-mdx-md-2.0.0.tgz#1d252881ea35d74698423ab44917e1f5b197b92d" + integrity sha512-EpAiszsB3blw4Rpba7xTOUptcFeBFi+6PY8VnJ2hhimH+vCQDirWgsMpz7w1XcZE7LVrSAUGb9VJpG9ghlYvYQ== + dependencies: + micromark-util-types "^2.0.0" + +micromark-extension-mdxjs-esm@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/micromark-extension-mdxjs-esm/-/micromark-extension-mdxjs-esm-3.0.0.tgz#de21b2b045fd2059bd00d36746081de38390d54a" + integrity sha512-DJFl4ZqkErRpq/dAPyeWp15tGrcrrJho1hKK5uBS70BCtfrIFg81sqcTVu3Ta+KD1Tk5vAtBNElWxtAa+m8K9A== + dependencies: + "@types/estree" "^1.0.0" + devlop "^1.0.0" + micromark-core-commonmark "^2.0.0" + micromark-util-character "^2.0.0" + micromark-util-events-to-acorn "^2.0.0" + micromark-util-symbol "^2.0.0" + micromark-util-types "^2.0.0" + unist-util-position-from-estree "^2.0.0" + vfile-message "^4.0.0" + +micromark-extension-mdxjs@3.0.0, micromark-extension-mdxjs@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/micromark-extension-mdxjs/-/micromark-extension-mdxjs-3.0.0.tgz#b5a2e0ed449288f3f6f6c544358159557549de18" + integrity sha512-A873fJfhnJ2siZyUrJ31l34Uqwy4xIFmvPY1oj+Ean5PHcPBYzEsvqvWGaWcfEIr11O5Dlw3p2y0tZWpKHDejQ== + dependencies: + acorn "^8.0.0" + acorn-jsx "^5.0.0" + micromark-extension-mdx-expression "^3.0.0" + micromark-extension-mdx-jsx "^3.0.0" + micromark-extension-mdx-md "^2.0.0" + micromark-extension-mdxjs-esm "^3.0.0" + micromark-util-combine-extensions "^2.0.0" + micromark-util-types "^2.0.0" + +micromark-factory-destination@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/micromark-factory-destination/-/micromark-factory-destination-2.0.1.tgz#8fef8e0f7081f0474fbdd92deb50c990a0264639" + integrity sha512-Xe6rDdJlkmbFRExpTOmRj9N3MaWmbAgdpSrBQvCFqhezUn4AHqJHbaEnfbVYYiexVSs//tqOdY/DxhjdCiJnIA== + dependencies: + micromark-util-character "^2.0.0" + micromark-util-symbol "^2.0.0" + micromark-util-types "^2.0.0" + +micromark-factory-label@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/micromark-factory-label/-/micromark-factory-label-2.0.1.tgz#5267efa97f1e5254efc7f20b459a38cb21058ba1" + integrity sha512-VFMekyQExqIW7xIChcXn4ok29YE3rnuyveW3wZQWWqF4Nv9Wk5rgJ99KzPvHjkmPXF93FXIbBp6YdW3t71/7Vg== + dependencies: + devlop "^1.0.0" + micromark-util-character "^2.0.0" + micromark-util-symbol "^2.0.0" + micromark-util-types "^2.0.0" + +micromark-factory-mdx-expression@^2.0.0: + version "2.0.3" + resolved "https://registry.yarnpkg.com/micromark-factory-mdx-expression/-/micromark-factory-mdx-expression-2.0.3.tgz#bb09988610589c07d1c1e4425285895041b3dfa9" + integrity sha512-kQnEtA3vzucU2BkrIa8/VaSAsP+EJ3CKOvhMuJgOEGg9KDC6OAY6nSnNDVRiVNRqj7Y4SlSzcStaH/5jge8JdQ== + dependencies: + "@types/estree" "^1.0.0" + devlop "^1.0.0" + micromark-factory-space "^2.0.0" + micromark-util-character "^2.0.0" + micromark-util-events-to-acorn "^2.0.0" + micromark-util-symbol "^2.0.0" + micromark-util-types "^2.0.0" + unist-util-position-from-estree "^2.0.0" + vfile-message "^4.0.0" + +micromark-factory-space@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/micromark-factory-space/-/micromark-factory-space-2.0.1.tgz#36d0212e962b2b3121f8525fc7a3c7c029f334fc" + integrity sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg== + dependencies: + micromark-util-character "^2.0.0" + micromark-util-types "^2.0.0" + +micromark-factory-title@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/micromark-factory-title/-/micromark-factory-title-2.0.1.tgz#237e4aa5d58a95863f01032d9ee9b090f1de6e94" + integrity sha512-5bZ+3CjhAd9eChYTHsjy6TGxpOFSKgKKJPJxr293jTbfry2KDoWkhBb6TcPVB4NmzaPhMs1Frm9AZH7OD4Cjzw== + dependencies: + micromark-factory-space "^2.0.0" + micromark-util-character "^2.0.0" + micromark-util-symbol "^2.0.0" + micromark-util-types "^2.0.0" + +micromark-factory-whitespace@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/micromark-factory-whitespace/-/micromark-factory-whitespace-2.0.1.tgz#06b26b2983c4d27bfcc657b33e25134d4868b0b1" + integrity sha512-Ob0nuZ3PKt/n0hORHyvoD9uZhr+Za8sFoP+OnMcnWK5lngSzALgQYKMr9RJVOWLqQYuyn6ulqGWSXdwf6F80lQ== + dependencies: + micromark-factory-space "^2.0.0" + micromark-util-character "^2.0.0" + micromark-util-symbol "^2.0.0" + micromark-util-types "^2.0.0" + +micromark-util-character@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/micromark-util-character/-/micromark-util-character-2.1.1.tgz#2f987831a40d4c510ac261e89852c4e9703ccda6" + integrity sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q== + dependencies: + micromark-util-symbol "^2.0.0" + micromark-util-types "^2.0.0" + +micromark-util-chunked@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/micromark-util-chunked/-/micromark-util-chunked-2.0.1.tgz#47fbcd93471a3fccab86cff03847fc3552db1051" + integrity sha512-QUNFEOPELfmvv+4xiNg2sRYeS/P84pTW0TCgP5zc9FpXetHY0ab7SxKyAQCNCc1eK0459uoLI1y5oO5Vc1dbhA== + dependencies: + micromark-util-symbol "^2.0.0" + +micromark-util-classify-character@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/micromark-util-classify-character/-/micromark-util-classify-character-2.0.1.tgz#d399faf9c45ca14c8b4be98b1ea481bced87b629" + integrity sha512-K0kHzM6afW/MbeWYWLjoHQv1sgg2Q9EccHEDzSkxiP/EaagNzCm7T/WMKZ3rjMbvIpvBiZgwR3dKMygtA4mG1Q== + dependencies: + micromark-util-character "^2.0.0" + micromark-util-symbol "^2.0.0" + micromark-util-types "^2.0.0" + +micromark-util-combine-extensions@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/micromark-util-combine-extensions/-/micromark-util-combine-extensions-2.0.1.tgz#2a0f490ab08bff5cc2fd5eec6dd0ca04f89b30a9" + integrity sha512-OnAnH8Ujmy59JcyZw8JSbK9cGpdVY44NKgSM7E9Eh7DiLS2E9RNQf0dONaGDzEG9yjEl5hcqeIsj4hfRkLH/Bg== + dependencies: + micromark-util-chunked "^2.0.0" + micromark-util-types "^2.0.0" + +micromark-util-decode-numeric-character-reference@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-2.0.2.tgz#fcf15b660979388e6f118cdb6bf7d79d73d26fe5" + integrity sha512-ccUbYk6CwVdkmCQMyr64dXz42EfHGkPQlBj5p7YVGzq8I7CtjXZJrubAYezf7Rp+bjPseiROqe7G6foFd+lEuw== + dependencies: + micromark-util-symbol "^2.0.0" + +micromark-util-decode-string@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/micromark-util-decode-string/-/micromark-util-decode-string-2.0.1.tgz#6cb99582e5d271e84efca8e61a807994d7161eb2" + integrity sha512-nDV/77Fj6eH1ynwscYTOsbK7rR//Uj0bZXBwJZRfaLEJ1iGBR6kIfNmlNqaqJf649EP0F3NWNdeJi03elllNUQ== + dependencies: + decode-named-character-reference "^1.0.0" + micromark-util-character "^2.0.0" + micromark-util-decode-numeric-character-reference "^2.0.0" + micromark-util-symbol "^2.0.0" + +micromark-util-encode@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/micromark-util-encode/-/micromark-util-encode-2.0.1.tgz#0d51d1c095551cfaac368326963cf55f15f540b8" + integrity sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw== + +micromark-util-events-to-acorn@^2.0.0: + version "2.0.3" + resolved "https://registry.yarnpkg.com/micromark-util-events-to-acorn/-/micromark-util-events-to-acorn-2.0.3.tgz#e7a8a6b55a47e5a06c720d5a1c4abae8c37c98f3" + integrity sha512-jmsiEIiZ1n7X1Rr5k8wVExBQCg5jy4UXVADItHmNk1zkwEVhBuIUKRu3fqv+hs4nxLISi2DQGlqIOGiFxgbfHg== + dependencies: + "@types/estree" "^1.0.0" + "@types/unist" "^3.0.0" + devlop "^1.0.0" + estree-util-visit "^2.0.0" + micromark-util-symbol "^2.0.0" + micromark-util-types "^2.0.0" + vfile-message "^4.0.0" + +micromark-util-html-tag-name@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/micromark-util-html-tag-name/-/micromark-util-html-tag-name-2.0.1.tgz#e40403096481986b41c106627f98f72d4d10b825" + integrity sha512-2cNEiYDhCWKI+Gs9T0Tiysk136SnR13hhO8yW6BGNyhOC4qYFnwF1nKfD3HFAIXA5c45RrIG1ub11GiXeYd1xA== + +micromark-util-normalize-identifier@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-2.0.1.tgz#c30d77b2e832acf6526f8bf1aa47bc9c9438c16d" + integrity sha512-sxPqmo70LyARJs0w2UclACPUUEqltCkJ6PhKdMIDuJ3gSf/Q+/GIe3WKl0Ijb/GyH9lOpUkRAO2wp0GVkLvS9Q== + dependencies: + micromark-util-symbol "^2.0.0" + +micromark-util-resolve-all@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/micromark-util-resolve-all/-/micromark-util-resolve-all-2.0.1.tgz#e1a2d62cdd237230a2ae11839027b19381e31e8b" + integrity sha512-VdQyxFWFT2/FGJgwQnJYbe1jjQoNTS4RjglmSjTUlpUMa95Htx9NHeYW4rGDJzbjvCsl9eLjMQwGeElsqmzcHg== + dependencies: + micromark-util-types "^2.0.0" + +micromark-util-sanitize-uri@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.1.tgz#ab89789b818a58752b73d6b55238621b7faa8fd7" + integrity sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ== + dependencies: + micromark-util-character "^2.0.0" + micromark-util-encode "^2.0.0" + micromark-util-symbol "^2.0.0" + +micromark-util-subtokenize@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/micromark-util-subtokenize/-/micromark-util-subtokenize-2.1.0.tgz#d8ade5ba0f3197a1cf6a2999fbbfe6357a1a19ee" + integrity sha512-XQLu552iSctvnEcgXw6+Sx75GflAPNED1qx7eBJ+wydBb2KCbRZe+NwvIEEMM83uml1+2WSXpBAcp9IUCgCYWA== + dependencies: + devlop "^1.0.0" + micromark-util-chunked "^2.0.0" + micromark-util-symbol "^2.0.0" + micromark-util-types "^2.0.0" + +micromark-util-symbol@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz#e5da494e8eb2b071a0d08fb34f6cefec6c0a19b8" + integrity sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q== + +micromark-util-types@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/micromark-util-types/-/micromark-util-types-2.0.2.tgz#f00225f5f5a0ebc3254f96c36b6605c4b393908e" + integrity sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA== + +micromark@^4.0.0: + version "4.0.2" + resolved "https://registry.yarnpkg.com/micromark/-/micromark-4.0.2.tgz#91395a3e1884a198e62116e33c9c568e39936fdb" + integrity sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA== + dependencies: + "@types/debug" "^4.0.0" + debug "^4.0.0" + decode-named-character-reference "^1.0.0" + devlop "^1.0.0" + micromark-core-commonmark "^2.0.0" + micromark-factory-space "^2.0.0" + micromark-util-character "^2.0.0" + micromark-util-chunked "^2.0.0" + micromark-util-combine-extensions "^2.0.0" + micromark-util-decode-numeric-character-reference "^2.0.0" + micromark-util-encode "^2.0.0" + micromark-util-normalize-identifier "^2.0.0" + micromark-util-resolve-all "^2.0.0" + micromark-util-sanitize-uri "^2.0.0" + micromark-util-subtokenize "^2.0.0" + micromark-util-symbol "^2.0.0" + micromark-util-types "^2.0.0" + +micromatch@^4.0.5, micromatch@^4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.8.tgz#d66fa18f3a47076789320b9b1af32bd86d9fa202" + integrity sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA== + dependencies: + braces "^3.0.3" + picomatch "^2.3.1" + +mime-db@1.52.0: + version "1.52.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" + integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== + +mime-types@^2.1.12, mime-types@~2.1.24, mime-types@~2.1.34: + version "2.1.35" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" + integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== + dependencies: + mime-db "1.52.0" + +mime@1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" + integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== + +mimic-fn@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" + integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== + +mimic-response@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-3.1.0.tgz#2d1d59af9c1b129815accc2c46a022a5ce1fa3c9" + integrity sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ== + +mimic-response@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-4.0.0.tgz#35468b19e7c75d10f5165ea25e75a5ceea7cf70f" + integrity sha512-e5ISH9xMYU0DzrT+jl8q2ze9D6eWBto+I8CNpe+VI+K2J/F/k3PdkdTdz4wvGVH4NTpo+NRYTVIuMQEMMcsLqg== + +minimatch@^3.1.4: + version "3.1.5" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.5.tgz#580c88f8d5445f2bd6aa8f3cadefa0de79fbd69e" + integrity sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w== + dependencies: + brace-expansion "^1.1.7" + +minimist@^1.2.0, minimist@^1.2.3: + version "1.2.8" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" + integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== + +minipass@^3.0.0: + version "3.3.6" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.3.6.tgz#7bba384db3a1520d18c9c0e5251c3444e95dd94a" + integrity sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw== + dependencies: + yallist "^4.0.0" + +minipass@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-5.0.0.tgz#3e9788ffb90b694a5d0ec94479a45b5d8738133d" + integrity sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ== + +minizlib@^2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-2.1.2.tgz#e90d3466ba209b932451508a11ce3d3632145931" + integrity sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg== + dependencies: + minipass "^3.0.0" + yallist "^4.0.0" + +mintlify@^4: + version "4.2.527" + resolved "https://registry.yarnpkg.com/mintlify/-/mintlify-4.2.527.tgz#cb425afca23a365cc3ceb87e056d44475dc2077a" + integrity sha512-agP9TRdiMaW5GVdnBEAbaIONmLSdGYaCPMDyMxVzEiYaiARKEqVQw9OGayDXEmSq2qjikYOYppHlSmm+r8tMmA== + dependencies: + "@mintlify/cli" "4.0.1130" + +mitt@3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/mitt/-/mitt-3.0.1.tgz#ea36cf0cc30403601ae074c8f77b7092cdab36d1" + integrity sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw== + +mkdirp-classic@^0.5.2, mkdirp-classic@^0.5.3: + version "0.5.3" + resolved "https://registry.yarnpkg.com/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz#fa10c9115cc6d8865be221ba47ee9bed78601113" + integrity sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A== + +mkdirp@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" + integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== + +ms@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" + integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A== + +ms@2.1.3, ms@^2.1.3: + version "2.1.3" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" + integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== + +mute-stream@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-2.0.0.tgz#a5446fc0c512b71c83c44d908d5c7b7b4c493b2b" + integrity sha512-WWdIxpyjEn+FhQJQQv9aQAYlHoNVdzIzUySNV1gHUPDSdZJ3yZn7pAAbQcV7B56Mvu881q9FZV+0Vx2xC44VWA== + +mz@^2.7.0: + version "2.7.0" + resolved "https://registry.yarnpkg.com/mz/-/mz-2.7.0.tgz#95008057a56cafadc2bc63dde7f9ff6955948e32" + integrity sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q== + dependencies: + any-promise "^1.0.0" + object-assign "^4.0.1" + thenify-all "^1.0.0" + +nanoid@^3.3.11: + version "3.3.11" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.11.tgz#4f4f112cefbe303202f2199838128936266d185b" + integrity sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w== + +napi-build-utils@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/napi-build-utils/-/napi-build-utils-2.0.0.tgz#13c22c0187fcfccce1461844136372a47ddc027e" + integrity sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA== + +negotiator@0.6.3: + version "0.6.3" + resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" + integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== + +neotraverse@0.6.18: + version "0.6.18" + resolved "https://registry.yarnpkg.com/neotraverse/-/neotraverse-0.6.18.tgz#abcb33dda2e8e713cf6321b29405e822230cdb30" + integrity sha512-Z4SmBUweYa09+o6pG+eASabEpP6QkQ70yHj351pQoEXIs8uHbaU2DWVmzBANKgflPa47A50PtB2+NgRpQvr7vA== + +netmask@^2.0.2: + version "2.1.1" + resolved "https://registry.yarnpkg.com/netmask/-/netmask-2.1.1.tgz#80043d265b53aa521b3bd01e8fcdf353f9e1e81e" + integrity sha512-eonl3sLUha+S1GzTPxychyhnUzKyeQkZ7jLjKrBagJgPla13F+uQ71HgpFefyHgqrjEbCPkDArxYsjY8/+gLKA== + +next-mdx-remote-client@^1.0.3: + version "1.1.7" + resolved "https://registry.yarnpkg.com/next-mdx-remote-client/-/next-mdx-remote-client-1.1.7.tgz#5ab6497502de996d97ebb54a7c722ce584e29140" + integrity sha512-12Ap5Z/tFIETMXFSBTH2IFEhJAso7MvOJ5ICyesA4q6FM4vtAcmb+4ZKa4tV1IVQJLBVqOhaEfIESZzdwjmrQQ== + dependencies: + "@babel/code-frame" "^7.29.0" + "@mdx-js/mdx" "^3.1.1" + "@mdx-js/react" "^3.1.1" + remark-mdx-remove-esm "^1.3.1" + serialize-error "^13.0.1" + vfile "^6.0.3" + vfile-matter "^5.0.1" + +nimma@0.2.3: + version "0.2.3" + resolved "https://registry.yarnpkg.com/nimma/-/nimma-0.2.3.tgz#33cd6244ede857d9c8ac45b9d1aad07091559e45" + integrity sha512-1ZOI8J+1PKKGceo/5CT5GfQOG6H8I2BencSK06YarZ2wXwH37BSSUWldqJmMJYA5JfqDqffxDXynt6f11AyKcA== + dependencies: + "@jsep-plugin/regex" "^1.0.1" + "@jsep-plugin/ternary" "^1.0.2" + astring "^1.8.1" + jsep "^1.2.0" + optionalDependencies: + jsonpath-plus "^6.0.1 || ^10.1.0" + lodash.topath "^4.5.2" + +nlcst-to-string@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/nlcst-to-string/-/nlcst-to-string-4.0.0.tgz#05511e8461ebfb415952eb0b7e9a1a7d40471bd4" + integrity sha512-YKLBCcUYKAg0FNlOBT6aI91qFmSiFKiluk655WzPF+DDMA02qIyy8uiRqI8QXtcFpEvll12LpL5MXqEmAZ+dcA== + dependencies: + "@types/nlcst" "^2.0.0" + +node-abi@^3.3.0: + version "3.89.0" + resolved "https://registry.yarnpkg.com/node-abi/-/node-abi-3.89.0.tgz#eea98bf89d4534743bbbf2defa9f4f9bd3bdccfd" + integrity sha512-6u9UwL0HlAl21+agMN3YAMXcKByMqwGx+pq+P76vii5f7hTPtKDp08/H9py6DY+cfDw7kQNTGEj/rly3IgbNQA== + dependencies: + semver "^7.3.5" + +node-addon-api@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-4.3.0.tgz#52a1a0b475193e0928e98e0426a0d1254782b77f" + integrity sha512-73sE9+3UaLYYFmDsFZnqCInzPyh3MqIwZO9cw58yIqAZhONrrabrYyYe3TuIqtIiOuTXVhsGau8hcrhhwSsDIQ== + +node-fetch@2.6.7: + version "2.6.7" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" + integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== + dependencies: + whatwg-url "^5.0.0" + +node-fetch@^2.6.0, node-fetch@^2.7.0: + version "2.7.0" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d" + integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A== + dependencies: + whatwg-url "^5.0.0" + +non-error@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/non-error/-/non-error-0.1.0.tgz#b78b7d9a67ccb03ac979f9758813336ca7521cf2" + integrity sha512-TMB1uHiGsHRGv1uYclfhivcnf0/PdFp2pNqRxXjncaAsjYMoisaQJI+SSZCqRq+VliwRTC8tsMQfmrWjDMhkPQ== + +normalize-path@^3.0.0, normalize-path@~3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" + integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== + +normalize-url@^8.0.0: + version "8.1.1" + resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-8.1.1.tgz#751a20c8520e5725404c06015fea21d7567f25ef" + integrity sha512-JYc0DPlpGWB40kH5g07gGTrYuMqV653k3uBKY6uITPWds3M0ov3GaWGp9lbE3Bzngx8+XkfzgvASb9vk9JDFXQ== + +oauth4webapi@^3.8.5: + version "3.8.5" + resolved "https://registry.yarnpkg.com/oauth4webapi/-/oauth4webapi-3.8.5.tgz#4aa8a73f5c4644daf674a7c40497be910db99d3f" + integrity sha512-A8jmyUckVhRJj5lspguklcl90Ydqk61H3dcU0oLhH3Yv13KpAliKTt5hknpGGPZSSfOwGyraNEFmofDYH+1kSg== + +object-assign@^4, object-assign@^4.0.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" + integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== + +object-hash@3.0.0, object-hash@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/object-hash/-/object-hash-3.0.0.tgz#73f97f753e7baffc0e2cc9d6e079079744ac82e9" + integrity sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw== + +object-inspect@^1.13.3, object-inspect@^1.13.4: + version "1.13.4" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.4.tgz#8375265e21bc20d0fa582c22e1b13485d6e00213" + integrity sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew== + +object-keys@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" + integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== + +object.assign@^4.1.7: + version "4.1.7" + resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.7.tgz#8c14ca1a424c6a561b0bb2a22f66f5049a945d3d" + integrity sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw== + dependencies: + call-bind "^1.0.8" + call-bound "^1.0.3" + define-properties "^1.2.1" + es-object-atoms "^1.0.0" + has-symbols "^1.1.0" + object-keys "^1.1.1" + +on-finished@2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f" + integrity sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg== + dependencies: + ee-first "1.1.1" + +once@^1.3.1, once@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== + dependencies: + wrappy "1" + +onetime@^5.1.0: + version "5.1.2" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" + integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== + dependencies: + mimic-fn "^2.1.0" + +oniguruma-parser@^0.12.2: + version "0.12.2" + resolved "https://registry.yarnpkg.com/oniguruma-parser/-/oniguruma-parser-0.12.2.tgz#e27ca446f7fcf0969662a3ab9b4f43176d62b139" + integrity sha512-6HVa5oIrgMC6aA6WF6XyyqbhRPJrKR02L20+2+zpDtO5QAzGHAUGw5TKQvwi5vctNnRHkJYmjAhRVQF2EKdTQw== + +oniguruma-to-es@^4.3.4: + version "4.3.6" + resolved "https://registry.yarnpkg.com/oniguruma-to-es/-/oniguruma-to-es-4.3.6.tgz#43e640280241b0d687a314e7a641d476407a1c4d" + integrity sha512-csuQ9x3Yr0cEIs/Zgx/OEt9iBw9vqIunAPQkx19R/fiMq2oGVTgcMqO/V3Ybqefr1TBvosI6jU539ksaBULJyA== + dependencies: + oniguruma-parser "^0.12.2" + regex "^6.1.0" + regex-recursion "^6.0.2" + +open@^8.0.4, open@^8.4.2: + version "8.4.2" + resolved "https://registry.yarnpkg.com/open/-/open-8.4.2.tgz#5b5ffe2a8f793dcd2aad73e550cb87b59cb084f9" + integrity sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ== + dependencies: + define-lazy-prop "^2.0.0" + is-docker "^2.1.1" + is-wsl "^2.2.0" + +openapi-types@12.1.3: + version "12.1.3" + resolved "https://registry.yarnpkg.com/openapi-types/-/openapi-types-12.1.3.tgz#471995eb26c4b97b7bd356aacf7b91b73e777dd3" + integrity sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw== + +openid-client@^6.8.2: + version "6.8.3" + resolved "https://registry.yarnpkg.com/openid-client/-/openid-client-6.8.3.tgz#38aaf86552f1b9dbe1d0fe4a69512e533da14420" + integrity sha512-AoY/NaN9esS3+xvHInFSK0g3skSfeE0uqQAKRj4rB6/GsBIvzwTUaYo9+HcqpKIaP0dP85p5W07hayKgS4GAeA== + dependencies: + jose "^6.2.2" + oauth4webapi "^3.8.5" + +own-keys@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/own-keys/-/own-keys-1.0.1.tgz#e4006910a2bf913585289676eebd6f390cf51358" + integrity sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg== + dependencies: + get-intrinsic "^1.2.6" + object-keys "^1.1.1" + safe-push-apply "^1.0.0" + +p-any@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/p-any/-/p-any-4.0.0.tgz#0e9c8b0fa3e58cc79e6a1c6c715aa9326b6a4447" + integrity sha512-S/B50s+pAVe0wmEZHmBs/9yJXeZ5KhHzOsgKzt0hRdgkoR3DxW9ts46fcsWi/r3VnzsnkKS7q4uimze+zjdryw== + dependencies: + p-cancelable "^3.0.0" + p-some "^6.0.0" + +p-cancelable@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-3.0.0.tgz#63826694b54d61ca1c20ebcb6d3ecf5e14cd8050" + integrity sha512-mlVgR3PGuzlo0MmTdk4cXqXWlwQDLnONTAg6sm62XkMJEiRxN3GL3SffkYvqwonbkJBcrI7Uvv5Zh9yjvn2iUw== + +p-some@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/p-some/-/p-some-6.0.0.tgz#4613a822038abe125e42152ea9f7705a7967526f" + integrity sha512-CJbQCKdfSX3fIh8/QKgS+9rjm7OBNUTmwWswAFQAhc8j1NR1dsEDETUEuVUtQHZpV+J03LqWBEwvu0g1Yn+TYg== + dependencies: + aggregate-error "^4.0.0" + p-cancelable "^3.0.0" + +p-timeout@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/p-timeout/-/p-timeout-5.1.0.tgz#b3c691cf4415138ce2d9cfe071dba11f0fee085b" + integrity sha512-auFDyzzzGZZZdHz3BtET9VEz0SE/uMEAx7uWfGPucfzEwwe/xH0iVeZibQmANYE/hp9T2+UUZT5m+BKyrDp3Ew== + +pac-proxy-agent@^7.1.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/pac-proxy-agent/-/pac-proxy-agent-7.2.0.tgz#9cfaf33ff25da36f6147a20844230ec92c06e5df" + integrity sha512-TEB8ESquiLMc0lV8vcd5Ql/JAKAoyzHFXaStwjkzpOpC5Yv+pIzLfHvjTSdf3vpa2bMiUQrg9i6276yn8666aA== + dependencies: + "@tootallnate/quickjs-emscripten" "^0.23.0" + agent-base "^7.1.2" + debug "^4.3.4" + get-uri "^6.0.1" + http-proxy-agent "^7.0.0" + https-proxy-agent "^7.0.6" + pac-resolver "^7.0.1" + socks-proxy-agent "^8.0.5" + +pac-resolver@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/pac-resolver/-/pac-resolver-7.0.1.tgz#54675558ea368b64d210fd9c92a640b5f3b8abb6" + integrity sha512-5NPgf87AT2STgwa2ntRMr45jTKrYBGkVU36yT0ig/n/GMAa3oPqhZfIQ2kMEimReg0+t9kZViDVZ83qfVUlckg== + dependencies: + degenerator "^5.0.0" + netmask "^2.0.2" + +parent-module@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" + integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== + dependencies: + callsites "^3.0.0" + +parse-entities@^4.0.0: + version "4.0.2" + resolved "https://registry.yarnpkg.com/parse-entities/-/parse-entities-4.0.2.tgz#61d46f5ed28e4ee62e9ddc43d6b010188443f159" + integrity sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw== + dependencies: + "@types/unist" "^2.0.0" + character-entities-legacy "^3.0.0" + character-reference-invalid "^2.0.0" + decode-named-character-reference "^1.0.0" + is-alphanumerical "^2.0.0" + is-decimal "^2.0.0" + is-hexadecimal "^2.0.0" + +parse-json@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd" + integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg== + dependencies: + "@babel/code-frame" "^7.0.0" + error-ex "^1.3.1" + json-parse-even-better-errors "^2.3.0" + lines-and-columns "^1.1.6" + +parse-latin@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/parse-latin/-/parse-latin-7.0.0.tgz#8dfacac26fa603f76417f36233fc45602a323e1d" + integrity sha512-mhHgobPPua5kZ98EF4HWiH167JWBfl4pvAIXXdbaVohtK7a6YBOy56kvhCqduqyo/f3yrHFWmqmiMg/BkBkYYQ== + dependencies: + "@types/nlcst" "^2.0.0" + "@types/unist" "^3.0.0" + nlcst-to-string "^4.0.0" + unist-util-modify-children "^4.0.0" + unist-util-visit-children "^3.0.0" + vfile "^6.0.0" + +parse5@^7.0.0: + version "7.3.0" + resolved "https://registry.yarnpkg.com/parse5/-/parse5-7.3.0.tgz#d7e224fa72399c7a175099f45fc2ad024b05ec05" + integrity sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw== + dependencies: + entities "^6.0.0" + +parseurl@~1.3.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" + integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== + +patch-console@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/patch-console/-/patch-console-2.0.0.tgz#9023f4665840e66f40e9ce774f904a63167433bb" + integrity sha512-0YNdUceMdaQwoKce1gatDScmMo5pu/tfABfnzEqeG0gtTmd7mh/WcwgUjtAeOU7N8nFFlbQBnFK2gXW5fGvmMA== + +path-key@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" + integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== + +path-parse@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" + integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== + +path-to-regexp@0.1.7: + version "0.1.7" + resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" + integrity sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ== + +pend@~1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50" + integrity sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg== + +picocolors@^1.0.0, picocolors@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.1.1.tgz#3d321af3eab939b083c8f929a1d12cda81c26b6b" + integrity sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA== + +picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.1: + version "2.3.2" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.2.tgz#5a942915e26b372dc0f0e6753149a16e6b1c5601" + integrity sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA== + +picomatch@^4.0.4: + version "4.0.4" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-4.0.4.tgz#fd6f5e00a143086e074dffe4c924b8fb293b0589" + integrity sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A== + +pify@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" + integrity sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog== + +pirates@^4.0.1: + version "4.0.7" + resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.7.tgz#643b4a18c4257c8a65104b73f3049ce9a0a15e22" + integrity sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA== + +pony-cause@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/pony-cause/-/pony-cause-1.1.1.tgz#f795524f83bebbf1878bd3587b45f69143cbf3f9" + integrity sha512-PxkIc/2ZpLiEzQXu5YRDOUgBlfGYBY8156HY5ZcRAwwonMk5W/MrJP2LLkG/hF7GEQzaHo2aS7ho6ZLCOvf+6g== + +possible-typed-array-names@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz#93e3582bc0e5426586d9d07b79ee40fc841de4ae" + integrity sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg== + +postcss-import@^15.1.0: + version "15.1.0" + resolved "https://registry.yarnpkg.com/postcss-import/-/postcss-import-15.1.0.tgz#41c64ed8cc0e23735a9698b3249ffdbf704adc70" + integrity sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew== + dependencies: + postcss-value-parser "^4.0.0" + read-cache "^1.0.0" + resolve "^1.1.7" + +postcss-js@^4.0.1: + version "4.1.0" + resolved "https://registry.yarnpkg.com/postcss-js/-/postcss-js-4.1.0.tgz#003b63c6edde948766e40f3daf7e997ae43a5ce6" + integrity sha512-oIAOTqgIo7q2EOwbhb8UalYePMvYoIeRY2YKntdpFQXNosSu3vLrniGgmH9OKs/qAkfoj5oB3le/7mINW1LCfw== + dependencies: + camelcase-css "^2.0.1" + +postcss-load-config@^4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-load-config/-/postcss-load-config-4.0.2.tgz#7159dcf626118d33e299f485d6afe4aff7c4a3e3" + integrity sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ== + dependencies: + lilconfig "^3.0.0" + yaml "^2.3.4" + +"postcss-load-config@^4.0.2 || ^5.0 || ^6.0": + version "6.0.1" + resolved "https://registry.yarnpkg.com/postcss-load-config/-/postcss-load-config-6.0.1.tgz#6fd7dcd8ae89badcf1b2d644489cbabf83aa8096" + integrity sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g== + dependencies: + lilconfig "^3.1.1" + +postcss-nested@^6.0.1, postcss-nested@^6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/postcss-nested/-/postcss-nested-6.2.0.tgz#4c2d22ab5f20b9cb61e2c5c5915950784d068131" + integrity sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ== + dependencies: + postcss-selector-parser "^6.1.1" + +postcss-selector-parser@^6.0.11, postcss-selector-parser@^6.1.1, postcss-selector-parser@^6.1.2: + version "6.1.2" + resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz#27ecb41fb0e3b6ba7a1ec84fff347f734c7929de" + integrity sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg== + dependencies: + cssesc "^3.0.0" + util-deprecate "^1.0.2" + +postcss-value-parser@^4.0.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514" + integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ== + +postcss@8.5.6: + version "8.5.6" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.5.6.tgz#2825006615a619b4f62a9e7426cc120b349a8f3c" + integrity sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg== + dependencies: + nanoid "^3.3.11" + picocolors "^1.1.1" + source-map-js "^1.2.1" + +postcss@^8.4.23, postcss@^8.4.47: + version "8.5.10" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.5.10.tgz#8992d8c30acf3f12169e7c09514a12fed7e48356" + integrity sha512-pMMHxBOZKFU6HgAZ4eyGnwXF/EvPGGqUr0MnZ5+99485wwW41kW91A4LOGxSHhgugZmSChL5AlElNdwlNgcnLQ== + dependencies: + nanoid "^3.3.11" + picocolors "^1.1.1" + source-map-js "^1.2.1" + +posthog-node@5.17.2: + version "5.17.2" + resolved "https://registry.yarnpkg.com/posthog-node/-/posthog-node-5.17.2.tgz#9d990d929c755937219ac50d2ad2ef7709a30a1b" + integrity sha512-lz3YJOr0Nmiz0yHASaINEDHqoV+0bC3eD8aZAG+Ky292dAnVYul+ga/dMX8KCBXg8hHfKdxw0SztYD5j6dgUqQ== + dependencies: + "@posthog/core" "1.7.1" + +prebuild-install@^7.0.1: + version "7.1.3" + resolved "https://registry.yarnpkg.com/prebuild-install/-/prebuild-install-7.1.3.tgz#d630abad2b147443f20a212917beae68b8092eec" + integrity sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug== + dependencies: + 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 "^2.0.0" + node-abi "^3.3.0" + pump "^3.0.0" + rc "^1.2.7" + simple-get "^4.0.0" + tar-fs "^2.0.0" + tunnel-agent "^0.6.0" + +progress@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" + integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== + +property-information@^6.0.0: + version "6.5.0" + resolved "https://registry.yarnpkg.com/property-information/-/property-information-6.5.0.tgz#6212fbb52ba757e92ef4fb9d657563b933b7ffec" + integrity sha512-PgTgs/BlvHxOu8QuEN7wi5A0OmXaBcHpmCSTehcs6Uuu9IkDIEo13Hy7n898RHfrQ49vKCoGeWZSaAK01nwVig== + +property-information@^7.0.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/property-information/-/property-information-7.1.0.tgz#b622e8646e02b580205415586b40804d3e8bfd5d" + integrity sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ== + +proxy-addr@~2.0.7: + version "2.0.7" + resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025" + integrity sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg== + dependencies: + forwarded "0.2.0" + ipaddr.js "1.9.1" + +proxy-agent@^6.4.0: + version "6.5.0" + resolved "https://registry.yarnpkg.com/proxy-agent/-/proxy-agent-6.5.0.tgz#9e49acba8e4ee234aacb539f89ed9c23d02f232d" + integrity sha512-TmatMXdr2KlRiA2CyDu8GqR8EjahTG3aY3nXjdzFyoZbmB8hrBsTyMezhULIXKnC0jpfjlmiZ3+EaCzoInSu/A== + dependencies: + agent-base "^7.1.2" + debug "^4.3.4" + http-proxy-agent "^7.0.1" + https-proxy-agent "^7.0.6" + lru-cache "^7.14.1" + pac-proxy-agent "^7.1.0" + proxy-from-env "^1.1.0" + socks-proxy-agent "^8.0.5" + +proxy-from-env@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" + integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== + +public-ip@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/public-ip/-/public-ip-5.0.0.tgz#b392fcc88552c3b36933a286068948816515f92a" + integrity sha512-xaH3pZMni/R2BG7ZXXaWS9Wc9wFlhyDVJF47IJ+3ali0TGv+2PsckKxbmo+rnx3ZxiV2wblVhtdS3bohAP6GGw== + dependencies: + dns-socket "^4.2.2" + got "^12.0.0" + is-ip "^3.1.0" + +pump@^3.0.0: + version "3.0.4" + resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.4.tgz#1f313430527fa8b905622ebd22fe1444e757ab3c" + integrity sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA== + dependencies: + end-of-stream "^1.1.0" + once "^1.3.1" + +puppeteer-core@22.14.0: + version "22.14.0" + resolved "https://registry.yarnpkg.com/puppeteer-core/-/puppeteer-core-22.14.0.tgz#5bb466adba725c966b0a86f0337a476d4c68ebec" + integrity sha512-rl4tOY5LcA3e374GAlsGGHc05HL3eGNf5rZ+uxkl6id9zVZKcwcp1Z+Nd6byb6WPiPeecT/dwz8f/iUm+AZQSw== + dependencies: + "@puppeteer/browsers" "2.3.0" + chromium-bidi "0.6.2" + debug "^4.3.5" + devtools-protocol "0.0.1312386" + ws "^8.18.0" + +puppeteer@22.14.0: + version "22.14.0" + resolved "https://registry.yarnpkg.com/puppeteer/-/puppeteer-22.14.0.tgz#11697c929f5d9d7eac5a3438a0ff12dc65aedcbe" + integrity sha512-MGTR6/pM8zmWbTdazb6FKnwIihzsSEXBPH49mFFU96DNZpQOevCAZMnjBZGlZRGRzRK6aADCavR6SQtrbv5dQw== + dependencies: + "@puppeteer/browsers" "2.3.0" + cosmiconfig "^9.0.0" + devtools-protocol "0.0.1312386" + puppeteer-core "22.14.0" + +qs@6.11.0: + version "6.11.0" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.0.tgz#fd0d963446f7a65e1367e01abd85429453f0c37a" + integrity sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q== + dependencies: + side-channel "^1.0.4" + +queue-microtask@^1.2.2: + version "1.2.3" + resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" + integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== + +quick-lru@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-5.1.1.tgz#366493e6b3e42a3a6885e2e99d18f80fb7a8c932" + integrity sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA== + +range-parser@~1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" + integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== + +raw-body@2.5.1: + version "2.5.1" + resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.1.tgz#fe1b1628b181b700215e5fd42389f98b71392857" + 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" + +rc@^1.2.7: + version "1.2.8" + resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" + integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== + dependencies: + deep-extend "^0.6.0" + ini "~1.3.0" + minimist "^1.2.0" + strip-json-comments "~2.0.1" + +react-reconciler@^0.32.0: + version "0.32.0" + resolved "https://registry.yarnpkg.com/react-reconciler/-/react-reconciler-0.32.0.tgz#a08bcd8c454a4cd839164d6e05926e30a7a7fac2" + integrity sha512-2NPMOzgTlG0ZWdIf3qG+dcbLSoAc/uLfOwckc3ofy5sSK0pLJqnQLpUFxvGcN2rlXSjnVtGeeFLNimCQEj5gOQ== + dependencies: + scheduler "^0.26.0" + +react@19.2.3: + version "19.2.3" + resolved "https://registry.yarnpkg.com/react/-/react-19.2.3.tgz#d83e5e8e7a258cf6b4fe28640515f99b87cd19b8" + integrity sha512-Ku/hhYbVjOQnXDZFv2+RibmLFGwFdeeKHFcOTlrt7xplBnya5OGn/hIRDsqDiSUcfORsDC7MPxwork8jBwsIWA== + +read-cache@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/read-cache/-/read-cache-1.0.0.tgz#e664ef31161166c9751cdbe8dbcf86b5fb58f774" + integrity sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA== + dependencies: + pify "^2.3.0" + +readable-stream@^3.1.1, readable-stream@^3.4.0: + version "3.6.2" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" + integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== + dependencies: + inherits "^2.0.3" + string_decoder "^1.1.1" + util-deprecate "^1.0.1" + +readdirp@~3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" + integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== + dependencies: + picomatch "^2.2.1" + +recma-build-jsx@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/recma-build-jsx/-/recma-build-jsx-1.0.0.tgz#c02f29e047e103d2fab2054954e1761b8ea253c4" + integrity sha512-8GtdyqaBcDfva+GUKDr3nev3VpKAhup1+RvkMvUxURHpW7QyIvk9F5wz7Vzo06CEMSilw6uArgRqhpiUcWp8ew== + dependencies: + "@types/estree" "^1.0.0" + estree-util-build-jsx "^3.0.0" + vfile "^6.0.0" + +recma-jsx@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/recma-jsx/-/recma-jsx-1.0.1.tgz#58e718f45e2102ed0bf2fa994f05b70d76801a1a" + integrity sha512-huSIy7VU2Z5OLv6oFLosQGGDqPqdO1iq6bWNAdhzMxSJP7RAso4fCZ1cKu8j9YHCZf3TPrq4dw3okhrylgcd7w== + dependencies: + acorn-jsx "^5.0.0" + estree-util-to-js "^2.0.0" + recma-parse "^1.0.0" + recma-stringify "^1.0.0" + unified "^11.0.0" + +recma-parse@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/recma-parse/-/recma-parse-1.0.0.tgz#c351e161bb0ab47d86b92a98a9d891f9b6814b52" + integrity sha512-OYLsIGBB5Y5wjnSnQW6t3Xg7q3fQ7FWbw/vcXtORTnyaSFscOtABg+7Pnz6YZ6c27fG1/aN8CjfwoUEUIdwqWQ== + dependencies: + "@types/estree" "^1.0.0" + esast-util-from-js "^2.0.0" + unified "^11.0.0" + vfile "^6.0.0" + +recma-stringify@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/recma-stringify/-/recma-stringify-1.0.0.tgz#54632030631e0c7546136ff9ef8fde8e7b44f130" + integrity sha512-cjwII1MdIIVloKvC9ErQ+OgAtwHBmcZ0Bg4ciz78FtbT8In39aAYbaA7zvxQ61xVMSPE8WxhLwLbhif4Js2C+g== + dependencies: + "@types/estree" "^1.0.0" + estree-util-to-js "^2.0.0" + unified "^11.0.0" + vfile "^6.0.0" + +reflect.getprototypeof@^1.0.6, reflect.getprototypeof@^1.0.9: + version "1.0.10" + resolved "https://registry.yarnpkg.com/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz#c629219e78a3316d8b604c765ef68996964e7bf9" + integrity sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw== + dependencies: + call-bind "^1.0.8" + define-properties "^1.2.1" + es-abstract "^1.23.9" + es-errors "^1.3.0" + es-object-atoms "^1.0.0" + get-intrinsic "^1.2.7" + get-proto "^1.0.1" + which-builtin-type "^1.2.1" + +regex-recursion@^6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/regex-recursion/-/regex-recursion-6.0.2.tgz#a0b1977a74c87f073377b938dbedfab2ea582b33" + integrity sha512-0YCaSCq2VRIebiaUviZNs0cBz1kg5kVS2UKUfNIx8YVs1cN3AV7NTctO5FOKBA+UT2BPJIWZauYHPqJODG50cg== + dependencies: + regex-utilities "^2.3.0" + +regex-utilities@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/regex-utilities/-/regex-utilities-2.3.0.tgz#87163512a15dce2908cf079c8960d5158ff43280" + integrity sha512-8VhliFJAWRaUiVvREIiW2NXXTmHs4vMNnSzuJVhscgmGav3g9VDxLrQndI3dZZVVdp0ZO/5v0xmX516/7M9cng== + +regex@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/regex/-/regex-6.1.0.tgz#d7ce98f8ee32da7497c13f6601fca2bc4a6a7803" + integrity sha512-6VwtthbV4o/7+OaAF9I5L5V3llLEsoPyq9P1JVXkedTP33c7MfCG0/5NOPcSJn0TzXcG9YUrR0gQSWioew3LDg== + dependencies: + regex-utilities "^2.3.0" + +regexp.prototype.flags@^1.5.4: + version "1.5.4" + resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz#1ad6c62d44a259007e55b3970e00f746efbcaa19" + integrity sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA== + dependencies: + call-bind "^1.0.8" + define-properties "^1.2.1" + es-errors "^1.3.0" + get-proto "^1.0.1" + gopd "^1.2.0" + set-function-name "^2.0.2" + +rehype-katex@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/rehype-katex/-/rehype-katex-7.0.1.tgz#832e6d7af2744a228981d1b0fe89483a9e7c93a1" + integrity sha512-OiM2wrZ/wuhKkigASodFoo8wimG3H12LWQaH8qSPVJn9apWKFSH3YOCtbKpBorTVw/eI7cuT21XBbvwEswbIOA== + dependencies: + "@types/hast" "^3.0.0" + "@types/katex" "^0.16.0" + hast-util-from-html-isomorphic "^2.0.0" + hast-util-to-text "^4.0.0" + katex "^0.16.0" + unist-util-visit-parents "^6.0.0" + vfile "^6.0.0" + +rehype-minify-whitespace@^6.0.0: + version "6.0.2" + resolved "https://registry.yarnpkg.com/rehype-minify-whitespace/-/rehype-minify-whitespace-6.0.2.tgz#7dd234ce0775656ce6b6b0aad0a6093de29b2278" + integrity sha512-Zk0pyQ06A3Lyxhe9vGtOtzz3Z0+qZ5+7icZ/PL/2x1SHPbKao5oB/g/rlc6BCTajqBb33JcOe71Ye1oFsuYbnw== + dependencies: + "@types/hast" "^3.0.0" + hast-util-minify-whitespace "^1.0.0" + +rehype-parse@9.0.1: + version "9.0.1" + resolved "https://registry.yarnpkg.com/rehype-parse/-/rehype-parse-9.0.1.tgz#9993bda129acc64c417a9d3654a7be38b2a94c20" + integrity sha512-ksCzCD0Fgfh7trPDxr2rSylbwq9iYDkSn8TCDmEJ49ljEUBxDVCzCHv7QNzZOfODanX4+bWQ4WZqLCRWYLfhag== + dependencies: + "@types/hast" "^3.0.0" + hast-util-from-html "^2.0.0" + unified "^11.0.0" + +rehype-recma@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/rehype-recma/-/rehype-recma-1.0.0.tgz#d68ef6344d05916bd96e25400c6261775411aa76" + integrity sha512-lqA4rGUf1JmacCNWWZx0Wv1dHqMwxzsDWYMTowuplHF3xH0N/MmrZ/G3BDZnzAkRmxDadujCjaKM2hqYdCBOGw== + dependencies: + "@types/estree" "^1.0.0" + "@types/hast" "^3.0.0" + hast-util-to-estree "^3.0.0" + +rehype-stringify@10.0.1: + version "10.0.1" + resolved "https://registry.yarnpkg.com/rehype-stringify/-/rehype-stringify-10.0.1.tgz#2ec1ebc56c6aba07905d3b4470bdf0f684f30b75" + integrity sha512-k9ecfXHmIPuFVI61B9DeLPN0qFHfawM6RsuX48hoqlaKSF61RskNjSm1lI8PhBEM0MRdLxVVm4WmTqJQccH9mA== + dependencies: + "@types/hast" "^3.0.0" + hast-util-to-html "^9.0.0" + unified "^11.0.0" + +remark-frontmatter@5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/remark-frontmatter/-/remark-frontmatter-5.0.0.tgz#b68d61552a421ec412c76f4f66c344627dc187a2" + integrity sha512-XTFYvNASMe5iPN0719nPrdItC9aU0ssC4v14mH1BCi1u0n1gAocqcujWUrByftZTbLhRtiKRyjYTSIOcr69UVQ== + dependencies: + "@types/mdast" "^4.0.0" + mdast-util-frontmatter "^2.0.0" + micromark-extension-frontmatter "^2.0.0" + unified "^11.0.0" + +remark-gfm@4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/remark-gfm/-/remark-gfm-4.0.0.tgz#aea777f0744701aa288b67d28c43565c7e8c35de" + integrity sha512-U92vJgBPkbw4Zfu/IiW2oTZLSL3Zpv+uI7My2eq8JxKgqraFdU8YUGicEJCEgSbeaG+QDFqIcwwfMTOEelPxuA== + dependencies: + "@types/mdast" "^4.0.0" + mdast-util-gfm "^3.0.0" + micromark-extension-gfm "^3.0.0" + remark-parse "^11.0.0" + remark-stringify "^11.0.0" + unified "^11.0.0" + +remark-gfm@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/remark-gfm/-/remark-gfm-4.0.1.tgz#33227b2a74397670d357bf05c098eaf8513f0d6b" + integrity sha512-1quofZ2RQ9EWdeN34S79+KExV1764+wCUGop5CPL1WGdD0ocPpu91lzPGbwWMECpEpd42kJGQwzRfyov9j4yNg== + dependencies: + "@types/mdast" "^4.0.0" + mdast-util-gfm "^3.0.0" + micromark-extension-gfm "^3.0.0" + remark-parse "^11.0.0" + remark-stringify "^11.0.0" + unified "^11.0.0" + +remark-math@6.0.0, remark-math@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/remark-math/-/remark-math-6.0.0.tgz#0acdf74675f1c195fea6efffa78582f7ed7fc0d7" + integrity sha512-MMqgnP74Igy+S3WwnhQ7kqGlEerTETXMvJhrUzDikVZ2/uogJCb+WHUg97hK9/jcfc0dkD73s3LN8zU49cTEtA== + dependencies: + "@types/mdast" "^4.0.0" + mdast-util-math "^3.0.0" + micromark-extension-math "^3.0.0" + unified "^11.0.0" + +remark-mdx-remove-esm@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/remark-mdx-remove-esm/-/remark-mdx-remove-esm-1.3.1.tgz#c6f6de7714c3cc0b1b8235f0885027801c259997" + integrity sha512-POa8abdiuicD2e+zQkclxzJa5JEGLtV8XIOFVvisnGuw4l4xd6dfQozedwqR8JTeXQmxLebvYhlbwHoQP9RWkw== + dependencies: + "@types/mdast" "^4.0.4" + mdast-util-mdxjs-esm "^2.0.1" + unist-util-remove "^4.0.0" + +remark-mdx@3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/remark-mdx/-/remark-mdx-3.0.1.tgz#8f73dd635c1874e44426e243f72c0977cf60e212" + integrity sha512-3Pz3yPQ5Rht2pM5R+0J2MrGoBSrzf+tJG94N+t/ilfdh8YLyyKYtidAYwTveB20BoHAcwIopOUqhcmh2F7hGYA== + dependencies: + mdast-util-mdx "^3.0.0" + micromark-extension-mdxjs "^3.0.0" + +remark-mdx@3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/remark-mdx/-/remark-mdx-3.1.0.tgz#f979be729ecb35318fa48e2135c1169607a78343" + integrity sha512-Ngl/H3YXyBV9RcRNdlYsZujAmhsxwzxpDzpDEhFBVAGthS4GDgnctpDjgFl/ULx5UEDzqtW1cyBSNKqYYrqLBA== + dependencies: + mdast-util-mdx "^3.0.0" + micromark-extension-mdxjs "^3.0.0" + +remark-mdx@^3.0.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/remark-mdx/-/remark-mdx-3.1.1.tgz#047f97038bc7ec387aebb4b0a4fe23779999d845" + integrity sha512-Pjj2IYlUY3+D8x00UJsIOg5BEvfMyeI+2uLPn9VO9Wg4MEtN/VTIq2NEJQfde9PnX15KgtHyl9S0BcTnWrIuWg== + dependencies: + mdast-util-mdx "^3.0.0" + micromark-extension-mdxjs "^3.0.0" + +remark-parse@11.0.0, remark-parse@^11.0.0: + version "11.0.0" + resolved "https://registry.yarnpkg.com/remark-parse/-/remark-parse-11.0.0.tgz#aa60743fcb37ebf6b069204eb4da304e40db45a1" + integrity sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA== + dependencies: + "@types/mdast" "^4.0.0" + mdast-util-from-markdown "^2.0.0" + micromark-util-types "^2.0.0" + unified "^11.0.0" + +remark-rehype@11.1.1: + version "11.1.1" + resolved "https://registry.yarnpkg.com/remark-rehype/-/remark-rehype-11.1.1.tgz#f864dd2947889a11997c0a2667cd6b38f685bca7" + integrity sha512-g/osARvjkBXb6Wo0XvAeXQohVta8i84ACbenPpoSsxTOQH/Ae0/RGP4WZgnMH5pMLpsj4FG7OHmcIcXxpza8eQ== + dependencies: + "@types/hast" "^3.0.0" + "@types/mdast" "^4.0.0" + mdast-util-to-hast "^13.0.0" + unified "^11.0.0" + vfile "^6.0.0" + +remark-rehype@^11.0.0: + version "11.1.2" + resolved "https://registry.yarnpkg.com/remark-rehype/-/remark-rehype-11.1.2.tgz#2addaadda80ca9bd9aa0da763e74d16327683b37" + integrity sha512-Dh7l57ianaEoIpzbp0PC9UKAdCSVklD8E5Rpw7ETfbTl3FqcOOgq5q2LVDhgGCkaBv7p24JXikPdvhhmHvKMsw== + dependencies: + "@types/hast" "^3.0.0" + "@types/mdast" "^4.0.0" + mdast-util-to-hast "^13.0.0" + unified "^11.0.0" + vfile "^6.0.0" + +remark-smartypants@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/remark-smartypants/-/remark-smartypants-3.0.2.tgz#cbaf2b39624c78fcbd6efa224678c1d2e9bc1dfb" + integrity sha512-ILTWeOriIluwEvPjv67v7Blgrcx+LZOkAUVtKI3putuhlZm84FnqDORNXPPm+HY3NdZOMhyDwZ1E+eZB/Df5dA== + dependencies: + retext "^9.0.0" + retext-smartypants "^6.0.0" + unified "^11.0.4" + unist-util-visit "^5.0.0" + +remark-stringify@11.0.0, remark-stringify@^11.0.0: + version "11.0.0" + resolved "https://registry.yarnpkg.com/remark-stringify/-/remark-stringify-11.0.0.tgz#4c5b01dd711c269df1aaae11743eb7e2e7636fd3" + integrity sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw== + dependencies: + "@types/mdast" "^4.0.0" + mdast-util-to-markdown "^2.0.0" + unified "^11.0.0" + +remark@15.0.1: + version "15.0.1" + resolved "https://registry.yarnpkg.com/remark/-/remark-15.0.1.tgz#ac7e7563260513b66426bc47f850e7aa5862c37c" + integrity sha512-Eht5w30ruCXgFmxVUSlNWQ9iiimq07URKeFS3hNc8cUWy1llX4KDWfyEDZRycMc+znsN9Ux5/tJ/BFdgdOwA3A== + dependencies: + "@types/mdast" "^4.0.0" + remark-parse "^11.0.0" + remark-stringify "^11.0.0" + unified "^11.0.0" + +require-directory@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== + +require-from-string@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" + integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== + +resolve-alpn@^1.2.0: + version "1.2.1" + resolved "https://registry.yarnpkg.com/resolve-alpn/-/resolve-alpn-1.2.1.tgz#b7adbdac3546aaaec20b45e7d8265927072726f9" + integrity sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g== + +resolve-from@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" + integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== + +resolve@^1.1.7, resolve@^1.22.2, resolve@^1.22.8: + version "1.22.12" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.12.tgz#f5b2a680897c69c238a13cd16b15671f8b73549f" + integrity sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA== + dependencies: + es-errors "^1.3.0" + is-core-module "^2.16.1" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" + +responselike@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/responselike/-/responselike-3.0.0.tgz#20decb6c298aff0dbee1c355ca95461d42823626" + integrity sha512-40yHxbNcl2+rzXvZuVkrYohathsSJlMTXKryG5y8uciHv1+xDLHQpgjG64JUO9nrEq2jGLH6IZ8BcZyw3wrweg== + dependencies: + lowercase-keys "^3.0.0" + +restore-cursor@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-4.0.0.tgz#519560a4318975096def6e609d44100edaa4ccb9" + integrity sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg== + dependencies: + onetime "^5.1.0" + signal-exit "^3.0.2" + +retext-latin@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/retext-latin/-/retext-latin-4.0.0.tgz#d02498aa1fd39f1bf00e2ff59b1384c05d0c7ce3" + integrity sha512-hv9woG7Fy0M9IlRQloq/N6atV82NxLGveq+3H2WOi79dtIYWN8OaxogDm77f8YnVXJL2VD3bbqowu5E3EMhBYA== + dependencies: + "@types/nlcst" "^2.0.0" + parse-latin "^7.0.0" + unified "^11.0.0" + +retext-smartypants@^6.0.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/retext-smartypants/-/retext-smartypants-6.2.0.tgz#4e852c2974cf2cfa253eeec427c97efc43b5d158" + integrity sha512-kk0jOU7+zGv//kfjXEBjdIryL1Acl4i9XNkHxtM7Tm5lFiCog576fjNC9hjoR7LTKQ0DsPWy09JummSsH1uqfQ== + dependencies: + "@types/nlcst" "^2.0.0" + nlcst-to-string "^4.0.0" + unist-util-visit "^5.0.0" + +retext-stringify@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/retext-stringify/-/retext-stringify-4.0.0.tgz#501d5440bd4d121e351c7c509f8507de9611e159" + integrity sha512-rtfN/0o8kL1e+78+uxPTqu1Klt0yPzKuQ2BfWwwfgIUSayyzxpM1PJzkKt4V8803uB9qSy32MvI7Xep9khTpiA== + dependencies: + "@types/nlcst" "^2.0.0" + nlcst-to-string "^4.0.0" + unified "^11.0.0" + +retext@^9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/retext/-/retext-9.0.0.tgz#ab5cd72836894167b0ca6ae70fdcfaa166267f7a" + integrity sha512-sbMDcpHCNjvlheSgMfEcVrZko3cDzdbe1x/e7G66dFp0Ff7Mldvi2uv6JkJQzdRcvLYE8CA8Oe8siQx8ZOgTcA== + dependencies: + "@types/nlcst" "^2.0.0" + retext-latin "^4.0.0" + retext-stringify "^4.0.0" + unified "^11.0.0" + +reusify@^1.0.4: + version "1.1.0" + resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.1.0.tgz#0fe13b9522e1473f51b558ee796e08f11f9b489f" + integrity sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw== + +run-async@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/run-async/-/run-async-3.0.0.tgz#42a432f6d76c689522058984384df28be379daad" + integrity sha512-540WwVDOMxA6dN6We19EcT9sc3hkXPw5mzRNGM3FkdN/vtE9NFvj5lFAPNwUDmJjXidm3v7TC1cTE7t17Ulm1Q== + +run-parallel@^1.1.9: + version "1.2.0" + resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" + integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== + dependencies: + queue-microtask "^1.2.2" + +rxjs@^7.8.1: + version "7.8.2" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.8.2.tgz#955bc473ed8af11a002a2be52071bf475638607b" + integrity sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA== + dependencies: + tslib "^2.1.0" + +safe-array-concat@^1.1.3: + version "1.1.4" + resolved "https://registry.yarnpkg.com/safe-array-concat/-/safe-array-concat-1.1.4.tgz#a54cc9b61a57f33b42abad3cbdda3a2b38cc5719" + integrity sha512-wtZlHyOje6OZTGqAoaDKxFkgRtkF9CnHAVnCHKfuj200wAgL+bSJhdsCD2l0Qx/2ekEXjPWcyKkfGb5CPboslg== + dependencies: + call-bind "^1.0.9" + call-bound "^1.0.4" + get-intrinsic "^1.3.0" + has-symbols "^1.1.0" + isarray "^2.0.5" + +safe-buffer@5.2.1, safe-buffer@^5.0.1, safe-buffer@~5.2.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + +safe-push-apply@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/safe-push-apply/-/safe-push-apply-1.0.0.tgz#01850e981c1602d398c85081f360e4e6d03d27f5" + integrity sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA== + dependencies: + es-errors "^1.3.0" + isarray "^2.0.5" + +safe-regex-test@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/safe-regex-test/-/safe-regex-test-1.1.0.tgz#7f87dfb67a3150782eaaf18583ff5d1711ac10c1" + integrity sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw== + dependencies: + call-bound "^1.0.2" + es-errors "^1.3.0" + is-regex "^1.2.1" + +safe-stable-stringify@^1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/safe-stable-stringify/-/safe-stable-stringify-1.1.1.tgz#c8a220ab525cd94e60ebf47ddc404d610dc5d84a" + integrity sha512-ERq4hUjKDbJfE4+XtZLFPCDi8Vb1JqaxAPTxWFLBx8XcAlf9Bda/ZJdVezs/NAfsMQScyIlUMx+Yeu7P7rx5jw== + +"safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0": + version "2.1.2" + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== + +sax@>=0.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/sax/-/sax-1.6.0.tgz#da59637629307b97e7c4cb28e080a7bc38560d5b" + integrity sha512-6R3J5M4AcbtLUdZmRv2SygeVaM7IhrLXu9BmnOGmmACak8fiUtOsYNWUS4uK7upbmHIBbLBeFeI//477BKLBzA== + +scheduler@^0.26.0: + version "0.26.0" + resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.26.0.tgz#4ce8a8c2a2095f13ea11bf9a445be50c555d6337" + integrity sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA== + +semver@7.7.2: + version "7.7.2" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.7.2.tgz#67d99fdcd35cec21e6f8b87a7fd515a33f982b58" + integrity sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA== + +semver@^7.3.5, semver@^7.6.3, semver@^7.7.3: + version "7.7.4" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.7.4.tgz#28464e36060e991fa7a11d0279d2d3f3b57a7e8a" + integrity sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA== + +send@0.18.0: + version "0.18.0" + resolved "https://registry.yarnpkg.com/send/-/send-0.18.0.tgz#670167cc654b05f5aa4a767f9113bb371bc706be" + 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" + +serialize-error@^13.0.1: + version "13.0.1" + resolved "https://registry.yarnpkg.com/serialize-error/-/serialize-error-13.0.1.tgz#dd1e1bf6d3e3d01037d126bd95e919f48b0c8ec0" + integrity sha512-bBZaRwLH9PN5HbLCjPId4dP5bNGEtumcErgOX952IsvOhVPrm3/AeK1y0UHA/QaPG701eg0yEnOKsCOC6X/kaA== + dependencies: + non-error "^0.1.0" + type-fest "^5.4.1" + +serve-static@1.15.0: + version "1.15.0" + resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.15.0.tgz#faaef08cffe0a1a62f60cad0c4e513cff0ac9540" + integrity sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g== + dependencies: + encodeurl "~1.0.2" + escape-html "~1.0.3" + parseurl "~1.3.3" + send "0.18.0" + +set-function-length@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.2.2.tgz#aac72314198eaed975cf77b2c3b6b880695e5449" + integrity sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg== + dependencies: + define-data-property "^1.1.4" + es-errors "^1.3.0" + function-bind "^1.1.2" + get-intrinsic "^1.2.4" + gopd "^1.0.1" + has-property-descriptors "^1.0.2" + +set-function-name@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/set-function-name/-/set-function-name-2.0.2.tgz#16a705c5a0dc2f5e638ca96d8a8cd4e1c2b90985" + integrity sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ== + dependencies: + define-data-property "^1.1.4" + es-errors "^1.3.0" + functions-have-names "^1.2.3" + has-property-descriptors "^1.0.2" + +set-proto@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/set-proto/-/set-proto-1.0.0.tgz#0760dbcff30b2d7e801fd6e19983e56da337565e" + integrity sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw== + dependencies: + dunder-proto "^1.0.1" + es-errors "^1.3.0" + es-object-atoms "^1.0.0" + +setprototypeof@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" + integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== + +sharp-ico@0.1.5: + version "0.1.5" + resolved "https://registry.yarnpkg.com/sharp-ico/-/sharp-ico-0.1.5.tgz#5d263558adfb00903313db9403e20dc66ffcfa5b" + integrity sha512-a3jODQl82NPp1d5OYb0wY+oFaPk7AvyxipIowCHk7pBsZCWgbe0yAkU2OOXdoH0ENyANhyOQbs9xkAiRHcF02Q== + dependencies: + decode-ico "*" + ico-endec "*" + sharp "*" + +sharp@*: + version "0.34.5" + resolved "https://registry.yarnpkg.com/sharp/-/sharp-0.34.5.tgz#b6f148e4b8c61f1797bde11a9d1cfebbae2c57b0" + integrity sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg== + dependencies: + "@img/colour" "^1.0.0" + detect-libc "^2.1.2" + semver "^7.7.3" + optionalDependencies: + "@img/sharp-darwin-arm64" "0.34.5" + "@img/sharp-darwin-x64" "0.34.5" + "@img/sharp-libvips-darwin-arm64" "1.2.4" + "@img/sharp-libvips-darwin-x64" "1.2.4" + "@img/sharp-libvips-linux-arm" "1.2.4" + "@img/sharp-libvips-linux-arm64" "1.2.4" + "@img/sharp-libvips-linux-ppc64" "1.2.4" + "@img/sharp-libvips-linux-riscv64" "1.2.4" + "@img/sharp-libvips-linux-s390x" "1.2.4" + "@img/sharp-libvips-linux-x64" "1.2.4" + "@img/sharp-libvips-linuxmusl-arm64" "1.2.4" + "@img/sharp-libvips-linuxmusl-x64" "1.2.4" + "@img/sharp-linux-arm" "0.34.5" + "@img/sharp-linux-arm64" "0.34.5" + "@img/sharp-linux-ppc64" "0.34.5" + "@img/sharp-linux-riscv64" "0.34.5" + "@img/sharp-linux-s390x" "0.34.5" + "@img/sharp-linux-x64" "0.34.5" + "@img/sharp-linuxmusl-arm64" "0.34.5" + "@img/sharp-linuxmusl-x64" "0.34.5" + "@img/sharp-wasm32" "0.34.5" + "@img/sharp-win32-arm64" "0.34.5" + "@img/sharp-win32-ia32" "0.34.5" + "@img/sharp-win32-x64" "0.34.5" + +sharp@0.33.5, sharp@^0.33.1: + version "0.33.5" + resolved "https://registry.yarnpkg.com/sharp/-/sharp-0.33.5.tgz#13e0e4130cc309d6a9497596715240b2ec0c594e" + integrity sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw== + dependencies: + color "^4.2.3" + detect-libc "^2.0.3" + semver "^7.6.3" + optionalDependencies: + "@img/sharp-darwin-arm64" "0.33.5" + "@img/sharp-darwin-x64" "0.33.5" + "@img/sharp-libvips-darwin-arm64" "1.0.4" + "@img/sharp-libvips-darwin-x64" "1.0.4" + "@img/sharp-libvips-linux-arm" "1.0.5" + "@img/sharp-libvips-linux-arm64" "1.0.4" + "@img/sharp-libvips-linux-s390x" "1.0.4" + "@img/sharp-libvips-linux-x64" "1.0.4" + "@img/sharp-libvips-linuxmusl-arm64" "1.0.4" + "@img/sharp-libvips-linuxmusl-x64" "1.0.4" + "@img/sharp-linux-arm" "0.33.5" + "@img/sharp-linux-arm64" "0.33.5" + "@img/sharp-linux-s390x" "0.33.5" + "@img/sharp-linux-x64" "0.33.5" + "@img/sharp-linuxmusl-arm64" "0.33.5" + "@img/sharp-linuxmusl-x64" "0.33.5" + "@img/sharp-wasm32" "0.33.5" + "@img/sharp-win32-ia32" "0.33.5" + "@img/sharp-win32-x64" "0.33.5" + +shebang-command@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" + integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== + dependencies: + shebang-regex "^3.0.0" + +shebang-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" + integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== + +shiki@^3.11.0: + version "3.23.0" + resolved "https://registry.yarnpkg.com/shiki/-/shiki-3.23.0.tgz#fca5332195e3afd6c94b384103ae9671a29c7fb9" + integrity sha512-55Dj73uq9ZXL5zyeRPzHQsK7Nbyt6Y10k5s7OjuFZGMhpp4r/rsLBH0o/0fstIzX1Lep9VxefWljK/SKCzygIA== + dependencies: + "@shikijs/core" "3.23.0" + "@shikijs/engine-javascript" "3.23.0" + "@shikijs/engine-oniguruma" "3.23.0" + "@shikijs/langs" "3.23.0" + "@shikijs/themes" "3.23.0" + "@shikijs/types" "3.23.0" + "@shikijs/vscode-textmate" "^10.0.2" + "@types/hast" "^3.0.4" + +side-channel-list@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/side-channel-list/-/side-channel-list-1.0.1.tgz#c2e0b5a14a540aebee3bbc6c3f8666cc9b509127" + integrity sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w== + dependencies: + es-errors "^1.3.0" + object-inspect "^1.13.4" + +side-channel-map@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/side-channel-map/-/side-channel-map-1.0.1.tgz#d6bb6b37902c6fef5174e5f533fab4c732a26f42" + integrity sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA== + dependencies: + call-bound "^1.0.2" + es-errors "^1.3.0" + get-intrinsic "^1.2.5" + object-inspect "^1.13.3" + +side-channel-weakmap@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz#11dda19d5368e40ce9ec2bdc1fb0ecbc0790ecea" + integrity sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A== + dependencies: + call-bound "^1.0.2" + es-errors "^1.3.0" + get-intrinsic "^1.2.5" + object-inspect "^1.13.3" + side-channel-map "^1.0.1" + +side-channel@^1.0.4, side-channel@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.1.0.tgz#c3fcff9c4da932784873335ec9765fa94ff66bc9" + integrity sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw== + dependencies: + es-errors "^1.3.0" + object-inspect "^1.13.3" + side-channel-list "^1.0.0" + side-channel-map "^1.0.1" + side-channel-weakmap "^1.0.2" + +signal-exit@^3.0.2, signal-exit@^3.0.7: + version "3.0.7" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" + integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== + +signal-exit@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.1.0.tgz#952188c1cbd546070e2dd20d0f41c0ae0530cb04" + integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw== + +simple-concat@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/simple-concat/-/simple-concat-1.0.1.tgz#f46976082ba35c2263f1c8ab5edfe26c41c9552f" + integrity sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q== + +simple-get@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-4.0.1.tgz#4a39db549287c979d352112fa03fd99fd6bc3543" + integrity sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA== + dependencies: + decompress-response "^6.0.0" + once "^1.3.1" + simple-concat "^1.0.0" + +simple-swizzle@^0.2.2: + version "0.2.4" + resolved "https://registry.yarnpkg.com/simple-swizzle/-/simple-swizzle-0.2.4.tgz#a8d11a45a11600d6a1ecdff6363329e3648c3667" + integrity sha512-nAu1WFPQSMNr2Zn9PGSZK9AGn4t/y97lEm+MXTtUDwfP0ksAIX4nO+6ruD9Jwut4C49SB1Ws+fbXsm/yScWOHw== + dependencies: + is-arrayish "^0.3.1" + +slice-ansi@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-5.0.0.tgz#b73063c57aa96f9cd881654b15294d95d285c42a" + integrity sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ== + dependencies: + ansi-styles "^6.0.0" + is-fullwidth-code-point "^4.0.0" + +slice-ansi@^7.1.0: + version "7.1.2" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-7.1.2.tgz#adf7be70aa6d72162d907cd0e6d5c11f507b5403" + integrity sha512-iOBWFgUX7caIZiuutICxVgX1SdxwAVFFKwt1EvMYYec/NWO5meOJ6K5uQxhrYBdQJne4KxiqZc+KptFOWFSI9w== + dependencies: + ansi-styles "^6.2.1" + is-fullwidth-code-point "^5.0.0" + +smart-buffer@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-4.2.0.tgz#6e1d71fa4f18c05f7d0ff216dd16a481d0e8d9ae" + integrity sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg== + +socket.io-adapter@~2.5.2: + version "2.5.6" + resolved "https://registry.yarnpkg.com/socket.io-adapter/-/socket.io-adapter-2.5.6.tgz#c697f609d36a676a46749782274607d8df52c1d8" + integrity sha512-DkkO/dz7MGln0dHn5bmN3pPy+JmywNICWrJqVWiVOyvXjWQFIv9c2h24JrQLLFJ2aQVQf/Cvl1vblnd4r2apLQ== + dependencies: + debug "~4.4.1" + ws "~8.18.3" + +socket.io-parser@~4.2.4: + version "4.2.6" + resolved "https://registry.yarnpkg.com/socket.io-parser/-/socket.io-parser-4.2.6.tgz#19156bf179af3931abd05260cfb1491822578a6f" + integrity sha512-asJqbVBDsBCJx0pTqw3WfesSY0iRX+2xzWEWzrpcH7L6fLzrhyF8WPI8UaeM4YCuDfpwA/cgsdugMsmtz8EJeg== + dependencies: + "@socket.io/component-emitter" "~3.1.0" + debug "~4.4.1" + +socket.io@4.7.2: + version "4.7.2" + resolved "https://registry.yarnpkg.com/socket.io/-/socket.io-4.7.2.tgz#22557d76c3f3ca48f82e73d68b7add36a22df002" + integrity sha512-bvKVS29/I5fl2FGLNHuXlQaUH/BlzX1IN6S+NKLNZpBsPZIDH+90eQmCs2Railn4YUiww4SzUedJ6+uzwFnKLw== + dependencies: + accepts "~1.3.4" + base64id "~2.0.0" + cors "~2.8.5" + debug "~4.3.2" + engine.io "~6.5.2" + socket.io-adapter "~2.5.2" + socket.io-parser "~4.2.4" + +socks-proxy-agent@^8.0.5: + version "8.0.5" + resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-8.0.5.tgz#b9cdb4e7e998509d7659d689ce7697ac21645bee" + integrity sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw== + dependencies: + agent-base "^7.1.2" + debug "^4.3.4" + socks "^2.8.3" + +socks@^2.8.3: + version "2.8.7" + resolved "https://registry.yarnpkg.com/socks/-/socks-2.8.7.tgz#e2fb1d9a603add75050a2067db8c381a0b5669ea" + integrity sha512-HLpt+uLy/pxB+bum/9DzAgiKS8CX1EvbWxI4zlmgGCExImLdiad2iCwXT5Z4c9c3Eq8rP2318mPW2c+QbtjK8A== + dependencies: + ip-address "^10.0.1" + smart-buffer "^4.2.0" + +source-map-js@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.2.1.tgz#1ce5650fddd87abc099eda37dcff024c2667ae46" + integrity sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA== + +source-map@^0.7.0: + version "0.7.6" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.6.tgz#a3658ab87e5b6429c8a1f3ba0083d4c61ca3ef02" + integrity sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ== + +source-map@~0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== + +space-separated-tokens@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz#1ecd9d2350a3844572c3f4a312bceb018348859f" + integrity sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q== + +sprintf-js@~1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" + integrity sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g== + +stack-utils@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-2.0.6.tgz#aaf0748169c02fc33c8232abccf933f54a1cc34f" + integrity sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ== + dependencies: + escape-string-regexp "^2.0.0" + +statuses@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" + integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== + +stop-iteration-iterator@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/stop-iteration-iterator/-/stop-iteration-iterator-1.1.0.tgz#f481ff70a548f6124d0312c3aa14cbfa7aa542ad" + integrity sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ== + dependencies: + es-errors "^1.3.0" + internal-slot "^1.1.0" + +streamx@^2.12.5, streamx@^2.15.0, streamx@^2.25.0: + version "2.25.0" + resolved "https://registry.yarnpkg.com/streamx/-/streamx-2.25.0.tgz#cc967e99390fda8b918b1eeaf3bc437637c8c7af" + integrity sha512-0nQuG6jf1w+wddNEEXCF4nTg3LtufWINB5eFEN+5TNZW7KWJp6x87+JFL43vaAUPyCfH1wID+mNVyW6OHtFamg== + dependencies: + events-universal "^1.0.0" + fast-fifo "^1.3.2" + text-decoder "^1.1.0" + +string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +string-width@^7.0.0, string-width@^7.2.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-7.2.0.tgz#b5bb8e2165ce275d4d43476dd2700ad9091db6dc" + integrity sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ== + dependencies: + emoji-regex "^10.3.0" + get-east-asian-width "^1.0.0" + strip-ansi "^7.1.0" + +string.prototype.trim@^1.2.10: + version "1.2.10" + resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.2.10.tgz#40b2dd5ee94c959b4dcfb1d65ce72e90da480c81" + integrity sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA== + dependencies: + call-bind "^1.0.8" + call-bound "^1.0.2" + define-data-property "^1.1.4" + define-properties "^1.2.1" + es-abstract "^1.23.5" + es-object-atoms "^1.0.0" + has-property-descriptors "^1.0.2" + +string.prototype.trimend@^1.0.9: + version "1.0.9" + resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.9.tgz#62e2731272cd285041b36596054e9f66569b6942" + integrity sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ== + dependencies: + call-bind "^1.0.8" + call-bound "^1.0.2" + define-properties "^1.2.1" + es-object-atoms "^1.0.0" + +string.prototype.trimstart@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz#7ee834dda8c7c17eff3118472bb35bfedaa34dde" + integrity sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg== + dependencies: + call-bind "^1.0.7" + define-properties "^1.2.1" + es-object-atoms "^1.0.0" + +string_decoder@^1.1.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" + integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== + dependencies: + safe-buffer "~5.2.0" + +stringify-entities@^4.0.0: + version "4.0.4" + resolved "https://registry.yarnpkg.com/stringify-entities/-/stringify-entities-4.0.4.tgz#b3b79ef5f277cc4ac73caeb0236c5ba939b3a4f3" + integrity sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg== + dependencies: + character-entities-html4 "^2.0.0" + character-entities-legacy "^3.0.0" + +strip-ansi@^6.0.0, strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +strip-ansi@^7.1.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.2.0.tgz#d22a269522836a627af8d04b5c3fd2c7fa3e32e3" + integrity sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w== + dependencies: + ansi-regex "^6.2.2" + +strip-json-comments@~2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" + integrity sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ== + +style-to-js@^1.0.0: + version "1.1.21" + resolved "https://registry.yarnpkg.com/style-to-js/-/style-to-js-1.1.21.tgz#2908941187f857e79e28e9cd78008b9a0b3e0e8d" + integrity sha512-RjQetxJrrUJLQPHbLku6U/ocGtzyjbJMP9lCNK7Ag0CNh690nSH8woqWH9u16nMjYBAok+i7JO1NP2pOy8IsPQ== + dependencies: + style-to-object "1.0.14" + +style-to-object@1.0.14: + version "1.0.14" + resolved "https://registry.yarnpkg.com/style-to-object/-/style-to-object-1.0.14.tgz#1d22f0e7266bb8c6d8cae5caf4ec4f005e08f611" + integrity sha512-LIN7rULI0jBscWQYaSswptyderlarFkjQ+t79nzty8tcIAceVomEVlLzH5VP4Cmsv6MtKhs7qaAiwlcp+Mgaxw== + dependencies: + inline-style-parser "0.2.7" + +sucrase@^3.32.0, sucrase@^3.34.0, sucrase@^3.35.0: + version "3.35.1" + resolved "https://registry.yarnpkg.com/sucrase/-/sucrase-3.35.1.tgz#4619ea50393fe8bd0ae5071c26abd9b2e346bfe1" + integrity sha512-DhuTmvZWux4H1UOnWMB3sk0sbaCVOoQZjv8u1rDoTV0HTdGem9hkAZtl4JZy8P2z4Bg0nT+YMeOFyVr4zcG5Tw== + dependencies: + "@jridgewell/gen-mapping" "^0.3.2" + commander "^4.0.0" + lines-and-columns "^1.1.6" + mz "^2.7.0" + pirates "^4.0.1" + tinyglobby "^0.2.11" + ts-interface-checker "^0.1.9" + +supports-preserve-symlinks-flag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" + integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== + +tagged-tag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/tagged-tag/-/tagged-tag-1.0.0.tgz#a0b5917c2864cba54841495abfa3f6b13edcf4d6" + integrity sha512-yEFYrVhod+hdNyx7g5Bnkkb0G6si8HJurOoOEgC8B/O0uXLHlaey/65KRv6cuWBNhBgHKAROVpc7QyYqE5gFng== + +tailwindcss@3.4.4: + version "3.4.4" + resolved "https://registry.yarnpkg.com/tailwindcss/-/tailwindcss-3.4.4.tgz#351d932273e6abfa75ce7d226b5bf3a6cb257c05" + integrity sha512-ZoyXOdJjISB7/BcLTR6SEsLgKtDStYyYZVLsUtWChO4Ps20CBad7lfJKVDiejocV4ME1hLmyY0WJE3hSDcmQ2A== + dependencies: + "@alloc/quick-lru" "^5.2.0" + arg "^5.0.2" + chokidar "^3.5.3" + didyoumean "^1.2.2" + dlv "^1.1.3" + fast-glob "^3.3.0" + glob-parent "^6.0.2" + is-glob "^4.0.3" + jiti "^1.21.0" + lilconfig "^2.1.0" + micromatch "^4.0.5" + normalize-path "^3.0.0" + object-hash "^3.0.0" + picocolors "^1.0.0" + postcss "^8.4.23" + postcss-import "^15.1.0" + postcss-js "^4.0.1" + postcss-load-config "^4.0.1" + postcss-nested "^6.0.1" + postcss-selector-parser "^6.0.11" + resolve "^1.22.2" + sucrase "^3.32.0" + +tailwindcss@^3.4.17: + version "3.4.19" + resolved "https://registry.yarnpkg.com/tailwindcss/-/tailwindcss-3.4.19.tgz#af2a0a4ae302d52ebe078b6775e799e132500ee2" + integrity sha512-3ofp+LL8E+pK/JuPLPggVAIaEuhvIz4qNcf3nA1Xn2o/7fb7s/TYpHhwGDv1ZU3PkBluUVaF8PyCHcm48cKLWQ== + dependencies: + "@alloc/quick-lru" "^5.2.0" + arg "^5.0.2" + chokidar "^3.6.0" + didyoumean "^1.2.2" + dlv "^1.1.3" + fast-glob "^3.3.2" + glob-parent "^6.0.2" + is-glob "^4.0.3" + jiti "^1.21.7" + lilconfig "^3.1.3" + micromatch "^4.0.8" + normalize-path "^3.0.0" + object-hash "^3.0.0" + picocolors "^1.1.1" + postcss "^8.4.47" + postcss-import "^15.1.0" + postcss-js "^4.0.1" + postcss-load-config "^4.0.2 || ^5.0 || ^6.0" + postcss-nested "^6.2.0" + postcss-selector-parser "^6.1.2" + resolve "^1.22.8" + sucrase "^3.35.0" + +tar-fs@^2.0.0: + version "2.1.4" + resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-2.1.4.tgz#800824dbf4ef06ded9afea4acafe71c67c76b930" + integrity sha512-mDAjwmZdh7LTT6pNleZ05Yt65HC3E+NiQzl672vQG38jIrehtJk/J3mNwIg+vShQPcLF/LV7CMnDW6vjj6sfYQ== + dependencies: + chownr "^1.1.1" + mkdirp-classic "^0.5.2" + pump "^3.0.0" + tar-stream "^2.1.4" + +tar-fs@^3.0.6: + version "3.1.2" + resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-3.1.2.tgz#114b012f54796f31e62f3e57792820a80b83ae6e" + integrity sha512-QGxxTxxyleAdyM3kpFs14ymbYmNFrfY+pHj7Z8FgtbZ7w2//VAgLMac7sT6nRpIHjppXO2AwwEOg0bPFVRcmXw== + dependencies: + pump "^3.0.0" + tar-stream "^3.1.5" + optionalDependencies: + bare-fs "^4.0.1" + bare-path "^3.0.0" + +tar-stream@^2.1.4: + version "2.2.0" + resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-2.2.0.tgz#acad84c284136b060dc3faa64474aa9aebd77287" + integrity sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ== + dependencies: + bl "^4.0.3" + end-of-stream "^1.4.1" + fs-constants "^1.0.0" + inherits "^2.0.3" + readable-stream "^3.1.1" + +tar-stream@^3.1.5: + version "3.1.8" + resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-3.1.8.tgz#a26f5b26c34dfd4936a4f8a9e694a8f5102af13d" + integrity sha512-U6QpVRyCGHva435KoNWy9PRoi2IFYCgtEhq9nmrPPpbRacPs9IH4aJ3gbrFC8dPcXvdSZ4XXfXT5Fshbp2MtlQ== + dependencies: + b4a "^1.6.4" + bare-fs "^4.5.5" + fast-fifo "^1.2.0" + streamx "^2.15.0" + +tar@6.1.15: + version "6.1.15" + resolved "https://registry.yarnpkg.com/tar/-/tar-6.1.15.tgz#c9738b0b98845a3b344d334b8fa3041aaba53a69" + integrity sha512-/zKt9UyngnxIT/EAGYuxaMYgOIJiP81ab9ZfkILq4oNLPFX50qyYmu7jRj9qeXoxmJHjGlbH0+cm2uy1WCs10A== + dependencies: + chownr "^2.0.0" + fs-minipass "^2.0.0" + minipass "^5.0.0" + minizlib "^2.1.1" + mkdirp "^1.0.3" + yallist "^4.0.0" + +teex@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/teex/-/teex-1.0.1.tgz#b8fa7245ef8e8effa8078281946c85ab780a0b12" + integrity sha512-eYE6iEI62Ni1H8oIa7KlDU6uQBtqr4Eajni3wX7rpfXD8ysFx8z0+dri+KWEPWpBsxXfxu58x/0jvTVT1ekOSg== + dependencies: + streamx "^2.12.5" + +text-decoder@^1.1.0: + version "1.2.7" + resolved "https://registry.yarnpkg.com/text-decoder/-/text-decoder-1.2.7.tgz#5d073a9a74b9c0a9d28dfadcab96b604af57d8ba" + integrity sha512-vlLytXkeP4xvEq2otHeJfSQIRyWxo/oZGEbXrtEEF9Hnmrdly59sUbzZ/QgyWuLYHctCHxFF4tRQZNQ9k60ExQ== + dependencies: + b4a "^1.6.4" + +thenify-all@^1.0.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/thenify-all/-/thenify-all-1.6.0.tgz#1a1918d402d8fc3f98fbf234db0bcc8cc10e9726" + integrity sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA== + dependencies: + thenify ">= 3.1.0 < 4" + +"thenify@>= 3.1.0 < 4": + version "3.3.1" + resolved "https://registry.yarnpkg.com/thenify/-/thenify-3.3.1.tgz#8932e686a4066038a016dd9e2ca46add9838a95f" + integrity sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw== + dependencies: + any-promise "^1.0.0" + +through@^2.3.8: + version "2.3.8" + resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" + integrity sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg== + +tinyglobby@^0.2.11: + version "0.2.16" + resolved "https://registry.yarnpkg.com/tinyglobby/-/tinyglobby-0.2.16.tgz#1c3b7eb953fce42b226bc5a1ee06428281aff3d6" + integrity sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg== + dependencies: + fdir "^6.5.0" + picomatch "^4.0.4" + +to-data-view@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/to-data-view/-/to-data-view-1.1.0.tgz#08d6492b0b8deb9b29bdf1f61c23eadfa8994d00" + integrity sha512-1eAdufMg6mwgmlojAx3QeMnzB/BTVp7Tbndi3U7ftcT2zCZadjxkkmLmd97zmaxWi+sgGcgWrokmpEoy0Dn0vQ== + +to-regex-range@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== + dependencies: + is-number "^7.0.0" + +toidentifier@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" + integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== + +tr46@~0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" + integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== + +trim-lines@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/trim-lines/-/trim-lines-3.0.1.tgz#d802e332a07df861c48802c04321017b1bd87338" + integrity sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg== + +trim-trailing-lines@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/trim-trailing-lines/-/trim-trailing-lines-2.1.0.tgz#9aac7e89b09cb35badf663de7133c6de164f86df" + integrity sha512-5UR5Biq4VlVOtzqkm2AZlgvSlDJtME46uV0br0gENbwN4l5+mMKT4b9gJKqWtuL2zAIqajGJGuvbCbcAJUZqBg== + +trough@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/trough/-/trough-2.2.0.tgz#94a60bd6bd375c152c1df911a4b11d5b0256f50f" + integrity sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw== + +ts-interface-checker@^0.1.9: + version "0.1.13" + resolved "https://registry.yarnpkg.com/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz#784fd3d679722bc103b1b4b8030bcddb5db2a699" + integrity sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA== + +tslib@^1.14.1: + version "1.14.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" + integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== + +tslib@^2.0.1, tslib@^2.1.0, tslib@^2.2.0, tslib@^2.4.0, tslib@^2.6.0, tslib@^2.8.1: + version "2.8.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f" + integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w== + +tunnel-agent@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" + integrity sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w== + dependencies: + safe-buffer "^5.0.1" + +twoslash-protocol@0.3.8: + version "0.3.8" + resolved "https://registry.yarnpkg.com/twoslash-protocol/-/twoslash-protocol-0.3.8.tgz#451011af75d76f300784d7bf1a975cfe7a744ed5" + integrity sha512-HmvAHoiEviK8LqvAQyc9/irkdvwTUiR1fHmNwH/0gq8EHxyBt4PWVPixjEXg6wJu1u6yBrILEWXGK9Kw58/8yQ== + +twoslash@^0.3.6: + version "0.3.8" + resolved "https://registry.yarnpkg.com/twoslash/-/twoslash-0.3.8.tgz#bfeeb7218b6e3e1be617daf84eeee2aa9861c391" + integrity sha512-OeDz0kDl8sqPUN3nr7gqcvOs70f5lZsdhKYTX3/SgB9OvdadzzoYJI/4SBXhXV1HG8E9fLc+e17itoRYTxmoig== + dependencies: + "@typescript/vfs" "^1.6.4" + twoslash-protocol "0.3.8" + +type-fest@^0.21.3: + version "0.21.3" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37" + integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w== + +type-fest@^4.27.0: + version "4.41.0" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-4.41.0.tgz#6ae1c8e5731273c2bf1f58ad39cbae2c91a46c58" + integrity sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA== + +type-fest@^5.4.1: + version "5.6.0" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-5.6.0.tgz#502f7a003b7309e96a7e17052cc2ab2c7e5c7a31" + integrity sha512-8ZiHFm91orbSAe2PSAiSVBVko18pbhbiB3U9GglSzF/zCGkR+rxpHx6sEMCUm4kxY4LjDIUGgCfUMtwfZfjfUA== + dependencies: + tagged-tag "^1.0.0" + +type-is@~1.6.18: + version "1.6.18" + resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" + integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== + dependencies: + media-typer "0.3.0" + mime-types "~2.1.24" + +typed-array-buffer@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz#a72395450a4869ec033fd549371b47af3a2ee536" + integrity sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw== + dependencies: + call-bound "^1.0.3" + es-errors "^1.3.0" + is-typed-array "^1.1.14" + +typed-array-byte-length@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz#8407a04f7d78684f3d252aa1a143d2b77b4160ce" + integrity sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg== + dependencies: + call-bind "^1.0.8" + for-each "^0.3.3" + gopd "^1.2.0" + has-proto "^1.2.0" + is-typed-array "^1.1.14" + +typed-array-byte-offset@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/typed-array-byte-offset/-/typed-array-byte-offset-1.0.4.tgz#ae3698b8ec91a8ab945016108aef00d5bff12355" + integrity sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ== + dependencies: + available-typed-arrays "^1.0.7" + call-bind "^1.0.8" + for-each "^0.3.3" + gopd "^1.2.0" + has-proto "^1.2.0" + is-typed-array "^1.1.15" + reflect.getprototypeof "^1.0.9" + +typed-array-length@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/typed-array-length/-/typed-array-length-1.0.7.tgz#ee4deff984b64be1e118b0de8c9c877d5ce73d3d" + integrity sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg== + dependencies: + call-bind "^1.0.7" + for-each "^0.3.3" + gopd "^1.0.1" + is-typed-array "^1.1.13" + possible-typed-array-names "^1.0.0" + reflect.getprototypeof "^1.0.6" + +unbox-primitive@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.1.0.tgz#8d9d2c9edeea8460c7f35033a88867944934d1e2" + integrity sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw== + dependencies: + call-bound "^1.0.3" + has-bigints "^1.0.2" + has-symbols "^1.1.0" + which-boxed-primitive "^1.1.1" + +unbzip2-stream@^1.4.3: + version "1.4.3" + resolved "https://registry.yarnpkg.com/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz#b0da04c4371311df771cdc215e87f2130991ace7" + integrity sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg== + dependencies: + buffer "^5.2.1" + through "^2.3.8" + +undici-types@~7.19.0: + version "7.19.2" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-7.19.2.tgz#1b67fc26d0f157a0cba3a58a5b5c1e2276b8ba2a" + integrity sha512-qYVnV5OEm2AW8cJMCpdV20CDyaN3g0AjDlOGf1OW4iaDEx8MwdtChUp4zu4H0VP3nDRF/8RKWH+IPp9uW0YGZg== + +unified@11.0.5, unified@^11.0.0, unified@^11.0.4: + version "11.0.5" + resolved "https://registry.yarnpkg.com/unified/-/unified-11.0.5.tgz#f66677610a5c0a9ee90cab2b8d4d66037026d9e1" + integrity sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA== + dependencies: + "@types/unist" "^3.0.0" + bail "^2.0.0" + devlop "^1.0.0" + extend "^3.0.0" + is-plain-obj "^4.0.0" + trough "^2.0.0" + vfile "^6.0.0" + +unist-builder@4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/unist-builder/-/unist-builder-4.0.0.tgz#817b326c015a6f9f5e92bb55b8e8bc5e578fe243" + integrity sha512-wmRFnH+BLpZnTKpc5L7O67Kac89s9HMrtELpnNaE6TAobq5DTZZs5YaTQfAZBA9bFPECx2uVAPO31c+GVug8mg== + dependencies: + "@types/unist" "^3.0.0" + +unist-util-find-after@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/unist-util-find-after/-/unist-util-find-after-5.0.0.tgz#3fccc1b086b56f34c8b798e1ff90b5c54468e896" + integrity sha512-amQa0Ep2m6hE2g72AugUItjbuM8X8cGQnFoHk0pGfrFeT9GZhzN5SW8nRsiGKK7Aif4CrACPENkA6P/Lw6fHGQ== + dependencies: + "@types/unist" "^3.0.0" + unist-util-is "^6.0.0" + +unist-util-is@^5.0.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/unist-util-is/-/unist-util-is-5.2.1.tgz#b74960e145c18dcb6226bc57933597f5486deae9" + integrity sha512-u9njyyfEh43npf1M+yGKDGVPbY/JWEemg5nH05ncKPfi+kBbKBJoTdsogMu33uhytuLlv9y0O7GH7fEdwLdLQw== + dependencies: + "@types/unist" "^2.0.0" + +unist-util-is@^6.0.0: + version "6.0.1" + resolved "https://registry.yarnpkg.com/unist-util-is/-/unist-util-is-6.0.1.tgz#d0a3f86f2dd0db7acd7d8c2478080b5c67f9c6a9" + integrity sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g== + dependencies: + "@types/unist" "^3.0.0" + +unist-util-map@4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/unist-util-map/-/unist-util-map-4.0.0.tgz#29ab31b16d2760b2a31c71b2169500f5b00dbaac" + integrity sha512-HJs1tpkSmRJUzj6fskQrS5oYhBYlmtcvy4SepdDEEsL04FjBrgF0Mgggvxc1/qGBGgW7hRh9+UBK1aqTEnBpIA== + dependencies: + "@types/unist" "^3.0.0" + +unist-util-modify-children@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/unist-util-modify-children/-/unist-util-modify-children-4.0.0.tgz#981d6308e887b005d1f491811d3cbcc254b315e9" + integrity sha512-+tdN5fGNddvsQdIzUF3Xx82CU9sMM+fA0dLgR9vOmT0oPT2jH+P1nd5lSqfCfXAw+93NhcXNY2qqvTUtE4cQkw== + dependencies: + "@types/unist" "^3.0.0" + array-iterate "^2.0.0" + +unist-util-position-from-estree@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/unist-util-position-from-estree/-/unist-util-position-from-estree-2.0.0.tgz#d94da4df596529d1faa3de506202f0c9a23f2200" + integrity sha512-KaFVRjoqLyF6YXCbVLNad/eS4+OfPQQn2yOd7zF/h5T/CSL2v8NpN6a5TPvtbXthAGw5nG+PuTtq+DdIZr+cRQ== + dependencies: + "@types/unist" "^3.0.0" + +unist-util-position@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/unist-util-position/-/unist-util-position-5.0.0.tgz#678f20ab5ca1207a97d7ea8a388373c9cf896be4" + integrity sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA== + dependencies: + "@types/unist" "^3.0.0" + +unist-util-remove-position@5.0.0, unist-util-remove-position@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/unist-util-remove-position/-/unist-util-remove-position-5.0.0.tgz#fea68a25658409c9460408bc6b4991b965b52163" + integrity sha512-Hp5Kh3wLxv0PHj9m2yZhhLt58KzPtEYKQQ4yxfYFEO7EvHwzyDYnduhHnY1mDxoqr7VUwVuHXk9RXKIiYS1N8Q== + dependencies: + "@types/unist" "^3.0.0" + unist-util-visit "^5.0.0" + +unist-util-remove@4.0.0, unist-util-remove@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/unist-util-remove/-/unist-util-remove-4.0.0.tgz#94b7d6bbd24e42d2f841e947ed087be5c82b222e" + integrity sha512-b4gokeGId57UVRX/eVKej5gXqGlc9+trkORhFJpu9raqZkZhU0zm8Doi05+HaiBsMEIJowL+2WtQ5ItjsngPXg== + dependencies: + "@types/unist" "^3.0.0" + unist-util-is "^6.0.0" + unist-util-visit-parents "^6.0.0" + +unist-util-stringify-position@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz#449c6e21a880e0855bf5aabadeb3a740314abac2" + integrity sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ== + dependencies: + "@types/unist" "^3.0.0" + +unist-util-visit-children@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/unist-util-visit-children/-/unist-util-visit-children-3.0.0.tgz#4bced199b71d7f3c397543ea6cc39e7a7f37dc7e" + integrity sha512-RgmdTfSBOg04sdPcpTSD1jzoNBjt9a80/ZCzp5cI9n1qPzLZWF9YdvWGN2zmTumP1HWhXKdUWexjy/Wy/lJ7tA== + dependencies: + "@types/unist" "^3.0.0" + +unist-util-visit-parents@6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/unist-util-visit-parents/-/unist-util-visit-parents-6.0.1.tgz#4d5f85755c3b8f0dc69e21eca5d6d82d22162815" + integrity sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw== + dependencies: + "@types/unist" "^3.0.0" + unist-util-is "^6.0.0" + +unist-util-visit-parents@^5.1.1: + version "5.1.3" + resolved "https://registry.yarnpkg.com/unist-util-visit-parents/-/unist-util-visit-parents-5.1.3.tgz#b4520811b0ca34285633785045df7a8d6776cfeb" + integrity sha512-x6+y8g7wWMyQhL1iZfhIPhDAs7Xwbn9nRosDXl7qoPTSCy0yNxnKc+hWokFifWQIDGi154rdUqKvbCa4+1kLhg== + dependencies: + "@types/unist" "^2.0.0" + unist-util-is "^5.0.0" + +unist-util-visit-parents@^6.0.0: + version "6.0.2" + resolved "https://registry.yarnpkg.com/unist-util-visit-parents/-/unist-util-visit-parents-6.0.2.tgz#777df7fb98652ce16b4b7cd999d0a1a40efa3a02" + integrity sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ== + dependencies: + "@types/unist" "^3.0.0" + unist-util-is "^6.0.0" + +unist-util-visit@4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/unist-util-visit/-/unist-util-visit-4.1.2.tgz#125a42d1eb876283715a3cb5cceaa531828c72e2" + integrity sha512-MSd8OUGISqHdVvfY9TPhyK2VdUrPgxkUtWSuMHF6XAAFuL4LokseigBnZtPnJMu+FbynTkFNnFlyjxpVKujMRg== + dependencies: + "@types/unist" "^2.0.0" + unist-util-is "^5.0.0" + unist-util-visit-parents "^5.1.1" + +unist-util-visit@5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/unist-util-visit/-/unist-util-visit-5.0.0.tgz#a7de1f31f72ffd3519ea71814cccf5fd6a9217d6" + integrity sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg== + dependencies: + "@types/unist" "^3.0.0" + unist-util-is "^6.0.0" + unist-util-visit-parents "^6.0.0" + +unist-util-visit@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/unist-util-visit/-/unist-util-visit-5.1.0.tgz#9a2a28b0aa76a15e0da70a08a5863a2f060e2468" + integrity sha512-m+vIdyeCOpdr/QeQCu2EzxX/ohgS8KbnPDgFni4dQsfSCtpz8UqDyY5GjRru8PDKuYn7Fq19j1CQ+nJSsGKOzg== + dependencies: + "@types/unist" "^3.0.0" + unist-util-is "^6.0.0" + unist-util-visit-parents "^6.0.0" + +universalify@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.1.tgz#168efc2180964e6386d061e094df61afe239b18d" + integrity sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw== + +unpipe@1.0.0, unpipe@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" + integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== + +urijs@^1.19.11: + version "1.19.11" + resolved "https://registry.yarnpkg.com/urijs/-/urijs-1.19.11.tgz#204b0d6b605ae80bea54bea39280cdb7c9f923cc" + integrity sha512-HXgFDgDommxn5/bIv0cnQZsPhHDA90NPHD6+c/v21U5+Sx5hoP8+dP9IZXBU1gIfvdRfhG8cel9QNPeionfcCQ== + +urlpattern-polyfill@10.0.0: + version "10.0.0" + resolved "https://registry.yarnpkg.com/urlpattern-polyfill/-/urlpattern-polyfill-10.0.0.tgz#f0a03a97bfb03cdf33553e5e79a2aadd22cac8ec" + integrity sha512-H/A06tKD7sS1O1X2SshBVeA5FLycRpjqiBeqGKmBwBDBy28EnRjORxTNe269KSSr5un5qyWi1iL61wLxpd+ZOg== + +util-deprecate@^1.0.1, util-deprecate@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== + +utility-types@^3.10.0: + version "3.11.0" + resolved "https://registry.yarnpkg.com/utility-types/-/utility-types-3.11.0.tgz#607c40edb4f258915e901ea7995607fdf319424c" + integrity sha512-6Z7Ma2aVEWisaL6TvBCy7P8rm2LQoPv6dJ7ecIaIixHcwfbJ0x7mWdbcwlIM5IGQxPZSFYeqRCqlOOeKoJYMkw== + +utils-merge@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" + integrity sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA== + +uuid@11.1.0: + version "11.1.0" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-11.1.0.tgz#9549028be1753bb934fc96e2bca09bb4105ae912" + integrity sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A== + +vary@^1, vary@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" + integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg== + +vfile-location@^5.0.0: + version "5.0.3" + resolved "https://registry.yarnpkg.com/vfile-location/-/vfile-location-5.0.3.tgz#cb9eacd20f2b6426d19451e0eafa3d0a846225c3" + integrity sha512-5yXvWDEgqeiYiBe1lbxYF7UMAIm/IcopxMHrMQDq3nvKcjPKIhZklUKL+AE7J7uApI4kwe2snsK+eI6UTj9EHg== + dependencies: + "@types/unist" "^3.0.0" + vfile "^6.0.0" + +vfile-matter@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/vfile-matter/-/vfile-matter-5.0.1.tgz#3f701840dde13c68d72d5c5ebd9cf233dff84419" + integrity sha512-o6roP82AiX0XfkyTHyRCMXgHfltUNlXSEqCIS80f+mbAyiQBE2fxtDVMtseyytGx75sihiJFo/zR6r/4LTs2Cw== + dependencies: + vfile "^6.0.0" + yaml "^2.0.0" + +vfile-message@^4.0.0: + version "4.0.3" + resolved "https://registry.yarnpkg.com/vfile-message/-/vfile-message-4.0.3.tgz#87b44dddd7b70f0641c2e3ed0864ba73e2ea8df4" + integrity sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw== + dependencies: + "@types/unist" "^3.0.0" + unist-util-stringify-position "^4.0.0" + +vfile@6.0.3, vfile@^6.0.0, vfile@^6.0.3: + version "6.0.3" + resolved "https://registry.yarnpkg.com/vfile/-/vfile-6.0.3.tgz#3652ab1c496531852bf55a6bac57af981ebc38ab" + integrity sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q== + dependencies: + "@types/unist" "^3.0.0" + vfile-message "^4.0.0" + +web-namespaces@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/web-namespaces/-/web-namespaces-2.0.1.tgz#1010ff7c650eccb2592cebeeaf9a1b253fd40692" + integrity sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ== + +webidl-conversions@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" + integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== + +whatwg-url@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" + integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw== + dependencies: + tr46 "~0.0.3" + webidl-conversions "^3.0.0" + +which-boxed-primitive@^1.1.0, which-boxed-primitive@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz#d76ec27df7fa165f18d5808374a5fe23c29b176e" + integrity sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA== + dependencies: + is-bigint "^1.1.0" + is-boolean-object "^1.2.1" + is-number-object "^1.1.1" + is-string "^1.1.1" + is-symbol "^1.1.1" + +which-builtin-type@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/which-builtin-type/-/which-builtin-type-1.2.1.tgz#89183da1b4907ab089a6b02029cc5d8d6574270e" + integrity sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q== + dependencies: + call-bound "^1.0.2" + function.prototype.name "^1.1.6" + has-tostringtag "^1.0.2" + is-async-function "^2.0.0" + is-date-object "^1.1.0" + is-finalizationregistry "^1.1.0" + is-generator-function "^1.0.10" + is-regex "^1.2.1" + is-weakref "^1.0.2" + isarray "^2.0.5" + which-boxed-primitive "^1.1.0" + which-collection "^1.0.2" + which-typed-array "^1.1.16" + +which-collection@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/which-collection/-/which-collection-1.0.2.tgz#627ef76243920a107e7ce8e96191debe4b16c2a0" + integrity sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw== + dependencies: + is-map "^2.0.3" + is-set "^2.0.3" + is-weakmap "^2.0.2" + is-weakset "^2.0.3" + +which-typed-array@^1.1.16, which-typed-array@^1.1.19: + version "1.1.20" + resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.20.tgz#3fdb7adfafe0ea69157b1509f3a1cd892bd1d122" + integrity sha512-LYfpUkmqwl0h9A2HL09Mms427Q1RZWuOHsukfVcKRq9q95iQxdw0ix1JQrqbcDR9PH1QDwf5Qo8OZb5lksZ8Xg== + dependencies: + available-typed-arrays "^1.0.7" + call-bind "^1.0.8" + call-bound "^1.0.4" + for-each "^0.3.5" + get-proto "^1.0.1" + gopd "^1.2.0" + has-tostringtag "^1.0.2" + +which@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" + integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== + dependencies: + isexe "^2.0.0" + +widest-line@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/widest-line/-/widest-line-5.0.0.tgz#b74826a1e480783345f0cd9061b49753c9da70d0" + integrity sha512-c9bZp7b5YtRj2wOe6dlj32MK+Bx/M/d+9VB2SHM1OtsUHR0aV0tdP6DWh/iMt0kWi1t5g1Iudu6hQRNd1A4PVA== + dependencies: + string-width "^7.0.0" + +wrap-ansi@^6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53" + integrity sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +wrap-ansi@^9.0.0: + version "9.0.2" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-9.0.2.tgz#956832dea9494306e6d209eb871643bb873d7c98" + integrity sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww== + dependencies: + ansi-styles "^6.2.1" + string-width "^7.0.0" + strip-ansi "^7.1.0" + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== + +ws@^8.18.0: + version "8.20.0" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.20.0.tgz#4cd9532358eba60bc863aad1623dfb045a4d4af8" + integrity sha512-sAt8BhgNbzCtgGbt2OxmpuryO63ZoDk/sqaB/znQm94T4fCEsy/yV+7CdC1kJhOU9lboAEU7R3kquuycDoibVA== + +ws@~8.17.1: + version "8.17.1" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.17.1.tgz#9293da530bb548febc95371d90f9c878727d919b" + integrity sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ== + +ws@~8.18.3: + version "8.18.3" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.18.3.tgz#b56b88abffde62791c639170400c93dcb0c95472" + integrity sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg== + +xml2js@^0.6.1: + version "0.6.2" + resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.6.2.tgz#dd0b630083aa09c161e25a4d0901e2b2a929b499" + integrity sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA== + dependencies: + sax ">=0.6.0" + xmlbuilder "~11.0.0" + +xmlbuilder@~11.0.0: + version "11.0.1" + resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-11.0.1.tgz#be9bae1c8a046e76b31127726347d0ad7002beb3" + integrity sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA== + +xss@1.0.15: + version "1.0.15" + resolved "https://registry.yarnpkg.com/xss/-/xss-1.0.15.tgz#96a0e13886f0661063028b410ed1b18670f4e59a" + integrity sha512-FVdlVVC67WOIPvfOwhoMETV72f6GbW7aOabBC3WxN/oUdoEMDyLz4OgRv5/gck2ZeNqEQu+Tb0kloovXOfpYVg== + dependencies: + commander "^2.20.3" + cssfilter "0.0.10" + +y18n@^5.0.5: + version "5.0.8" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" + integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== + +yallist@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" + integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== + +yaml@^2.0.0, yaml@^2.3.4, yaml@^2.4.5: + version "2.8.3" + resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.8.3.tgz#a0d6bd2efb3dd03c59370223701834e60409bd7d" + integrity sha512-AvbaCLOO2Otw/lW5bmh9d/WEdcDFdQp2Z2ZUH3pX9U2ihyUY0nvLv7J6TrWowklRGPYbB/IuIMfYgxaCPg5Bpg== + +yargs-parser@^21.1.1: + version "21.1.1" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" + integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== + +yargs@17.7.1: + version "17.7.1" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.1.tgz#34a77645201d1a8fc5213ace787c220eabbd0967" + integrity sha512-cwiTb08Xuv5fqF4AovYacTFNxk62th7LKJ6BL9IGUpTJrWoU7/7WdQGTP2SjKf1dUNBGzDd28p/Yfs/GI6JrLw== + dependencies: + cliui "^8.0.1" + 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.1.1" + +yargs@^17.7.2: + version "17.7.2" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269" + integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w== + dependencies: + cliui "^8.0.1" + 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.1.1" + +yauzl@^2.10.0: + version "2.10.0" + resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9" + integrity sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g== + dependencies: + buffer-crc32 "~0.2.3" + fd-slicer "~1.1.0" + +yoctocolors-cjs@^2.1.3: + version "2.1.3" + resolved "https://registry.yarnpkg.com/yoctocolors-cjs/-/yoctocolors-cjs-2.1.3.tgz#7e4964ea8ec422b7a40ac917d3a344cfd2304baa" + integrity sha512-U/PBtDf35ff0D8X8D0jfdzHYEPFxAI7jJlxZXwCSez5M3190m+QobIfh+sWDWSHMCWWJN2AWamkegn6vr6YBTw== + +yoga-layout@~3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/yoga-layout/-/yoga-layout-3.2.1.tgz#d2d1ba06f0e81c2eb650c3e5ad8b0b4adde1e843" + integrity sha512-0LPOt3AxKqMdFBZA3HBAt/t/8vIKq7VaQYbuA8WxCgung+p9TVyKRYdpvCb80HcdTN2NkbIKbhNwKUfm3tQywQ== + +zod-to-json-schema@3.20.4: + version "3.20.4" + resolved "https://registry.yarnpkg.com/zod-to-json-schema/-/zod-to-json-schema-3.20.4.tgz#155f687c5a059fdc0f1bb3ff32d6e9200036b6f4" + integrity sha512-Un9+kInJ2Zt63n6Z7mLqBifzzPcOyX+b+Exuzf7L1+xqck9Q2EPByyTRduV3kmSPaXaRer1JCsucubpgL1fipg== + +zod@3.21.4: + version "3.21.4" + resolved "https://registry.yarnpkg.com/zod/-/zod-3.21.4.tgz#10882231d992519f0a10b5dd58a38c9dabbb64db" + integrity sha512-m46AKbrzKVzOzs/DZgVnG5H55N1sv1M8qZU3A8RIKbs3mrACDNeIOeilDymVb2HdmP8uwshOCF4uJ8uM9rCqJw== + +zod@3.23.8: + version "3.23.8" + resolved "https://registry.yarnpkg.com/zod/-/zod-3.23.8.tgz#e37b957b5d52079769fb8097099b592f0ef4067d" + integrity sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g== + +zod@3.24.0: + version "3.24.0" + resolved "https://registry.yarnpkg.com/zod/-/zod-3.24.0.tgz#babb32313f7c5f4a99812feee806d186b4f76bde" + integrity sha512-Hz+wiY8yD0VLA2k/+nsg2Abez674dDGTai33SwNvMPuf9uIrBC9eFgIMQxBBbHFxVXi8W+5nX9DcAh9YNSQm/w== + +zod@^4.3.6: + version "4.3.6" + resolved "https://registry.yarnpkg.com/zod/-/zod-4.3.6.tgz#89c56e0aa7d2b05107d894412227087885ab112a" + integrity sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg== + +zwitch@^2.0.0, zwitch@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/zwitch/-/zwitch-2.0.4.tgz#c827d4b0acb76fc3e685a4c6ec2902d51070e9d7" + integrity sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A== diff --git a/docs/.claude/commands/move-page.md b/docs/.claude/commands/move-page.md deleted file mode 100644 index d956200fe0f4e..0000000000000 --- a/docs/.claude/commands/move-page.md +++ /dev/null @@ -1,27 +0,0 @@ -# Move documentation page - -I need to move a documentation page from its current location to a new one within our documentation site. Please help me with the full process including: - -1. Moving the source file to the destination directory: - - If there's a file with the same name in the destination directory, ask for the new name and rename the source file before moving it - - Use the `mv` command to move the file to the new location - -2. Updating relevant _meta.js files to maintain proper navigation: - - Add the page to the destination directory's _meta.js file - - Remove the page from the source directory's _meta.js file - - If the source _meta.js file becomes empty (just contains `module.exports = {}`) - - Delete it - - Delete the directory where that _meta.js file was from the _meta.js file in its parent directory - -3. Finding and updating all internal references/links to the moved page: - - Search for references to the old URL path in all files - - Pay special attention to link references at the bottom of files - - Check plugins that might construct URLs programmatically - -4. Adding a redirect from the old URL to the new one: - - Add a new entry at the top of the redirects.json file - - Format should follow existing entries with "permanent": true - -Before starting, ask for: -- Source page path (in URL format, e.g., /reference/configuration/environment-variables) -- Destination page path (in URL format, e.g., /product/configuration/reference/environment-variables) diff --git a/docs/.gitignore b/docs/.gitignore index 26565a4c68ee6..822788e19093e 100644 --- a/docs/.gitignore +++ b/docs/.gitignore @@ -1,37 +1,4 @@ -# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. - -# dependencies -/node_modules -/.pnp -.pnp.js - -# testing -/coverage - -# next.js -/.next/ -/out/ - -# production -/build - -# misc -.DS_Store -*.pem -.idea - -# debug -npm-debug.log* -yarn-debug.log* -yarn-error.log* -.pnpm-debug.log* - -# local env files -.env*.local - -# vercel -.vercel - -# typescript -*.tsbuildinfo -next-env.d.ts +.next +node_modules +_pagefind/ +public/_pagefind/ diff --git a/docs/.nvmrc b/docs/.nvmrc deleted file mode 100644 index 8fdd954df9831..0000000000000 --- a/docs/.nvmrc +++ /dev/null @@ -1 +0,0 @@ -22 \ No newline at end of file diff --git a/docs/CLAUDE.md b/docs/CLAUDE.md index 6750612d693ab..26329abedf60c 100644 --- a/docs/CLAUDE.md +++ b/docs/CLAUDE.md @@ -1,81 +1,210 @@ -# CLAUDE.md +# Cube Documentation (LEGACY — DEPRECATED) -This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. +> **This `/docs` site is deprecated. Do not add or edit content here.** +> The active documentation site is `/docs-mintlify` (Mintlify). Write all new and updated +> docs there — see `docs-mintlify/CLAUDE.md` for conventions. The guidance below is kept +> only for reference to the legacy site. -## Repository Overview +This file provides guidance to Claude Code when working with the documentation site. -This repository contains the documentation site for Cube, a semantic layer for building data applications. The documentation is built using Next.js with the Nextra documentation theme and MDX for content authoring. +## Writing Style -## Project Structure +**Tone**: Professional, direct, and instructive. Address the reader as "you" in second person. -- `/pages`: Contains all the documentation content in MDX format -- `/components`: React components used throughout the documentation site - - `/common`: General UI components like buttons, logos, etc. - - `/layouts`: Page layout components - - `/mdx`: Custom components for use within MDX content - - `/overrides`: Components that override Nextra defaults -- `/public`: Static assets (images, icons) -- `/styles`: Global CSS styles -- `/scripts`: Utility scripts for managing content +**Good**: "You can connect a Cube deployment to Metabase using the SQL API." +**Avoid**: "One can connect..." or "Users can connect..." -## Development Commands +**Headings**: +- H1 (`#`) for page title only (one per page) +- H2 (`##`) for major sections +- H3 (`###`) for subsections +- H4 (`####`) rarely, only for deep nesting -```bash -# Start development server -npm run dev +**Code**: +- Always specify language: ` ```python`, ` ```yaml`, ` ```javascript` +- Use `filename=` attribute when helpful: ` ```python filename="cube.py"` +- Inline code with backticks for identifiers: `driver_factory`, `security_context`, `pre_aggregations` -# Build for production -npm run build +**Links**: +- Define references at file bottom: + ``` + [ref-config]: /product/configuration + [ref-env-vars]: /product/configuration/reference/environment-variables + ``` +- Use reference syntax inline: `[configuration options][ref-config]` -# Start production server -npm run start +**Paragraphs**: Keep moderate length (3-4 sentences). Use bullet lists (with `-`) for multiple items. -# Utility commands for content management -npm run create-redirects # Create redirect entries -npm run migrate-content # Run content migration scripts -npm run update-links # Update links in content files +## Custom Components + +### Alert Boxes + +Use for callouts. Content should be on separate lines from the tags. + +**InfoBox** — informational notes: +```mdx + + +Scheduled refreshes are available on [Premium and Enterprise plans](https://cube.dev/pricing). + + +``` + +**WarningBox** — important warnings: +```mdx + + +Cube expects the context to be an object. If you don't provide an object as the +JWT payload, you will receive an error. + + ``` -## Technology Stack +**SuccessBox** — availability or positive notes: +```mdx + -- **Framework**: Next.js with Nextra theme for documentation -- **Content**: MDX (Markdown with JSX) -- **Styling**: CSS/SCSS modules with Tailwind CSS -- **Deployment**: Vercel +Presentation tools are available in both Cube Cloud and Cube Core. -## Content Organization + +``` -The documentation follows a hierarchical structure: +**ReferenceBox** — links to related documentation: +```mdx + -1. Main sections are defined in `/pages/_meta.js` -2. Each section has its own `_meta.js` file that defines the order and titles of pages -3. Content is written in MDX files with frontmatter +See [Cube style guide][ref-style-guide] for more recommendations on syntax and structure. -## Component Usage in MDX + +``` -The documentation uses custom MDX components for specialized content presentation: +### Code Tabs (for multi-language examples) -- `` - For highlighting important information -- `` - For code examples in multiple languages -- `` and `` - For creating responsive grids -- `` - For embedding videos -- `` - For displaying screenshots +````mdx + -## Best Practices +```python +from cube import config +``` + +```javascript +const config = {} +``` -1. **MDX Content**: - - Use the appropriate custom components for different content types - - Follow the existing section structure when adding new pages - - Include proper frontmatter with title and description + +```` -2. **Component Development**: - - Use CSS/SCSS modules for component styling - - Follow the existing folder structure for new components - - Export components through index files for cleaner imports +### UI Navigation + +```mdx +Settings → Configuration +``` + +### Environment Variables + +```mdx +CUBEJS_DB_SSL +``` + +Auto-links to the environment variables reference. + +### Images + +```mdx + + + +``` + +### Videos + +```mdx + + +``` -3. **Navigation**: - - Update `_meta.js` files when adding new pages to ensure proper navigation +### Grids (for navigation cards) -## Deployment +```mdx + + + +``` + +### Community Drivers + +```mdx + +``` + +## Documentation Structure + +### File Organization + +- Content lives in `/content/product/` +- Each directory needs `_meta.js` for navigation +- Use `index.mdx` with `asIndexPage: true` frontmatter for section overviews + +### _meta.js Files + +Define navigation order and display names: + +```javascript +export default { + "introduction": "Introduction", + "getting-started": "Getting started", + "configuration": "Data Sources & Config" +} +``` + +Hide pages from navigation: + +```javascript +export default { + "visible-page": "Visible Page", + "hidden-page": { + title: "Hidden Page", + display: "hidden" + } +} +``` + +### index.mdx Files + +Create section landing pages: + +```mdx +--- +asIndexPage: true +--- + +# Section Title + +Overview content here... +``` + +### URL Mapping + +File paths map directly to URLs: +- `configuration/data-sources/postgres.mdx` → `/product/configuration/data-sources/postgres` + +## Redirects + +When moving or renaming pages, add redirects to `redirects.json`: + +```json +{ + "source": "/old/path", + "destination": "/new/path", + "permanent": true +} +``` -The site is deployed to Vercel. The deployment process is automated via GitHub integration. +Always use `"permanent": true` for documentation moves. diff --git a/docs/README.md b/docs/README.md deleted file mode 100644 index 0e7a3972c34c9..0000000000000 --- a/docs/README.md +++ /dev/null @@ -1 +0,0 @@ -# Cube Docs diff --git a/docs/app/[[...mdxPath]]/page.jsx b/docs/app/[[...mdxPath]]/page.jsx new file mode 100644 index 0000000000000..e63d7806ea1a0 --- /dev/null +++ b/docs/app/[[...mdxPath]]/page.jsx @@ -0,0 +1,23 @@ +import { generateStaticParamsFor, importPage } from 'nextra/pages' +import { useMDXComponents } from '../../mdx-components' + +export const generateStaticParams = generateStaticParamsFor('mdxPath') + +export async function generateMetadata(props) { + const params = await props.params + const { metadata } = await importPage(params.mdxPath) + return metadata +} + +const Wrapper = useMDXComponents().wrapper + +export default async function Page(props) { + const params = await props.params + const result = await importPage(params.mdxPath) + const { default: MDXContent, toc, metadata } = result + return ( + + + + ) +} diff --git a/docs/app/globals.css b/docs/app/globals.css new file mode 100644 index 0000000000000..32cef2f654046 --- /dev/null +++ b/docs/app/globals.css @@ -0,0 +1,292 @@ +/* Override primary colors */ +:root { + --x-color-primary-600: hsl(251, 61%, 52%); + /* Darker, more saturated backgrounds for sidebar active items */ + --x-color-primary-50: hsl(251, 70%, 95%); + --x-color-primary-100: hsl(251, 70%, 92%); + + /* Brand colors */ + --purple: hsl(251, 94%, 66%); + --purple_bright: hsl(251, 61%, 52%); + --purple_bg: hsl(240, 50%, 98%); + --purple_bg_a08: hsla(244, 94%, 66%, 0.08); + + --pink: hsl(342, 69%, 53%); + --pink_bright: hsl(342, 62%, 48%); + + /* Dark palette */ + --dark: hsl(240, 32%, 10%); + --dark_03: hsl(240, 8%, 45%); + --dark_04: hsl(240, 9%, 69%); + --dark_05: hsl(240, 16%, 91%); + --dark_bg: hsl(240, 12%, 97%); + + /* Gray */ + --gray_01: hsl(228, 6%, 31%); + --gray_02: hsl(225, 4%, 39%); + + /* Spacing */ + --space-2xs: 4px; + --space-xs: 8px; + --space-s: 16px; + --space-m: 24px; + --space-l: 32px; + --space-xl: 48px; + --space-2xl: 64px; +} + +/* Dark mode: brighter purple for links and UI elements */ +.dark { + --nextra-primary-lightness: 65%; +} + +/* Content links in dark mode - brighter purple */ +.dark main a { + color: hsl(251, 90%, 75%) !important; +} + +/* Left sidebar active item - brighter purple in dark mode */ +.dark aside:first-of-type a.x\:font-semibold, +.dark aside:first-of-type a[class*="font-semibold"] { + background-color: hsl(251, 50%, 22%) !important; + color: hsl(251, 100%, 85%) !important; +} + +/* Left sidebar hover - more visible in dark mode */ +.dark aside:first-of-type a:hover { + background-color: hsl(240, 10%, 20%) !important; +} + +/* Font family definitions */ +h1, h2, h3, h4, h5, h6 { + font-family: var(--font-cera-pro), system-ui, -apple-system, sans-serif; +} + +code, pre, kbd, samp { + font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace; +} + +/* Code block styling - matches old docs style */ +.nextra-code { + margin-top: var(--space-m) !important; +} + +.nextra-code pre { + background-color: rgba(124, 58, 237, 0.05) !important; + --tw-ring-shadow: none !important; + box-shadow: none !important; + padding-top: 12px !important; + padding-bottom: 12px !important; +} + +code.nextra-code { + font-size: 0.875rem !important; +} + +.nextra-code pre > div:first-child { + margin-top: 0 !important; +} + +.nextra-code pre code { + margin-top: 0 !important; + font-size: 0.8rem !important; +} + +.nextra-code pre code, +.nextra-code pre code span { + background-color: transparent !important; + line-height: 1.5 !important; +} + +/* Dark mode code blocks */ +.dark .nextra-code pre { + background-color: rgba(124, 58, 237, 0.1) !important; +} + +/* Code block filename header - match code block background */ +.nextra-code > div:first-child:has(+ pre) { + background-color: rgba(124, 58, 237, 0.12) !important; + border: none !important; + border-bottom: 1px solid rgba(124, 58, 237, 0.15) !important; + padding: 10px 16px !important; + height: auto !important; + min-height: 0 !important; +} + +.dark .nextra-code > div:first-child:has(+ pre) { + background-color: rgba(124, 58, 237, 0.15) !important; + border-bottom-color: rgba(124, 58, 237, 0.2) !important; +} + +/* Style tree code blocks like regular code blocks */ +[data-language="tree"] { + margin-top: var(--space-m); +} + +[data-language="tree"] pre { + background-color: rgba(124, 58, 237, 0.05) !important; + box-shadow: none !important; +} + +[data-language="tree"] figure { + box-shadow: none !important; +} + +[data-language="tree"] pre code, +[data-language="tree"] pre code span { + background-color: transparent !important; +} + +/* Style inline code (code not in pre blocks) */ +:not(pre) > code, +code:not(.nextra-code) { + background-color: hsla(240, 12%, 97%, 0.75) !important; + border: 1px solid var(--dark_05) !important; + border-radius: 4px !important; + padding: 2px 6px !important; + font-size: 0.875em !important; +} + +.dark :not(pre) > code, +.dark code:not(.nextra-code) { + background-color: hsla(240, 6%, 18%, 0.75) !important; + border-color: hsl(240, 6%, 28%) !important; +} + +/* Inline code in headings should inherit font size */ +h1 code, h2 code, h3 code, h4 code, h5 code, h6 code, +h1 code.nextra-code, h2 code.nextra-code, h3 code.nextra-code, +h4 code.nextra-code, h5 code.nextra-code, h6 code.nextra-code { + font-size: 0.85em !important; +} + +/* Inline code outside links should inherit text color */ +:not(a) > code { + color: inherit !important; +} + +/* Link underline opacity - only for content area links */ +article a { + text-decoration-color: color-mix(in srgb, currentColor 25%, transparent) !important; +} + +article a:hover { + text-decoration: underline !important; + text-decoration-color: color-mix(in srgb, currentColor 50%, transparent) !important; +} + +/* Remove underline from sidebar/nav links */ +aside a, +nav a, +header a, +footer a { + text-decoration: none !important; +} + +aside a:hover, +nav a:hover, +header a:hover, +footer a:hover { + text-decoration: none !important; +} + +/* External link arrows - hide them (target Nextra's LinkArrowIcon by its classes) */ +a[href^="http"] svg.x\:shrink-0 { + display: none !important; +} + +/* Table styling */ +table { + font-size: 1rem; + line-height: 1.43; +} + +th { + background-color: hsla(240, 12%, 97%, 0.75); +} + +.dark th { + background-color: hsla(240, 6%, 20%, 0.75); +} + +/* Remove striped rows - overrides Nextra's x:even:bg-gray-100 */ +tr:nth-child(even) { + background-color: transparent !important; +} + +/* Search popup - make wider */ +@media (min-width: 768px) { + .nextra-search .nextra-search-results { + width: 750px !important; + } +} + +/* Video styling - margins like Screenshot */ +article video { + margin: var(--space-m) 0; +} + +/* Navbar icons - vertical alignment */ +nav[class*="nextra-nav"] a[href], +nav[class*="nextra-nav"] > a, +header nav a[href] { + display: flex !important; + align-items: center !important; +} + +/* Search button alignment */ +nav[class*="nextra-nav"] button:not([aria-label="Menu"]), +header nav button:not([aria-label="Menu"]) { + display: flex !important; + align-items: center !important; +} + +/* Keep search button visible on mobile */ +header.nextra-navbar nav > div.x\:max-md\:hidden:has(button) { + display: flex !important; +} + +/* Hide "Get started for free" button on mobile */ +@media (max-width: 767px) { + header.nextra-navbar nav a[href*="cubecloud.dev/auth/signup"] { + display: none !important; + } +} + +/* Legacy-docs Banner - taller bar so the "visit new docs" link is more prominent */ +.nextra-banner > div { + padding-top: 32px !important; + padding-bottom: 32px !important; + font-size: 1.125rem !important; +} + +/* Legacy-docs Banner - stick to top on all viewports (Nextra default is mobile-only sticky) */ +.nextra-banner { + position: sticky !important; + top: 0 !important; + z-index: 30 !important; +} + +/* Shift the sticky navbar below the sticky banner so they stack instead of overlap */ +header.nextra-navbar { + top: var(--nextra-banner-height) !important; +} + +/* Purple Banner wrapper - animated reveal */ +.pb-wrapper { + --purple-banner-font: var(--font-cera-pro), system-ui, -apple-system, sans-serif; + max-height: 0; + overflow: hidden; + transition: max-height 0.3s ease-in-out; +} + +.pb-wrapper--visible { + max-height: 100px; +} + +@media (max-width: 768px) { + .pb-wrapper--visible { + max-height: 160px; + } +} + diff --git a/docs/app/layout.jsx b/docs/app/layout.jsx new file mode 100644 index 0000000000000..4b5ff3ae4ec62 --- /dev/null +++ b/docs/app/layout.jsx @@ -0,0 +1,140 @@ +import { Layout, Navbar } from 'nextra-theme-docs' +import { Banner, Head } from 'nextra/components' +import { getPageMap } from 'nextra/page-map' +import localFont from 'next/font/local' +import 'nextra-theme-docs/style.css' +import './globals.css' + +const ceraPro = localFont({ + src: [ + { + path: '../fonts/CeraPro-Regular.woff2', + weight: '300', + style: 'normal', + }, + { + path: '../fonts/CeraPro-Regular.woff2', + weight: '400', + style: 'normal', + }, + { + path: '../fonts/CeraPro-Medium.woff2', + weight: '500', + style: 'normal', + }, + { + path: '../fonts/CeraPro-Bold.woff2', + weight: '600', + style: 'normal', + }, + { + path: '../fonts/CeraPro-Bold.woff2', + weight: '700', + style: 'normal', + }, + ], + variable: '--font-cera-pro', +}) + +import { Footer } from '../components/Footer' +import { LogoWithVersion } from '../components/LogoWithVersion' +import { GetStartedButton } from '../components/GetStartedButton' +import { AnalyticsProvider } from '../components/AnalyticsProvider' +import { PurpleBannerWrapper } from '../components/PurpleBannerWrapper' +import { AlgoliaSearch } from '../components/AlgoliaSearch' +import { SearchProviderWrapper } from '../components/SearchProviderWrapper' + +const SlackIcon = () => ( + + + +) + +export const metadata = { + title: { + template: '%s | Cube documentation', + default: 'Cube documentation', + }, + description: 'Cube documentation built with Nextra' +} + +const navbar = ( + } + logoLink={false} + align="left" + projectLink="https://github.com/cube-js/cube" + chatLink="https://slack.cube.dev" + chatIcon={} + > + + +) + +const footer =
+ +const banner = ( + + + You're looking at the old Cube documentation. Visit the new docs → + + +) + +export default async function RootLayout({ children }) { + return ( + + + {process.env.NODE_ENV === 'production' && ( + + + + + + + +``` + +## Pre-setting dashboard filters via URL + +You can pre-set dashboard filter values by adding URL parameters in the format +`?f_.=`. The `` and `` +must match the internal names (not display titles) of the semantic view and +dimension configured on the filter widget. If the filter type is omitted, it +defaults to `equals`. + +Example: + +``` +https://your-tenant.cubecloud.dev/embed/dashboard/YOUR_DASHBOARD_PUBLIC_ID?session=YOUR_SESSION_ID&f_orders_transactions.users_country={"value":"USA"} +``` + +This works on both regular and published (embedded) dashboards. The filter is +only applied if a matching filter widget for that dimension already exists on the +dashboard. + +## Customize dashboard style + +You can customize the appearance of your dashboard — including background, widget +styling, borders, titles, and fonts — using the Styling pane in the +Dashboard Builder. Open your dashboard, click Dashboard Builder in the +top bar, then click the gear icon to open the Styling panel. + +## User attributes + +User attributes enable row-level security and personalized chat responses by filtering data based on user permissions. The attributes you pass during session generation automatically filter data queries and responses. + + + User attributes must first be configured in your Cube admin panel. See the + [User Attributes documentation](/product/administration/users-and-permissions/user-attributes) for + setup instructions. + + +**How it works:** + +1. **Configure attributes** in your admin panel (e.g., `city`, `department`) +2. **Pass attributes** during session generation +3. **Data is automatically filtered** based on user permissions through access policies +4. **AI responses are personalized** to the user's context + +**Example use cases:** + +- Sales reps only see data for their assigned territory +- Regional managers see data filtered by their city +- Department heads see only their department's metrics + +## Example application + +For a complete working example of signed embedding, check out the [cube-embedding-demo](https://github.com/cubedevinc/cube-embedding-demo) repository. This demo application provides: + +- A full working example of iframe embedding +- Implementation of signed iframe embedding with session generation +- A React-based UI for testing embedding functionality +- Backend server that securely handles API key authentication + +You can clone the repository, configure it with your Cube credentials, and run it locally to test embedding functionality or use it as a reference implementation for your own application. + +[ref-api-keys]: /product/administration/api-keys +[ref-generate-session]: /product/apis-integrations/embed-apis/generate-session diff --git a/docs/pages/product/administration/workspace/vizard.mdx b/docs/content/product/embedding/vizard.mdx similarity index 100% rename from docs/pages/product/administration/workspace/vizard.mdx rename to docs/content/product/embedding/vizard.mdx diff --git a/docs/content/product/exploration/_meta.js b/docs/content/product/exploration/_meta.js new file mode 100644 index 0000000000000..f620131a9db80 --- /dev/null +++ b/docs/content/product/exploration/_meta.js @@ -0,0 +1,10 @@ +export default { + "workbooks": "Workbooks", + "explore": "Explore", + "analytics-chat": "Analytics Chat", + "playground": { + title: "Playground", + display: "hidden" + }, +} + diff --git a/docs/content/product/exploration/analytics-chat.mdx b/docs/content/product/exploration/analytics-chat.mdx new file mode 100644 index 0000000000000..a5a4a16af0248 --- /dev/null +++ b/docs/content/product/exploration/analytics-chat.mdx @@ -0,0 +1,25 @@ +# Analytics Chat + +Analytics Chat is a conversational interface that allows you to explore your data using natural language. Ask questions and get AI-powered insights without writing queries or building visualizations manually. + +## How it works + +The AI agent interprets your questions, generates queries against your semantic model, and presents findings in natural language. The agent can create multiple queries to answer complex questions and perform ad hoc analysis while maintaining full data governance through your semantic layer. + +## Key features + +- **Natural language queries** – Ask questions in plain language without knowing SQL +- **Multi-query reasoning** – The AI creates and synthesizes multiple queries for complex questions +- **Semantic model integration** – All queries run against your semantic model with proper access control and security +- **Save to Workbook** – Export insights to [Workbooks](/product/exploration/workbooks) for further analysis + +## Embedding + +Analytics Chat can be [embedded](/product/embedding) into your applications for customer-facing analytics, internal tools, or white-label solutions. + +## Learn more + +- [Workbooks](/product/exploration/workbooks) – Build and organize reports with AI assistance +- [Embedding](/product/embedding) – Embed analytics in your applications +- [Cube Agentic Analytics announcement](https://cube.dev/blog/cube-agentic-analytics) – Learn about the vision behind agentic analytics + diff --git a/docs/pages/product/exploration/explore.mdx b/docs/content/product/exploration/explore.mdx similarity index 100% rename from docs/pages/product/exploration/explore.mdx rename to docs/content/product/exploration/explore.mdx diff --git a/docs/content/product/exploration/playground.mdx b/docs/content/product/exploration/playground.mdx new file mode 100644 index 0000000000000..0d0bed7f21c34 --- /dev/null +++ b/docs/content/product/exploration/playground.mdx @@ -0,0 +1,218 @@ +# Playground + +Playground is a web-based tool that helps validate the data model by executing +[queries][ref-queries] and previewing their results. It is supposed to be used +by data engineers and developers while building the [data model][ref-data-modeling]. +If you'd like to let end users query the data, [connect a BI tool][ref-dataviz-tools] +or use the [JavaScript SDKs][ref-js-sdk] to build your own query builder. + + + + +We recommend to migrate over to [Explore](/product/exploration/explore) and [Workbooks](/product/exploration/workbooks) for data analysis in exploration in Cube cloud platform. + +Playground is available in Cube Core at [localhost:4000](http://localhost:4000) +when it's run in the [development mode][ref-dev-mode]. + + + +You can [view](#viewing-the-data-model) the data model entities or [search](#searching-the-data-model) +for them, [compose](#composing-queries) a query from scratch or [paste](#pasting-a-query) +an exsiting query, view [results](#viewing-results), check a [generated +query](#viewing-a-generated-query), or copy equivalent [queries for data APIs](#copying-api-queries). + +## Viewing the data model + +You can see a list of all cubes or views in the sidebar on the left. Choose either +Cubes or Views to switch between cubes and views and click +on a cube or a view to view a list of its members. + + + +Members of cubes and views (i.e., measures, dimensions, hierarchies, folders, etc.) +are shown using distinct colors and icons. If a member has +a [title][ref-data-model-title] or a [description][ref-data-model-description] set +in the data model, they will be shown in a tooltip. If a member is not +[public][ref-data-model-public], you will see a lock sign next to it. + + + +Even if a cube, a view, or their member is not public, Playground would still allow +you to query and validate it. + + + +### Switching the security context + +You can click on the Security Context button in the top right corner to +change the security context. Changing the security context can affect the contents +of the sidebar that you see: + + + +## Searching the data model + +You can search for cubes, views, and their members using the search bar in the +sidebar on the left. Click on the element in the search results to add it to a new +or existing query. + + + +## Composing queries + +You can compose a new query by selecting desired measures, dimensions, and segments +in the sidebar on the left. Click on the _funnel_ icon next to any member to add a filter +for it to the query or use the Filters pane to add filters, including filters +with [advanced boolean logic][ref-boolean-filters]. + +Click All members or Used members to show only members of the +query or all available members. Click Reset to remove all members from the query. + + + +Use the Order drop-down on the right to specify how the +[results](#viewing-results) shall be sorted. + + + +Use the Options drop-down on the right to specify if the query shall be +[ungrouped][ref-ungrouped-query], to set a [time zone][ref-time-zone], or to set +a [row limit][ref-row-limit] and an offset. You can also request the count of all rows +in the result set as if there's no limit present. + + + +### Pasting a query + +You can also compose a new query by clicking on the _pencil_ button in the sidebar on the +left and pasting a [REST API][ref-rest-api] query or a [GraphQL API][ref-graphql-api] +query from the clipboard and clicking Apply. + + + +Pasting a [SQL API][ref-sql-api] query is not supported. + +### Using query tabs + +You can use query tabs to keep results of previous queries while still being +able to make new queries. Previous queries are kept in the local storage in your browser +and will be restored when you open Playground once again. + +You can also double-click on a query tab to give it a meaningful name. + +### Saving a report + +You can save a _query to a view_ by clicking Save Report in the top right corner. + + + +You can manage saved reports in the [Saved Reports][ref-saved-reports] page. + +## Viewing results + +Click Run Query on the top to run (or re-run) the query and check the +querying time in the top right corner. Click on the querying time to create a +pre-aggregation to accelerate the query. + +View query results on the Results tab. Check the number of rows in the result +set on the bottom and use the pagination control in the bottom right corner, if needed. + + + +Expand the Chart pane to visualize the results. Choose one of visualization +types and pivot data via the Pivot drop-down, if needed. Click Code +to generate front-end code in [Chart Prototyping][ref-chart-prototyping]. + + + +## Viewing a generated query + +View the SQL query that Cube did (or will) run against the data source to get the results +on the Generated SQL tab. Click Copy to put it into your clipboard. + + + + + +Note that a generated query can contain placeholders, e.g., `?` or `$1`, for parameters +that Cube passes to an underlying data source driver later when executing the query. + + + +## Copying API queries + +View the queries for respective data APIs on the SQL API, REST API, +and GraphQL API tabs. Click Copy to put one of them into your clipboard. + + + +{/* + +You can use this Playground to view and [generate data model][ref-data-model] +files. + + + +Data model generator currently has the following limitations: +- Even if [multiple data sources][ref-multiple-data-sources] are configured, +it will only show the tables from in default data source. As a workaround, you +can configure the second data source as default, generate data model files for +it, then change the default data source back. +- With each generation, files in the data model folder will be rewritten. If +you'd like to combine files from multiple generations, please back them up +manually. + + + +*/} + +[ref-dev-mode]: /product/configuration#development-mode +[ref-dataviz-tools]: /product/configuration/visualization-tools +[ref-js-sdk]: /product/apis-integrations/javascript-sdk +[ref-data-model]: /product/data-modeling/data-model-ide#generating-data-model-files +[ref-multiple-data-sources]: /product/configuration/advanced/multiple-data-sources +[ref-queries]: /product/apis-integrations/queries +[ref-data-modeling]: /product/data-modeling/overview +[ref-data-model-title]: /product/data-modeling/reference/measures#title +[ref-data-model-description]: /product/data-modeling/reference/measures#description +[ref-data-model-public]: /product/data-modeling/reference/measures#public +[ref-rest-api]: /product/apis-integrations/rest-api +[ref-graphql-api]: /product/apis-integrations/graphql-api +[ref-sql-api]: /product/apis-integrations/sql-api +[ref-ungrouped-query]: /product/apis-integrations/queries#ungrouped-query +[ref-time-zone]: /product/apis-integrations/queries#time-zone +[ref-row-limit]: /product/apis-integrations/queries#limit +[ref-chart-prototyping]: /product/embedding/vizard +[ref-boolean-filters]: /product/apis-integrations/rest-api/query-format#boolean-logical-operators +[ref-saved-reports]: /product/workspace/saved-reports + diff --git a/docs/content/product/exploration/workbooks/_meta.js b/docs/content/product/exploration/workbooks/_meta.js new file mode 100644 index 0000000000000..74d953c360be9 --- /dev/null +++ b/docs/content/product/exploration/workbooks/_meta.js @@ -0,0 +1,6 @@ +export default { + "querying-data": "Querying data", + "source-sql-tabs": "Source SQL Tabs", + "charts": "Charts", +} + diff --git a/docs/pages/product/exploration/workbooks/charts.mdx b/docs/content/product/exploration/workbooks/charts.mdx similarity index 100% rename from docs/pages/product/exploration/workbooks/charts.mdx rename to docs/content/product/exploration/workbooks/charts.mdx diff --git a/docs/content/product/exploration/workbooks/index.mdx b/docs/content/product/exploration/workbooks/index.mdx new file mode 100644 index 0000000000000..c55b2d898a254 --- /dev/null +++ b/docs/content/product/exploration/workbooks/index.mdx @@ -0,0 +1,36 @@ +--- +asIndexPage: true +--- + +# Workbooks + +Workbooks allow you to build reports with an AI agent, organize the results of your +analysis, and share insights with your team. + +## Tabs + +Workbooks can contain one or more tabs, each providing a different way to query and analyze your data. Tabs enable you to organize multiple analyses within a single workbook, making it easy to explore different aspects of your data or combine insights from different sources. + +## Tab types + +Workbooks support two types of tabs, each designed for different querying approaches: + +### Semantic Query + +[Semantic Query tabs](/product/exploration/workbooks/querying-data) allow you to query your data model through the semantic layer. This ensures all queries use consistent metrics, respect access control policies, and benefit from pre-aggregations for fast performance. + +You can query the semantic layer in three ways: + +- **Point and click** – Use the intuitive interface to select measures and dimensions, build visualizations, and explore your data interactively +- **AI agent** – Ask the AI agent to build queries and visualizations based on natural language questions +- **Semantic SQL** – Write Semantic SQL queries manually to have full control over your queries while still leveraging the semantic layer + +### Source SQL Query + +[Source SQL Query tabs](/product/exploration/workbooks/source-sql-tabs) allow you to query your connected data sources directly, bypassing the semantic layer. This gives you direct access to your raw data and enables deeper exploration beyond what's defined in your data model. + +You can query source SQL in two ways: + +- **Write SQL manually** – Write standard SQL queries directly against your data source for maximum flexibility +- **Ask AI** – Use the AI agent to help you research your data source, build SQL queries, and refine results in real-time + diff --git a/docs/content/product/exploration/workbooks/querying-data.mdx b/docs/content/product/exploration/workbooks/querying-data.mdx new file mode 100644 index 0000000000000..20d64986ff457 --- /dev/null +++ b/docs/content/product/exploration/workbooks/querying-data.mdx @@ -0,0 +1,39 @@ +# Querying data + +In the Semantic Query tab, you can query the semantic layer. On the left, there is a selector for the semantic view that you want to query. + + + +On the left side, you can select a semantic view you would like to query. Inside the semantic view, you can see the measures and dimensions grouped either by cubes or folders. You can search within your semantic view to find the relevant member. + +## Filtering + +Dimensions and measures can be added as filters to focus on specific rows of data. + +## Pivoting + +You can add dimensions to the pivot by right-clicking on the left pane or in the results header. + +Note that chart tables are different from results tables. You can configure pivots in chart tables separately. + +## Limiting + +By default, queries are limited to 10,000 rows of data, but the limit can be adjusted up to 50,000. + +## Sorting + +You can sort results by clicking on dimensions or measures in the left pane or table header. + + +## Advanced semantic queries + +Advanced semantic queries typically can contain CTEs (Common Table Expressions) and unions, and can contain multiple semantic views. In many cases for advanced semantic queries, the interactive components of the UI would be disabled—not the whole UI—as these complex queries require manual SQL editing. + + + + + +Currently, advanced semantic queries can be placed on dashboards, but dashboard filters cannot be applied to advanced semantic queries. + + + diff --git a/docs/pages/product/exploration/workbooks/source-sql-tabs.mdx b/docs/content/product/exploration/workbooks/source-sql-tabs.mdx similarity index 100% rename from docs/pages/product/exploration/workbooks/source-sql-tabs.mdx rename to docs/content/product/exploration/workbooks/source-sql-tabs.mdx diff --git a/docs/content/product/getting-started/_meta.js b/docs/content/product/getting-started/_meta.js new file mode 100644 index 0000000000000..ebe9f3b9c0e72 --- /dev/null +++ b/docs/content/product/getting-started/_meta.js @@ -0,0 +1,20 @@ +export default { + "connect-your-data": "Connect your data", + "use-analytics-chat": "Use analytics chat", + "create-workbooks-and-dashboards": "Create workbooks and dashboards", + "develop-in-ide": "Develop in IDE", + "embed-analytics": "Embed analytics", + "core": "Cube Core", + "cloud": { + title: "Cube Cloud and Snowflake", + display: "hidden" + }, + "databricks": { + title: "Cube Cloud and Databricks", + display: "hidden" + }, + "migrate-from-core": { + title: "Migrate from Cube Core", + display: "hidden" + } +} diff --git a/docs/content/product/getting-started/cloud/_meta.js b/docs/content/product/getting-started/cloud/_meta.js new file mode 100644 index 0000000000000..ca9068e2aef6f --- /dev/null +++ b/docs/content/product/getting-started/cloud/_meta.js @@ -0,0 +1,7 @@ +export default { + "load-data": "Load data", + "connect-to-snowflake": "Connect to Snowflake", + "create-data-model": "Create data model", + "query-from-bi": "Query from BI", + "query-from-react-app": "Query from React" +} \ No newline at end of file diff --git a/docs/content/product/getting-started/cloud/connect-to-snowflake.mdx b/docs/content/product/getting-started/cloud/connect-to-snowflake.mdx new file mode 100644 index 0000000000000..0f1d0444ef7ef --- /dev/null +++ b/docs/content/product/getting-started/cloud/connect-to-snowflake.mdx @@ -0,0 +1,74 @@ +# Connect to Snowflake + +In this section, we’ll create a Cube Cloud deployment and connect it to +Snowflake. A deployment represents a data model, configuration, and managed +infrastructure. + +To continue with this guide, you'll need to have a Cube Cloud account. If you +don't have one yet, [click here to sign up][cube-cloud-signup] for free. + +First, [sign in to your Cube Cloud account][cube-cloud-signin]. Then, +click Create Deployment: + +Give the deployment a name, select the cloud provider and region of your choice, +and click Next: + + + + + +Microsoft Azure is available on [Enterprise and above plans](https://cube.dev/pricing). +[Contact us](https://cube.dev/contact) for details. + + + +## Set up a Cube project + +Next, click Create to create a new project from scratch: + + + +## Connect to your Snowflake + +The last step is to connect Cube Cloud to Snowflake. First, select it from the +grid: + + + +Then enter your Snowflake credentials: + +- **Username:** Your Snowflake username. Please note, it is usually **not** your + email address. +- **Password:** Your Snowflake password. +- **Database:** `CUBE_DEMO`, that is the database we've created in the previous + step. +- **Account:** Your snowflake account identifier. You can find it in your + Snowflake URL as the `account_locator` part. +- **Region:** Your Snowflake account region. You can find it in your Snowflake + URL. If your URL includes a `cloud` part, use both the `cloud_region_id` and + `cloud` together e.g. `us-east-2.aws`, otherwise just use `cloud_region_id` +- **Warehouse:** `CUBE_DEMO_WH`, that is the warehouse we've created in the + previous step. +- **Role:** You can leave it blank. + +Click Apply, Cube Cloud will test the connection and proceed to the +next step. + +## Generate data model from your Snowflake schema + +Cube can now generate a basic data model from your data warehouse schema, which +helps getting started with data modeling faster. Select all four tables in our +`ECOM` schema and click through the data model generation wizard. We'll inspect +these generated files in the next section and start making changes to them. + +[cube-cloud-signin]: https://cubecloud.dev/auth +[cube-cloud-signup]: https://cubecloud.dev/auth/signup diff --git a/docs/content/product/getting-started/cloud/create-data-model.mdx b/docs/content/product/getting-started/cloud/create-data-model.mdx new file mode 100644 index 0000000000000..79793dd372823 --- /dev/null +++ b/docs/content/product/getting-started/cloud/create-data-model.mdx @@ -0,0 +1,214 @@ +# Create your first data model + +Cube follows a dataset-oriented data modeling approach, which is inspired by and +expands upon dimensional modeling. Cube incorporates this approach and provides +a practical framework for implementing dataset-oriented data modeling. + +When building a data model in Cube, you work with two dataset-centric objects: +**cubes** and **views**. **Cubes** usually represent business entities such as +customers, line items, and orders. In cubes, you define all the calculations +within the measures and dimensions of these entities. Additionally, you define +relationships between cubes, such as "an order has many line items" or "a user +may place multiple orders." + +**Views** sit on top of a data graph of cubes and create a facade of your entire +data model, with which data consumers can interact. You can think of views as +the final data products for your data consumers - BI users, data apps, AI +agents, etc. When building views, you select measures and dimensions from +different connected cubes and present them as a single dataset to BI or data +apps. + + + +## Working with cubes + +To begin building your data model, click on Enter Development Mode in +Cube Cloud. This will take you to your personal developer space, where you can +safely make changes to your data model without affecting the production +environment. + +In the previous section, we generated four cubes from the Snowflake schema. To +see the data graph of these four cubes and how they are connected to each other, +navigate to the [Visual Modeler][ref-visual-model] page. + +Let's review the `orders` cube first and update it with additional dimensions +and measures. + +Once you are in developer mode, navigate to the Data Model and click +on the `orders.yml` file in the left sidebar inside the `model/cubes` directory +to open it. + +You should see the following content of `model/cubes/orders.yml` file. + +```yaml +cubes: + - name: orders + sql_table: ECOM.ORDERS + + joins: + - name: users + sql: "{CUBE}.USER_ID = {users}.ID" + relationship: many_to_one + + dimensions: + - name: status + sql: STATUS + type: string + + - name: id + sql: ID + type: number + primary_key: true + + - name: created_at + sql: CREATED_AT + type: time + + - name: completed_at + sql: COMPLETED_AT + type: time + + measures: + - name: count + type: count +``` + +As you can see, we already have a `count` measure that we can use to calculate +the total count of our orders. + +Let's add an additional measure to the `orders` cube to calculate only +**completed orders**. The `status` dimension in the `orders` cube reflects the +three possible statuses: **processing**, **shipped**, or **completed**. We will +create a new measure `completed_count` by using a filter on that dimension. To +do this, we will use a +[filter parameter](/product/data-modeling/reference/measures#filters) of the +measure and [refer][ref-member-references] to the existing dimension. + +Add the following measure definition to your `model/cubes/orders.yml` file. It +should be included within the `measures` block. + +```yaml +- name: completed_count + type: count + filters: + - sql: "{CUBE}.status = 'completed'" +``` + +With these two measures in place, `count` and `completed_count`, we can create a +**derived measure**. Derived measures are measures that you can create based on +existing measures. Let's create the `completed_percentage` derived measure. + +Add the following measure definition to your `model/cubes/orders.yml` file +within the `measures` block. + +```yaml +- name: completed_percentage + type: number + sql: "(1.0 * {CUBE.completed_count} / NULLIF({CUBE.count}, 0))" + format: percent +``` + +Below you can see what your updated `orders` cube should look like with two new +measures. Feel free to copy this code and paste it into your +`model/cubes/order.yml` file. + +```yaml +cubes: + - name: orders + sql_table: ECOM.ORDERS + + joins: + - name: users + sql: "{CUBE}.USER_ID = {users}.ID" + relationship: many_to_one + + dimensions: + - name: status + sql: STATUS + type: string + + - name: id + sql: ID + type: number + primary_key: true + + - name: created_at + sql: CREATED_AT + type: time + + - name: completed_at + sql: COMPLETED_AT + type: time + + measures: + - name: count + type: count + + - name: completed_count + type: count + filters: + - sql: "{CUBE}.status = 'completed'" + + - name: completed_percentage + type: number + sql: "(1.0 * {CUBE.completed_count} / NULLIF({CUBE.count}, 0))" + format: percent +``` + +Click Save All in the upper corner to save changes to the data model. +Now, you can navigate to Cube’s Playground. The Playground is a web-based tool +that allows you to query your data without connecting any tools or writing any +code. It's the fastest way to explore and test your data model. + +You can select measures and dimensions from different cubes in playground, +including your newly created `completed_percentage` measure. + +## Working with views + +When building views, we recommend following entity-oriented design and +structuring your views around your business entities. Usually, cubes tend to be +normalized entities without duplicated or redundant members, while views are +denormalized entities where you pick as many measures and dimensions from +multiple cubes as needed to describe a business entity. + +Let's create our first view, which will provide all necessary measures and +dimensions to explore orders. Views are usually located in the `views` folder +and have a `_view` postfix. + +Create `model/views/orders_view.yml` with the following content: + +```yaml +views: + - name: orders_view + + cubes: + - join_path: orders + includes: + - status + - created_at + - count + - completed_count + - completed_percentage + + - join_path: orders.users + prefix: true + includes: + - city + - age + - state +``` + +When building views, you can leverage the `cubes` parameter, which enables you +to include measures and dimensions from other cubes in the view. You can build +your view by combining multiple joined cubes and specifying the path by which +they should be joined for that particular view. + +After saving, you can experiment with your newly created view in the Playground. +In the next section, we will learn how to query our `orders_view` using a BI +tool. + +[ref-member-references]: /product/data-modeling/syntax#references +[ref-visual-model]: /product/data-modeling/visual-modeler \ No newline at end of file diff --git a/docs/content/product/getting-started/cloud/index.mdx b/docs/content/product/getting-started/cloud/index.mdx new file mode 100644 index 0000000000000..d38e4ddd30bcd --- /dev/null +++ b/docs/content/product/getting-started/cloud/index.mdx @@ -0,0 +1,19 @@ +--- +asIndexPage: true +--- + +# Getting started with Cube Cloud and Snowflake + +This getting started guide will show you how to use Cube Cloud with Snowflake. +You will learn how to: + +- Load sample data into your Snowflake account +- Connect Cube Cloud to Snowflake +- Create your first Cube data model +- Connect to a BI tool to explore this model +- Create React application with Cube REST API + +## Prerequisites + +- [Cube Cloud account](https://cubecloud.dev/auth/signup) +- [Snowflake account](https://signup.snowflake.com/) diff --git a/docs/pages/product/getting-started/cloud/load-data.mdx b/docs/content/product/getting-started/cloud/load-data.mdx similarity index 100% rename from docs/pages/product/getting-started/cloud/load-data.mdx rename to docs/content/product/getting-started/cloud/load-data.mdx diff --git a/docs/pages/product/getting-started/cloud/query-from-bi.mdx b/docs/content/product/getting-started/cloud/query-from-bi.mdx similarity index 100% rename from docs/pages/product/getting-started/cloud/query-from-bi.mdx rename to docs/content/product/getting-started/cloud/query-from-bi.mdx diff --git a/docs/pages/product/getting-started/cloud/query-from-react-app.mdx b/docs/content/product/getting-started/cloud/query-from-react-app.mdx similarity index 100% rename from docs/pages/product/getting-started/cloud/query-from-react-app.mdx rename to docs/content/product/getting-started/cloud/query-from-react-app.mdx diff --git a/docs/pages/product/getting-started/connect-your-data.mdx b/docs/content/product/getting-started/connect-your-data.mdx similarity index 100% rename from docs/pages/product/getting-started/connect-your-data.mdx rename to docs/content/product/getting-started/connect-your-data.mdx diff --git a/docs/content/product/getting-started/core/_meta.js b/docs/content/product/getting-started/core/_meta.js new file mode 100644 index 0000000000000..6fb20139f2af2 --- /dev/null +++ b/docs/content/product/getting-started/core/_meta.js @@ -0,0 +1,6 @@ +export default { + "create-a-project": "Create a project", + "query-data": "Query data", + "add-a-pre-aggregation": "Add a pre-aggregation", + "learn-more": "Learn more" +} \ No newline at end of file diff --git a/docs/content/product/getting-started/core/add-a-pre-aggregation.mdx b/docs/content/product/getting-started/core/add-a-pre-aggregation.mdx new file mode 100644 index 0000000000000..6707db24be47f --- /dev/null +++ b/docs/content/product/getting-started/core/add-a-pre-aggregation.mdx @@ -0,0 +1,35 @@ +# Add a pre-aggregation + +In this step, we'll add a pre-aggregation to optimize the performance of a +specific query. Pre-aggregations are a caching technique that massively reduces +query time from seconds to milliseconds. They are extremely useful for speeding +up queries that are run frequently. + +From the Build tab, execute a query: + + + +Just above the results, click on Query was not accelerated with +pre-aggregation to bring up the pre-aggregation suggestion: + + + +A pre-aggregation will be automatically suggested for the query; +click Add to the Data Model and then retry the query in the +Playground. This time, the query should be accelerated with a pre-aggregation: + + + +And with that, we conclude our Getting Started with Cube guide. If you'd like to +learn more about Cube, [check out this page][next]. + +[next]: /product/getting-started/core/learn-more diff --git a/docs/content/product/getting-started/core/create-a-project.mdx b/docs/content/product/getting-started/core/create-a-project.mdx new file mode 100644 index 0000000000000..cfbb1ddb32931 --- /dev/null +++ b/docs/content/product/getting-started/core/create-a-project.mdx @@ -0,0 +1,110 @@ +# Create a project + +In this step, we will create a Cube Core project on your computer, connect a +data source, and generate data models. + +## Scaffold a project + +Start by opening your terminal to create a new folder for the project, then +create a `docker-compose.yml` file within it: + +```bash +mkdir my-first-cube-project +cd my-first-cube-project +touch docker-compose.yml +``` + +Open the `docker-compose.yml` file and add the following content: + +```yaml +services: + cube: + image: cubejs/cube:latest + ports: + - 4000:4000 + - 15432:15432 + environment: + - CUBEJS_DEV_MODE=true + volumes: + - .:/cube/conf +``` + +Note that we're setting the CUBEJS_DEV_MODE environment variable to `true` to +enable the [Development Mode](/product/configuration#development-mode). This is +handy for local development but not suitable for +[production](/product/deployment/production-checklist). + + + +If you're using Linux as the Docker host OS, you'll also need to add +`network_mode: 'host'` to your `docker-compose.yml`. + + + +## Start the development server + +From the newly-created project directory, run the following command to start +Cube: + +```bash +docker compose up -d +``` + + + +Using Windows? Remember to use [PowerShell][powershell-docs] or +[WSL2][wsl2-docs] to run the command below. + + + +## Connect a data source + +Head to [http://localhost:4000](http://localhost:4000) to open the [Developer +Playground][ref-devtools-playground]. + +The Playground has a database connection wizard that loads when Cube is first +started up and no `.env` file is found. After database credentials have been set +up, an `.env` file will automatically be created and populated with credentials. + + + + + +Want to use a sample database instead? Select PostgreSQL and use the +credentials below: + +
+ +| Field | Value | +| -------- | ------------------ | +| Host | `demo-db.cube.dev` | +| Port | `5432` | +| Database | `ecom` | +| Username | `cube` | +| Password | `12345` | + +
+ +After selecting the data source, enter valid credentials for it and +click Apply. Check the [Connecting to Databases][ref-conf-db] page +for more details on specific data sources. + + + +You should see tables available to you from the configured database; select the +`orders` table. After selecting the table, click Generate Data Model +and pick either YAML (recommended) or JavaScript format: + + + +Finally, click Build in the dialog, which should take you to +the Build page. + +You're now ready for the next step, [querying the +data][ref-getting-started-core-query-cube]. + +[powershell-docs]: https://learn.microsoft.com/en-us/powershell/ +[ref-conf-db]: /product/configuration/data-sources +[ref-getting-started-core-query-cube]: /product/getting-started/core/query-data +[ref-devtools-playground]: /product/workspace/playground +[wsl2-docs]: https://learn.microsoft.com/en-us/windows/wsl/install diff --git a/docs/content/product/getting-started/core/index.mdx b/docs/content/product/getting-started/core/index.mdx new file mode 100644 index 0000000000000..0cc6098b5bcdd --- /dev/null +++ b/docs/content/product/getting-started/core/index.mdx @@ -0,0 +1,21 @@ +--- +asIndexPage: true +--- + +# Getting started with Cube Core + +First, we'll create a new project, connect it to a database and generate a data +model from it. Then, we'll run queries using the Developer Playground and APIs. +Finally, we'll add a pre-aggregation to optimize query latency down to +milliseconds. + +This guide will walk you through the following tasks: + +- [Create a new project](/product/getting-started/core/create-a-project) +- [Run queries using the Developer Playground and APIs](/product/getting-started/core/query-data) +- [Add a pre-aggregation to optimize query performance](/product/getting-started/core/add-a-pre-aggregation) + +If you'd prefer to try Cube Cloud, then you can refer to [Getting Started using +Cube Cloud][ref-getting-started-cloud-overview] instead. + +[ref-getting-started-cloud-overview]: /product/getting-started/cloud diff --git a/docs/pages/product/getting-started/core/learn-more.mdx b/docs/content/product/getting-started/core/learn-more.mdx similarity index 100% rename from docs/pages/product/getting-started/core/learn-more.mdx rename to docs/content/product/getting-started/core/learn-more.mdx diff --git a/docs/pages/product/getting-started/core/query-data.mdx b/docs/content/product/getting-started/core/query-data.mdx similarity index 100% rename from docs/pages/product/getting-started/core/query-data.mdx rename to docs/content/product/getting-started/core/query-data.mdx diff --git a/docs/pages/product/getting-started/create-workbooks-and-dashboards.mdx b/docs/content/product/getting-started/create-workbooks-and-dashboards.mdx similarity index 100% rename from docs/pages/product/getting-started/create-workbooks-and-dashboards.mdx rename to docs/content/product/getting-started/create-workbooks-and-dashboards.mdx diff --git a/docs/content/product/getting-started/databricks/_meta.js b/docs/content/product/getting-started/databricks/_meta.js new file mode 100644 index 0000000000000..e1cd137e8fdf9 --- /dev/null +++ b/docs/content/product/getting-started/databricks/_meta.js @@ -0,0 +1,7 @@ +export default { + "load-data": "Load data", + "connect-to-databricks": "Connect to Databricks", + "create-data-model": "Create data model", + "query-from-bi": "Query from BI", + "query-from-react-app": "Query from React" +} diff --git a/docs/content/product/getting-started/databricks/connect-to-databricks.mdx b/docs/content/product/getting-started/databricks/connect-to-databricks.mdx new file mode 100644 index 0000000000000..653d4b565e7b0 --- /dev/null +++ b/docs/content/product/getting-started/databricks/connect-to-databricks.mdx @@ -0,0 +1,71 @@ +# Connect to Databricks + +In this section, we’ll create a Cube Cloud deployment and connect it to +Databricks. A deployment represents a data model, configuration, and managed +infrastructure. + +To continue with this guide, you'll need to have a Cube Cloud account. If you +don't have one yet, [click here to sign up][cube-cloud-signup] for free. + +First, [sign in to your Cube Cloud account][cube-cloud-signin]. Then, +click Create Deployment: + +Give the deployment a name, select the cloud provider and region of your choice, +and click Next: + + + + + +Microsoft Azure is available on [Enterprise and above plans](https://cube.dev/pricing). +[Contact us](https://cube.dev/contact) for details. + + + +## Set up a Cube project + +Next, click Create to create a new project from scratch: + + + +## Connect to your Databricks + +The last step is to connect Cube Cloud to Databricks. First, select it from the +grid: + + + +Then enter your Databricks credentials: + +- **Access Token:** A personal access token for your Databricks account. [You + can generate one][databricks-docs-pat] in your Databricks account settings. +- **Databricks JDBC URL:** The JDBC URL for your Databricks SQL warehouse. [You + can find it][databricks-docs-jdbc-url] in the SQL warehouse settings screen. +- **Databricks Catalog:** This should match the same catalog where you uploaded + the files in the last section. If left unspecified, the `default` catalog is + used. + +[databricks-docs-pat]: https://docs.databricks.com/en/dev-tools/auth/pat.html#databricks-personal-access-tokens-for-workspace-users +[databricks-docs-jdbc-url]: https://docs.databricks.com/en/integrations/jdbc/compute.html + +Click Apply, Cube Cloud will test the connection and proceed to the +next step. + +## Generate data model from your Databricks schema + +Cube can now generate a basic data model from your data warehouse, which helps +getting started with data modeling faster. Select all four tables in our catalog +and click through the data model generation wizard. We'll inspect these +generated files in the next section and start making changes to them. + +[cube-cloud-signin]: https://cubecloud.dev/auth +[cube-cloud-signup]: https://cubecloud.dev/auth/signup diff --git a/docs/content/product/getting-started/databricks/create-data-model.mdx b/docs/content/product/getting-started/databricks/create-data-model.mdx new file mode 100644 index 0000000000000..10c083a05e402 --- /dev/null +++ b/docs/content/product/getting-started/databricks/create-data-model.mdx @@ -0,0 +1,214 @@ +# Create your first data model + +Cube follows a dataset-oriented data modeling approach, which is inspired by and +expands upon dimensional modeling. Cube incorporates this approach and provides +a practical framework for implementing dataset-oriented data modeling. + +When building a data model in Cube, you work with two dataset-centric objects: +**cubes** and **views**. **Cubes** usually represent business entities such as +customers, line items, and orders. In cubes, you define all the calculations +within the measures and dimensions of these entities. Additionally, you define +relationships between cubes, such as "an order has many line items" or "a user +may place multiple orders." + +**Views** sit on top of a data graph of cubes and create a facade of your entire +data model, with which data consumers can interact. You can think of views as +the final data products for your data consumers - BI users, data apps, AI +agents, etc. When building views, you select measures and dimensions from +different connected cubes and present them as a single dataset to BI or data +apps. + + + +## Working with cubes + +To begin building your data model, click on Enter Development Mode in +Cube Cloud. This will take you to your personal developer space, where you can +safely make changes to your data model without affecting the production +environment. + +In the previous section, we generated four cubes. To see the data graph of these +four cubes and how they are connected to each other, navigate to the +[Visual Modeler][ref-visual-model] page. + +Let's review the `orders` cube first and update it with additional dimensions +and measures. + +Once you are in developer mode, navigate to the Data Model and click +on the `orders.yml` file in the left sidebar inside the `model/cubes` directory +to open it. + +You should see the following content of `model/cubes/orders.yml` file. + +```yaml +cubes: + - name: orders + sql_table: ECOM.ORDERS + + joins: + - name: users + sql: "{CUBE}.USER_ID = {users}.USER_ID" + relationship: many_to_one + + dimensions: + - name: status + sql: STATUS + type: string + + - name: id + sql: ID + type: number + primary_key: true + + - name: created_at + sql: CREATED_AT + type: time + + - name: completed_at + sql: COMPLETED_AT + type: time + + measures: + - name: count + type: count +``` + +As you can see, we already have a `count` measure that we can use to calculate +the total count of our orders. + +Let's add an additional measure to the `orders` cube to calculate only +**completed orders**. The `status` dimension in the `orders` cube reflects the +three possible statuses: **processing**, **shipped**, or **completed**. We will +create a new measure `completed_count` by using a filter on that dimension. To +do this, we will use a +[filter parameter](/product/data-modeling/reference/measures#filters) of the +measure and [refer][ref-member-references] to the existing dimension. + +Add the following measure definition to your `model/cubes/orders.yml` file. It +should be included within the `measures` block. + +```yaml +- name: completed_count + type: count + filters: + - sql: "{CUBE}.status = 'completed'" +``` + +With these two measures in place, `count` and `completed_count`, we can create a +**derived measure**. Derived measures are measures that you can create based on +existing measures. Let's create the `completed_percentage` derived measure. + +Add the following measure definition to your `model/cubes/orders.yml` file +within the `measures` block. + +```yaml +- name: completed_percentage + type: number + sql: "(1.0 * {CUBE.completed_count} / NULLIF({CUBE.count}, 0))" + format: percent +``` + +Below you can see what your updated `orders` cube should look like with two new +measures. Feel free to copy this code and paste it into your +`model/cubes/order.yml` file. + +```yaml +cubes: + - name: orders + sql_table: ECOM.ORDERS + + joins: + - name: users + sql: "{CUBE}.USER_ID = {users}.USER_ID" + relationship: many_to_one + + dimensions: + - name: status + sql: STATUS + type: string + + - name: id + sql: ID + type: number + primary_key: true + + - name: created_at + sql: CREATED_AT + type: time + + - name: completed_at + sql: COMPLETED_AT + type: time + + measures: + - name: count + type: count + + - name: completed_count + type: count + filters: + - sql: "{CUBE}.status = 'completed'" + + - name: completed_percentage + type: number + sql: "(1.0 * {CUBE.completed_count} / NULLIF({CUBE.count}, 0))" + format: percent +``` + +Click Save All in the upper corner to save changes to the data model. +Now, you can navigate to Cube’s Playground. The Playground is a web-based tool +that allows you to query your data without connecting any tools or writing any +code. It's the fastest way to explore and test your data model. + +You can select measures and dimensions from different cubes in playground, +including your newly created `completed_percentage` measure. + +## Working with views + +When building views, we recommend following entity-oriented design and +structuring your views around your business entities. Usually, cubes tend to be +normalized entities without duplicated or redundant members, while views are +denormalized entities where you pick as many measures and dimensions from +multiple cubes as needed to describe a business entity. + +Let's create our first view, which will provide all necessary measures and +dimensions to explore orders. Views are usually located in the `views` folder +and have a `_view` postfix. + +Create `model/views/orders_view.yml` with the following content: + +```yaml +views: + - name: orders_view + + cubes: + - join_path: orders + includes: + - status + - created_at + - count + - completed_count + - completed_percentage + + - join_path: orders.users + prefix: true + includes: + - city + - age + - state +``` + +When building views, you can leverage the `cubes` parameter, which enables you +to include measures and dimensions from other cubes in the view. You can build +your view by combining multiple joined cubes and specifying the path by which +they should be joined for that particular view. + +After saving, you can experiment with your newly created view in the Playground. +In the next section, we will learn how to query our `orders_view` using a BI +tool. + +[ref-member-references]: /product/data-modeling/syntax#references +[ref-visual-model]: /product/data-modeling/visual-modeler \ No newline at end of file diff --git a/docs/content/product/getting-started/databricks/index.mdx b/docs/content/product/getting-started/databricks/index.mdx new file mode 100644 index 0000000000000..d708544fda594 --- /dev/null +++ b/docs/content/product/getting-started/databricks/index.mdx @@ -0,0 +1,19 @@ +--- +asIndexPage: true +--- + +# Getting started with Cube Cloud and Databricks + +This getting started guide will show you how to use Cube Cloud with Databricks. +You will learn how to: + +- Load sample data into your Databricks account +- Connect Cube Cloud to Databricks +- Create your first Cube data model +- Connect to a BI tool to explore this model +- Create React application with Cube REST API + +## Prerequisites + +- [Cube Cloud account](https://cubecloud.dev/auth/signup) +- [Databricks account](https://www.databricks.com/try-databricks) diff --git a/docs/pages/product/getting-started/databricks/load-data.mdx b/docs/content/product/getting-started/databricks/load-data.mdx similarity index 100% rename from docs/pages/product/getting-started/databricks/load-data.mdx rename to docs/content/product/getting-started/databricks/load-data.mdx diff --git a/docs/pages/product/getting-started/databricks/query-from-bi.mdx b/docs/content/product/getting-started/databricks/query-from-bi.mdx similarity index 100% rename from docs/pages/product/getting-started/databricks/query-from-bi.mdx rename to docs/content/product/getting-started/databricks/query-from-bi.mdx diff --git a/docs/pages/product/getting-started/databricks/query-from-react-app.mdx b/docs/content/product/getting-started/databricks/query-from-react-app.mdx similarity index 100% rename from docs/pages/product/getting-started/databricks/query-from-react-app.mdx rename to docs/content/product/getting-started/databricks/query-from-react-app.mdx diff --git a/docs/pages/product/getting-started/develop-in-ide.mdx b/docs/content/product/getting-started/develop-in-ide.mdx similarity index 100% rename from docs/pages/product/getting-started/develop-in-ide.mdx rename to docs/content/product/getting-started/develop-in-ide.mdx diff --git a/docs/content/product/getting-started/embed-analytics.mdx b/docs/content/product/getting-started/embed-analytics.mdx new file mode 100644 index 0000000000000..d34f56ff65233 --- /dev/null +++ b/docs/content/product/getting-started/embed-analytics.mdx @@ -0,0 +1,22 @@ +# Embed analytics + +Cube offers rich options for embedded analytics. You can embed [dashboards][ref-dashboards] and [analytics chat][ref-analytics-chat] as iframes, use the [Analytics Chat API][ref-chat-api] directly to create your own conversational analytics experience, or use [Core Data APIs][ref-core-apis] directly to build custom visualizations, reporting, and dashboarding experiences. + +## Embed with iframes + +The simplest way to embed Cube content is using iframes. You can embed both dashboards and analytics chat directly into your applications. Cube supports two authentication methods for iframe embedding: [private embedding][ref-private-embedding] for internal use cases and [signed embedding][ref-signed-embedding] for customer-facing applications. + +## Use the Chat API + +For more control over the conversational analytics experience, you can use the [Analytics Chat API][ref-chat-api] directly. This API-first approach lets you programmatically integrate AI-powered conversations with your data into your applications, giving you full control over the user experience. + +## Build custom experiences + +If you want complete control over visualizations and user interfaces, you can use [Cube's core APIs][ref-core-apis]—including REST, GraphQL, and SQL APIs—directly. This headless approach enables you to build fully custom visualization, reporting, and dashboarding experiences tailored to your specific needs. + +[ref-dashboards]: /product/presentation/dashboards +[ref-analytics-chat]: /product/exploration/analytics-chat +[ref-chat-api]: /product/apis-integrations/embed-apis/chat-api +[ref-core-apis]: /product/apis-integrations/core-data-apis +[ref-private-embedding]: /product/embedding/private-embedding +[ref-signed-embedding]: /product/embedding/signed-embedding diff --git a/docs/content/product/getting-started/index.mdx b/docs/content/product/getting-started/index.mdx new file mode 100644 index 0000000000000..d890332d10eb9 --- /dev/null +++ b/docs/content/product/getting-started/index.mdx @@ -0,0 +1,44 @@ +--- +asIndexPage: true +--- + +# Getting started with Cube + +It's easy to get started with Cube—just click the button below and create your free account. Once your account is created, you can connect your data source or use our demo deployment. AI will build your initial semantic model, and you'll be able to use Cube features such as analytics chat, workbooks, dashboards, and Agentic IDE. + + + + + +## Getting started with Cube Core + +Cube Core is a headless, open-source semantic layer that powers the Cube Business Intelligence Platform. While Cube Core lacks frontend and AI features, you can use it to power your own embedded analytics or build your own AI agent or BI tool. + +Cube Core is packaged and distributed as Docker images that can be run in a containerized environment. You can run Cube Core on your own infrastructure with Docker. + + + + + +## Migrating from Cube Core to Cube + +Cube Cloud supports several ways to import existing Cube projects: + +- [Import a GitHub repository](/product/getting-started/migrate-from-core/import-github-repository) +- [Import a GitLab repository](/product/getting-started/migrate-from-core/import-gitlab-repository-via-ssh) +- [Import a Bitbucket repository](/product/getting-started/migrate-from-core/import-bitbucket-repository-via-ssh) +- [Import a Git repository](/product/getting-started/migrate-from-core/import-git-repository-via-ssh) +- [Import a local project with CLI](/product/getting-started/migrate-from-core/upload-with-cli) + +[cube-cloud]: https://cube.dev/cloud/ +[ref-infrastructure]: /product/deployment/cloud +[ref-workspace]: /product/workspace +[ref-data-sources]: /product/configuration/data-sources diff --git a/docs/content/product/getting-started/migrate-from-core/_meta.js b/docs/content/product/getting-started/migrate-from-core/_meta.js new file mode 100644 index 0000000000000..2551962fbe3c5 --- /dev/null +++ b/docs/content/product/getting-started/migrate-from-core/_meta.js @@ -0,0 +1,7 @@ +export default { + "upload-with-cli": "Upload with CLI", + "import-gitlab-repository-via-ssh": "Import a GitLab repository", + "import-github-repository": "Import a GitHub repository", + "import-git-repository-via-ssh": "Import a Git repository", + "import-bitbucket-repository-via-ssh": "Import a Bitbucket repository" +} \ No newline at end of file diff --git a/docs/content/product/getting-started/migrate-from-core/import-bitbucket-repository-via-ssh.mdx b/docs/content/product/getting-started/migrate-from-core/import-bitbucket-repository-via-ssh.mdx new file mode 100644 index 0000000000000..e0629062843b7 --- /dev/null +++ b/docs/content/product/getting-started/migrate-from-core/import-bitbucket-repository-via-ssh.mdx @@ -0,0 +1,206 @@ +# Import a Bitbucket repository + +This guide walks you through setting up Cube Cloud, importing a +[Bitbucket][bitbucket] repository with an existing Cube project via SSH, and +connecting to your database. + +## Step 1: Create an account + +Navigate to [cubecloud.dev](https://cubecloud.dev/), and create a new Cube Cloud +account. + +## Step 2: Create a new Deployment + +Click Create Deployment. This is the first step in the deployment +creation. Give it a name and select the cloud provider and region of your +choice. + +
+ Cube Cloud Create Deployment Screen +
+ + + +Microsoft Azure is available on [Enterprise and above plans](https://cube.dev/pricing). +[Contact us](https://cube.dev/contact) for details. + + + +## Step 3: Import Git repository + +Next up, the second step in creating a Cube App from scratch in Cube Cloud is to +click Import Git repository via SSH. + +
+ Cube Cloud Upload Project Screen +
+ +Now go to your Bitbucket repository and on the Clone dialog, switch +to SSH and copy the URL: + +
+ Getting the repository's SSH URL from Bitbucket +
+ +Back in Cube Cloud, paste the URL and click Generate SSH key: + +
+ Getting SSH key from Cube Cloud +
+ +Now copy the SSH key and go back to Bitbucket and into the repository's +settings. Click Access keys from the navigation, then click  Add +key button. Give the key a label (`Cube Cloud`, for example) and paste the +SSH key in the relevant field: + +
+ Add Cube Cloud deploy key to Bitbucket +
+ +Click Add SSH key to save, then go back to Cube Cloud and +click Connect. After a connection is successfully established, you +should see the next screen: + +
+ Getting webhook URL from Cube Cloud +
+ +Copy the Cube Cloud Git Webhook URL, go to your Bitbucket +repository's settings, and click Webhooks from the navigation. +Click Add webhook, then add a title (`Cube Cloud`, for example). +Paste the URL into the correct field, ensure the Repository > Push +trigger is checked and click Save. + +
+ Add Cube Cloud webhook to Bitbucket +
+ +Back in Cube Cloud, click Connect to test the webhook. + +## Step 4: Connect your Database + +Enter your credentials to connect to your database. Check the [connecting to +databases][link-connecting-to-databases] guide for more details. + + + +Want to use a sample database instead? We also have a sample database where you +can try out Cube Cloud: + +
+ +| Field | Value | +| -------- | ------------------ | +| Host | `demo-db.cube.dev` | +| Port | `5432` | +| Database | `ecom` | +| Username | `cube` | +| Password | `12345` | + +
+ +
+ Cube Cloud Setup Database Screen +
+ +In the UI it'll look exactly like the image below. + +
+ Cube Cloud Setup Database Screen +
+ +If you run into issues here, make sure to allow the Cube Cloud IPs to access +your database. This means you need to enable these IPs in your firewall. If you +are using AWS, this would mean adding a security group with allowed IPs. + +## Step 5: Generate the Data Model + +Step five in this case consists of generating data models. Start by selecting +the database tables to generate the data models from, then +hit Generate. + +
+ Cube Cloud Setup Database Screen +
+ +Cube Cloud will generate the data models and spin up your Cube deployment. With +this, you're done. You've created a Cube deployment, configured a database +connection, and generated data models! + +
+ Cube Cloud Setup Database Screen +
+ +You're ready for the last step, running queries in the Playground. + +## Step 6: Try out Cube Cloud + +Now you can navigate to Playground to try out your queries or connect your +application to the Cube Cloud API. + +
+ Cube Cloud Playground +
+ +[bitbucket]: https://bitbucket.org/ +[link-connecting-to-databases]: /product/configuration/data-sources diff --git a/docs/content/product/getting-started/migrate-from-core/import-git-repository-via-ssh.mdx b/docs/content/product/getting-started/migrate-from-core/import-git-repository-via-ssh.mdx new file mode 100644 index 0000000000000..b1dc1898e18b5 --- /dev/null +++ b/docs/content/product/getting-started/migrate-from-core/import-git-repository-via-ssh.mdx @@ -0,0 +1,167 @@ +# Import a Git repository + +This guide walks you through setting up Cube Cloud, importing a generic Git +repository with an existing Cube project via SSH, and connecting to your +database. + +## Step 1: Create an account + +Navigate to [cubecloud.dev](https://cubecloud.dev/), and create a new Cube Cloud +account. + +## Step 2: Create a new Deployment + +Click Create Deployment button. This is the first step in the +deployment creation. Give it a name and select the cloud provider and region of +your choice. + +
+ Cube Cloud Create Deployment Screen +
+ + + +Microsoft Azure is available on [Enterprise and above plans](https://cube.dev/pricing). +[Contact us](https://cube.dev/contact) for details. + + + +## Step 3: Import Git repository + +Next up, the second step in creating a Cube App from scratch in Cube Cloud is to +click Import Git repository via SSH button. + +
+ Cube Cloud Upload Project Screen +
+ +Enter the SSH URL of your Git repository, and click Generate SSH key: + +
+ Getting SSH key from Cube Cloud +
+ +Copy the SSH key and add it to your hosted Git repository. Back in Cube Cloud, +click Connect. After a connection is successfully established, you +should see the next screen: + +
+ Getting webhook URL from Cube Cloud +
+ +Copy the Cube Cloud Git Webhook URL and add it your hosted Git +repository's webhooks. Ensure that the Git repository can push events which +should trigger a build on Cube Cloud. Back in Cube Cloud, +click Connect to test the webhook. + +## Step 4: Connect your Database + +Enter your credentials to connect to your database. Check the [connecting to +databases][link-connecting-to-databases] guide for more details. + + + +Want to use a sample database instead? We also have a sample database where you +can try out Cube Cloud: + +
+ +| Field | Value | +| -------- | ------------------ | +| Host | `demo-db.cube.dev` | +| Port | `5432` | +| Database | `ecom` | +| Username | `cube` | +| Password | `12345` | + +
+ +
+ Cube Cloud Setup Database Screen +
+ +In the UI it'll look exactly like the image below. + +
+ Cube Cloud Setup Database Screen +
+ +If you run into issues here, make sure to allow the Cube Cloud IPs to access +your database. This means you need to enable these IPs in your firewall. If you +are using AWS, this would mean adding a security group with allowed IPs. + +## Step 5: Generate the Data Model + +Step five in this case consists of generating data models. Start by selecting +the database tables to generate the data models from, then +hit Generate. + +
+ Cube Cloud Setup Database Screen +
+ +Cube Cloud will generate the data models and spin up your Cube deployment. With +this, you're done. You've created a Cube deployment, configured a database +connection, and generated data models! + +
+ Cube Cloud Setup Database Screen +
+ +You're ready for the last step, running queries in the Playground. + +## Step 6: Try out Cube Cloud + +Now you can navigate to Playground to try out your queries or connect your +application to the Cube Cloud API. + +
+ Cube Cloud Playground +
+ +[link-connecting-to-databases]: /product/configuration/data-sources diff --git a/docs/content/product/getting-started/migrate-from-core/import-github-repository.mdx b/docs/content/product/getting-started/migrate-from-core/import-github-repository.mdx new file mode 100644 index 0000000000000..e0cef9728cc26 --- /dev/null +++ b/docs/content/product/getting-started/migrate-from-core/import-github-repository.mdx @@ -0,0 +1,145 @@ +# Import a GitHub repository + +This guide walks you through setting up Cube Cloud, importing a [GitHub][github] +repository with an existing Cube project, and connecting to your database. + +## Step 1: Create an account + +Navigate to [cubecloud.dev](https://cubecloud.dev/), and create a new Cube Cloud +account. + +## Step 2: Create a new Deployment + +Click Create Deployment. This is the first step in the deployment +creation. Give it a name and select the cloud provider and region of your +choice. + +
+ Cube Cloud Create Deployment Screen +
+ + + +Microsoft Azure is available on [Enterprise and above plans](https://cube.dev/pricing). +[Contact us](https://cube.dev/contact) for details. + + + +## Step 3: Import repository from GitHub + +Next up, click Import from a GitHub repository. This will pop open a +GitHub app authorization dialog where you must first install the Cube Cloud +GitHub app to the desired organization. After authorizing Cube Cloud to access +your GitHub repository, you should see the following screen in Cube Cloud: + +
+ Cube Cloud Import from GitHub screen +
+ +Select your repository and the desired branch to use as the default. If the +repository is a monorepo, you should also provide the path to the Cube project +within it. Deployments connected to a Git monorepo will trigger a rebuild +**only** when committed files begin with the provided path. + +## Step 4: Connect your Database + +Enter your credentials to connect to your database. Check the [connecting to +databases][link-connecting-to-databases] guide for more details. + + + +Want to use a sample database instead? We also have a sample database where you +can try out Cube Cloud: + +
+ +| Field | Value | +| -------- | ------------------ | +| Host | `demo-db.cube.dev` | +| Port | `5432` | +| Database | `ecom` | +| Username | `cube` | +| Password | `12345` | + +
+ +
+ Cube Cloud Setup Database Screen +
+ +In the UI it'll look exactly like the image below. + +
+ Cube Cloud Setup Database Screen +
+ +If you run into issues here, make sure to allow the Cube Cloud IPs to access +your database. This means you need to enable these IPs in your firewall. If you +are using AWS, this would mean adding a security group with allowed IPs. + +## Step 5: Generate the Data Model + +Step four in this case consists of generating data models. Start by selecting +the database tables to generate the data models from, then +hit Generate. + +
+ Cube Cloud Setup Database Screen +
+ +Cube Cloud will generate the data models and spin up your Cube deployment. With +this, you're done. You've created a Cube deployment, configured a database +connection, and generated data models! + +
+ Cube Cloud Setup Database Screen +
+ +You're ready for the last step, running queries in the Playground. + +## Step 6: Try out Cube Cloud + +Now you can navigate to Playground to try out your queries or connect your +application to Cube Cloud API. + +
+ Cube Cloud Playground +
+ +[github]: https://github.com +[link-connecting-to-databases]: /product/configuration/data-sources diff --git a/docs/content/product/getting-started/migrate-from-core/import-gitlab-repository-via-ssh.mdx b/docs/content/product/getting-started/migrate-from-core/import-gitlab-repository-via-ssh.mdx new file mode 100644 index 0000000000000..dc3a6de3388e2 --- /dev/null +++ b/docs/content/product/getting-started/migrate-from-core/import-gitlab-repository-via-ssh.mdx @@ -0,0 +1,205 @@ +# Import a GitLab repository + +This guide walks you through setting up Cube Cloud, importing a [GitLab][gitlab] +repository with an existing Cube project via SSH, and connecting to your +database. + +## Step 1: Create an account + +Navigate to [cubecloud.dev](https://cubecloud.dev/), and create a new Cube Cloud +account. + +## Step 2: Create a new Deployment + +Click Create Deployment. This is the first step in the deployment +creation. Give it a name and select the cloud provider and region of your +choice. + +
+ Cube Cloud Create Deployment Screen +
+ + + +Microsoft Azure is available on [Enterprise and above plans](https://cube.dev/pricing). +[Contact us](https://cube.dev/contact) for details. + + + +## Step 3: Import Git repository + +Next up, the second step in creating a Cube App from scratch in Cube Cloud is to +click Import Git repository via SSH. + +
+ Cube Cloud Upload Project Screen +
+ +Now go to your GitLab repository and from the Clone dropdown menu, +copy the Clone with SSH URL: + +
+ Getting the repository's SSH URL from GitLab +
+ +Back in Cube Cloud, paste the URL and click Generate SSH key: + +
+ Getting SSH key from Cube Cloud +
+ +Now copy the SSH key and go back to GitLab and paste it into the repository's +settings. Find the Deploy keys section and click Expand. +Give the key a title (`Cube Cloud`, for example) and paste the SSH key in the +relevant field: + +
+ Add Cube Cloud deploy key to GitLab +
+ +Ensure Grant write permissions to this key is checked, then +click Add key. Go back to Cube Cloud and click Connect. +After a connection is successfully established, you should see the next screen: + +
+ Getting webhook URL from Cube Cloud +
+ +Copy the Cube Cloud Git Webhook URL and go to your GitLab +project's Webhooks settings. Paste the URL into the correct field, +ensure the Push events trigger is checked and click Add +webhook. + +
+ Add Cube Cloud webhook to GitLab +
+ +Back in Cube Cloud, click Connect to test the webhook. + +## Step 4: Connect your Database + +Enter your credentials to connect to your database. Check the [connecting to +databases][link-connecting-to-databases] guide for more details. + + + +Want to use a sample database instead? We also have a sample database where you +can try out Cube Cloud: + +
+ +| Field | Value | +| -------- | ------------------ | +| Host | `demo-db.cube.dev` | +| Port | `5432` | +| Database | `ecom` | +| Username | `cube` | +| Password | `12345` | + +
+ +
+ Cube Cloud Setup Database Screen +
+ +In the UI it'll look exactly like the image below. + +
+ Cube Cloud Setup Database Screen +
+ +If you run into issues here, make sure to allow the Cube Cloud IPs to access +your database. This means you need to enable these IPs in your firewall. If you +are using AWS, this would mean adding a security group with allowed IPs. + +## Step 5: Generate the Data Model + +Step five in this case consists of generating data models. Start by selecting +the database tables to generate the data models from, then +hit Generate. + +
+ Generating data models for a new Cube Cloud deployment +
+ +Cube Cloud will generate the data models and spin up your Cube deployment. With +this, you're done. You've created a Cube deployment, configured a database +connection, and generated data models! + +
+ Cube Cloud Playground +
+ +You're ready for the last step, running queries in the Playground. + +## Step 6: Try out Cube Cloud + +Now you can navigate to Playground to try out your queries or connect your +application to the Cube Cloud API. + +
+ Cube Cloud Playground +
+ +[gitlab]: https://gitlab.com/ +[link-connecting-to-databases]: /product/configuration/data-sources diff --git a/docs/content/product/getting-started/migrate-from-core/index.mdx b/docs/content/product/getting-started/migrate-from-core/index.mdx new file mode 100644 index 0000000000000..bf04beb01bc4c --- /dev/null +++ b/docs/content/product/getting-started/migrate-from-core/index.mdx @@ -0,0 +1,4 @@ +--- +asIndexPage: true +--- + diff --git a/docs/content/product/getting-started/migrate-from-core/upload-with-cli.mdx b/docs/content/product/getting-started/migrate-from-core/upload-with-cli.mdx new file mode 100644 index 0000000000000..d99d2431cdbd2 --- /dev/null +++ b/docs/content/product/getting-started/migrate-from-core/upload-with-cli.mdx @@ -0,0 +1,95 @@ +# Import a local project to Cube Cloud with CLI + +This guide walks you through setting up Cube Cloud, importing an existing Cube +project from a local machine via SSH, and connecting to your database. + + + +## Step 1: Create Deployment + +Click Create Deployment. Then give it a name and select the cloud +provider and region of your choice. + +
+ Cube Cloud Create Deployment Screen +
+ + + +Microsoft Azure is available on [Enterprise and above plans](https://cube.dev/pricing). +[Contact us](https://cube.dev/contact) for details. + + + +## Step 2: Upload your Cube project + +The next step is to upload your existing Cube project to the Cube Cloud. + +You can do it by running the following command from terminal in your Cube +project directory. + +```bash +npx cubejs-cli deploy --token +``` + +
+ Cube Cloud Upload Project Screen +
+ +## Step 3: Connect your Database + +Enter your credentials to connect to your database. Check the [connecting to +databases][ref-cloud-connecting-to-databases] guide for more details. + + + +Want to use a sample database instead? We also have a sample database where you +can try out Cube Cloud: + +
+ +| Field | Value | +| -------- | ------------------ | +| Host | `demo-db.cube.dev` | +| Port | `5432` | +| Database | `ecom` | +| Username | `cube` | +| Password | `12345` | + +
+ +
+ Cube Cloud Setup Database Screen +
+ +## Step 4: Try out Cube Cloud + +Now you can navigate to [the Playground][ref-cloud-playground] to try out your +queries or connect your application to Cube Cloud API. + +
+ Cube Cloud Playground +
+ +[ref-cloud-connecting-to-databases]: /product/configuration/data-sources +[ref-cloud-playground]: /cloud/dev-tools/dev-playground diff --git a/docs/pages/product/getting-started/use-analytics-chat.mdx b/docs/content/product/getting-started/use-analytics-chat.mdx similarity index 100% rename from docs/pages/product/getting-started/use-analytics-chat.mdx rename to docs/content/product/getting-started/use-analytics-chat.mdx diff --git a/docs/content/product/introduction.mdx b/docs/content/product/introduction.mdx new file mode 100644 index 0000000000000..c42fdfbaa5f67 --- /dev/null +++ b/docs/content/product/introduction.mdx @@ -0,0 +1,101 @@ +--- +toc: false +--- + +# Introduction + +Cube is the business intelligence platform powered by the open-source semantic layer. + +Cube uses AI agents to build data models and enable data consumers to perform analysis. Use AI to quickly build semantic layer and fully control the analytics context. + + + +Cube is a new generation of a business intelligence and embedded analytics platform built to be used by both humans and AI agents. It empowers different personas across your organization: + +- **Data Engineers** can quickly curate data models with AI assistance, accelerating the development and maintenance of semantic layers +- **Data Analysts** can perform deep analysis with AI assistance, diving into complex data relationships and patterns +- **Business Users** benefit from workbooks and dashboards that Cube can automatically build and maintain + +## How is Cube different? + +At the foundation of Cube's agentic analytics platform is an [open-source semantic layer](https://github.com/cube-js/cube)—the critical infrastructure that enables both AI agents and humans to work with trusted, consistent data. + +The semantic layer provides the governed data foundation that makes agentic analytics possible. It organizes data from your cloud data warehouses into centralized, consistent definitions that AI agents can reliably query, explore, and reason about. Without a semantic layer, AI agents would struggle with inconsistent metrics, scattered business logic, and ungoverned data access—making their outputs unreliable and potentially dangerous. + +### Semantic SQL + +Unlike other tools, Cube AI agents don't query the data warehouse directly. Instead, they query the semantic layer using Semantic SQL, creating a trusted proxy architecture. The semantic layer runtime acts as guardrails between AI agents and your warehouse—all queries must pass through this deterministic runtime, which validates every request and prevents incorrect queries from reaching your data. + +Semantic SQL extends Postgres-compatible SQL with the MEASURE function. This architecture lets AI leverage the full power of SQL to build ad-hoc derived calculations on top of existing semantic model calculations, combining flexibility with governance. + +Security policies are enforced deterministically at the semantic layer runtime, ensuring consistent access control across all queries. + + + +### Semantic layer architecture + +#### Code-first + +A code-first approach is essential for both traditional data engineering and agentic analytics. Managing data models, configurations, and policies as code enables the same proven practices that power modern software development: version control for collaboration and code reviews, automated testing and documentation, and established patterns for reusability and maintainability. + +For agentic analytics specifically, a code-first semantic layer creates new possibilities. AI agents can help curate and maintain data models themselves, accelerating development while maintaining quality through git workflows. The structured, version-controlled nature of code makes it easier for agents to understand changes, suggest improvements, and even implement modifications autonomously. + +Everything within Cube—from configurations to data models to access control policies—is managed through code. This foundation enables both human data engineers and AI agents to collaborate on building and maintaining the semantic layer that powers agentic analytics. + +The semantic layer that powers Cube's agentic analytics platform is built on four essential pillars: data modeling, access control, caching, and APIs. Each pillar plays a critical role in enabling AI agents and users to work with data reliably, securely, and efficiently. + +#### Data Modeling + +**The data model provides the knowledge graph that AI agents use to understand your business.** It centralizes metric definitions, entity relationships, and business logic upstream from all consumption tools—whether those are AI agents, BI tools, or custom applications. This centralization is critical for agentic analytics: AI agents need a structured understanding of what metrics mean, how entities relate, and what calculations are valid. + +When an AI agent analyzes sales performance or answers questions about customer behavior, it relies on the semantic layer's data model to understand that "revenue" is calculated consistently, that customers have orders, and that orders contain line items. This structured knowledge enables agents to generate reliable insights and navigate complex data relationships autonomously. + +**Cube's data model is code-first.** Data teams define data models with YAML or JavaScript code, managed through version control systems. This enables AI-assisted development where agents can help curate and maintain the semantic layer itself, accelerating model development while maintaining quality through git workflows and multiple isolated environments. + +**Cube's data model is dataset-centric**, inspired by and expanding upon dimensional modeling. You work with two types of objects: + +**Cubes** represent business entities such as customers, line items, and orders. They define all calculations within measures and dimensions, as well as relationships between entities. These relationships form the knowledge graph that AI agents traverse when exploring data and generating insights. + +**Views** sit on top of the data graph of cubes, creating facades that data consumers interact with. Think of views as the final data products for AI agents, BI users, and applications. Views select measures and dimensions from connected cubes and present them as unified datasets, providing AI agents with the right context and scope for specific analytical tasks. + +#### Access Control + +**Access control ensures that AI agents respect the same data security policies as human users.** This is critical for agentic analytics: when AI agents autonomously query and analyze data, they must enforce the same governance rules that apply to human users—whether that's row-level security, column-level restrictions, or data masking. + +By centralizing access control in the semantic layer, you ensure that all data consumption—whether by AI agents, BI tools, or custom applications—goes through a single governed checkpoint. This provides comprehensive oversight and prevents agents from inadvertently exposing sensitive data or violating security policies. + +Cube's code-first approach enables data teams to **define access control policies with Python or JavaScript**, ranging from simple row-level access rules to completely custom data models per tenant backed by different data sources. These policies apply uniformly to all consumers of the semantic layer, ensuring AI agents operate within the same security boundaries as human users. + +#### Caching + +**Caching enables AI agents to deliver fast, interactive experiences without overwhelming your data infrastructure.** For agentic analytics to be effective, AI agents must respond quickly to user questions, iteratively explore data, and generate insights in real-time. Without caching, every agent query would hit your data warehouse directly, creating latency issues and potentially significant costs. + +The semantic layer acts as a performance buffer between AI agents and your data sources. Through intelligent caching, it ensures agents can work interactively while protecting your cloud data warehouse from unnecessary and redundant load. + +Cube implements caching through an **aggregate awareness framework called pre-aggregations.** Data teams define pre-aggregates in the data model as rollup tables, including measures and dimensions. Cube builds and refreshes these pre-aggregates in the background by querying your cloud data warehouse and storing results in Cube Store, Cube's purpose-built caching engine backed by distributed file storage such as S3. Pre-aggregations can be refreshed on schedule or as part of workflow orchestration. + +When an AI agent sends a query to Cube, the aggregate awareness engine determines if an existing and fresh pre-aggregate can serve that query. This significantly accelerates agent responses and reduces both latency and data warehouse costs—essential for enabling the iterative, exploratory workflows that characterize agentic analytics. + +#### APIs + +**APIs enable AI agents, applications, and tools to interact with the semantic layer through standard protocols.** For agentic analytics to work across diverse use cases—from AI-powered workbooks to embedded analytics to traditional BI—the semantic layer must provide universal interoperability. AI agents need to query data, introspect the data model, and integrate with other systems without requiring custom integrations for every tool or framework. + +Rather than inventing proprietary protocols, Cube implements widely adopted standards: **REST, GraphQL, and SQL.** + +**REST and GraphQL** provide modern API interfaces for building custom applications and enabling programmatic access. These APIs power agentic workflows, allowing AI agents to query data, retrieve results, and build interactive experiences. + +**SQL** is universally adopted across the data stack. Every BI tool, visualization platform, and data application can query a SQL data source. Cube implements Postgres-compatible SQL and extends it to support semantic layer concepts like measures—special types that know how to evaluate themselves based on data model definitions. Any tool that can connect to Postgres or Redshift can connect to Cube, making the semantic layer accessible to both AI agents and traditional analytics tools. + +**Data model introspection through the meta API** is essential for agentic analytics. It enables AI agents to discover available metrics, understand entity relationships, and determine valid queries—providing the context agents need to navigate the semantic layer autonomously. This same introspection capability allows BI tools to automatically map to data model objects and helps applications build dynamic interfaces. + + +[ref-workbooks]: /product/workspace/workbooks +[ref-embedding]: /product/apis-integrations/embedding +[ref-chat-api]: /product/apis-integrations/chat-api +[ref-mcp-server]: /product/apis-integrations/mcp-server +[ref-spaces-agents-models]: /product/agentic-analytics/spaces-agents-models +[ref-agent-rules]: /product/agentic-analytics/agent-rules +[ref-agent-memories]: /product/agentic-analytics/memory-isolation \ No newline at end of file diff --git a/docs/content/product/presentation/_meta.js b/docs/content/product/presentation/_meta.js new file mode 100644 index 0000000000000..43d2adf1a53f8 --- /dev/null +++ b/docs/content/product/presentation/_meta.js @@ -0,0 +1,5 @@ +export default { + "dashboards": "Dashboards", + "scheduled-refreshes": "Scheduled Refreshes", + "notifications": "Notifications" +} diff --git a/docs/content/product/presentation/dashboards.mdx b/docs/content/product/presentation/dashboards.mdx new file mode 100644 index 0000000000000..7b9a83059d664 --- /dev/null +++ b/docs/content/product/presentation/dashboards.mdx @@ -0,0 +1,18 @@ +# Dashboards + +Dashboards let you select and organize reports from your workbooks into polished, shareable views for your team and stakeholders. Transform your exploratory analysis into production-ready deliverables by choosing which insights to highlight and present. + +## Use cases + +Dashboards enable you to: + +- **Monitor key metrics** – Display critical business indicators that refresh with live data +- **Distribute analysis** – Package your findings into reports for regular distribution +- **Build data tools** – Develop specialized applications powered by your semantic layer +- **Present insights** – Showcase important discoveries in a polished, accessible format + +## How it works + +Select the reports you want to include from your [workbook][ref-workbooks], arrange them to tell your data story, and publish the dashboard. This gives stakeholders direct access to the insights that matter most, without the complexity of the underlying analysis. + +[ref-workbooks]: /product/exploration/workbooks diff --git a/docs/content/product/presentation/notifications.mdx b/docs/content/product/presentation/notifications.mdx new file mode 100644 index 0000000000000..b57ab0ed101d1 --- /dev/null +++ b/docs/content/product/presentation/notifications.mdx @@ -0,0 +1,69 @@ +# Notifications + + + +Notifications are available on [Premium and Enterprise plans](https://cube.dev/pricing). +
Users need at least the [Explorer][ref-roles] role and Edit or Manage permission +on the workbook to set up notifications. + +
+ +Notifications let you send email or Slack messages with a screenshot of a +dashboard after each [scheduled refresh][ref-scheduled-refreshes]. This is useful +for distributing regular updates to stakeholders without requiring them to log in. + +## Creating a notification + +Notifications are configured as part of a [scheduled refresh][ref-scheduled-refreshes]. +When creating or editing a schedule, click Add notification to expand +the notification configuration card. + +### Delivery channel + +Toggle between two delivery channels: + +- **Email** — select multiple recipients from workspace users using a searchable + picker with checkboxes. +- **Slack** — select a Slack channel to post to. Requires connecting your Slack + workspace first (one-time OAuth flow via Connect to Slack). Once + connected, select a channel from a searchable picker. + +### Screenshot attachment + +Choose the format for the dashboard screenshot attached to the notification: + +- **PNG** (default) +- **PDF** + +Select the format using the Attach screenshot as option. + +### Removing a notification + +To remove a notification from a scheduled refresh, click the X button in the +notification card header before saving. + +## Email notifications + +Email notifications are sent to selected workspace users after a scheduled +refresh completes. Each recipient receives a message with a link to the +dashboard and the attached screenshot. + +## Slack notifications + +Slack notifications post a message with the dashboard screenshot to a single +Slack channel per schedule. + +### Connecting Slack + +Before you can send Slack notifications, connect your Slack workspace: + +1. When configuring a notification, select Slack as the delivery + channel. +2. Click Connect to Slack to start the OAuth flow. +3. Authorize Cube to post to your Slack workspace. + +This is a one-time setup. Once connected, you can select any channel your Slack +workspace has access to. + +[ref-roles]: /product/administration/users-and-permissions/roles-and-permissions +[ref-scheduled-refreshes]: /product/presentation/scheduled-refreshes diff --git a/docs/content/product/presentation/scheduled-refreshes.mdx b/docs/content/product/presentation/scheduled-refreshes.mdx new file mode 100644 index 0000000000000..72eb63afef441 --- /dev/null +++ b/docs/content/product/presentation/scheduled-refreshes.mdx @@ -0,0 +1,95 @@ +# Scheduled Refreshes + + + +Scheduled refreshes are available on [Premium and Enterprise plans](https://cube.dev/pricing). +
Users need at least the [Explorer][ref-roles] role and Edit or Manage permission +on the workbook to set up scheduled refreshes. + +
+ +Scheduled refreshes allow you to automatically refresh published dashboards on a +recurring schedule. When a scheduled refresh runs, the dashboard widgets are +queried in the background, refreshing Cube's in-memory cache. This warms up +dashboards so they load instantly when users open them, eliminating wait times. + +You can also attach [notifications][ref-notifications] to scheduled refreshes to +send email or Slack messages with a dashboard screenshot after each refresh. + +## Accessing scheduled refreshes + +From the Dashboard Builder, click the calendar icon in the toolbar to open the +scheduled refreshes sidebar. From this sidebar, you can create new schedules, +modify existing ones, or remove schedules you no longer need. + + + +The dashboard must be published before schedules can be created. + + + +## Creating a schedule + +Click New scheduled refresh in the sidebar footer. A dialog opens +with the following configuration options. + +### Frequency + +| Option | Description | +| --- | --- | +| Hourly | Runs every hour at the specified minute | +| Daily | Runs once a day at the specified time | +| Weekly | Runs on a chosen day of the week at the specified time | +| Monthly | Runs on a chosen day of the month at the specified time | +| Custom | Accepts a cron expression (5-part: minute hour day month weekday) | + +Time is specified in 12-hour format with an AM/PM selector. For Hourly +schedules, only the minute field is shown. + +### Timezone + +Select from common timezones including UTC, US timezones, London, Paris, Berlin, +Tokyo, Shanghai, Singapore, and Sydney. Defaults to your browser's timezone if +it matches a common one, otherwise UTC. + +### Notifications + +You can optionally attach [notifications][ref-notifications] to a scheduled +refresh. Click Add notification to expand the notification +configuration. See the [Notifications][ref-notifications] page for details. + +Click Save to create or update the schedule. + +## Managing schedules + +The sidebar lists all existing schedules with the following information: + +- **Status indicator** — current state: not run yet, last run succeeded, last + run failed, or currently running with phase details. +- **Schedule description** — human-readable text like "At 09:00 AM". +- **Enable/disable toggle** — turn schedules on or off without deleting them. +- **Next run time** — shows the next scheduled execution, or "Disabled" if the + schedule is off. + +### Actions + +| Action | Description | +| --- | --- | +| Run now | Manually trigger the schedule immediately | +| Edit | Open the form dialog to modify the schedule | +| Delete | Remove the schedule permanently | + +## Run phases + +When a scheduled refresh runs, it progresses through these phases: + +1. Initializing +2. Fetching credentials +3. Refreshing dashboard +4. Generating screenshot (if notifications are configured) +5. Sending notifications (if notifications are configured) + +The sidebar shows real-time status updates during execution. + +[ref-roles]: /product/administration/users-and-permissions/roles-and-permissions +[ref-notifications]: /product/presentation/notifications diff --git a/docs/mdx-components.jsx b/docs/mdx-components.jsx new file mode 100644 index 0000000000000..f1c10a2bb3b9b --- /dev/null +++ b/docs/mdx-components.jsx @@ -0,0 +1,74 @@ +import { useMDXComponents as getThemeComponents } from 'nextra-theme-docs' +import { Btn } from './components/mdx/Btn' +import { InfoBox, WarningBox, SuccessBox, ReferenceBox } from './components/mdx/AlertBox' +import { Screenshot, Diagram } from './components/mdx/Screenshot' +import { YouTubeVideo } from './components/mdx/YouTubeVideo' +import { LoomVideo } from './components/mdx/LoomVideo' +import { ProductVideo } from './components/mdx/ProductVideo' +import { CommunitySupportedDriver } from './components/mdx/CommunitySupportedDriver' +import { Grid } from './components/mdx/Grid' +import { GridItem } from './components/mdx/GridItem' +import { CodeTabs } from './components/mdx/CodeTabs' +import { Pre } from './components/mdx/Pre' +import { EnvVar } from './components/mdx/EnvVar' +import { FeedbackBlock } from './components/FeedbackBlock' + +const themeComponents = getThemeComponents() + +// Custom wrapper that adds FeedbackBlock at the bottom of each page +const ThemeWrapper = themeComponents.wrapper +const CustomWrapper = ({ children, ...props }) => ( + + {children} + + +) + +// Stub component that renders children +const Stub = ({ children }) => <>{children} + +// Stub component that renders nothing +const EmptyStub = () => null + +// Stub components - to be replaced with real implementations +const customComponents = { + // UI Components + Btn, + Screenshot, + Diagram, + + // Code display + CodeTabs, + pre: Pre, + + // Alert boxes + InfoBox, + WarningBox, + SuccessBox, + ReferenceBox, + + // Layout + Grid, + GridItem, + + // Video embeds + YouTubeVideo, + LoomVideo, + ProductVideo, + + // Cube-specific components + CommunitySupportedDriver, + EnvVar, + QueryBuilder: EmptyStub, + QueryRenderer: EmptyStub, + CubeProvider: Stub, +} + +export function useMDXComponents(components) { + return { + ...themeComponents, + ...customComponents, + wrapper: CustomWrapper, + ...components + } +} diff --git a/docs/next-env.d.ts b/docs/next-env.d.ts new file mode 100644 index 0000000000000..a4a7b3f5cfa2f --- /dev/null +++ b/docs/next-env.d.ts @@ -0,0 +1,5 @@ +/// +/// + +// NOTE: This file should not be edited +// see https://nextjs.org/docs/pages/building-your-application/configuring/typescript for more information. diff --git a/docs/next-sitemap.config.js b/docs/next-sitemap.config.js deleted file mode 100644 index bc1d82193946c..0000000000000 --- a/docs/next-sitemap.config.js +++ /dev/null @@ -1,10 +0,0 @@ -/** @type {import('next-sitemap').IConfig} */ -module.exports = { - exclude: ['*/_meta', '/docs'], - siteUrl: process.env.SITE_URL || 'https://cube.dev/docs', - generateRobotsTxt: true, // (optional), - robotsTxtOptions: { - policies: [{ userAgent: '*', disallow: '/' }], - }, - // ...other options -} diff --git a/docs/next.config.mjs b/docs/next.config.mjs index 31273b54ac14f..8150a0577dd26 100644 --- a/docs/next.config.mjs +++ b/docs/next.config.mjs @@ -1,38 +1,43 @@ -import nextra from "nextra"; -import remarkMath from "remark-math"; -import remarkFrontmatter from "remark-frontmatter"; -import remarkHtmlKatex from "remark-html-katex"; -import linkEnvironmentVariables from "./plugins/link-environment-variables.mjs"; - -import redirects from './redirects.json' with { type: "json" }; - -/** - * @type {import('next').NextConfig} - */ -const config = { - basePath: process.env.BASE_PATH || "", - async redirects() { - return redirects; - }, -}; +import nextra from 'nextra' +import path from 'path' +// Cross-domain redirects to the new Mintlify docs at docs.cube.dev. +// Generated from redirects.json by docs-mintlify/scripts/build_old_site_redirects.py. +import redirects from './redirects-new-docs.json' with { type: 'json' } const withNextra = nextra({ - theme: "nextra-theme-docs", - themeConfig: "./theme.config.tsx", - defaultShowCopyCode: true, - flexsearch: false, + contentDirBasePath: '/', + search: false, mdxOptions: { - remarkPlugins: [ - remarkMath, - remarkFrontmatter, - remarkHtmlKatex, - linkEnvironmentVariables, - ], + rehypePrettyCodeOptions: { + theme: { + light: 'one-light', + dark: 'one-dark-pro' + } + } + } +}) + +export default withNextra({ + basePath: process.env.BASE_PATH || '', + async redirects() { + return [ + { + source: '/', + destination: 'https://docs.cube.dev/docs/introduction', + permanent: true + }, + ...redirects + ] }, - transform: async (result, options) => { - console.log(`${options.route}.mdx`); - return result; + outputFileTracingRoot: import.meta.dirname, + turbopack: { + root: import.meta.dirname, + resolveAlias: { + 'next-mdx-import-source-file': './mdx-components.jsx' + } }, -}); - -export default withNextra(config); + webpack: (config) => { + config.resolve.alias['next-mdx-import-source-file'] = path.resolve(import.meta.dirname, 'mdx-components.jsx') + return config + } +}) diff --git a/docs/package.json b/docs/package.json index 60f69c8314740..cc9a6cd1fa504 100644 --- a/docs/package.json +++ b/docs/package.json @@ -1,53 +1,28 @@ { - "name": "@cubejs-docs/site", - "version": "2.0.0", - "keywords": [], - "license": "MIT", + "name": "docs", + "version": "1.0.0", "private": true, + "license": "MIT", "scripts": { - "dev": "next dev", - "build": "next build", - "postbuild": "next-sitemap && rm -rf .next/cache", - "start": "next start", - "create-redirects": "ts-node --esm scripts/create-redirects.mjs", - "migrate-content": "ts-node ./scripts/migrate-content.ts", - "update-links": "ts-node --esm scripts/update-links.mjs" + "dev": "NODE_OPTIONS='--max-old-space-size=16384' next dev --webpack", + "build": "NODE_OPTIONS='--max-old-space-size=16384' next build --webpack", + "start": "next start" }, "dependencies": { - "@cube-dev/marketing-ui": "0.0.1-beta.22", - "@cube-dev/purple-banner": "https://github.com/cubedevinc/purple-banner/releases/download/v2.0.21/cube-dev-purple-banner-2.0.21.tgz", - "@cubejs-client/core": "^0.32.17", - "@radix-ui/react-dialog": "^1.0.4", - "@radix-ui/react-navigation-menu": "^1.1.3", - "classnames": "^2.3.2", - "cubedev-tracking": "^1.1.0", - "date-fns": "^2.30.0", - "next": "^14.2.35", - "next-sitemap": "^4.1.3", - "nextra": "^2.13.2", - "nextra-theme-docs": "^2.4.0", - "react": "^18.2.0", - "react-dom": "^18.2.0", - "remark-html-katex": "^4.0.1", - "remark-math": "^5.1.1", - "unist-util-visit": "^4.1.2" + "@cube-dev/marketing-ui": "^0.0.1-beta.22", + "@cube-dev/purple-banner": "https://github.com/cubedevinc/purple-banner/releases/download/v2.0.23/cube-dev-purple-banner-2.0.23.tgz", + "@radix-ui/react-dialog": "^1.1.15", + "@radix-ui/react-navigation-menu": "^1.2.14", + "algoliasearch": "^5.49.0", + "cubedev-tracking": "1.1.0", + "next": "^16.1.7", + "nextra": "^4.6.1", + "nextra-theme-docs": "^4.6.1", + "react": "^19.2.4", + "react-dom": "^19.2.4", + "search-insights": "^2.17.3" }, "devDependencies": { - "@tsconfig/node16": "^1.0.3", - "@types/node": "^18.13.0", - "autoprefixer": "^10.4.14", - "front-matter": "^4.0.2", - "glob": "^9.3.4", - "postcss": "^8.4.21", - "prettier": "^2.8.8", - "remark": "^14.0.3", - "remark-frontmatter": "^4.0.1", - "remark-gfm": "^3.0.1", - "remark-mdx": "^2.3.0", - "sass": "^1.62.1", - "tailwindcss": "^3.3.1", - "ts-node": "^10.9.1", - "typescript": "^4.9.5", - "vfile-reporter": "^7.0.5" + "typescript": "^5.5.0" } } diff --git a/docs/pages/_app.tsx b/docs/pages/_app.tsx deleted file mode 100644 index 35d19c47a6408..0000000000000 --- a/docs/pages/_app.tsx +++ /dev/null @@ -1,134 +0,0 @@ -import { type AppProps } from "next/app"; - -import "@/styles/globals.css"; -import "@/styles/palette.css"; -import "@/styles/typography.css"; -import "@/styles/math.css"; -import "@/styles/images.css"; -import "katex/dist/katex.min.css"; -import "@cube-dev/marketing-ui/dist/index.css"; - -import PurpleBanner from '@cube-dev/purple-banner'; -import localFont from "next/font/local"; -import { Inter } from "next/font/google"; -import { SearchProvider } from "@cube-dev/marketing-ui"; -import { useRouter } from 'next/router'; -import { useEffect, useState } from 'react'; - -export const SourceCodePro = localFont({ - src: "../fonts/SourceCodePro-Regular.woff2", - weight: "400", - style: "normal", -}); - -export const JetBrainsMono = localFont({ - src: "../fonts/JetBrainsMono-Regular.woff2", - weight: "400", - style: "normal", -}); - -const inter = Inter({ - subsets: ["latin"], - weight: ["400", "500", "600", "700"], -}); - -export const CeraPro = localFont({ - src: [ - { - path: "../fonts/CeraPro-Regular.woff2", - weight: "300", - style: "normal", - }, - { - path: "../fonts/CeraPro-Regular.woff2", - weight: "400", - style: "normal", - }, - { - path: "../fonts/CeraPro-Medium.woff2", - weight: "500", - style: "normal", - }, - { - path: "../fonts/CeraPro-Bold.woff2", - weight: "600", - style: "normal", - }, - { - path: "../fonts/CeraPro-Bold.woff2", - weight: "700", - style: "normal", - }, - ], -}); - -type Props = { origin: string | null }; - -export default function MyApp({ origin, Component, pageProps }: AppProps & Props) { - const router = useRouter() - const [pbVisible, setPbVisible] = useState(false) - - useEffect(() => { - requestAnimationFrame(() => setPbVisible(true)) - }, []) - - // Track page views - useEffect(() => { - const handleRouteChange = async (url) => { - if (typeof window !== 'undefined') { - const { page } = await import('cubedev-tracking'); - page(); - } - } - - router.events.on('routeChangeStart', handleRouteChange) - - // If the component is unmounted, unsubscribe - // from the event with the `off` method: - return () => { - router.events.off('routeChangeStart', handleRouteChange) - } - }, [router]) - - return ( - - - -
- -
- - -
- ); -} diff --git a/docs/pages/_meta.js b/docs/pages/_meta.js deleted file mode 100644 index fa119aab20fb9..0000000000000 --- a/docs/pages/_meta.js +++ /dev/null @@ -1,41 +0,0 @@ -// introduction: "Introduction", -// "getting-started": "Getting Started", -// configuration: "Configuration", -// "data-modeling": "Data Modeling", -// caching: "Caching", -// auth: "Authentication & Authorization", -// "rest-api": "REST API", -// "graphql-api": "GraphHQL API", -// "sql-api": "SQL API", -// "frontend-integrations": "Frontend Integrations", -// workspace: "Workspace", -// deployment: "Deployment", -// monitoring: "Monitoring", - -module.exports = { - // index: { - // title: "Home", - // theme: { - // layout: "raw", - // sidebar: false, - // toc: false, - // }, - // }, - docs: { - // type: "page", - title: "[Demo] MDX Components", - display: "hidden", - }, - - product: { - type: "page", - title: "Documentation", - }, - - changelog: { - type: "page", - title: "Changelog", - href: "https://cube.dev/blog/category/changelog", - newWindow: true, - }, -}; diff --git a/docs/pages/docs.mdx b/docs/pages/docs.mdx deleted file mode 100644 index 00d8aac49d4bf..0000000000000 --- a/docs/pages/docs.mdx +++ /dev/null @@ -1,255 +0,0 @@ -# MDX Components - -# Heading 1 - -## Heading 2 - -### Heading 3 - -#### Heading 4 - -##### Heading 5 - -###### Heading 6 - ---- - -## Code block - -#### Default - -```javascript -cube(`monthly_retention`, { - // ... - - dimensions: { - months_since_signup: { - sql: `DATEDIFF('month', ${CUBE}.signup_month, ${CUBE}.activity_month)`, - type: `number` - }, - - signup_date: { - sql: `(signup_month AT TIME ZONE 'America/Los_Angeles')`, - type: `time` - } - } -}) -``` - -#### With tabs - - - -```yaml -cubes: - - name: monthly_retention - # ... - dimensions: - - name: months_since_signup - sql: "DATEDIFF('month', signup_month, activity_month)" - type: number - - - name: signup_date - sql: "(signup_month AT TIME ZONE 'America/Los_Angeles')" - type: time -``` - -```javascript -cube(`monthly_retention`, { - // ... - - dimensions: { - months_since_signup: { - sql: `DATEDIFF('month', ${CUBE}.signup_month, ${CUBE}.activity_month)`, - type: `number` - }, - - signup_date: { - sql: `(signup_month AT TIME ZONE 'America/Los_Angeles')`, - type: `time` - } - } -}) -``` - - - -## Alert Box - - - DangerBox - - -DangerBox - - - InfoBox - - -InfoBox - - - SuccessBox - - -SuccessBox - - - WarningBox - - -WarningBox - -## Buttons - - - - - - Yes - No - - - - - - - - Yes - No - - - -## Inline Button - -You can implement the element directly by using inline Button component. - -## Inline code - -SQL query `SELECT * FROM users`. - -## Selected text - -- TODO - -## Table - -| Field | Value | Description | -|:---------|:-------------------|-------------| -| Host | `demo-db.cube.dev` | Foo | -| Port | `5432` | Bar | -| Database | `ecom` | Baz | -| Username | `cube` | More Foo | -| Password | `12345` | More Bar | - -## Video - -#### Loom - - - -#### Youtube - - - -## Image - - - -## Card links - -### Two-column - - - - - - -### Three-column - - - - - - - - -## Cube Cloud Promo block - - - -Playground is available in Cube Cloud on [all tiers](#). - - - -## Event promo block - - - - - - - - - -## Case Study promo block - -} -> - -How RamSoft built its users native embedded analytics—in two weeks. [Read the case studies](#). - - diff --git a/docs/pages/product/_meta.js b/docs/pages/product/_meta.js deleted file mode 100644 index 8bd8189045407..0000000000000 --- a/docs/pages/product/_meta.js +++ /dev/null @@ -1,12 +0,0 @@ -module.exports = { - "introduction": "Introduction", - "getting-started": "Getting started", - "configuration": "Data Sources & Config", - "data-modeling": "Data modeling", - "exploration": "Explore & Analyze", - "presentation": "Present & Share", - "caching": "Caching", - "auth": "Access control", - "apis-integrations": "APIs & integrations", - "administration": "Administration" -} \ No newline at end of file diff --git a/docs/pages/product/administration.mdx b/docs/pages/product/administration.mdx deleted file mode 100644 index 73199c6ff2227..0000000000000 --- a/docs/pages/product/administration.mdx +++ /dev/null @@ -1,20 +0,0 @@ -# Administration - -Administration tools help you deploy, manage, and monitor your Cube projects. - - - -Most administration tools are available in Cube Cloud. - - - -## Administration in Cube Cloud - -In Cube Cloud, you can: - -- Use [Workspace][ref-workspace] tools to build, test, and manage Cube projects -- Use [Deployment][ref-deployment] tools to deploy and scale your Cube infrastructure - -[ref-workspace]: /product/administration/workspace -[ref-deployment]: /product/administration/deployment - diff --git a/docs/pages/product/administration/_meta.js b/docs/pages/product/administration/_meta.js deleted file mode 100644 index 51c772fe15d88..0000000000000 --- a/docs/pages/product/administration/_meta.js +++ /dev/null @@ -1,8 +0,0 @@ -module.exports = { - "users-and-permissions": "Users & permissions", - "ai": "AI", - "workspace": "Workspace", - "deployment": "Deployment", - "distribution": "Distribution" -} - diff --git a/docs/pages/product/administration/ai.mdx b/docs/pages/product/administration/ai.mdx deleted file mode 100644 index afbe9a129bb43..0000000000000 --- a/docs/pages/product/administration/ai.mdx +++ /dev/null @@ -1,22 +0,0 @@ -# AI - -AI tools help you configure and manage AI-powered features in Cube Cloud. - - - -AI tools are available in Cube Cloud. - - - -## AI tools - -Configure AI features to: - -- Set up [spaces, agents, and models][ref-spaces] for your AI-powered applications -- Define [agent rules][ref-rules] to control agent behavior -- Manage [agent memories][ref-memories] for context persistence - -[ref-spaces]: /product/administration/ai/spaces-agents-models -[ref-rules]: /product/administration/ai/agent-rules -[ref-memories]: /product/administration/ai/memory-isolation - diff --git a/docs/pages/product/administration/ai/_meta.js b/docs/pages/product/administration/ai/_meta.js deleted file mode 100644 index fe3e386511a98..0000000000000 --- a/docs/pages/product/administration/ai/_meta.js +++ /dev/null @@ -1,6 +0,0 @@ -module.exports = { - "spaces-agents-models": "Spaces, agents, models", - "agent-rules": "Agent rules", - "memory-isolation": "Agent memories" -} - diff --git a/docs/pages/product/administration/deployment.mdx b/docs/pages/product/administration/deployment.mdx deleted file mode 100644 index 9ef2dee903523..0000000000000 --- a/docs/pages/product/administration/deployment.mdx +++ /dev/null @@ -1,249 +0,0 @@ -# Overview - -This section contains a general overview of deploying a Cube cluster in -production. You can also check platform-specific guides for [Cube -Cloud][ref-deploy-cubecloud] and [Docker][ref-deploy-docker]. - -If you are moving Cube to production, check out the [Production -Checklist][ref-deploy-prod-list]. - -## Components - -As shown in the diagram below, a typical production deployment of Cube includes -the following components: - -- One or multiple API instances -- A Refresh Worker -- A Cube Store cluster - -
- Deployment Overview -
- -**API Instances** process incoming API requests and query either Cube Store for -pre-aggregated data or connected database(s) for raw data. The **Refresh -Worker** builds and refreshes pre-aggregations in the background. **Cube Store** -ingests pre-aggregations built by Refresh Worker and responds to queries from -API instances. - -API instances and Refresh Workers can be configured via [environment -variables][ref-config-env] or the [`cube.js` configuration file][ref-config-js]. -They also need access to the data model files. Cube Store clusters can be -configured via environment variables. - -You can find an example Docker Compose configuration for a Cube deployment in -the platform-specific guide for [Docker][ref-deploy-docker]. - -## API instances - -API instances process incoming API requests and query either Cube Store for -pre-aggregated data or connected data sources for raw data. It is possible to -horizontally scale API instances and use a load balancer to balance incoming -requests between multiple API instances. - -The [Cube Docker image][dh-cubejs] is used for API Instance. - -API instances can be configured via environment variables or the `cube.js` -configuration file, and **must** have access to the data model files (as -specified by [`schema_path`][ref-conf-ref-schemapath]. - -## Refresh Worker - -A Refresh Worker updates pre-aggregations and invalidates the in-memory cache in -the background. They also keep the refresh keys up-to-date for all data models -and pre-aggregations. Please note that the in-memory cache is just invalidated -but not populated by Refresh Worker. In-memory cache is populated lazily during -querying. On the other hand, pre-aggregations are eagerly populated and kept -up-to-date by Refresh Worker. - -The [Cube Docker image][dh-cubejs] can be used for creating Refresh Workers; to -make the service act as a Refresh Worker, `CUBEJS_REFRESH_WORKER=true` should be -set in the environment variables. - -## Cube Store - -Cube Store is the purpose-built pre-aggregations storage for Cube. - -Cube Store uses a distributed query engine architecture. In every Cube Store -cluster: - -- a one or many [router nodes](#cube-store-cube-store-router) handle incoming - connections, manages database metadata, builds query plans, and orchestrates - their execution -- multiple [worker nodes](#cube-store-cube-store-worker) ingest warmed up data - and execute queries in parallel -- a local or cloud-based blob storage keeps pre-aggregated data in columnar - format - -
- Cube Store Router with two Cube Store Workers -
- -By default, Cube Store listens on the port `3030` for queries coming from Cube. -The port could be changed by setting `CUBESTORE_HTTP_PORT` environment variable. -In a case of using custom port, please make sure to change -`CUBEJS_CUBESTORE_PORT` environment variable for Cube API Instances and Refresh -Worker. - -Both the router and worker use the [Cube Store Docker image][dh-cubestore]. The -following environment variables should be used to manage the roles: - -| Environment Variable | Specify on Router? | Specify on Worker? | -| ----------------------- | ------------------ | ------------------ | -| `CUBESTORE_SERVER_NAME` | ✅ Yes | ✅ Yes | -| `CUBESTORE_META_PORT` | ✅ Yes | — | -| `CUBESTORE_WORKERS` | ✅ Yes | ✅ Yes | -| `CUBESTORE_WORKER_PORT` | — | ✅ Yes | -| `CUBESTORE_META_ADDR` | — | ✅ Yes | - - - -Looking for a deeper dive on Cube Store architecture? Check out -[this presentation](https://docs.google.com/presentation/d/1oQ-koloag0UcL-bUHOpBXK4txpqiGl41rxhgDVrw7gw/) -by our CTO, [Pavel][gh-pavel]. - - - -### Cube Store Router - -
- Cube Store Router with two Cube Store Workers -
- -The Router in a Cube Store cluster is responsible for receiving queries from -Cube, managing metadata for the Cube Store cluster, and query planning and -distribution for the Workers. It also [provides a MySQL-compatible -interface][ref-caching-inspect-sql] that can be used to query pre-aggregations -from Cube Store directly. Cube **only** communicates with the Router, and does -not interact with Workers directly. - -[ref-caching-inspect-sql]: - /product/caching/using-pre-aggregations#inspecting-pre-aggregations - -### Cube Store Worker - -
- Cube Store Router with two Cube Store Workers -
- -Workers in a Cube Store cluster receive and execute subqueries from the Router, -and directly interact with the underlying distributed storage for insertions, -selections and pre-aggregation warmup. Workers **do not** interact with each -other directly, and instead rely on the Router to distribute queries and manage -any associated metadata. - -### Scaling - -Although Cube Store _can_ be run in single-instance mode, this is often -unsuitable for production deployments. For high concurrency and data throughput, -we **strongly** recommend running Cube Store as a cluster of multiple instances -instead. Because the storage layer is decoupled from the query processing -engine, you can horizontally scale your Cube Store cluster for as much -concurrency as you require. - -A sample Docker Compose stack setting Cube Store cluster up might look like: - -```yaml -services: - cubestore_router: - image: cubejs/cubestore:latest - environment: - - CUBESTORE_WORKERS=cubestore_worker_1:10001,cubestore_worker_2:10002 - - CUBESTORE_REMOTE_DIR=/cube/data - - CUBESTORE_META_PORT=9999 - - CUBESTORE_SERVER_NAME=cubestore_router:9999 - volumes: - - .cubestore:/cube/data - depends_on: - - cubestore_worker_1 - - cubestore_worker_2 - - cubestore_worker_1: - image: cubejs/cubestore:latest - environment: - - CUBESTORE_WORKERS=cubestore_worker_1:10001,cubestore_worker_2:10002 - - CUBESTORE_SERVER_NAME=cubestore_worker_1:10001 - - CUBESTORE_WORKER_PORT=10001 - - CUBESTORE_REMOTE_DIR=/cube/data - - CUBESTORE_META_ADDR=cubestore_router:9999 - volumes: - - .cubestore:/cube/data - - cubestore_worker_2: - image: cubejs/cubestore:latest - environment: - - CUBESTORE_WORKERS=cubestore_worker_1:10001,cubestore_worker_2:10002 - - CUBESTORE_SERVER_NAME=cubestore_worker_2:10002 - - CUBESTORE_WORKER_PORT=10002 - - CUBESTORE_REMOTE_DIR=/cube/data - - CUBESTORE_META_ADDR=cubestore_router:9999 - volumes: - - .cubestore:/cube/data -``` - -### Storage - -Cube Store makes use of a separate storage layer for storing metadata as well as -for persisting pre-aggregations as Parquet files. Cube Store can use both AWS S3 -and Google Cloud, or if desired, a local path on the server if all nodes of a -cluster run on a single machine. - -A simplified example using AWS S3 might look like: - -```yaml -services: - cubestore_router: - image: cubejs/cubestore:latest - environment: - - CUBESTORE_SERVER_NAME=cubestore_router:9999 - - CUBESTORE_META_PORT=9999 - - CUBESTORE_WORKERS=cubestore_worker_1:9001 - - CUBESTORE_S3_BUCKET= - - CUBESTORE_S3_REGION= - - CUBESTORE_AWS_ACCESS_KEY_ID= - - CUBESTORE_AWS_SECRET_ACCESS_KEY= - cubestore_worker_1: - image: cubejs/cubestore:latest - environment: - - CUBESTORE_SERVER_NAME=cubestore_worker_1:9001 - - CUBESTORE_WORKER_PORT=9001 - - CUBESTORE_META_ADDR=cubestore_router:9999 - - CUBESTORE_WORKERS=cubestore_worker_1:9001 - - CUBESTORE_S3_BUCKET= - - CUBESTORE_S3_REGION= - - CUBESTORE_AWS_ACCESS_KEY_ID= - - CUBESTORE_AWS_SECRET_ACCESS_KEY= - depends_on: - - cubestore_router -``` - - -[dh-cubejs]: https://hub.docker.com/r/cubejs/cube -[dh-cubestore]: https://hub.docker.com/r/cubejs/cubestore -[ref-deploy-prod-list]: /product/deployment/production-checklist -[ref-deploy-cubecloud]: /product/deployment/cloud -[ref-deploy-docker]: /product/deployment/core -[ref-config-env]: /product/configuration/reference/environment-variables -[ref-config-js]: /product/configuration/reference/config -[ref-conf-ref-schemapath]: /product/configuration/reference/config#schema_path -[gh-pavel]: https://github.com/paveltiunov diff --git a/docs/pages/product/administration/deployment/_meta.js b/docs/pages/product/administration/deployment/_meta.js deleted file mode 100644 index b9fde31cd12f9..0000000000000 --- a/docs/pages/product/administration/deployment/_meta.js +++ /dev/null @@ -1,17 +0,0 @@ -module.exports = { - "providers": "Cloud providers", - "infrastructure": "Infrastructure options", - "vpc": "VPC", - "byoc": "BYOC", - "deployments": "Deployments", - "deployment-types": "Deployment types", - "continuous-deployment": "Continuous deployment", - "custom-domains": "Custom domains", - "warm-up": "Deployment warm-up", - "auto-suspension": "Auto-suspension", - "scalability": "Scalability", - "pricing": "Pricing", - "support": "Support", - "limits": "Limits", - "core": "Cube Core" -} diff --git a/docs/pages/product/administration/deployment/auto-suspension.mdx b/docs/pages/product/administration/deployment/auto-suspension.mdx deleted file mode 100644 index 2950c7327e762..0000000000000 --- a/docs/pages/product/administration/deployment/auto-suspension.mdx +++ /dev/null @@ -1,124 +0,0 @@ -# Auto-suspension - - - -Auto-suspension is available in Cube Cloud on -[Starter and above](https://cube.dev/pricing) product tiers. - - - -Cube Cloud can automatically suspend deployments when not in use to reduce -[resource consumption][ref-deployment-pricing], which helps manage your spend. - - - -Auto-suspension is useful for deployments that are not used 24/7, such as -staging deployments. However, **auto-suspension shall not be used for production -deployments**. See [effects on experience][self-effects] for details. - - - - - -Auto-suspension is not avaiable for [production multi-clusters][ref-prod-multi-cluster]. - - - -Auto-suspension will hibernate the deployment when **no** API -requests are received after a period of time, and automatically resume the -deployment when API requests start coming in again: - - - -[Development instances][ref-deployment-dev-instance] are auto-suspended -automatically when not in use for 30 minutes, whereas [production -clusters][ref-deployment-prod-cluster] can auto-suspend after no API -requests were received within a configurable time period. - -During auto-suspension, resources are monitored in 5 minute intervals. This -means that if a deployment was suspended 4 minutes ago, and a request comes in, -the deployment will resume immediately and 5 minute of CCU usage will be billed. - -## Effects on experience - -If auto-suspension is enabled, the behavior of your Cube Cloud deployment will -experience some notable changes. - -When a deployment is auto-suspended: - -- [Data model][ref-data-model] compilation artifacts are discarded since the -API instances are de-provisioned. -- [Refresh worker][ref-refresh-worker] is suspended, which stops pre-aggregation -builds and prevents the pre-aggregations from being kept up-to-date. -- [Semantic Layer Sync][ref-sls] is suspended, which prevents scheduled syncs -from running. -- [Monitoring integrations][ref-monitoring] are also suspended, which prevents -the export of metrics and logs. - -When a deployment is resumed from auto-suspension: - -- [Data model][ref-data-model] compilation would need to be done from scratch. -It applies to all tenants in case [multitenancy][ref-multitenancy] is set up. -Consequently, one or more queries served after a deployment is resumed from -auto-suspension are likely to have suboptimal performance. -- [Refresh worker][ref-refresh-worker] would need to refresh all -pre-aggregations that became stale during the suspension, competing for the -query queue with API instances and compromising the end-user experience. - -## Configuration - -To enable auto-suspension, navigate to Settings → Configuration -of your Cube Cloud deployment and ensure that Enable auto-suspend -is turned on: - - - -To configure how long Cube Cloud should wait before suspending -the deployment, adjust Auto-suspend threshold. For best experience, -it's not recommended to choose anything below 1 hour. - -The deployment will temporarily become unavailable for reconfiguration; this -usually takes less than a minute. - -## Resuming a suspended deployment - -To resume a suspended deployment, send a query to Cube using the API or by -navigating to the deployment in Cube Cloud. - - - -Currently, Cube Cloud's auto-suspension feature cannot guarantee a 100% resume -rate on the first query or a specific time frame for resume. While in most -cases, deployment resumes within several seconds of the first query, there is -still a possibility that it may take longer to resume your deployment. This can -potentially lead to an error response code for the initial query. - - - -Deployments typically resume in under 30 seconds, but can take significantly -longer in certain situations depending on two major factors: - -- **Data model:** How many cubes and views are defined. -- **Query complexity:** How complicated the queries being sent to the API are - -Complex data models take more time to compile, and complex queries can cause -response times to be significantly longer than usual. - -[ref-deployment-dev-instance]: - /product/deployment/cloud/deployment-types#development-instance -[ref-deployment-prod-cluster]: - /product/deployment/cloud/deployment-types#production-cluster -[ref-prod-multi-cluster]: /product/deployment/cloud/deployment-types#production-multi-cluster -[ref-deployment-pricing]: /product/deployment/cloud/pricing -[ref-monitoring]: /product/workspace/monitoring -[ref-data-model]: /product/data-modeling/overview -[ref-multitenancy]: /product/configuration/multitenancy -[self-effects]: #effects-on-experience -[ref-refresh-worker]: /product/deployment#refresh-worker -[ref-sls]: /product/apis-integrations/semantic-layer-sync#on-schedule \ No newline at end of file diff --git a/docs/pages/product/administration/deployment/byoc.mdx b/docs/pages/product/administration/deployment/byoc.mdx deleted file mode 100644 index 5d371c1e849b6..0000000000000 --- a/docs/pages/product/administration/deployment/byoc.mdx +++ /dev/null @@ -1,29 +0,0 @@ -# Bring Your Own Cloud - -This guide outlines the Bring Your Own Cloud (BYOC) deployment configuration for Cube Cloud. -With BYOC, all the components interacting with private data are deployed on the customer infrastructure -on a platform of choice (AWS/Azure/GCP) and managed by the Cube Cloud Control Plane via the Cube Cloud Operator. - - - -BYOC is available in Cube Cloud on the -[Enterprise Premier](https://cube.dev/pricing) product tier. -[Contact us](https://cube.dev/contact) for details. - - - -Cube Cloud supports BYOC on AWS, GCP, and Azure. Below, you can find documentation for AWS. Reach out to your account team for Azure or GCP BYOC documentation. - - - - - - diff --git a/docs/pages/product/administration/deployment/byoc/_meta.js b/docs/pages/product/administration/deployment/byoc/_meta.js deleted file mode 100644 index f2b513f81c7a0..0000000000000 --- a/docs/pages/product/administration/deployment/byoc/_meta.js +++ /dev/null @@ -1,5 +0,0 @@ -module.exports = { - aws: "AWS", - azure: "Azure", - gcp: "GCP", -}; diff --git a/docs/pages/product/administration/deployment/byoc/aws/_meta.js b/docs/pages/product/administration/deployment/byoc/aws/_meta.js deleted file mode 100644 index 54ac5927aa12f..0000000000000 --- a/docs/pages/product/administration/deployment/byoc/aws/_meta.js +++ /dev/null @@ -1,4 +0,0 @@ -module.exports = { - deployment: "Deployment", - privatelink: "Private Connectivity", -}; diff --git a/docs/pages/product/administration/deployment/byoc/gcp/_meta.js b/docs/pages/product/administration/deployment/byoc/gcp/_meta.js deleted file mode 100644 index 10f8337183d2e..0000000000000 --- a/docs/pages/product/administration/deployment/byoc/gcp/_meta.js +++ /dev/null @@ -1,3 +0,0 @@ -module.exports = { - deployment: "Deployment", -}; diff --git a/docs/pages/product/administration/deployment/custom-domains.mdx b/docs/pages/product/administration/deployment/custom-domains.mdx deleted file mode 100644 index 1ed9b4b98189c..0000000000000 --- a/docs/pages/product/administration/deployment/custom-domains.mdx +++ /dev/null @@ -1,37 +0,0 @@ -# Custom domains - -By default, Cube Cloud deployments and their API endpoints use auto-generated -anonymized domain names, e.g., `emerald-llama.gcp-us-central1.cubecloudapp.dev`. -You can also assign a custom domain to your deployment. - - - -Custom domains are available in Cube Cloud on -[Premium and above](https://cube.dev/pricing) product tiers. - - - -To set up a custom domain, go to your deployment's settings page. Under -the Custom Domain section, type in your custom domain and -click Add: - - - -After doing this, copy the provided domain and add the following `CNAME` records -to your DNS provider: - -| Name | Value | -| ------------- | ------------------------------------------- | -| `YOUR_DOMAIN` | The copied value from Cube Cloud's settings | - -Using the example subdomain from the screenshot, a `CNAME` record for `acme.dev` -would look like: - -| Name | Value | -| ---------- | ----------------------------------------------------- | -| `insights` | `colossal-crowville.gcp-us-central1.cubecloudapp.dev` | - -DNS changes can sometimes take up to 15 minutes to propagate, please wait at -least 15 minutes and/or try using another DNS provider to verify the `CNAME` -record correctly before raising a new support ticket. - diff --git a/docs/pages/product/administration/deployment/deployment-types.mdx b/docs/pages/product/administration/deployment/deployment-types.mdx deleted file mode 100644 index c41290a0fb145..0000000000000 --- a/docs/pages/product/administration/deployment/deployment-types.mdx +++ /dev/null @@ -1,182 +0,0 @@ -# Deployment types - -Cube Cloud provides you with three deployment types: - -* [Development instance](#development-instance) — designed for development use -cases. -* [Production cluster](#production-cluster) — designed for production workloads -and high-availability. -* [Production multi-cluster](#production-multi-cluster) — designed for -demanding production workloads, high-scalability, high-availaility, and -advanced multi-tenancy configurations. - -## Development instance - - - -Development instance is available in Cube Cloud for free, no credit card -required. Your free trial is limited to 2 development instances and only 1,000 -queries per day. Upgrade to [any paid product tier](https://cube.dev/pricing) -to unlock all features. - - - -
- High-level architecture diagram of a Cube Cloud Development Instance -
- -Development instances are designed for development use cases only. This makes it -easy to get started with Cube Cloud quickly, and also allows you to build and -query pre-aggregations on-demand. - -Development instances don't have dedicated [refresh workers][ref-refresh-worker] -and, consequently, they do not refresh pre-aggregations on schedule. - -Development instances do not provide high-availability nor do they guarantee -fast response times. Development instances also [auto-suspend][ref-auto-sus] -after 30 minutes of inactivity, which can cause the first request after the instance -wakes up to take additional time to process. They also have [limits][ref-limits] -on the maximum number of queries per day and the maximum number of Cube Store -Workers. We **strongly** advise not using a development instance in a production -environment, it is for testing and learning about Cube only and will not deliver -a production-level experience for your users. - -You can try a Cube Cloud development instance by -[signing up for Cube Cloud](https://cubecloud.dev/auth/signup) to try it free -(no credit card required). - -## Production cluster - - - -Production cluster is available in Cube Cloud on -[all paid product tiers](https://cube.dev/pricing). -You can also choose a [deployment tier](/product/deployment/cloud/pricing#deployment-tiers). - - - -
- High-level architecture diagram of a Cube Cloud Production Cluster -
- -Production Clusters are designed to support high-availability production -workloads. It consists of several key components, including starting with 2 Cube -API instances, 1 Cube Refresh Worker and 2 Cube Store Routers - all of which run -on dedicated infrastructure. The cluster can automatically scale to meet the -needs of your workload by adding more components as necessary; check the page on -[scalability][ref-scalability] to learn more. - -## Production multi-cluster - -Production multi-cluster deployments are designed for demanding production -workloads, high-scalability, high-availaility, and large [multi-tenancy][ref-multitenancy] -configurations, e.g., with more than 100 tenants. - - - -Production multi-cluster is available in Cube Cloud on -[Premium and above](https://cube.dev/pricing) product tiers. - - - -It provides you with two options: -* Scale the number of [production cluster](#production-cluster) deployments -serving your workload, allowing to route requests over up to 10 production -clusters and up to 100 API instances. -* Optionally, scale the number of Cube Store routers, allowing for increased -Cube Store querying performance. - -
- High-level architecture diagram of a Cube Cloud Production Multi-Cluster -
- -Each production cluster is billed separately, and all production clusters can -use auto-scaling to match demand. - -### Configuring production multi-cluster - -To switch your Cube Cloud deployment to production multi-cluster, navigate to -Settings → General, select it under Type, and confirm -with ✓: - - - -To set the number of production clusters within your production multi-cluster -deployment, navigate to Settings → Configuration and edit -Number of clusters. - - - -### Routing traffic between production clusters - -Cube Cloud routes requests between multiple production clusters within a -production multi-cluster deployment based on [`context_to_app_id`][ref-ctx-to-app-id]. -In most cases, it should return an identifier that does not change over time -for each tenant. - -The following implementation will make sure that all requests from a -particular tenant are always routed to the same production cluster. This -approach ensures that only one production cluster keeps compiled data model -cache for each tenant and serves its requests. It allows to reduce the -footprint of the compiled data model cache on individual production clusters. - - - -```python -from cube import config - -@config('context_to_app_id') -def context_to_app_id(ctx: dict) -> str: - return f"CUBE_APP_{ctx['securityContext']['tenant_id']}" -``` - -```js -module.exports = { - contextToAppId: ({ securityContext }) => { - return `CUBE_APP_${securityContext.tenant_id}` - } -} -``` - - - - - -If your implementation of `context_to_app_id` returns identifiers that change -over time for each tenant, requests from one tenant would likely hit multiple -production clusters and you would not have the benefit of reduced memory footprint. -Also you might see 502 or timeout errors in case of different cluster nodes would return different `context_to_app_id` results for the same request. - - - -## Switching between deployment types - -To switch a deployment's type, go to the deployment's Settings screen -and select from the available options: - - - -[ref-ctx-to-app-id]: /product/configuration/reference/config#context_to_app_id -[ref-limits]: /product/deployment/cloud/limits#resources -[ref-scalability]: /product/deployment/cloud/scalability -[ref-multitenancy]: /product/configuration/multitenancy -[ref-auto-sus]: /product/deployment/cloud/auto-suspension -[ref-refresh-worker]: /product/deployment#refresh-worker diff --git a/docs/pages/product/administration/deployment/infrastructure.mdx b/docs/pages/product/administration/deployment/infrastructure.mdx deleted file mode 100644 index 3c3c1c6a828d5..0000000000000 --- a/docs/pages/product/administration/deployment/infrastructure.mdx +++ /dev/null @@ -1,169 +0,0 @@ -# Infrastructure Options - -Cube Cloud provides four infrastructure options to host your Cube deployments: - -* [Shared infrastructure](#shared-infrastructure) - your -deployments are sharing compute resources and network with other customers. -Data in-motion and data at-rest are both on the Cube Cloud side. -* [Dedicated infrastructure](#dedicated-infrastructure) - your -deployments reside in a dedicated VPC inside a Cube Cloud account and do not -share resources with anyone else. Data in-motion and data at-rest are both on -the Cube Cloud side. -* [Dedicated infrastructure with CSPS](#dedicated-infrastructure-with-csps) - -same as dedicated infrastructure, but data at-rest is stored in a customer-supplied -object store. -* [Bring Your Own Cloud (BYOC)](#byoc) - Cube Cloud data plane is fully hosted -in your cloud account. - - -## Shared infrastructure - -This is the most common deployment option that is the easiest to get started with. -In this scenario, everything is deployed on the Cube Cloud infrastructure in -one of our **shared** VPCs. Cube Cloud Control Plane takes care of creating, -scaling, and monitoring your Cube Deployments, as well as managing Cube Store -and persisting pre-aggregated data. This option requires the least effort to -set up. - - - -Shared infrastructure is available in Cube Cloud on -[all product tiers](https://cube.dev/pricing). - - - -Please note that some Enterprise features, such as VPC peering or PrivateLink are -not available on the shared infrastructure. There's also a possibility of resource -contention ("noisy neighbor") problem. - -
- High-level diagram of the fully managed Cube Cloud Infrastructure option (shared) -
- -## Dedicated infrastructure - -It is similar to the previous option, but each customer gets a -[Dedicated][ref-dedicated-vpc] VPC within one of Cube Cloud's own cloud -accounts that hosts only that customer's deployments. This option is great for -most of the typical Enterprise use-cases as it provides a higher level of -performance, as well as additional security and isolation. - - - -Dedicated infrastructure is available in Cube Cloud on -[Enterprise and above](https://cube.dev/pricing) product tiers. - - - -
- High-level diagram of the fully managed Cube Cloud Infrastructure option (dedicated) -
- -## Dedicated infrastructure with CSPS - -Cube Cloud offers a **customer-supplied pre-aggregation storage (CSPS)** that -allows moving all data at rest to the customer -infrastructure. In this scenario, all Cube components reside on the Cube Cloud -side. However, Cube Store uses a customer-provided object store for reading and -persisting pre-aggregated data. This provides additional peace of mind when -processing highly critical business or personal information. - - - -Dedicated infrastructure with CSPS is available in Cube Cloud on the -[Enterprise Premier](https://cube.dev/pricing) product tier. - - - - -
- High-level diagram explaining the CSPS option -
- -## BYOC - -With [Bring Your Own Cloud](/product/deployment/cloud/byoc) (BYOC) all the components interacting with private data are deployed on the customer infrastructure -on a platform of choice (AWS/Azure/GCP) and managed by the Cube Cloud Control Plane via the Cube Cloud Operator. - - - -BYOC is available in Cube Cloud on the -[Enterprise Premier](https://cube.dev/pricing) product tier. - - - -
- High-level architecture diagram of the Cube Cloud BYOC deployment option -
- -## Understanding "Cube Cloud Region" - -Throughout Cube documentation and when interacting with Cube staff, you may encounter the term **"Cube Cloud Region"** or simply **"Region"**. Understanding this term is crucial for properly configuring and managing your Cube deployments. - -### What is a Cube Cloud Region? - -A **Cube Cloud Region** refers to a specific cloud infrastructure instance used to host your Cube deployments. While it includes a geographical location component, it encompasses much more than just a physical data center location. - -Each Cube Cloud Region is identified by a unique identifier that contains several components: -- **Cloud provider** (AWS, GCP, or Azure) -- **Geographical region** (e.g., us-east-1, eu-west-1) -- **Infrastructure type** (shared, dedicated, or BYOC) -- **Tenant identifier** (for dedicated infrastructure) -- **Environment** (e.g., prod, staging) - -For example, a region identifier might look like: -- `aws-us-east-1-shared` for shared infrastructure in AWS US East -- `aws-us-east-1-t-12345-prod` for dedicated infrastructure with tenant ID 12345 -- `gcp-europe-west1-t-12345-byoc` for a BYOC deployment in GCP Europe - -Each region also has a human-readable display name that's visible in the Cube Cloud UI. For dedicated infrastructure regions, these display names typically include the customer name and/or environment name (e.g., "Acme Corp Production (N. Virginia)" or "Acme Corp Staging (Iowa)") to help distinguish between different infrastructure instances. - - - -### Not to be confused with... - -The term "Cube Cloud Region" should **not** be confused with: - -- **Cloud provider regions alone** (like AWS `us-east-1`) - A Cube Cloud Region includes but is not limited to the underlying cloud provider region -- **Geographical regions** - While geography is a component, the Cube Cloud Region encompasses infrastructure type and tenant isolation as well -- **Availability zones** - These are subdivisions within cloud provider regions and are handled transparently by Cube Cloud - -### Why this matters - -Understanding your Cube Cloud Region is important for: - -1. **API endpoints**: Your deployment's API endpoints include the region identifier (e.g., `..cubecloudapp.dev`) -2. **Network configuration**: When setting up VPC peering, PrivateLink, or custom domains, you'll need the exact region identifier -3. **Support requests**: Providing the correct region identifier helps Cube support team quickly locate and assist with your deployment -4. **Infrastructure planning**: Different region types offer different capabilities (e.g., PrivateLink is only available in dedicated and BYOC regions) - -### Finding your region identifier - -You can find your Cube Cloud Region identifier in: -- The Cube Cloud UI deployment settings -- API endpoint URLs provided in the deployment overview -- Communication from Cube Cloud support when your infrastructure is provisioned - -When in doubt, contact Cube Cloud support with your deployment ID, and they can provide the exact region identifier for your infrastructure. - -[ref-dedicated-vpc]: /product/deployment/cloud/vpc diff --git a/docs/pages/product/administration/deployment/limits.mdx b/docs/pages/product/administration/deployment/limits.mdx deleted file mode 100644 index d792c6e19be52..0000000000000 --- a/docs/pages/product/administration/deployment/limits.mdx +++ /dev/null @@ -1,112 +0,0 @@ -# Limits and quotas in Cube Cloud - -Cube Cloud implements limits on resource usage on account and deployment levels -to ensure the best experience for all Cube Cloud users. - - - -Limits apply to Cube Cloud accounts on -[all product tiers](https://cube.dev/pricing). - - - -## Limit types - -Each limit can be of one of the following types: - -- _Hard limit_ either has a threshold that can't be exceeded or prevents further - use of a resource when a threshhold is hit until a cool-down period passes - (e.g., until the next day starts) or the limit is increased (e.g., when a Cube - Cloud account upgrades to another tier). -- _Soft limit_ may allow further use of a resource after a threshold is hit. - -## Resources - -The following resources are subject to limits, depending on [deployment -types][ref-deployment-types] and [product tiers][ref-pricing]: - -| Resource | Free Tier | Starter | Premium | Enterprise | Enterprise Premier | -| ----------------------------------------------------------------------------------- | :-------: | :-------: | :-------: | :--------: | :---------------------------: | -| Number of deployments | 2 | Unlimited | Unlimited | Unlimited | Unlimited | -| Number of API instances per deployment | 1 | 10 | 10 | 10 | [Contact us][cube-contact-us] | -| Number of Cube Store workers per deployment | 2 | 16 | 16 | 32 | [Contact us][cube-contact-us] | -| Queries per day for each [development instance][ref-dev-instance] | 1,000 | 10,000 | Unlimited | Unlimited | Unlimited | -| Queries per day for each [production cluster][ref-prod-cluster] | — | 50,000 | Unlimited | Unlimited | Unlimited | -| [Query History][ref-query-history] — retention period | 1 day | Depends on the [tier][ref-query-history-tiers] | Depends on the [tier][ref-query-history-tiers] | Depends on the [tier][ref-query-history-tiers] | Depends on the [tier][ref-query-history-tiers] | -| [Query History][ref-query-history] — queries processed per day for each deployment | 1,000 | Depends on the [tier][ref-query-history-tiers] | Depends on the [tier][ref-query-history-tiers] | Depends on the [tier][ref-query-history-tiers] | Depends on the [tier][ref-query-history-tiers] | -| [Audit Log][ref-audit-log] — retention period | — | — | — | — | 30 days | -| [Audit Log][ref-audit-log] — events collected | — | — | — | — | 10,000 | -| [Monitoring Integrations][ref-monitoring-integrations] — exported data | — | Depends on the [tier][ref-monitoring-integrations-tiers] | Depends on the [tier][ref-monitoring-integrations-tiers] | Depends on the [tier][ref-monitoring-integrations-tiers] | Depends on the [tier][ref-monitoring-integrations-tiers] | - -### Number of deployments - -This is a hard limit. Consider upgrading to [another tier][ref-pricing]. - -### Number of API instances - -This is a hard limit. Consider upgrading to [another tier][ref-pricing]. - -### Number of Cube Store workers - -This is a hard limit. Consider upgrading to [another tier][ref-pricing]. - -An option to use 32 Cube Store workers is subject to availability in select -regions. Please [contact support][cube-contact-us] for more details. - -### Queries per day - -This is a hard limit. Usage is calculated per Cube Cloud account, i.e., in total -for all deployments within an account. - -When a threshold is hit, further queries will not be processed. In that case, -consider upgrading a development instance to a production cluster. -Alternatively, consider upgrading to [another tier][ref-pricing]. - -### Queries processed by Query History per day - -This is a soft limit. Usage is calculated per Cube Cloud account, i.e., in total -for all deployments within an account. - -When a threshold is hit, query processing will be stopped. Please [contact -support][cube-contact-us] for further assistance. - -### Data retained by Query History - -This is a soft limit. Usage is calculated per Cube Cloud account, i.e., in total -for all deployments within an account. - -### Data collected and retained by Audit Log - -This is a hard limit. Usage is calculated per Cube Cloud account, i.e., in total -for all deployments within an account. Please [contact -support][cube-contact-us] for further assistance. - -### Data exported via Monitoring Integrations - -This is a hard limit. Consider upgrading to the next [Monitoring Integrations tier][ref-monitoring-integrations-tiers]. -Usage is calculated per Cube Cloud deployment. - -## Quotas - -The [REST][ref-rest-api] and [GraphQL][ref-gql-api] APIs both have a standard -quota of 100 requests per second per deployment; this can also go higher -for short bursts of traffic. These limits can be raised on request, -[contact support][cube-contact-us] for more details. - -When the quota is exceeded, the API will return a `429 Too Many Requests` -response. - -[ref-rest-api]: /product/apis-integrations/rest-api -[ref-gql-api]: /product/apis-integrations/graphql-api -[ref-deployment-types]: /product/deployment/cloud/deployment-types -[ref-pricing]: /product/deployment/cloud/pricing -[ref-query-history]: /product/workspace/query-history -[ref-monitoring-integrations]: /product/workspace/monitoring -[ref-dev-instance]: - /product/deployment/cloud/deployment-types#development-instance -[ref-prod-cluster]: - /product/deployment/cloud/deployment-types#production-cluster -[cube-contact-us]: https://cube.dev/contact -[ref-query-history-tiers]: /product/deployment/cloud/pricing#query-history-tiers -[ref-audit-log]: /product/workspace/audit-log -[ref-monitoring-integrations-tiers]: /product/deployment/cloud/pricing#monitoring-integrations-tiers diff --git a/docs/pages/product/administration/deployment/pricing.mdx b/docs/pages/product/administration/deployment/pricing.mdx deleted file mode 100644 index 03fbdfed77b49..0000000000000 --- a/docs/pages/product/administration/deployment/pricing.mdx +++ /dev/null @@ -1,371 +0,0 @@ -# Pricing in Cube Cloud - -Cube Cloud pricing is based on resource consumption which we measure -using [Cube Consumption Units](#cube-consumption-unit) in 5 minute intervals. -Each [product tier](#product-tiers) has different features and functionality -that you should review as you think about what is right for your business. - -## Cube Consumption Unit - -_Cube Consumption Unit_ (CCU) is a way to measure resource consumption -used to run Cube Cloud infrastructure and [resources](#resources) within it. - -The price of a CCU is determined by the [product tier](#product-tiers) you're subscribed to. -Each product tier determines the features, scalability, availability, as well as -the [speed and scope of support][ref-support] you may receive for your deployment. - -You can also set [Budgets][ref-cloud-budgets] to make sure you know your usage -is on track and as expected. - -[ref-cloud-budgets]: /product/workspace/budgets - -## Payment plans - -Payment plans determine whether you have a fixed-term contract or a recurring -subscription: - -* _On-demand payment plan_ allows you to subscribe at any time, add your credit -card, and start using Cube Cloud right away. [Starter](#starter) and [Premium](#premium) -product tiers are available on the on-demand payment plan. -* _Commit payment plan_ allows you to have a contract with a CCU amount specified -in an order form. [Premium](#premium), [Enterprise](#enterprise), and -[Enterprise Premier](#enterprise-premier) product tiers are available on the -commit payment plan. [Contact us][link-contact-us] to learn more. - -## Product tiers - -### Free - -**Free product tier is designed for development and testing purposes.** It is not -intended for production use. - -It offers up to two [Development Instances][ref-cloud-deployment-dev-instance]. - -You can review its [support terms][ref-free-tier-support] and [limits][ref-cloud-limits]. - -### Starter - -**Starter product tier targets low-scale production that is not business-critical.** - -It offers a [Production Cluster][ref-cloud-deployment-prod-cluster], the ability -to use third-party packages from the npm registry, AWS and GCP support in select -regions, pre-aggregations of up to 150GB in size, auto-suspend controls, and -[Semantic Layer Sync][ref-sls] with a single BI tool (such as Preset or Metabase). - -You can review its [pricing][cube-pricing], [support -terms][ref-starter-tier-support], and [limits][ref-cloud-limits]. - -### Premium - -**Premium product tier is designed for basic small-scale production deployments.** - -It offers everything in the [Starter product tier](#starter) as well as enabling -the use of [Production Multi-Clusters][ref-cloud-deployment-prod-multicluster], -support for [custom domains][ref-cloud-custom-domains], AWS and GCP support -in all regions. Cube Cloud provides a 99.95% uptime SLA for this product tier. - -You can review its [pricing][cube-pricing], [support -terms][ref-premium-tier-support], and [limits][ref-cloud-limits]. - -### Enterprise - -**Enterprise product tier is suitable for high-scale or mission-critical production -deployments with more significant security and compliance needs.** - -It offers everything in the [Premium product tier](#premium) as well as [Semantic Layer -Sync][ref-sls] with unlimited supported BI tools, SAML 2.0 -support for [single sign-on][ref-sso], Azure support for all regions, [dedicated -infrastructure][ref-dedicated-infra], [VPC peering][ref-cloud-vpc-peering], -[monitoring integrations][ref-monitoring-integrations], and [role-based access -control][ref-cloud-acl]. Cube Cloud provides a 99.99% uptime SLA for this product tier. - -You can review its [pricing][cube-pricing], [support -terms][ref-enterprise-tier-support], and [limits][ref-cloud-limits]. - -### Enterprise Premier - -**Enterprise Premier product tier caters to high-scale, high-availability -mission-critical production deployments with security and compliance needs.** - -It offers everything in the [Enterprise product tier](#enterprise) as well as -unlimited pre-aggregation sizes, and support for kSQL and Elasticsearch. Cube -Cloud provides a 99.995% uptime SLA for this product tier. - -You can review its [pricing][cube-pricing], [support -terms][ref-enterprise-premier-tier-support], and [limits][ref-cloud-limits]. - -## Resources - -The following resource types incur CCU consumption and apply to _individual resources_ -of deployments within a Cube Cloud account. The consumption is measured in 5-minute intervals. - -| Resource type | CCUs per hour | Notes | -| --- | :---: | --- | -| [Production Cluster][ref-production-cluster] | 4..8 | Depends on a [chosen tier](#deployment-tiers) | -| [Development Instance][ref-development-instance] | 1..2 | Depends on a [chosen tier](#deployment-tiers) | -| Cube API Instance | 1..2 | Depends on a [chosen tier](#deployment-tiers) | -| Cube Store Worker | 1..2 | Depends on a [chosen tier](#cube-store-worker-tiers) | -| [Semantic Catalog][ref-semantic-catalog] | 2..4 | Depends on a [chosen tier](#semantic-catalog-tiers) | -| [Query History][ref-query-history] | 0..20 | Depends on a [chosen tier](#query-history-tiers) | -| [Monitoring Integrations][ref-monitoring-integrations] | 1..4 | Depends on a [chosen tier](#monitoring-integrations-tiers) | - -The following resource types incur CCU consumption and apply to the _whole Cube Cloud -account_: - -| Resource type | CCUs per hour | Notes | -| --- | :---: | --- | -| [Dedicated infrastructure][ref-dedicated-infra] | 3 | — | -| [Audit Log][ref-audit-log] | 4..6 | Depends on the [chosen tier](#audit-log-tiers) | - -The following resource types incur cost and apply to the _whole Cube Cloud account_: - -| Resource type | Cost per month | Notes | -| --- | :---: | --- | -| [AI tokens](#ai-tokens) | Varies | Depends on the number of tokens used | - -### Deployment tiers - -[Production clusters][ref-production-cluster] (including individual API instances) -and [development instances][ref-development-instance] are involved in serving -requests through [APIs & integrations][ref-apis] under the following tiers: - -| Tier | CCUs per hour | CPU and memory | Dependent features | -| ---- | :--- | --- | --- | -| S | 4 — _for Production Cluster_
1 — _for Development Instance_
1 — _for Cube API Instance_ | 100% | — | -| M | 8 — _for Production Cluster_
2 — _for Development Instance_
2 — _for Cube API Instance_ | 200% | [DAX API][ref-dax-api], [MDX API][ref-mdx-api] | - -You can upgrade to a chosen tier in the -Settings of your deployment. -Upgrading to the M tier is only available on [Enterprise and above][cube-pricing] product tiers. - -### Cube Store Worker tiers - -[Cube Store workers][ref-cube-store-architecture] are involved in building -pre-aggregations and executing queries against them under the following tiers: - -| Tier | CCUs per hour | Throughput | Dependent features | -| ---- | :-----------: | ---------- | ------------------ | -| S | 1 | 100% | — | -| M | 2 | 200% | [Data-at-rest encryption][ref-data-at-rest-encryption] with [customer-managed keys][ref-customer-managed-keys] in Cube Store | - -You can upgrade to a chosen tier in the -Settings of your deployment. - -### Semantic Catalog tiers - -[Semantic Catalog][ref-semantic-catalog] provides observability into other data -tools interoperating with your data model under the following tiers: - -| Tier | CCUs per hour | Data assets | -| ---- | :-----------: | ---------- | -| S | 2 | Up to 30,000 | -| M | 4 | Up to 100,000 | - -You can upgrade to a chosen tier in the -Settings of your deployment. - -### Query History tiers - -[Query History][ref-query-history] and [Performance Insights][ref-performance-insights] -features analyze and visualize the data available under the following tiers: - -| Tier | CCUs per hour | API requests | Data retention | -| ---- | :-----------: | ------------------- | -------------- | -| XS | 0 | Up to 50,000/day | 1 day | -| S | 2 | Up to 100,000/day | 7 days | -| M | 5 | Up to 250,000/day | 14 days | -| L | 10 | Up to 500,000/day | 21 days | -| XL | 20 | Up to 1,000,000/day | 30 days | - -You can upgrade to a chosen tier in the -Settings of your deployment. - -### Monitoring Integrations tiers - -[Monitoring Integrations][ref-monitoring-integrations] feature has the following tiers: - -| Tier | CCUs per hour | Exported data | Dependent features | -| ---- | :-----------: | -------------- | --- | -| XS | 1 | Up to 10 GB/mo | — | -| S | 2 | Up to 25 GB/mo | — | -| M | 4 | Up to 50 GB/mo | [Query History export][ref-query-history-export] | - -You can [upgrade][ref-monitoring-integrations-config] to a chosen tier in the -Settings of your deployment. - -### Audit Log tiers - -[Audit Log][ref-audit-log] collects, stores, and displays security-related events -under the following tiers: - -| Tier | CCUs per hour | Dependent features | -| ---- | :------------------------: | ------------------ | -| S | 4 | — | -| M | 6 | Audit Log data export | - -### AI tokens - -The price of AI tokens is passed through from the underlying AI service provider without -any markup. The cost depends on the number of tokens processed by your Cube Cloud account -when using AI features. - -You can control the const by setting the token limit on the Billing page of -your Cube Cloud account. When the limit is [reached](#token-limit-exceeded), you can -increase it to continue using AI features. - -## Total cost examples - -The following examples provide insight into the total cost to use Cube Cloud: -- [Small-scale deployment](#small-scale-deployment) (production cluster, Premium product tier, S deployment tier). -- [Medium-scale deployment](#medium-scale-deployment) (production cluster with auto-scaling, Enterprise product tier, S deployment tier). -- [Large-scale deployment](#large-scale-deployment) (production multi-cluster with dedicated infrastructure, Enterprise product tier, M deployment tier). - -### Small-scale deployment - -Suppose a company uses Cube Cloud to power self-serve business intelligence for -a couple of teams in Eastern and Pacific time zones. - -This organization: -* Uses the Premium product tier of Cube Cloud. -* Runs a single Production Cluster (S tier) that is active 24/7 but never has to auto-scale -its API instances because the usage is spread evenly with no bursts. -* Operates on a small volume of data that requires the usage of just 2 Cube Store -Workers to run queries and refresh pre-aggregations mostly during working hours, -being active approximately 50% of the time. -* Updates its data model infrequently and without using a dedicated Development -Instance for testing purposes, with 2 data engineers spending just 1 hour a day each, -in the development mode of the Production Cluster. - -| Resource | Usage per month | CCU per month | -| ----------------------------------------------- | --------------------------------------------------------- | --------------------------------------------------- | -| Production Cluster | 1 Production Cluster ×
24 hours per day ×
30 days | 720 hours ×
4 CCUs per hour =
**2880 CCUs** | -| Additional Cube API Instance | — | — | -| Cube Store Worker | 2 Cube Store Workers ×
12 hours per day ×
30 days | 720 hours ×
1 CCU per hour =
**720 CCUs** | -| Development Instance | — | — | -| Development Instance
(for development mode) | 2 users ×
1 hour per day ×
30 days | 60 hours ×
1 CCU per hour =
**60 CCUs** | -| **Total** | | **3660 CCUs** | - -### Medium-scale deployment - -Suppose a company with a globally distributed workforce uses Cube Cloud to enable self-serve -exploration in multiple BI tools and AI agents; it also uses Cube Cloud to power embedded -analytics in its SaaS platform that caters to a vast worldwide customer base. - -This organization: -* Uses the Enterprise product tier of Cube Cloud. -* Runs two Production Clusters (S tier) that are active 24/7 and auto-scale up to 8 API instances -during a peak hour every day. -* Operates on a moderate volume of data that requires the usage of 4 Cube Store -Workers by both Production Clusters to run queries and refresh pre-aggregations 24/7, -being active approximately 50% of the time. -* Uses a dedicated Development Instance (S tier) for testing purposes that is active 12 hours a day. -* Has a team of 5 data engineers who frequently update the data model, with each data engineer -spending about 4 hours a day in the development mode of the dedicated Development Instance. - -| Resource | Usage per month | CCU per month | -| ----------------------------------------------- | ------------------------------------------------------------------------------------- | ---------------------------------------------------- | -| Production Cluster | 2 Production Clusters ×
24 hours per day ×
30 days | 1440 hours ×
4 CCUs per hour =
**5760 CCUs** | -| Additional Cube API Instance | 2 Production Clusters ×
(8 – 2) API Instances ×
1 hour per day ×
30 days | 360 hours ×
1 CCU per hour =
**360 CCUs** | -| Cube Store Worker | 2 Production Clusters ×
4 Cube Store Workers ×
12 hours per day ×
30 days | 2880 hours ×
1 CCU per hour =
**2880 CCUs** | -| Development Instance | 1 Development Instance ×
12 hours per day ×
30 days | 360 hours ×
1 CCU per hour =
**360 CCUs** | -| Development Instance
(for development mode) | 5 users ×
4 hours per day ×
30 days | 600 hours ×
1 CCU per hour =
**600 CCUs** | -| **Total** | | **9960 CCUs** | - -### Large-scale deployment - -Suppose a company uses Cube Cloud as a mission-critical part of their infrastructure to enable -its globally distributed workforce, customer base, and (or) partners to operate at scale. - -This organization: -* Uses the Enterprise product tier of Cube Cloud. -* Uses [dedicated infrastructure][ref-dedicated-infra]. -* Runs a Production Multi-Cluster that is active 24/7, includes 3 Production Clusters (M tier), with each -Production Cluster auto-scaling up to 10 API instances during a few peak hours every day. -* Operates on a large volume of data that requires the usage of 16 Cube Store Workers to run -queries and refresh pre-aggregations 24/7, being active approximately 50% of the time. -* Uses a dedicated Development Instance (M tier) for testing purposes that is active 24 hours a day. -* Has a team of 10 data engineers who frequently update the data model, with each data engineer -spending about 4 hours a day in the development mode of the dedicated Development Instance. -* Uses a [Query History tier](#query-history-tiers) with 14-day data retention to inform the work -of data engineers. - -| Resource | Usage per month | CCU per month | -| ----------------------------------------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------- | -| Dedicated infrastructure | 1 region ×
24 hours per day ×
30 days | 720 hours ×
3 CCUs per hour =
**2160 CCUs** | -| Production Multi-Cluster | 3 Production Clusters ×
24 hours per day ×
30 days | 2160 hours ×
8 CCUs per hour =
**17280 CCUs** | -| Additional Cube API Instance | 3 Production Clusters ×
(10 – 2) API Instances ×
4 hours per day ×
30 days | 2880 hours ×
2 CCU per hour =
**5760 CCUs** | -| Cube Store Worker | 1 Production Multi-Cluster ×
16 Cube Store Workers ×
12 hours per day ×
30 days | 5760 hours ×
1 CCU per hour =
**5760 CCUs** | -| Development Instance | 1 Development Instance ×
24 hours per day ×
30 days | 720 hours ×
2 CCU per hour =
**1440 CCUs** | -| Development Instance
(for development mode) | 10 users ×
4 hours per day ×
30 days | 1200 hours ×
2 CCU per hour =
**2400 CCUs** | -| Query History (M tier) | 24 hours per day ×
30 days | 720 hours ×
5 CCUs per hour =
**3600 CCUs** | -| **Total** | | **38400 CCUs** | - -## Payment terms - -### Upgrades - -You may upgrade your CCUs to a higher-level product tier at any time by -paying the difference in per-Cube Consumption Unit pricing, or by asking to convert -the price paid for the remaining CCUs into CCUs for the higher product tier -at the CCU pricing for that product tier (resulting in a lower number of available CCUs -but upgraded to the higher product tier). - -### Terms - -If payment is not received within the contract terms (usually Net-30) or for -additional required payment for CCUs exceeding the balance of CCUs in your -account, services may degrade or be suspended until new CCUs are purchased. - -Future purchases and upgrades are subject to the pricing that is in effect at -the time of the order. No credit is allowed for downgrading CCUs to a lower -product tier level. Payments are non-refundable. - -## Troubleshooting - -### `Token limit exceeded` - -[On-demand](#payment-plans) customers may encounter the following error when their AI -usage exceeds the limit set for their Cube Cloud account: `Token limit exceeded. Please -purchase or allocate more tokens.` - -To resolve this issue, a user with administrative permissions needs to increase the limit -for the AI token consumption at the Billing page of their Cube Cloud account. - - - -[cube-pricing]: https://cube.dev/pricing -[link-contact-us]: https://cube.dev/contact -[ref-cloud-deployment-dev-instance]: - /product/deployment/cloud/deployment-types#development-instance -[ref-cloud-deployment-prod-cluster]: - /product/deployment/cloud/deployment-types#production-cluster -[ref-cloud-limits]: /product/deployment/cloud/limits -[ref-monitoring-integrations]: /product/monitoring/integrations -[ref-monitoring-integrations-config]: /product/workspace/monitoring#configuration -[ref-cloud-acl]: /product/administration/users-and-permissions/custom-roles -[ref-cloud-deployment-prod-multicluster]: - /product/deployment/cloud/deployment-types#production-multi-cluster -[ref-cloud-custom-domains]: /product/deployment/cloud/custom-domains -[ref-cloud-vpc-peering]: /product/deployment/cloud/vpc -[ref-sls]: /product/apis-integrations/semantic-layer-sync -[ref-support]: /product/deployment/cloud/support -[ref-free-tier-support]: /product/deployment/cloud/support#free -[ref-starter-tier-support]: /product/deployment/cloud/support#starter -[ref-premium-tier-support]: /product/deployment/cloud/support#premium -[ref-enterprise-tier-support]: /product/deployment/cloud/support#enterprise -[ref-enterprise-premier-tier-support]: /product/deployment/cloud/support#enterprise-premier -[ref-query-history]: /product/workspace/query-history -[ref-performance-insights]: /product/workspace/performance -[ref-audit-log]: /product/workspace/audit-log -[ref-dedicated-infra]: /product/deployment/cloud/infrastructure#dedicated-infrastructure -[ref-sso]: /product/workspace/sso -[ref-production-cluster]: /product/deployment/cloud/deployment-types#production-cluster -[ref-development-instance]: /product/deployment/cloud/deployment-types#development-instance -[ref-apis]: /product/apis-integrations -[ref-mdx-api]: /product/apis-integrations/mdx-api -[ref-dax-api]: /product/apis-integrations/dax-api -[ref-cube-store-architecture]: /product/caching/running-in-production#architecture -[ref-data-at-rest-encryption]: /product/caching/running-in-production#data-at-rest-encryption -[ref-customer-managed-keys]: /product/workspace/encryption-keys -[ref-semantic-catalog]: /product/workspace/semantic-catalog -[ref-query-history-export]: /product/workspace/monitoring#query-history-export \ No newline at end of file diff --git a/docs/pages/product/administration/deployment/providers.mdx b/docs/pages/product/administration/deployment/providers.mdx deleted file mode 100644 index dfce3f21401f2..0000000000000 --- a/docs/pages/product/administration/deployment/providers.mdx +++ /dev/null @@ -1,49 +0,0 @@ -# Cloud providers in Cube Cloud - -Cube Cloud works with all three major cloud providers: - -- [Amazon Web Services](https://aws.amazon.com) (AWS) -- [Google Cloud Platform](https://cloud.google.com) (GCP) -- [Microsoft Azure](https://azure.microsoft.com) - - - -AWS and GCP are available in Cube Cloud on [all product tiers](https://cube.dev/pricing). -Azure is only available on [Enterprise and above](https://cube.dev/pricing) product tiers. -[Contact us](https://cube.dev/contact) for details. - - - -## Regions - -You can create [deployments][ref-deployments] in any available shared region of any provider. - -You can also use [dedicated infrastructure][ref-dedicated-infra] in a region of -your choice and use [VPC peering][ref-vpc]. - -## Services - -See provider-specific pages for a list of services Cube Cloud integrates with. - - - - - - - - -[ref-deployments]: /product/deployment/cloud/deployments -[ref-vpc]: /product/deployment/cloud/vpc -[ref-dedicated-infra]: /product/deployment/cloud/infrastructure#dedicated-infrastructure \ No newline at end of file diff --git a/docs/pages/product/administration/deployment/providers/_meta.js b/docs/pages/product/administration/deployment/providers/_meta.js deleted file mode 100644 index 9864216b0c2e2..0000000000000 --- a/docs/pages/product/administration/deployment/providers/_meta.js +++ /dev/null @@ -1,5 +0,0 @@ -module.exports = { - "aws": "AWS", - "gcp": "GCP", - "azure": "Azure" -} \ No newline at end of file diff --git a/docs/pages/product/administration/deployment/providers/aws.mdx b/docs/pages/product/administration/deployment/providers/aws.mdx deleted file mode 100644 index a703a6ed682de..0000000000000 --- a/docs/pages/product/administration/deployment/providers/aws.mdx +++ /dev/null @@ -1,48 +0,0 @@ -# Integrating with services on AWS - -Cube Cloud works with numerious services available on -[Amazon Web Services](https://aws.amazon.com) (AWS). -This page provides a non-exhaustive lists of these services. - - - -[Contact us](https://cube.dev/contact) if you have questions about Cube Cloud integration with a particular service. - - - -## Data sources - -Cube Cloud integrates with the following [data sources](/product/configuration/data-sources): - -- [Amazon Redshift](/product/configuration/data-sources/aws-redshift) -- [Amazon Athena](/product/configuration/data-sources/aws-athena) -- [Postgres](/product/configuration/data-sources/postgres), [Microsoft SQL Server](/product/configuration/data-sources/ms-sql), [MySQL](/product/configuration/data-sources/mysql), and [Oracle](/product/configuration/data-sources/oracle) on [Amazon RDS](https://aws.amazon.com/rds/) -- [Hive / SparkSQL](/product/configuration/data-sources/hive), [Presto](/product/configuration/data-sources/presto), and [Trino](/product/configuration/data-sources/trino) on [Amazon EMR](https://aws.amazon.com/emr/) -- [Elasticsearch](/product/configuration/data-sources/elasticsearch) on [Amazon OpenSearch Service](https://aws.amazon.com/opensearch-service/) -- [Parquet, CSV, and JSON files](/product/configuration/data-sources/duckdb) on [Amazon S3](https://aws.amazon.com/s3/) - -## Data visualization tools - -Cube Cloud integrates with the following [data visualization tools](/product/configuration/visualization-tools): - -- [Amazon QuickSight](https://aws.amazon.com/quicksight/) via [SQL API](/product/apis-integrations/sql-api) - -## Storage - -[Amazon S3](https://aws.amazon.com/s3/) can be used as storage for [export buckets](/product/caching/using-pre-aggregations#export-bucket) and [pre-aggregations](/product/caching/using-pre-aggregations). - -## Compute - -[Amazon EC2](https://aws.amazon.com/ec2/) can be used as compute for [deployments](/product/deployment/cloud/deployments). - -## Authentication - -[Amazon Cognito](https://aws.amazon.com/pm/cognito/) can be used for [authentication of API requests](/product/auth/recipes/aws-cognito). - -## Monitoring - -[Amazon CloudWatch](https://aws.amazon.com/cloudwatch/) and [Amazon S3](https://aws.amazon.com/s3/) can be used as destinations for [monitoring integrations](/product/workspace/monitoring). - -## Networking - -[Amazon VPC](https://aws.amazon.com/vpc/) can be used for [secure networking](/product/deployment/cloud/vpc/aws). \ No newline at end of file diff --git a/docs/pages/product/administration/deployment/providers/azure.mdx b/docs/pages/product/administration/deployment/providers/azure.mdx deleted file mode 100644 index 088861e381be4..0000000000000 --- a/docs/pages/product/administration/deployment/providers/azure.mdx +++ /dev/null @@ -1,59 +0,0 @@ -# Integrating with services on Azure - -Cube Cloud works with numerious services available on -[Microsoft Azure](https://azure.microsoft.com). -This page provides a non-exhaustive lists of these services. - - - -[Contact us](https://cube.dev/contact) if you have questions about Cube Cloud integration with a particular service. - - - -## Data sources - -Cube Cloud integrates with the following [data sources](/product/configuration/data-sources): - -- [Microsoft Fabric](/product/configuration/data-sources/ms-fabric) -- [Microsoft SQL Server](/product/configuration/data-sources/ms-sql) on [Azure SQL](https://azure.microsoft.com/en-us/products/azure-sql) -- [Postgres](/product/configuration/data-sources/postgres) on [Azure Database for PostgreSQL](https://azure.microsoft.com/en-us/products/postgresql/) -- [MySQL](/product/configuration/data-sources/mysql) on [Azure Database for MySQL](https://azure.microsoft.com/en-us/products/mysql/) - -## Data visualization tools - -Cube Cloud integrates with the following [data visualization tools](/product/configuration/visualization-tools): - -- [Microsoft Power BI][ref-powerbi] via the [DAX API][ref-dax-api] -- [Microsoft Excel][ref-excel] via the [MDX API][ref-mdx-api] and -[Cube Cloud for Excel][ref-cube-cloud-for-excel] - -## Storage - -[Azure Blob Storage](https://azure.microsoft.com/en-us/products/storage/blobs) can be used as storage for [export buckets](/product/caching/using-pre-aggregations#export-bucket) and [pre-aggregations](/product/caching/using-pre-aggregations). - -## Compute - -[Azure Virtual Machines](https://azure.microsoft.com/en-gb/products/virtual-machines/) can be used as compute for [deployments](/product/deployment/cloud/deployments). - -## Authentication - -[Microsoft Entra ID](https://www.microsoft.com/en-us/security/business/identity-access/microsoft-entra-id) can be used for authentication of API requests. - -## Single sign-on - -[Microsoft Entra ID](https://www.microsoft.com/en-us/security/business/identity-access/microsoft-entra-id) can be used for [single sign-on](/product/workspace/sso/microsoft-entra-id). - -## Monitoring - -[Azure Monitor](https://azure.microsoft.com/en-us/products/monitor) and [Azure Blob Storage](https://azure.microsoft.com/en-us/products/storage/blobs) can be used as destinations for [monitoring integrations](/product/workspace/monitoring). - -## Networking - -[Azure Virtual Network](https://azure.microsoft.com/en-us/products/virtual-network) can be used for [secure networking](/product/deployment/cloud/vpc/azure). - - -[ref-powerbi]: /product/configuration/visualization-tools/powerbi -[ref-dax-api]: /product/apis-integrations/dax-api -[ref-excel]: /product/configuration/visualization-tools/excel -[ref-mdx-api]: /product/apis-integrations/mdx-api -[ref-cube-cloud-for-excel]: /product/apis-integrations/microsoft-excel \ No newline at end of file diff --git a/docs/pages/product/administration/deployment/providers/gcp.mdx b/docs/pages/product/administration/deployment/providers/gcp.mdx deleted file mode 100644 index 8f6326e05ea4c..0000000000000 --- a/docs/pages/product/administration/deployment/providers/gcp.mdx +++ /dev/null @@ -1,50 +0,0 @@ -# Integrating with services on GCP - -Cube Cloud works with numerious services available on -[Google Cloud Platform](https://cloud.google.com) (GCP). -This page provides a non-exhaustive lists of these services. - - - -[Contact us](https://cube.dev/contact) if you have questions about Cube Cloud integration with a particular service. - - - -## Data sources - -Cube Cloud integrates with the following [data sources](/product/configuration/data-sources): - -- [Google BigQuery](/product/configuration/data-sources/google-bigquery) -- [Postgres](/product/configuration/data-sources/postgres), [Microsoft SQL Server](/product/configuration/data-sources/ms-sql), [MySQL](/product/configuration/data-sources/mysql) on [Google Cloud SQL](https://cloud.google.com/sql) -- [Hive / SparkSQL](/product/configuration/data-sources/hive), [Presto](/product/configuration/data-sources/presto), and [Trino](/product/configuration/data-sources/trino) on [Google Dataproc](https://cloud.google.com/dataproc) -- [Parquet, CSV, and JSON files](/product/configuration/data-sources/duckdb) on [Google Cloud Storage](https://cloud.google.com/storage) - -## Data visualization tools - -Cube Cloud integrates with the following [data visualization tools](/product/configuration/visualization-tools): - -- [Looker Studio](https://cloud.google.com/looker-studio) via [SQL API](/product/apis-integrations/sql-api) - -## Storage - -[Google Cloud Storage](https://cloud.google.com/storage) can be used as storage for [export buckets](/product/caching/using-pre-aggregations#export-bucket) and [pre-aggregations](/product/caching/using-pre-aggregations). - -## Compute - -[Google Compute Engine](https://cloud.google.com/products/compute) can be used as compute for [deployments](/product/deployment/cloud/deployments). - -## Authentication - -[Google Identity Platform](https://cloud.google.com/security/products/identity-platform) can be used for authentication of API requests. - -## Single sign-on - -[Google Workspace](https://workspace.google.com) can be used for [single sign-on](/product/workspace/sso/google-workspace). - -## Monitoring - -[Google Cloud Logging](https://cloud.google.com/logging), [Google Cloud Monitoring](https://cloud.google.com/monitoring), and [Google Cloud Storage](https://cloud.google.com/storage) can be used as destinations for [monitoring integrations](/product/workspace/monitoring). - -## Networking - -[Google VPC](https://cloud.google.com/vpc) can be used for [secure networking](/product/deployment/cloud/vpc/gcp). \ No newline at end of file diff --git a/docs/pages/product/administration/deployment/support.mdx b/docs/pages/product/administration/deployment/support.mdx deleted file mode 100644 index c5a5f71e11b0c..0000000000000 --- a/docs/pages/product/administration/deployment/support.mdx +++ /dev/null @@ -1,114 +0,0 @@ -# Support in Cube Cloud - -Cube Cloud [product tiers][ref-cloud-pricing] include different levels of support -in terms of speed and scope that you should review as you think about what is -right for your business. - -## Support by product tiers - -### Free - -* [Free product tier][ref-free-tier] offers support via **online resources** such as -[documentation][ref-docs-intro], [webinars][cube-webinars], and [community -Slack][cube-slack]. - -### Starter - -* [Starter product tier][ref-starter-tier] includes support via **online resources** such as -[documentation][ref-docs-intro], [webinars][cube-webinars], and [community -Slack][cube-slack]. -* You can also connect with our support team during [support hours](#support-hours) -with **2 support tickets per month** through the in-product chat feature. - -### Premium - -* [Premium product tier][ref-premium-tier] includes support via **online resources** such as -[documentation][ref-docs-intro], [webinars][cube-webinars], and [community -Slack][cube-slack]. -* It also includes **either 4 support tickets per month** (self-serve customers) -or **unlimited support tickets** (customers with an annual commit) for our support engineers during -[support hours](#support-hours) through our in-product chat. - -| Priority | Response time during support hours | -| -------- | ---------------------------------- | -| P0 | 60 minutes | -| P1 | 4 hours | -| P2 | 8 business hours | -| P3 | 2 business days | - -### Enterprise - -* [Enterprise product tier][ref-enterprise-tier] includes support via **online resources** such as -[documentation][ref-docs-intro], [webinars][cube-webinars], and [community -Slack][cube-slack]. -* It also includes **unlimited support tickets** for our support engineers during -[support hours](#support-hours) through our in-product chat with faster -response times as compared to the [Premium product tier](#premium-support). - -| Priority | Response Time during Support Hours | -| -------- | ---------------------------------- | -| P0 | 30 minutes | -| P1 | 2 hours | -| P2 | 8 business hours | -| P3 | 2 business days | - -* Enterprise product tier also includes a **dedicated customer success manager** (CSM) -who will provide quarterly reviews, sharing new features and training as well -as usage and optimization advice. - -### Enterprise Premier - -* [Enterprise Premier product tier][ref-enterprise-premier-tier] includes support via **online resources** such as -[documentation][ref-docs-intro], [webinars][cube-webinars], and [community -Slack][cube-slack]. -* It also includes **unlimited support tickets** for our support engineers during -[support hours](#support-hours) through our in-product chat with faster -response times as compared to the [Enterprise product tier](#enterprise-support). - -| Priority | Response time during support hours | -| -------- | ---------------------------------- | -| P0 | 15 minutes | -| P1 | 1 hour | -| P2 | 8 business hours | -| P3 | 2 business days | - -* Enterprise Premier product tier also includes a **dedicated customer success manager** (CSM) -who will provide quarterly reviews, sharing new features and training as well -as usage and optimization advice. - -## Support hours - -Official support hours are weekdays (Monday through Friday) from 8am ET to 8pm -ET. The above response times are only during support hours. - -## Support priority definitions - -We prioritize support requests based on their severity, as follows: - -- **P0**: The platform is severely impacted or completely shut down. We will - assign specialists to work continuously to fix the issue, provide ongoing - updates, and start working on a temporary workaround or fix. - -- **P1**: The platform is functioning with limited capabilities or facing - critical issues preventing a production deployment. We will assign specialists - to fix the issue, provide ongoing updates, and start working on a temporary - workaround or fix. - -- **P2**: There are issues with workaround solutions or non-critical functions. - We will use resources during local business hours until the issue is resolved - or a workaround is in place. - -- **P3**: There is a need for clarification in the documentation, or a - suggestion for product enhancement. We will triage the request, provide - clarification when possible, and may include a resolution in a future update. - - -[ref-docs-intro]: /product/introduction -[cube-webinars]: https://cube.dev/events -[cube-slack]: https://slack.cube.dev -[ref-cloud-pricing]: /product/deployment/cloud/pricing -[ref-free-tier]: /product/deployment/cloud/pricing#free -[ref-starter-tier]: /product/deployment/cloud/pricing#starter -[ref-premium-tier]: /product/deployment/cloud/pricing#premium -[ref-enterprise-tier]: /product/deployment/cloud/pricing#enterprise -[ref-enterprise-premier-tier]: /product/deployment/cloud/pricing#enterprise-premier diff --git a/docs/pages/product/administration/deployment/vpc.mdx b/docs/pages/product/administration/deployment/vpc.mdx deleted file mode 100644 index 61b4e099f64ce..0000000000000 --- a/docs/pages/product/administration/deployment/vpc.mdx +++ /dev/null @@ -1,37 +0,0 @@ -# Connecting with a VPC in Cube Cloud - -For improved stability and security, Cube Cloud supports connecting to one or -more VPCs (virtual private clouds) in your Azure, AWS, or GCP accounts. - - - -VPC connectivity requires [dedicated infrastructure][ref-dedicated-infra] -and is available in Cube Cloud on -[Enterprise and above](https://cube.dev/pricing) product tiers. - - - -VPC connection improves stability through dedicated infrastructure for a -deployment and improves security by preventing your database traffic from being -routed through the public internet. - - - - - - - - -[ref-dedicated-infra]: /product/deployment/cloud/infrastructure#dedicated-infrastructure diff --git a/docs/pages/product/administration/deployment/vpc/_meta.js b/docs/pages/product/administration/deployment/vpc/_meta.js deleted file mode 100644 index 9864216b0c2e2..0000000000000 --- a/docs/pages/product/administration/deployment/vpc/_meta.js +++ /dev/null @@ -1,5 +0,0 @@ -module.exports = { - "aws": "AWS", - "gcp": "GCP", - "azure": "Azure" -} \ No newline at end of file diff --git a/docs/pages/product/administration/deployment/vpc/aws.mdx b/docs/pages/product/administration/deployment/vpc/aws.mdx deleted file mode 100644 index de84164fbb345..0000000000000 --- a/docs/pages/product/administration/deployment/vpc/aws.mdx +++ /dev/null @@ -1,15 +0,0 @@ -# Connecting with a VPC on AWS - -[Dedicated infrastructure][dedicated-infrastructure] in Cube Cloud comes with -an option of setting up a direct network connection between -an AWS VPC on the Cube Cloud side and your own VPC(s). Such a connection allows you to -access internal datasources without the need to expose any ports publicly. - -On AWS, Cube Cloud supports two main ways of establishing a private network connection: - -- [AWS PrivateLink][aws-private-link] -- [VPC Peering][aws-vpc-peering] - -[dedicated-infrastructure]: /product/deployment/cloud/infrastructure#dedicated-infrastructure -[aws-private-link]: /product/deployment/cloud/vpc/aws/private-link -[aws-vpc-peering]: /product/deployment/cloud/vpc/aws/vpc-peering diff --git a/docs/pages/product/administration/deployment/vpc/aws/_meta.js b/docs/pages/product/administration/deployment/vpc/aws/_meta.js deleted file mode 100644 index bbcdaa6c8a3e3..0000000000000 --- a/docs/pages/product/administration/deployment/vpc/aws/_meta.js +++ /dev/null @@ -1,4 +0,0 @@ -module.exports = { - "private-link": "PrivateLink", - "vpc-peering": "VPC Peering", - } \ No newline at end of file diff --git a/docs/pages/product/administration/deployment/vpc/azure/_meta.js b/docs/pages/product/administration/deployment/vpc/azure/_meta.js deleted file mode 100644 index a8d1280ad1997..0000000000000 --- a/docs/pages/product/administration/deployment/vpc/azure/_meta.js +++ /dev/null @@ -1,4 +0,0 @@ -module.exports = { - "private-link": "Private Link", - "vpc-peering": "VNet Peering", -} \ No newline at end of file diff --git a/docs/pages/product/administration/deployment/warm-up.mdx b/docs/pages/product/administration/deployment/warm-up.mdx deleted file mode 100644 index 820d5b9f8646c..0000000000000 --- a/docs/pages/product/administration/deployment/warm-up.mdx +++ /dev/null @@ -1,92 +0,0 @@ -# Deployment warm-up - -Deployment warm-up improves querying performance by executing time-consuming -tasks after a Cube Cloud deployment is spun up but before it's exposed to -requests from users. - - - -Deployment warm-up is available in Cube Cloud on -[Starter and above](https://cube.dev/pricing) product tiers. - - - - - -Deployment warm-up is only available for [production cluster][ref-prod-cluster] -and [production multi-cluster][ref-prod-multi-cluster] deployments. - - - -There are two warm-up options: - -* [Data model warm-up](#data-model-warm-up) — compiles the data model and -populates data model compilation cache ahead of time. -* [Pre-aggregation warm-up](#pre-aggregation-warm-up) — builds and refreshes -pre-aggregations ahead of time. - -## Data model warm-up - -By default, an API instance compiles the [data model][ref-data-model] and -stores results in the data model compilation cache when the first request hits -that API instance. For [multi-tenant][ref-multitenancy] configurations, a -request from a particular tenant would only trigger the data model compilation -for that tenant. - -Depending on the complexity of the data model (i.e., the number of cubes, -views, and their members) and the use of [dynamic data models][ref-dynamic-data-model], -its compilation might take from a few milliseconds to a few seconds. - -Data-model warm-up will compile the data model before a Cube Cloud deployment -is exposed to requests from users, making sure that they aren't affected by -the data model compilation time. - - - -If a data model warm-up takes more than 15 minutes, the deployment will be -considered unhealthy and rolled back. - - - -### Configuring data model warm-up - -To configure data model warm-up, navigate to Settings → Configuration -and enable Warm-up data model before deploying API: - - - -## Pre-aggregation warm-up - -By default, the refresh worker takes care of [pre-aggregation][ref-pre-aggs] -refresh and runs pre-aggregation builds. When first requests hit API instances, -it's possible that pre-aggregations would still be being built and users would -need to wait or the completion of that process. - -Depending on the volume of data and the configuration of pre-aggregations, -their builds might take from seconds to minutes. - -Pre-aggregation warm-up will refresh pre-aggregations before a Cube Cloud -deployment is exposed to requests from users, making sure they aren't affected -by the pre-aggregation build time. - - - -If a pre-aggregation warm-up takes more than 24 hours, it will be cancelled. -However, the deployment will still succeed. - - - -### Configuring pre-aggregation warm-up - -To configure pre-aggregation warm-up, navigate to Settings → Configuration -and enable Warm-up pre-aggregations before deploying API: - - - - -[ref-prod-cluster]: /product/deployment/cloud/deployment-types#production-cluster -[ref-prod-multi-cluster]: /product/deployment/cloud/deployment-types#production-multi-cluster -[ref-data-model]: /product/data-modeling/overview -[ref-dynamic-data-model]: /product/data-modeling/dynamic -[ref-multitenancy]: /product/configuration/multitenancy -[ref-pre-aggs]: /product/caching#pre-aggregations \ No newline at end of file diff --git a/docs/pages/product/administration/distribution.mdx b/docs/pages/product/administration/distribution.mdx deleted file mode 100644 index e9412b2fbe17b..0000000000000 --- a/docs/pages/product/administration/distribution.mdx +++ /dev/null @@ -1,124 +0,0 @@ -# Distribution - -This page explains the difference between [Cube Core and Cube Cloud](#cube-core-and-cube-cloud), -provides links to ready-to-use [artifacts](#artifacts), and explains the -[versioning model](#versions) and the release cycle, including the [long-term -support](#long-term-support) (LTS). - -## Cube Core and Cube Cloud - -_Cube Core_ is the universal semantic layer, developed by [Cube Dev][link-company] -and the community in open source under a permissive [Apache License 2.0][link-license]. -You can find its [source code][link-repo] on GitHub. - -_Cube Cloud_ is the managed platform for Cube Core, developed by Cube Dev as a -[commercial product][link-pricing]. It includes everything from Cube Core and -provides additional semantic layer features, [managed infrastructure][ref-infrastructure] -and [workspace tools][ref-workspace]. - -_Cube_ can be used to refer to both products if the distinction is not important -in a particular case. - - - -All Cube Cloud-specific features are marked with similar green boxes throughout -this documentation. - - - -You are welcome to either [sign up for Cube Cloud][link-sign-up] and start using it -for free. You can also [self-host][ref-deployment] a Cube Core deployment. - -## Artifacts - -Cube Core is packaged and distributed as Docker images that you can run in a -containerized environment. You can find images for [Cube][link-dockerhub-cube] -and [Cube Store][link-dockerhub-cubestore] on Docker Hub. - -Note that Cube Store images support the `linux/amd64` architecture while Cube -images support both `linux/amd64` and `linux/arm64`. The latter is convenient for -Mac computers with [Apple silicon][link-apple-silicon] that you might use to run -Cube locally. - -Notably, the following tags are used with Docker images: -- `v1.1.0` and similar, one tag per each released version. -- `latest`, always pointing to the latest release. -- `dev`, always pointing to the bleeding-edge image built for the latest commit. - -## Versions - -Cube is actively developed, and new versions are released frequently. - -Versions mostly follow [SemVer][link-semver] principles, with the only exception -that breaking changes can happen both in _major_ and _minor_ versions. Before -upgrading, it is recommended that you check the [release notes][link-releases] -on GitHub and read [changelog entries][link-changelog] in the blog. - - - -You can find a list of currently [deprecated features][link-github-deprecation] on GitHub. -Usually, there are also deprecation notices in the documentation that look similar to this one. - - - -Additionally, Cube Cloud provides LTS or Regular [update -channels][ref-update-channels]. - -### Long-term support - -To provide guarantees for the long-term support of Cube Core, some minor releases -are designated as _long-term support (LTS) releases_. - - - -Check the [long-term support announcement][link-lts-accouncement] in the blog. - - - -For 12 months after being marked as LTS, these releases receive fixes for defects -that significantly impact stability and functionality as well as the security -fixes for critical vulnerabilities. It is recommended to use the latest patch -version within an LTS release. - -List of LTS releases: - -| Version | Status | End-of-life date | -| --- | --- | --- | -| `v1.4.x` | Active | October 29, 2026 | -| `v1.0.x` | End-of-life | October 29, 2025 | - -### Documentation - -The documentation at [cube.dev/docs](https://cube.dev/docs) always reflects the -latest released version. - -To obtain the documentation for a specific version: -* Clone the [GitHub repository](https://github.com/cube-js/cube) at the desired tag. -* Navigate to the `docs` folder and start a local documentation server. -* Open [localhost:3000](http://localhost:3000) in your browser. - -```sh -git clone --depth 1 --branch v1.5.0 https://github.com/cube-js/cube.git -cd cube/docs -yarn && yarn dev -open http://localhost:3000 -``` - - -[link-repo]: https://github.com/cube-js/cube -[link-license]: https://github.com/cube-js/cube/blob/master/LICENSE -[link-releases]: https://github.com/cube-js/cube/releases -[link-company]: https://cube.dev/about -[link-pricing]: https://cube.dev/pricing -[link-sign-up]: https://cubecloud.dev/auth/signup -[link-changelog]: https://cube.dev/blog/category/changelog -[link-lts-accouncement]: https://cube.dev/blog/introducing-long-term-support-lts-for-cube-core -[link-dockerhub-cube]: https://hub.docker.com/r/cubejs/cube/tags -[link-dockerhub-cubestore]: https://hub.docker.com/r/cubejs/cubestore/tags -[link-apple-silicon]: https://support.apple.com/en-us/116943 -[link-semver]: https://semver.org -[link-github-deprecation]: https://github.com/cube-js/cube/blob/master/DEPRECATION.md -[ref-infrastructure]: /product/administration/deployment/cloud -[ref-workspace]: /product/administration/workspace -[ref-deployment]: /product/administration/deployment -[ref-update-channels]: /product/administration/deployment/cloud/deployments#update-channels \ No newline at end of file diff --git a/docs/pages/product/administration/users-and-permissions.mdx b/docs/pages/product/administration/users-and-permissions.mdx deleted file mode 100644 index ee3c3fb5509b2..0000000000000 --- a/docs/pages/product/administration/users-and-permissions.mdx +++ /dev/null @@ -1,22 +0,0 @@ -# Users and permissions - -Manage users and control access to features and data in Cube Cloud. - - - -Users and permissions management is available in Cube Cloud. - - - -## Users and permissions - -Configure access control to: - -- Define [user attributes][ref-attributes] for personalized data access -- Set up [roles and permissions][ref-roles] to control feature access -- Create [custom roles][ref-custom-roles] with specific permissions for your team - -[ref-attributes]: /product/administration/users-and-permissions/user-attributes -[ref-roles]: /product/administration/users-and-permissions/roles-and-permissions -[ref-custom-roles]: /product/administration/users-and-permissions/custom-roles - diff --git a/docs/pages/product/administration/users-and-permissions/_meta.js b/docs/pages/product/administration/users-and-permissions/_meta.js deleted file mode 100644 index 07f9566f8ab40..0000000000000 --- a/docs/pages/product/administration/users-and-permissions/_meta.js +++ /dev/null @@ -1,7 +0,0 @@ -module.exports = { - "roles-and-permissions": "Roles & permissions", - "user-attributes": "User attributes", - "user-groups": "User groups", - "custom-roles": "Custom roles", -} - diff --git a/docs/pages/product/administration/users-and-permissions/custom-roles.mdx b/docs/pages/product/administration/users-and-permissions/custom-roles.mdx deleted file mode 100644 index 6ac7844c5f238..0000000000000 --- a/docs/pages/product/administration/users-and-permissions/custom-roles.mdx +++ /dev/null @@ -1,153 +0,0 @@ -# Custom roles - - - -Custom roles are available in Cube Cloud on -[Enterprise plan.](https://cube.dev/pricing) - - - -Cube comes with [default roles][ref-default-roles] that cover common use cases. However, if you need more customization, you can create custom roles with a fine-grained set of permissions tailored to your organization's specific needs. - -[ref-default-roles]: /product/administration/users-and-permissions/roles-and-permissions - - -## Managing roles - -In Cube Cloud, users are not assigned permissions directly. Instead, they are assigned -_roles_ that are associated with _policies_. Each policy define what _actions_ they can -perform and on what _resources_ they can perform those actions. This approach makes it -easier to manage permissions at scale. - -Each role can be associated with one or more of the following policies: - -| Policy | Description | -| --- | --- | -| `Global` | Controls account-level functionality, e.g., as Billing. | -| `Deployment` | Controls deployment-level functionality, e.g., as Playground. | -| `Report` | Controls access to specific reports in Saved Reports. | -| `ReportFolder` | Controls access to specific folders in Saved Reports. | -| `Agent` | Controls access to specific [AI agents][ref-ai-agents]. | -| `AgentSpace` | Controls access to specific AI agent [spaces][ref-ai-spaces]. | -| `Workbook` | Controls access to specific [workbooks][ref-workbooks]. | - -Each policy can apply to _all resources_ or _specific resources_. For example, a policy -could apply to all deployments or only to a specific deployment. - -Also, each policy can have _all actions_ or only _specific actions_ associated with it. -For example, a policy could allow a user to view, create, or delete one or more -deployments if it's associated with those specific actions. - -See [actions reference](#actions) for a list of available actions. - -### Browsing roles - -To see a list of custom roles, go to the **Admin -> Custom Roles** page in your Cube -account: - - - -### Creating a role - -To create a new role, click the Add Role button. Enter a name and an optional -description for the role, then click Add Policy and select either Deployment -or Global for this policy's scope. - -Deployment policies apply to deployment-level functionality, such as the -Playground and Data Model editor. Global policies apply to account-level -functionality, such as Billing. Once the policy scope has been -selected, you can restrict which actions this role can perform by selecting -"Specific" and using the dropdown to select specific actions. - - - -When you are finished, click Create to create the role. - -## Assigning roles to users - -To assign custom roles to users: - -1. Navigate to Admin → Users -2. Choose one of the following methods: - - **From the users table**: Use the dropdown in the users table - - **From individual user page**: Click on a user and assign roles from their profile page -3. You can assign multiple custom roles to a single user - -## Actions - -Policies can have the following actions associated with them. - -### `Global` - -| Action | Description | -| --- | --- | -| `Alerts Access`
`Alerts Create`
`Alerts Edit`
`Alerts Delete` | View, create, edit, and delete [budgets][ref-budgets]. | -| `Billing Access` | Access the billing data of the Cube Cloud account. | -| `Deployment Manage` | Create and delete deployments in the Cube Cloud account. | -| `Agent Admin` | Administer AI agents across the account. | -| `AI BI Developer` | Developer-level access to AI BI features with full AI token usage. | -| `AI BI User` | User-level access to AI BI features with standard AI token usage. | -| `AI BI Viewer` | Viewer-level access to AI BI features with limited AI token usage. | - -### `Deployment` - -| Action | Description | -| --- | --- | -| `Deployment View`
`Deployment Edit` | Access the deployment, change its settings. | -| `Playground Access` | Use [Playground][ref-playground]. | -| `Data Model View` | View the source code in the [data model][ref-data-model] editor, use [Visual Model][ref-visual-model]. | -| `Data Model Edit (all branches)`
`Data Model Edit (dev branches only)` | Use the [development mode][ref-dev-mode], edit the data model, perform Git operations (e.g., commit, pull, push). | -| `Queries & Metrics Access` | Use [Query History][ref-query-history] and [Performance Insights][ref-perf-insights]. | -| `SQL Runner Access` | Use [SQL Runner][ref-sql-runner]. | -| `Data Assets Access` | Use [Semantic Catalog][ref-semantic-catalog]. | - -### `Report` - -| Action | Description | -| --- | --- | -| `Report Read`
`Report Manage` | View and create/delete reports. | - -### `ReportFolder` - -| Action | Description | -| --- | --- | -| `Report Read`
`Report Manage` | View and create/delete report folders. | - -### `Agent` - -| Action | Description | -| --- | --- | -| `Agent Access`
`Agent Manage` | View and manage AI agents. | - -### `AgentSpace` - -| Action | Description | -| --- | --- | -| `Agent Space Manage` | Manage AI agent spaces. | - -### `Workbook` - -| Action | Description | -| --- | --- | -| `Workbook Read`
`Workbook Manage`
`Workbook Edit` | View, manage, and edit workbooks. | - - -[ref-budgets]: /product/workspace/budgets -[ref-playground]: /product/workspace/playground -[ref-data-model]: /product/workspace/data-model -[ref-visual-model]: /product/workspace/visual-model -[ref-dev-mode]: /product/workspace/dev-mode -[ref-query-history]: /product/workspace/query-history -[ref-perf-insights]: /product/workspace/performance -[ref-sql-runner]: /product/workspace/sql-runner -[ref-semantic-catalog]: /product/workspace/semantic-catalog -[ref-ai-agents]: /product/administration/ai/spaces-agents-models#2-agents-ai-agents -[ref-ai-spaces]: /product/administration/ai/spaces-agents-models#1-spaces-agent-spaces -[ref-workbooks]: /product/exploration/workbooks - diff --git a/docs/pages/product/administration/users-and-permissions/roles-and-permissions.mdx b/docs/pages/product/administration/users-and-permissions/roles-and-permissions.mdx deleted file mode 100644 index d4b4aea901d45..0000000000000 --- a/docs/pages/product/administration/users-and-permissions/roles-and-permissions.mdx +++ /dev/null @@ -1,62 +0,0 @@ -# Roles & Permissions - -_Understanding user roles and permissions in Cube._ - -Cube has three built-in default roles: Admin, Developer, and Explorer. Each role has specific permissions and access levels designed to support different responsibilities within the platform. - -The Enterprise tier allows creation of custom roles with a customized set of permissions tailored to your organization's specific needs. - - -## Default Roles - -### Admin Role - -- Has highest level of privileges -- Can manage semantic models -- Can manage other users -- Has access to admin section -- Full query capabilities - - -Admin roles are billed at the developer rate. - - -### Developer Role - -- Can create and edit semantic models -- Can execute SQL queries against data sources -- Can create and edit workbooks -- Can create and edit data apps -- No access to admin settings - -### Explorer Role - -- Can query semantic models -- Can create and edit workbooks -- Can create and edit data apps -- Can execute Semantic SQL queries -- Cannot make changes to semantic models -- Cannot query source data directly - -## Future Implementation - -A Viewer role is planned for future implementation with the following capabilities: - -- Use Analytics Chat with ability to query Semantic Views and existing reports -- View (read-only) access to shared data apps - -## Agent Permissions - -Agents are connected to Semantic Model Deployments and inherit the permission level of the user they are operating under. - -Each agent can be configured to use the _Restrict Views_ feature which allows to select the views that are visible to the agent. -This feature should not be used as a security measure. Configure [access policies][ref-data-access-policies] instead. - -## Typical Usage Scenarios - -- Explorers: Typically data consumers and analysts -- Developers: Usually data stewards and data engineers -- Admins: Typically assigned to data engineers managing the entire Cube instance (billed at the developer rate with additional privileges) - - -[ref-data-access-policies]: /product/auth/data-access-policies \ No newline at end of file diff --git a/docs/pages/product/administration/workspace.mdx b/docs/pages/product/administration/workspace.mdx deleted file mode 100644 index cba87e06b67a9..0000000000000 --- a/docs/pages/product/administration/workspace.mdx +++ /dev/null @@ -1,87 +0,0 @@ -# Workspace - -Workspace tools are designed to help you build, test, deploy, and manage -Cube projects. - - - -Most workspace tools depend on the [managed infrastructure][ref-infrastructure] -and are only available in Cube Cloud. - - - -## Workspace tools in Cube Cloud - -In Cube Cloud, you can: - -- Use the [managed infrastructure][ref-infrastructure] to deploy -- Use the code-first [data model editor][ref-data-model] or the no-code [Visual Model][ref-visual-model] -editor to build and enhance the data model of your semantic layer. -- Use the [development mode][ref-dev-mode] and [environments][ref-environments] to -collaborate and test features before going to production. -- Use [Playground][ref-playground] to run queries and test the data model. -- Use [Saved Reports][ref-saved-reports] to manage reports saved from Playground and -spreadsheet integrations, i.e., [Cube Cloud for Sheets][ref-sheets-integration] and -[Cube Cloud for Excel][ref-excel-integration]. -- Use [Chart Prototyping][ref-vizard] to generate code of a front-end - application that works with Cube. -- Use [SQL Runner][ref-sql-runner] to inform the development of the data - model. -- Use the [Integrations][ref-integrations] page to connect your semantic layer -to BIs, spreadsheets, and other visualization tools. -- Use [Query History][ref-query-history] to observe queries and their - performance in real-time. -- Use the [pre-aggregations page][ref-pre-aggs] to inspect pre-aggregations - and their build history. Add new pre-aggregations via [Rollup Designer][ref-rollup-designer]. -- Use [Performance Insights][ref-perf-insights] to analyze the performance - of your deployment as a whole. -- Use [Monitoring Integrations][ref-monitoring-integrations] to export logs and -metrics to external monitoring tools. -- Use [custom roles][ref-custom-roles] to manage access control for users of your Cube Cloud account and [single sign-on][ref-sso]. -- Use [Audit Log][ref-audit-log] to review security-related events in your -Cube Cloud account. -- Use the [Chats History][ref-chats-history] page to review and search past interactions with AI agents. -- Use the [API keys][ref-api-keys] page to manage API keys for secure access to your Cube account. -- Use the [encryption keys][ref-encryption-keys] page to manage [data-at-rest -encryption in Cube Store][ref-cube-store-encryption]. -- Use [Budgets][ref-budgets] to control the usage and spend of your Cube - Cloud account. -- Use [Preferences][ref-prefs] to adjust the workspace to your liking. - -## Workspace tools in Cube Core - -With Cube Core, you can: - -- Use the data model builder to generate the initial data model. -- Use [Playground][ref-playground] to run queries and test the data model. -- Use [Chart Prototyping][ref-vizard] to generate code of a front-end - application that works with Cube. -- Use the [command-line tool][ref-cli] to automate your workflows. - -[ref-infrastructure]: /product/deployment/cloud -[ref-data-model]: /product/workspace/data-model -[ref-rollup-designer]: /product/workspace/rollup-designer -[ref-dev-mode]: /product/workspace/dev-mode -[ref-environments]: /product/workspace/environments -[ref-sql-runner]: /product/workspace/sql-runner -[ref-playground]: /product/workspace/playground -[ref-vizard]: /product/workspace/vizard -[ref-integrations]: /product/workspace/integrations -[ref-query-history]: /product/workspace/query-history -[ref-pre-aggs]: /product/workspace/pre-aggregations -[ref-perf-insights]: /product/workspace/performance -[ref-monitoring-integrations]: /product/workspace/monitoring -[ref-custom-roles]: /product/administration/users-and-permissions/custom-roles -[ref-sso]: /product/workspace/sso -[ref-audit-log]: /product/workspace/audit-log -[ref-budgets]: /product/workspace/budgets -[ref-prefs]: /product/workspace/preferences -[ref-cli]: /product/workspace/cli -[ref-encryption-keys]: /product/workspace/encryption-keys -[ref-cube-store-encryption]: /product/caching/running-in-production#data-at-rest-encryption -[ref-visual-model]: /product/workspace/visual-model -[ref-saved-reports]: /product/workspace/saved-reports -[ref-sheets-integration]: /product/apis-integrations/google-sheets -[ref-excel-integration]: /product/apis-integrations/excel -[ref-api-keys]: /product/workspace/api-keys -[ref-chats-history]: /product/workspace/chats-history \ No newline at end of file diff --git a/docs/pages/product/administration/workspace/_meta.js b/docs/pages/product/administration/workspace/_meta.js deleted file mode 100644 index a95bd98cbbb93..0000000000000 --- a/docs/pages/product/administration/workspace/_meta.js +++ /dev/null @@ -1,25 +0,0 @@ -module.exports = { - "vizard": "Chart Prototyping", - "data-model": "Data Model", - "visual-model": "Visual Model", - "saved-reports": "Saved Reports", - "rollup-designer": "Rollup Designer", - "dev-mode": "Development mode", - "environments": "Environments", - "integrations": "Integrations", - "sql-runner": "SQL Runner", - "query-history": "Query History", - "pre-aggregations": "Pre-aggregations", - "performance": "Performance Insights", - "monitoring": "Monitoring Integrations", - "sso": "Authentication & SSO", - "audit-log": "Audit Log", - "chats-history": "Chats History", - "api-keys": "API keys", - "encryption-keys": "Encryption keys", - "budgets": "Budgets", - "preferences": "Preferences", - "cli": "CLI", - "semantic-catalog": "Semantic Catalog", - "recipes": "Recipes", -} diff --git a/docs/pages/product/administration/workspace/audit-log.mdx b/docs/pages/product/administration/workspace/audit-log.mdx deleted file mode 100644 index bf2cbb03e4817..0000000000000 --- a/docs/pages/product/administration/workspace/audit-log.mdx +++ /dev/null @@ -1,99 +0,0 @@ -# Audit Log - -Audit Log collects, stores, and displays security-related events within a Cube Cloud -account, across all deployments. You can use it to maintain and review a historical -record of activity for compliance purposes. - - - -Audit Log is available in Cube Cloud on the -[Enterprise Premier](https://cube.dev/pricing) product tier. -You can also choose an [Audit Log tier](/product/deployment/cloud/pricing#audit-log-tiers). - - - -Read below about [collected events](#event-types). Also, see how you can [enable](#configuration) -Audit Log, [view events](#viewing-events), and [download](#downloading-events) them. - - - -## Configuration - -To enable Audit Log, navigate to the Team & Security page, open the -Audit Log tab, and turn the Enable Audit Log switch on. - - - -If you choose to disable Audit Log, your account will be billed for using it until the -end of the month. - - - -## Viewing events - -### Table view - -Audit Log displays events in a table with the following information for each event: -- Event timestamp in your local time zone. -- User email, if applicable to a particular event. -- Event name (see [event types](#event-types) for the full list). -- Deployment name, if applicable to a particular event. - - - -### Extended view - -You can click on any event to view extended information: -- IP address from which an event was initiated. -- Event-specific attributes. - - - -#### Sanitization - -Audit Log uses heuristics to detect sensitive values (e.g., passwords and tokens) -and sanitize them, i.e., replace them with `[HIDDEN]` in event-specific -attributes. You can see that a password was sanitized on the screenshot above. - -If you'd like your custom environment variable to be sanitized, include one of -the following substrings in its name: `PASS`, `SECRET`, `TOKEN`, `KEY`. - -### Filters - -You can also customize the table view with filters on the top and in the right sidebar: -- Text input for full-text search. -- Date range filter. -- Filters to narrow the view down to a specific user, event, or deployment. - - - -## Downloading events - -You can use the ↓ CSV button to download a CSV file with all events in the -current view: - - - -## Event types - -Audit Log collects the following types of events: - -| Category | Event type | -| --- | --- | -| Users | `Created user`
`Deleted user`
`Invited user`
`Updated user profile`
`Requested password reset`
`Changed password` | -| [Custom roles](/product/administration/users-and-permissions/custom-roles) | `Created role`
`Deleted role`
`Updated role`
`Assigned role to user`
`Assigned roles to user`
`Removed role from user` | -| Authentication | `Logged in`
`Logged out`
`Redirected to SAML provider for login`
`Logged in via SAML` | -| Account and [single sign-on](/product/workspace/sso) | `Updated account settings`
`Updated account authentication configuration`
`Updated account SAML configuration`
`Uploaded identity provider metadata file` | -| [Deployments](/product/deployment/cloud/deployments) | `Created deployment`
`Deleted deployment`
`Updated deployment configuration`
`Enabled SQL API for deployment`
`Generated data model` | -| Branches and [dev mode](/product/workspace/dev-mode) | `Created Git branch`
`Deleted Git branch`
`Entered dev mode`
`Exited dev mode`
`Pulled changes to data model`
`Committed and merged changes to data model`
`Merged changes to data model`
`Reverted changes to data model in branch` | -| [Continuous deployment](/product/deployment/cloud/continuous-deployment) | `Requested connection of GitHub account`
`Connected deployment to GitHub repository`
`Generated SSH key for deployment`
`Connected deployment to Git upstream`
`Generated Git credentials for Cube Cloud repository`
`Generated webhook token for Git repository`
`Received a Git hook`
`Started uploading files`
`Finished uploading files`
`Triggered new build` | -| [Budgets](/product/workspace/budgets) | `Created budget`
`Deleted budget`
`Updated budget` | \ No newline at end of file diff --git a/docs/pages/product/administration/workspace/budgets.mdx b/docs/pages/product/administration/workspace/budgets.mdx deleted file mode 100644 index a986e5fd883ca..0000000000000 --- a/docs/pages/product/administration/workspace/budgets.mdx +++ /dev/null @@ -1,82 +0,0 @@ -# Budgets - -As an account administrator, you can define rules which trigger notifications -when your account's usage exceeds a certain threshold. These rules are called -"budgets". - - - -Budgets are available in Cube Cloud on -[Premium and above](https://cube.dev/pricing) product tiers. - - - - - -## How budgets work - -Budgets are configured on a per-account basis. When a budget is triggered, any configured users -will receive an email notification. Budget notifications are sent immediately after being triggered. - -## List all budgets - -To see a list of all configured budgets in your account, first go to the Billing settings page by -clicking on your avatar in the top right corner, then clicking on Billing. - -On the Billing settings page, click the Budgets tab to see all configured budgets in your -account: - - - -## Create a budget - -To create a new budget, click the Add Budget button. Enter a name for the budget, -then select a time period (either 'Daily' or 'Monthly') and a corresponding target amount, which -is the amount of usage that will trigger a notification. - - - -### Threshold Rules - -You can also configure threshold rules, which allow you to trigger notifications when usage -exceeds a certain percentage of the target amount. For example, if you set a target amount of -\$1,000 and a threshold of 80%, you will also receive a notification when your usage exceeds \$800. - - - - - -A good rule-of-thumb for accounts that pay annually is to set a monthly budget of 1/12 (~8.3%) for your first budget. - - - -If you have multiple thresholds defined, some thresholds __may not be triggered__ if a higher threshold -is triggered first. For example, if you have a target amount of \$1,000 and thresholds of 80% and 90%, -and your usage hits 95%, you will only receive a notification when your usage exceeds \$900. - -### Managing Notifications - -When creating a new budget, by default, all users will receive email notifications. - - - -You can also specify particular users who should receive alerts by -toggling the **Specific users** option and selecting them. Optionally, -you can also add additional email addresses that should receive -email notifications by entering the email address in the **Custom email** field. diff --git a/docs/pages/product/administration/workspace/cli.mdx b/docs/pages/product/administration/workspace/cli.mdx deleted file mode 100644 index df28d6a99c8be..0000000000000 --- a/docs/pages/product/administration/workspace/cli.mdx +++ /dev/null @@ -1,55 +0,0 @@ -# CLI - -The Cube command line interface (CLI) is used for various Cube workflows. It -could help you in areas such as: - -- Creating a new Cube service. -- Generating a data model based on your database tables. - -See the [CLI command reference][ref-ref-cli] for details on all commands. - -## Quickstart - -Once installed, run the following command to create new Cube service - -```bash -npx cubejs-cli create -d -``` - -specifying the project name and your database using `-d` flag. Available -options: - -- `postgres` -- `mysql` -- `mongobi` -- `athena` -- `redshift` -- `bigquery` -- `mssql` -- `clickhouse` -- `snowflake` -- `presto` - -For example, - -```bash -npx cubejs-cli create hello-world -d postgres -``` - -Once run, the `create` command will create a new project directory that contains -the scaffolding for your new Cube project. This includes all the files necessary -to spin up the Cube backend, example frontend code for displaying the results of -Cube queries in a React app, and some example data model files to highlight the -format of the Cube Data Model layer. - -The `.env` file in this project directory contains placeholders for the relevant -database credentials. For MySQL, Redshift, and PostgreSQL, you'll need to fill -in the target host, database name, user and password. For Athena, you'll need to -specify the AWS access and secret keys with the [access necessary to run Athena -queries][link-athena-access], and the target AWS region and [S3 output -location][link-athena-output] where query results are stored. - - -[link-athena-access]: https://docs.aws.amazon.com/athena/latest/ug/access.html -[link-athena-output]: https://docs.aws.amazon.com/athena/latest/ug/querying.html -[ref-ref-cli]: /product/workspace/cli/reference \ No newline at end of file diff --git a/docs/pages/product/administration/workspace/cli/_meta.js b/docs/pages/product/administration/workspace/cli/_meta.js deleted file mode 100644 index ca8ef87b8fac3..0000000000000 --- a/docs/pages/product/administration/workspace/cli/_meta.js +++ /dev/null @@ -1,3 +0,0 @@ -module.exports = { - "reference": "Reference" -} diff --git a/docs/pages/product/administration/workspace/cli/reference.mdx b/docs/pages/product/administration/workspace/cli/reference.mdx deleted file mode 100644 index db808c5c912c9..0000000000000 --- a/docs/pages/product/administration/workspace/cli/reference.mdx +++ /dev/null @@ -1,154 +0,0 @@ -# CLI command reference - -With this CLI utility, you can [create](#create) a barebones Cube app, -[generate](#generate) a data model, [validate](#validate) it, or -[generate](#token) a JSON web token. - -You can also use the CLI utility to [deploy](#deploy) your Cube application to -Cube Cloud. This is one of supported ways of [continuous deployment][ref-ci]. - -## `create` - -The `create` command generates a barebones Cube app. - -### Usage - -```bash -npx cubejs-cli create APP-NAME -d DB-TYPE [-t TEMPLATE] -``` - -| Parameter | Description | Values | -| --------------------------- | -------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- | -| `-d, --db-type ` | Preconfigure Cube app for selected database. | `postgres`, `mysql`, `athena`, `mongobi`, `bigquery`, `redshift`, `mssql`, `clickhouse`, `snowflake`, `presto`, `druid` | -| `-t, --template