diff --git a/.github/styles/config/vocabularies/embucket/accept.txt b/.github/styles/config/vocabularies/embucket/accept.txt index 5a709ac4..fd90266b 100644 --- a/.github/styles/config/vocabularies/embucket/accept.txt +++ b/.github/styles/config/vocabularies/embucket/accept.txt @@ -33,3 +33,18 @@ NYC UTC DBAs? config +repo +repos +serverless +toolchain +Makefile +walkthrough +rollout +charset +env +hardcoded +hardcode +unpatched +deployer +anonymized +bootable diff --git a/.github/workflows/docs-ci.yml b/.github/workflows/docs-ci.yml index 6e008ce2..a54f928b 100644 --- a/.github/workflows/docs-ci.yml +++ b/.github/workflows/docs-ci.yml @@ -5,10 +5,12 @@ on: branches: [main] paths: - "docs/**" + - ".github/workflows/docs-ci.yml" pull_request: branches: [main] paths: - "docs/**" + - ".github/workflows/docs-ci.yml" # Cancel in-progress runs for the same branch/PR to save resources concurrency: @@ -49,10 +51,47 @@ jobs: working-directory: ./docs run: pnpm prettier --check . + smoke: + name: Docs Smoke Checks + runs-on: ubuntu-latest + needs: [format] + steps: + - uses: actions/checkout@v6 + - name: Setup Node.js + uses: actions/setup-node@v6 + with: + node-version: "22" + - name: Setup PNPM + uses: pnpm/action-setup@v4 + with: + version: "10.11.0" + run_install: false + - name: Get pnpm store directory + id: pnpm-cache + shell: bash + run: | + echo "STORE_PATH=$(pnpm store path)" >> $GITHUB_OUTPUT + - name: Setup pnpm cache + uses: actions/cache@v4 + with: + path: ${{ steps.pnpm-cache.outputs.STORE_PATH }} + key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/docs/pnpm-lock.yaml') }} + restore-keys: | + ${{ runner.os }}-pnpm-store- + - name: Install dependencies + working-directory: ./docs + run: pnpm install + - name: Run Astro check + working-directory: ./docs + run: pnpm check + - name: Run docs smoke checks + working-directory: ./docs + run: pnpm smoke + build: name: Validate Build runs-on: ubuntu-latest - needs: [format] + needs: [format, smoke] steps: - uses: actions/checkout@v6 - name: Setup Node.js @@ -81,7 +120,7 @@ jobs: run: pnpm install - name: Validate build working-directory: ./docs - run: pnpm build:dry-run + run: pnpm build vale-lint: name: Vale lint @@ -89,5 +128,7 @@ jobs: steps: - uses: actions/checkout@v6 - uses: errata-ai/vale-action@v2.1.1 + continue-on-error: true with: files: "docs/src/content/" + reporter: github-check diff --git a/README.md b/README.md index 666e4f40..a8120d18 100644 --- a/README.md +++ b/README.md @@ -1,42 +1,65 @@ # Embucket -**Run Snowflake SQL dialect on your data lake in 30 seconds. Zero dependencies.** +Embucket exposes a Snowflake-compatible API over lakehouse data. The repo currently ships two runtime artifacts: -[![License](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) +- `embucketd` for local and self-hosted runs +- `embucket-lambda` for AWS Lambda deployments -## Introduction +## Choose your path -Embucket is a single binary lakehouse that provides a wire-compatible Snowflake replacement and works with Apache Iceberg open table format. Perfect for simple deployments. Built on proven open source: +- **Start locally** if you want the fastest test or evaluation loop. +- **Run from source** if you want to build `embucketd` yourself for local evaluation. +- **Deploy on AWS Lambda** if you want the current serverless runtime. +- **Connect dbt** if you want the recommended client path. +- **Run Snowplow web analytics** if you want a fuller example on the Lambda + dbt path. +- **Use S3 Tables** if you want the currently documented external catalog. +- **Troubleshoot** if your client, auth, or runtime setup does not behave as expected. -- [Apache DataFusion](https://datafusion.apache.org/) for SQL execution -- [Apache Iceberg](https://iceberg.apache.org/) for ACID table metadata +Relevant guides live under `docs/src/content/docs/`: -Embucket features: +- `essentials/quick-start.mdx` +- `essentials/runtime-modes.mdx` +- `guides/aws-lambda.mdx` +- `guides/dbt.mdx` +- `guides/self-hosted.mdx` +- `guides/snowplow.mdx` +- `guides/s3-tables.mdx` +- `guides/troubleshooting.mdx` -- **Snowflake SQL dialect and API**: Use your existing queries, dbt projects, and BI tools -- **Apache Iceberg storage**: Your data stays in Apache Iceberg format on object storage, no lock-in -- **Radical simplicity** - Single binary deployment -- **Query-per-node**: Each instance handles complete queries independently -- **Horizontal scaling** - Add nodes for more throughput +If you want to build the local binary instead of using Docker, start with `docs/src/content/docs/guides/self-hosted.mdx`. -## Quick start +If you want a fuller example on the recommended client path, start with `docs/src/content/docs/guides/snowplow.mdx`. -Start Embucket and run your first query in 30 seconds: +## Support summary + +The current docs should make these distinctions explicit: + +- **Local mode** is the fastest path for tests and evaluation. +- **AWS Lambda + dbt-embucket** is verified and is the recommended client path. +- **AWS Lambda + Snowflake CLI over Function URL** is tested, but not production-ready because the Function URL is publicly reachable. +- **Production-facing Lambda deployments** should avoid a public Function URL. The AWS Lambda guide includes an anonymized private API Gateway example. +- **AWS S3 Tables** is the currently documented external catalog path. + +## Local quick start + +Run Embucket locally: ```bash docker run --name embucket --rm -p 3000:3000 embucket/embucket ``` -Install and configure the Snowflake CLI against the local endpoint: +Expected startup log: + +```text +{"timestamp":"2025-07-01T15:35:05.687807Z","level":"INFO","fields":{"message":"Listening on http://0.0.0.0:3000"},"target":"embucketd"} +``` + +Configure Snowflake CLI for the local endpoint: ```bash -$ pip install snowflake-cli # Install snowflake cli if you haven't already -# Configure the Snowflake CLI to connect to the local endpoint -# Find the config file path -$ snow --info | grep "config_file_path" -A 1 -$ CONFIG= -# Update the config file with the following: -$ echo ' +snow --info + +# Add this connection block to your Snowflake CLI config file. [connections.local] host = "localhost" region = "us-east-2" @@ -45,245 +68,42 @@ protocol = "http" database = "embucket" schema = "public" warehouse = "em.wh" -password = "embucket" account = "acc.local" user = "embucket" -' >> $CONFIG -$ snow connection test -c local -# Expected output -+-----------------------------+ -| key | value | -|-----------------+-----------| -| Connection name | local | -| Status | OK | -| Host | localhost | -| Account | acc | -| User | embucket | -| Role | not set | -| Database | embucket | -| Warehouse | em.wh | -+-----------------------------+ -``` - -Run a query: - -```bash -$ snow sql -c local -q "select dateadd(day, -1, current_timestamp()) as yesterday;" -# Expected output -+----------------------------------+ -| yesterday | -|----------------------------------| -| 2025-01-02 03:04:05.040000+00:00 | -+----------------------------------+ -``` - -**Done.** You just ran Snowflake SQL dialect against the local Embucket instance. - -## External catalogs - -Embucket can connect to external catalogs via YAML configuration. At the moment the only supported catalog is AWS S3 table buckets. - -**Important**: External catalogs must be defined via YAML configuration file. - -Define catalogs by pointing `embucketd` at a YAML config file. - -**Using Docker:** - -```bash -docker run --name embucket --rm -p 3000:3000 \ - -v $PWD/config:/app/config \ - embucket/embucket \ - ./embucketd --metastore-config config/metastore.yaml -``` - -**Using binary:** - -```bash -./embucketd \ - --metastore-config config/metastore.yaml -``` - -**Sample configuration** (`config/metastore.yaml`): - -```yaml -volumes: - # S3 Tables volume - connects to AWS S3 Table Bucket - - ident: demo - type: s3-tables - database: demo - credentials: - credential_type: access_key - aws-access-key-id: YOUR_ACCESS_KEY - aws-secret-access-key: YOUR_SECRET_KEY - arn: arn:aws:s3tables:us-east-2:123456789012:bucket/my-table-bucket -``` - -Query the catalog. Assume the catalog is name `demo` (`database: demo` in the config above). - -```bash -$ snow sql -c local -q "show schemas in demo; show tables in demo.tpch_10;" -show schemas in demo; -+----------------------------------------------------------------------------+ -| created_on | name | kind | database_name | schema_name | -|------------+--------------------------+------+---------------+-------------| -| None | public | None | demo | None | -| None | public_derived | None | demo | None | -| None | public_scratch | None | demo | None | -| None | public_snowplow_manifest | None | demo | None | -| None | sturukin | None | demo | None | -| None | tpcds_10 | None | demo | None | -| None | tpcds_100 | None | demo | None | -| None | tpch_10 | None | demo | None | -| None | tpch_100 | None | demo | None | -| None | information_schema | None | demo | None | -+----------------------------------------------------------------------------+ - -show tables in demo.tpch_10; -+-------------------------------------------------------------+ -| created_on | name | kind | database_name | schema_name | -|------------+----------+-------+---------------+-------------| -| None | orders | TABLE | demo | tpch_10 | -| None | nation | TABLE | demo | tpch_10 | -| None | customer | TABLE | demo | tpch_10 | -| None | part | TABLE | demo | tpch_10 | -| None | lineitem | TABLE | demo | tpch_10 | -| None | partsupp | TABLE | demo | tpch_10 | -| None | region | TABLE | demo | tpch_10 | -| None | supplier | TABLE | demo | tpch_10 | -| None | t1 | TABLE | demo | tpch_10 | -| None | t3 | TABLE | demo | tpch_10 | -+-------------------------------------------------------------+ -``` - -Update the credentials and ARN/bucket details with your own values for real deployments. - -## External Iceberg tables - -Embucket can also be configured to work with external Iceberg tables. Define tables in the metastore config file. - -**Important**: External tables must be in the same bucket as the `volume` defined in the metastore config file. - -```yaml -volumes: - - ident: lakehouse - type: s3 - region: us-east-2 - bucket: YOUR_BUCKET_NAME - credentials: - credential_type: access_key - aws-access-key-id: YOUR_ACCESS_KEY - aws-secret-access-key: YOUR_SECRET_KEY -databases: - - ident: demo - volume: lakehouse -schemas: - - database: demo - schema: tpch_10 -tables: -- database: demo - schema: tpch_10 - table: customer - metadata_location: s3://YOUR_BUCKET_NAME/tpch_10/customer/metadata/00001-eea1cccb-38a4-4fe2-8c95-c01dae9d0c60.metadata.json -- database: demo - schema: tpch_10 - table: lineitem - metadata_location: s3://YOUR_BUCKET_NAME/tpch_10/lineitem/metadata/00001-d777220e-d508-4033-a229-8c4c8d8fe514.metadata.json -``` - -## Build from source - -```bash -git clone https://github.com/Embucket/embucket.git -cd embucket && cargo build -./target/debug/embucketd -``` - -## Deployment - -Embucket supports all different deployments modes as it is single binary. - -### Lambda - -One of the interesting deployment modes is AWS Lambda, Google Cloud Functions, and Azure Functions. At the moment, Embucket can be natively built for AWS Lambda. - -To build for Lambda, make sure you have `cargo-lambda` installed (`cargo install cargo-lambda`) and run the following command: - -```bash -$ cargo lambda build --release -p embucket-lambda --arm64 -``` - -To deploy to AWS Lambda, you will need to create a new function in the AWS Console and upload the binary. By default deploy command will use the `bootstrap` binary, use default IAM role `AWSLambdaBasicExecutionRole`, use default memory size `1024`, default timeout `30` and include `config` directory. - -**Important**: Make sure configuration file exists in the `config` directory (i.e. `config/metastore.yaml`). - -Use the `cargo lambda deploy` command to deploy the binary to AWS Lambda. - -```bash -$ cargo lambda deploy --binary-name bootstrap embucket-lambda -``` - -It is also recommended to enable function URL to access the API. Read [cargo-lambda](https://www.cargo-lambda.info/commands/deploy.html#function-urls) documentation and configure the IAM role to allow function URL access. - -```bash -$ cargo lambda deploy --binary-name bootstrap embucket-lambda --enable-function-url +password = "embucket" ``` -The expected output is: +Validate the connection and run a query: ```bash -✅ function deployed successfully 🎉 -🛠️ binary last compiled 1 minute ago -🔍 arn: arn:aws:lambda:us-east-2:123456789012:function:embucket-lambda:1 -🎭 version: 1 -🔗 url: https://7mh4xw9n2pqjvf5kzrbt8ycusg6dla3e.lambda-url.us-east-2.on.aws/ +snow connection test -c local +snow sql -c local -q "SELECT 1 AS ok" ``` -The 32 alphanumeric characters after `url.` are the function URL. You can use it to access the API. +You can also open `http://127.0.0.1:3000/` to inspect the current Swagger/OpenAPI surface served by `embucketd`. -Create a new connection profile for Snowflake CLI: +## AWS Lambda quick pointer -```bash -$ snow connection add -Enter connection name: lambda -Enter account: acc.lambda -Enter user: embucket -Enter password: -Enter role: em.role -Enter warehouse: em.wh -Enter database: demo -Enter schema: public -Enter host: https://7mh4xw9n2pqjvf5kzrbt8ycusg6dla3e.lambda-url.us-east-2.on.aws -Enter port: -Enter region: us-east-2 -Enter authenticator: -Enter workload identity provider: -Enter private key file: -Enter token file path: -``` +If you want the current serverless path, start with `docs/src/content/docs/guides/aws-lambda.mdx`. -Now use it to run queries: +The current runtime is built from `crates/embucket-lambda` and can be deployed with: ```bash -$ snow sql -c lambda -q "select dateadd(day, -1, current_timestamp()) as yesterday;" -select dateadd(day, -1, current_timestamp()) as yesterday; -+----------------------------------+ -| yesterday | -|----------------------------------| -| 2025-01-02 03:04:05.040000+00:00 | -+----------------------------------+ +make -C crates/embucket-lambda deploy ``` +For test-only validation, you can expose a Function URL and connect Snowflake CLI to it. For production-facing traffic, keep the Lambda private and put an API gateway layer in front of it. -## Contributing +## dbt quick pointer -Contributions welcome. To get involved: +If you want the recommended client workflow, start with `docs/src/content/docs/guides/dbt.mdx`. -1. **Fork** the repository on GitHub -2. **Create** a new branch for your feature or bug fix -3. **Submit** a pull request with a detailed description +The official adapter lives in the sibling repository `Embucket/dbt-embucket` and uses: -For more details, see [CONTRIBUTING.md](CONTRIBUTING.md). +- `type: embucket` +- `function_arn` to reach the deployed Lambda +- `dbt debug` and `dbt run` as the verified end-to-end checks -## License +## S3 Tables quick pointer -This project uses the **Apache 2.0 License**. See [LICENSE](LICENSE) for details. +The current docs treat AWS S3 Tables as the supported external catalog path. Start with `docs/src/content/docs/guides/s3-tables.mdx` for the YAML shape, AWS prerequisites, and query flow. diff --git a/docs/package.json b/docs/package.json index 643deb88..14b71bc0 100644 --- a/docs/package.json +++ b/docs/package.json @@ -6,10 +6,12 @@ "astro": "astro", "build": "astro build", "build:dry-run": "astro build --dry-run", + "check": "astro check", "dev": "astro dev", "format": "prettier --write .", "ncu": "ncu -u", "preview": "astro preview", + "smoke": "node ./scripts/validate-docs-smoke.mjs", "start": "astro dev" }, "dependencies": { @@ -24,11 +26,13 @@ "tailwindcss": "^4.1.17" }, "devDependencies": { + "@astrojs/check": "^0.9.8", "npm-check-updates": "^19.1.2", "prettier": "^3.6.2", "prettier-plugin-astro": "^0.14.1", "prettier-plugin-packagejson": "^2.5.19", "prettier-plugin-tailwindcss": "^0.7.1", - "starlight-links-validator": "^0.19.1" + "starlight-links-validator": "^0.19.1", + "typescript": "^5.9.3" } } diff --git a/docs/pnpm-lock.yaml b/docs/pnpm-lock.yaml index cda427bf..1e132a15 100644 --- a/docs/pnpm-lock.yaml +++ b/docs/pnpm-lock.yaml @@ -10,22 +10,22 @@ importers: dependencies: '@astrojs/starlight': specifier: ^0.36.2 - version: 0.36.2(astro@5.15.4(@types/node@24.0.10)(jiti@2.6.1)(lightningcss@1.30.2)(rollup@4.44.1)(typescript@5.8.3)) + version: 0.36.2(astro@5.15.4(@types/node@24.0.10)(jiti@2.6.1)(lightningcss@1.30.2)(rollup@4.44.1)(typescript@5.9.3)(yaml@2.8.3)) '@astrojs/starlight-tailwind': specifier: ^4.0.2 - version: 4.0.2(@astrojs/starlight@0.36.2(astro@5.15.4(@types/node@24.0.10)(jiti@2.6.1)(lightningcss@1.30.2)(rollup@4.44.1)(typescript@5.8.3)))(tailwindcss@4.1.17) + version: 4.0.2(@astrojs/starlight@0.36.2(astro@5.15.4(@types/node@24.0.10)(jiti@2.6.1)(lightningcss@1.30.2)(rollup@4.44.1)(typescript@5.9.3)(yaml@2.8.3)))(tailwindcss@4.1.17) '@fontsource/inter': specifier: ^5.2.8 version: 5.2.8 '@tailwindcss/vite': specifier: ^4.1.17 - version: 4.1.17(vite@6.4.1(@types/node@24.0.10)(jiti@2.6.1)(lightningcss@1.30.2)) + version: 4.1.17(vite@6.4.1(@types/node@24.0.10)(jiti@2.6.1)(lightningcss@1.30.2)(yaml@2.8.3)) astro: specifier: ^5.15.4 - version: 5.15.4(@types/node@24.0.10)(jiti@2.6.1)(lightningcss@1.30.2)(rollup@4.44.1)(typescript@5.8.3) + version: 5.15.4(@types/node@24.0.10)(jiti@2.6.1)(lightningcss@1.30.2)(rollup@4.44.1)(typescript@5.9.3)(yaml@2.8.3) astro-mermaid: specifier: ^1.1.0 - version: 1.1.0(astro@5.15.4(@types/node@24.0.10)(jiti@2.6.1)(lightningcss@1.30.2)(rollup@4.44.1)(typescript@5.8.3))(mermaid@11.12.1) + version: 1.1.0(astro@5.15.4(@types/node@24.0.10)(jiti@2.6.1)(lightningcss@1.30.2)(rollup@4.44.1)(typescript@5.9.3)(yaml@2.8.3))(mermaid@11.12.1) mermaid: specifier: ^11.12.1 version: 11.12.1 @@ -36,6 +36,9 @@ importers: specifier: ^4.1.17 version: 4.1.17 devDependencies: + '@astrojs/check': + specifier: ^0.9.8 + version: 0.9.8(prettier-plugin-astro@0.14.1)(prettier@3.6.2)(typescript@5.9.3) npm-check-updates: specifier: ^19.1.2 version: 19.1.2 @@ -53,7 +56,10 @@ importers: version: 0.7.1(prettier-plugin-astro@0.14.1)(prettier@3.6.2) starlight-links-validator: specifier: ^0.19.1 - version: 0.19.1(@astrojs/starlight@0.36.2(astro@5.15.4(@types/node@24.0.10)(jiti@2.6.1)(lightningcss@1.30.2)(rollup@4.44.1)(typescript@5.8.3))) + version: 0.19.1(@astrojs/starlight@0.36.2(astro@5.15.4(@types/node@24.0.10)(jiti@2.6.1)(lightningcss@1.30.2)(rollup@4.44.1)(typescript@5.9.3)(yaml@2.8.3))) + typescript: + specifier: ^5.9.3 + version: 5.9.3 packages: @@ -63,9 +69,18 @@ packages: '@antfu/utils@9.3.0': resolution: {integrity: sha512-9hFT4RauhcUzqOE4f1+frMKLZrgNog5b06I7VmZQV1BkvwvqrbC8EBZf3L1eEL2AKb6rNKjER0sEvJiSP1FXEA==} + '@astrojs/check@0.9.8': + resolution: {integrity: sha512-LDng8446QLS5ToKjRHd3bgUdirvemVVExV7nRyJfW2wV36xuv7vDxwy5NWN9zqeSEDgg0Tv84sP+T3yEq+Zlkw==} + hasBin: true + peerDependencies: + typescript: ^5.0.0 + '@astrojs/compiler@2.12.2': resolution: {integrity: sha512-w2zfvhjNCkNMmMMOn5b0J8+OmUaBL1o40ipMvqcG6NRpdC+lKxmTi48DT8Xw0SzJ3AfmeFLB45zXZXtmbsjcgw==} + '@astrojs/compiler@2.13.1': + resolution: {integrity: sha512-f3FN83d2G/v32ipNClRKgYv30onQlMZX1vCeZMjPsMMPl1mDpmbl0+N5BYo4S/ofzqJyS5hvwacEo0CCVDn/Qg==} + '@astrojs/internal-helpers@0.6.1': resolution: {integrity: sha512-l5Pqf6uZu31aG+3Lv8nl/3s4DbUzdlxTWDof4pEpto6GUJNhhCbelVi9dEyurOVyqaelwmS9oSyOWOENSfgo9A==} @@ -75,6 +90,18 @@ packages: '@astrojs/internal-helpers@0.7.4': resolution: {integrity: sha512-lDA9MqE8WGi7T/t2BMi+EAXhs4Vcvr94Gqx3q15cFEz8oFZMO4/SFBqYr/UcmNlvW+35alowkVj+w9VhLvs5Cw==} + '@astrojs/language-server@2.16.6': + resolution: {integrity: sha512-N990lu+HSFiG57owR0XBkr02BYMgiLCshLf+4QG4v6jjSWkBeQGnzqi+E1L08xFPPJ7eEeXnxPXGLaVv5pa4Ug==} + hasBin: true + peerDependencies: + prettier: ^3.0.0 + prettier-plugin-astro: '>=0.11.0' + peerDependenciesMeta: + prettier: + optional: true + prettier-plugin-astro: + optional: true + '@astrojs/markdown-remark@6.3.2': resolution: {integrity: sha512-bO35JbWpVvyKRl7cmSJD822e8YA8ThR/YbUsciWNA7yTcqpIAL2hJDToWP5KcZBWxGT6IOdOkHSXARSNZc4l/Q==} @@ -112,6 +139,9 @@ packages: resolution: {integrity: sha512-UFBgfeldP06qu6khs/yY+q1cDAaArM2/7AEIqQ9Cuvf7B1hNLq0xDrZkct+QoIGyjq56y8IaE2I3CTvG99mlhQ==} engines: {node: 18.20.8 || ^20.3.0 || >=22.0.0} + '@astrojs/yaml2ts@0.2.3': + resolution: {integrity: sha512-PJzRmgQzUxI2uwpdX2lXSHtP4G8ocp24/t+bZyf5Fy0SZLSF9f9KXZoMlFM/XCGue+B0nH/2IZ7FpBYQATBsCg==} + '@babel/helper-string-parser@7.27.1': resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==} engines: {node: '>=6.9.0'} @@ -159,6 +189,27 @@ packages: resolution: {integrity: sha512-WyOx8cJQ+FQus4Mm4uPIZA64gbk3Wxh0so5Lcii0aJifqwoVOlfFtorjLE0Hen4OYyHZMXDWqMmaQemBhgxFRQ==} engines: {node: '>=14'} + '@emmetio/abbreviation@2.3.3': + resolution: {integrity: sha512-mgv58UrU3rh4YgbE/TzgLQwJ3pFsHHhCLqY20aJq+9comytTXUDNGG/SMtSeMJdkpxgXSXunBGLD8Boka3JyVA==} + + '@emmetio/css-abbreviation@2.1.8': + resolution: {integrity: sha512-s9yjhJ6saOO/uk1V74eifykk2CBYi01STTK3WlXWGOepyKa23ymJ053+DNQjpFcy1ingpaO7AxCcwLvHFY9tuw==} + + '@emmetio/css-parser@0.4.1': + resolution: {integrity: sha512-2bC6m0MV/voF4CTZiAbG5MWKbq5EBmDPKu9Sb7s7nVcEzNQlrZP6mFFFlIaISM8X6514H9shWMme1fCm8cWAfQ==} + + '@emmetio/html-matcher@1.3.0': + resolution: {integrity: sha512-NTbsvppE5eVyBMuyGfVu2CRrLvo7J4YHb6t9sBFLyY03WYhXET37qA4zOYUjBWFCRHO7pS1B9khERtY0f5JXPQ==} + + '@emmetio/scanner@1.0.4': + resolution: {integrity: sha512-IqRuJtQff7YHHBk4G8YZ45uB9BaAGcwQeVzgj/zj8/UdOhtQpEIupUhSk8dys6spFIWVZVeK20CzGEnqR5SbqA==} + + '@emmetio/stream-reader-utils@0.1.0': + resolution: {integrity: sha512-ZsZ2I9Vzso3Ho/pjZFsmmZ++FWeEd/txqybHTm4OgaZzdS8V9V/YYWQwg5TC38Z7uLWUV1vavpLLbjJtKubR1A==} + + '@emmetio/stream-reader@2.2.0': + resolution: {integrity: sha512-fXVXEyFA5Yv3M3n8sUGT7+fvecGrZP4k6FnWWMSZVQf69kAq0LLpaBQLGcPR30m3zMmKYhECP4k/ZkzvhEW5kw==} + '@emnapi/runtime@1.7.0': resolution: {integrity: sha512-oAYoQnCYaQZKVS53Fq23ceWMRxq5EhQsE0x0RdQ55jT7wagMu5k+fS39v1fiSLrtrLQlXwVINenqhLMtTrV/1Q==} @@ -918,6 +969,32 @@ packages: '@ungap/structured-clone@1.3.0': resolution: {integrity: sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==} + '@volar/kit@2.4.28': + resolution: {integrity: sha512-cKX4vK9dtZvDRaAzeoUdaAJEew6IdxHNCRrdp5Kvcl6zZOqb6jTOfk3kXkIkG3T7oTFXguEMt5+9ptyqYR84Pg==} + peerDependencies: + typescript: '*' + + '@volar/language-core@2.4.28': + resolution: {integrity: sha512-w4qhIJ8ZSitgLAkVay6AbcnC7gP3glYM3fYwKV3srj8m494E3xtrCv6E+bWviiK/8hs6e6t1ij1s2Endql7vzQ==} + + '@volar/language-server@2.4.28': + resolution: {integrity: sha512-NqcLnE5gERKuS4PUFwlhMxf6vqYo7hXtbMFbViXcbVkbZ905AIVWhnSo0ZNBC2V127H1/2zP7RvVOVnyITFfBw==} + + '@volar/language-service@2.4.28': + resolution: {integrity: sha512-Rh/wYCZJrI5vCwMk9xyw/Z+MsWxlJY1rmMZPsxUoJKfzIRjS/NF1NmnuEcrMbEVGja00aVpCsInJfixQTMdvLw==} + + '@volar/source-map@2.4.28': + resolution: {integrity: sha512-yX2BDBqJkRXfKw8my8VarTyjv48QwxdJtvRgUpNE5erCsgEUdI2DsLbpa+rOQVAJYshY99szEcRDmyHbF10ggQ==} + + '@volar/typescript@2.4.28': + resolution: {integrity: sha512-Ja6yvWrbis2QtN4ClAKreeUZPVYMARDYZl9LMEv1iQ1QdepB6wn0jTRxA9MftYmYa4DQ4k/DaSZpFPUfxl8giw==} + + '@vscode/emmet-helper@2.11.0': + resolution: {integrity: sha512-QLxjQR3imPZPQltfbWRnHU6JecWTF1QSWhx3GAKQpslx7y3Dp6sIIXhKjiUJ/BR9FX8PVthjr9PD6pNwOJfAzw==} + + '@vscode/l10n@0.0.18': + resolution: {integrity: sha512-KYSIHVmslkaCDyw013pphY+d7x1qV8IZupYfeIfzNA+nsaWHbn5uPuQRvdRFsa9zFzGeudPuoGoZ1Op4jrJXIQ==} + acorn-jsx@5.3.2: resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} peerDependencies: @@ -928,6 +1005,17 @@ packages: engines: {node: '>=0.4.0'} hasBin: true + ajv-draft-04@1.0.0: + resolution: {integrity: sha512-mv00Te6nmYbRp5DCwclxtt7yV/joXJPGS7nM+97GdxvuttCOfgI3K4U25zboyeX0O+myI8ERluxQe5wljMmVIw==} + peerDependencies: + ajv: ^8.5.0 + peerDependenciesMeta: + ajv: + optional: true + + ajv@8.18.0: + resolution: {integrity: sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==} + ansi-align@3.0.1: resolution: {integrity: sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==} @@ -943,6 +1031,10 @@ packages: resolution: {integrity: sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==} engines: {node: '>=12'} + ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + ansi-styles@6.2.1: resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} engines: {node: '>=12'} @@ -1060,6 +1152,10 @@ packages: resolution: {integrity: sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==} engines: {node: '>=10'} + cliui@8.0.1: + resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} + engines: {node: '>=12'} + clone@2.1.2: resolution: {integrity: sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==} engines: {node: '>=0.8'} @@ -1071,6 +1167,13 @@ packages: collapse-white-space@2.1.0: resolution: {integrity: sha512-loKTxY1zCOuG4j9f6EPnuyyYkf58RnhhWTvRoZEokgB+WbdXehfjFviyOVYkqzEWz1Q5kRiZdBYS5SwxbQYwzw==} + color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + + color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + comma-separated-tokens@2.0.3: resolution: {integrity: sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==} @@ -1346,6 +1449,9 @@ packages: resolution: {integrity: sha512-2QF/g9/zTaPDc3BjNcVTGoBbXBgYfMTTceLaYcFJ/W9kggFUkhxD/hMEeuLKbugyef9SqAx8cpgwlIP/jinUTA==} engines: {node: '>=4'} + emmet@2.4.11: + resolution: {integrity: sha512-23QPJB3moh/U9sT4rQzGgeyyGIrcM+GH5uVYg2C6wZIxAIJq7Ng3QLT79tl8FUwDXhyq9SusfknOrofAKqvgyQ==} + emoji-regex@10.4.0: resolution: {integrity: sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==} @@ -1378,6 +1484,10 @@ packages: engines: {node: '>=18'} hasBin: true + escalade@3.2.0: + resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} + engines: {node: '>=6'} + escape-string-regexp@5.0.0: resolution: {integrity: sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==} engines: {node: '>=12'} @@ -1421,6 +1531,9 @@ packages: fast-deep-equal@3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + fast-uri@3.1.0: + resolution: {integrity: sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==} + fdir@6.4.6: resolution: {integrity: sha512-hiFoqpyZcfNm1yc4u8oWCf9A2c4D3QjCrks3zmoVKVxpQRzmPNar1hUJcBG2RQHvEVGDN+Jm81ZheVLAQMK6+w==} peerDependencies: @@ -1429,6 +1542,15 @@ packages: picomatch: optional: true + fdir@6.5.0: + resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==} + engines: {node: '>=12.0.0'} + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true + flattie@1.1.1: resolution: {integrity: sha512-9UbaD6XdAL97+k/n+N7JwX46K/M6Zc6KcFYskrYL8wbBV/Uyk0CTAMY0VT+qiK5PM7AIc9aTWYtq65U7T+aCNQ==} engines: {node: '>=8'} @@ -1444,6 +1566,10 @@ packages: engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} os: [darwin] + get-caller-file@2.0.5: + resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} + engines: {node: 6.* || 8.* || >= 10.*} + get-east-asian-width@1.3.0: resolution: {integrity: sha512-vpeMIQKxczTD/0s2CdEWHcb0eeJe6TFjxb+J5xgX7hScxqrGuyjmv4c1D4A/gelKfyox0gJJwIHF+fLjeaM8kQ==} engines: {node: '>=18'} @@ -1615,6 +1741,15 @@ packages: resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} hasBin: true + json-schema-traverse@1.0.0: + resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} + + jsonc-parser@2.3.1: + resolution: {integrity: sha512-H8jvkz1O50L3dMZCsLqiuB2tA7muqbSg1AtGEkN0leAqGjsUzDJir3Zwr02BhqdcITPg3ei3mZ+HjMocAknhhg==} + + jsonc-parser@3.3.1: + resolution: {integrity: sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==} + katex@0.16.22: resolution: {integrity: sha512-XCHRdUw4lf3SKBaJe4EvgqIuWwkPSo9XoeO8GjQW94Bp7TWv9hNhzZjZ+OH9yf1UmLygb7DIT5GSFQiyt16zYg==} hasBin: true @@ -1926,6 +2061,9 @@ packages: ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + muggle-string@0.4.1: + resolution: {integrity: sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ==} + nanoid@3.3.11: resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} @@ -1999,6 +2137,9 @@ packages: parse5@7.3.0: resolution: {integrity: sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==} + path-browserify@1.0.1: + resolution: {integrity: sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==} + path-data-parser@0.1.0: resolution: {integrity: sha512-NOnmBpt5Y2RWbuv0LMzsayp3lVylAHLPUTut412ZA3l+C4uw4ZVkQbjShYCQ8TCpUMdPapr4YjUqLYD6v68j+w==} @@ -2020,6 +2161,10 @@ packages: resolution: {integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==} engines: {node: '>=12'} + picomatch@4.0.4: + resolution: {integrity: sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==} + engines: {node: '>=12'} + pkg-types@1.3.1: resolution: {integrity: sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==} @@ -2206,6 +2351,20 @@ packages: remark-stringify@11.0.0: resolution: {integrity: sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==} + request-light@0.5.8: + resolution: {integrity: sha512-3Zjgh+8b5fhRJBQZoy+zbVKpAQGLyka0MPgW3zruTF4dFFJ8Fqcfu9YsAvi/rvdcaTeWG3MkbZv4WKxAn/84Lg==} + + request-light@0.7.0: + resolution: {integrity: sha512-lMbBMrDoxgsyO+yB3sDcrDuX85yYt7sS8BfQd11jtbW/z5ZWgLZRcEGLsLoYw7I0WSUGQBs8CC8ScIxkTX1+6Q==} + + require-directory@2.1.1: + resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} + engines: {node: '>=0.10.0'} + + require-from-string@2.0.2: + resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} + engines: {node: '>=0.10.0'} + restructure@3.0.2: resolution: {integrity: sha512-gSfoiOEA0VPE6Tukkrr7I0RBdE0s7H1eFCDBk05l1KIQT1UIKNc5JZy6jdyW6eYH3aR3g5b3PuL77rq0hvwtAw==} @@ -2376,6 +2535,10 @@ packages: resolution: {integrity: sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==} engines: {node: '>=12.0.0'} + tinyglobby@0.2.16: + resolution: {integrity: sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==} + engines: {node: '>=12.0.0'} + trim-lines@3.0.1: resolution: {integrity: sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==} @@ -2403,8 +2566,14 @@ packages: resolution: {integrity: sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==} engines: {node: '>=16'} - typescript@5.8.3: - resolution: {integrity: sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==} + typesafe-path@0.2.2: + resolution: {integrity: sha512-OJabfkAg1WLZSqJAJ0Z6Sdt3utnbzr/jh+NAHoyWHJe8CMSy79Gm085094M9nvTPy22KzTVn5Zq5mbapCI/hPA==} + + typescript-auto-import-cache@0.3.6: + resolution: {integrity: sha512-RpuHXrknHdVdK7wv/8ug3Fr0WNsNi5l5aB8MYYuXhq2UH5lnEB1htJ1smhtD5VeCsGr2p8mUDtd83LCQDFVgjQ==} + + typescript@5.9.3: + resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==} engines: {node: '>=14.17'} hasBin: true @@ -2588,6 +2757,75 @@ packages: vite: optional: true + volar-service-css@0.0.70: + resolution: {integrity: sha512-K1qyOvBpE3rzdAv3e4/6Rv5yizrYPy5R/ne3IWCAzLBuMO4qBMV3kSqWzj6KUVe6S0AnN6wxF7cRkiaKfYMYJw==} + peerDependencies: + '@volar/language-service': ~2.4.0 + peerDependenciesMeta: + '@volar/language-service': + optional: true + + volar-service-emmet@0.0.70: + resolution: {integrity: sha512-xi5bC4m/VyE3zy/n2CXspKeDZs3qA41tHLTw275/7dNWM/RqE2z3BnDICQybHIVp/6G1iOQj5c1qXMgQC08TNg==} + peerDependencies: + '@volar/language-service': ~2.4.0 + peerDependenciesMeta: + '@volar/language-service': + optional: true + + volar-service-html@0.0.70: + resolution: {integrity: sha512-eR6vCgMdmYAo4n+gcT7DSyBQbwB8S3HZZvSagTf0sxNaD4WppMCFfpqWnkrlGStPKMZvMiejRRVmqsX9dYcTvQ==} + peerDependencies: + '@volar/language-service': ~2.4.0 + peerDependenciesMeta: + '@volar/language-service': + optional: true + + volar-service-prettier@0.0.70: + resolution: {integrity: sha512-Z6BCFSpGVCd8BPAsZ785Kce1BGlWd5ODqmqZGVuB14MJvrR4+CYz6cDy4F+igmE1gMifqfvMhdgT8Aud4M5ngg==} + peerDependencies: + '@volar/language-service': ~2.4.0 + prettier: ^2.2 || ^3.0 + peerDependenciesMeta: + '@volar/language-service': + optional: true + prettier: + optional: true + + volar-service-typescript-twoslash-queries@0.0.70: + resolution: {integrity: sha512-IdD13Z9N2Bu8EM6CM0fDV1E69olEYGHDU25X51YXmq8Y0CmJ2LNj6gOiBJgpS5JGUqFzECVhMNBW7R0sPdRTMQ==} + peerDependencies: + '@volar/language-service': ~2.4.0 + peerDependenciesMeta: + '@volar/language-service': + optional: true + + volar-service-typescript@0.0.70: + resolution: {integrity: sha512-l46Bx4cokkUedTd74ojO5H/zqHZJ8SUuyZ0IB8JN4jfRqUM3bQFBHoOwlZCyZmOeO0A3RQNkMnFclxO4c++gsg==} + peerDependencies: + '@volar/language-service': ~2.4.0 + peerDependenciesMeta: + '@volar/language-service': + optional: true + + volar-service-yaml@0.0.70: + resolution: {integrity: sha512-0c8bXDBeoATF9F6iPIlOuYTuZAC4c+yi0siQo920u7eiBJk8oQmUmg9cDUbR4+Gl++bvGP4plj3fErbJuPqdcQ==} + peerDependencies: + '@volar/language-service': ~2.4.0 + peerDependenciesMeta: + '@volar/language-service': + optional: true + + vscode-css-languageservice@6.3.10: + resolution: {integrity: sha512-eq5N9Er3fC4vA9zd9EFhyBG90wtCCuXgRSpAndaOgXMh1Wgep5lBgRIeDgjZBW9pa+332yC9+49cZMW8jcL3MA==} + + vscode-html-languageservice@5.6.2: + resolution: {integrity: sha512-ulCrSnFnfQ16YzvwnYUgEbUEl/ZG7u2eV27YhvLObSHKkb8fw1Z9cgsnUwjTEeDIdJDoTDTDpxuhQwoenoLNMg==} + + vscode-json-languageservice@4.1.8: + resolution: {integrity: sha512-0vSpg6Xd9hfV+eZAaYN63xVVMOTmJ4GgHxXnkLCh+9RsQBkWKIghzLhW2B9ebfG+LQQg8uLtsQ2aUKjTgE+QOg==} + engines: {npm: '>=7.0.0'} + vscode-jsonrpc@8.2.0: resolution: {integrity: sha512-C+r0eKJUIfiDIfwJhria30+TYWPtuHJXHtI7J0YlOmKAo7ogxP20T0zxB7HZQIFhIyvoBPwWskjxrvAtfjyZfA==} engines: {node: '>=14.0.0'} @@ -2605,9 +2843,15 @@ packages: resolution: {integrity: sha512-woByF3PDpkHFUreUa7Hos7+pUWdeWMXRd26+ZX2A8cFx6v/JPTtd4/uN0/jB6XQHYaOlHbio03NTHCqrgG5n7g==} hasBin: true + vscode-nls@5.2.0: + resolution: {integrity: sha512-RAaHx7B14ZU04EU31pT+rKz2/zSl7xMsfIZuo8pd+KZO6PXtQmpevpq3vxvWNcrGbdmhM/rr5Uw5Mz+NBfhVng==} + vscode-uri@3.0.8: resolution: {integrity: sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw==} + vscode-uri@3.1.0: + resolution: {integrity: sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ==} + web-namespaces@2.0.1: resolution: {integrity: sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ==} @@ -2619,6 +2863,10 @@ packages: resolution: {integrity: sha512-c9bZp7b5YtRj2wOe6dlj32MK+Bx/M/d+9VB2SHM1OtsUHR0aV0tdP6DWh/iMt0kWi1t5g1Iudu6hQRNd1A4PVA==} engines: {node: '>=18'} + wrap-ansi@7.0.0: + resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} + engines: {node: '>=10'} + wrap-ansi@9.0.0: resolution: {integrity: sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==} engines: {node: '>=18'} @@ -2626,10 +2874,32 @@ packages: xxhash-wasm@1.1.0: resolution: {integrity: sha512-147y/6YNh+tlp6nd/2pWq38i9h6mz/EuQ6njIrmW8D1BS5nCqs0P6DG+m6zTGnNz5I+uhZ0SHxBs9BsPrwcKDA==} + y18n@5.0.8: + resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} + engines: {node: '>=10'} + + yaml-language-server@1.20.0: + resolution: {integrity: sha512-qhjK/bzSRZ6HtTvgeFvjNPJGWdZ0+x5NREV/9XZWFjIGezew2b4r5JPy66IfOhd5OA7KeFwk1JfmEbnTvev0cA==} + hasBin: true + + yaml@2.7.1: + resolution: {integrity: sha512-10ULxpnOCQXxJvBgxsn9ptjq6uviG/htZKk9veJGhlqn3w/DxQ631zFF+nlQXLwmImeS5amR2dl2U8sg6U9jsQ==} + engines: {node: '>= 14'} + hasBin: true + + yaml@2.8.3: + resolution: {integrity: sha512-AvbaCLOO2Otw/lW5bmh9d/WEdcDFdQp2Z2ZUH3pX9U2ihyUY0nvLv7J6TrWowklRGPYbB/IuIMfYgxaCPg5Bpg==} + engines: {node: '>= 14.6'} + hasBin: true + yargs-parser@21.1.1: resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} engines: {node: '>=12'} + yargs@17.7.2: + resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} + engines: {node: '>=12'} + yocto-queue@1.2.1: resolution: {integrity: sha512-AyeEbWOu/TAXdxlV9wmGcR0+yh2j3vYPGOECcIj2S7MkrLyC7ne+oye2BKTItt0ii2PHk4cDy+95+LshzbXnGg==} engines: {node: '>=12.20'} @@ -2671,14 +2941,53 @@ snapshots: '@antfu/utils@9.3.0': {} + '@astrojs/check@0.9.8(prettier-plugin-astro@0.14.1)(prettier@3.6.2)(typescript@5.9.3)': + dependencies: + '@astrojs/language-server': 2.16.6(prettier-plugin-astro@0.14.1)(prettier@3.6.2)(typescript@5.9.3) + chokidar: 4.0.3 + kleur: 4.1.5 + typescript: 5.9.3 + yargs: 17.7.2 + transitivePeerDependencies: + - prettier + - prettier-plugin-astro + '@astrojs/compiler@2.12.2': {} + '@astrojs/compiler@2.13.1': {} + '@astrojs/internal-helpers@0.6.1': {} '@astrojs/internal-helpers@0.7.1': {} '@astrojs/internal-helpers@0.7.4': {} + '@astrojs/language-server@2.16.6(prettier-plugin-astro@0.14.1)(prettier@3.6.2)(typescript@5.9.3)': + dependencies: + '@astrojs/compiler': 2.13.1 + '@astrojs/yaml2ts': 0.2.3 + '@jridgewell/sourcemap-codec': 1.5.5 + '@volar/kit': 2.4.28(typescript@5.9.3) + '@volar/language-core': 2.4.28 + '@volar/language-server': 2.4.28 + '@volar/language-service': 2.4.28 + muggle-string: 0.4.1 + tinyglobby: 0.2.16 + volar-service-css: 0.0.70(@volar/language-service@2.4.28) + volar-service-emmet: 0.0.70(@volar/language-service@2.4.28) + volar-service-html: 0.0.70(@volar/language-service@2.4.28) + volar-service-prettier: 0.0.70(@volar/language-service@2.4.28)(prettier@3.6.2) + volar-service-typescript: 0.0.70(@volar/language-service@2.4.28) + volar-service-typescript-twoslash-queries: 0.0.70(@volar/language-service@2.4.28) + volar-service-yaml: 0.0.70(@volar/language-service@2.4.28) + vscode-html-languageservice: 5.6.2 + vscode-uri: 3.1.0 + optionalDependencies: + prettier: 3.6.2 + prettier-plugin-astro: 0.14.1 + transitivePeerDependencies: + - typescript + '@astrojs/markdown-remark@6.3.2': dependencies: '@astrojs/internal-helpers': 0.6.1 @@ -2757,12 +3066,12 @@ snapshots: transitivePeerDependencies: - supports-color - '@astrojs/mdx@4.3.0(astro@5.15.4(@types/node@24.0.10)(jiti@2.6.1)(lightningcss@1.30.2)(rollup@4.44.1)(typescript@5.8.3))': + '@astrojs/mdx@4.3.0(astro@5.15.4(@types/node@24.0.10)(jiti@2.6.1)(lightningcss@1.30.2)(rollup@4.44.1)(typescript@5.9.3)(yaml@2.8.3))': dependencies: '@astrojs/markdown-remark': 6.3.2 '@mdx-js/mdx': 3.1.0(acorn@8.15.0) acorn: 8.15.0 - astro: 5.15.4(@types/node@24.0.10)(jiti@2.6.1)(lightningcss@1.30.2)(rollup@4.44.1)(typescript@5.8.3) + astro: 5.15.4(@types/node@24.0.10)(jiti@2.6.1)(lightningcss@1.30.2)(rollup@4.44.1)(typescript@5.9.3)(yaml@2.8.3) es-module-lexer: 1.7.0 estree-util-visit: 2.0.0 hast-util-to-html: 9.0.5 @@ -2786,22 +3095,22 @@ snapshots: stream-replace-string: 2.0.0 zod: 3.25.69 - '@astrojs/starlight-tailwind@4.0.2(@astrojs/starlight@0.36.2(astro@5.15.4(@types/node@24.0.10)(jiti@2.6.1)(lightningcss@1.30.2)(rollup@4.44.1)(typescript@5.8.3)))(tailwindcss@4.1.17)': + '@astrojs/starlight-tailwind@4.0.2(@astrojs/starlight@0.36.2(astro@5.15.4(@types/node@24.0.10)(jiti@2.6.1)(lightningcss@1.30.2)(rollup@4.44.1)(typescript@5.9.3)(yaml@2.8.3)))(tailwindcss@4.1.17)': dependencies: - '@astrojs/starlight': 0.36.2(astro@5.15.4(@types/node@24.0.10)(jiti@2.6.1)(lightningcss@1.30.2)(rollup@4.44.1)(typescript@5.8.3)) + '@astrojs/starlight': 0.36.2(astro@5.15.4(@types/node@24.0.10)(jiti@2.6.1)(lightningcss@1.30.2)(rollup@4.44.1)(typescript@5.9.3)(yaml@2.8.3)) tailwindcss: 4.1.17 - '@astrojs/starlight@0.36.2(astro@5.15.4(@types/node@24.0.10)(jiti@2.6.1)(lightningcss@1.30.2)(rollup@4.44.1)(typescript@5.8.3))': + '@astrojs/starlight@0.36.2(astro@5.15.4(@types/node@24.0.10)(jiti@2.6.1)(lightningcss@1.30.2)(rollup@4.44.1)(typescript@5.9.3)(yaml@2.8.3))': dependencies: '@astrojs/markdown-remark': 6.3.5 - '@astrojs/mdx': 4.3.0(astro@5.15.4(@types/node@24.0.10)(jiti@2.6.1)(lightningcss@1.30.2)(rollup@4.44.1)(typescript@5.8.3)) + '@astrojs/mdx': 4.3.0(astro@5.15.4(@types/node@24.0.10)(jiti@2.6.1)(lightningcss@1.30.2)(rollup@4.44.1)(typescript@5.9.3)(yaml@2.8.3)) '@astrojs/sitemap': 3.4.1 '@pagefind/default-ui': 1.3.0 '@types/hast': 3.0.4 '@types/js-yaml': 4.0.9 '@types/mdast': 4.0.4 - astro: 5.15.4(@types/node@24.0.10)(jiti@2.6.1)(lightningcss@1.30.2)(rollup@4.44.1)(typescript@5.8.3) - astro-expressive-code: 0.41.2(astro@5.15.4(@types/node@24.0.10)(jiti@2.6.1)(lightningcss@1.30.2)(rollup@4.44.1)(typescript@5.8.3)) + astro: 5.15.4(@types/node@24.0.10)(jiti@2.6.1)(lightningcss@1.30.2)(rollup@4.44.1)(typescript@5.9.3)(yaml@2.8.3) + astro-expressive-code: 0.41.2(astro@5.15.4(@types/node@24.0.10)(jiti@2.6.1)(lightningcss@1.30.2)(rollup@4.44.1)(typescript@5.9.3)(yaml@2.8.3)) bcp-47: 2.1.0 hast-util-from-html: 2.0.3 hast-util-select: 6.0.4 @@ -2836,6 +3145,10 @@ snapshots: transitivePeerDependencies: - supports-color + '@astrojs/yaml2ts@0.2.3': + dependencies: + yaml: 2.8.3 + '@babel/helper-string-parser@7.27.1': {} '@babel/helper-validator-identifier@7.27.1': {} @@ -2876,6 +3189,29 @@ snapshots: '@ctrl/tinycolor@4.1.0': {} + '@emmetio/abbreviation@2.3.3': + dependencies: + '@emmetio/scanner': 1.0.4 + + '@emmetio/css-abbreviation@2.1.8': + dependencies: + '@emmetio/scanner': 1.0.4 + + '@emmetio/css-parser@0.4.1': + dependencies: + '@emmetio/stream-reader': 2.2.0 + '@emmetio/stream-reader-utils': 0.1.0 + + '@emmetio/html-matcher@1.3.0': + dependencies: + '@emmetio/scanner': 1.0.4 + + '@emmetio/scanner@1.0.4': {} + + '@emmetio/stream-reader-utils@0.1.0': {} + + '@emmetio/stream-reader@2.2.0': {} + '@emnapi/runtime@1.7.0': dependencies: tslib: 2.8.1 @@ -3365,12 +3701,12 @@ snapshots: '@tailwindcss/oxide-win32-arm64-msvc': 4.1.17 '@tailwindcss/oxide-win32-x64-msvc': 4.1.17 - '@tailwindcss/vite@4.1.17(vite@6.4.1(@types/node@24.0.10)(jiti@2.6.1)(lightningcss@1.30.2))': + '@tailwindcss/vite@4.1.17(vite@6.4.1(@types/node@24.0.10)(jiti@2.6.1)(lightningcss@1.30.2)(yaml@2.8.3))': dependencies: '@tailwindcss/node': 4.1.17 '@tailwindcss/oxide': 4.1.17 tailwindcss: 4.1.17 - vite: 6.4.1(@types/node@24.0.10)(jiti@2.6.1)(lightningcss@1.30.2) + vite: 6.4.1(@types/node@24.0.10)(jiti@2.6.1)(lightningcss@1.30.2)(yaml@2.8.3) '@types/d3-array@3.2.1': {} @@ -3544,12 +3880,73 @@ snapshots: '@ungap/structured-clone@1.3.0': {} + '@volar/kit@2.4.28(typescript@5.9.3)': + dependencies: + '@volar/language-service': 2.4.28 + '@volar/typescript': 2.4.28 + typesafe-path: 0.2.2 + typescript: 5.9.3 + vscode-languageserver-textdocument: 1.0.12 + vscode-uri: 3.1.0 + + '@volar/language-core@2.4.28': + dependencies: + '@volar/source-map': 2.4.28 + + '@volar/language-server@2.4.28': + dependencies: + '@volar/language-core': 2.4.28 + '@volar/language-service': 2.4.28 + '@volar/typescript': 2.4.28 + path-browserify: 1.0.1 + request-light: 0.7.0 + vscode-languageserver: 9.0.1 + vscode-languageserver-protocol: 3.17.5 + vscode-languageserver-textdocument: 1.0.12 + vscode-uri: 3.1.0 + + '@volar/language-service@2.4.28': + dependencies: + '@volar/language-core': 2.4.28 + vscode-languageserver-protocol: 3.17.5 + vscode-languageserver-textdocument: 1.0.12 + vscode-uri: 3.1.0 + + '@volar/source-map@2.4.28': {} + + '@volar/typescript@2.4.28': + dependencies: + '@volar/language-core': 2.4.28 + path-browserify: 1.0.1 + vscode-uri: 3.1.0 + + '@vscode/emmet-helper@2.11.0': + dependencies: + emmet: 2.4.11 + jsonc-parser: 2.3.1 + vscode-languageserver-textdocument: 1.0.12 + vscode-languageserver-types: 3.17.5 + vscode-uri: 3.1.0 + + '@vscode/l10n@0.0.18': {} + acorn-jsx@5.3.2(acorn@8.15.0): dependencies: acorn: 8.15.0 acorn@8.15.0: {} + ajv-draft-04@1.0.0(ajv@8.18.0): + optionalDependencies: + ajv: 8.18.0 + + ajv@8.18.0: + dependencies: + fast-deep-equal: 3.1.3 + fast-uri: 3.1.0 + json-schema-traverse: 1.0.0 + require-from-string: 2.0.2 + ansi-align@3.0.1: dependencies: string-width: 4.2.3 @@ -3562,6 +3959,10 @@ snapshots: ansi-regex@6.1.0: {} + ansi-styles@4.3.0: + dependencies: + color-convert: 2.0.1 + ansi-styles@6.2.1: {} anymatch@3.1.3: @@ -3579,20 +3980,20 @@ snapshots: astring@1.9.0: {} - astro-expressive-code@0.41.2(astro@5.15.4(@types/node@24.0.10)(jiti@2.6.1)(lightningcss@1.30.2)(rollup@4.44.1)(typescript@5.8.3)): + astro-expressive-code@0.41.2(astro@5.15.4(@types/node@24.0.10)(jiti@2.6.1)(lightningcss@1.30.2)(rollup@4.44.1)(typescript@5.9.3)(yaml@2.8.3)): dependencies: - astro: 5.15.4(@types/node@24.0.10)(jiti@2.6.1)(lightningcss@1.30.2)(rollup@4.44.1)(typescript@5.8.3) + astro: 5.15.4(@types/node@24.0.10)(jiti@2.6.1)(lightningcss@1.30.2)(rollup@4.44.1)(typescript@5.9.3)(yaml@2.8.3) rehype-expressive-code: 0.41.2 - astro-mermaid@1.1.0(astro@5.15.4(@types/node@24.0.10)(jiti@2.6.1)(lightningcss@1.30.2)(rollup@4.44.1)(typescript@5.8.3))(mermaid@11.12.1): + astro-mermaid@1.1.0(astro@5.15.4(@types/node@24.0.10)(jiti@2.6.1)(lightningcss@1.30.2)(rollup@4.44.1)(typescript@5.9.3)(yaml@2.8.3))(mermaid@11.12.1): dependencies: - astro: 5.15.4(@types/node@24.0.10)(jiti@2.6.1)(lightningcss@1.30.2)(rollup@4.44.1)(typescript@5.8.3) + astro: 5.15.4(@types/node@24.0.10)(jiti@2.6.1)(lightningcss@1.30.2)(rollup@4.44.1)(typescript@5.9.3)(yaml@2.8.3) import-meta-resolve: 4.2.0 mdast-util-to-string: 4.0.0 mermaid: 11.12.1 unist-util-visit: 5.0.0 - astro@5.15.4(@types/node@24.0.10)(jiti@2.6.1)(lightningcss@1.30.2)(rollup@4.44.1)(typescript@5.8.3): + astro@5.15.4(@types/node@24.0.10)(jiti@2.6.1)(lightningcss@1.30.2)(rollup@4.44.1)(typescript@5.9.3)(yaml@2.8.3): dependencies: '@astrojs/compiler': 2.12.2 '@astrojs/internal-helpers': 0.7.4 @@ -3642,20 +4043,20 @@ snapshots: smol-toml: 1.4.2 tinyexec: 1.0.1 tinyglobby: 0.2.14 - tsconfck: 3.1.6(typescript@5.8.3) + tsconfck: 3.1.6(typescript@5.9.3) ultrahtml: 1.6.0 unifont: 0.6.0 unist-util-visit: 5.0.0 unstorage: 1.17.2 vfile: 6.0.3 - vite: 6.4.1(@types/node@24.0.10)(jiti@2.6.1)(lightningcss@1.30.2) - vitefu: 1.1.1(vite@6.4.1(@types/node@24.0.10)(jiti@2.6.1)(lightningcss@1.30.2)) + vite: 6.4.1(@types/node@24.0.10)(jiti@2.6.1)(lightningcss@1.30.2)(yaml@2.8.3) + vitefu: 1.1.1(vite@6.4.1(@types/node@24.0.10)(jiti@2.6.1)(lightningcss@1.30.2)(yaml@2.8.3)) xxhash-wasm: 1.1.0 yargs-parser: 21.1.1 yocto-spinner: 0.2.3 zod: 3.25.76 zod-to-json-schema: 3.24.6(zod@3.25.76) - zod-to-ts: 1.2.0(typescript@5.8.3)(zod@3.25.76) + zod-to-ts: 1.2.0(typescript@5.9.3)(zod@3.25.76) optionalDependencies: sharp: 0.34.5 transitivePeerDependencies: @@ -3762,12 +4163,24 @@ snapshots: cli-boxes@3.0.0: {} + cliui@8.0.1: + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 7.0.0 + clone@2.1.2: {} clsx@2.1.1: {} collapse-white-space@2.1.0: {} + color-convert@2.0.1: + dependencies: + color-name: 1.1.4 + + color-name@1.1.4: {} + comma-separated-tokens@2.0.3: {} commander@7.2.0: {} @@ -4039,6 +4452,11 @@ snapshots: dset@3.1.4: {} + emmet@2.4.11: + dependencies: + '@emmetio/abbreviation': 2.3.3 + '@emmetio/css-abbreviation': 2.1.8 + emoji-regex@10.4.0: {} emoji-regex@8.0.0: {} @@ -4096,6 +4514,8 @@ snapshots: '@esbuild/win32-ia32': 0.25.5 '@esbuild/win32-x64': 0.25.5 + escalade@3.2.0: {} + escape-string-regexp@5.0.0: {} estree-util-attach-comments@3.0.0: @@ -4148,6 +4568,8 @@ snapshots: fast-deep-equal@3.1.3: {} + fast-uri@3.1.0: {} + fdir@6.4.6(picomatch@4.0.2): optionalDependencies: picomatch: 4.0.2 @@ -4156,6 +4578,10 @@ snapshots: optionalDependencies: picomatch: 4.0.3 + fdir@6.5.0(picomatch@4.0.4): + optionalDependencies: + picomatch: 4.0.4 + flattie@1.1.1: {} fontace@0.3.0: @@ -4178,6 +4604,8 @@ snapshots: fsevents@2.3.3: optional: true + get-caller-file@2.0.5: {} + get-east-asian-width@1.3.0: {} git-hooks-list@4.1.1: {} @@ -4454,6 +4882,12 @@ snapshots: dependencies: argparse: 2.0.1 + json-schema-traverse@1.0.0: {} + + jsonc-parser@2.3.1: {} + + jsonc-parser@3.3.1: {} + katex@0.16.22: dependencies: commander: 8.3.0 @@ -5052,6 +5486,8 @@ snapshots: ms@2.1.3: {} + muggle-string@0.4.1: {} + nanoid@3.3.11: {} neotraverse@0.6.18: {} @@ -5134,6 +5570,8 @@ snapshots: dependencies: entities: 6.0.1 + path-browserify@1.0.1: {} + path-data-parser@0.1.0: {} pathe@2.0.3: {} @@ -5146,6 +5584,8 @@ snapshots: picomatch@4.0.3: {} + picomatch@4.0.4: {} + pkg-types@1.3.1: dependencies: confbox: 0.1.8 @@ -5358,6 +5798,14 @@ snapshots: mdast-util-to-markdown: 2.1.2 unified: 11.0.5 + request-light@0.5.8: {} + + request-light@0.7.0: {} + + require-directory@2.1.1: {} + + require-from-string@2.0.2: {} + restructure@3.0.2: {} retext-latin@4.0.0: @@ -5520,9 +5968,9 @@ snapshots: space-separated-tokens@2.0.2: {} - starlight-links-validator@0.19.1(@astrojs/starlight@0.36.2(astro@5.15.4(@types/node@24.0.10)(jiti@2.6.1)(lightningcss@1.30.2)(rollup@4.44.1)(typescript@5.8.3))): + starlight-links-validator@0.19.1(@astrojs/starlight@0.36.2(astro@5.15.4(@types/node@24.0.10)(jiti@2.6.1)(lightningcss@1.30.2)(rollup@4.44.1)(typescript@5.9.3)(yaml@2.8.3))): dependencies: - '@astrojs/starlight': 0.36.2(astro@5.15.4(@types/node@24.0.10)(jiti@2.6.1)(lightningcss@1.30.2)(rollup@4.44.1)(typescript@5.8.3)) + '@astrojs/starlight': 0.36.2(astro@5.15.4(@types/node@24.0.10)(jiti@2.6.1)(lightningcss@1.30.2)(rollup@4.44.1)(typescript@5.9.3)(yaml@2.8.3)) '@types/picomatch': 3.0.2 github-slugger: 2.0.0 hast-util-from-html: 2.0.3 @@ -5607,21 +6055,32 @@ snapshots: fdir: 6.4.6(picomatch@4.0.2) picomatch: 4.0.2 + tinyglobby@0.2.16: + dependencies: + fdir: 6.5.0(picomatch@4.0.4) + picomatch: 4.0.4 + trim-lines@3.0.1: {} trough@2.2.0: {} ts-dedent@2.2.0: {} - tsconfck@3.1.6(typescript@5.8.3): + tsconfck@3.1.6(typescript@5.9.3): optionalDependencies: - typescript: 5.8.3 + typescript: 5.9.3 tslib@2.8.1: {} type-fest@4.41.0: {} - typescript@5.8.3: {} + typesafe-path@0.2.2: {} + + typescript-auto-import-cache@0.3.6: + dependencies: + semver: 7.7.3 + + typescript@5.9.3: {} ufo@1.6.1: {} @@ -5733,7 +6192,7 @@ snapshots: '@types/unist': 3.0.3 vfile-message: 4.0.2 - vite@6.4.1(@types/node@24.0.10)(jiti@2.6.1)(lightningcss@1.30.2): + vite@6.4.1(@types/node@24.0.10)(jiti@2.6.1)(lightningcss@1.30.2)(yaml@2.8.3): dependencies: esbuild: 0.25.5 fdir: 6.4.6(picomatch@4.0.3) @@ -5746,10 +6205,89 @@ snapshots: fsevents: 2.3.3 jiti: 2.6.1 lightningcss: 1.30.2 + yaml: 2.8.3 - vitefu@1.1.1(vite@6.4.1(@types/node@24.0.10)(jiti@2.6.1)(lightningcss@1.30.2)): + vitefu@1.1.1(vite@6.4.1(@types/node@24.0.10)(jiti@2.6.1)(lightningcss@1.30.2)(yaml@2.8.3)): optionalDependencies: - vite: 6.4.1(@types/node@24.0.10)(jiti@2.6.1)(lightningcss@1.30.2) + vite: 6.4.1(@types/node@24.0.10)(jiti@2.6.1)(lightningcss@1.30.2)(yaml@2.8.3) + + volar-service-css@0.0.70(@volar/language-service@2.4.28): + dependencies: + vscode-css-languageservice: 6.3.10 + vscode-languageserver-textdocument: 1.0.12 + vscode-uri: 3.1.0 + optionalDependencies: + '@volar/language-service': 2.4.28 + + volar-service-emmet@0.0.70(@volar/language-service@2.4.28): + dependencies: + '@emmetio/css-parser': 0.4.1 + '@emmetio/html-matcher': 1.3.0 + '@vscode/emmet-helper': 2.11.0 + vscode-uri: 3.1.0 + optionalDependencies: + '@volar/language-service': 2.4.28 + + volar-service-html@0.0.70(@volar/language-service@2.4.28): + dependencies: + vscode-html-languageservice: 5.6.2 + vscode-languageserver-textdocument: 1.0.12 + vscode-uri: 3.1.0 + optionalDependencies: + '@volar/language-service': 2.4.28 + + volar-service-prettier@0.0.70(@volar/language-service@2.4.28)(prettier@3.6.2): + dependencies: + vscode-uri: 3.1.0 + optionalDependencies: + '@volar/language-service': 2.4.28 + prettier: 3.6.2 + + volar-service-typescript-twoslash-queries@0.0.70(@volar/language-service@2.4.28): + dependencies: + vscode-uri: 3.1.0 + optionalDependencies: + '@volar/language-service': 2.4.28 + + volar-service-typescript@0.0.70(@volar/language-service@2.4.28): + dependencies: + path-browserify: 1.0.1 + semver: 7.7.3 + typescript-auto-import-cache: 0.3.6 + vscode-languageserver-textdocument: 1.0.12 + vscode-nls: 5.2.0 + vscode-uri: 3.1.0 + optionalDependencies: + '@volar/language-service': 2.4.28 + + volar-service-yaml@0.0.70(@volar/language-service@2.4.28): + dependencies: + vscode-uri: 3.1.0 + yaml-language-server: 1.20.0 + optionalDependencies: + '@volar/language-service': 2.4.28 + + vscode-css-languageservice@6.3.10: + dependencies: + '@vscode/l10n': 0.0.18 + vscode-languageserver-textdocument: 1.0.12 + vscode-languageserver-types: 3.17.5 + vscode-uri: 3.1.0 + + vscode-html-languageservice@5.6.2: + dependencies: + '@vscode/l10n': 0.0.18 + vscode-languageserver-textdocument: 1.0.12 + vscode-languageserver-types: 3.17.5 + vscode-uri: 3.1.0 + + vscode-json-languageservice@4.1.8: + dependencies: + jsonc-parser: 3.3.1 + vscode-languageserver-textdocument: 1.0.12 + vscode-languageserver-types: 3.17.5 + vscode-nls: 5.2.0 + vscode-uri: 3.1.0 vscode-jsonrpc@8.2.0: {} @@ -5766,8 +6304,12 @@ snapshots: dependencies: vscode-languageserver-protocol: 3.17.5 + vscode-nls@5.2.0: {} + vscode-uri@3.0.8: {} + vscode-uri@3.1.0: {} + web-namespaces@2.0.1: {} which-pm-runs@1.1.0: {} @@ -5776,6 +6318,12 @@ snapshots: dependencies: string-width: 7.2.0 + wrap-ansi@7.0.0: + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi@9.0.0: dependencies: ansi-styles: 6.2.1 @@ -5784,8 +6332,38 @@ snapshots: xxhash-wasm@1.1.0: {} + y18n@5.0.8: {} + + yaml-language-server@1.20.0: + dependencies: + '@vscode/l10n': 0.0.18 + ajv: 8.18.0 + ajv-draft-04: 1.0.0(ajv@8.18.0) + prettier: 3.6.2 + request-light: 0.5.8 + vscode-json-languageservice: 4.1.8 + vscode-languageserver: 9.0.1 + vscode-languageserver-textdocument: 1.0.12 + vscode-languageserver-types: 3.17.5 + vscode-uri: 3.1.0 + yaml: 2.7.1 + + yaml@2.7.1: {} + + yaml@2.8.3: {} + yargs-parser@21.1.1: {} + yargs@17.7.2: + dependencies: + cliui: 8.0.1 + escalade: 3.2.0 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + string-width: 4.2.3 + y18n: 5.0.8 + yargs-parser: 21.1.1 + yocto-queue@1.2.1: {} yocto-spinner@0.2.3: @@ -5798,9 +6376,9 @@ snapshots: dependencies: zod: 3.25.76 - zod-to-ts@1.2.0(typescript@5.8.3)(zod@3.25.76): + zod-to-ts@1.2.0(typescript@5.9.3)(zod@3.25.76): dependencies: - typescript: 5.8.3 + typescript: 5.9.3 zod: 3.25.76 zod@3.25.69: {} diff --git a/docs/scripts/validate-docs-smoke.mjs b/docs/scripts/validate-docs-smoke.mjs new file mode 100644 index 00000000..7487a6f9 --- /dev/null +++ b/docs/scripts/validate-docs-smoke.mjs @@ -0,0 +1,113 @@ +import { readFileSync } from 'node:fs'; +import path from 'node:path'; +import { fileURLToPath } from 'node:url'; + +const __dirname = path.dirname(fileURLToPath(import.meta.url)); +const docsRoot = path.resolve(__dirname, '..'); +const repoRoot = path.resolve(docsRoot, '..'); + +function read(relativePath, base = repoRoot) { + return readFileSync(path.join(base, relativePath), 'utf8'); +} + +function assert(condition, message) { + if (!condition) { + throw new Error(message); + } +} + +function assertIncludes(content, expected, label) { + assert(content.includes(expected), `${label} is missing expected text: ${expected}`); +} + +const quickStart = read('docs/src/content/docs/essentials/quick-start.mdx'); +const snowflakeCli = read('docs/src/content/docs/guides/snowflake-cli.mdx'); +const troubleshooting = read('docs/src/content/docs/guides/troubleshooting.mdx'); +const runtimeModes = read('docs/src/content/docs/essentials/runtime-modes.mdx'); +const configuration = read('docs/src/content/docs/essentials/configuration.mdx'); +const supportMatrix = read('docs/src/content/docs/essentials/support-matrix.mdx'); +const dbtGuide = read('docs/src/content/docs/guides/dbt.mdx'); +const endToEndDbt = read('docs/src/content/docs/guides/end-to-end-dbt.mdx'); +const docsMaintenance = read('docs/src/content/docs/development/docs-maintenance.mdx'); +const awsLambda = read('docs/src/content/docs/guides/aws-lambda.mdx'); +const s3Tables = read('docs/src/content/docs/guides/s3-tables.mdx'); +const selfHosted = read('docs/src/content/docs/guides/self-hosted.mdx'); +const snowplow = read('docs/src/content/docs/guides/snowplow.mdx'); +const docsReadme = read('docs/README.md'); +const packageJson = JSON.parse(read('docs/package.json')); + +const highTrafficGuides = [ + 'docs/src/content/docs/essentials/quick-start.mdx', + 'docs/src/content/docs/essentials/runtime-modes.mdx', + 'docs/src/content/docs/guides/aws-lambda.mdx', + 'docs/src/content/docs/guides/dbt.mdx', + 'docs/src/content/docs/guides/end-to-end-dbt.mdx', + 'docs/src/content/docs/guides/self-hosted.mdx', + 'docs/src/content/docs/guides/snowplow.mdx', + 'docs/src/content/docs/guides/troubleshooting.mdx', +]; + +for (const guidePath of highTrafficGuides) { + const content = read(guidePath); + assert(/> Owner:/m.test(content), `${guidePath} must include an Owner block near the top`); + assert( + /> Last reviewed:/m.test(content), + `${guidePath} must include a Last reviewed block near the top`, + ); +} + +for (const [content, label] of [ + [quickStart, 'Quick Start'], + [snowflakeCli, 'Snowflake CLI guide'], + [troubleshooting, 'Troubleshooting guide'], +]) { + assertIncludes(content, 'embucket/embucket', label); + assertIncludes(content, '3000', label); + assertIncludes(content, 'embucket', label); +} + +assertIncludes(quickStart, 'http://127.0.0.1:3000/', 'Quick Start'); +assertIncludes(runtimeModes, 'private API Gateway example', 'Runtime modes'); +assertIncludes(configuration, 'METASTORE_CONFIG=./metastore.yaml', 'Configuration guide'); +assertIncludes(configuration, 'volumes: []', 'Configuration guide'); +assertIncludes(snowflakeCli, 'protocol = "http"', 'Snowflake CLI guide'); +assertIncludes(troubleshooting, 'protocol = "http"', 'Troubleshooting guide'); +assertIncludes(selfHosted, 'cargo build', 'Self-hosted guide'); +assertIncludes(selfHosted, 'target/debug/embucketd', 'Self-hosted guide'); +assertIncludes(selfHosted, 'snow connection test', 'Self-hosted guide'); +assertIncludes(selfHosted, 'evaluation and testing', 'Self-hosted guide'); +assertIncludes(selfHosted, 'METASTORE_CONFIG=./metastore.yaml', 'Self-hosted guide'); +assertIncludes(awsLambda, 'AWS::ApiGateway::RestApi', 'AWS Lambda guide'); +assertIncludes(awsLambda, 'AWS::EC2::VPCEndpoint', 'AWS Lambda guide'); +assertIncludes(snowplow, 'embucket-snowplow', 'Snowplow guide'); +assertIncludes(snowplow, 'dbt run', 'Snowplow guide'); +assertIncludes(snowplow, 'dbt show', 'Snowplow guide'); +assertIncludes(snowplow, 'compatibility workaround', 'Snowplow guide'); +assertIncludes(runtimeModes, '/guides/self-hosted/', 'Runtime modes'); +assertIncludes(runtimeModes, '/guides/snowplow/', 'Runtime modes'); +assertIncludes(supportMatrix, '/guides/self-hosted/', 'Support matrix'); +assertIncludes(supportMatrix, '/guides/snowplow/', 'Support matrix'); +assertIncludes(dbtGuide, '/guides/snowplow/', 'dbt guide'); +assertIncludes(endToEndDbt, '/guides/snowplow/', 'End-to-end dbt guide'); +assertIncludes(awsLambda, '/guides/snowplow/', 'AWS Lambda guide'); +assertIncludes(s3Tables, '/guides/snowplow/', 'S3 Tables guide'); +assertIncludes(docsMaintenance, 'Self-hosted local binary', 'Docs maintenance'); +assertIncludes(docsMaintenance, 'Snowplow web analytics', 'Docs maintenance'); + +const requiredCommands = [ + 'pnpm dev', + 'pnpm build', + 'pnpm preview', + 'pnpm astro', + 'pnpm format', + 'pnpm ncu', +]; +for (const command of requiredCommands) { + assertIncludes(docsReadme, command, 'docs/README.md'); +} + +for (const scriptName of ['astro', 'build', 'check', 'format', 'ncu', 'preview', 'smoke']) { + assert(scriptName in packageJson.scripts, `docs/package.json is missing script: ${scriptName}`); +} + +console.log('Docs smoke checks passed.'); diff --git a/docs/src/content/docs/development/docs-maintenance.mdx b/docs/src/content/docs/development/docs-maintenance.mdx new file mode 100644 index 00000000..6cfcf6cb --- /dev/null +++ b/docs/src/content/docs/development/docs-maintenance.mdx @@ -0,0 +1,69 @@ +--- +title: Docs maintenance +description: How to review docs and keep them current. +sidebar: + order: 1 +--- + +> Owner: Embucket maintainers +> Last reviewed: 2026-04-07 + +This page documents the current release-gate process for docs changes. + +## Automated checks + +The repository already includes a docs CI workflow at `.github/workflows/docs-ci.yml`. + +On docs changes, it currently runs: + +- formatting checks +- `astro check` +- repo-safe docs smoke checks for repeated constants, guide metadata, and referenced local files +- a full docs build +- Vale linting + +The docs site also uses `starlight-links-validator` during the build. + +## What still needs manual smoke testing + +Before release, manually check the commands in the highest-traffic guides: + +- `Quick Start` +- `Runtime modes` +- `Self-hosted local binary` +- `AWS Lambda` +- `dbt` +- `End-to-end dbt workflow` +- `Snowplow web analytics` +- `Troubleshooting` + +Confirm at least these points: + +- the local quick start still starts `embucket/embucket` +- the self-hosted guide still uses `cargo build` and can start `target/debug/embucketd` +- the Snowflake command-line tool can still run a simple query against the documented path +- the Lambda guide still reflects the current deploy flow +- the dbt guide still matches the current `dbt-embucket` adapter contract +- the Snowplow guide still matches the current `embucket-snowplow` flow and uses `dbt run` plus `dbt show` as the success state + +The automated smoke checks stay intentionally static. They do not call AWS, run dbt against a live Lambda, or execute the Snowflake command-line tool against live infrastructure. + +## Owner and freshness convention + +Major guides should include a short block near the top with: + +- owner +- last reviewed date + +This repository now uses that pattern in the highest-traffic guides so readers can see which pages the team reviewed recently. + +## Release checklist + +Before a release or launch push, confirm: + +1. current runtime names are consistent +2. quick-start ports and URLs still match the implementation +3. support claims still match verified workflows +4. docs CI is green +5. the top guides have a recent review date +6. self-hosted and Snowplow guides still match the current source repositories and local commands diff --git a/docs/src/content/docs/development/tracing.mdx b/docs/src/content/docs/development/tracing.mdx index 3849c516..f0c425de 100644 --- a/docs/src/content/docs/development/tracing.mdx +++ b/docs/src/content/docs/development/tracing.mdx @@ -9,7 +9,7 @@ Embucket uses `tracing::instrument` to instrument code for tracing. You can use ### Tracing span processor experimental async runtime -Embucket uses `BatchSpanProcessor`, which uses a dedicated background thread for collecting and exporting spans. This processor works well in production. Some development environments may hang on startup as reported in [issue #1123](https://github.com/embucket/embucket-labs/issues/1123). In this case, you can switch to `BatchSpanProcessor` using the experimental async runtime. +Embucket uses `BatchSpanProcessor`, which uses a dedicated background thread for collecting and exporting spans. This processor works well in production. If a development environment hangs on startup, switch to the experimental async runtime instead. Use this command-line argument: `--tracing-span-processor=batch-span-processor-experimental-async-runtime`. ### Tracing span processor tuning @@ -43,8 +43,8 @@ docker run --rm --name jaeger -p 16686:16686 -p 4317:4317 -p 4318:4318 -p 5778:5 Use the `RUST_LOG` environment variable to define log levels and the `--tracing-level` argument to enable tracing with [Jaeger](https://www.jaegertracing.io/). Both default log level and default tracing level use `info`. -``` -target/debug/embucketd --jwt-secret=test --backend=memory '--cors-allow-origin=http://localhost:8080' --cors-enabled=true --tracing-level=trace +```bash +target/debug/embucketd --jwt-secret=test --tracing-level=trace ``` ## Profiling @@ -54,11 +54,11 @@ This guide includes Samply as one way to profile, presented here as an experimen To start profiling, prepend `samply record` to the `embucketd` command invocation. Perform the actions you need to profile, then stop profiling to open a profile report in the browser. -``` +```bash # install Samply cargo install --locked samply # Profile debug build -cargo build && samply record RUST_LOG=debug target/debug/embucketd --jwt-secret=test --backend=memory '--cors-allow-origin=http://localhost:8080' --cors-enabled=true +cargo build && samply record RUST_LOG=debug target/debug/embucketd --jwt-secret=test ``` diff --git a/docs/src/content/docs/essentials/architecture.mdx b/docs/src/content/docs/essentials/architecture.mdx index 6e431f42..9d2595e0 100644 --- a/docs/src/content/docs/essentials/architecture.mdx +++ b/docs/src/content/docs/essentials/architecture.mdx @@ -1,86 +1,113 @@ --- title: Architecture -description: Comprehensive overview of Embucket's zero-disk lakehouse architecture, core components, and system design principles +description: Understand how Embucket handles data, metadata, query execution, authentication, and runtime packaging today. +sidebar: + order: 3 --- -import { Aside, Steps } from '@astrojs/starlight/components'; +import { Aside } from '@astrojs/starlight/components'; -Embucket delivers a Snowflake-compatible lakehouse. This document explains how Embucket's components work together to provide a complete analytics platform in a single binary. +> Owner: Embucket maintainers +> Last reviewed: 2026-04-07 -You'll learn about the system's architecture, core components, data flow, and operational characteristics. This overview targets data engineers, platform architects, and anyone deploying Embucket in production. +Embucket exposes a Snowflake-compatible API over lakehouse data. The current implementation is easiest to reason about if you separate it into five layers: runtime, metadata, storage, query execution, and auth/session handling. -## Core components +Use this page when you want the current mental model before choosing a runtime, configuring metadata, or planning around query and session limits. -Embucket integrates four key components into a single binary that delivers complete lakehouse capabilities. +## Runtime model -### Query engine +The repo currently ships two runtime artifacts: -[Apache DataFusion](https://datafusion.apache.org/) powers Embucket's SQL execution. DataFusion provides: +- `embucketd` for local and self-hosted runs +- `embucket-lambda` for AWS Lambda deployments -- **Vectorized processing**: Columnar data processing using Apache Arrow -- **SQL compliance**: ANSI SQL support with Snowflake-specific extensions -- **Extensibility**: Custom functions and data source integrations +The Lambda runtime wraps the same Snowflake-compatible router used by `embucketd`, so the client-facing API shape stays aligned across both runtime modes. -Each Embucket node runs a complete query engine, enabling horizontal scalability and fault tolerance. +Read [Runtime modes](/essentials/runtime-modes/) for the operational tradeoffs. + +If you are still choosing a path, start there before deploying. + +## Metadata model + +Embucket does not present itself as a managed metadata service. Instead, it loads metadata from configuration or supported external catalogs. + +Current documented paths are: + +- YAML metastore config loaded from `METASTORE_CONFIG` +- AWS S3 Tables as the documented external catalog path +- external Iceberg table definitions described in the metastore YAML + +If you need to configure metadata now, start with [Configuration](/essentials/configuration/) or [AWS S3 table bucket](/guides/s3-tables/). -### Data storage +## Storage model -[Apache Iceberg](https://iceberg.apache.org/) manages table metadata and provides ACID guarantees: +Data stays in your object storage. The current docs and code paths center on: -- **Schema evolution**: Add, drop, and change columns without rewriting data -- **Time travel**: Query historical table snapshots -- **ACID transactions**: Atomic commits with snapshot isolation -- **Partition pruning**: Efficient query performance on large datasets +- Apache Iceberg metadata +- Parquet data files +- AWS S3 or S3-compatible object storage flows -All table data stays in your object storage using Parquet files organized by Iceberg's metadata structure. +For AWS-managed table metadata, use [AWS S3 table bucket](/guides/s3-tables/). -### API compatibility +For a minimal local path, use the checked-in metastore config flow instead of starting with external catalog setup. -Embucket implements Snowflake's SQL dialect and REST API: +## Query model -- **SQL compatibility**: Snowflake-flavored SQL with existing queries -- **REST API**: v1 Snowflake REST API for driver compatibility -- **Tool integration**: Works with dbt, Apache Superset, and BI tools -- **Protocol support**: All native drivers built on top of REST API +Embucket executes Snowflake-flavored SQL through Apache DataFusion. The important operational property today is that query execution is **single-node per request**. -### ACID guarantees +That means: -Embucket provides ACID properties through Iceberg's snapshot isolation: +- each node handles complete queries independently +- there is no documented distributed query plan across many nodes +- scaling is primarily a throughput and placement question, not a distributed execution story -- **Atomicity**: All changes within a transaction succeed or fail together -- **Consistency**: Schema validation ensures data integrity -- **Isolation**: Concurrent queries see consistent snapshots -- **Durability**: Committed changes persist in object storage +This is why the docs distinguish local evaluation from the current Lambda deployment path instead of treating them as interchangeable production footprints. -## Deployment patterns +Plan for that limit before treating Lambda as a high-concurrency production endpoint. -Embucket's stateless architecture supports deployment patterns for different requirements. +## Auth and session model -### Single node deployment +The current Snowflake-compatible HTTP surface exposes: -Deploy one Embucket instance for development or small workloads: +- `/session/v1/login-request` +- `/session` +- `/queries/v1/query-request` +- `/queries/v1/abort-request` -- Simple setup with minimal resource requirements -- Suitable for development and testing environments -- Single point of failure during maintenance +The local demo path uses configurable demo credentials, which default to `embucket` / `embucket`. -{/* vale Google.Headings = NO */} +After login: -### Run on AWS Lambda +- Embucket issues a JWT token +- clients can pass it in `Authorization: Snowflake Token="..."` +- the runtime also uses a `session_id` cookie for session continuity -{/* vale Google.Headings = YES */} +Current implementation details worth knowing: -Deploy Embucket as an AWS Lambda function: +- JWT token lifetime is 3 days +- session inactivity expiry is 60 seconds -- High availability and fault tolerance -- Horizontal scaling for increased query throughput +If you are debugging auth problems, continue to [Troubleshooting](/guides/troubleshooting/). - +## When to use local mode or Lambda + +The API shape stays aligned, but the operational envelope changes: + +- **local mode** is the fastest path for tests and evaluation +- **Lambda + Function URL** is a tested validation path, but not production-ready because the URL is publicly reachable +- **Lambda + dbt-embucket** is the verified and recommended client workflow +- **private API gateway in front of Lambda** is the safer production-facing ingress pattern + +Use [Quick Start](/essentials/quick-start/) for local evaluation and [End-to-end dbt workflow](/guides/end-to-end-dbt/) for the shortest complete Lambda path. + +## Related guides + +- [Quick Start](/essentials/quick-start/) +- [Support matrix](/essentials/support-matrix/) +- [AWS Lambda](/guides/aws-lambda/) +- [dbt](/guides/dbt/) diff --git a/docs/src/content/docs/essentials/configuration.mdx b/docs/src/content/docs/essentials/configuration.mdx index 2e445cbd..3020dd14 100644 --- a/docs/src/content/docs/essentials/configuration.mdx +++ b/docs/src/content/docs/essentials/configuration.mdx @@ -1,98 +1,104 @@ --- title: Configuration -description: Configure Embucket for different deployment scenarios using environment variables or configuration files. +description: Configure Embucket with the current source-backed flags, environment variables, and metastore settings. +sidebar: + order: 2 --- import { Aside } from '@astrojs/starlight/components'; -This guide covers how to configure Embucket for your specific deployment needs. You can configure Embucket using environment variables, configuration files, or command-line options to control storage backends, networking, authentication, and performance settings. +> Owner: Embucket maintainers +> Last reviewed: 2026-04-07 -Embucket supports flexible configuration through many methods, allowing you to adapt it for development, testing, and production environments. +This page covers the current configuration surface backed by the repository. It focuses on settings that are visible in `crates/embucketd/src/cli.rs`, plus the checked-in config examples in `config/`. -## Configuration methods +## Configuration precedence -You can configure Embucket using three methods, in order of precedence: +The current local runtime supports these configuration sources, from highest to lowest precedence: -1. **Command-line arguments** - Highest precedence -2. **Environment variables** - Medium precedence -3. **Configuration file** `.env` - Lowest precedence +1. command-line flags +2. environment variables +3. `.env` loaded at startup -### Configuration file + -Create a `.env` file in your working directory with key-value pairs. Embucket automatically loads this file at startup. +## Core runtime settings -```bash -# Basic configuration example -METASTORE_CONFIG=config/metastore.yaml -JWT_SECRET=your-secret-key -``` +| Purpose | Flag | Environment variable | Default | +| --------------------- | ------------------------- | ----------------------- | ----------- | +| metastore config path | `--metastore-config` | `METASTORE_CONFIG` | unset | +| bind host | `--host` | `BUCKET_HOST` | `localhost` | +| bind port | `--port` | `BUCKET_PORT` | `3000` | +| result serialization | `--data-format` | `DATA_FORMAT` | `json` | +| parser dialect | `--sql-parser-dialect` | `SQL_PARSER_DIALECT` | `snowflake` | +| query concurrency | `--max-concurrency-level` | `MAX_CONCURRENCY_LEVEL` | `8` | +| query timeout | `--query-timeout-secs` | `QUERY_TIMEOUT_SECS` | `1200` | +| demo user | `--auth-demo-user` | `AUTH_DEMO_USER` | `embucket` | +| demo password | `--auth-demo-password` | `AUTH_DEMO_PASSWORD` | `embucket` | +| JWT signing secret | `--jwt-secret` | `JWT_SECRET` | unset | +| tracing level | `--tracing-level` | `TRACING_LEVEL` | `info` | +| service idle timeout | `--idle-timeout-seconds` | `IDLE_TIMEOUT_SECONDS` | `18000` | -### Environment variables +## Local `.env` example -Set environment variables in your shell or deployment environment. Environment variables override configuration file settings. +Start with a minimal local `.env` like this: ```bash -export METASTORE_CONFIG=config/metastore.yaml -export JWT_SECRET=your-secret-key +METASTORE_CONFIG=./metastore.yaml +JWT_SECRET=secret +TRACING_LEVEL=debug +RUST_LOG=info ``` -### Command-line arguments - -Pass configuration options directly to the `embucketd` command. Command-line arguments override both environment variables and configuration file settings. - -```bash -embucketd --metastore-config config/metastore.yaml --port 3001 -``` +Use stronger secrets than the example when you share an environment with anyone else. -## Core settings - -These settings control Embucket's basic operation and most deployments need them. - -### Network configuration - -| Setting | Environment Variable | Default | Description | -| -------- | -------------------- | ----------- | ----------------------------------- | -| `--host` | `BUCKET_HOST` | `localhost` | Host address to bind the API server | -| `--port` | `BUCKET_PORT` | `3000` | Port for the API server | +## Metastore configuration -### Authentication +Embucket currently expects metastore configuration through `METASTORE_CONFIG` or `--metastore-config`. -| Setting | Environment Variable | Default | Description | -| ---------------------- | -------------------- | ---------- | -------------------------------------------- | -| `--jwt-secret` | `JWT_SECRET` | None | Required secret key for JWT token generation | -| `--auth-demo-user` | `AUTH_DEMO_USER` | `embucket` | Username for demo authentication | -| `--auth-demo-password` | `AUTH_DEMO_PASSWORD` | `embucket` | Password for demo authentication | +For a minimal local file, start with: - +```yaml +volumes: [] +``` -## Metastore configuration +That keeps the local runtime usable for evaluation and testing while you build out a richer metastore definition. -The Embucket metastore uses a YAML file that defines volumes, databases, schemas, and tables. -Specify the path with the `--metastore-config` command-line argument or the `METASTORE_CONFIG` environment variable. +### Configure the table-bucket volume -In Embucket, a volume defines the storage location for data. Configure either an S3 volume or an S3 tables volume. +```yaml +volumes: + - ident: embucket + type: s3-tables + database: demo + credentials: + credential_type: access_key + aws-access-key-id: ACCESS_KEY + aws-secret-access-key: SECRET_ACCESS_KEY + arn: arn:aws:s3tables:us-east-2:123456789012:bucket/my-table-bucket +``` -### S3 volume +Use this path if you want the currently documented external catalog flow. See [AWS S3 table bucket](/guides/s3-tables/) for the end-to-end setup. -Use an S3 volume to point at Iceberg tables already stored on S3—for example, Snowflake Open Catalog Managed tables. +### External Iceberg tables on S3 ```yaml volumes: - - ident: tpch + - ident: lakehouse type: s3 region: us-east-2 - bucket: embucket-lakehouse + bucket: YOUR_BUCKET_NAME credentials: credential_type: access_key - aws-access-key-id: - aws-secret-access-key: + aws-access-key-id: YOUR_ACCESS_KEY + aws-secret-access-key: YOUR_SECRET_KEY databases: - ident: demo - volume: tpch + volume: lakehouse schemas: - database: demo @@ -102,93 +108,39 @@ tables: - database: demo schema: tpch_10 table: customer - metadata_location: s3:///metadata/00001-eea1cccb-38a4-4fe2-8c95-c01dae9d0c60.metadata.json - - - database: demo - schema: tpch_10 - table: lineitem - metadata_location: s3:///metadata/00001-d777220e-d508-4033-a229-8c4c8d8fe514.metadata.json + metadata_location: s3://YOUR_BUCKET_NAME/tpch_10/customer/metadata/00001.metadata.json ``` -In this example: +This path is useful when you already have Iceberg metadata in object storage and want Embucket to expose it through the Snowflake-compatible API. -- Define a single `tpch` volume with type `s3` -- Create one database, `demo`, that uses the `tpch` volume -- Create the `tpch_10` schema inside the `demo` database -- Create two tables, `customer` and `lineitem`, inside the `tpch_10` schema +## Runtime and tracing settings -When loaded, Embucket creates a database `demo` with schema `tpch_10` and two tables `customer` and `lineitem`. It uses the `tpch` volume information in the configuration file to access data. +The current runtime also exposes memory, disk, AWS SDK, and object-store timeout controls. The most important ones for everyday operation are: -### S3 tables volume +- `MEM_POOL_TYPE` +- `MEM_POOL_SIZE_MB` +- `DISK_POOL_SIZE_MB` +- `AWS_SDK_CONNECT_TIMEOUT_SECS` +- `AWS_SDK_OPERATION_TIMEOUT_SECS` +- `OBJECT_STORE_TIMEOUT_SECS` +- `OBJECT_STORE_CONNECT_TIMEOUT_SECS` +- `TRACING_LEVEL` +- `RUST_LOG` -Use S3 tables volume for data managed by AWS S3 Table buckets. +For deeper tracing guidance, see [Tracing and profiling](/development/tracing/). -```yaml -volumes: - - ident: tpch - type: s3-tables - database: demo - credentials: - credential_type: access_key - aws-access-key-id: - aws-secret-access-key: - arn: arn:aws:s3tables:us-east-2:767397688925:bucket/my-testing-minimal -``` - -In this example: - -- Define a single `tpch` volume of type `s3-tables` -- Each `s3-tables` volume maps to one database; here, `demo` - -When loaded, Embucket creates a database `demo` and lists all namespaces and tables that exist in the provided S3 Table bucket. - -## Advanced settings - -### Data format - -| Setting | Environment Variable | Default | Description | -| --------------- | -------------------- | ------- | ----------------------------------------------------------------- | -| `--data-format` | `DATA_FORMAT` | `json` | Data serialization format for Snowflake v1 API: `json` or `arrow` | - -### Memory and disk pools +## Current authentication defaults -| Setting | Environment Variable | Default | Description | -| ------- | --------------------------------- | -------- | ------------------------------------ | -| N/A | `MEM_POOL_TYPE` | `greedy` | Memory pool allocation strategy | -| N/A | `MEM_POOL_SIZE_MB` | `4096` | Memory pool size in megabytes | -| N/A | `MEM_ENABLE_TRACK_CONSUMERS_POOL` | `true` | Enable memory pool consumer tracking | -| N/A | `DISK_POOL_SIZE_MB` | `102400` | Disk pool size in megabytes | +Local quick starts assume demo authentication: -Embucket doesn't create default volumes, databases, or schemas. Seed the metastore with a configuration file or create the necessary entries before querying. +- username: `embucket` +- password: `embucket` -### Tracing and debugging +Override them with `AUTH_DEMO_USER` and `AUTH_DEMO_PASSWORD` when you need different demo credentials. -| Setting | Environment Variable | Default | Description | -| -------------------------- | -------------------- | ---------------------- | --------------------------------------------- | -| `--tracing-level` | `TRACING_LEVEL` | `info` | Log level: `off`, `info`, `debug`, or `trace` | -| `--tracing-span-processor` | `span_processor` | `batch-span-processor` | Tracing span processor type | +## Related guides - - -## Command-line reference - -View all available command-line options: - -```bash -embucketd --help -``` - -Common command patterns: - -```bash -# Start with custom port and S3 backend -embucketd --port 3001 --backend s3 --bucket my-data-bucket - -# Start with file backend and custom storage path -embucketd --backend file --file-storage-path /opt/embucket/data - -# Start with debug logging -embucketd --tracing-level debug -``` +- [Quick Start](/essentials/quick-start/) +- [Runtime modes](/essentials/runtime-modes/) +- [AWS Lambda](/guides/aws-lambda/) +- [Troubleshooting](/guides/troubleshooting/) diff --git a/docs/src/content/docs/essentials/quick-start.mdx b/docs/src/content/docs/essentials/quick-start.mdx index b8c4d876..8433879f 100644 --- a/docs/src/content/docs/essentials/quick-start.mdx +++ b/docs/src/content/docs/essentials/quick-start.mdx @@ -1,54 +1,59 @@ --- title: Quick Start -description: Get up and running with Embucket in under 5 minutes. From download to first query with zero dependencies. +description: Start Embucket locally, connect the Snowflake command-line tool, and run a first query in the current test and evaluation path. sidebar: order: 0 --- import { Aside, Steps } from '@astrojs/starlight/components'; -This guide shows you how to start Embucket and run your first query in under 5 minutes. You use Embucket's single-binary architecture to start running queries. +> Owner: Embucket maintainers +> Last reviewed: 2026-04-07 -Read this guide to: +This quick start is the fastest way to try Embucket locally. This is the current **test and evaluation** path, not the recommended production deployment path. -- Start Embucket with zero external dependencies -- Connect with the Snowflake command-line tool -- Run your first query +By the end of this guide, you can: -This guide doesn't cover production deployment or advanced configuration options. +- start the current `embucket/embucket` container +- connect the Snowflake command-line tool to the local endpoint +- run a query successfully ## Step 1: Start Embucket -Start the Embucket server: +Run the local container: ```bash -docker run --name embucket --rm -p 3000:3000 embucket/embucket ./embucketd +docker run --name embucket --rm -p 3000:3000 embucket/embucket ``` -**Done.** You need no external dependencies, databases, or complex configuration. +Expected startup output includes a line like: -Embucket displays output like: - -``` +```text {"timestamp":"2025-07-01T15:35:05.687807Z","level":"INFO","fields":{"message":"Listening on http://0.0.0.0:3000"},"target":"embucketd"} ``` -