diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d2fd249..6e6814a 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -44,6 +44,30 @@ npm run dev -w site/ # http://localhost:432x/docs 2. **Sidebar** — add the page to `site//src/nav.ts`. 3. **Tests** — add the route to `cypress/fixtures/-pages.ts` so the page-existence / single-h1 tests cover it. +## Generating the DoltHub API docs + +The DoltHub API reference under `site/dolt/src/content/products/dolthub/api/` is generated, not hand-edited — don't touch the generated files directly, edit the source and regenerate. + +### v1alpha1 + +Source of truth: the Swagger JSON in `site/dolt/src/content/.gitbook/assets/dolthub-api/.json`, plus per-page markdown templates in `scripts/api-source/.md`. To update an endpoint, edit whichever of those covers it, then run: + +```sh +python3 scripts/generate-api-docs.py +``` + +This regenerates `site/dolt/src/content/products/dolthub/api/*.md` (excluding the `v2/` subdirectory). + +### v2 + +Source of truth: the OpenAPI spec at `specs/dolthub-v2.yaml`. To update an endpoint or schema, edit that spec, then run: + +```sh +npm run generate-api-v2 --workspace site/dolt +``` + +This writes `site/dolt/src/content/products/dolthub/api/v2/database.md` (one section per `Database`-tagged endpoint), `user.md`, `operations.md`, and `models.md` (one entry per component schema). `authentication.md`, `README.md`, and `migration.md` in that directory are hand-written and untouched by the script. + ## Workflow | Branch | What happens on merge | @@ -65,7 +89,6 @@ npm run dev -w site/ # http://localhost:432x/docs ## Caveats - **`cli.md` is generated**, not hand-edited. To update it, run `dolt dump-docs --file=site/dolt/src/content/reference/cli/cli.md` from a Dolt binary at the right version, then `chmod 644`. -- **DoltHub API docs are generated.** Don't hand-edit `site/dolt/src/content/products/dolthub/api/*.md` — regenerate instead. To update an endpoint, edit either the Swagger JSON in `site/dolt/src/content/.gitbook/assets/dolthub-api/.json` or the per-page markdown template in `scripts/api-source/.md`, then run `python3 scripts/generate-api-docs.py`. - **Internal links** are site-absolute with no `.md` extension. Use the URL form: `/sql-reference/version-control/dolt-sql-procedures#dolt_merge`, `/cli-reference/cli#dolt-status`, etc. A rehype plugin prepends the `/docs` base at build time, so write links *without* `/docs/`. Same-page anchors stay as `#anchor`. - **Images** must use *relative* paths (e.g. `../../.gitbook/assets/foo.png`) so Astro's asset pipeline can fingerprint them. Don't use absolute `/…` for images. - **Code blocks need a language** for syntax highlighting. Common: `sql` (incl. `mysql>` sessions — `mysql` isn't a Shiki grammar, use `sql`), `bash` (shell sessions), `text` (plain output / `+---+` result tables), `yaml`, `go`, `python`, `json`, `diff`, `ini`. Leave bare only when nothing fits. diff --git a/package-lock.json b/package-lock.json index c5fa433..a76ada8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,7 +11,9 @@ "site/*" ], "devDependencies": { + "@types/node": "^26.1.0", "cypress": "^15.15.0", + "remark-heading-id": "^1.0.1", "typescript": "^5.0.0" } }, @@ -34,26 +36,32 @@ "license": "MIT" }, "node_modules/@astrojs/internal-helpers": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/@astrojs/internal-helpers/-/internal-helpers-0.9.1.tgz", - "integrity": "sha512-1pWuARqYom/TzuU3+0ZugsTrKlUydWKuULmDqSMTuonY+9IRDUEGKX/8PXQ1nBxRq3w85uGtd9q9SXfqEldMIQ==", + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/@astrojs/internal-helpers/-/internal-helpers-0.10.0.tgz", + "integrity": "sha512-Ry2R3VPeIN4uPCSA4xQc+e+vsJXkalKpEbDc07hV+a/o5Bs2N/s/uDcPJH/05L19DKh9tAy7e6JM3YZ6Cxfezw==", "license": "MIT", "dependencies": { - "picomatch": "^4.0.4" + "@types/hast": "^3.0.4", + "@types/mdast": "^4.0.4", + "js-yaml": "^4.1.1", + "picomatch": "^4.0.4", + "retext-smartypants": "^6.2.0", + "shiki": "^4.0.2", + "smol-toml": "^1.6.0", + "unified": "^11.0.5" } }, "node_modules/@astrojs/markdown-remark": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/@astrojs/markdown-remark/-/markdown-remark-7.1.2.tgz", - "integrity": "sha512-caXZ4Dc2St2dW8luEg22GlP0gupLdztCTQE4EzZOxW1pqWXz9mbeJEuHUkgDYcKWW8tjIHkydYDhWLVoxJ327Q==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@astrojs/markdown-remark/-/markdown-remark-7.2.0.tgz", + "integrity": "sha512-+YxmVQu1Bd+MFfSzjq1rOJvD9+nIOJzz5YIIhdIH01RrxRkKbyKoEgyIqP3yv51MhzMDgd79QaPv+kCVPT8vHw==", "license": "MIT", "dependencies": { - "@astrojs/internal-helpers": "0.9.1", + "@astrojs/internal-helpers": "0.10.0", "@astrojs/prism": "4.0.2", "github-slugger": "^2.0.0", "hast-util-from-html": "^2.0.3", "hast-util-to-text": "^4.0.2", - "js-yaml": "^4.1.1", "mdast-util-definitions": "^6.0.0", "rehype-raw": "^7.0.0", "rehype-stringify": "^10.0.1", @@ -61,9 +69,6 @@ "remark-parse": "^11.0.0", "remark-rehype": "^11.1.2", "remark-smartypants": "^3.0.2", - "retext-smartypants": "^6.2.0", - "shiki": "^4.0.0", - "smol-toml": "^1.6.0", "unified": "^11.0.5", "unist-util-remove-position": "^5.0.0", "unist-util-visit": "^5.1.0", @@ -71,6 +76,48 @@ "vfile": "^6.0.3" } }, + "node_modules/@astrojs/markdown-remark/node_modules/unist-util-is": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.1.tgz", + "integrity": "sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/@astrojs/markdown-remark/node_modules/unist-util-visit": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.1.0.tgz", + "integrity": "sha512-m+vIdyeCOpdr/QeQCu2EzxX/ohgS8KbnPDgFni4dQsfSCtpz8UqDyY5GjRru8PDKuYn7Fq19j1CQ+nJSsGKOzg==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/@astrojs/markdown-remark/node_modules/unist-util-visit-parents": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.2.tgz", + "integrity": "sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/@astrojs/prism": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/@astrojs/prism/-/prism-4.0.2.tgz", @@ -84,14 +131,14 @@ } }, "node_modules/@astrojs/react": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/@astrojs/react/-/react-5.0.5.tgz", - "integrity": "sha512-5jSFDqWqLdEyp7CEVD66A7AQEEuwLkCGR25NJ4FR5EjziZQqZTGc7hJOFZ97qb98BiU6vElrS70R8iI+HhufGQ==", + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/@astrojs/react/-/react-5.0.7.tgz", + "integrity": "sha512-N9cCoxvnLWaP+AK1Fv4e5Mc7ktnVTpSo2nWLwvD9Ohr1dJKygwrTSm9yatqoahgb1A5Kwjg/rT2shRiIVdn3aw==", "license": "MIT", "dependencies": { - "@astrojs/internal-helpers": "0.9.1", + "@astrojs/internal-helpers": "0.10.0", "@vitejs/plugin-react": "^5.2.0", - "devalue": "^5.6.4", + "devalue": "^5.8.1", "ultrahtml": "^1.6.0", "vite": "^7.3.2" }, @@ -409,21 +456,21 @@ } }, "node_modules/@capsizecss/unpack": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@capsizecss/unpack/-/unpack-4.0.0.tgz", - "integrity": "sha512-VERIM64vtTP1C4mxQ5thVT9fK0apjPFobqybMtA1UdUujWka24ERHbRHFGmpbbhp73MhV+KSsHQH9C6uOTdEQA==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@capsizecss/unpack/-/unpack-4.0.1.tgz", + "integrity": "sha512-CuNiSqg7+e1cO/GjffyMOm5Tt2jUF9CWHHnvQ/UkqvtkGfHdgwEC0wpmq7fkN3gxwpRnrAN0WzO3vREKmNolMQ==", "license": "MIT", "dependencies": { - "fontkitten": "^1.0.0" + "fontkitten": "^1.0.3" }, "engines": { "node": ">=18" } }, "node_modules/@clack/core": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@clack/core/-/core-1.3.1.tgz", - "integrity": "sha512-fT1qHVGAag4IEkrupZ6lRRbNCs1vS9P01KB/sG8zKgvUztbYtFBtQpjSITNwooDZ83tpsPzP0mRNs1/KVszCRA==", + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/@clack/core/-/core-1.4.3.tgz", + "integrity": "sha512-/kr3UWNtdJfxZtPgDqUOmG2pvwlmcLGheex5yiZKdwbzZJxhV+HMNR9QNmyY5cGwTNV6LrR7Jtp+KjhUAP1qBQ==", "license": "MIT", "dependencies": { "fast-wrap-ansi": "^0.2.0", @@ -434,12 +481,12 @@ } }, "node_modules/@clack/prompts": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@clack/prompts/-/prompts-1.4.0.tgz", - "integrity": "sha512-S0My7XPGIgpRWMDG8uRqalbgT+a6FmCUdOW+HaIOVVpUPHOb7RrpvjTjiODadKp06fsrVDJZlIzc6yCTp4AnxA==", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@clack/prompts/-/prompts-1.7.0.tgz", + "integrity": "sha512-y7/yvZ2TPAnR9+jnc00klvNNLkJiXFFrQA/hlLCcxA9a2A4zQIOimyFQ9XfwYKiGD1fb5GY8vbKIIgO8d5Tb2A==", "license": "MIT", "dependencies": { - "@clack/core": "1.3.1", + "@clack/core": "1.4.3", "fast-string-width": "^3.0.2", "fast-wrap-ansi": "^0.2.0", "sisteransi": "^1.0.5" @@ -449,9 +496,9 @@ } }, "node_modules/@cypress/request": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@cypress/request/-/request-4.0.0.tgz", - "integrity": "sha512-wGTQfwDMMMiz/muFw4YbCLwTh0uZsXKK+6zWBzftADpitSi6iM62C8GzEhNcng2srUiGPksOriQkA8zakW2R0g==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@cypress/request/-/request-4.0.1.tgz", + "integrity": "sha512-y20e+e6dFYkOUUJLVUZTsJRuTiXZaUQ32WD+R/ux/HBybbTx4ge7cNINcua0pU8+SNkKuRbOF12mBmzuzM8n5w==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -468,7 +515,7 @@ "json-stringify-safe": "~5.0.1", "mime-types": "~2.1.19", "performance-now": "^2.1.0", - "qs": "~6.14.1", + "qs": "^6.15.2", "safe-buffer": "^5.1.2", "tough-cookie": "^5.0.0", "tunnel-agent": "^0.6.0" @@ -579,9 +626,9 @@ } }, "node_modules/@dolthub/web-utils": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@dolthub/web-utils/-/web-utils-0.3.0.tgz", - "integrity": "sha512-kjyp3EntU+g0L01g4jt23y5eckSFNCedMB5XKfPo8PtA6WSRJCCizp/oiQY7A/PPRdYTL/Dooq2I7vPKbjSOAQ==", + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@dolthub/web-utils/-/web-utils-0.3.1.tgz", + "integrity": "sha512-Vb630amOczvRK/m0mixPSus4ulLKORrePXaGLj2zAwOmocQ3Sow7suuLiaxqksU2Gam1gryTi7REFyXrSEg0Aw==", "dependencies": { "timeago.js": "^4.0.2" }, @@ -595,9 +642,9 @@ } }, "node_modules/@emnapi/runtime": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.10.0.tgz", - "integrity": "sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==", + "version": "1.11.2", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.11.2.tgz", + "integrity": "sha512-kyOl3X0DuTiT1h2ft8r2fYO8JYtU9a9Xis/zBSiGArNaagCOWx90N1k2wxp18czFDH+OgcWGb5ZP/XMt3dcyPA==", "license": "MIT", "optional": true, "dependencies": { @@ -1831,9 +1878,9 @@ "license": "MIT" }, "node_modules/@rollup/pluginutils": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.3.0.tgz", - "integrity": "sha512-5EdhGZtnu3V88ces7s53hhfK5KSASnJZv8Lulpc04cWO3REESroJXg73DFsOmgbU2BhwV0E20bu2IDZb3VKW4Q==", + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.4.0.tgz", + "integrity": "sha512-MfPp06CjRLfXQ3wY0R8vJDYBy/MvVcc9OulEfR0B8Iv9ko+GCNaRZ+EpJYFl27LhKsZK0o420sYCRHCjfCgeUg==", "license": "MIT", "dependencies": { "@types/estree": "^1.0.0", @@ -1853,9 +1900,9 @@ } }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.60.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.60.4.tgz", - "integrity": "sha512-F5QXMSiFebS9hKZj02XhWLLnRpJ3B3AROP0tWbFBSj+6kCbg5m9j5JoHKd4mmSVy5mS/IMQloYgYxCuJC0fxEQ==", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.62.2.tgz", + "integrity": "sha512-6o7ZLZK+BeenkZCFNDXqpbjw9bD6nuWonvS/lwQJp7NoVVxm6p3qE7qQ5jGuBjiFsgvqjD8mZAU5oWxTmbOeOg==", "cpu": [ "arm" ], @@ -1866,9 +1913,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.60.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.60.4.tgz", - "integrity": "sha512-GxxTKApUpzRhof7poWvCJHRF51C67u1R7D6DiluBE8wKU1u5GWE8t+v81JvJYtbawoBFX1hLv5Ei4eVjkWokaw==", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.62.2.tgz", + "integrity": "sha512-BaH7BllCACHoH1LguOU56UItGfUWjujlO65kS9LAodViaN4bwIKd7oeW/ZHJ/4ljr/7MIiENnNy3HJ0zXv8Zkw==", "cpu": [ "arm64" ], @@ -1879,9 +1926,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.60.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.60.4.tgz", - "integrity": "sha512-tua0TaJxMOB1R0V0RS1jFZ/RpURFDJIOR2A6jWwQeawuFyS4gBW+rntLRaQd0EQ4bd6Vp44Z2rXW+YYDBsj6IA==", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.62.2.tgz", + "integrity": "sha512-v39RCCvj4He82I9sFmk+M1VZ0PLM9sfsLVikjfx2hYBNALhrrOR2D3JjQA6AhlaSOgcR+RzrKY7e1+bT6SUO/A==", "cpu": [ "arm64" ], @@ -1892,9 +1939,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.60.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.60.4.tgz", - "integrity": "sha512-CSKq7MsP+5PFIcydhAiR1K0UhEI1A2jWXVKHPCBZ151yOutENwvnPocgVHkivu2kviURtCEB6zUQw0vs8RrhMg==", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.62.2.tgz", + "integrity": "sha512-yl0y2vq3S3lHeuXhEdss6TWfKW8vkujImO12tn4ZkG/4oghr09LvdYm2RElVjokTQiUvDUGXLGsYeLqUMCKpGA==", "cpu": [ "x64" ], @@ -1905,9 +1952,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.60.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.60.4.tgz", - "integrity": "sha512-+O8OkVdyvXMtJEciu2wS/pzm1IxntEEQx3z5TAVy4l32G0etZn+RsA48ARRrFm6Ri8fvqPQfgrvNxSjKAbnd3g==", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.62.2.tgz", + "integrity": "sha512-tT4pvt4qXD+vEoezupCWi+a1F0vvDiksiHc+PxRlYTOH1I6/X4id9jPxTP+Fg+545euaFT1jJVs4CEdHZAU1vw==", "cpu": [ "arm64" ], @@ -1918,9 +1965,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.60.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.60.4.tgz", - "integrity": "sha512-Iw3oMskH3AfNuhU0MSN7vNbdi4me/NiYo2azqPz/Le16zHSa+3RRmliCMWWQmh4lcndccU40xcJuTYJZxNo/lw==", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.62.2.tgz", + "integrity": "sha512-6nU5F2wCW+qvCBhTn1pdIU3bzsIoF7EUwsCDRxilWGprQR6yd508YnH9+OKFCwpfS8pjZqDUmnCAr7exax0XCg==", "cpu": [ "x64" ], @@ -1931,9 +1978,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.60.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.60.4.tgz", - "integrity": "sha512-EIPRXTVQpHyF8WOo219AD2yEltPehLTcTMz2fn6JsatLYSzQf00hj3rulF+yauOlF9/FtM2WpkT/hJh/KJFGhA==", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.62.2.tgz", + "integrity": "sha512-n1GJHPOvpIfhi3TmrCeh6S6URt9BFCt0KQE3qvexyGCTAKpR4Lg+eWvNZEqu7epxwus/8ElT3hacYEucm49SZg==", "cpu": [ "arm" ], @@ -1944,9 +1991,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.60.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.60.4.tgz", - "integrity": "sha512-J3Yh9PzzF1Ovah2At+lHiGQdsYgArxBbXv/zHfSyaiFQEqvNv7DcW98pCrmdjCZBrqBiKrKKe2V+aaSGWuBe/w==", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.62.2.tgz", + "integrity": "sha512-JqgflS8wEB+UXV/vS1RpRbifGBeN4D5lz8D8oOFbFZw4vedvdOgCFAjfBmIMdW3yL10XpQQ0Ambepw6MXrhOnA==", "cpu": [ "arm" ], @@ -1957,9 +2004,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.60.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.60.4.tgz", - "integrity": "sha512-BFDEZMYfUvLn37ONE1yMBojPxnMlTFsdyNoqncT0qFq1mAfllL+ATMMJd8TeuVMiX84s1KbcxcZbXInmcO2mRg==", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.62.2.tgz", + "integrity": "sha512-wnFJkogWvN4jm/hQRF2UBaeUmk20j5+DmHvoyWii2b8HJDyvz1MF2OU/6ynXt2KR63rbZLWkFpoytpdc/yBuSA==", "cpu": [ "arm64" ], @@ -1970,9 +2017,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.60.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.60.4.tgz", - "integrity": "sha512-pc9EYOSlOgdQ2uPl1o9PF6/kLSgaUosia7gOuS8mB69IxJvlclko1MECXysjs5ryez1/5zjYqx3+xYU0TU6R1A==", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.62.2.tgz", + "integrity": "sha512-HVu2bp0zhvJ8xHEV9+UUs7S90VadmBSY3LcIMvozbPo4AuMGDWlz3ymHLHZPX4hR67TKTt8Qp5PJ5RBg/i+RMQ==", "cpu": [ "arm64" ], @@ -1983,9 +2030,9 @@ ] }, "node_modules/@rollup/rollup-linux-loong64-gnu": { - "version": "4.60.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.60.4.tgz", - "integrity": "sha512-NxnomyxYerDh5n4iLrNa+sH+Z+U4BMEE46V2PgQ/hoB909i8gV1M5wPojWg9fk1jWpO3IQnOs20K4wyZuFLEFQ==", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.62.2.tgz", + "integrity": "sha512-mQqqAV8QaoSgr9I2fKDLY2BAVvmKjWoGiu/cSYQonsLvtqwEn1E4QYfnCOcp5zoEqNhsDYin1s6jx/VJmrxlZg==", "cpu": [ "loong64" ], @@ -1996,9 +2043,9 @@ ] }, "node_modules/@rollup/rollup-linux-loong64-musl": { - "version": "4.60.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.60.4.tgz", - "integrity": "sha512-nbJnQ8a3z1mtmrwImCYhc6BGpThAyYVRQxw9uKSKG4wR6aAYno9sVjJ0zaZcW9BPJX1GbrDPf+SvdWjgTuDmnw==", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.62.2.tgz", + "integrity": "sha512-IxKLoxCQ2IWi6bT2akyDUBGsOImDKB+sPp4EsTmwFQ/fMwpCKm8uLSSgP/Kx/QYUgKis6SEZ5/Nlhup0DIA0PQ==", "cpu": [ "loong64" ], @@ -2009,9 +2056,9 @@ ] }, "node_modules/@rollup/rollup-linux-ppc64-gnu": { - "version": "4.60.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.60.4.tgz", - "integrity": "sha512-2EU6acNrQLd8tYvo/LXW535wupT3m6fo7HKo6lr7ktQoItxTyOL1ZCR/GfGCuXl2vR+zmfI6eRXkSemafv+iVg==", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.62.2.tgz", + "integrity": "sha512-Mk5ha2RQSgyFfmYYLkBpPnUk8D8FriBxesO1u9O75X0mHgXL1UQcH5Itl2lurWL2tj0RxV9b9tJgipac0hRY9A==", "cpu": [ "ppc64" ], @@ -2022,9 +2069,9 @@ ] }, "node_modules/@rollup/rollup-linux-ppc64-musl": { - "version": "4.60.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.60.4.tgz", - "integrity": "sha512-WeBtoMuaMxiiIrO2IYP3xs6GMWkJP2C0EoT8beTLkUPmzV1i/UcOSVw1d5r9KBODtHKilG5yFxsGRnBbK3wJ4A==", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.62.2.tgz", + "integrity": "sha512-CjvEnqJL/0/TQ3TXX3OPIJ/kmBellrWd4heXUmHeJlTnmwjKpSJzoehLaL6Xk0ZnMHBu9dZuFADNOrtjF4v+2w==", "cpu": [ "ppc64" ], @@ -2035,9 +2082,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.60.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.60.4.tgz", - "integrity": "sha512-FJHFfqpKUI3A10WrWKiFbBZ7yVbGT4q4B5o1qKFFojqpaYoh9LrQgqWCmmcxQzVSXYtyB5bzkXrYzlHTs21MYA==", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.62.2.tgz", + "integrity": "sha512-1SiZbzwdkaDURsew/tSOrooKiYy7EQGT6m8ufavAi9NEyQb/6VuIxFXAL1fqa4iZe3g4NbNk4P7J32z2tw5Mgg==", "cpu": [ "riscv64" ], @@ -2048,9 +2095,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.60.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.60.4.tgz", - "integrity": "sha512-mcEl6CUT5IAUmQf1m9FYSmVqCJlpQ8r8eyftFUHG8i9OhY7BkBXSUdnLH5DOf0wCOjcP9v/QO93zpmF1SptCCw==", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.62.2.tgz", + "integrity": "sha512-nQts12zJ3NQRoE6uYljOH89v7szzLDvG2JD/vsX+vGXU8w/At1GowTZ5/7qeFQ8m7L55rpR8Okugnuo5bgjy2Q==", "cpu": [ "riscv64" ], @@ -2061,9 +2108,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.60.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.60.4.tgz", - "integrity": "sha512-ynt3JxVd2w2buzoKDWIyiV1pJW93xlQic1THVLXilz429oijRpSHivZAgp65KBu+cMcgf1eVVjdnTLvPxgCuoQ==", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.62.2.tgz", + "integrity": "sha512-E9/ll019jhPIJgpzfZoIkBGhcz+kKNgVWYRY0zr9srBdPPFVpvOKW8VaJKUbeK+eZXyQF9ltME+Kk6affeaPgg==", "cpu": [ "s390x" ], @@ -2074,9 +2121,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.60.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.60.4.tgz", - "integrity": "sha512-Boiz5+MsaROEWDf+GGEwF8VMHGhlUoQMtIPjOgA5fv4osupqTVnJteQNKJwUcnUog2G55jYXH7KZFFiJe0TEzQ==", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.62.2.tgz", + "integrity": "sha512-5BqxR/pshjey51iliyzTD5Xi3EN0aLmQ2lZ3lvefVV9c82BvrLo2/6OT55iifpWBufs6kdwWbuOKS841DrmK9A==", "cpu": [ "x64" ], @@ -2087,9 +2134,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.60.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.60.4.tgz", - "integrity": "sha512-+qfSY27qIrFfI/Hom04KYFw3GKZSGU4lXus51wsb5EuySfFlWRwjkKWoE9emgRw/ukoT4Udsj4W/+xxG8VbPKg==", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.62.2.tgz", + "integrity": "sha512-uNN83XxQrRAh/w0/pmAfibcwyb6YWt4gP+dpnQKPVJshAloQ785ii8CT8ZCIxkGg9opVsvAlGhFitSm6D1Jjpg==", "cpu": [ "x64" ], @@ -2100,9 +2147,9 @@ ] }, "node_modules/@rollup/rollup-openbsd-x64": { - "version": "4.60.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.60.4.tgz", - "integrity": "sha512-VpTfOPHgVXEBeeR8hZ2O0F3aSso+JDWqTWmTmzcQKted54IAdUVbxE+j/MVxUsKa8L20HJhv3vUezVPoquqWjA==", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.62.2.tgz", + "integrity": "sha512-srjEIxSH3LRnJN6THczDHWQplqEMFiAJrTab0msUryh9kwNpkICf3Ea6q6MN/2cZwRFUNx5w+h6Hpi4QuHS6Zg==", "cpu": [ "x64" ], @@ -2113,9 +2160,9 @@ ] }, "node_modules/@rollup/rollup-openharmony-arm64": { - "version": "4.60.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.60.4.tgz", - "integrity": "sha512-IPOsh5aRYuLv/nkU51X10Bf75Bsf6+gZdx1X+QP5QM6lIJFHHqbHLG0uJn/hWthzo13UAc2umiUorqZy3axoZg==", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.62.2.tgz", + "integrity": "sha512-8hOJnxgbyObnCm5AlRA3A931xX19xq80RjVTKgJOvEKWqJruP/Uf12IbAOaDjjEXYRewwHLfmF0YRIdK3OwKWA==", "cpu": [ "arm64" ], @@ -2126,9 +2173,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.60.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.60.4.tgz", - "integrity": "sha512-4QzE9E81OohJ/HKzHhsqU+zcYYojVOXlFMs1DdyMT6qXl/niOH7AVElmmEdUNHHS/oRkc++d5k6Vy85zFs0DEw==", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.62.2.tgz", + "integrity": "sha512-mmF4AY1i0hG/bLWUctUq59gtmgaSIRa3cu/A3JFRp/sCNEme2bgDEiDS22P9FbnJB8NJNF4jPJiSP5RHQpUTDg==", "cpu": [ "arm64" ], @@ -2139,9 +2186,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.60.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.60.4.tgz", - "integrity": "sha512-zTPgT1YuHHcd+Tmx7h8aml0FWFVelV5N54oHow9SLj+GfoDy/huQ+UV396N/C7KpMDMiPspRktzM1/0r1usYEA==", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.62.2.tgz", + "integrity": "sha512-DZgkknc6jhHrk46V25vbAM0zZkyP0nSDkJB8/dRkLTxv470dOmWDqGoEJl/9A0dFfS7yE3REOwNDxpHwSLSt0Q==", "cpu": [ "ia32" ], @@ -2152,9 +2199,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-gnu": { - "version": "4.60.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.60.4.tgz", - "integrity": "sha512-DRS4G7mi9lJxqEDezIkKCaUIKCrLUUDCUaCsTPCi/rtqaC6D/jjwslMQyiDU50Ka0JKpeXeRBFBAXwArY52vBw==", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.62.2.tgz", + "integrity": "sha512-T6xr6ucWSFto+VGajA8YH26LdpHRuP4YLHEKAtCWvJDOlnmWcDZVCI2Jmjr+IFHDlt2zRaTAKE4tfjTaWLgJBg==", "cpu": [ "x64" ], @@ -2165,9 +2212,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.60.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.60.4.tgz", - "integrity": "sha512-QVTUovf40zgTqlFVrKA1uXMVvU2QWEFWfAH8Wdc48IxLvrJMQVMBRjuQyUpzZCDkakImib9eVazbWlC6ksWtJw==", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.62.2.tgz", + "integrity": "sha512-BfzEnDJOt9T8M989/lA37EcJgat01wLRnoi5dQf3QzOH7jzpqTAzdDbVfRljVr5r+jzKqpbHeyOfAaXxAd0PAA==", "cpu": [ "x64" ], @@ -2178,13 +2225,13 @@ ] }, "node_modules/@shikijs/core": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-4.1.0.tgz", - "integrity": "sha512-jLJtSJeuFffqX6/inRE1zqU5aFv2hrszvYgq3OjbAgFRZiWv7abKMDdQzYxuSDfmUPQozZvI/kuy6VMTvnvqTQ==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-4.3.1.tgz", + "integrity": "sha512-ANMDxuaPsNMdDC1m4vfvhlDmJweMwkE5XitTwrq2rWHx5jM+dlm4MmHt2PP6t0uejfR77SuhrhJ0zEijIF/uhA==", "license": "MIT", "dependencies": { - "@shikijs/primitive": "4.1.0", - "@shikijs/types": "4.1.0", + "@shikijs/primitive": "4.3.1", + "@shikijs/types": "4.3.1", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4", "hast-util-to-html": "^9.0.5" @@ -2194,12 +2241,12 @@ } }, "node_modules/@shikijs/engine-javascript": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@shikijs/engine-javascript/-/engine-javascript-4.1.0.tgz", - "integrity": "sha512-YquhawCUgaBfhsS72e2Y/dI59gCBNPHu3fEO/tvLaXrTssxZrY5ddjtNLTwndrMgPo8b3IscE+xoICDzpTmlFQ==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@shikijs/engine-javascript/-/engine-javascript-4.3.1.tgz", + "integrity": "sha512-JBItcnPuYq7jVJdZo/vMj94r+szT7XEjHFX+mvFDGSEIbVAXAGyHAHzhbWzpGOwYidCZrErJLLgn2PVeiokHnQ==", "license": "MIT", "dependencies": { - "@shikijs/types": "4.1.0", + "@shikijs/types": "4.3.1", "@shikijs/vscode-textmate": "^10.0.2", "oniguruma-to-es": "^4.3.6" }, @@ -2208,12 +2255,12 @@ } }, "node_modules/@shikijs/engine-oniguruma": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-4.1.0.tgz", - "integrity": "sha512-axLpjVs45YBvvINa+dJF+NPW+KtFkNXsFr4SDw2BMj9GdeMnGxVB9PQb2xXlJYovslt/nz6giedAyOANkfc7hg==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-4.3.1.tgz", + "integrity": "sha512-OXyNMzg0pews+msMj4cHeqT4xiYKKvbnn6VbdAXxfoFl3SSx4fJTc8FadECuc5/H9p3BzhNAoAUXKwAu9rWYhg==", "license": "MIT", "dependencies": { - "@shikijs/types": "4.1.0", + "@shikijs/types": "4.3.1", "@shikijs/vscode-textmate": "^10.0.2" }, "engines": { @@ -2221,24 +2268,24 @@ } }, "node_modules/@shikijs/langs": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@shikijs/langs/-/langs-4.1.0.tgz", - "integrity": "sha512-nwOMruEkbgdZfQ/b8CgpNBVOpvG1k0N5tbmgiFeqsan401+x3ILqlzZJowSla4Agmq4hG2Uf2wh5jLTEhR8VSg==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@shikijs/langs/-/langs-4.3.1.tgz", + "integrity": "sha512-m0l9nsDqgBHvbZbk7A0/kXz/impK3uB/c6rAn6Gpg/uPtdZRQ+alsN/17MU5thb68XTj/4DxkZAotrM0GGSpDQ==", "license": "MIT", "dependencies": { - "@shikijs/types": "4.1.0" + "@shikijs/types": "4.3.1" }, "engines": { "node": ">=20" } }, "node_modules/@shikijs/primitive": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@shikijs/primitive/-/primitive-4.1.0.tgz", - "integrity": "sha512-zx2/2Uwj2q9X3KSyYREEhXO23xBw5WUhP4orK2lE4r+t9JGITmEe0JH+wPmJhqHpOT2bRRs6lAL945+LDvOAGw==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@shikijs/primitive/-/primitive-4.3.1.tgz", + "integrity": "sha512-CXQRQOYy1leqQ8ceTeJdmXv/bsUY++6QyLpXJ94LZAAYj5X2SKRdc5ipguv4NPyGVKItB2PPwUpRNe0Sjh5S1A==", "license": "MIT", "dependencies": { - "@shikijs/types": "4.1.0", + "@shikijs/types": "4.3.1", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" }, @@ -2247,21 +2294,21 @@ } }, "node_modules/@shikijs/themes": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@shikijs/themes/-/themes-4.1.0.tgz", - "integrity": "sha512-emCcTnUM7yO2wltYbaxm+yLvcCI4+h8XBKc4KmJ7EZUXoSGjcCHifkI//R4OFit9ewpg7H2/9tjOuXrT2v/Knw==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@shikijs/themes/-/themes-4.3.1.tgz", + "integrity": "sha512-dgpoJ4WqNi2yTmizQHBJ5zcX6j2lE6icN/0yt4l1kkf16jrY/pwPLoTb1ETsWMz0OBLf9ZNvwmxft+cH+N9qSA==", "license": "MIT", "dependencies": { - "@shikijs/types": "4.1.0" + "@shikijs/types": "4.3.1" }, "engines": { "node": ">=20" } }, "node_modules/@shikijs/types": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-4.1.0.tgz", - "integrity": "sha512-3EQWX54fMpniOrDblzAhiwiJwpiTMW6+B9DWyUd9ska483tbayFYuw47UxwuPknI31bKnySfVQ/QW+jFL4rFdA==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-4.3.1.tgz", + "integrity": "sha512-CHFxE0jztBIZRHH6gxXE7DXUCFXjReEGxZ/j0rfSLGKZuwp2xBYycEP14875DSa9KLL/6700oxIq6oO6ef9K2g==", "license": "MIT", "dependencies": { "@shikijs/vscode-textmate": "^10.0.2", @@ -2376,14 +2423,13 @@ } }, "node_modules/@types/node": { - "version": "25.9.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-25.9.1.tgz", - "integrity": "sha512-xfrlY7UD5rMJk3ZVJP8BNzS28J36YJg+xp+LPXV1TdWxr8uMH5A860QNxYDGQe/ylDSgjxE52Q9VnO7p75tJxg==", + "version": "26.1.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-26.1.0.tgz", + "integrity": "sha512-O0A1G3xPGy4w7AgQdAQYUlQ+BKk2Oovw8eRpofyp5KdBZULnbe+WqaOVNrm705SHphCiG4XHsACrSmPu1f+Kgw==", "dev": true, "license": "MIT", - "optional": true, "dependencies": { - "undici-types": ">=7.24.0 <7.24.7" + "undici-types": "~8.3.0" } }, "node_modules/@types/parse-json": { @@ -2393,9 +2439,9 @@ "license": "MIT" }, "node_modules/@types/react": { - "version": "19.2.15", - "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.15.tgz", - "integrity": "sha512-eRwcGNHve+E8qtEQSSRl6urh+rFop4v8gm6O8rGv25CodbvFdLjA1vVQ1KkiFE0w0UPOnb8tDiFKL5lp0rtY5Q==", + "version": "19.2.17", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.17.tgz", + "integrity": "sha512-MXfmqaVPEVgkBT/aY0aGCkRWWtByiYQXo3xdQ8r5RzuFrPiRn8Gar2tQdXSUQ2GKV3bkXckek89V8wQBY2Q/Aw==", "dev": true, "license": "MIT", "dependencies": { @@ -2448,21 +2494,10 @@ "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", "license": "MIT" }, - "node_modules/@types/yauzl": { - "version": "2.10.3", - "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.3.tgz", - "integrity": "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@types/node": "*" - } - }, "node_modules/@ungap/structured-clone": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.1.tgz", - "integrity": "sha512-mUFwbeTqrVgDQxFveS+df2yfap6iuP20NAKAsBt5jDEoOTDew+zwLAOilHCeQJOVSvmgCX4ogqIrA0mnyr08yQ==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.2.tgz", + "integrity": "sha512-5jsZFwgR5rTdKwidH9Qmat75RKwqfpKlWWB1frDkljN127mwqBu8K0PYo7/hFpF03IEJpfVPpCQDY/eDx3iHvA==", "license": "ISC" }, "node_modules/@vitejs/plugin-react": { @@ -2634,14 +2669,14 @@ } }, "node_modules/astro": { - "version": "6.3.8", - "resolved": "https://registry.npmjs.org/astro/-/astro-6.3.8.tgz", - "integrity": "sha512-xH2UA8Z17IS+JaqSlSkBor7jO6gd7zXTLdmu06nKpfpDDJFbi/7KZEy3NDmWxmier+6XrCZ9Z4aitO8jhC9oiA==", + "version": "6.4.8", + "resolved": "https://registry.npmjs.org/astro/-/astro-6.4.8.tgz", + "integrity": "sha512-KK5lX90uU9EeVaTjINyj3sy9/NFXVa59aowaqbWBDDKLXZh4rr7GwIaCFYVetE22MJtsCNFerQXn0vlCLmpP/Q==", "license": "MIT", "dependencies": { "@astrojs/compiler": "^4.0.0", - "@astrojs/internal-helpers": "0.9.1", - "@astrojs/markdown-remark": "7.1.2", + "@astrojs/internal-helpers": "0.10.0", + "@astrojs/markdown-remark": "7.2.0", "@astrojs/telemetry": "3.3.2", "@capsizecss/unpack": "^4.0.0", "@clack/prompts": "^1.1.0", @@ -2653,7 +2688,7 @@ "clsx": "^2.1.1", "common-ancestor-path": "^2.0.0", "cookie": "^1.1.1", - "devalue": "^5.6.3", + "devalue": "^5.8.1", "diff": "^8.0.3", "dset": "^3.1.4", "es-module-lexer": "^2.0.0", @@ -2712,9 +2747,9 @@ } }, "node_modules/astro/node_modules/semver": { - "version": "7.8.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.1.tgz", - "integrity": "sha512-rkVq3IXh+4FDGch+KwzX3aV9W3kO54GyEgpvBzSyctDA6Xtd7RJQV1xmXbeQp5v7+VzLOfVqiutSE6GICgPFvg==", + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", "license": "ISC", "bin": { "semver": "bin/semver.js" @@ -2723,6 +2758,48 @@ "node": ">=10" } }, + "node_modules/astro/node_modules/unist-util-is": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.1.tgz", + "integrity": "sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/astro/node_modules/unist-util-visit": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.1.0.tgz", + "integrity": "sha512-m+vIdyeCOpdr/QeQCu2EzxX/ohgS8KbnPDgFni4dQsfSCtpz8UqDyY5GjRru8PDKuYn7Fq19j1CQ+nJSsGKOzg==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/astro/node_modules/unist-util-visit-parents": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.2.tgz", + "integrity": "sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", @@ -2741,9 +2818,9 @@ } }, "node_modules/autoprefixer": { - "version": "10.5.0", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.5.0.tgz", - "integrity": "sha512-FMhOoZV4+qR6aTUALKX2rEqGG+oyATvwBt9IIzVR5rMa2HRWPkxf+P+PAJLD1I/H5/II+HuZcBJYEFBpq39ong==", + "version": "10.5.2", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.5.2.tgz", + "integrity": "sha512-rD5t5DwOjJdmSORcTq64j8MawTC+tbQ+HHqjR4NDumamy/ambn1UJrlKL+KdwujWxMkFjPM3pPHOEA9tl4767Q==", "funding": [ { "type": "opencollective", @@ -2760,8 +2837,8 @@ ], "license": "MIT", "dependencies": { - "browserslist": "^4.28.2", - "caniuse-lite": "^1.0.30001787", + "browserslist": "^4.28.4", + "caniuse-lite": "^1.0.30001799", "fraction.js": "^5.3.4", "picocolors": "^1.1.1", "postcss-value-parser": "^4.2.0" @@ -2849,9 +2926,9 @@ "license": "MIT" }, "node_modules/baseline-browser-mapping": { - "version": "2.10.32", - "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.32.tgz", - "integrity": "sha512-wbPvpyjJPC0zdfdKXxqEL3Ea+bOMD/87X4lftiJkkaBiuG6ALQy1SLmEd7BSmVCuwCQsBrCamgBoLyfFDD1EPg==", + "version": "2.10.42", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.42.tgz", + "integrity": "sha512-c/jurFrDLyui7o1J86yLkRu4LMsTYcBohveus7/I2Hzdn9KIP2bdJPTue/lR1KH46enoPbD77GKeSYNdyPoD3Q==", "license": "Apache-2.0", "bin": { "baseline-browser-mapping": "dist/cli.cjs" @@ -2915,9 +2992,9 @@ } }, "node_modules/browserslist": { - "version": "4.28.2", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.2.tgz", - "integrity": "sha512-48xSriZYYg+8qXna9kwqjIVzuQxi+KYWp2+5nCYnYKPTr0LvD89Jqk2Or5ogxz0NUMfIjhh2lIUX/LyX9B4oIg==", + "version": "4.28.5", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.5.tgz", + "integrity": "sha512-Cu2E6QejHWzuDMTkuwgpABFgDfZrXLQq5V13YOACZx4mFAG4IwGTbTfHPMr4WtxlHoXSM8FIuRwYYCz5XiabaQ==", "funding": [ { "type": "opencollective", @@ -2934,10 +3011,10 @@ ], "license": "MIT", "dependencies": { - "baseline-browser-mapping": "^2.10.12", - "caniuse-lite": "^1.0.30001782", - "electron-to-chromium": "^1.5.328", - "node-releases": "^2.0.36", + "baseline-browser-mapping": "^2.10.42", + "caniuse-lite": "^1.0.30001800", + "electron-to-chromium": "^1.5.387", + "node-releases": "^2.0.50", "update-browserslist-db": "^1.2.3" }, "bin": { @@ -2972,16 +3049,6 @@ "ieee754": "^1.1.13" } }, - "node_modules/buffer-crc32": { - "version": "0.2.13", - "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", - "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": "*" - } - }, "node_modules/cachedir": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/cachedir/-/cachedir-2.4.0.tgz", @@ -3042,9 +3109,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001793", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001793.tgz", - "integrity": "sha512-iwSsYWaCOoh26cV8NwNRViHlrfUvYsHDfRVcbtmw0Kg6PJIZZXwMkj1442FYLBGkeUf1juAsU3DTfxW579mrPA==", + "version": "1.0.30001802", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001802.tgz", + "integrity": "sha512-vmv8ub2xwTNmljSKf82mtCk5JH7hC+YgzLj3P5zotvA0tPQ9016tdNNOG8WRca1IxOnhSsivB+J0z5FeE5LOUw==", "funding": [ { "type": "opencollective", @@ -3563,9 +3630,9 @@ "license": "MIT" }, "node_modules/cypress": { - "version": "15.15.0", - "resolved": "https://registry.npmjs.org/cypress/-/cypress-15.15.0.tgz", - "integrity": "sha512-N8qBv3AUYn6xfIG73O5O58kTClUBSZ7a3C08IQFkSGTUdEauJ3BqwTFb/f9KPZgadftoZjllC0XSwD7xNNolbA==", + "version": "15.18.0", + "resolved": "https://registry.npmjs.org/cypress/-/cypress-15.18.0.tgz", + "integrity": "sha512-aLfOYSLlVt1b6QSoVUjbCY27taZlYAT8ST47xQbwd9pvQrY/g5gXi12yItZTB+kxkkj+ZcvUYmRLUC95SlCJsw==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -3590,7 +3657,6 @@ "eventemitter2": "6.4.7", "execa": "4.1.0", "executable": "^4.1.1", - "extract-zip": "2.0.1", "fs-extra": "^9.1.0", "hasha": "5.2.2", "is-installed-globally": "~0.4.0", @@ -3609,7 +3675,7 @@ "tree-kill": "1.2.2", "tslib": "1.14.1", "untildify": "^4.0.0", - "yauzl": "^2.10.0" + "yauzl": "^3.3.1" }, "bin": { "cypress": "bin/cypress" @@ -3871,9 +3937,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.5.361", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.361.tgz", - "integrity": "sha512-Q6Hts7N9FnJc5LeGRINFvLhCI9xZmNtTDe5ZbcVezQz7cU4a8Aua3GH1b8J2XY8Al9PF+OCwYqhgsOOheMdvkA==", + "version": "1.5.387", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.387.tgz", + "integrity": "sha512-TaxwufTFDufvPEoXdhwVrA3UdFWBeWGkYoJ1K8ldF1xe6gKfth6iRNS5lTQ5JPNOHdGQm8PT1QYKUqFLCiUefQ==", "license": "ISC" }, "node_modules/emoji-regex": { @@ -3947,9 +4013,9 @@ } }, "node_modules/es-module-lexer": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.1.0.tgz", - "integrity": "sha512-n27zTYMjYu1aj4MjCWzSP7G9r75utsaoc8m61weK+W8JMBGGQybd43GstCXZ3WNmSFtGT9wi59qQTW6mhTR5LQ==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.3.0.tgz", + "integrity": "sha512-KLdwQm2NvGLDkQDCGvmiQrhkd0JbMzXthwQAUgWjQuQdBLFa3eiBP5arXZyA+f8x+x7OXgud6bq2rxjGtHV2tw==", "license": "MIT" }, "node_modules/es-object-atoms": { @@ -4115,27 +4181,6 @@ "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", "license": "MIT" }, - "node_modules/extract-zip": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", - "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "debug": "^4.1.1", - "get-stream": "^5.1.0", - "yauzl": "^2.10.0" - }, - "bin": { - "extract-zip": "cli.js" - }, - "engines": { - "node": ">= 10.17.0" - }, - "optionalDependencies": { - "@types/yauzl": "^2.9.1" - } - }, "node_modules/extsprintf": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", @@ -4207,16 +4252,6 @@ "reusify": "^1.0.4" } }, - "node_modules/fd-slicer": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", - "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", - "dev": true, - "license": "MIT", - "dependencies": { - "pend": "~1.2.0" - } - }, "node_modules/fdir": { "version": "6.5.0", "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", @@ -4293,17 +4328,17 @@ } }, "node_modules/form-data": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz", - "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.6.tgz", + "integrity": "sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ==", "dev": true, "license": "MIT", "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" + "hasown": "^2.0.4", + "mime-types": "^2.1.35" }, "engines": { "node": ">= 6" @@ -4603,9 +4638,9 @@ } }, "node_modules/hasown": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.3.tgz", - "integrity": "sha512-ej4AhfhfL2Q2zpMmLo7U1Uv9+PyhIZpgQLGT1F9miIGmiCJIoCgSmczFdrc97mWT4kVY72KA+WnnhJ5pghSvSg==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz", + "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==", "license": "MIT", "dependencies": { "function-bind": "^1.1.2" @@ -4716,6 +4751,48 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/hast-util-raw/node_modules/unist-util-is": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.1.tgz", + "integrity": "sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-raw/node_modules/unist-util-visit": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.1.0.tgz", + "integrity": "sha512-m+vIdyeCOpdr/QeQCu2EzxX/ohgS8KbnPDgFni4dQsfSCtpz8UqDyY5GjRru8PDKuYn7Fq19j1CQ+nJSsGKOzg==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-raw/node_modules/unist-util-visit-parents": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.2.tgz", + "integrity": "sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/hast-util-to-html": { "version": "9.0.5", "resolved": "https://registry.npmjs.org/hast-util-to-html/-/hast-util-to-html-9.0.5.tgz", @@ -5254,13 +5331,10 @@ } }, "node_modules/js-cookie": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.7.tgz", - "integrity": "sha512-z/wZZgDrkNV1eA0ULjM/F9/50Ya8fbzgKneSpoPsXSGd0KnpdtHfOZWK+GcwLk+EZbS4F9RBhU+K2RgzuDaItw==", - "license": "MIT", - "engines": { - "node": ">=20" - } + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.8.tgz", + "integrity": "sha512-yeJd4aNAdYZQjaon2bpD/Gb0B/omw7HQOsynXXcOiWVCacbBcPlgn8S/d1X6blFSaHao7ozqtW7NZW19xpCtIw==", + "license": "MIT" }, "node_modules/js-tokens": { "version": "4.0.0", @@ -5269,9 +5343,19 @@ "license": "MIT" }, "node_modules/js-yaml": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", - "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.0.tgz", + "integrity": "sha512-1td788aAnnZ5qs7V2QIRl1owjtYpbKt749Y3xauqQgwIIGF/xXWz1wMTEBx5O3LK3lXLVuqXPdPxj2BoFHaW9Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/puzrin" + }, + { + "type": "github", + "url": "https://github.com/sponsors/nodeca" + } + ], "license": "MIT", "dependencies": { "argparse": "^2.0.1" @@ -5569,6 +5653,48 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/mdast-util-definitions/node_modules/unist-util-is": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.1.tgz", + "integrity": "sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-definitions/node_modules/unist-util-visit": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.1.0.tgz", + "integrity": "sha512-m+vIdyeCOpdr/QeQCu2EzxX/ohgS8KbnPDgFni4dQsfSCtpz8UqDyY5GjRru8PDKuYn7Fq19j1CQ+nJSsGKOzg==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-definitions/node_modules/unist-util-visit-parents": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.2.tgz", + "integrity": "sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/mdast-util-find-and-replace": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/mdast-util-find-and-replace/-/mdast-util-find-and-replace-3.0.2.tgz", @@ -5597,17 +5723,44 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/mdast-util-from-markdown": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.3.tgz", - "integrity": "sha512-W4mAWTvSlKvf8L6J+VN9yLSqQ9AOAAvHuoDAmPkz4dHf553m5gVj2ejadHJhoJmcmxEnOv6Pa8XJhpxE93kb8Q==", + "node_modules/mdast-util-find-and-replace/node_modules/unist-util-is": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.1.tgz", + "integrity": "sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==", "license": "MIT", "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", + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-find-and-replace/node_modules/unist-util-visit-parents": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.2.tgz", + "integrity": "sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-from-markdown": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.3.tgz", + "integrity": "sha512-W4mAWTvSlKvf8L6J+VN9yLSqQ9AOAAvHuoDAmPkz4dHf553m5gVj2ejadHJhoJmcmxEnOv6Pa8XJhpxE93kb8Q==", + "license": "MIT", + "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", @@ -5796,6 +5949,19 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/mdast-util-phrasing/node_modules/unist-util-is": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.1.tgz", + "integrity": "sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/mdast-util-to-hast": { "version": "13.2.1", "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.2.1.tgz", @@ -5817,6 +5983,48 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/mdast-util-to-hast/node_modules/unist-util-is": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.1.tgz", + "integrity": "sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-to-hast/node_modules/unist-util-visit": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.1.0.tgz", + "integrity": "sha512-m+vIdyeCOpdr/QeQCu2EzxX/ohgS8KbnPDgFni4dQsfSCtpz8UqDyY5GjRru8PDKuYn7Fq19j1CQ+nJSsGKOzg==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-to-hast/node_modules/unist-util-visit-parents": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.2.tgz", + "integrity": "sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/mdast-util-to-markdown": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-2.1.2.tgz", @@ -5838,6 +6046,48 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/mdast-util-to-markdown/node_modules/unist-util-is": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.1.tgz", + "integrity": "sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-to-markdown/node_modules/unist-util-visit": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.1.0.tgz", + "integrity": "sha512-m+vIdyeCOpdr/QeQCu2EzxX/ohgS8KbnPDgFni4dQsfSCtpz8UqDyY5GjRru8PDKuYn7Fq19j1CQ+nJSsGKOzg==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-to-markdown/node_modules/unist-util-visit-parents": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.2.tgz", + "integrity": "sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/mdast-util-to-string": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-4.0.0.tgz", @@ -6550,9 +6800,9 @@ } }, "node_modules/nanoid": { - "version": "3.3.12", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.12.tgz", - "integrity": "sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==", + "version": "3.3.15", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.15.tgz", + "integrity": "sha512-y7Wygv/7mEOvxTuEQDB8StXdMRBWf1kR/tlhAzBRUFkB2jfcLOAxO/SHmOO2zgz1pVgK29/kyupn059/bCHdjA==", "funding": [ { "type": "github", @@ -6602,9 +6852,9 @@ "license": "MIT" }, "node_modules/node-releases": { - "version": "2.0.46", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.46.tgz", - "integrity": "sha512-GYVXHE2KnrzAfsAjl4uP++evGFCrAU1jta4ubEjIG7YWt/64Gqv66a30yKwWczVjA6j3bM4nBwH7Pk1JmDHaxQ==", + "version": "2.0.50", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.50.tgz", + "integrity": "sha512-J6l92tKHX6w8Jy5nO1Vuc01NoIiRGi/d6qBKVxh+IQ8Cr3b6HbVNfKiF8ZpFKufTwpwxMmce2W3iQZ861ZRyTg==", "license": "MIT", "engines": { "node": ">=18" @@ -6685,14 +6935,17 @@ } }, "node_modules/obug": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/obug/-/obug-2.1.1.tgz", - "integrity": "sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/obug/-/obug-2.1.3.tgz", + "integrity": "sha512-9miFgM2OFba7hB+pRgvtV84pYTBaoTHohvmIgiRt6dRIzbwEOIaNaP+dIlGs2fNFoB0SeISs0Jz5WFVRid6Xyg==", "funding": [ "https://github.com/sponsors/sxzz", "https://opencollective.com/debug" ], - "license": "MIT" + "license": "MIT", + "engines": { + "node": ">=12.20.0" + } }, "node_modules/ofetch": { "version": "1.5.1", @@ -6777,9 +7030,9 @@ } }, "node_modules/p-queue": { - "version": "9.3.0", - "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-9.3.0.tgz", - "integrity": "sha512-7NED7xhQ74Ngp4JP/2e0VZHp7vSWfJfqeiR92jPgxsz6m0Se4P03YoTKa9dDXyZ3r6P616gUXttrB6nnHYKang==", + "version": "9.3.1", + "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-9.3.1.tgz", + "integrity": "sha512-POWdiIPmsUPGwb4FeQ4OBg46aqmcInSWe45CKDsGHiOBiVQM9chqfQTuqhuTzcg2Vz9faTI65at0KkVyVEiCHw==", "license": "MIT", "dependencies": { "eventemitter3": "^5.0.4", @@ -6805,9 +7058,9 @@ } }, "node_modules/package-manager-detector": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/package-manager-detector/-/package-manager-detector-1.6.0.tgz", - "integrity": "sha512-61A5ThoTiDG/C8s8UMZwSorAGwMJ0ERVGj2OjoW5pAalsNOg15+iQiPzrLJ4jhZ1HJzmC2PIHT2oEiH3R5fzNA==", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/package-manager-detector/-/package-manager-detector-1.7.0.tgz", + "integrity": "sha512-xg1eHpwYL/D/HEdWw2goFZP6vV0FH7W+PZ5rFkGjdIDLtxq7EkzBUeT3m+lndYCt8wKbmofUu1MUdMCXkCk9ZQ==", "license": "MIT" }, "node_modules/pagefind": { @@ -6965,9 +7218,9 @@ "license": "ISC" }, "node_modules/picomatch": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", - "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.5.tgz", + "integrity": "sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==", "license": "MIT", "engines": { "node": ">=12" @@ -6995,9 +7248,9 @@ } }, "node_modules/postcss": { - "version": "8.5.15", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.15.tgz", - "integrity": "sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A==", + "version": "8.5.16", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.16.tgz", + "integrity": "sha512-vuwillviilfKZsg0VGj5R/YwwcHx4SLsIOI/7K6mQkWx+l5cUHTjj5g0AasTBcyXsbfTgrwsUNmVUb5xVwyPwg==", "funding": [ { "type": "opencollective", @@ -7125,9 +7378,9 @@ } }, "node_modules/postcss-selector-parser": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", - "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.4.tgz", + "integrity": "sha512-bIoJLOmjCO1S9XdY/DcnR5hJxvrDir1PbGChrzXG3vw0/FOliy/fA3dmdhQ441kah4gKv+TwckGzex6wNS5cnQ==", "license": "MIT", "dependencies": { "cssesc": "^3.0.0", @@ -7187,9 +7440,9 @@ } }, "node_modules/property-information": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/property-information/-/property-information-7.1.0.tgz", - "integrity": "sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/property-information/-/property-information-7.2.0.tgz", + "integrity": "sha512-IAtzIB6sUiWaJYrX9smp3V46pBGbBeLFRGdh25kg1334VcBlD8HzhPeNIWQH9zhGmo2itIe25EHt9dQP7G5hmg==", "license": "MIT", "funding": { "type": "github", @@ -7215,13 +7468,14 @@ } }, "node_modules/qs": { - "version": "6.15.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.2.tgz", - "integrity": "sha512-Rzq0KEyX/w/tEybncDgdkZrJgVUsUMk3xjh3t5bv3S1HTAtg+uOYt72+ZfwiQwKdysThkTBdL/rTi6HDmX9Ddw==", + "version": "6.15.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.3.tgz", + "integrity": "sha512-O9gl3zCl5h5blw1KGUzQKhA5oUXSl8rwUIM5o0S3nCXMliSvy5Dzx7/DJcI+SwgICv+IneSZwhBh1oSyEHA71A==", "dev": true, "license": "BSD-3-Clause", "dependencies": { - "side-channel": "^1.1.0" + "es-define-property": "^1.0.1", + "side-channel": "^1.1.1" }, "engines": { "node": ">=0.6" @@ -7257,9 +7511,9 @@ "license": "MIT" }, "node_modules/react": { - "version": "19.2.6", - "resolved": "https://registry.npmjs.org/react/-/react-19.2.6.tgz", - "integrity": "sha512-sfWGGfavi0xr8Pg0sVsyHMAOziVYKgPLNrS7ig+ivMNb3wbCBw3KxtflsGBAwD3gYQlE/AEZsTLgToRrSCjb0Q==", + "version": "19.2.7", + "resolved": "https://registry.npmjs.org/react/-/react-19.2.7.tgz", + "integrity": "sha512-HNe9WslTbXmFK8o8cmwgAeJFSBvt1bPdHCVKtaaV+WlAN36mpT4hcRpwbf3fY56ar2oIXzsBpOAiIRHAdY0OlQ==", "license": "MIT", "engines": { "node": ">=0.10.0" @@ -7279,15 +7533,15 @@ } }, "node_modules/react-dom": { - "version": "19.2.6", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.6.tgz", - "integrity": "sha512-0prMI+hvBbPjsWnxDLxlCGyM8PN6UuWjEUCYmZhO67xIV9Xasa/r/vDnq+Xyq4Lo27g8QSbO5YzARu0D1Sps3g==", + "version": "19.2.7", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.7.tgz", + "integrity": "sha512-t0BRVXvbiE/o20Hfw669rLbMCDWtYZLvmJigy2f0MxsXF+71pxhR3xOkspmsO8h3ZlNzyibAmtCa3l4lYKk6gQ==", "license": "MIT", "dependencies": { "scheduler": "^0.27.0" }, "peerDependencies": { - "react": "^19.2.6" + "react": "^19.2.7" } }, "node_modules/react-hotkeys": { @@ -7350,6 +7604,48 @@ "react": ">=18" } }, + "node_modules/react-markdown/node_modules/unist-util-is": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.1.tgz", + "integrity": "sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/react-markdown/node_modules/unist-util-visit": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.1.0.tgz", + "integrity": "sha512-m+vIdyeCOpdr/QeQCu2EzxX/ohgS8KbnPDgFni4dQsfSCtpz8UqDyY5GjRru8PDKuYn7Fq19j1CQ+nJSsGKOzg==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/react-markdown/node_modules/unist-util-visit-parents": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.2.tgz", + "integrity": "sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/react-refresh": { "version": "0.18.0", "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.18.0.tgz", @@ -7514,6 +7810,48 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/rehype-autolink-headings/node_modules/unist-util-is": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.1.tgz", + "integrity": "sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/rehype-autolink-headings/node_modules/unist-util-visit": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.1.0.tgz", + "integrity": "sha512-m+vIdyeCOpdr/QeQCu2EzxX/ohgS8KbnPDgFni4dQsfSCtpz8UqDyY5GjRru8PDKuYn7Fq19j1CQ+nJSsGKOzg==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/rehype-autolink-headings/node_modules/unist-util-visit-parents": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.2.tgz", + "integrity": "sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/rehype-parse": { "version": "9.0.1", "resolved": "https://registry.npmjs.org/rehype-parse/-/rehype-parse-9.0.1.tgz", @@ -7561,6 +7899,48 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/rehype-slug/node_modules/unist-util-is": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.1.tgz", + "integrity": "sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/rehype-slug/node_modules/unist-util-visit": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.1.0.tgz", + "integrity": "sha512-m+vIdyeCOpdr/QeQCu2EzxX/ohgS8KbnPDgFni4dQsfSCtpz8UqDyY5GjRru8PDKuYn7Fq19j1CQ+nJSsGKOzg==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/rehype-slug/node_modules/unist-util-visit-parents": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.2.tgz", + "integrity": "sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/rehype-stringify": { "version": "10.0.1", "resolved": "https://registry.npmjs.org/rehype-stringify/-/rehype-stringify-10.0.1.tgz", @@ -7594,6 +7974,20 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/remark-heading-id": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/remark-heading-id/-/remark-heading-id-1.0.1.tgz", + "integrity": "sha512-GmJjuCeEkYvwFlvn/Skjc/1Qafj71412gbQnrwUmP/tKskmAf1cMRlZRNoovV+aIvsSRkTb2rCmGv2b9RdoJbQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "lodash": "^4.17.21", + "unist-util-visit": "^1.4.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/remark-parse": { "version": "11.0.0", "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-11.0.0.tgz", @@ -7642,6 +8036,48 @@ "node": ">=16.0.0" } }, + "node_modules/remark-smartypants/node_modules/unist-util-is": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.1.tgz", + "integrity": "sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-smartypants/node_modules/unist-util-visit": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.1.0.tgz", + "integrity": "sha512-m+vIdyeCOpdr/QeQCu2EzxX/ohgS8KbnPDgFni4dQsfSCtpz8UqDyY5GjRru8PDKuYn7Fq19j1CQ+nJSsGKOzg==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-smartypants/node_modules/unist-util-visit-parents": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.2.tgz", + "integrity": "sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/remark-stringify": { "version": "11.0.0", "resolved": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-11.0.0.tgz", @@ -7798,6 +8234,48 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/retext-smartypants/node_modules/unist-util-is": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.1.tgz", + "integrity": "sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/retext-smartypants/node_modules/unist-util-visit": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.1.0.tgz", + "integrity": "sha512-m+vIdyeCOpdr/QeQCu2EzxX/ohgS8KbnPDgFni4dQsfSCtpz8UqDyY5GjRru8PDKuYn7Fq19j1CQ+nJSsGKOzg==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/retext-smartypants/node_modules/unist-util-visit-parents": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.2.tgz", + "integrity": "sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/retext-stringify": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/retext-stringify/-/retext-stringify-4.0.0.tgz", @@ -7831,12 +8309,12 @@ "license": "MIT" }, "node_modules/rollup": { - "version": "4.60.4", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.60.4.tgz", - "integrity": "sha512-WHeFSbZYsPu3+bLoNRUuAO+wavNlocOPf3wSHTP7hcFKVnJeWsYlCDbr3mTS14FCizf9ccIxXA8sGL8zKeQN3g==", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.62.2.tgz", + "integrity": "sha512-RFnrW4lhXA3s3eqHDZvN654g8OTjzRfqpIRJYczCGB6HzphckVAi/Qh4tbPUbRuDi7s1Llv8g/NspLkttY3gTA==", "license": "MIT", "dependencies": { - "@types/estree": "1.0.8" + "@types/estree": "1.0.9" }, "bin": { "rollup": "dist/bin/rollup" @@ -7846,40 +8324,34 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.60.4", - "@rollup/rollup-android-arm64": "4.60.4", - "@rollup/rollup-darwin-arm64": "4.60.4", - "@rollup/rollup-darwin-x64": "4.60.4", - "@rollup/rollup-freebsd-arm64": "4.60.4", - "@rollup/rollup-freebsd-x64": "4.60.4", - "@rollup/rollup-linux-arm-gnueabihf": "4.60.4", - "@rollup/rollup-linux-arm-musleabihf": "4.60.4", - "@rollup/rollup-linux-arm64-gnu": "4.60.4", - "@rollup/rollup-linux-arm64-musl": "4.60.4", - "@rollup/rollup-linux-loong64-gnu": "4.60.4", - "@rollup/rollup-linux-loong64-musl": "4.60.4", - "@rollup/rollup-linux-ppc64-gnu": "4.60.4", - "@rollup/rollup-linux-ppc64-musl": "4.60.4", - "@rollup/rollup-linux-riscv64-gnu": "4.60.4", - "@rollup/rollup-linux-riscv64-musl": "4.60.4", - "@rollup/rollup-linux-s390x-gnu": "4.60.4", - "@rollup/rollup-linux-x64-gnu": "4.60.4", - "@rollup/rollup-linux-x64-musl": "4.60.4", - "@rollup/rollup-openbsd-x64": "4.60.4", - "@rollup/rollup-openharmony-arm64": "4.60.4", - "@rollup/rollup-win32-arm64-msvc": "4.60.4", - "@rollup/rollup-win32-ia32-msvc": "4.60.4", - "@rollup/rollup-win32-x64-gnu": "4.60.4", - "@rollup/rollup-win32-x64-msvc": "4.60.4", + "@rollup/rollup-android-arm-eabi": "4.62.2", + "@rollup/rollup-android-arm64": "4.62.2", + "@rollup/rollup-darwin-arm64": "4.62.2", + "@rollup/rollup-darwin-x64": "4.62.2", + "@rollup/rollup-freebsd-arm64": "4.62.2", + "@rollup/rollup-freebsd-x64": "4.62.2", + "@rollup/rollup-linux-arm-gnueabihf": "4.62.2", + "@rollup/rollup-linux-arm-musleabihf": "4.62.2", + "@rollup/rollup-linux-arm64-gnu": "4.62.2", + "@rollup/rollup-linux-arm64-musl": "4.62.2", + "@rollup/rollup-linux-loong64-gnu": "4.62.2", + "@rollup/rollup-linux-loong64-musl": "4.62.2", + "@rollup/rollup-linux-ppc64-gnu": "4.62.2", + "@rollup/rollup-linux-ppc64-musl": "4.62.2", + "@rollup/rollup-linux-riscv64-gnu": "4.62.2", + "@rollup/rollup-linux-riscv64-musl": "4.62.2", + "@rollup/rollup-linux-s390x-gnu": "4.62.2", + "@rollup/rollup-linux-x64-gnu": "4.62.2", + "@rollup/rollup-linux-x64-musl": "4.62.2", + "@rollup/rollup-openbsd-x64": "4.62.2", + "@rollup/rollup-openharmony-arm64": "4.62.2", + "@rollup/rollup-win32-arm64-msvc": "4.62.2", + "@rollup/rollup-win32-ia32-msvc": "4.62.2", + "@rollup/rollup-win32-x64-gnu": "4.62.2", + "@rollup/rollup-win32-x64-msvc": "4.62.2", "fsevents": "~2.3.2" } }, - "node_modules/rollup/node_modules/@types/estree": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", - "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", - "license": "MIT" - }, "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -8001,9 +8473,9 @@ } }, "node_modules/sharp/node_modules/semver": { - "version": "7.8.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.1.tgz", - "integrity": "sha512-rkVq3IXh+4FDGch+KwzX3aV9W3kO54GyEgpvBzSyctDA6Xtd7RJQV1xmXbeQp5v7+VzLOfVqiutSE6GICgPFvg==", + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", "license": "ISC", "optional": true, "bin": { @@ -8037,17 +8509,17 @@ } }, "node_modules/shiki": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/shiki/-/shiki-4.1.0.tgz", - "integrity": "sha512-l/ABZPUR5v70jI10EzqfMS/I96vjSGv2y0ihUV+WYFzv0EfvW4s54m0Lg8wCrrL+2IkwBzFTuxkZjPf8b2NX9Q==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-4.3.1.tgz", + "integrity": "sha512-oR+qDVi2OjX1tmDpyv+3KviX01KzO6Af+0NNnKnsp9491UEGz2YpxTuJboS/6VhYpTdqzmuJBuiTlrAWWJAssw==", "license": "MIT", "dependencies": { - "@shikijs/core": "4.1.0", - "@shikijs/engine-javascript": "4.1.0", - "@shikijs/engine-oniguruma": "4.1.0", - "@shikijs/langs": "4.1.0", - "@shikijs/themes": "4.1.0", - "@shikijs/types": "4.1.0", + "@shikijs/core": "4.3.1", + "@shikijs/engine-javascript": "4.3.1", + "@shikijs/engine-oniguruma": "4.3.1", + "@shikijs/langs": "4.3.1", + "@shikijs/themes": "4.3.1", + "@shikijs/types": "4.3.1", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" }, @@ -8056,15 +8528,15 @@ } }, "node_modules/side-channel": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", - "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.1.tgz", + "integrity": "sha512-6x6dK6zJdpTzF4sQeNYxwtvBzf6Eg4GtlesS94HOvTudUeyK2WXAaIfmDgsyslYrRBeFIlsi54AYsFGUuhmvrQ==", "dev": true, "license": "MIT", "dependencies": { "es-errors": "^1.3.0", - "object-inspect": "^1.13.3", - "side-channel-list": "^1.0.0", + "object-inspect": "^1.13.4", + "side-channel-list": "^1.0.1", "side-channel-map": "^1.0.1", "side-channel-weakmap": "^1.0.2" }, @@ -8175,9 +8647,9 @@ } }, "node_modules/smol-toml": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/smol-toml/-/smol-toml-1.6.1.tgz", - "integrity": "sha512-dWUG8F5sIIARXih1DTaQAX4SsiTXhInKf1buxdY9DIg4ZYPZK5nGM1VRIYmEbDbsHt7USo99xSLFu5Q1IqTmsg==", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/smol-toml/-/smol-toml-1.7.0.tgz", + "integrity": "sha512-aqVvWoyO21L23mb+drl4RmMXbf6N7FdHjAhTRA9ZBL7apWBgfWC16KjrASI+1p9GAroljyMHj6fK67i0UiTNvQ==", "license": "BSD-3-Clause", "engines": { "node": ">= 18" @@ -8452,9 +8924,9 @@ } }, "node_modules/systeminformation": { - "version": "5.31.6", - "resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-5.31.6.tgz", - "integrity": "sha512-Uv2b2uGGM6ns+26czgW2cYRabYdnswM0ddSOOlryHOaelzsmDSet1iM/NT7VOYxW8x/BW+HkY+b1Ve2pLTSGSA==", + "version": "5.31.13", + "resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-5.31.13.tgz", + "integrity": "sha512-iUJXJoKzm4vtLSeT3nwe2s9QjoJAxHg7wYJ0KaQ54Xy2u9jsTq0ULWQQ0+T72FXjX2XnGqubazNx9lUfng7ELw==", "dev": true, "license": "MIT", "os": [ @@ -8559,27 +9031,27 @@ "license": "MIT" }, "node_modules/tinyclip": { - "version": "0.1.12", - "resolved": "https://registry.npmjs.org/tinyclip/-/tinyclip-0.1.12.tgz", - "integrity": "sha512-Ae3OVUqifDw0wBriIBS7yVaW44Dp6eSHQcyq4Igc7eN2TJH/2YsicswaW+J/OuMvhpDPOKEgpAZCjkb4hpoyeA==", + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/tinyclip/-/tinyclip-0.1.15.tgz", + "integrity": "sha512-uo33abH+Ays0xYaDysoBt494Hb3hsEczMpcC0MwFl773pazORx4fmvKhclhR1wonUbB6vvpRsvVMwnhfqeMc+A==", "license": "MIT", "engines": { "node": "^16.14.0 || >= 17.3.0" } }, "node_modules/tinyexec": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.2.2.tgz", - "integrity": "sha512-M/Q0B2cp4K7kynaT/vnED1j8TlLY+Pp7C6Wl2bl/7u/F0mUVwdyOpwomQb8JpYLitHUssAJRmLZdMCGsrx7i+g==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.2.4.tgz", + "integrity": "sha512-SHf/r48b7vOrjve9PxJo3MN5v5yuyjHvdUcrQffT3WXMUfnGmHDVbC4k3sHJaJTgZCwpUplIaAo5ANtMyp3YHg==", "license": "MIT", "engines": { "node": ">=18" } }, "node_modules/tinyglobby": { - "version": "0.2.16", - "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.16.tgz", - "integrity": "sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==", + "version": "0.2.17", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz", + "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==", "license": "MIT", "dependencies": { "fdir": "^6.5.0", @@ -8759,12 +9231,11 @@ "license": "MIT" }, "node_modules/undici-types": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.24.6.tgz", - "integrity": "sha512-WRNW+sJgj5OBN4/0JpHFqtqzhpbnV0GuB+OozA9gCL7a993SmU+1JBZCzLNxYsbMfIeDL+lTsphD5jN5N+n0zg==", + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-8.3.0.tgz", + "integrity": "sha512-j375ScV60dom+YkPFIfTLcOiPxkN/buHz5GobjLhixFuANaNs3C9l4GmrWqejgXWJ7BbJcFYpTEUkS1Ge8bpZQ==", "dev": true, - "license": "MIT", - "optional": true + "license": "MIT" }, "node_modules/unified": { "version": "11.0.5", @@ -8810,7 +9281,7 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/unist-util-is": { + "node_modules/unist-util-find-after/node_modules/unist-util-is": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.1.tgz", "integrity": "sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==", @@ -8823,6 +9294,13 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/unist-util-is": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-3.0.0.tgz", + "integrity": "sha512-sVZZX3+kspVNmLWBPAB6r+7D9ZgAFPNWm66f7YNb420RlQSbn+n8rG8dGZSkrER7ZIXGQYNm5pqC3v3HopH24A==", + "dev": true, + "license": "MIT" + }, "node_modules/unist-util-modify-children": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/unist-util-modify-children/-/unist-util-modify-children-4.0.0.tgz", @@ -8864,10 +9342,10 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/unist-util-stringify-position": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", - "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", + "node_modules/unist-util-remove-position/node_modules/unist-util-is": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.1.tgz", + "integrity": "sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==", "license": "MIT", "dependencies": { "@types/unist": "^3.0.0" @@ -8877,7 +9355,7 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/unist-util-visit": { + "node_modules/unist-util-remove-position/node_modules/unist-util-visit": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.1.0.tgz", "integrity": "sha512-m+vIdyeCOpdr/QeQCu2EzxX/ohgS8KbnPDgFni4dQsfSCtpz8UqDyY5GjRru8PDKuYn7Fq19j1CQ+nJSsGKOzg==", @@ -8892,6 +9370,43 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/unist-util-remove-position/node_modules/unist-util-visit-parents": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.2.tgz", + "integrity": "sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-stringify-position": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", + "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-1.4.1.tgz", + "integrity": "sha512-AvGNk7Bb//EmJZyhtRUnNMEpId/AZ5Ph/KUpTI09WHQuDZHKovQ1oEv3mfmKpWKtoMzyMC4GLBm1Zy5k12fjIw==", + "dev": true, + "license": "MIT", + "dependencies": { + "unist-util-visit-parents": "^2.0.0" + } + }, "node_modules/unist-util-visit-children": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/unist-util-visit-children/-/unist-util-visit-children-3.0.0.tgz", @@ -8906,17 +9421,13 @@ } }, "node_modules/unist-util-visit-parents": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.2.tgz", - "integrity": "sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-2.1.2.tgz", + "integrity": "sha512-DyN5vD4NE3aSeB+PXYNKxzGsfocxp6asDc2XXE3b0ekO2BaRUpBicbbUygfSvYfUz1IkmjFR1YF7dPklraMZ2g==", + "dev": true, "license": "MIT", "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-is": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "unist-util-is": "^3.0.0" } }, "node_modules/universalify": { @@ -9041,9 +9552,9 @@ } }, "node_modules/unstorage/node_modules/lru-cache": { - "version": "11.5.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.5.0.tgz", - "integrity": "sha512-5YgH9UJd7wVb9hIouI2adWpgqrrICkt070Dnj8EUY1+B4B2P9eRLPAkAAo6NICA7CEhOIeBHl46u9zSNpNu7zA==", + "version": "11.5.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.5.1.tgz", + "integrity": "sha512-RPimw/7aMdv2oqRrxKwvZXcPfwBrn/JZ2xYcY9Hus/6LaS3VOAKVWKWgNLCFSiOm1ESXinjsDlidVU7JlnCN2A==", "license": "BlueOak-1.0.0", "engines": { "node": "20 || >=22" @@ -9180,12 +9691,12 @@ } }, "node_modules/vite": { - "version": "7.3.3", - "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.3.tgz", - "integrity": "sha512-/4XH147Ui7OGTjg3HbdWe5arnZQSbfuRzdr9Ec7TQi5I7R+ir0Rlc9GIvD4v0XZurELqA035KVXJXpR61xhiTA==", + "version": "7.3.6", + "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.6.tgz", + "integrity": "sha512-4XP60spRGjSZFf1qYH+dJIkK2znL3zQfl9KkOV9MkkRR/3Dls0dxaBsQPTloEc5BLXWPL9vsOxopxyKoMmDueg==", "license": "MIT", "dependencies": { - "esbuild": "^0.27.0", + "esbuild": "^0.27.0 || ^0.28.0", "fdir": "^6.5.0", "picomatch": "^4.0.3", "postcss": "^8.5.6", @@ -9407,14 +9918,16 @@ } }, "node_modules/yauzl": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", - "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-3.4.0.tgz", + "integrity": "sha512-jIH9yLR9wqr0wOS0TpBvo/g/2UgZH5qePVbjgRliiF0BYvOZyaBknKsF+x9Iht0O6sqgnB93rCICdOZFecJuDw==", "dev": true, "license": "MIT", "dependencies": { - "buffer-crc32": "~0.2.3", - "fd-slicer": "~1.1.0" + "pend": "~1.2.0" + }, + "engines": { + "node": ">=12" } }, "node_modules/yocto-queue": { diff --git a/package.json b/package.json index b110b01..fac24fc 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,9 @@ "compile": "tsc --noEmit" }, "devDependencies": { + "@types/node": "^26.1.0", "cypress": "^15.15.0", + "remark-heading-id": "^1.0.1", "typescript": "^5.0.0" }, "overrides": { diff --git a/scripts/generate-api-v2.mjs b/scripts/generate-api-v2.mjs new file mode 100644 index 0000000..4462563 --- /dev/null +++ b/scripts/generate-api-v2.mjs @@ -0,0 +1,443 @@ +#!/usr/bin/env node +/** + * Generates per-tag Markdown pages for the DoltHub v2 API from the OpenAPI spec. + * + * Usage: + * node scripts/generate-api-v2.mjs + * + * Output: site/dolt/src/content/products/dolthub/api/v2/ + * database.md — all Database-tagged endpoints + * user.md — User-tagged endpoints + * operations.md — Operations-tagged endpoints + * models.md — all component schemas + * + * authentication.md and README.md are hand-written; this script does not touch them. + */ + +import { readFileSync, writeFileSync, mkdirSync, existsSync } from "fs"; +import { join, dirname } from "path"; +import { fileURLToPath } from "url"; +import yaml from "yaml"; + +const __dirname = dirname(fileURLToPath(import.meta.url)); +const SPEC_PATH = join(__dirname, "../specs/dolthub-v2.yaml"); +const OUT_DIR = join( + __dirname, + "../site/dolt/src/content/products/dolthub/api/v2" +); + +const spec = yaml.parse(readFileSync(SPEC_PATH, "utf-8")); + +// --------------------------------------------------------------------------- +// $ref resolution (with cycle guard) +// --------------------------------------------------------------------------- + +function resolveRef(ref) { + const parts = ref.replace(/^#\//, "").split("/"); + let obj = spec; + for (const p of parts) obj = obj[p]; + return obj; +} + +function deref(obj, depth = 0) { + if (depth > 8) return obj; // cycle guard + if (typeof obj !== "object" || obj === null) return obj; + if (Array.isArray(obj)) return obj.map((x) => deref(x, depth + 1)); + if ("$ref" in obj) return deref(resolveRef(obj.$ref), depth + 1); + return Object.fromEntries( + Object.entries(obj).map(([k, v]) => [k, deref(v, depth + 1)]) + ); +} + +function refName(refStr) { + return refStr?.split("/").pop(); +} + +// --------------------------------------------------------------------------- +// Formatting helpers +// --------------------------------------------------------------------------- + +const METHOD_LABELS = { + get: "GET", + post: "POST", + put: "PUT", + patch: "PATCH", + delete: "DELETE", +}; + +function escapeMarkdown(str = "") { + return str.replace(/\|/g, "\\|").replace(/\n+/g, " ").trim(); +} + +function methodBadge(method) { + const colors = { + get: "009485", + post: "6DB0FC", + patch: "FFCA28", + put: "FFA726", + delete: "EF5350", + }; + const color = colors[method] ?? "888888"; + const label = METHOD_LABELS[method] ?? method.toUpperCase(); + return `![${label}](https://img.shields.io/badge/${label}-${color}?style=flat-square)`; +} + +function curlExample(method, path, operation) { + const lines = [ + `curl -X ${METHOD_LABELS[method] ?? method.toUpperCase()} 'https://www.dolthub.com${path}'`, + ` -H 'Authorization: Bearer YOUR_TOKEN'`, + ]; + if (method !== "get" && method !== "delete") { + lines.push(` -H 'Content-Type: application/json'`); + const reqBody = operation.requestBody?.content?.["application/json"]?.schema; + if (reqBody) { + const resolved = deref(reqBody); + const required = resolved.required ?? []; + const props = resolved.properties ?? {}; + const example = Object.fromEntries( + Object.entries(props) + .filter(([k]) => required.includes(k)) + .slice(0, 4) + .map(([k, v]) => { + const t = v.type ?? (v.enum ? "enum" : "object"); + const ex = + v.examples?.[0] ?? + v.example ?? + (t === "string" ? `"example_${k}"` : t === "boolean" ? false : 0); + return [k, ex]; + }) + ); + if (Object.keys(example).length > 0) { + lines.push(` -d '${JSON.stringify(example)}'`); + } + } + } + return lines.join(" \\\n"); +} + +function parametersSection(params) { + if (!params?.length) return ""; + const rows = params + .map((p) => { + const resolved = deref(p); + const location = resolved.in ?? ""; + const name = resolved.name ?? ""; + const required = resolved.required ? "yes" : "no"; + const type = resolved.schema?.type ?? ""; + const desc = escapeMarkdown(resolved.description ?? ""); + return `| \`${name}\` | ${location} | ${type} | ${required} | ${desc} |`; + }) + .join("\n"); + return `\n**Parameters**\n\n| Name | In | Type | Required | Description |\n|------|----|------|----------|-------------|\n${rows}\n`; +} + +function requestBodySection(requestBody) { + if (!requestBody) return ""; + const schema = requestBody.content?.["application/json"]?.schema; + if (!schema) return ""; + const resolved = deref(schema); + const required = resolved.required ?? []; + const props = resolved.properties ?? {}; + if (!Object.keys(props).length) return ""; + const rows = Object.entries(props) + .map(([k, v]) => { + const req = required.includes(k) ? "yes" : "no"; + const type = v.type ?? (v.$ref ? refName(v.$ref) : "object"); + const desc = escapeMarkdown(v.description ?? ""); + return `| \`${k}\` | ${type} | ${req} | ${desc} |`; + }) + .join("\n"); + return `\n**Request body**\n\n| Field | Type | Required | Description |\n|-------|------|----------|-------------|\n${rows}\n`; +} + +function responseSchemaName(schema) { + if (!schema) return ""; + if (schema.$ref) return refName(schema.$ref); + // Common pattern: allOf: [Envelope, { properties: { data: $ref Schema } }] + if (schema.allOf) { + for (const s of schema.allOf) { + if (s.properties?.data?.$ref) return refName(s.properties.data.$ref); + // List responses: data.items.$ref + if (s.properties?.data?.items?.$ref) + return refName(s.properties.data.items.$ref) + "[]"; + } + } + return ""; +} + +function successExampleBlock(rawResponses) { + if (!rawResponses) return ""; + const successCode = Object.keys(rawResponses).find((c) => /^2/.test(c)); + if (!successCode) return ""; + + const rawResp = rawResponses[successCode]; + const resp = rawResp.$ref ? resolveRef(rawResp.$ref) : rawResp; + const schema = resp.content?.["application/json"]?.schema; + if (!schema?.allOf) return ""; + + let dataExample = null; + let isList = false; + + for (const s of schema.allOf) { + if (s.properties?.data?.$ref) { + const name = refName(s.properties.data.$ref); + dataExample = spec.components?.schemas?.[name]?.examples?.[0] ?? null; + break; + } + if (s.properties?.data?.type === "array" && s.properties?.data?.items?.$ref) { + const name = refName(s.properties.data.items.$ref); + dataExample = spec.components?.schemas?.[name]?.examples?.[0] ?? null; + isList = true; + break; + } + } + + if (!dataExample) return ""; + + const body = isList + ? { data: [dataExample], meta: { next_page_token: "eyJvZmZzZXQiOjI1fQ" } } + : { data: dataExample }; + + return `\n**Example response \`${successCode}\`**\n\n\`\`\`json\n${JSON.stringify(body, null, 2)}\n\`\`\`\n`; +} + +function responsesSection(rawResponses) { + if (!rawResponses) return ""; + const rows = Object.entries(rawResponses) + .map(([code, rawResp]) => { + // Resolve top-level $ref (e.g. $ref: "#/components/responses/Unauthorized") + const resp = rawResp.$ref ? resolveRef(rawResp.$ref) : rawResp; + const desc = escapeMarkdown(resp.description ?? ""); + const schema = resp.content?.["application/json"]?.schema; + const name = responseSchemaName(schema); + const schemaLink = name + ? `[\`${name}\`](models#model-${name.replace("[]", "").toLowerCase()})` + : ""; + return `| \`${code}\` | ${desc} | ${schemaLink} |`; + }) + .join("\n"); + return `\n**Responses**\n\n| Status | Description | Schema |\n|--------|-------------|--------|\n${rows}\n`; +} + +// --------------------------------------------------------------------------- +// Derive sub-resource label from path (for grouping within the Database page) +// --------------------------------------------------------------------------- + +function subResource(path) { + // After /databases/{owner}/{database}/... + const m = path.match( + /^\/api\/v2\/databases\/\{[^}]+\}\/\{[^}]+\}\/([^/]+)/ + ); + if (m) { + switch (m[1]) { + case "branches": return "Branches"; + case "tags": return "Tags"; + case "forks": return "Forks"; + case "releases": return "Releases"; + case "sql": return "SQL"; + case "pulls": return "Pull Requests"; + case "imports": return "Imports"; + default: return m[1]; + } + } + if (path.startsWith("/api/v2/databases")) return "Databases"; + return "Other"; +} + +// --------------------------------------------------------------------------- +// Build per-endpoint Markdown block +// --------------------------------------------------------------------------- + +function endpointBlock(method, path, operation, headingLevel = "###") { + const anchor = `{#${operation.operationId}}`; + const title = operation.summary + ? operation.summary.replace(/\.$/, "") + : `${METHOD_LABELS[method]} ${path}`; + const heading = `${headingLevel} ${title} ${anchor}\n`; + const methodPath = `\`${METHOD_LABELS[method]} ${path}\`\n\n`; + const description = + operation.description && + operation.description.trim() !== (operation.summary ?? "").trim() + ? `${operation.description.trim()}\n\n` + : ""; + const params = parametersSection(operation.parameters); + const body = requestBodySection(deref(operation.requestBody ?? {})); + const responses = responsesSection(operation.responses); + const successExample = successExampleBlock(operation.responses); + const curl = `\n**Example request**\n\n\`\`\`sh\n${curlExample(method, path, operation)}\n\`\`\`\n`; + return [heading, methodPath, description, params, body, curl, responses, successExample] + .filter(Boolean) + .join(""); +} + +// --------------------------------------------------------------------------- +// Collect operations by tag +// --------------------------------------------------------------------------- + +const byTag = {}; // tag → [{ method, path, operation }] + +for (const [path, pathItem] of Object.entries(spec.paths ?? {})) { + for (const method of [ + "get", + "post", + "put", + "patch", + "delete", + "head", + "options", + ]) { + const op = pathItem[method]; + if (!op) continue; + for (const tag of op.tags ?? ["Untagged"]) { + if (!byTag[tag]) byTag[tag] = []; + byTag[tag].push({ method, path, operation: op }); + } + } +} + +// --------------------------------------------------------------------------- +// Tag-level page generators +// --------------------------------------------------------------------------- + +function generateTagPage(tag, items, frontmatter) { + const tagInfo = spec.tags?.find((t) => t.name === tag) ?? {}; + const intro = tagInfo.description ? `${tagInfo.description}\n\n` : ""; + + // For Database tag, group by sub-resource + if (tag === "Database") { + const groups = {}; + for (const item of items) { + const g = subResource(item.path); + if (!groups[g]) groups[g] = []; + groups[g].push(item); + } + const order = [ + "Databases", + "SQL", + "Branches", + "Tags", + "Forks", + "Releases", + "Pull Requests", + "Imports", + ]; + const sorted = [ + ...order.filter((g) => groups[g]), + ...Object.keys(groups).filter((g) => !order.includes(g)), + ]; + const sections = sorted + .map((g) => { + const endpoints = groups[g] + .map((item) => + endpointBlock(item.method, item.path, item.operation, "###") + ) + .join("\n---\n\n"); + return `## ${g}\n\n${endpoints}`; + }) + .join("\n\n"); + return `${frontmatter}\n\n${intro}${sections}\n`; + } + + // Other tags: flat list + const content = items + .map((item) => + endpointBlock(item.method, item.path, item.operation, "##") + ) + .join("\n---\n\n"); + return `${frontmatter}\n\n${intro}${content}\n`; +} + +// --------------------------------------------------------------------------- +// Models page +// --------------------------------------------------------------------------- + +function schemaBlock(name, schema) { + const anchor = `{#model-${name.toLowerCase()}}`; + const heading = `## ${name} ${anchor}\n`; + const desc = schema.description ? `${schema.description.trim()}\n\n` : ""; + + if (schema.enum) { + const descs = schema["x-enum-descriptions"] ?? []; + const hasDescs = descs.some(Boolean); + const values = schema.enum + .map((v, i) => + hasDescs + ? `| \`${v}\` | ${escapeMarkdown(descs[i] ?? "")} |` + : `| \`${v}\` |` + ) + .join("\n"); + const header = hasDescs + ? `| Value | Description |\n|-------|-------------|` + : `| Value |\n|-------|`; + return `${heading}${desc}**Enum values**\n\n${header}\n${values}\n`; + } + + const props = schema.properties ?? schema.allOf?.find((s) => s.properties)?.properties; + if (!props || !Object.keys(props).length) { + const type = schema.type ?? (schema.allOf ? "object" : ""); + return `${heading}${desc}${type ? `_Type: \`${type}\`_\n` : ""}\n`; + } + + const required = schema.required ?? schema.allOf?.find((s) => s.required)?.required ?? []; + const rows = Object.entries(props) + .map(([k, v]) => { + const req = required.includes(k) ? "yes" : "no"; + const type = v.type ?? (v.$ref ? refName(v.$ref) : v.allOf ? "object" : "object"); + const d = escapeMarkdown(v.description ?? ""); + return `| \`${k}\` | \`${type}\` | ${req} | ${d} |`; + }) + .join("\n"); + + return `${heading}${desc}| Field | Type | Required | Description |\n|-------|------|----------|-------------|\n${rows}\n`; +} + +function generateModelsPage() { + const fm = `---\ntitle: "Models"\ndescription: Request and response schemas for the DoltHub v2 API.\n---\n\n# Models`; + const schemas = Object.entries(spec.components?.schemas ?? {}); + const blocks = schemas + .map(([name, schema]) => schemaBlock(name, deref(schema))) + .join("\n---\n\n"); + return `${fm}\n\nShared request and response types used across the v2 API. See the [error model](#model-problem) for how failures are reported.\n\n${blocks}\n`; +} + +// --------------------------------------------------------------------------- +// Write output files +// --------------------------------------------------------------------------- + +mkdirSync(OUT_DIR, { recursive: true }); + +const tagPages = [ + { + tag: "User", + file: "user.md", + frontmatter: + '---\ntitle: "User"\ndescription: The authenticated user resource in the DoltHub v2 API.\n---\n\n# User', + }, + { + tag: "Database", + file: "database.md", + frontmatter: + '---\ntitle: "Database"\ndescription: DoltHub databases, branches, tags, forks, releases, SQL, pull requests, and imports.\n---\n\n# Database', + }, + { + tag: "Operations", + file: "operations.md", + frontmatter: + '---\ntitle: "Operations"\ndescription: Long-running async operations in the DoltHub v2 API.\n---\n\n# Operations', + }, +]; + +for (const { tag, file, frontmatter } of tagPages) { + const items = byTag[tag] ?? []; + if (!items.length) { + console.warn(`Warning: no endpoints found for tag "${tag}"`); + continue; + } + const content = generateTagPage(tag, items, frontmatter); + writeFileSync(join(OUT_DIR, file), content); + console.log(`Wrote ${file} (${items.length} endpoints)`); +} + +const modelsContent = generateModelsPage(); +writeFileSync(join(OUT_DIR, "models.md"), modelsContent); +console.log(`Wrote models.md (${Object.keys(spec.components?.schemas ?? {}).length} schemas)`); diff --git a/site/dolt/package.json b/site/dolt/package.json index 8633057..3c25879 100644 --- a/site/dolt/package.json +++ b/site/dolt/package.json @@ -6,7 +6,8 @@ "scripts": { "dev": "astro dev --port 4321", "build": "node ../../scripts/check-content-frontmatter.mjs src/content && astro build && cp _redirects dist/_redirects && cp _headers dist/_headers && cp dist/docs/404.html dist/404.html && cp dist/docs/llms.txt dist/llms.txt && npx pagefind --site dist/docs", - "preview": "astro preview --port 4321" + "preview": "astro preview --port 4321", + "generate-api-v2": "node ../../scripts/generate-api-v2.mjs" }, "dependencies": { "@astrojs/react": "^5.0.1", diff --git a/site/dolt/src/content/products/dolthub/api/README.md b/site/dolt/src/content/products/dolthub/api/README.md index 231328e..f027093 100644 --- a/site/dolt/src/content/products/dolthub/api/README.md +++ b/site/dolt/src/content/products/dolthub/api/README.md @@ -5,10 +5,18 @@ description: Programmatic access to databases hosted on DoltHub. # DoltHub/DoltLab API -DoltHub and DoltLab expose three independent HTTP APIs against your hosted databases. Pick the one that fits the task: +DoltHub and DoltLab expose HTTP APIs for programmatic access to your hosted databases. -- **[v1alpha1 API](/products/dolthub/api/v1alpha1)** — the resource-oriented API for managing databases, branches, pull requests, releases, tags, file uploads, and async jobs. SQL read and write endpoints live here too. -- **[CSV API](/products/dolthub/api/csv)** — bulk export and import of table data as CSV. Independent of the v1alpha1 surface. -- **[Webhooks](/products/dolthub/api/hooks)** — receive HTTP callbacks when events happen on your database (pushes, pull-request activity, and so on). Independent of the v1alpha1 surface. +## REST API + +The REST API is available in two versions. **New integrations should use v2.** + +- **[v2 API](/products/dolthub/api/v2)** — the current generation. An explicit, versioned, OpenAPI-defined contract with consistent HTTP semantics, a single [RFC 9457](https://www.rfc-editor.org/rfc/rfc9457) error model, a uniform response envelope, and a standardized async-operations protocol. Start here. +- **[v1alpha1 API](/products/dolthub/api/v1alpha1)** — the original API. Still supported, but new endpoints are being added to v2 only. See the [migration guide](/products/dolthub/api/v2/migration) if you are moving an existing integration. + +## Other API surfaces + +- **[CSV API](/products/dolthub/api/csv)** — bulk export and import of table data as CSV. +- **[Webhooks](/products/dolthub/api/hooks)** — receive HTTP callbacks when events happen on your database (pushes, pull-request activity, and so on). > **Note:** please send requests to `https://www.dolthub.com`, not `https://dolthub.com`. diff --git a/site/dolt/src/content/products/dolthub/api/v2/README.md b/site/dolt/src/content/products/dolthub/api/v2/README.md new file mode 100644 index 0000000..6c58579 --- /dev/null +++ b/site/dolt/src/content/products/dolthub/api/v2/README.md @@ -0,0 +1,59 @@ +--- +title: "DoltHub API v2" +description: The DoltHub v2 API — an explicit, versioned, OpenAPI-defined contract for databases, branches, SQL, and more. +--- + +# DoltHub API v2 + +_API version: v2_ + +The v2 API is the current generation of the DoltHub HTTP surface. Every endpoint lives under `https://www.dolthub.com/api/v2/`. + +> **Note:** please send requests to `https://www.dolthub.com`, not `https://dolthub.com`. + +Compared to `v1alpha1`, v2 commits to: +- Consistent HTTP semantics (correct status codes, idempotent GETs, etc.) +- A single error model ([RFC 9457](https://www.rfc-editor.org/rfc/rfc9457) problem details) +- A uniform success [Envelope](models#model-envelope) wrapping every response +- A standardized [long-running operations](operations) protocol for async mutations + +## All endpoints + +### User + +| Method | Path | What it does | +|--------|------|--------------| +| **GET** | `/api/v2/user` | [Get the authenticated user](user#getCurrentUser) | + +### Database + +| Method | Path | What it does | +|--------|------|--------------| +| **POST** | `/api/v2/databases` | [Create a database](database#createDatabase) | +| **GET** | `/api/v2/databases/{owner}/{database}` | [Get a database](database#getDatabase) | +| **GET** | `/api/v2/databases/{owner}/{database}/branches` | [List branches](database#listBranches) | +| **POST** | `/api/v2/databases/{owner}/{database}/branches` | [Create a branch](database#createBranch) | +| **GET** | `/api/v2/databases/{owner}/{database}/tags` | [List tags](database#listTags) | +| **POST** | `/api/v2/databases/{owner}/{database}/tags` | [Create a tag](database#createTag) | +| **GET** | `/api/v2/databases/{owner}/{database}/forks` | [List forks](database#listForks) | +| **POST** | `/api/v2/databases/{owner}/{database}/forks` | [Fork a database](database#createFork) | +| **GET** | `/api/v2/databases/{owner}/{database}/releases` | [List releases](database#listReleases) | +| **POST** | `/api/v2/databases/{owner}/{database}/releases` | [Create a release](database#createRelease) | +| **GET** | `/api/v2/databases/{owner}/{database}/sql` | [Run a read-only SQL query](database#runSqlReadQuery) | +| **POST** | `/api/v2/databases/{owner}/{database}/sql` | [Run a read-only SQL query (large-query variant)](database#runSqlReadQueryPost) | +| **GET** | `/api/v2/databases/{owner}/{database}/pulls` | [List pull requests](database#listPulls) | +| **POST** | `/api/v2/databases/{owner}/{database}/pulls` | [Create a pull request](database#createPull) | +| **GET** | `/api/v2/databases/{owner}/{database}/pulls/{pull_number}` | [Get a pull request](database#getPull) | +| **PATCH** | `/api/v2/databases/{owner}/{database}/pulls/{pull_number}` | [Update a pull request](database#updatePull) | +| **GET** | `/api/v2/databases/{owner}/{database}/pulls/{pull_number}/comments` | [List pull request comments](database#listPullComments) | +| **POST** | `/api/v2/databases/{owner}/{database}/pulls/{pull_number}/comments` | [Add a pull request comment](database#createPullComment) | +| **POST** | `/api/v2/databases/{owner}/{database}/pulls/{pull_number}/merge` | [Merge a pull request](database#mergePull) | +| **POST** | `/api/v2/databases/{owner}/{database}/imports/uploads` | [Initialize a multipart upload](database#createImportUpload) | +| **POST** | `/api/v2/databases/{owner}/{database}/imports` | [Create an import operation](database#createImport) | + +### Operations + +| Method | Path | What it does | +|--------|------|--------------| +| **GET** | `/api/v2/databases/{owner}/{database}/operations` | [List a database's async operations](operations#listOperations) | +| **GET** | `/api/v2/operations/{operation_id}` | [Get an async operation](operations#getOperation) | diff --git a/site/dolt/src/content/products/dolthub/api/v2/authentication.md b/site/dolt/src/content/products/dolthub/api/v2/authentication.md new file mode 100644 index 0000000..ecec084 --- /dev/null +++ b/site/dolt/src/content/products/dolthub/api/v2/authentication.md @@ -0,0 +1,40 @@ +--- +title: "Authentication" +description: How to authenticate requests to the DoltHub v2 API. +--- + +# Authentication + +_API version: v2_ + +The v2 API supports two credential types. Both use the `Authorization: Bearer ` header. + +## Personal access tokens + +Create a token at [dolthub.com/settings/tokens](https://www.dolthub.com/settings/tokens). Copy it immediately — it is shown only once. + +Include the token on every request that requires authentication: + +```sh +curl https://www.dolthub.com/api/v2/user \ + -H 'Authorization: Bearer dh_YOUR_TOKEN_HERE' +``` + +Tokens have no built-in expiry but can be revoked from the settings page at any time. + +## OAuth 2.0 + +The v2 API also accepts OAuth 2.0 access tokens using the authorization-code flow: + +- **Authorization URL:** `https://www.dolthub.com/oauth/authorize` +- **Token URL:** `https://www.dolthub.com/oauth/token` + +Scope definitions are listed in the spec. If you are building a third-party integration that acts on behalf of a user, OAuth is the recommended approach. + +## Which endpoints require authentication + +Most write operations and all operations on private databases require authentication. Public databases can be read (SQL queries, list branches, etc.) without a token. + +Endpoints that require authentication will return `401 Unauthorized` if no valid credential is supplied, and `403 Forbidden` if the credential is valid but lacks permission. + +See [Models → Problem](models#model-problem) for the error response format. diff --git a/site/dolt/src/content/products/dolthub/api/v2/database.md b/site/dolt/src/content/products/dolthub/api/v2/database.md new file mode 100644 index 0000000..5503fb3 --- /dev/null +++ b/site/dolt/src/content/products/dolthub/api/v2/database.md @@ -0,0 +1,1218 @@ +--- +title: "Database" +description: DoltHub databases, branches, tags, forks, releases, SQL, pull requests, and imports. +--- + +# Database + +DoltHub databases and their metadata. + +## Databases + +### Create a database {#createDatabase} +`POST /api/v2/databases` + +Creates a database under the named owner (a user or organization). The caller's credentials must allow creating under that owner — creating for yourself works as long as you authenticate; creating for an organization requires membership with the appropriate role. Returns the new `Database` resource on `201`. If a database with the same `{owner, name}` already exists, the response is `409 Conflict`. + + +**Request body** + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `owner` | string | yes | The user or organization that will own the database. | +| `name` | string | yes | The database name. Must be unique within the owner and conform to DoltHub's naming rules (letters, digits, `-`, `_`; cannot start or end with `-`). | +| `description` | string | no | Optional human-readable description. | +| `visibility` | string | yes | Whether the database is publicly readable. Defaults are *not* applied — clients must declare the intended visibility on create. | + +**Example request** + +```sh +curl -X POST 'https://www.dolthub.com/api/v2/databases' \ + -H 'Authorization: Bearer YOUR_TOKEN' \ + -H 'Content-Type: application/json' \ + -d '{"owner":"dolthub","name":"us-jails","visibility":"public"}' +``` + +**Responses** + +| Status | Description | Schema | +|--------|-------------|--------| +| `201` | The newly-created database. | [`Database`](models#model-database) | +| `400` | The request was malformed or failed input validation. | [`Problem`](models#model-problem) | +| `401` | Authentication credentials were missing or invalid. | [`Problem`](models#model-problem) | +| `403` | Authenticated, but not permitted to perform this action. | [`Problem`](models#model-problem) | +| `405` | The HTTP method is not supported for this resource. | [`Problem`](models#model-problem) | +| `409` | The request conflicts with the current state of the resource (e.g. it already exists). | [`Problem`](models#model-problem) | +| `500` | An unexpected server error occurred. | [`Problem`](models#model-problem) | + +**Example response `201`** + +```json +{ + "data": { + "owner": "dolthub", + "name": "us-jails", + "description": "Open data about incarceration in the United States.", + "visibility": "public", + "fork_network_count": 3, + "star_count": 42, + "size_bytes": 10485760, + "last_write_at": "2024-01-15T12:34:56Z" + } +} +``` + +--- + +### Get a database {#getDatabase} +`GET /api/v2/databases/{owner}/{database}` + +Returns the metadata for the database `{owner}/{database}`. Public databases are readable without authentication; private databases require a credential with access (and return `404` otherwise, so their existence isn't leaked). + + +**Parameters** + +| Name | In | Type | Required | Description | +|------|----|------|----------|-------------| +| `owner` | path | string | yes | The user or organization that owns the database. | +| `database` | path | string | yes | The database name, unique within the owner. | + +**Example request** + +```sh +curl -X GET 'https://www.dolthub.com/api/v2/databases/{owner}/{database}' \ + -H 'Authorization: Bearer YOUR_TOKEN' +``` + +**Responses** + +| Status | Description | Schema | +|--------|-------------|--------| +| `200` | The database's metadata. | [`Database`](models#model-database) | +| `400` | The request was malformed or failed input validation. | [`Problem`](models#model-problem) | +| `401` | Authentication credentials were missing or invalid. | [`Problem`](models#model-problem) | +| `404` | The requested resource does not exist. | [`Problem`](models#model-problem) | +| `405` | The HTTP method is not supported for this resource. | [`Problem`](models#model-problem) | +| `500` | An unexpected server error occurred. | [`Problem`](models#model-problem) | + +**Example response `200`** + +```json +{ + "data": { + "owner": "dolthub", + "name": "us-jails", + "description": "Open data about incarceration in the United States.", + "visibility": "public", + "fork_network_count": 3, + "star_count": 42, + "size_bytes": 10485760, + "last_write_at": "2024-01-15T12:34:56Z" + } +} +``` + + +## SQL + +### Run a read-only SQL query {#runSqlReadQuery} +`GET /api/v2/databases/{owner}/{database}/sql` + +Executes a read-only SQL query against the database at the given revision and returns the result rows, the column schema, and the query-execution status. Read queries are not paginated — the full row set comes back in one response, bounded by `limit` (default 1000) and the server-enforced row cap. For larger result sets, refine the query (`LIMIT`/`WHERE`/`SELECT` fewer columns) or use the phase-4 async SQL job. +SQL-level errors (syntax errors, missing tables, timeouts, row-limit exceeded) come back as `200` with `status: "error" | "timeout" | "row_limit" | "not_workspace"` and a human-readable `message` — they are query-level conditions, not transport-level failures. HTTP `4xx` / `5xx` are reserved for transport-level problems (auth, the database doesn't exist, malformed request). +Public databases are readable without authentication; private databases require a credential with access (and return `404` otherwise, so their existence isn't leaked). + + +**Parameters** + +| Name | In | Type | Required | Description | +|------|----|------|----------|-------------| +| `owner` | path | string | yes | The user or organization that owns the database. | +| `database` | path | string | yes | The database name, unique within the owner. | +| `ref` | query | string | yes | The branch, tag, or commit hash to query against. A 32-character value using only the characters `0-9a-v` (Dolt's base32 alphabet) is treated as a commit hash; everything else resolves as a branch, tag, or other ref. | +| `q` | query | string | yes | The SQL query to execute. Read-only — use the phase-4 SQL write endpoint for mutations. | +| `limit` | query | string | no | Maximum number of rows to return (default `1000`). The server enforces an upper cap; refine the query or use the async SQL job for larger result sets. | +| `timeout_ms` | query | string | no | Per-query execution timeout in milliseconds (default `30000`, server-enforced cap `60000`). A query that hits the cap returns `status: "timeout"`. | + +**Example request** + +```sh +curl -X GET 'https://www.dolthub.com/api/v2/databases/{owner}/{database}/sql' \ + -H 'Authorization: Bearer YOUR_TOKEN' +``` + +**Responses** + +| Status | Description | Schema | +|--------|-------------|--------| +| `200` | The query result. SQL-level errors live in `status` + `message`. | [`QueryResult`](models#model-queryresult) | +| `400` | The request was malformed or failed input validation. | [`Problem`](models#model-problem) | +| `401` | Authentication credentials were missing or invalid. | [`Problem`](models#model-problem) | +| `404` | The requested resource does not exist. | [`Problem`](models#model-problem) | +| `405` | The HTTP method is not supported for this resource. | [`Problem`](models#model-problem) | +| `500` | An unexpected server error occurred. | [`Problem`](models#model-problem) | + +**Example response `200`** + +```json +{ + "data": { + "columns": [ + { + "name": "state_name", + "type": "VARCHAR(255)", + "is_primary_key": true, + "source_table": "jails" + }, + { + "name": "count", + "type": "BIGINT", + "is_primary_key": false, + "source_table": "" + } + ], + "rows": [ + [ + "California", + "162" + ], + [ + "Texas", + "108" + ], + [ + null, + "0" + ] + ], + "status": "success", + "warnings": [] + } +} +``` + +--- + +### Run a read-only SQL query (large-query variant) {#runSqlReadQueryPost} +`POST /api/v2/databases/{owner}/{database}/sql` + +Identical to `GET /sql` but accepts the query in the request body to avoid the browser/proxy URL-length limit (~4–8 KB) that `?q=` hits for large SQL statements. Use this when the query is too long for a query string; prefer `GET` for short queries (simpler to cache and log). The response shape is identical. + + +**Parameters** + +| Name | In | Type | Required | Description | +|------|----|------|----------|-------------| +| `owner` | path | string | yes | The user or organization that owns the database. | +| `database` | path | string | yes | The database name, unique within the owner. | + +**Request body** + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `ref` | string | yes | The branch, tag, or commit hash to query against. A 32-character value using only the characters `0-9a-v` (Dolt's base32 alphabet) is treated as a commit hash; everything else resolves as a branch, tag, or other ref. | +| `q` | string | yes | The SQL query to execute. Read-only — mutations are rejected. | +| `limit` | integer | no | Maximum number of rows to return (default `1000`). | +| `timeout_ms` | integer | no | Per-query execution timeout in milliseconds (default `30000`, cap `60000`). | + +**Example request** + +```sh +curl -X POST 'https://www.dolthub.com/api/v2/databases/{owner}/{database}/sql' \ + -H 'Authorization: Bearer YOUR_TOKEN' \ + -H 'Content-Type: application/json' \ + -d '{"ref":"main","q":"SELECT name, year FROM jails WHERE state = 'California' LIMIT 10"}' +``` + +**Responses** + +| Status | Description | Schema | +|--------|-------------|--------| +| `200` | The query result. SQL-level errors live in `status` + `message`. | [`QueryResult`](models#model-queryresult) | +| `400` | The request was malformed or failed input validation. | [`Problem`](models#model-problem) | +| `401` | Authentication credentials were missing or invalid. | [`Problem`](models#model-problem) | +| `404` | The requested resource does not exist. | [`Problem`](models#model-problem) | +| `405` | The HTTP method is not supported for this resource. | [`Problem`](models#model-problem) | +| `500` | An unexpected server error occurred. | [`Problem`](models#model-problem) | + +**Example response `200`** + +```json +{ + "data": { + "columns": [ + { + "name": "state_name", + "type": "VARCHAR(255)", + "is_primary_key": true, + "source_table": "jails" + }, + { + "name": "count", + "type": "BIGINT", + "is_primary_key": false, + "source_table": "" + } + ], + "rows": [ + [ + "California", + "162" + ], + [ + "Texas", + "108" + ], + [ + null, + "0" + ] + ], + "status": "success", + "warnings": [] + } +} +``` + + +## Branches + +### List branches {#listBranches} +`GET /api/v2/databases/{owner}/{database}/branches` + +Returns the branches of the database `{owner}/{database}`, ordered by the backend. Cursor-paginated via `page_token` (request) / `meta.next_page_token` (response); when `next_page_token` is absent or empty there are no further pages. Public databases are readable without authentication; private databases require a credential with access (and return `404` otherwise, so their existence isn't leaked). + + +**Parameters** + +| Name | In | Type | Required | Description | +|------|----|------|----------|-------------| +| `owner` | path | string | yes | The user or organization that owns the database. | +| `database` | path | string | yes | The database name, unique within the owner. | +| `page_token` | query | string | no | Opaque cursor returned in a prior response's `meta.next_page_token`. Pass it back to fetch the next page; omit it on the first request. The token format is server-defined — clients must treat it as an opaque string. | + +**Example request** + +```sh +curl -X GET 'https://www.dolthub.com/api/v2/databases/{owner}/{database}/branches' \ + -H 'Authorization: Bearer YOUR_TOKEN' +``` + +**Responses** + +| Status | Description | Schema | +|--------|-------------|--------| +| `200` | The database's branches. | [`Branch[]`](models#model-branch) | +| `400` | The request was malformed or failed input validation. | [`Problem`](models#model-problem) | +| `401` | Authentication credentials were missing or invalid. | [`Problem`](models#model-problem) | +| `404` | The requested resource does not exist. | [`Problem`](models#model-problem) | +| `405` | The HTTP method is not supported for this resource. | [`Problem`](models#model-problem) | +| `500` | An unexpected server error occurred. | [`Problem`](models#model-problem) | + +**Example response `200`** + +```json +{ + "data": [ + { + "name": "main", + "head_commit_sha": "vt1u8gdsovtj0qq2qmd6he7n5o4mq2qm", + "last_updated_at": "2024-01-15T12:34:56Z" + } + ], + "meta": { + "next_page_token": "eyJvZmZzZXQiOjI1fQ" + } +} +``` + +--- + +### Create a branch {#createBranch} +`POST /api/v2/databases/{owner}/{database}/branches` + +Creates a new branch in `{owner}/{database}` pointing at the source revision named by `from`. Authentication required; the caller must have write access. Returns the new `Branch` resource on `201`. A `409 Conflict` comes back if a branch with the same name already exists. + + +**Parameters** + +| Name | In | Type | Required | Description | +|------|----|------|----------|-------------| +| `owner` | path | string | yes | The user or organization that owns the database. | +| `database` | path | string | yes | The database name, unique within the owner. | + +**Request body** + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `name` | string | yes | The new branch's name. | +| `from` | object | yes | | + +**Example request** + +```sh +curl -X POST 'https://www.dolthub.com/api/v2/databases/{owner}/{database}/branches' \ + -H 'Authorization: Bearer YOUR_TOKEN' \ + -H 'Content-Type: application/json' \ + -d '{"name":"feature-x","from":0}' +``` + +**Responses** + +| Status | Description | Schema | +|--------|-------------|--------| +| `201` | The newly-created branch. | [`Branch`](models#model-branch) | +| `400` | The request was malformed or failed input validation. | [`Problem`](models#model-problem) | +| `401` | Authentication credentials were missing or invalid. | [`Problem`](models#model-problem) | +| `403` | Authenticated, but not permitted to perform this action. | [`Problem`](models#model-problem) | +| `404` | The requested resource does not exist. | [`Problem`](models#model-problem) | +| `405` | The HTTP method is not supported for this resource. | [`Problem`](models#model-problem) | +| `409` | The request conflicts with the current state of the resource (e.g. it already exists). | [`Problem`](models#model-problem) | +| `500` | An unexpected server error occurred. | [`Problem`](models#model-problem) | + +**Example response `201`** + +```json +{ + "data": { + "name": "main", + "head_commit_sha": "vt1u8gdsovtj0qq2qmd6he7n5o4mq2qm", + "last_updated_at": "2024-01-15T12:34:56Z" + } +} +``` + + +## Tags + +### List tags {#listTags} +`GET /api/v2/databases/{owner}/{database}/tags` + +Returns the tags of the database `{owner}/{database}`, ordered by the backend. Cursor-paginated via `page_token` (request) / `meta.next_page_token` (response); when `next_page_token` is absent or empty there are no further pages. Public databases are readable without authentication; private databases require a credential with access (and return `404` otherwise, so their existence isn't leaked). + + +**Parameters** + +| Name | In | Type | Required | Description | +|------|----|------|----------|-------------| +| `owner` | path | string | yes | The user or organization that owns the database. | +| `database` | path | string | yes | The database name, unique within the owner. | +| `page_token` | query | string | no | Opaque cursor returned in a prior response's `meta.next_page_token`. Pass it back to fetch the next page; omit it on the first request. The token format is server-defined — clients must treat it as an opaque string. | + +**Example request** + +```sh +curl -X GET 'https://www.dolthub.com/api/v2/databases/{owner}/{database}/tags' \ + -H 'Authorization: Bearer YOUR_TOKEN' +``` + +**Responses** + +| Status | Description | Schema | +|--------|-------------|--------| +| `200` | The database's tags. | [`Tag[]`](models#model-tag) | +| `400` | The request was malformed or failed input validation. | [`Problem`](models#model-problem) | +| `401` | Authentication credentials were missing or invalid. | [`Problem`](models#model-problem) | +| `404` | The requested resource does not exist. | [`Problem`](models#model-problem) | +| `405` | The HTTP method is not supported for this resource. | [`Problem`](models#model-problem) | +| `500` | An unexpected server error occurred. | [`Problem`](models#model-problem) | + +**Example response `200`** + +```json +{ + "data": [ + { + "name": "v1.0.0", + "commit_sha": "vt1u8gdsovtj0qq2qmd6he7n5o4mq2qm", + "message": "First public release.", + "tagged_at": "2024-01-15T12:34:56Z" + } + ], + "meta": { + "next_page_token": "eyJvZmZzZXQiOjI1fQ" + } +} +``` + +--- + +### Create a tag {#createTag} +`POST /api/v2/databases/{owner}/{database}/tags` + +Creates a new tag in `{owner}/{database}` pointing at the source revision named by `from`. The optional `message` makes the tag annotated; omitted yields a lightweight tag. Returns the new `Tag` resource on `201`. Authentication required; the caller must have write access. A `409 Conflict` comes back if a tag with the same name already exists. + + +**Parameters** + +| Name | In | Type | Required | Description | +|------|----|------|----------|-------------| +| `owner` | path | string | yes | The user or organization that owns the database. | +| `database` | path | string | yes | The database name, unique within the owner. | + +**Request body** + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `name` | string | yes | The new tag's name, unique within the database. | +| `from` | object | yes | | +| `message` | string | no | Optional annotation message. Present → annotated tag; absent → lightweight tag. | + +**Example request** + +```sh +curl -X POST 'https://www.dolthub.com/api/v2/databases/{owner}/{database}/tags' \ + -H 'Authorization: Bearer YOUR_TOKEN' \ + -H 'Content-Type: application/json' \ + -d '{"name":"v1.0.0","from":0}' +``` + +**Responses** + +| Status | Description | Schema | +|--------|-------------|--------| +| `201` | The newly-created tag. | [`Tag`](models#model-tag) | +| `400` | The request was malformed or failed input validation. | [`Problem`](models#model-problem) | +| `401` | Authentication credentials were missing or invalid. | [`Problem`](models#model-problem) | +| `403` | Authenticated, but not permitted to perform this action. | [`Problem`](models#model-problem) | +| `404` | The requested resource does not exist. | [`Problem`](models#model-problem) | +| `405` | The HTTP method is not supported for this resource. | [`Problem`](models#model-problem) | +| `409` | The request conflicts with the current state of the resource (e.g. it already exists). | [`Problem`](models#model-problem) | +| `500` | An unexpected server error occurred. | [`Problem`](models#model-problem) | + +**Example response `201`** + +```json +{ + "data": { + "name": "v1.0.0", + "commit_sha": "vt1u8gdsovtj0qq2qmd6he7n5o4mq2qm", + "message": "First public release.", + "tagged_at": "2024-01-15T12:34:56Z" + } +} +``` + + +## Forks + +### List forks {#listForks} +`GET /api/v2/databases/{owner}/{database}/forks` + +Returns the databases that have been directly forked from `{owner}/{database}` — immediate children only. Forks-of-forks are not flattened into the list; use `fork_network_count` on the `Database` resource for the transitive total. Topology context (`parent`, `network_root`, total `fork_network_count`) lives on the `Database` resource. Pagination (`page_token` / `meta.next_page_token`) will be added when the backend supports it; until then the full list is returned in one response. Public databases are readable without authentication; private databases require a credential with access (and return `404` otherwise, so their existence isn't leaked). + + +**Parameters** + +| Name | In | Type | Required | Description | +|------|----|------|----------|-------------| +| `owner` | path | string | yes | The user or organization that owns the database. | +| `database` | path | string | yes | The database name, unique within the owner. | + +**Example request** + +```sh +curl -X GET 'https://www.dolthub.com/api/v2/databases/{owner}/{database}/forks' \ + -H 'Authorization: Bearer YOUR_TOKEN' +``` + +**Responses** + +| Status | Description | Schema | +|--------|-------------|--------| +| `200` | The database's direct fork children (immediate forks only). | [`DatabaseRef[]`](models#model-databaseref) | +| `400` | The request was malformed or failed input validation. | [`Problem`](models#model-problem) | +| `401` | Authentication credentials were missing or invalid. | [`Problem`](models#model-problem) | +| `404` | The requested resource does not exist. | [`Problem`](models#model-problem) | +| `405` | The HTTP method is not supported for this resource. | [`Problem`](models#model-problem) | +| `500` | An unexpected server error occurred. | [`Problem`](models#model-problem) | + +**Example response `200`** + +```json +{ + "data": [ + { + "owner": "dolthub", + "name": "us-jails" + } + ], + "meta": { + "next_page_token": "eyJvZmZzZXQiOjI1fQ" + } +} +``` + +--- + +### Fork a database {#createFork} +`POST /api/v2/databases/{owner}/{database}/forks` + +Forks `{owner}/{database}` into `owner`'s namespace. Returns `202` with an `OperationRef`; follow `OperationRef.href` to poll for completion (operation IDs contain slashes and must not be interpolated raw into path templates). The caller must have read access on the source database and may only fork into a namespace they own. Duplicate forks (same source forked twice into the same owner) surface as `422` via the standard error model. Authentication is required. + + +**Parameters** + +| Name | In | Type | Required | Description | +|------|----|------|----------|-------------| +| `owner` | path | string | yes | The user or organization that owns the source database. | +| `database` | path | string | yes | The source database name, unique within the owner. | + +**Request body** + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `owner` | string | yes | The user or organization that will own the new fork. | + +**Example request** + +```sh +curl -X POST 'https://www.dolthub.com/api/v2/databases/{owner}/{database}/forks' \ + -H 'Authorization: Bearer YOUR_TOKEN' \ + -H 'Content-Type: application/json' \ + -d '{"owner":"taylor"}' +``` + +**Responses** + +| Status | Description | Schema | +|--------|-------------|--------| +| `202` | The fork operation has been accepted and is queued. | [`OperationRef`](models#model-operationref) | +| `400` | The request was malformed or failed input validation. | [`Problem`](models#model-problem) | +| `401` | Authentication credentials were missing or invalid. | [`Problem`](models#model-problem) | +| `403` | Authenticated, but not permitted to perform this action. | [`Problem`](models#model-problem) | +| `404` | The requested resource does not exist. | [`Problem`](models#model-problem) | +| `405` | The HTTP method is not supported for this resource. | [`Problem`](models#model-problem) | +| `422` | The request was well-formed but semantically invalid. | [`Problem`](models#model-problem) | +| `500` | An unexpected server error occurred. | [`Problem`](models#model-problem) | + + +## Releases + +### List releases {#listReleases} +`GET /api/v2/databases/{owner}/{database}/releases` + +Returns the releases of the database `{owner}/{database}`, ordered by the backend. Cursor-paginated via `page_token` (request) / `meta.next_page_token` (response); when `next_page_token` is absent or empty there are no further pages. Public databases are readable without authentication; private databases require a credential with access (and return `404` otherwise, so their existence isn't leaked). + + +**Parameters** + +| Name | In | Type | Required | Description | +|------|----|------|----------|-------------| +| `owner` | path | string | yes | The user or organization that owns the database. | +| `database` | path | string | yes | The database name, unique within the owner. | +| `page_token` | query | string | no | Opaque cursor returned in a prior response's `meta.next_page_token`. Pass it back to fetch the next page; omit it on the first request. The token format is server-defined — clients must treat it as an opaque string. | + +**Example request** + +```sh +curl -X GET 'https://www.dolthub.com/api/v2/databases/{owner}/{database}/releases' \ + -H 'Authorization: Bearer YOUR_TOKEN' +``` + +**Responses** + +| Status | Description | Schema | +|--------|-------------|--------| +| `200` | The database's releases. | [`Release[]`](models#model-release) | +| `400` | The request was malformed or failed input validation. | [`Problem`](models#model-problem) | +| `401` | Authentication credentials were missing or invalid. | [`Problem`](models#model-problem) | +| `404` | The requested resource does not exist. | [`Problem`](models#model-problem) | +| `405` | The HTTP method is not supported for this resource. | [`Problem`](models#model-problem) | +| `500` | An unexpected server error occurred. | [`Problem`](models#model-problem) | + +**Example response `200`** + +```json +{ + "data": [ + { + "tag": "v1.0.0", + "title": "First public release", + "commit_sha": "vt1u8gdsovtj0qq2qmd6he7n5o4mq2qm", + "description": "## Highlights\n- new join planner", + "created_at": "2024-01-15T12:34:56Z", + "updated_at": "2024-01-15T12:34:56Z" + } + ], + "meta": { + "next_page_token": "eyJvZmZzZXQiOjI1fQ" + } +} +``` + +--- + +### Create a release {#createRelease} +`POST /api/v2/databases/{owner}/{database}/releases` + +Creates a release in `{owner}/{database}` pinned to the commit named by `commit_sha` and published under `tag`. When `create_tag_if_not_exists` is true and no tag with that name exists, the backend creates one pointing at the same commit; otherwise the tag must already exist and point at the same commit. Returns the new `Release` resource on `201`. Authentication required; the caller must have write access. A `409 Conflict` comes back if a release with the same tag already exists. + + +**Parameters** + +| Name | In | Type | Required | Description | +|------|----|------|----------|-------------| +| `owner` | path | string | yes | The user or organization that owns the database. | +| `database` | path | string | yes | The database name, unique within the owner. | + +**Request body** + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `tag` | string | yes | The tag the release is published under, unique within the database. | +| `title` | string | yes | Human-readable title. | +| `commit_sha` | string | yes | The commit hash the release points at. | +| `description` | string | no | Optional release notes body (markdown). | +| `create_tag_if_not_exists` | boolean | no | When true and no tag named `tag` exists, create one pointing at `commit_sha`. Defaults to false — the caller is responsible for tag creation otherwise. | + +**Example request** + +```sh +curl -X POST 'https://www.dolthub.com/api/v2/databases/{owner}/{database}/releases' \ + -H 'Authorization: Bearer YOUR_TOKEN' \ + -H 'Content-Type: application/json' \ + -d '{"tag":"v1.0.0","title":"First public release","commit_sha":"vt1u8gdsovtj0qq2qmd6he7n5o4mq2qm"}' +``` + +**Responses** + +| Status | Description | Schema | +|--------|-------------|--------| +| `201` | The newly-created release. | [`Release`](models#model-release) | +| `400` | The request was malformed or failed input validation. | [`Problem`](models#model-problem) | +| `401` | Authentication credentials were missing or invalid. | [`Problem`](models#model-problem) | +| `403` | Authenticated, but not permitted to perform this action. | [`Problem`](models#model-problem) | +| `404` | The requested resource does not exist. | [`Problem`](models#model-problem) | +| `405` | The HTTP method is not supported for this resource. | [`Problem`](models#model-problem) | +| `409` | The request conflicts with the current state of the resource (e.g. it already exists). | [`Problem`](models#model-problem) | +| `500` | An unexpected server error occurred. | [`Problem`](models#model-problem) | + +**Example response `201`** + +```json +{ + "data": { + "tag": "v1.0.0", + "title": "First public release", + "commit_sha": "vt1u8gdsovtj0qq2qmd6he7n5o4mq2qm", + "description": "## Highlights\n- new join planner", + "created_at": "2024-01-15T12:34:56Z", + "updated_at": "2024-01-15T12:34:56Z" + } +} +``` + + +## Pull Requests + +### List pull requests {#listPulls} +`GET /api/v2/databases/{owner}/{database}/pulls` + +Returns the pull requests for the database `{owner}/{database}`, ordered by the backend. Cursor-paginated via `page_token` (request) / `meta.next_page_token` (response); when `next_page_token` is absent or empty there are no further pages. Public databases are readable without authentication; private databases require a credential with access (and return `404` otherwise, so their existence isn't leaked). + + +**Parameters** + +| Name | In | Type | Required | Description | +|------|----|------|----------|-------------| +| `owner` | path | string | yes | The user or organization that owns the database. | +| `database` | path | string | yes | The database name, unique within the owner. | +| `page_token` | query | string | no | Opaque cursor returned in a prior response's `meta.next_page_token`. Pass it back to fetch the next page; omit it on the first request. The token format is server-defined — clients must treat it as an opaque string. | + +**Example request** + +```sh +curl -X GET 'https://www.dolthub.com/api/v2/databases/{owner}/{database}/pulls' \ + -H 'Authorization: Bearer YOUR_TOKEN' +``` + +**Responses** + +| Status | Description | Schema | +|--------|-------------|--------| +| `200` | The database's pull requests. | [`PullSummary[]`](models#model-pullsummary) | +| `400` | The request was malformed or failed input validation. | [`Problem`](models#model-problem) | +| `401` | Authentication credentials were missing or invalid. | [`Problem`](models#model-problem) | +| `404` | The requested resource does not exist. | [`Problem`](models#model-problem) | +| `405` | The HTTP method is not supported for this resource. | [`Problem`](models#model-problem) | +| `500` | An unexpected server error occurred. | [`Problem`](models#model-problem) | + +**Example response `200`** + +```json +{ + "data": [ + { + "pull_number": 42, + "title": "Fix join planner regression", + "description": "Fixes #99.", + "state": "open", + "created_at": "2024-01-15T12:34:56Z", + "creator": "dolthub" + } + ], + "meta": { + "next_page_token": "eyJvZmZzZXQiOjI1fQ" + } +} +``` + +--- + +### Create a pull request {#createPull} +`POST /api/v2/databases/{owner}/{database}/pulls` + +Opens a new pull request in `{owner}/{database}`. `to_branch.database` must equal the URL's `{owner}/{database}`. `from_branch.database` is usually the same; for a cross-fork pull it points at a fork — in that case the caller must have read access on the fork's database and the fork's network root must match the target. Returns the new `Pull` resource on `201`. Authentication is required. + + +**Parameters** + +| Name | In | Type | Required | Description | +|------|----|------|----------|-------------| +| `owner` | path | string | yes | The user or organization that owns the database. | +| `database` | path | string | yes | The database name, unique within the owner. | + +**Request body** + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `title` | string | yes | The pull request's title. | +| `description` | string | no | Optional pull-request body (markdown). | +| `from_branch` | object | yes | A reference to a branch within a specific database. Carries the database so callers can disambiguate cross-fork pull requests, where `from_branch` and `to_branch` may live in different repositories. | +| `to_branch` | object | yes | A reference to a branch within a specific database. Carries the database so callers can disambiguate cross-fork pull requests, where `from_branch` and `to_branch` may live in different repositories. | + +**Example request** + +```sh +curl -X POST 'https://www.dolthub.com/api/v2/databases/{owner}/{database}/pulls' \ + -H 'Authorization: Bearer YOUR_TOKEN' \ + -H 'Content-Type: application/json' \ + -d '{"title":"Fix join planner regression","from_branch":{"database":{"owner":"dolthub","name":"us-jails"},"branch_name":"my-feature"},"to_branch":{"database":{"owner":"dolthub","name":"us-jails"},"branch_name":"my-feature"}}' +``` + +**Responses** + +| Status | Description | Schema | +|--------|-------------|--------| +| `201` | The newly-created pull request. | [`Pull`](models#model-pull) | +| `400` | The request was malformed or failed input validation. | [`Problem`](models#model-problem) | +| `401` | Authentication credentials were missing or invalid. | [`Problem`](models#model-problem) | +| `403` | Authenticated, but not permitted to perform this action. | [`Problem`](models#model-problem) | +| `404` | The requested resource does not exist. | [`Problem`](models#model-problem) | +| `405` | The HTTP method is not supported for this resource. | [`Problem`](models#model-problem) | +| `409` | The request conflicts with the current state of the resource (e.g. it already exists). | [`Problem`](models#model-problem) | +| `500` | An unexpected server error occurred. | [`Problem`](models#model-problem) | + +**Example response `201`** + +```json +{ + "data": { + "pull_number": 42, + "title": "Fix join planner regression", + "description": "Fixes #99.", + "state": "open", + "from_branch": { + "database": { + "owner": "dolthub", + "name": "us-jails" + }, + "branch_name": "my-feature" + }, + "to_branch": { + "database": { + "owner": "dolthub", + "name": "us-jails" + }, + "branch_name": "main" + }, + "created_at": "2024-01-15T12:34:56Z", + "creator": "dolthub" + } +} +``` + +--- + +### Get a pull request {#getPull} +`GET /api/v2/databases/{owner}/{database}/pulls/{pull_number}` + +Returns the pull request `{pull_number}` in the database `{owner}/{database}`. Unlike the list endpoint, the per-pull resource exposes structured `from_branch` / `to_branch` references, each carrying the database the branch lives in — necessary to disambiguate cross-fork pulls where the source branch lives in a different repository. Public databases are readable without authentication; private databases require a credential with access (and return `404` otherwise, so their existence isn't leaked). + + +**Parameters** + +| Name | In | Type | Required | Description | +|------|----|------|----------|-------------| +| `owner` | path | string | yes | The user or organization that owns the database. | +| `database` | path | string | yes | The database name, unique within the owner. | +| `pull_number` | path | string | yes | The per-database sequential pull-request identifier (à la GitHub PR numbers). | + +**Example request** + +```sh +curl -X GET 'https://www.dolthub.com/api/v2/databases/{owner}/{database}/pulls/{pull_number}' \ + -H 'Authorization: Bearer YOUR_TOKEN' +``` + +**Responses** + +| Status | Description | Schema | +|--------|-------------|--------| +| `200` | The requested pull request. | [`Pull`](models#model-pull) | +| `400` | The request was malformed or failed input validation. | [`Problem`](models#model-problem) | +| `401` | Authentication credentials were missing or invalid. | [`Problem`](models#model-problem) | +| `404` | The requested resource does not exist. | [`Problem`](models#model-problem) | +| `405` | The HTTP method is not supported for this resource. | [`Problem`](models#model-problem) | +| `500` | An unexpected server error occurred. | [`Problem`](models#model-problem) | + +**Example response `200`** + +```json +{ + "data": { + "pull_number": 42, + "title": "Fix join planner regression", + "description": "Fixes #99.", + "state": "open", + "from_branch": { + "database": { + "owner": "dolthub", + "name": "us-jails" + }, + "branch_name": "my-feature" + }, + "to_branch": { + "database": { + "owner": "dolthub", + "name": "us-jails" + }, + "branch_name": "main" + }, + "created_at": "2024-01-15T12:34:56Z", + "creator": "dolthub" + } +} +``` + +--- + +### Update a pull request {#updatePull} +`PATCH /api/v2/databases/{owner}/{database}/pulls/{pull_number}` + +Partially updates the pull request `{pull_number}` in `{owner}/{database}`. The body carries only the fields the caller is changing — any subset of `title`, `description`, `state`; at least one must be present. `state` is restricted to the writable transitions (`open` ↔ `closed`); merging happens via the dedicated merge operation (phase 4), not by writing state here. Returns the canonical `Pull` resource on `200`. Authentication required. + + +**Parameters** + +| Name | In | Type | Required | Description | +|------|----|------|----------|-------------| +| `owner` | path | string | yes | The user or organization that owns the database. | +| `database` | path | string | yes | The database name, unique within the owner. | +| `pull_number` | path | string | yes | The per-database sequential pull-request identifier. | + +**Request body** + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `title` | string | no | New title; omit to leave unchanged. | +| `description` | string | no | New description body (markdown); omit to leave unchanged. | +| `state` | string | no | New state. Merging is a separate operation; this field can't transition to `merged`. | + +**Example request** + +```sh +curl -X PATCH 'https://www.dolthub.com/api/v2/databases/{owner}/{database}/pulls/{pull_number}' \ + -H 'Authorization: Bearer YOUR_TOKEN' \ + -H 'Content-Type: application/json' +``` + +**Responses** + +| Status | Description | Schema | +|--------|-------------|--------| +| `200` | The updated pull request. | [`Pull`](models#model-pull) | +| `400` | The request was malformed or failed input validation. | [`Problem`](models#model-problem) | +| `401` | Authentication credentials were missing or invalid. | [`Problem`](models#model-problem) | +| `403` | Authenticated, but not permitted to perform this action. | [`Problem`](models#model-problem) | +| `404` | The requested resource does not exist. | [`Problem`](models#model-problem) | +| `405` | The HTTP method is not supported for this resource. | [`Problem`](models#model-problem) | +| `500` | An unexpected server error occurred. | [`Problem`](models#model-problem) | + +**Example response `200`** + +```json +{ + "data": { + "pull_number": 42, + "title": "Fix join planner regression", + "description": "Fixes #99.", + "state": "open", + "from_branch": { + "database": { + "owner": "dolthub", + "name": "us-jails" + }, + "branch_name": "my-feature" + }, + "to_branch": { + "database": { + "owner": "dolthub", + "name": "us-jails" + }, + "branch_name": "main" + }, + "created_at": "2024-01-15T12:34:56Z", + "creator": "dolthub" + } +} +``` + +--- + +### List a pull request's comments {#listPullComments} +`GET /api/v2/databases/{owner}/{database}/pulls/{pull_number}/comments` + +Returns the top-level comments on pull request `{pull_number}` in `{owner}/{database}`, in the order the backend returns them. The backend doesn't paginate comments today, so the full list is returned in one response; if a comment volume hot spot appears, `page_token` / `meta.next_page_token` will be wired through without changing the resource shape. Diff-line comments and review comments are separate resources (not in v2 yet). Public databases are readable without authentication; private databases require a credential with access (and return `404` otherwise, so their existence isn't leaked). + + +**Parameters** + +| Name | In | Type | Required | Description | +|------|----|------|----------|-------------| +| `owner` | path | string | yes | The user or organization that owns the database. | +| `database` | path | string | yes | The database name, unique within the owner. | +| `pull_number` | path | string | yes | The per-database sequential pull-request identifier (à la GitHub PR numbers). | + +**Example request** + +```sh +curl -X GET 'https://www.dolthub.com/api/v2/databases/{owner}/{database}/pulls/{pull_number}/comments' \ + -H 'Authorization: Bearer YOUR_TOKEN' +``` + +**Responses** + +| Status | Description | Schema | +|--------|-------------|--------| +| `200` | The pull request's comments. | [`PullComment[]`](models#model-pullcomment) | +| `400` | The request was malformed or failed input validation. | [`Problem`](models#model-problem) | +| `401` | Authentication credentials were missing or invalid. | [`Problem`](models#model-problem) | +| `404` | The requested resource does not exist. | [`Problem`](models#model-problem) | +| `405` | The HTTP method is not supported for this resource. | [`Problem`](models#model-problem) | +| `500` | An unexpected server error occurred. | [`Problem`](models#model-problem) | + +**Example response `200`** + +```json +{ + "data": [ + { + "comment_id": "1c8f3b1e-5d2e-4a3a-9f2b-0e7a6d5c4b3a", + "author": "alice", + "body": "LGTM — one nit on the join planner case.", + "created_at": "2024-01-15T12:34:56Z", + "updated_at": "2024-01-15T12:34:56Z" + } + ], + "meta": { + "next_page_token": "eyJvZmZzZXQiOjI1fQ" + } +} +``` + +--- + +### Add a top-level comment to a pull request {#createPullComment} +`POST /api/v2/databases/{owner}/{database}/pulls/{pull_number}/comments` + +Posts a new top-level comment on pull request `{pull_number}` in `{owner}/{database}`. The body carries only the comment text; author and timestamps are server-assigned from the authenticated caller and the server clock. Returns the new `PullComment` on `201`. Diff-line and review comments are separate resources (not in v2 yet). + + +**Parameters** + +| Name | In | Type | Required | Description | +|------|----|------|----------|-------------| +| `owner` | path | string | yes | The user or organization that owns the database. | +| `database` | path | string | yes | The database name, unique within the owner. | +| `pull_number` | path | string | yes | The per-database sequential pull-request identifier. | + +**Request body** + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `body` | string | yes | The comment text (markdown). | + +**Example request** + +```sh +curl -X POST 'https://www.dolthub.com/api/v2/databases/{owner}/{database}/pulls/{pull_number}/comments' \ + -H 'Authorization: Bearer YOUR_TOKEN' \ + -H 'Content-Type: application/json' \ + -d '{"body":"LGTM — one nit on the join planner case."}' +``` + +**Responses** + +| Status | Description | Schema | +|--------|-------------|--------| +| `201` | The newly-created comment. | [`PullComment`](models#model-pullcomment) | +| `400` | The request was malformed or failed input validation. | [`Problem`](models#model-problem) | +| `401` | Authentication credentials were missing or invalid. | [`Problem`](models#model-problem) | +| `403` | Authenticated, but not permitted to perform this action. | [`Problem`](models#model-problem) | +| `404` | The requested resource does not exist. | [`Problem`](models#model-problem) | +| `405` | The HTTP method is not supported for this resource. | [`Problem`](models#model-problem) | +| `500` | An unexpected server error occurred. | [`Problem`](models#model-problem) | + +**Example response `201`** + +```json +{ + "data": { + "comment_id": "1c8f3b1e-5d2e-4a3a-9f2b-0e7a6d5c4b3a", + "author": "alice", + "body": "LGTM — one nit on the join planner case.", + "created_at": "2024-01-15T12:34:56Z", + "updated_at": "2024-01-15T12:34:56Z" + } +} +``` + +--- + +### Merge a pull request {#mergePull} +`POST /api/v2/databases/{owner}/{database}/pulls/{pull_number}/merge` + +Kicks off a merge of pull `{pull_number}` in `{owner}/{database}`. Returns `202` with an `OperationRef`; poll `GET /api/v2/operations/{id}` until `status` is `succeeded` (the operation's `result.pull_id` echoes the merged pull) or `failed`. The caller must have write access on the database. Preconditions like "pull is already merged" or "has conflicts" surface as `422` via the standard error model rather than being pre-checked here. Authentication is required. + + +**Parameters** + +| Name | In | Type | Required | Description | +|------|----|------|----------|-------------| +| `owner` | path | string | yes | The user or organization that owns the database. | +| `database` | path | string | yes | The database name, unique within the owner. | +| `pull_number` | path | string | yes | The pull request number (per-database sequential id). | + +**Example request** + +```sh +curl -X POST 'https://www.dolthub.com/api/v2/databases/{owner}/{database}/pulls/{pull_number}/merge' \ + -H 'Authorization: Bearer YOUR_TOKEN' \ + -H 'Content-Type: application/json' +``` + +**Responses** + +| Status | Description | Schema | +|--------|-------------|--------| +| `202` | The merge operation has been accepted and is queued. | [`OperationRef`](models#model-operationref) | +| `400` | The request was malformed or failed input validation. | [`Problem`](models#model-problem) | +| `401` | Authentication credentials were missing or invalid. | [`Problem`](models#model-problem) | +| `403` | Authenticated, but not permitted to perform this action. | [`Problem`](models#model-problem) | +| `404` | The requested resource does not exist. | [`Problem`](models#model-problem) | +| `405` | The HTTP method is not supported for this resource. | [`Problem`](models#model-problem) | +| `422` | The request was well-formed but semantically invalid. | [`Problem`](models#model-problem) | +| `500` | An unexpected server error occurred. | [`Problem`](models#model-problem) | + + +## Imports + +### Initialize a multipart upload for an import {#createImportUpload} +`POST /api/v2/databases/{owner}/{database}/imports/uploads` + +Starts a multipart upload session and returns the pre-signed part URLs the client uses to upload the source file directly to object storage. Once every part is uploaded, call `POST /api/v2/databases/{owner}/{database}/imports` with the returned `token`, `contents_key`, and the collected `completed_parts` to create the import operation. Authentication is required. + + +**Parameters** + +| Name | In | Type | Required | Description | +|------|----|------|----------|-------------| +| `owner` | path | string | yes | The user or organization that owns the database. | +| `database` | path | string | yes | The database name, unique within the owner. | + +**Request body** + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `content_length` | integer | yes | Total size of the file being uploaded, in bytes. | +| `num_parts` | integer | yes | Number of parts the client will split the upload into. | +| `file_type` | string | yes | Source file format for an import. | + +**Example request** + +```sh +curl -X POST 'https://www.dolthub.com/api/v2/databases/{owner}/{database}/imports/uploads' \ + -H 'Authorization: Bearer YOUR_TOKEN' \ + -H 'Content-Type: application/json' \ + -d '{"content_length":1048576,"num_parts":4,"file_type":"csv"}' +``` + +**Responses** + +| Status | Description | Schema | +|--------|-------------|--------| +| `201` | The multipart upload session. | [`ImportUpload`](models#model-importupload) | +| `400` | The request was malformed or failed input validation. | [`Problem`](models#model-problem) | +| `401` | Authentication credentials were missing or invalid. | [`Problem`](models#model-problem) | +| `403` | Authenticated, but not permitted to perform this action. | [`Problem`](models#model-problem) | +| `404` | The requested resource does not exist. | [`Problem`](models#model-problem) | +| `405` | The HTTP method is not supported for this resource. | [`Problem`](models#model-problem) | +| `500` | An unexpected server error occurred. | [`Problem`](models#model-problem) | + +--- + +### Create an import operation {#createImport} +`POST /api/v2/databases/{owner}/{database}/imports` + +Imports the previously-uploaded file into `{owner}/{database}` as the table named in the body. The upload (token, contents_key, and the parts uploaded against the URLs returned by `POST .../imports/uploads`) must already be complete; the import itself runs asynchronously. Returns `202` + an `OperationRef`; poll `GET /api/v2/operations/{id}` until `status` is `succeeded` or `failed`. Authentication is required. + + +**Parameters** + +| Name | In | Type | Required | Description | +|------|----|------|----------|-------------| +| `owner` | path | string | yes | The user or organization that owns the database. | +| `database` | path | string | yes | The database name, unique within the owner. | + +**Request body** + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `branch_name` | string | yes | The branch to import onto. | +| `table_name` | string | yes | The destination table. | +| `file_name` | string | yes | The original file name (used for the commit message and import description). | +| `file_size` | integer | yes | Size of the uploaded file in bytes; must match the `content_length` from `createImportUpload`. | +| `file_type` | string | yes | Source file format for an import. | +| `import_operation` | string | yes | How the imported rows are applied to the target table. `create` requires the table not to exist; `overwrite` replaces it; `update` upserts into an existing table; `replace` truncates then inserts. | +| `token` | string | yes | Upload-session token from `createImportUpload`. | +| `contents_key` | string | yes | Contents key from `createImportUpload`. | +| `completed_parts` | array | yes | One entry per uploaded part, in any order. | +| `file_parts_md5` | string | yes | MD5 of the concatenated per-part MD5s, base64-encoded. Some backends require this for integrity verification of the assembled file. | +| `primary_keys` | array | yes | Primary-key column names. May be empty when the destination table already exists (its existing primary keys are used). Required (possibly empty) so a missing field fails fast rather than mis-importing as no-primary-key. | +| `commit_message` | string | no | Override the default commit message the import produces. | +| `pull_request_branch_name` | string | no | When set, the import lands on this branch (created from `branch_name`) and a pull request is opened against `branch_name`. When unset, the import lands directly on `branch_name`. | +| `column_map` | object | no | Optional mapping from source column names to destination column names. Useful when the file's columns don't match the target table's columns. | + +**Example request** + +```sh +curl -X POST 'https://www.dolthub.com/api/v2/databases/{owner}/{database}/imports' \ + -H 'Authorization: Bearer YOUR_TOKEN' \ + -H 'Content-Type: application/json' \ + -d '{"branch_name":"main","table_name":"states","file_name":"states.csv","file_size":1048576}' +``` + +**Responses** + +| Status | Description | Schema | +|--------|-------------|--------| +| `202` | The import operation has been accepted and is queued. | [`OperationRef`](models#model-operationref) | +| `400` | The request was malformed or failed input validation. | [`Problem`](models#model-problem) | +| `401` | Authentication credentials were missing or invalid. | [`Problem`](models#model-problem) | +| `403` | Authenticated, but not permitted to perform this action. | [`Problem`](models#model-problem) | +| `404` | The requested resource does not exist. | [`Problem`](models#model-problem) | +| `405` | The HTTP method is not supported for this resource. | [`Problem`](models#model-problem) | +| `500` | An unexpected server error occurred. | [`Problem`](models#model-problem) | + diff --git a/site/dolt/src/content/products/dolthub/api/v2/migration.md b/site/dolt/src/content/products/dolthub/api/v2/migration.md new file mode 100644 index 0000000..bb84ac9 --- /dev/null +++ b/site/dolt/src/content/products/dolthub/api/v2/migration.md @@ -0,0 +1,143 @@ +--- +title: "Migrating from v1alpha1" +description: How to migrate your integrations from the DoltHub v1alpha1 API to v2. +--- + +# Migrating from v1alpha1 + +This page covers the mechanical changes needed to move an existing v1alpha1 integration to v2. Read it alongside the [v2 overview](../v2) and the per-resource pages. + +## 1. Base URL + +Every v1alpha1 path lives under `/api/v1alpha1/`. Every v2 path lives under `/api/v2/`. + +```diff +- https://www.dolthub.com/api/v1alpha1/dolthub/us-jails ++ https://www.dolthub.com/api/v2/databases/dolthub/us-jails/sql?q=SHOW+TABLES +``` + +The database owner and name moved from path roots into `/databases/{owner}/{database}/`. + +--- + +## 2. Response envelope + +v1alpha1 responses are flat and ad-hoc — each endpoint has its own top-level shape. v2 wraps every success response in a uniform envelope: + +```json +{ + "data": { ... }, + "meta": { "next_page_token": "eyJ..." } +} +``` + +`data` is the resource (or an array of resources for list endpoints). `meta` is present on list responses and carries the pagination cursor; it is absent on single-resource responses. + +**Before (v1alpha1 branch list):** +```json +{ + "database_owner": "dolthub", + "database_name": "us-jails", + "branches": [ { "name": "main", ... } ] +} +``` + +**After (v2 branch list):** +```json +{ + "data": [ { "name": "main", "head_commit_sha": "abc...", "last_updated_at": "..." } ], + "meta": { "next_page_token": "eyJ..." } +} +``` + +--- + +## 3. Error model + +v1alpha1 error shapes vary by endpoint. v2 uses [RFC 9457 Problem Details](https://www.rfc-editor.org/rfc/rfc9457) for every non-2xx response. See [Models → Problem](models#model-problem). + +```json +{ + "type": "https://dolthub.com/docs/api/errors/not-found", + "title": "Not found", + "status": 404, + "detail": "Branch 'feature' does not exist in dolthub/us-jails", + "instance": "/api/v2/databases/dolthub/us-jails/branches/feature", + "code": "NOT_FOUND", + "request_id": "req_01HZX9P7Q5N2M8" +} +``` + +Branch on `code` (a stable `SCREAMING_SNAKE_CASE` string), never on `title` or `detail` (prose that can change). + +--- + +## 4. Pagination + +v1alpha1 list endpoints use offset-based pagination (or no pagination). v2 uses **cursor-based pagination** throughout. + +- If `meta.next_page_token` is present in the response, pass it back as `?page_token=` to fetch the next page. +- An absent or empty `next_page_token` means you are on the last page. + +```sh +# First page +curl 'https://www.dolthub.com/api/v2/databases/dolthub/us-jails/branches' + +# Next page +curl 'https://www.dolthub.com/api/v2/databases/dolthub/us-jails/branches?page_token=eyJ...' +``` + +--- + +## 5. Async operations + +v1alpha1 exposes separate polling endpoints per operation type (e.g. `GET /fork`, `GET /{owner}/{database}/write`, `GET /{owner}/{database}/pulls/{id}/merge`). + +v2 uses a single unified protocol: any async mutation returns `202` with an `OperationRef`: + +```json +{ + "data": { + "id": "owners/dolthub/repos/us-jails/jobs/abc123", + "href": "https://www.dolthub.com/api/v2/operations/owners/dolthub/repos/us-jails/jobs/abc123" + } +} +``` + +Poll `GET /api/v2/operations/{operation_id}` until `status` is `succeeded` or `failed`. See [Operations](operations#getOperation). + +```sh +curl 'https://www.dolthub.com/api/v2/operations/owners/dolthub/repos/us-jails/jobs/abc123' \ + -H 'Authorization: Bearer YOUR_TOKEN' +``` + +--- + +## 6. Endpoint mapping + +| v1alpha1 | v2 | +|---|---| +| `GET /user` | [`GET /api/v2/user`](user#getCurrentUser) | +| `POST /database` | [`POST /api/v2/databases`](database#createDatabase) | +| `GET /{owner}/{database}?q=` | [`GET /api/v2/databases/{owner}/{database}/sql?q=`](database#runSqlReadQuery) | +| `GET /{owner}/{database}/{ref}?q=` | [`GET /api/v2/databases/{owner}/{database}/sql?q=&ref=`](database#runSqlReadQuery) | +| `GET /{owner}/{database}/forks` | [`GET /api/v2/databases/{owner}/{database}/forks`](database#listForks) | +| `GET /{owner}/{database}/branches` | [`GET /api/v2/databases/{owner}/{database}/branches`](database#listBranches) | +| `POST /{owner}/{database}/branches` | [`POST /api/v2/databases/{owner}/{database}/branches`](database#createBranch) | +| `GET /{owner}/{database}/pulls` | [`GET /api/v2/databases/{owner}/{database}/pulls`](database#listPulls) | +| `POST /{owner}/{database}/pulls` | [`POST /api/v2/databases/{owner}/{database}/pulls`](database#createPull) | +| `GET /{owner}/{database}/pulls/{id}` | [`GET /api/v2/databases/{owner}/{database}/pulls/{pull_number}`](database#getPull) | +| `PATCH /{owner}/{database}/pulls/{id}` | [`PATCH /api/v2/databases/{owner}/{database}/pulls/{pull_number}`](database#updatePull) | +| `POST /{owner}/{database}/pulls/{id}/comments` | [`POST /api/v2/databases/{owner}/{database}/pulls/{pull_number}/comments`](database#createPullComment) | +| `POST /{owner}/{database}/pulls/{id}/merge` | [`POST /api/v2/databases/{owner}/{database}/pulls/{pull_number}/merge`](database#mergePull) | +| `GET /{owner}/{database}/pulls/{id}/merge` | Poll [`GET /api/v2/operations/{id}`](operations#getOperation) | +| `GET /{owner}/{database}/releases` | [`GET /api/v2/databases/{owner}/{database}/releases`](database#listReleases) | +| `POST /{owner}/{database}/releases` | [`POST /api/v2/databases/{owner}/{database}/releases`](database#createRelease) | +| `GET /{owner}/{database}/tags` | [`GET /api/v2/databases/{owner}/{database}/tags`](database#listTags) | +| `POST /{owner}/{database}/tags` | [`POST /api/v2/databases/{owner}/{database}/tags`](database#createTag) | +| `POST /{owner}/{database}/upload` | [`POST .../imports/uploads`](database#createImportUpload) then [`POST .../imports`](database#createImport) | +| `GET /{owner}/{database}/upload` | Poll [`GET /api/v2/operations/{id}`](operations#getOperation) | +| `POST /fork` | [`POST /api/v2/databases/{owner}/{database}/forks`](database#createFork) | +| `GET /fork` | Poll [`GET /api/v2/operations/{id}`](operations#getOperation) | +| `GET /{owner}/{database}/jobs` | [`GET /api/v2/databases/{owner}/{database}/operations`](operations#listOperations) | +| `GET /users/{username}/operations` | [`GET /api/v2/databases/{owner}/{database}/operations`](operations#listOperations) | diff --git a/site/dolt/src/content/products/dolthub/api/v2/models.md b/site/dolt/src/content/products/dolthub/api/v2/models.md new file mode 100644 index 0000000..06b0479 --- /dev/null +++ b/site/dolt/src/content/products/dolthub/api/v2/models.md @@ -0,0 +1,488 @@ +--- +title: "Models" +description: Request and response schemas for the DoltHub v2 API. +--- + +# Models + +Shared request and response types used across the v2 API. See the [error model](#model-problem) for how failures are reported. + +## ErrorCode {#model-errorcode} +A stable, machine-readable error code in SCREAMING_SNAKE_CASE. Clients branch on this value, never on the human-readable `title`/`detail` prose. The baseline codes below cover the standard HTTP failure categories; endpoint-specific codes (e.g. `BRANCH_NOT_FOUND`) are appended to this enum alongside the endpoints that emit them, which is an additive, non-breaking change under the v2 stability policy (§5.1). + +**Enum values** + +| Value | +|-------| +| `VALIDATION_FAILED` | +| `UNAUTHENTICATED` | +| `PERMISSION_DENIED` | +| `NOT_FOUND` | +| `METHOD_NOT_ALLOWED` | +| `CONFLICT` | +| `UNPROCESSABLE` | +| `RATE_LIMITED` | +| `INTERNAL` | +| `SERVICE_UNAVAILABLE` | +| `OPERATION_FAILED` | + +--- + +## Problem {#model-problem} +A structured error body returned for every non-2xx response, following RFC 9457 (Problem Details for HTTP APIs). This is the single error model for the entire v2 API — there are no ad-hoc error shapes. + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `type` | `string` | no | A URI identifying the problem type; when dereferenced it points at human-readable documentation for the error. | +| `title` | `string` | yes | A short, human-readable summary of the problem type. | +| `status` | `integer` | yes | The HTTP status code, repeated in the body for convenience. | +| `detail` | `string` | no | A human-readable explanation specific to this occurrence of the problem. | +| `instance` | `string` | no | A URI reference identifying the specific occurrence (typically the request path). | +| `code` | `string` | yes | A stable, machine-readable error code in SCREAMING_SNAKE_CASE. Clients branch on this value, never on the human-readable `title`/`detail` prose. The baseline codes below cover the standard HTTP failure categories; endpoint-specific codes (e.g. `BRANCH_NOT_FOUND`) are appended to this enum alongside the endpoints that emit them, which is an additive, non-breaking change under the v2 stability policy (§5.1). | +| `request_id` | `string` | yes | The request identifier, echoed on every response. Include it when contacting support so a request can be traced end-to-end. | + +--- + +## Meta {#model-meta} +Response metadata carried alongside the primary `data` payload. All fields are optional; list endpoints populate `next_page_token` for cursor pagination (§5.6). + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `next_page_token` | `string` | no | Opaque cursor for the next page of a list response. Absent or empty when there are no further results; otherwise pass it back as the `page_token` query parameter to fetch the next page. | + +--- + +## Envelope {#model-envelope} +The success envelope wrapping every 2xx response body (§5.4): the resource or list of resources under `data`, with optional `meta`. This is the single success shape for the API — there are no unenveloped success bodies. Endpoints narrow `data` to a concrete resource via `allOf` (see the section comment above); the base leaves `data` unconstrained so that composition works. + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `data` | `object,array` | yes | The primary response payload — a resource, or an array of resources for list endpoints. | +| `meta` | `object` | no | Response metadata carried alongside the primary `data` payload. All fields are optional; list endpoints populate `next_page_token` for cursor pagination (§5.6). | + +--- + +## DatabaseRef {#model-databaseref} +A minimal reference to a database — owner and name only. Used wherever the API points at another database (a fork's parent, a network's root, an item in the forks list) without re-embedding the full Database resource. + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `owner` | `string` | yes | The user or organization that owns the referenced database. | +| `name` | `string` | yes | The referenced database's name. | + +--- + +## CreateDatabaseRequest {#model-createdatabaserequest} +Body for `POST /api/v2/databases`. `owner` names the user or organization that will own the new database; the caller's credentials must allow creating under that owner. + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `owner` | `string` | yes | The user or organization that will own the database. | +| `name` | `string` | yes | The database name. Must be unique within the owner and conform to DoltHub's naming rules (letters, digits, `-`, `_`; cannot start or end with `-`). | +| `description` | `string` | no | Optional human-readable description. | +| `visibility` | `string` | yes | Whether the database is publicly readable. Defaults are *not* applied — clients must declare the intended visibility on create. | + +--- + +## CreatePullRequest {#model-createpullrequest} +Body for `POST /api/v2/databases/{owner}/{database}/pulls`. `to_branch.database` must equal the URL's `{owner}/{database}` (the PR opens against this repo); `from_branch.database` is usually the same but may point at a fork for cross-fork PRs. + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `title` | `string` | yes | The pull request's title. | +| `description` | `string` | no | Optional pull-request body (markdown). | +| `from_branch` | `object` | yes | A reference to a branch within a specific database. Carries the database so callers can disambiguate cross-fork pull requests, where `from_branch` and `to_branch` may live in different repositories. | +| `to_branch` | `object` | yes | A reference to a branch within a specific database. Carries the database so callers can disambiguate cross-fork pull requests, where `from_branch` and `to_branch` may live in different repositories. | + +--- + +## CreatePullCommentRequest {#model-createpullcommentrequest} +Body for `POST /api/v2/databases/{owner}/{database}/pulls/{pull_number}/comments`. Carries only the comment text; author and timestamps are server-assigned. + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `body` | `string` | yes | The comment text (markdown). | + +--- + +## MergePullRequest {#model-mergepullrequest} +Body for `POST /api/v2/databases/{owner}/{database}/pulls/{pull_number}/merge`. Currently empty — the merge takes no parameters today. The empty object exists so the schema is closed under `additionalProperties` (mistyped fields fail loud rather than getting silently dropped) and so we have a stable place to add the conflict-resolution strategy when that ships. + +_Type: `object`_ + + +--- + +## CreateForkRequest {#model-createforkrequest} +Body for `POST /api/v2/databases/{owner}/{database}/forks`. The URL identifies the source database; `owner` is the user or organization that will own the new fork. The new fork inherits the source database's name. Forking into a namespace the caller does not own returns `403`. + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `owner` | `string` | yes | The user or organization that will own the new fork. | + +--- + +## UpdatePullRequest {#model-updatepullrequest} +Body for `PATCH /api/v2/databases/{owner}/{database}/pulls/{pull_number}`. Every field is optional; the caller supplies whichever fields they're changing and the server only updates those. At least one field must be present. `state` is restricted to the writable transitions (`open` ↔ `closed`); to merge, use the merge operation. + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `title` | `string` | no | New title; omit to leave unchanged. | +| `description` | `string` | no | New description body (markdown); omit to leave unchanged. | +| `state` | `string` | no | New state. Merging is a separate operation; this field can't transition to `merged`. | + +--- + +## CreateBranchRequest {#model-createbranchrequest} +Body for `POST /api/v2/databases/{owner}/{database}/branches`. `from` is a discriminated union — one of `{ branch }` or `{ commit }` — that names the source revision the new branch will point at. + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `name` | `string` | yes | The new branch's name. | +| `from` | `object` | yes | | + +--- + +## CreateTagRequest {#model-createtagrequest} +Body for `POST /api/v2/databases/{owner}/{database}/tags`. `from` is the same `{ branch | commit }` discriminated union used by `CreateBranchRequest`. Supplying `message` produces an annotated tag; omitting it produces a lightweight tag. + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `name` | `string` | yes | The new tag's name, unique within the database. | +| `from` | `object` | yes | | +| `message` | `string` | no | Optional annotation message. Present → annotated tag; absent → lightweight tag. | + +--- + +## CreateReleaseRequest {#model-createreleaserequest} +Body for `POST /api/v2/databases/{owner}/{database}/releases`. Releases pin to a specific commit (`commit_sha`), not a moving branch. The release is published under `tag`; `create_tag_if_not_exists` lets the backend create that tag implicitly when it doesn't already exist, otherwise the tag must already point at `commit_sha`. + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `tag` | `string` | yes | The tag the release is published under, unique within the database. | +| `title` | `string` | yes | Human-readable title. | +| `commit_sha` | `string` | yes | The commit hash the release points at. | +| `description` | `string` | no | Optional release notes body (markdown). | +| `create_tag_if_not_exists` | `boolean` | no | When true and no tag named `tag` exists, create one pointing at `commit_sha`. Defaults to false — the caller is responsible for tag creation otherwise. | + +--- + +## ImportFileType {#model-importfiletype} +Source file format for an import. + +**Enum values** + +| Value | +|-------| +| `csv` | +| `psv` | +| `xlsx` | +| `json` | +| `sql` | +| `yaml` | + +--- + +## ImportOperation {#model-importoperation} +How the imported rows are applied to the target table. `create` requires the table not to exist; `overwrite` replaces it; `update` upserts into an existing table; `replace` truncates then inserts. + +**Enum values** + +| Value | +|-------| +| `create` | +| `overwrite` | +| `update` | +| `replace` | + +--- + +## CompletedPart {#model-completedpart} +One part of a multipart upload, identified by its part number and the ETag the storage backend returned. + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `part_number` | `integer` | yes | The 1-based part number this entry corresponds to. | +| `etag` | `string` | yes | The ETag returned by the storage backend for this part. | + +--- + +## ImportUploadPart {#model-importuploadpart} +A single part in an upload session — the part number plus the pre-signed URL to PUT it to. + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `part_number` | `integer` | yes | The 1-based part number. | +| `url` | `string` | yes | Pre-signed URL the client should upload this part to. | + +--- + +## ImportUpload {#model-importupload} +A multipart upload session. The client PUTs each file chunk to the matching `parts[].url`, collects the storage backend's ETag for each, and then calls `createImport` with the `token`, `contents_key`, and the collected `CompletedPart`s. + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `token` | `string` | yes | Opaque upload-session token. Pass verbatim to `createImport`. | +| `contents_key` | `string` | yes | Storage key the assembled file will live at. Pass verbatim to `createImport`. | +| `parts` | `array` | yes | One entry per part, in part-number order. | +| `http_method` | `string` | yes | HTTP method to use when uploading each part. Currently always `PUT`. | +| `headers` | `object` | yes | Headers the client must include on each part upload (e.g. proxy-auth, signed-headers added by the storage backend). Usually empty; clients should iterate every entry and add each name with all of its values to the part-upload request. Each header may have multiple values. | + +--- + +## CreateImportUploadRequest {#model-createimportuploadrequest} +Body for `POST /api/v2/databases/{owner}/{database}/imports/uploads`. Asks the server to mint a multipart upload session for a file of `content_length` bytes split into `num_parts` parts; the response carries the pre-signed URLs to upload to. + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `content_length` | `integer` | yes | Total size of the file being uploaded, in bytes. | +| `num_parts` | `integer` | yes | Number of parts the client will split the upload into. | +| `file_type` | `string` | yes | Source file format for an import. | + +--- + +## CreateImportRequest {#model-createimportrequest} +Body for `POST /api/v2/databases/{owner}/{database}/imports`. Wraps a completed multipart upload (`token`, `contents_key`, `completed_parts`) into an import job that loads the file into `table_name` on `branch_name`. Returns `202` + an `OperationRef`. + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `branch_name` | `string` | yes | The branch to import onto. | +| `table_name` | `string` | yes | The destination table. | +| `file_name` | `string` | yes | The original file name (used for the commit message and import description). | +| `file_size` | `integer` | yes | Size of the uploaded file in bytes; must match the `content_length` from `createImportUpload`. | +| `file_type` | `string` | yes | Source file format for an import. | +| `import_operation` | `string` | yes | How the imported rows are applied to the target table. `create` requires the table not to exist; `overwrite` replaces it; `update` upserts into an existing table; `replace` truncates then inserts. | +| `token` | `string` | yes | Upload-session token from `createImportUpload`. | +| `contents_key` | `string` | yes | Contents key from `createImportUpload`. | +| `completed_parts` | `array` | yes | One entry per uploaded part, in any order. | +| `file_parts_md5` | `string` | yes | MD5 of the concatenated per-part MD5s, base64-encoded. Some backends require this for integrity verification of the assembled file. | +| `primary_keys` | `array` | yes | Primary-key column names. May be empty when the destination table already exists (its existing primary keys are used). Required (possibly empty) so a missing field fails fast rather than mis-importing as no-primary-key. | +| `commit_message` | `string` | no | Override the default commit message the import produces. | +| `pull_request_branch_name` | `string` | no | When set, the import lands on this branch (created from `branch_name`) and a pull request is opened against `branch_name`. When unset, the import lands directly on `branch_name`. | +| `column_map` | `object` | no | Optional mapping from source column names to destination column names. Useful when the file's columns don't match the target table's columns. | + +--- + +## OperationStatus {#model-operationstatus} +The lifecycle state of an async operation. + +**Enum values** + +| Value | +|-------| +| `queued` | +| `running` | +| `succeeded` | +| `failed` | + +--- + +## OperationType {#model-operationtype} +The kind of work this operation performs. + +**Enum values** + +| Value | +|-------| +| `import` | +| `merge` | +| `sql_write` | +| `fork` | +| `dolt_ci` | + +--- + +## OperationError {#model-operationerror} +Error details recorded when an operation reaches the `failed` status. + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `status` | `integer` | yes | HTTP-equivalent status code for the failure. | +| `code` | `string` | yes | A stable, machine-readable error code in SCREAMING_SNAKE_CASE. Clients branch on this value, never on the human-readable `title`/`detail` prose. The baseline codes below cover the standard HTTP failure categories; endpoint-specific codes (e.g. `BRANCH_NOT_FOUND`) are appended to this enum alongside the endpoints that emit them, which is an additive, non-breaking change under the v2 stability policy (§5.1). | +| `title` | `string` | yes | A short, human-readable summary of the failure. | +| `detail` | `string` | no | A human-readable explanation of the failure, sourced from the underlying operation error message when available. | + +--- + +## Operation {#model-operation} +A long-running async operation. Every async mutation returns an `OperationRef`; poll `GET /api/v2/operations/{id}` until `status` is `succeeded` or `failed`. The `id` is opaque — pass it back to the poll endpoint verbatim. + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `id` | `string` | yes | Opaque operation identifier. Pass verbatim to `GET /api/v2/operations/{id}`. | +| `type` | `string` | yes | The kind of work this operation performs. | +| `status` | `string` | yes | The lifecycle state of an async operation. | +| `created_at` | `string` | yes | When the operation was enqueued. | +| `cancelable` | `boolean` | yes | Reserved for a future cancel endpoint. Always `false` today — no `POST /api/v2/operations/{id}/cancel` exists yet. | +| `error` | `object` | no | Error details recorded when an operation reaches the `failed` status. | +| `result` | `object` | no | Present when `status` is `succeeded`. Shape depends on `type`: `import`/`merge` → `{ pull_id }`; `sql_write` → `{ commit_sha }`; `fork` → `{ database: { owner, name } }`. | + +--- + +## OperationRef {#model-operationref} +A reference to an in-progress async operation, returned in `202` responses. Pass `id` to `GET /api/v2/operations/{id}` to poll for completion. + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `id` | `string` | yes | The operation ID. | +| `href` | `string` | yes | Absolute URL of the poll endpoint. | + +--- + +## Database {#model-database} +A DoltHub database and its public metadata. v2 exposes the database's own fields; caller-specific state (your role on it, whether you've starred it) is not part of this resource. + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `owner` | `string` | yes | The user or organization that owns the database. | +| `name` | `string` | yes | The database name, unique within the owner. | +| `description` | `string` | no | The database's short description. | +| `visibility` | `string` | yes | Whether the database is publicly readable or private. | +| `fork_network_count` | `integer` | yes | The total number of databases in this database's fork network — transitive, counting forks-of-forks. The `/forks` endpoint returns immediate children only, so `fork_network_count` may exceed the length of that list. | +| `star_count` | `integer` | yes | The number of users who have starred the database. | +| `size_bytes` | `integer` | yes | The on-disk size of the database, in bytes. | +| `last_write_at` | `string` | no | When the database last received a write. | +| `parent` | `object` | no | The database this one was forked from. Omitted when this database is not a fork — i.e., it is the root of its fork network. | +| `network_root` | `object` | no | The original database at the root of this database's fork network. Omitted when this database is itself the root (no ancestors). | + +--- + +## Branch {#model-branch} +A branch in a database — a named pointer to a head commit. v2 exposes the branch's identity (name) and the head it currently points at; the head commit's full metadata (message, author, parents) belongs to the commit resource, not the branch list. + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `name` | `string` | yes | The branch name, unique within the database. | +| `head_commit_sha` | `string` | yes | The hash of the commit the branch currently points at. | +| `last_updated_at` | `string` | no | When the head commit was committed; absent if the backend didn't report it. | + +--- + +## Tag {#model-tag} +A tag in a database — a named, optionally annotated pointer to a specific commit. v2 exposes the tag's identity and the commit it targets; the target commit's full metadata (message, author, parents) belongs to the commit resource, not the tag list. + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `name` | `string` | yes | The tag name, unique within the database. | +| `commit_sha` | `string` | yes | The hash of the commit the tag points at. | +| `message` | `string` | no | The tag's annotation message; omitted when the tag has none. | +| `tagged_at` | `string` | no | When the tag was created; absent if the backend didn't report it. | + +--- + +## Release {#model-release} +A named release of a database — a title and notes attached to a specific commit, often but not always paired with a tag of the same name. v2 exposes the release's public fields; the internal release id is omitted (the tag is the user-facing identifier). + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `tag` | `string` | yes | The tag the release is published under, unique within the database. | +| `title` | `string` | yes | The release's human-readable title. | +| `commit_sha` | `string` | yes | The hash of the commit the release points at. | +| `description` | `string` | no | The release notes body (markdown). Omitted when the release has none. | +| `created_at` | `string` | yes | When the release was first published. | +| `updated_at` | `string` | yes | When the release was last edited; equals `created_at` for never-edited releases. | + +--- + +## PullSummary {#model-pullsummary} +The lean list shape of a pull request — title, state, creator, timestamps. Companion to the canonical `Pull` resource returned by the per-pull GET, which adds structured `from_branch` / `to_branch` references (fork-aware owner / database) needed to disambiguate cross-fork PRs. + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `pull_number` | `integer` | yes | The per-database sequential identifier (à la GitHub PR numbers). | +| `title` | `string` | yes | The pull request's human-readable title. | +| `description` | `string` | no | The pull request description (markdown). Omitted when the pull has none. | +| `state` | `string` | yes | The pull request's lifecycle state. | +| `created_at` | `string` | yes | When the pull request was created. | +| `creator` | `string` | yes | The username of the user who created the pull request. | + +--- + +## BranchRef {#model-branchref} +A reference to a branch within a specific database. Carries the database so callers can disambiguate cross-fork pull requests, where `from_branch` and `to_branch` may live in different repositories. + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `database` | `object` | yes | A minimal reference to a database — owner and name only. Used wherever the API points at another database (a fork's parent, a network's root, an item in the forks list) without re-embedding the full Database resource. | +| `branch_name` | `string` | yes | The branch name within the referenced database. | + +--- + +## Pull {#model-pull} +The canonical pull-request resource. Same public fields as the list `PullSummary` plus structured `from_branch` / `to_branch` references that carry the database the branch lives in (necessary for cross-fork pulls, where the source branch lives in a different repository). + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `pull_number` | `integer` | yes | The per-database sequential identifier (à la GitHub PR numbers). | +| `title` | `string` | yes | The pull request's human-readable title. | +| `description` | `string` | no | The pull request description (markdown). Omitted when the pull has none. | +| `state` | `string` | yes | The pull request's lifecycle state. | +| `from_branch` | `object` | yes | A reference to a branch within a specific database. Carries the database so callers can disambiguate cross-fork pull requests, where `from_branch` and `to_branch` may live in different repositories. | +| `to_branch` | `object` | yes | A reference to a branch within a specific database. Carries the database so callers can disambiguate cross-fork pull requests, where `from_branch` and `to_branch` may live in different repositories. | +| `created_at` | `string` | yes | When the pull request was created. | +| `creator` | `string` | yes | The username of the user who created the pull request. | + +--- + +## PullComment {#model-pullcomment} +A top-level comment on a pull request. Diff-line comments and review comments are modeled as separate resources (not in v2 yet). + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `comment_id` | `string` | yes | The opaque per-comment identifier, unique within the pull request. | +| `author` | `string` | yes | The username of the comment's author. | +| `body` | `string` | yes | The comment text (markdown). | +| `created_at` | `string` | yes | When the comment was first posted. | +| `updated_at` | `string` | yes | When the comment was last edited (equals `created_at` if never edited). | + +--- + +## QueryColumn {#model-querycolumn} +One column in a query result's schema. + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `name` | `string` | yes | The column name. | +| `type` | `string` | yes | The column's SQL type — e.g. `VARCHAR(255)`, `BIGINT`, `DATETIME(6)`. Clients parsing typed values are expected to read this and coerce `cells` accordingly. | +| `is_primary_key` | `boolean` | no | Whether the column is part of the source table's primary key. | +| `source_table` | `string` | no | The table this column came from. Empty for expressions or virtual columns (e.g. `COUNT(*)`). | + +--- + +## QueryResult {#model-queryresult} +The result of a `runSqlReadQuery` call. SQL-level conditions (success, error, timeout, row-limit) live in `status` and `message` — they are query-level, not transport-level. + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `columns` | `array` | yes | The result schema — one entry per column, in the row's cell order. | +| `rows` | `array` | yes | The result rows. Each row is an array of cell values, ordered to match the `columns` schema. Non-NULL cells are serialized as strings regardless of the underlying SQL type; clients can parse per `columns[i].type` to coerce typed values. NULL cells are serialized as JSON `null`. BLOB-typed cells are returned as the placeholder string `""` (the backend does not stream binary bytes over this endpoint); clients can detect blob columns via `columns[i].type`. | +| `status` | `string` | yes | The query's execution status. `success` is the only status that guarantees `rows` and `columns` are fully populated. | +| `message` | `string` | no | Server-supplied message describing the status. Always populated for non-`success` statuses; usually empty on success. | +| `warnings` | `array` | no | SQL-level warnings emitted by the query engine (e.g. truncated values). | + +--- + +## EmailAddress {#model-emailaddress} +An email address registered to a DoltHub user. + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `address` | `string` | yes | The email address. | +| `is_primary` | `boolean` | yes | Whether this is the user's primary email address. | +| `is_verified` | `boolean` | yes | Whether this email address has been verified. | + +--- + +## User {#model-user} +A DoltHub user. `GET /api/v2/user` returns the authenticated user's profile. v2 returns only the public-facing profile fields — internal flags (super-admin, two-factor settings, API tokens) are never included. + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `username` | `string` | yes | The user's DoltHub username (unique handle). | +| `display_name` | `string` | no | The user's display name. May be empty. | +| `bio` | `string` | no | The user's bio. May be empty. | +| `location` | `string` | no | The user's stated location. May be empty. | +| `website_url` | `string` | no | The user's website URL. May be empty. | +| `profile_pic_url` | `string` | no | URL of the user's profile picture. May be empty. | +| `email_addresses` | `array` | yes | The user's registered email addresses. | + diff --git a/site/dolt/src/content/products/dolthub/api/v2/operations.md b/site/dolt/src/content/products/dolthub/api/v2/operations.md new file mode 100644 index 0000000..3ba465b --- /dev/null +++ b/site/dolt/src/content/products/dolthub/api/v2/operations.md @@ -0,0 +1,73 @@ +--- +title: "Operations" +description: Long-running async operations in the DoltHub v2 API. +--- + +# Operations + +Long-running async operations. Every async mutation returns an OperationRef; poll this resource to track progress. + +## List a database's async operations {#listOperations} +`GET /api/v2/databases/{owner}/{database}/operations` + +Returns the async operations (imports, merges, SQL writes, forks, …) recorded against the database `{owner}/{database}`, ordered by the backend. Cursor-paginated via `page_token` (request) / `meta.next_page_token` (response); when `next_page_token` is absent or empty there are no further pages. Public databases are readable without authentication; private databases require a credential with access (and return `404` otherwise, so their existence isn't leaked). Each entry is the same `Operation` shape `GET /api/v2/operations/{id}` returns — `data[i].id` is what you pass to that endpoint to re-poll a single operation. + + +**Parameters** + +| Name | In | Type | Required | Description | +|------|----|------|----------|-------------| +| `owner` | path | string | yes | The user or organization that owns the database. | +| `database` | path | string | yes | The database name, unique within the owner. | +| `page_token` | query | string | no | Opaque cursor returned in a prior response's `meta.next_page_token`. Pass it back to fetch the next page; omit it on the first request. The token format is server-defined — clients must treat it as an opaque string. | + +**Example request** + +```sh +curl -X GET 'https://www.dolthub.com/api/v2/databases/{owner}/{database}/operations' \ + -H 'Authorization: Bearer YOUR_TOKEN' +``` + +**Responses** + +| Status | Description | Schema | +|--------|-------------|--------| +| `200` | The database's async operations. | [`Operation[]`](models#model-operation) | +| `400` | The request was malformed or failed input validation. | [`Problem`](models#model-problem) | +| `401` | Authentication credentials were missing or invalid. | [`Problem`](models#model-problem) | +| `404` | The requested resource does not exist. | [`Problem`](models#model-problem) | +| `405` | The HTTP method is not supported for this resource. | [`Problem`](models#model-problem) | +| `500` | An unexpected server error occurred. | [`Problem`](models#model-problem) | + +--- + +## Get an async operation {#getOperation} +`GET /api/v2/operations/{operation_id}` + +Polls a long-running operation by its `id`. Every async mutation (SQL write, import, merge, fork) returns an `OperationRef` in its `202` response; clients poll this endpoint until `status` is `succeeded` or `failed`. The `id` is the job resource name returned by the backend. + + +**Parameters** + +| Name | In | Type | Required | Description | +|------|----|------|----------|-------------| +| `operation_id` | path | string | yes | The operation ID returned in an `OperationRef`. | + +**Example request** + +```sh +curl -X GET 'https://www.dolthub.com/api/v2/operations/{operation_id}' \ + -H 'Authorization: Bearer YOUR_TOKEN' +``` + +**Responses** + +| Status | Description | Schema | +|--------|-------------|--------| +| `200` | The current state of the operation. | [`Operation`](models#model-operation) | +| `401` | Authentication credentials were missing or invalid. | [`Problem`](models#model-problem) | +| `403` | Authenticated, but not permitted to perform this action. | [`Problem`](models#model-problem) | +| `404` | The requested resource does not exist. | [`Problem`](models#model-problem) | +| `405` | The HTTP method is not supported for this resource. | [`Problem`](models#model-problem) | +| `500` | An unexpected server error occurred. | [`Problem`](models#model-problem) | + diff --git a/site/dolt/src/content/products/dolthub/api/v2/user.md b/site/dolt/src/content/products/dolthub/api/v2/user.md new file mode 100644 index 0000000..b9c0d21 --- /dev/null +++ b/site/dolt/src/content/products/dolthub/api/v2/user.md @@ -0,0 +1,53 @@ +--- +title: "User" +description: The authenticated user resource in the DoltHub v2 API. +--- + +# User + +The authenticated user. + +## Get the authenticated user {#getCurrentUser} +`GET /api/v2/user` + +Returns the profile of the user identified by the request's credentials. + + +**Example request** + +```sh +curl -X GET 'https://www.dolthub.com/api/v2/user' \ + -H 'Authorization: Bearer YOUR_TOKEN' +``` + +**Responses** + +| Status | Description | Schema | +|--------|-------------|--------| +| `200` | The authenticated user's profile. | [`User`](models#model-user) | +| `401` | Authentication credentials were missing or invalid. | [`Problem`](models#model-problem) | +| `405` | The HTTP method is not supported for this resource. | [`Problem`](models#model-problem) | +| `500` | An unexpected server error occurred. | [`Problem`](models#model-problem) | + +**Example response `200`** + +```json +{ + "data": { + "username": "dolthub", + "display_name": "DoltHub", + "bio": "The database for agents.", + "location": "San Mateo, CA", + "website_url": "https://www.dolthub.com", + "profile_pic_url": "https://www.dolthub.com/static/images/dolthub_logo.png", + "email_addresses": [ + { + "address": "dolt-interest@dolthub.com", + "is_primary": true, + "is_verified": true + } + ] + } +} +``` + diff --git a/site/dolt/src/nav.ts b/site/dolt/src/nav.ts index 08f44c0..ab77403 100644 --- a/site/dolt/src/nav.ts +++ b/site/dolt/src/nav.ts @@ -271,6 +271,18 @@ const nav: NavSection[] = [ { title: "Jobs", href: "/products/dolthub/api/v1alpha1/jobs" }, ], }, + { + title: "v2", + href: "/products/dolthub/api/v2", + children: [ + { title: "Authentication", href: "/products/dolthub/api/v2/authentication" }, + { title: "User", href: "/products/dolthub/api/v2/user" }, + { title: "Database", href: "/products/dolthub/api/v2/database" }, + { title: "Operations", href: "/products/dolthub/api/v2/operations" }, + { title: "Models", href: "/products/dolthub/api/v2/models" }, + { title: "Migrating from v1alpha1", href: "/products/dolthub/api/v2/migration" }, + ], + }, { title: "CSV", href: "/products/dolthub/api/csv" }, { title: "Webhooks", href: "/products/dolthub/api/hooks" }, ], diff --git a/site/shared/config/astro.mjs b/site/shared/config/astro.mjs index 8a21c2c..ffb3317 100644 --- a/site/shared/config/astro.mjs +++ b/site/shared/config/astro.mjs @@ -4,10 +4,12 @@ import { defineConfig } from "astro/config"; import tailwind from "@astrojs/tailwind"; import react from "@astrojs/react"; +import { unified } from "@astrojs/markdown-remark"; import rehypeSlug from "rehype-slug"; import rehypeAutolinkHeadings from "rehype-autolink-headings"; import rehypeBasePath from "./rehype-base.mjs"; import remarkInjectTitleH1 from "./remark-inject-title-h1.mjs"; +import remarkHeadingId from "remark-heading-id"; export const autolinkHeadingsOptions = { behavior: "append", @@ -52,12 +54,14 @@ export function buildAstroConfig(site, siteDir) { integrations: [tailwind(), react()], markdown: { shikiConfig, - remarkPlugins: [remarkInjectTitleH1], - rehypePlugins: [ - [rehypeBasePath, { base }], - rehypeSlug, - [rehypeAutolinkHeadings, autolinkHeadingsOptions], - ], + processor: unified({ + remarkPlugins: [remarkInjectTitleH1, remarkHeadingId], + rehypePlugins: [ + [rehypeBasePath, { base }], + rehypeSlug, + [rehypeAutolinkHeadings, autolinkHeadingsOptions], + ], + }), }, vite: buildViteConfig(siteDir), }); diff --git a/specs/dolthub-v2.yaml b/specs/dolthub-v2.yaml new file mode 100644 index 0000000..cfd4ecb --- /dev/null +++ b/specs/dolthub-v2.yaml @@ -0,0 +1,3425 @@ +# DoltHub Public API v2 — OpenAPI contract. +# +# This is the single source of truth for the v2 API (see dolthub-api-v2-plan.md §5.7). +# TypeScript DTO types, runtime/contract-test JSON Schemas, and the public docs are all +# generated from this file — never hand-edited downstream. +# +# Shared components are built up across phases: +# - components.schemas.Problem / ErrorCode -> 1.c (error model) [done] +# - components.schemas.Envelope / Meta -> 1.d (success envelope) [done] +# - components.schemas.Operation -> 4.a (async operation resource) [done] +# The first real path is GET /api/v2/user (1.t), which also adds the User / +# EmailAddress resources. +openapi: 3.1.0 + +info: + title: DoltHub API + version: 2.0.0 + summary: The public REST API for DoltHub databases, branches, commits, and SQL. + description: | + The DoltHub v2 API is an explicit, versioned, OpenAPI-defined contract. Unlike the + legacy `v1alpha1` API it replaces, v2 commits to consistent HTTP semantics, a single + error model (RFC 9457 problem details), a uniform success envelope, and a standardized + protocol for long-running operations. + + This document is the contract: it is the source of truth for the implementation, the + generated client types, and the rendered reference docs. See the stability policy for + what "v2" guarantees and how changes are versioned. + contact: + name: DoltHub Support + url: https://www.dolthub.com/contact + email: dolt-interest@dolthub.com + license: + name: DoltHub Terms of Service + url: https://www.dolthub.com/terms + termsOfService: https://www.dolthub.com/terms + +servers: + - url: https://www.dolthub.com + description: Production + +# Default: every operation requires one of the supported credential types. Individual +# operations may override this (e.g. public reads) once paths are added. +security: + - personalAccessToken: [] + - oauth2: [] + +# Operation tags are registered here so renderers (Scalar) group operations consistently. +# New tags are added as resources land in subsequent phases. +tags: + - name: Database + description: DoltHub databases and their metadata. + - name: User + description: The authenticated user. + - name: Operations + description: Long-running async operations. Every async mutation returns an OperationRef; poll this resource to track progress. + +paths: + /api/v2/user: + get: + operationId: getCurrentUser + summary: Get the authenticated user. + description: Returns the profile of the user identified by the request's credentials. + tags: + - User + responses: + "200": + description: The authenticated user's profile. + headers: + x-request-id: + description: >- + The request identifier — echoed on every response (including 2xx). Reuse + the inbound `x-request-id` from the caller / edge proxy when present; + otherwise the server mints a `req_` value. + schema: + type: string + examples: + - req_2f1c9e7a-3b6d-4c5e-8a9f-0d1e2f3a4b5c + content: + application/json: + schema: + allOf: + - $ref: "#/components/schemas/Envelope" + - type: object + required: + - data + properties: + data: + $ref: "#/components/schemas/User" + "401": + $ref: "#/components/responses/Unauthorized" + "405": + $ref: "#/components/responses/MethodNotAllowed" + "500": + $ref: "#/components/responses/InternalServerError" + /api/v2/databases: + post: + operationId: createDatabase + summary: Create a database. + description: >- + Creates a database under the named owner (a user or organization). The caller's + credentials must allow creating under that owner — creating for yourself works as + long as you authenticate; creating for an organization requires membership with the + appropriate role. Returns the new `Database` resource on `201`. If a database with + the same `{owner, name}` already exists, the response is `409 Conflict`. + tags: + - Database + security: + - personalAccessToken: [] + - oauth2: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/CreateDatabaseRequest" + responses: + "201": + description: The newly-created database. + headers: + x-request-id: + description: >- + The request identifier — echoed on every response. Reuse the inbound + `x-request-id` from the caller / edge proxy when present; otherwise the + server mints a `req_` value. + schema: + type: string + examples: + - req_2f1c9e7a-3b6d-4c5e-8a9f-0d1e2f3a4b5c + content: + application/json: + schema: + allOf: + - $ref: "#/components/schemas/Envelope" + - type: object + required: + - data + properties: + data: + $ref: "#/components/schemas/Database" + "400": + $ref: "#/components/responses/BadRequest" + "401": + $ref: "#/components/responses/Unauthorized" + "403": + $ref: "#/components/responses/Forbidden" + "405": + $ref: "#/components/responses/MethodNotAllowed" + "409": + $ref: "#/components/responses/Conflict" + "500": + $ref: "#/components/responses/InternalServerError" + /api/v2/databases/{owner}/{database}: + get: + operationId: getDatabase + summary: Get a database. + description: >- + Returns the metadata for the database `{owner}/{database}`. Public databases are readable + without authentication; private databases require a credential with access (and return + `404` otherwise, so their existence isn't leaked). + tags: + - Database + # Optional auth: anonymous callers may read public databases; a token, when supplied, is + # honored for private access. The empty `{}` marks authentication as optional. + security: + - {} + - personalAccessToken: [] + - oauth2: [] + parameters: + - name: owner + in: path + required: true + description: The user or organization that owns the database. + schema: + type: string + minLength: 1 + example: dolthub + - name: database + in: path + required: true + description: The database name, unique within the owner. + schema: + type: string + minLength: 1 + example: us-jails + responses: + "200": + description: The database's metadata. + headers: + x-request-id: + description: >- + The request identifier — echoed on every response (including 2xx). Reuse + the inbound `x-request-id` from the caller / edge proxy when present; + otherwise the server mints a `req_` value. + schema: + type: string + examples: + - req_2f1c9e7a-3b6d-4c5e-8a9f-0d1e2f3a4b5c + content: + application/json: + schema: + allOf: + - $ref: "#/components/schemas/Envelope" + - type: object + required: + - data + properties: + data: + $ref: "#/components/schemas/Database" + "400": + $ref: "#/components/responses/BadRequest" + "401": + $ref: "#/components/responses/Unauthorized" + "404": + $ref: "#/components/responses/NotFound" + "405": + $ref: "#/components/responses/MethodNotAllowed" + "500": + $ref: "#/components/responses/InternalServerError" + /api/v2/databases/{owner}/{database}/branches: + get: + operationId: listBranches + summary: List branches. + description: >- + Returns the branches of the database `{owner}/{database}`, ordered by the backend. + Cursor-paginated via `page_token` (request) / `meta.next_page_token` (response); when + `next_page_token` is absent or empty there are no further pages. Public databases are + readable without authentication; private databases require a credential with access (and + return `404` otherwise, so their existence isn't leaked). + tags: + - Database + # Optional auth: anonymous callers may read public databases; a token, when supplied, is + # honored for private access. The empty `{}` marks authentication as optional. + security: + - {} + - personalAccessToken: [] + - oauth2: [] + parameters: + - name: owner + in: path + required: true + description: The user or organization that owns the database. + schema: + type: string + example: dolthub + - name: database + in: path + required: true + description: The database name, unique within the owner. + schema: + type: string + example: us-jails + - $ref: "#/components/parameters/PageToken" + responses: + "200": + description: The database's branches. + headers: + x-request-id: + description: >- + The request identifier — echoed on every response (including 2xx). Reuse + the inbound `x-request-id` from the caller / edge proxy when present; + otherwise the server mints a `req_` value. + schema: + type: string + examples: + - req_2f1c9e7a-3b6d-4c5e-8a9f-0d1e2f3a4b5c + content: + application/json: + schema: + allOf: + - $ref: "#/components/schemas/Envelope" + - type: object + required: + - data + properties: + data: + type: array + items: + $ref: "#/components/schemas/Branch" + "400": + $ref: "#/components/responses/BadRequest" + "401": + $ref: "#/components/responses/Unauthorized" + "404": + $ref: "#/components/responses/NotFound" + "405": + $ref: "#/components/responses/MethodNotAllowed" + "500": + $ref: "#/components/responses/InternalServerError" + post: + operationId: createBranch + summary: Create a branch. + description: >- + Creates a new branch in `{owner}/{database}` pointing at the source revision named + by `from`. Authentication required; the caller must have write access. Returns the + new `Branch` resource on `201`. A `409 Conflict` comes back if a branch with the + same name already exists. + tags: + - Database + security: + - personalAccessToken: [] + - oauth2: [] + parameters: + - name: owner + in: path + required: true + description: The user or organization that owns the database. + schema: + type: string + minLength: 1 + example: dolthub + - name: database + in: path + required: true + description: The database name, unique within the owner. + schema: + type: string + minLength: 1 + example: us-jails + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/CreateBranchRequest" + responses: + "201": + description: The newly-created branch. + headers: + x-request-id: + description: >- + The request identifier — echoed on every response. Reuse the inbound + `x-request-id` from the caller / edge proxy when present; otherwise the + server mints a `req_` value. + schema: + type: string + examples: + - req_2f1c9e7a-3b6d-4c5e-8a9f-0d1e2f3a4b5c + content: + application/json: + schema: + allOf: + - $ref: "#/components/schemas/Envelope" + - type: object + required: + - data + properties: + data: + $ref: "#/components/schemas/Branch" + "400": + $ref: "#/components/responses/BadRequest" + "401": + $ref: "#/components/responses/Unauthorized" + "403": + $ref: "#/components/responses/Forbidden" + "404": + $ref: "#/components/responses/NotFound" + "405": + $ref: "#/components/responses/MethodNotAllowed" + "409": + $ref: "#/components/responses/Conflict" + "500": + $ref: "#/components/responses/InternalServerError" + /api/v2/databases/{owner}/{database}/tags: + get: + operationId: listTags + summary: List tags. + description: >- + Returns the tags of the database `{owner}/{database}`, ordered by the backend. + Cursor-paginated via `page_token` (request) / `meta.next_page_token` (response); when + `next_page_token` is absent or empty there are no further pages. Public databases are + readable without authentication; private databases require a credential with access (and + return `404` otherwise, so their existence isn't leaked). + tags: + - Database + # Optional auth: anonymous callers may read public databases; a token, when supplied, is + # honored for private access. The empty `{}` marks authentication as optional. + security: + - {} + - personalAccessToken: [] + - oauth2: [] + parameters: + - name: owner + in: path + required: true + description: The user or organization that owns the database. + schema: + type: string + minLength: 1 + example: dolthub + - name: database + in: path + required: true + description: The database name, unique within the owner. + schema: + type: string + minLength: 1 + example: us-jails + - $ref: "#/components/parameters/PageToken" + responses: + "200": + description: The database's tags. + headers: + x-request-id: + description: >- + The request identifier — echoed on every response (including 2xx). Reuse + the inbound `x-request-id` from the caller / edge proxy when present; + otherwise the server mints a `req_` value. + schema: + type: string + examples: + - req_2f1c9e7a-3b6d-4c5e-8a9f-0d1e2f3a4b5c + content: + application/json: + schema: + allOf: + - $ref: "#/components/schemas/Envelope" + - type: object + required: + - data + properties: + data: + type: array + items: + $ref: "#/components/schemas/Tag" + "400": + $ref: "#/components/responses/BadRequest" + "401": + $ref: "#/components/responses/Unauthorized" + "404": + $ref: "#/components/responses/NotFound" + "405": + $ref: "#/components/responses/MethodNotAllowed" + "500": + $ref: "#/components/responses/InternalServerError" + post: + operationId: createTag + summary: Create a tag. + description: >- + Creates a new tag in `{owner}/{database}` pointing at the source revision named by + `from`. The optional `message` makes the tag annotated; omitted yields a lightweight + tag. Returns the new `Tag` resource on `201`. Authentication required; the caller + must have write access. A `409 Conflict` comes back if a tag with the same name + already exists. + tags: + - Database + security: + - personalAccessToken: [] + - oauth2: [] + parameters: + - name: owner + in: path + required: true + description: The user or organization that owns the database. + schema: + type: string + minLength: 1 + example: dolthub + - name: database + in: path + required: true + description: The database name, unique within the owner. + schema: + type: string + minLength: 1 + example: us-jails + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/CreateTagRequest" + responses: + "201": + description: The newly-created tag. + headers: + x-request-id: + description: >- + The request identifier — echoed on every response. Reuse the inbound + `x-request-id` from the caller / edge proxy when present; otherwise the + server mints a `req_` value. + schema: + type: string + examples: + - req_2f1c9e7a-3b6d-4c5e-8a9f-0d1e2f3a4b5c + content: + application/json: + schema: + allOf: + - $ref: "#/components/schemas/Envelope" + - type: object + required: + - data + properties: + data: + $ref: "#/components/schemas/Tag" + "400": + $ref: "#/components/responses/BadRequest" + "401": + $ref: "#/components/responses/Unauthorized" + "403": + $ref: "#/components/responses/Forbidden" + "404": + $ref: "#/components/responses/NotFound" + "405": + $ref: "#/components/responses/MethodNotAllowed" + "409": + $ref: "#/components/responses/Conflict" + "500": + $ref: "#/components/responses/InternalServerError" + /api/v2/databases/{owner}/{database}/forks: + get: + operationId: listForks + summary: List forks. + description: >- + Returns the databases that have been directly forked from `{owner}/{database}` — + immediate children only. Forks-of-forks are not flattened into the list; use + `fork_network_count` on the `Database` resource for the transitive total. Topology + context (`parent`, `network_root`, total `fork_network_count`) lives on the `Database` + resource. Pagination (`page_token` / `meta.next_page_token`) will be added when the + backend supports it; until then the full list is returned in one response. Public + databases are readable without authentication; private databases require a credential + with access (and return `404` otherwise, so their existence isn't leaked). + tags: + - Database + # Optional auth: anonymous callers may read public databases; a token, when supplied, is + # honored for private access. The empty `{}` marks authentication as optional. + security: + - {} + - personalAccessToken: [] + - oauth2: [] + parameters: + - name: owner + in: path + required: true + description: The user or organization that owns the database. + schema: + type: string + minLength: 1 + example: dolthub + - name: database + in: path + required: true + description: The database name, unique within the owner. + schema: + type: string + minLength: 1 + example: us-jails + responses: + "200": + description: The database's direct fork children (immediate forks only). + headers: + x-request-id: + description: >- + The request identifier — echoed on every response (including 2xx). Reuse + the inbound `x-request-id` from the caller / edge proxy when present; + otherwise the server mints a `req_` value. + schema: + type: string + examples: + - req_2f1c9e7a-3b6d-4c5e-8a9f-0d1e2f3a4b5c + content: + application/json: + schema: + allOf: + - $ref: "#/components/schemas/Envelope" + - type: object + required: + - data + properties: + data: + type: array + items: + $ref: "#/components/schemas/DatabaseRef" + "400": + $ref: "#/components/responses/BadRequest" + "401": + $ref: "#/components/responses/Unauthorized" + "404": + $ref: "#/components/responses/NotFound" + "405": + $ref: "#/components/responses/MethodNotAllowed" + "500": + $ref: "#/components/responses/InternalServerError" + post: + operationId: createFork + summary: Fork a database. + description: >- + Forks `{owner}/{database}` into `owner`'s namespace. Returns `202` with an + `OperationRef`; follow `OperationRef.href` to poll for completion (operation IDs + contain slashes and must not be interpolated raw into path templates). The caller + must have read access on the source database and may only fork into a namespace + they own. Duplicate forks (same source forked twice into the same owner) surface + as `422` via the standard error model. Authentication is required. + tags: + - Database + security: + - personalAccessToken: [] + - oauth2: [] + parameters: + - name: owner + in: path + required: true + description: The user or organization that owns the source database. + schema: + type: string + minLength: 1 + example: dolthub + - name: database + in: path + required: true + description: The source database name, unique within the owner. + schema: + type: string + minLength: 1 + example: us-jails + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/CreateForkRequest" + responses: + "202": + description: The fork operation has been accepted and is queued. + headers: + x-request-id: + description: >- + The request identifier — echoed on every response. Reuse the inbound + `x-request-id` from the caller / edge proxy when present; otherwise the + server mints a `req_` value. + schema: + type: string + examples: + - req_2f1c9e7a-3b6d-4c5e-8a9f-0d1e2f3a4b5c + content: + application/json: + schema: + allOf: + - $ref: "#/components/schemas/Envelope" + - type: object + required: + - data + properties: + data: + $ref: "#/components/schemas/OperationRef" + "400": + $ref: "#/components/responses/BadRequest" + "401": + $ref: "#/components/responses/Unauthorized" + "403": + $ref: "#/components/responses/Forbidden" + "404": + $ref: "#/components/responses/NotFound" + "405": + $ref: "#/components/responses/MethodNotAllowed" + "422": + $ref: "#/components/responses/UnprocessableEntity" + "500": + $ref: "#/components/responses/InternalServerError" + /api/v2/databases/{owner}/{database}/releases: + get: + operationId: listReleases + summary: List releases. + description: >- + Returns the releases of the database `{owner}/{database}`, ordered by the backend. + Cursor-paginated via `page_token` (request) / `meta.next_page_token` (response); when + `next_page_token` is absent or empty there are no further pages. Public databases are + readable without authentication; private databases require a credential with access + (and return `404` otherwise, so their existence isn't leaked). + tags: + - Database + security: + - {} + - personalAccessToken: [] + - oauth2: [] + parameters: + - name: owner + in: path + required: true + description: The user or organization that owns the database. + schema: + type: string + minLength: 1 + example: dolthub + - name: database + in: path + required: true + description: The database name, unique within the owner. + schema: + type: string + minLength: 1 + example: us-jails + - $ref: "#/components/parameters/PageToken" + responses: + "200": + description: The database's releases. + headers: + x-request-id: + description: >- + The request identifier — echoed on every response (including 2xx). Reuse + the inbound `x-request-id` from the caller / edge proxy when present; + otherwise the server mints a `req_` value. + schema: + type: string + examples: + - req_2f1c9e7a-3b6d-4c5e-8a9f-0d1e2f3a4b5c + content: + application/json: + schema: + allOf: + - $ref: "#/components/schemas/Envelope" + - type: object + required: + - data + properties: + data: + type: array + items: + $ref: "#/components/schemas/Release" + "400": + $ref: "#/components/responses/BadRequest" + "401": + $ref: "#/components/responses/Unauthorized" + "404": + $ref: "#/components/responses/NotFound" + "405": + $ref: "#/components/responses/MethodNotAllowed" + "500": + $ref: "#/components/responses/InternalServerError" + post: + operationId: createRelease + summary: Create a release. + description: >- + Creates a release in `{owner}/{database}` pinned to the commit named by `commit_sha` + and published under `tag`. When `create_tag_if_not_exists` is true and no tag with + that name exists, the backend creates one pointing at the same commit; otherwise the + tag must already exist and point at the same commit. Returns the new `Release` + resource on `201`. Authentication required; the caller must have write access. A + `409 Conflict` comes back if a release with the same tag already exists. + tags: + - Database + security: + - personalAccessToken: [] + - oauth2: [] + parameters: + - name: owner + in: path + required: true + description: The user or organization that owns the database. + schema: + type: string + minLength: 1 + example: dolthub + - name: database + in: path + required: true + description: The database name, unique within the owner. + schema: + type: string + minLength: 1 + example: us-jails + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/CreateReleaseRequest" + responses: + "201": + description: The newly-created release. + headers: + x-request-id: + description: >- + The request identifier — echoed on every response. Reuse the inbound + `x-request-id` from the caller / edge proxy when present; otherwise the + server mints a `req_` value. + schema: + type: string + examples: + - req_2f1c9e7a-3b6d-4c5e-8a9f-0d1e2f3a4b5c + content: + application/json: + schema: + allOf: + - $ref: "#/components/schemas/Envelope" + - type: object + required: + - data + properties: + data: + $ref: "#/components/schemas/Release" + "400": + $ref: "#/components/responses/BadRequest" + "401": + $ref: "#/components/responses/Unauthorized" + "403": + $ref: "#/components/responses/Forbidden" + "404": + $ref: "#/components/responses/NotFound" + "405": + $ref: "#/components/responses/MethodNotAllowed" + "409": + $ref: "#/components/responses/Conflict" + "500": + $ref: "#/components/responses/InternalServerError" + /api/v2/databases/{owner}/{database}/sql: + get: + operationId: runSqlReadQuery + summary: Run a read-only SQL query. + description: >- + Executes a read-only SQL query against the database at the given revision and returns + the result rows, the column schema, and the query-execution status. Read queries are + not paginated — the full row set comes back in one response, bounded by `limit` + (default 1000) and the server-enforced row cap. For larger result sets, refine the + query (`LIMIT`/`WHERE`/`SELECT` fewer columns) or use the phase-4 async SQL job. + + SQL-level errors (syntax errors, missing tables, timeouts, row-limit exceeded) come + back as `200` with `status: "error" | "timeout" | "row_limit" | "not_workspace"` and a + human-readable `message` — they are query-level conditions, not transport-level + failures. HTTP `4xx` / `5xx` are reserved for transport-level problems (auth, the + database doesn't exist, malformed request). + + Public databases are readable without authentication; private databases require a + credential with access (and return `404` otherwise, so their existence isn't leaked). + tags: + - Database + security: + - {} + - personalAccessToken: [] + - oauth2: [] + parameters: + - name: owner + in: path + required: true + description: The user or organization that owns the database. + schema: + type: string + minLength: 1 + example: dolthub + - name: database + in: path + required: true + description: The database name, unique within the owner. + schema: + type: string + minLength: 1 + example: us-jails + - name: ref + in: query + required: true + description: >- + The branch, tag, or commit hash to query against. A 32-character value using only + the characters `0-9a-v` (Dolt's base32 alphabet) is treated as a commit hash; + everything else resolves as a branch, tag, or other ref. + schema: + type: string + minLength: 1 + example: main + - name: q + in: query + required: true + description: The SQL query to execute. Read-only — use the phase-4 SQL write endpoint for mutations. + schema: + type: string + minLength: 1 + example: "SELECT name, year FROM jails LIMIT 10" + - name: limit + in: query + required: false + description: >- + Maximum number of rows to return (default `1000`). The server enforces an upper + cap; refine the query or use the async SQL job for larger result sets. + schema: + type: string + pattern: "^[1-9][0-9]*$" + example: "100" + - name: timeout_ms + in: query + required: false + description: >- + Per-query execution timeout in milliseconds (default `30000`, server-enforced + cap `60000`). A query that hits the cap returns `status: "timeout"`. + schema: + type: string + pattern: "^[1-9][0-9]*$" + example: "10000" + responses: + "200": + description: The query result. SQL-level errors live in `status` + `message`. + headers: + x-request-id: + description: >- + The request identifier — echoed on every response (including 2xx). Reuse + the inbound `x-request-id` from the caller / edge proxy when present; + otherwise the server mints a `req_` value. + schema: + type: string + examples: + - req_2f1c9e7a-3b6d-4c5e-8a9f-0d1e2f3a4b5c + content: + application/json: + schema: + allOf: + - $ref: "#/components/schemas/Envelope" + - type: object + required: + - data + properties: + data: + $ref: "#/components/schemas/QueryResult" + "400": + $ref: "#/components/responses/BadRequest" + "401": + $ref: "#/components/responses/Unauthorized" + "404": + $ref: "#/components/responses/NotFound" + "405": + $ref: "#/components/responses/MethodNotAllowed" + "500": + $ref: "#/components/responses/InternalServerError" + post: + operationId: runSqlReadQueryPost + summary: Run a read-only SQL query (large-query variant). + description: >- + Identical to `GET /sql` but accepts the query in the request body to avoid the + browser/proxy URL-length limit (~4–8 KB) that `?q=` hits for large SQL statements. + Use this when the query is too long for a query string; prefer `GET` for short queries + (simpler to cache and log). The response shape is identical. + tags: + - Database + security: + - {} + - personalAccessToken: [] + - oauth2: [] + parameters: + - name: owner + in: path + required: true + description: The user or organization that owns the database. + schema: + type: string + minLength: 1 + example: dolthub + - name: database + in: path + required: true + description: The database name, unique within the owner. + schema: + type: string + minLength: 1 + example: us-jails + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - ref + - q + properties: + ref: + type: string + minLength: 1 + description: >- + The branch, tag, or commit hash to query against. A 32-character value using + only the characters `0-9a-v` (Dolt's base32 alphabet) is treated as a commit + hash; everything else resolves as a branch, tag, or other ref. + example: main + q: + type: string + minLength: 1 + description: The SQL query to execute. Read-only — mutations are rejected. + example: "SELECT name, year FROM jails WHERE state = 'California' LIMIT 10" + limit: + type: integer + minimum: 1 + description: Maximum number of rows to return (default `1000`). + example: 100 + timeout_ms: + type: integer + minimum: 1 + description: Per-query execution timeout in milliseconds (default `30000`, cap `60000`). + example: 10000 + responses: + "200": + description: The query result. SQL-level errors live in `status` + `message`. + headers: + x-request-id: + description: >- + The request identifier — echoed on every response (including 2xx). Reuse + the inbound `x-request-id` from the caller / edge proxy when present; + otherwise the server mints a `req_` value. + schema: + type: string + examples: + - req_2f1c9e7a-3b6d-4c5e-8a9f-0d1e2f3a4b5c + content: + application/json: + schema: + allOf: + - $ref: "#/components/schemas/Envelope" + - type: object + required: + - data + properties: + data: + $ref: "#/components/schemas/QueryResult" + "400": + $ref: "#/components/responses/BadRequest" + "401": + $ref: "#/components/responses/Unauthorized" + "404": + $ref: "#/components/responses/NotFound" + "405": + $ref: "#/components/responses/MethodNotAllowed" + "500": + $ref: "#/components/responses/InternalServerError" + /api/v2/databases/{owner}/{database}/pulls: + get: + operationId: listPulls + summary: List pull requests. + description: >- + Returns the pull requests for the database `{owner}/{database}`, ordered by the backend. + Cursor-paginated via `page_token` (request) / `meta.next_page_token` (response); when + `next_page_token` is absent or empty there are no further pages. Public databases are + readable without authentication; private databases require a credential with access + (and return `404` otherwise, so their existence isn't leaked). + tags: + - Database + security: + - {} + - personalAccessToken: [] + - oauth2: [] + parameters: + - name: owner + in: path + required: true + description: The user or organization that owns the database. + schema: + type: string + minLength: 1 + example: dolthub + - name: database + in: path + required: true + description: The database name, unique within the owner. + schema: + type: string + minLength: 1 + example: us-jails + - $ref: "#/components/parameters/PageToken" + responses: + "200": + description: The database's pull requests. + headers: + x-request-id: + description: >- + The request identifier — echoed on every response (including 2xx). Reuse + the inbound `x-request-id` from the caller / edge proxy when present; + otherwise the server mints a `req_` value. + schema: + type: string + examples: + - req_2f1c9e7a-3b6d-4c5e-8a9f-0d1e2f3a4b5c + content: + application/json: + schema: + allOf: + - $ref: "#/components/schemas/Envelope" + - type: object + required: + - data + properties: + data: + type: array + items: + $ref: "#/components/schemas/PullSummary" + "400": + $ref: "#/components/responses/BadRequest" + "401": + $ref: "#/components/responses/Unauthorized" + "404": + $ref: "#/components/responses/NotFound" + "405": + $ref: "#/components/responses/MethodNotAllowed" + "500": + $ref: "#/components/responses/InternalServerError" + post: + operationId: createPull + summary: Create a pull request. + description: >- + Opens a new pull request in `{owner}/{database}`. `to_branch.database` must equal + the URL's `{owner}/{database}`. `from_branch.database` is usually the same; for a + cross-fork pull it points at a fork — in that case the caller must have read access + on the fork's database and the fork's network root must match the target. Returns + the new `Pull` resource on `201`. Authentication is required. + tags: + - Database + security: + - personalAccessToken: [] + - oauth2: [] + parameters: + - name: owner + in: path + required: true + description: The user or organization that owns the database. + schema: + type: string + minLength: 1 + example: dolthub + - name: database + in: path + required: true + description: The database name, unique within the owner. + schema: + type: string + minLength: 1 + example: us-jails + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/CreatePullRequest" + responses: + "201": + description: The newly-created pull request. + headers: + x-request-id: + description: >- + The request identifier — echoed on every response. Reuse the inbound + `x-request-id` from the caller / edge proxy when present; otherwise the + server mints a `req_` value. + schema: + type: string + examples: + - req_2f1c9e7a-3b6d-4c5e-8a9f-0d1e2f3a4b5c + content: + application/json: + schema: + allOf: + - $ref: "#/components/schemas/Envelope" + - type: object + required: + - data + properties: + data: + $ref: "#/components/schemas/Pull" + "400": + $ref: "#/components/responses/BadRequest" + "401": + $ref: "#/components/responses/Unauthorized" + "403": + $ref: "#/components/responses/Forbidden" + "404": + $ref: "#/components/responses/NotFound" + "405": + $ref: "#/components/responses/MethodNotAllowed" + "409": + $ref: "#/components/responses/Conflict" + "500": + $ref: "#/components/responses/InternalServerError" + /api/v2/databases/{owner}/{database}/pulls/{pull_number}: + get: + operationId: getPull + summary: Get a pull request. + description: >- + Returns the pull request `{pull_number}` in the database `{owner}/{database}`. Unlike + the list endpoint, the per-pull resource exposes structured `from_branch` / + `to_branch` references, each carrying the database the branch lives in — necessary to + disambiguate cross-fork pulls where the source branch lives in a different repository. + Public databases are readable without authentication; private databases require a + credential with access (and return `404` otherwise, so their existence isn't leaked). + tags: + - Database + security: + - {} + - personalAccessToken: [] + - oauth2: [] + parameters: + - name: owner + in: path + required: true + description: The user or organization that owns the database. + schema: + type: string + minLength: 1 + example: dolthub + - name: database + in: path + required: true + description: The database name, unique within the owner. + schema: + type: string + minLength: 1 + example: us-jails + - name: pull_number + in: path + required: true + description: The per-database sequential pull-request identifier (à la GitHub PR numbers). + schema: + type: string + pattern: "^[1-9][0-9]*$" + example: "42" + responses: + "200": + description: The requested pull request. + headers: + x-request-id: + description: >- + The request identifier — echoed on every response (including 2xx). Reuse + the inbound `x-request-id` from the caller / edge proxy when present; + otherwise the server mints a `req_` value. + schema: + type: string + examples: + - req_2f1c9e7a-3b6d-4c5e-8a9f-0d1e2f3a4b5c + content: + application/json: + schema: + allOf: + - $ref: "#/components/schemas/Envelope" + - type: object + required: + - data + properties: + data: + $ref: "#/components/schemas/Pull" + "400": + $ref: "#/components/responses/BadRequest" + "401": + $ref: "#/components/responses/Unauthorized" + "404": + $ref: "#/components/responses/NotFound" + "405": + $ref: "#/components/responses/MethodNotAllowed" + "500": + $ref: "#/components/responses/InternalServerError" + patch: + operationId: updatePull + summary: Update a pull request. + description: >- + Partially updates the pull request `{pull_number}` in `{owner}/{database}`. The body + carries only the fields the caller is changing — any subset of `title`, `description`, + `state`; at least one must be present. `state` is restricted to the writable + transitions (`open` ↔ `closed`); merging happens via the dedicated merge operation + (phase 4), not by writing state here. Returns the canonical `Pull` resource on `200`. + Authentication required. + tags: + - Database + security: + - personalAccessToken: [] + - oauth2: [] + parameters: + - name: owner + in: path + required: true + description: The user or organization that owns the database. + schema: + type: string + minLength: 1 + example: dolthub + - name: database + in: path + required: true + description: The database name, unique within the owner. + schema: + type: string + minLength: 1 + example: us-jails + - name: pull_number + in: path + required: true + description: The per-database sequential pull-request identifier. + schema: + type: string + pattern: "^[1-9][0-9]*$" + example: "42" + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/UpdatePullRequest" + responses: + "200": + description: The updated pull request. + headers: + x-request-id: + description: >- + The request identifier — echoed on every response. Reuse the inbound + `x-request-id` from the caller / edge proxy when present; otherwise the + server mints a `req_` value. + schema: + type: string + examples: + - req_2f1c9e7a-3b6d-4c5e-8a9f-0d1e2f3a4b5c + content: + application/json: + schema: + allOf: + - $ref: "#/components/schemas/Envelope" + - type: object + required: + - data + properties: + data: + $ref: "#/components/schemas/Pull" + "400": + $ref: "#/components/responses/BadRequest" + "401": + $ref: "#/components/responses/Unauthorized" + "403": + $ref: "#/components/responses/Forbidden" + "404": + $ref: "#/components/responses/NotFound" + "405": + $ref: "#/components/responses/MethodNotAllowed" + "500": + $ref: "#/components/responses/InternalServerError" + /api/v2/databases/{owner}/{database}/pulls/{pull_number}/comments: + get: + operationId: listPullComments + summary: List a pull request's comments. + description: >- + Returns the top-level comments on pull request `{pull_number}` in + `{owner}/{database}`, in the order the backend returns them. The backend doesn't + paginate comments today, so the full list is returned in one response; if a comment + volume hot spot appears, `page_token` / `meta.next_page_token` will be wired through + without changing the resource shape. Diff-line comments and review comments are + separate resources (not in v2 yet). Public databases are readable without + authentication; private databases require a credential with access (and return `404` + otherwise, so their existence isn't leaked). + tags: + - Database + security: + - {} + - personalAccessToken: [] + - oauth2: [] + parameters: + - name: owner + in: path + required: true + description: The user or organization that owns the database. + schema: + type: string + minLength: 1 + example: dolthub + - name: database + in: path + required: true + description: The database name, unique within the owner. + schema: + type: string + minLength: 1 + example: us-jails + - name: pull_number + in: path + required: true + description: The per-database sequential pull-request identifier (à la GitHub PR numbers). + schema: + type: string + pattern: "^[1-9][0-9]*$" + example: "42" + responses: + "200": + description: The pull request's comments. + headers: + x-request-id: + description: >- + The request identifier — echoed on every response (including 2xx). Reuse + the inbound `x-request-id` from the caller / edge proxy when present; + otherwise the server mints a `req_` value. + schema: + type: string + examples: + - req_2f1c9e7a-3b6d-4c5e-8a9f-0d1e2f3a4b5c + content: + application/json: + schema: + allOf: + - $ref: "#/components/schemas/Envelope" + - type: object + required: + - data + properties: + data: + type: array + items: + $ref: "#/components/schemas/PullComment" + "400": + $ref: "#/components/responses/BadRequest" + "401": + $ref: "#/components/responses/Unauthorized" + "404": + $ref: "#/components/responses/NotFound" + "405": + $ref: "#/components/responses/MethodNotAllowed" + "500": + $ref: "#/components/responses/InternalServerError" + post: + operationId: createPullComment + summary: Add a top-level comment to a pull request. + description: >- + Posts a new top-level comment on pull request `{pull_number}` in + `{owner}/{database}`. The body carries only the comment text; author and timestamps + are server-assigned from the authenticated caller and the server clock. Returns the + new `PullComment` on `201`. Diff-line and review comments are separate resources + (not in v2 yet). + tags: + - Database + security: + - personalAccessToken: [] + - oauth2: [] + parameters: + - name: owner + in: path + required: true + description: The user or organization that owns the database. + schema: + type: string + minLength: 1 + example: dolthub + - name: database + in: path + required: true + description: The database name, unique within the owner. + schema: + type: string + minLength: 1 + example: us-jails + - name: pull_number + in: path + required: true + description: The per-database sequential pull-request identifier. + schema: + type: string + pattern: "^[1-9][0-9]*$" + example: "42" + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/CreatePullCommentRequest" + responses: + "201": + description: The newly-created comment. + headers: + x-request-id: + description: >- + The request identifier — echoed on every response. Reuse the inbound + `x-request-id` from the caller / edge proxy when present; otherwise the + server mints a `req_` value. + schema: + type: string + examples: + - req_2f1c9e7a-3b6d-4c5e-8a9f-0d1e2f3a4b5c + content: + application/json: + schema: + allOf: + - $ref: "#/components/schemas/Envelope" + - type: object + required: + - data + properties: + data: + $ref: "#/components/schemas/PullComment" + "400": + $ref: "#/components/responses/BadRequest" + "401": + $ref: "#/components/responses/Unauthorized" + "403": + $ref: "#/components/responses/Forbidden" + "404": + $ref: "#/components/responses/NotFound" + "405": + $ref: "#/components/responses/MethodNotAllowed" + "500": + $ref: "#/components/responses/InternalServerError" + /api/v2/databases/{owner}/{database}/imports/uploads: + post: + operationId: createImportUpload + summary: Initialize a multipart upload for an import. + description: >- + Starts a multipart upload session and returns the pre-signed part URLs the client + uses to upload the source file directly to object storage. Once every part is + uploaded, call `POST /api/v2/databases/{owner}/{database}/imports` with the returned + `token`, `contents_key`, and the collected `completed_parts` to create the import + operation. Authentication is required. + tags: + - Database + security: + - personalAccessToken: [] + - oauth2: [] + parameters: + - name: owner + in: path + required: true + description: The user or organization that owns the database. + schema: + type: string + minLength: 1 + example: dolthub + - name: database + in: path + required: true + description: The database name, unique within the owner. + schema: + type: string + minLength: 1 + example: us-jails + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/CreateImportUploadRequest" + responses: + "201": + description: The multipart upload session. + headers: + x-request-id: + description: >- + The request identifier — echoed on every response. Reuse the inbound + `x-request-id` from the caller / edge proxy when present; otherwise the + server mints a `req_` value. + schema: + type: string + examples: + - req_2f1c9e7a-3b6d-4c5e-8a9f-0d1e2f3a4b5c + content: + application/json: + schema: + allOf: + - $ref: "#/components/schemas/Envelope" + - type: object + required: + - data + properties: + data: + $ref: "#/components/schemas/ImportUpload" + "400": + $ref: "#/components/responses/BadRequest" + "401": + $ref: "#/components/responses/Unauthorized" + "403": + $ref: "#/components/responses/Forbidden" + "404": + $ref: "#/components/responses/NotFound" + "405": + $ref: "#/components/responses/MethodNotAllowed" + "500": + $ref: "#/components/responses/InternalServerError" + /api/v2/databases/{owner}/{database}/imports: + post: + operationId: createImport + summary: Create an import operation. + description: >- + Imports the previously-uploaded file into `{owner}/{database}` as the table named + in the body. The upload (token, contents_key, and the parts uploaded against the + URLs returned by `POST .../imports/uploads`) must already be complete; the import + itself runs asynchronously. Returns `202` + an `OperationRef`; poll + `GET /api/v2/operations/{id}` until `status` is `succeeded` or `failed`. + Authentication is required. + tags: + - Database + security: + - personalAccessToken: [] + - oauth2: [] + parameters: + - name: owner + in: path + required: true + description: The user or organization that owns the database. + schema: + type: string + minLength: 1 + example: dolthub + - name: database + in: path + required: true + description: The database name, unique within the owner. + schema: + type: string + minLength: 1 + example: us-jails + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/CreateImportRequest" + responses: + "202": + description: The import operation has been accepted and is queued. + headers: + x-request-id: + description: >- + The request identifier — echoed on every response. Reuse the inbound + `x-request-id` from the caller / edge proxy when present; otherwise the + server mints a `req_` value. + schema: + type: string + examples: + - req_2f1c9e7a-3b6d-4c5e-8a9f-0d1e2f3a4b5c + content: + application/json: + schema: + allOf: + - $ref: "#/components/schemas/Envelope" + - type: object + required: + - data + properties: + data: + $ref: "#/components/schemas/OperationRef" + "400": + $ref: "#/components/responses/BadRequest" + "401": + $ref: "#/components/responses/Unauthorized" + "403": + $ref: "#/components/responses/Forbidden" + "404": + $ref: "#/components/responses/NotFound" + "405": + $ref: "#/components/responses/MethodNotAllowed" + "500": + $ref: "#/components/responses/InternalServerError" + /api/v2/databases/{owner}/{database}/pulls/{pull_number}/merge: + post: + operationId: mergePull + summary: Merge a pull request. + description: >- + Kicks off a merge of pull `{pull_number}` in `{owner}/{database}`. Returns `202` + with an `OperationRef`; poll `GET /api/v2/operations/{id}` until `status` is + `succeeded` (the operation's `result.pull_id` echoes the merged pull) or `failed`. + The caller must have write access on the database. Preconditions like "pull is + already merged" or "has conflicts" surface as `422` via the standard error model + rather than being pre-checked here. Authentication is required. + tags: + - Database + security: + - personalAccessToken: [] + - oauth2: [] + parameters: + - name: owner + in: path + required: true + description: The user or organization that owns the database. + schema: + type: string + minLength: 1 + example: dolthub + - name: database + in: path + required: true + description: The database name, unique within the owner. + schema: + type: string + minLength: 1 + example: us-jails + - name: pull_number + in: path + required: true + description: The pull request number (per-database sequential id). + schema: + type: string + pattern: "^[1-9][0-9]*$" + example: "42" + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/MergePullRequest" + responses: + "202": + description: The merge operation has been accepted and is queued. + headers: + x-request-id: + description: >- + The request identifier — echoed on every response. Reuse the inbound + `x-request-id` from the caller / edge proxy when present; otherwise the + server mints a `req_` value. + schema: + type: string + examples: + - req_2f1c9e7a-3b6d-4c5e-8a9f-0d1e2f3a4b5c + content: + application/json: + schema: + allOf: + - $ref: "#/components/schemas/Envelope" + - type: object + required: + - data + properties: + data: + $ref: "#/components/schemas/OperationRef" + "400": + $ref: "#/components/responses/BadRequest" + "401": + $ref: "#/components/responses/Unauthorized" + "403": + $ref: "#/components/responses/Forbidden" + "404": + $ref: "#/components/responses/NotFound" + "405": + $ref: "#/components/responses/MethodNotAllowed" + "422": + $ref: "#/components/responses/UnprocessableEntity" + "500": + $ref: "#/components/responses/InternalServerError" + /api/v2/databases/{owner}/{database}/operations: + get: + operationId: listOperations + summary: List a database's async operations. + description: >- + Returns the async operations (imports, merges, SQL writes, forks, …) recorded against + the database `{owner}/{database}`, ordered by the backend. Cursor-paginated via + `page_token` (request) / `meta.next_page_token` (response); when `next_page_token` is + absent or empty there are no further pages. Public databases are readable without + authentication; private databases require a credential with access (and return `404` + otherwise, so their existence isn't leaked). Each entry is the same `Operation` shape + `GET /api/v2/operations/{id}` returns — `data[i].id` is what you pass to that endpoint + to re-poll a single operation. + tags: + - Operations + security: + - {} + - personalAccessToken: [] + - oauth2: [] + parameters: + - name: owner + in: path + required: true + description: The user or organization that owns the database. + schema: + type: string + minLength: 1 + example: dolthub + - name: database + in: path + required: true + description: The database name, unique within the owner. + schema: + type: string + minLength: 1 + example: us-jails + - $ref: "#/components/parameters/PageToken" + responses: + "200": + description: The database's async operations. + headers: + x-request-id: + description: >- + The request identifier — echoed on every response (including 2xx). Reuse + the inbound `x-request-id` from the caller / edge proxy when present; + otherwise the server mints a `req_` value. + schema: + type: string + examples: + - req_2f1c9e7a-3b6d-4c5e-8a9f-0d1e2f3a4b5c + content: + application/json: + schema: + allOf: + - $ref: "#/components/schemas/Envelope" + - type: object + required: + - data + properties: + data: + type: array + items: + $ref: "#/components/schemas/Operation" + "400": + $ref: "#/components/responses/BadRequest" + "401": + $ref: "#/components/responses/Unauthorized" + "404": + $ref: "#/components/responses/NotFound" + "405": + $ref: "#/components/responses/MethodNotAllowed" + "500": + $ref: "#/components/responses/InternalServerError" + /api/v2/operations/{operation_id}: + get: + operationId: getOperation + summary: Get an async operation. + description: >- + Polls a long-running operation by its `id`. Every async mutation (SQL write, import, + merge, fork) returns an `OperationRef` in its `202` response; clients poll this + endpoint until `status` is `succeeded` or `failed`. The `id` is the job resource + name returned by the backend. + tags: + - Operations + parameters: + - name: operation_id + in: path + required: true + description: The operation ID returned in an `OperationRef`. + schema: + type: string + minLength: 1 + example: owners/dolthub/repos/us-jails/jobs/abc123 + responses: + "200": + description: The current state of the operation. + headers: + x-request-id: + description: Echoes the inbound `x-request-id`, or a server-generated `req_*` UUID. + schema: + type: string + content: + application/json: + schema: + allOf: + - $ref: "#/components/schemas/Envelope" + - type: object + required: + - data + properties: + data: + $ref: "#/components/schemas/Operation" + "401": + $ref: "#/components/responses/Unauthorized" + "403": + $ref: "#/components/responses/Forbidden" + "404": + $ref: "#/components/responses/NotFound" + "405": + $ref: "#/components/responses/MethodNotAllowed" + "500": + $ref: "#/components/responses/InternalServerError" + +components: + # securitySchemes model the credential types the v2 auth layer accepts (§5.5). Personal + # access tokens and OAuth access tokens are both presented in the `Authorization` header. + # The public API does not support browser session cookies. + securitySchemes: + personalAccessToken: + type: http + scheme: bearer + description: "A DoltHub personal access token, sent as `Authorization: Bearer `." + oauth2: + type: oauth2 + description: "A DoltHub OAuth 2.0 access token, sent as `Authorization: Bearer `." + flows: + authorizationCode: + authorizationUrl: https://www.dolthub.com/oauth/authorize + tokenUrl: https://www.dolthub.com/oauth/token + scopes: {} + + schemas: + # --- Error model (1.c, §5.3) --------------------------------------------------------- + # Every non-2xx response uses Problem (RFC 9457). The Operation resource (1.e) is added + # to this map by its PR. + ErrorCode: + type: string + title: ErrorCode + description: >- + A stable, machine-readable error code in SCREAMING_SNAKE_CASE. Clients branch on + this value, never on the human-readable `title`/`detail` prose. The baseline codes + below cover the standard HTTP failure categories; endpoint-specific codes (e.g. + `BRANCH_NOT_FOUND`) are appended to this enum alongside the endpoints that emit them, + which is an additive, non-breaking change under the v2 stability policy (§5.1). + enum: + - VALIDATION_FAILED # 400 — malformed request or failed input validation + - UNAUTHENTICATED # 401 — missing or invalid credentials + - PERMISSION_DENIED # 403 — authenticated but not permitted + - NOT_FOUND # 404 — resource does not exist + - METHOD_NOT_ALLOWED # 405 — HTTP method not supported for this resource + - CONFLICT # 409 — conflicts with current state (e.g. already exists) + - UNPROCESSABLE # 422 — well-formed but semantically invalid + - RATE_LIMITED # 429 — rate limit exceeded + - INTERNAL # 500 — unexpected server fault + - SERVICE_UNAVAILABLE # 503 — temporarily unavailable + - OPERATION_FAILED # operation reached terminal failure state + examples: + - NOT_FOUND + Problem: + type: object + title: Problem + description: >- + A structured error body returned for every non-2xx response, following RFC 9457 + (Problem Details for HTTP APIs). This is the single error model for the entire v2 + API — there are no ad-hoc error shapes. + required: + - title + - status + - code + - request_id + properties: + type: + type: string + format: uri + default: about:blank + description: >- + A URI identifying the problem type; when dereferenced it points at + human-readable documentation for the error. + examples: + - https://dolthub.com/docs/api/errors/not-found + title: + type: string + description: A short, human-readable summary of the problem type. + examples: + - Not found + status: + type: integer + format: int32 + minimum: 400 + maximum: 599 + description: The HTTP status code, repeated in the body for convenience. + examples: + - 404 + detail: + type: string + description: A human-readable explanation specific to this occurrence of the problem. + examples: + - "Branch 'main' does not exist in dolthub/us-jails" + instance: + type: string + format: uri-reference + description: A URI reference identifying the specific occurrence (typically the request path). + examples: + - /api/v2/databases/dolthub/us-jails/branches/main + code: + $ref: "#/components/schemas/ErrorCode" + request_id: + type: string + description: >- + The request identifier, echoed on every response. Include it when contacting + support so a request can be traced end-to-end. + examples: + - req_01HZX9P7Q5N2M8 + additionalProperties: true + examples: + - type: https://dolthub.com/docs/api/errors/not-found + title: Not found + status: 404 + detail: "Branch 'main' does not exist in dolthub/us-jails" + instance: /api/v2/databases/dolthub/us-jails/branches/main + code: NOT_FOUND + request_id: req_01HZX9P7Q5N2M8 + + # --- Success envelope (1.d, §5.4) ---------------------------------------------------- + # Every 2xx response body is enveloped: the resource (or list) under `data`, with + # optional response metadata under `meta`. Concrete endpoint responses specialize the + # envelope by narrowing `data` to a specific resource via `allOf`, e.g.: + # + # responses: + # "200": + # content: + # application/json: + # schema: + # allOf: + # - $ref: "#/components/schemas/Envelope" + # - type: object + # properties: + # data: + # $ref: "#/components/schemas/User" + # + # The base types `data` only loosely (object or array) so this allOf narrowing composes + # cleanly ((object|array) ∩ User = User). The first real use is GET /api/v2/user in 1.t. + Meta: + type: object + title: Meta + description: >- + Response metadata carried alongside the primary `data` payload. All fields are + optional; list endpoints populate `next_page_token` for cursor pagination (§5.6). + properties: + next_page_token: + type: string + description: >- + Opaque cursor for the next page of a list response. Absent or empty when there + are no further results; otherwise pass it back as the `page_token` query + parameter to fetch the next page. + examples: + - eyJvZmZzZXQiOjI1fQ + additionalProperties: true + examples: + - next_page_token: eyJvZmZzZXQiOjI1fQ + Envelope: + type: object + title: Envelope + description: >- + The success envelope wrapping every 2xx response body (§5.4): the resource or list of + resources under `data`, with optional `meta`. This is the single success shape for + the API — there are no unenveloped success bodies. Endpoints narrow `data` to a + concrete resource via `allOf` (see the section comment above); the base leaves `data` + unconstrained so that composition works. + required: + - data + properties: + data: + type: [object, array] + description: The primary response payload — a resource, or an array of resources for list endpoints. + meta: + $ref: "#/components/schemas/Meta" + examples: + - data: + username: dolthub + meta: + next_page_token: eyJvZmZzZXQiOjI1fQ + + # --- Resources (1.t onward) ---------------------------------------------------------- + # Resource schemas are the public DTO surface — what the v2 spec contract guarantees to + # integrators. Field names are snake_case (§5.2). Fields are added additively under the + # v2 stability policy (§5.1); renames or removals require v3. + DatabaseRef: + type: object + title: DatabaseRef + description: >- + A minimal reference to a database — owner and name only. Used wherever the API points + at another database (a fork's parent, a network's root, an item in the forks list) + without re-embedding the full Database resource. + required: + - owner + - name + properties: + owner: + type: string + description: The user or organization that owns the referenced database. + examples: + - dolthub + name: + type: string + description: The referenced database's name. + examples: + - us-jails + examples: + - owner: dolthub + name: us-jails + CreateDatabaseRequest: + type: object + title: CreateDatabaseRequest + description: >- + Body for `POST /api/v2/databases`. `owner` names the user or organization that will + own the new database; the caller's credentials must allow creating under that owner. + required: + - owner + - name + - visibility + properties: + owner: + type: string + description: The user or organization that will own the database. + minLength: 1 + examples: + - dolthub + name: + type: string + description: >- + The database name. Must be unique within the owner and conform to DoltHub's + naming rules (letters, digits, `-`, `_`; cannot start or end with `-`). + minLength: 1 + examples: + - us-jails + description: + type: string + description: Optional human-readable description. + examples: + - Open data about incarceration in the United States. + visibility: + type: string + enum: + - public + - private + description: >- + Whether the database is publicly readable. Defaults are *not* applied — clients + must declare the intended visibility on create. + examples: + - public + additionalProperties: false + examples: + - owner: dolthub + name: us-jails + description: Open data about incarceration in the United States. + visibility: public + CreatePullRequest: + type: object + title: CreatePullRequest + description: >- + Body for `POST /api/v2/databases/{owner}/{database}/pulls`. `to_branch.database` + must equal the URL's `{owner}/{database}` (the PR opens against this repo); + `from_branch.database` is usually the same but may point at a fork for cross-fork + PRs. + required: + - title + - from_branch + - to_branch + properties: + title: + type: string + description: The pull request's title. + minLength: 1 + examples: + - Fix join planner regression + description: + type: string + description: Optional pull-request body (markdown). + examples: + - "Fixes #99." + from_branch: + $ref: "#/components/schemas/BranchRef" + to_branch: + $ref: "#/components/schemas/BranchRef" + examples: + - title: Fix join planner regression + description: "Fixes #99." + from_branch: + database: { owner: dolthub, name: us-jails } + branch_name: my-feature + to_branch: + database: { owner: dolthub, name: us-jails } + branch_name: main + CreatePullCommentRequest: + type: object + title: CreatePullCommentRequest + description: >- + Body for `POST /api/v2/databases/{owner}/{database}/pulls/{pull_number}/comments`. + Carries only the comment text; author and timestamps are server-assigned. + required: + - body + properties: + body: + type: string + description: The comment text (markdown). + minLength: 1 + examples: + - "LGTM — one nit on the join planner case." + additionalProperties: false + examples: + - body: "LGTM — one nit on the join planner case." + MergePullRequest: + type: object + title: MergePullRequest + description: >- + Body for `POST /api/v2/databases/{owner}/{database}/pulls/{pull_number}/merge`. + Currently empty — the merge takes no parameters today. The empty object exists so + the schema is closed under `additionalProperties` (mistyped fields fail loud + rather than getting silently dropped) and so we have a stable place to add the + conflict-resolution strategy when that ships. + additionalProperties: false + CreateForkRequest: + type: object + title: CreateForkRequest + description: >- + Body for `POST /api/v2/databases/{owner}/{database}/forks`. The URL identifies the + source database; `owner` is the user or organization that will own the new fork. + The new fork inherits the source database's name. Forking into a namespace the + caller does not own returns `403`. + required: + - owner + properties: + owner: + type: string + minLength: 1 + description: The user or organization that will own the new fork. + examples: + - taylor + additionalProperties: false + UpdatePullRequest: + type: object + title: UpdatePullRequest + description: >- + Body for `PATCH /api/v2/databases/{owner}/{database}/pulls/{pull_number}`. Every + field is optional; the caller supplies whichever fields they're changing and the + server only updates those. At least one field must be present. `state` is restricted + to the writable transitions (`open` ↔ `closed`); to merge, use the merge operation. + minProperties: 1 + properties: + title: + type: string + description: New title; omit to leave unchanged. + minLength: 1 + examples: + - Fix join planner regression — addresses regression #99 + description: + type: string + description: New description body (markdown); omit to leave unchanged. + examples: + - "Updated to cover the additional edge case from review." + state: + type: string + enum: + - open + - closed + description: New state. Merging is a separate operation; this field can't transition to `merged`. + examples: + - closed + additionalProperties: false + examples: + - state: closed + - title: New title + description: New body. + CreateBranchRequest: + type: object + title: CreateBranchRequest + description: >- + Body for `POST /api/v2/databases/{owner}/{database}/branches`. `from` is a + discriminated union — one of `{ branch }` or `{ commit }` — that names the source + revision the new branch will point at. + required: + - name + - from + properties: + name: + type: string + description: The new branch's name. + minLength: 1 + examples: + - feature-x + from: + oneOf: + - type: object + required: + - branch + properties: + branch: + type: string + description: Branch the new branch will fork from. + minLength: 1 + examples: + - main + additionalProperties: false + - type: object + required: + - commit + properties: + commit: + type: string + description: Commit hash the new branch will start at. + minLength: 1 + examples: + - vt1u8gdsovtj0qq2qmd6he7n5o4mq2qm + additionalProperties: false + additionalProperties: false + examples: + - name: feature-x + from: + branch: main + - name: hotfix + from: + commit: vt1u8gdsovtj0qq2qmd6he7n5o4mq2qm + CreateTagRequest: + type: object + title: CreateTagRequest + description: >- + Body for `POST /api/v2/databases/{owner}/{database}/tags`. `from` is the same + `{ branch | commit }` discriminated union used by `CreateBranchRequest`. Supplying + `message` produces an annotated tag; omitting it produces a lightweight tag. + required: + - name + - from + properties: + name: + type: string + description: The new tag's name, unique within the database. + minLength: 1 + examples: + - v1.0.0 + from: + oneOf: + - type: object + required: + - branch + properties: + branch: + type: string + description: Branch whose head the tag will point at. + minLength: 1 + examples: + - main + additionalProperties: false + - type: object + required: + - commit + properties: + commit: + type: string + description: Commit hash the tag will point at. + minLength: 1 + examples: + - vt1u8gdsovtj0qq2qmd6he7n5o4mq2qm + additionalProperties: false + message: + type: string + description: Optional annotation message. Present → annotated tag; absent → lightweight tag. + examples: + - First public release. + additionalProperties: false + examples: + - name: v1.0.0 + from: + branch: main + message: First public release. + - name: hotfix-tag + from: + commit: vt1u8gdsovtj0qq2qmd6he7n5o4mq2qm + CreateReleaseRequest: + type: object + title: CreateReleaseRequest + description: >- + Body for `POST /api/v2/databases/{owner}/{database}/releases`. Releases pin to a + specific commit (`commit_sha`), not a moving branch. The release is published under + `tag`; `create_tag_if_not_exists` lets the backend create that tag implicitly when it + doesn't already exist, otherwise the tag must already point at `commit_sha`. + required: + - tag + - title + - commit_sha + properties: + tag: + type: string + description: The tag the release is published under, unique within the database. + minLength: 1 + examples: + - v1.0.0 + title: + type: string + description: Human-readable title. + minLength: 1 + examples: + - First public release + commit_sha: + type: string + description: The commit hash the release points at. + minLength: 1 + examples: + - vt1u8gdsovtj0qq2qmd6he7n5o4mq2qm + description: + type: string + description: Optional release notes body (markdown). + examples: + - "## Highlights\n- new join planner" + create_tag_if_not_exists: + type: boolean + description: >- + When true and no tag named `tag` exists, create one pointing at `commit_sha`. + Defaults to false — the caller is responsible for tag creation otherwise. + examples: + - true + additionalProperties: false + examples: + - tag: v1.0.0 + title: First public release + commit_sha: vt1u8gdsovtj0qq2qmd6he7n5o4mq2qm + description: "## Highlights\n- new join planner" + create_tag_if_not_exists: true + ImportFileType: + type: string + title: ImportFileType + description: Source file format for an import. + enum: + - csv + - psv + - xlsx + - json + - sql + - yaml + examples: + - csv + ImportOperation: + type: string + title: ImportOperation + description: >- + How the imported rows are applied to the target table. `create` requires the table + not to exist; `overwrite` replaces it; `update` upserts into an existing table; + `replace` truncates then inserts. + enum: + - create + - overwrite + - update + - replace + examples: + - create + CompletedPart: + type: object + title: CompletedPart + description: One part of a multipart upload, identified by its part number and the ETag the storage backend returned. + required: + - part_number + - etag + properties: + part_number: + type: integer + minimum: 1 + description: The 1-based part number this entry corresponds to. + examples: + - 1 + etag: + type: string + minLength: 1 + description: The ETag returned by the storage backend for this part. + examples: + - '"d41d8cd98f00b204e9800998ecf8427e"' + additionalProperties: false + ImportUploadPart: + type: object + title: ImportUploadPart + description: A single part in an upload session — the part number plus the pre-signed URL to PUT it to. + required: + - part_number + - url + properties: + part_number: + type: integer + minimum: 1 + description: The 1-based part number. + examples: + - 1 + url: + type: string + format: uri + description: Pre-signed URL the client should upload this part to. + additionalProperties: false + ImportUpload: + type: object + title: ImportUpload + description: >- + A multipart upload session. The client PUTs each file chunk to the matching `parts[].url`, + collects the storage backend's ETag for each, and then calls `createImport` with the `token`, + `contents_key`, and the collected `CompletedPart`s. + required: + - token + - contents_key + - parts + - http_method + - headers + properties: + token: + type: string + description: Opaque upload-session token. Pass verbatim to `createImport`. + examples: + - upload-tok-9f3... + contents_key: + type: string + description: Storage key the assembled file will live at. Pass verbatim to `createImport`. + examples: + - imports/abc-def/states.csv + parts: + type: array + description: One entry per part, in part-number order. + items: + $ref: "#/components/schemas/ImportUploadPart" + http_method: + type: string + description: HTTP method to use when uploading each part. Currently always `PUT`. + enum: + - PUT + examples: + - PUT + headers: + type: object + description: >- + Headers the client must include on each part upload (e.g. proxy-auth, + signed-headers added by the storage backend). Usually empty; clients + should iterate every entry and add each name with all of its values to + the part-upload request. Each header may have multiple values. + additionalProperties: + type: array + items: + type: string + examples: + - {} + additionalProperties: false + CreateImportUploadRequest: + type: object + title: CreateImportUploadRequest + description: >- + Body for `POST /api/v2/databases/{owner}/{database}/imports/uploads`. Asks the + server to mint a multipart upload session for a file of `content_length` bytes + split into `num_parts` parts; the response carries the pre-signed URLs to upload to. + required: + - content_length + - num_parts + - file_type + properties: + content_length: + type: integer + format: int64 + minimum: 1 + description: Total size of the file being uploaded, in bytes. + examples: + - 1048576 + num_parts: + type: integer + minimum: 1 + description: Number of parts the client will split the upload into. + examples: + - 4 + file_type: + $ref: "#/components/schemas/ImportFileType" + additionalProperties: false + examples: + - content_length: 1048576 + num_parts: 4 + file_type: csv + CreateImportRequest: + type: object + title: CreateImportRequest + description: >- + Body for `POST /api/v2/databases/{owner}/{database}/imports`. Wraps a completed + multipart upload (`token`, `contents_key`, `completed_parts`) into an import job + that loads the file into `table_name` on `branch_name`. Returns `202` + an + `OperationRef`. + required: + - branch_name + - table_name + - file_name + - file_size + - file_type + - import_operation + - token + - contents_key + - completed_parts + - file_parts_md5 + - primary_keys + properties: + branch_name: + type: string + minLength: 1 + description: The branch to import onto. + examples: + - main + table_name: + type: string + minLength: 1 + description: The destination table. + examples: + - states + file_name: + type: string + minLength: 1 + description: The original file name (used for the commit message and import description). + examples: + - states.csv + file_size: + type: integer + format: int64 + minimum: 1 + description: Size of the uploaded file in bytes; must match the `content_length` from `createImportUpload`. + examples: + - 1048576 + file_type: + $ref: "#/components/schemas/ImportFileType" + import_operation: + $ref: "#/components/schemas/ImportOperation" + token: + type: string + minLength: 1 + description: Upload-session token from `createImportUpload`. + examples: + - upload-tok-9f3... + contents_key: + type: string + minLength: 1 + description: Contents key from `createImportUpload`. + examples: + - imports/abc-def/states.csv + completed_parts: + type: array + description: One entry per uploaded part, in any order. + items: + $ref: "#/components/schemas/CompletedPart" + minItems: 1 + file_parts_md5: + type: string + minLength: 1 + description: >- + MD5 of the concatenated per-part MD5s, base64-encoded. Some backends require + this for integrity verification of the assembled file. + examples: + - hT39yyZyRkX... + primary_keys: + type: array + description: >- + Primary-key column names. May be empty when the destination table already exists + (its existing primary keys are used). Required (possibly empty) so a missing + field fails fast rather than mis-importing as no-primary-key. + items: + type: string + minLength: 1 + examples: + - - id + - date + commit_message: + type: string + description: Override the default commit message the import produces. + examples: + - Initial load of US states. + pull_request_branch_name: + type: string + minLength: 1 + description: >- + When set, the import lands on this branch (created from `branch_name`) and a + pull request is opened against `branch_name`. When unset, the import lands + directly on `branch_name`. + examples: + - import/states-2026-06-23 + column_map: + type: object + description: >- + Optional mapping from source column names to destination column names. Useful + when the file's columns don't match the target table's columns. + additionalProperties: + type: string + additionalProperties: false + examples: + - branch_name: main + table_name: states + file_name: states.csv + file_size: 1048576 + file_type: csv + import_operation: create + token: upload-tok-9f3... + contents_key: imports/abc-def/states.csv + completed_parts: + - part_number: 1 + etag: '"d41d8cd98f00b204e9800998ecf8427e"' + file_parts_md5: hT39yyZyRkX... + primary_keys: + - id + OperationStatus: + type: string + title: OperationStatus + description: The lifecycle state of an async operation. + enum: + - queued + - running + - succeeded + - failed + examples: + - running + + OperationType: + type: string + title: OperationType + description: The kind of work this operation performs. + enum: + - import + - merge + - sql_write + - fork + - dolt_ci + examples: + - merge + + OperationError: + type: object + title: OperationError + description: Error details recorded when an operation reaches the `failed` status. + required: + - status + - code + - title + properties: + status: + type: integer + format: int32 + minimum: 400 + maximum: 599 + description: HTTP-equivalent status code for the failure. + examples: + - 422 + code: + $ref: "#/components/schemas/ErrorCode" + title: + type: string + description: A short, human-readable summary of the failure. + examples: + - Unprocessable + detail: + type: string + description: >- + A human-readable explanation of the failure, sourced from the underlying + operation error message when available. + examples: + - "Error 1213 (40001): serialization failure: this transaction conflicts with a committed transaction from another client, try restarting transaction" + + Operation: + type: object + title: Operation + description: >- + A long-running async operation. Every async mutation returns an `OperationRef`; poll + `GET /api/v2/operations/{id}` until `status` is `succeeded` or `failed`. The `id` is + opaque — pass it back to the poll endpoint verbatim. + required: + - id + - type + - status + - created_at + - cancelable + properties: + id: + type: string + description: >- + Opaque operation identifier. Pass verbatim to `GET /api/v2/operations/{id}`. + examples: + - owners/dolthub/repos/us-jails/jobs/abc123 + type: + $ref: "#/components/schemas/OperationType" + status: + $ref: "#/components/schemas/OperationStatus" + created_at: + type: string + format: date-time + description: When the operation was enqueued. + examples: + - "2026-06-01T12:00:00Z" + cancelable: + type: boolean + description: >- + Reserved for a future cancel endpoint. Always `false` today — + no `POST /api/v2/operations/{id}/cancel` exists yet. + examples: + - false + error: + $ref: "#/components/schemas/OperationError" + result: + type: object + description: >- + Present when `status` is `succeeded`. Shape depends on `type`: + `import`/`merge` → `{ pull_id }`; + `sql_write` → `{ commit_sha }`; + `fork` → `{ database: { owner, name } }`. + additionalProperties: true + + OperationRef: + type: object + title: OperationRef + description: >- + A reference to an in-progress async operation, returned in `202` responses. + Pass `id` to `GET /api/v2/operations/{id}` to poll for completion. + required: + - id + - href + properties: + id: + type: string + description: The operation ID. + examples: + - owners/dolthub/repos/us-jails/jobs/abc123 + href: + type: string + format: uri + description: Absolute URL of the poll endpoint. + examples: + - https://www.dolthub.com/api/v2/operations/owners%2Fdolthub%2Frepos%2Fus-jails%2Fjobs%2Fabc123 + + Database: + type: object + title: Database + description: >- + A DoltHub database and its public metadata. v2 exposes the database's own + fields; caller-specific state (your role on it, whether you've starred it) is not part of + this resource. + required: + - owner + - name + - visibility + - fork_network_count + - star_count + - size_bytes + properties: + owner: + type: string + description: The user or organization that owns the database. + examples: + - dolthub + name: + type: string + description: The database name, unique within the owner. + examples: + - us-jails + description: + type: string + description: The database's short description. + examples: + - Open data about incarceration in the United States. + visibility: + type: string + enum: + - public + - private + description: Whether the database is publicly readable or private. + examples: + - public + fork_network_count: + type: integer + format: int32 + description: >- + The total number of databases in this database's fork network — transitive, + counting forks-of-forks. The `/forks` endpoint returns immediate children + only, so `fork_network_count` may exceed the length of that list. + star_count: + type: integer + format: int32 + description: The number of users who have starred the database. + size_bytes: + type: integer + format: int64 + description: The on-disk size of the database, in bytes. + last_write_at: + type: string + format: date-time + description: When the database last received a write. + examples: + - "2024-01-15T12:34:56Z" + parent: + allOf: + - $ref: "#/components/schemas/DatabaseRef" + description: >- + The database this one was forked from. Omitted when this database is not a fork — + i.e., it is the root of its fork network. + network_root: + allOf: + - $ref: "#/components/schemas/DatabaseRef" + description: >- + The original database at the root of this database's fork network. Omitted when + this database is itself the root (no ancestors). + examples: + - owner: dolthub + name: us-jails + description: Open data about incarceration in the United States. + visibility: public + fork_network_count: 3 + star_count: 42 + size_bytes: 10485760 + last_write_at: "2024-01-15T12:34:56Z" + Branch: + type: object + title: Branch + description: >- + A branch in a database — a named pointer to a head commit. v2 exposes the branch's + identity (name) and the head it currently points at; the head commit's full metadata + (message, author, parents) belongs to the commit resource, not the branch list. + required: + - name + - head_commit_sha + properties: + name: + type: string + description: The branch name, unique within the database. + examples: + - main + head_commit_sha: + type: string + description: The hash of the commit the branch currently points at. + examples: + - vt1u8gdsovtj0qq2qmd6he7n5o4mq2qm + last_updated_at: + type: string + format: date-time + description: When the head commit was committed; absent if the backend didn't report it. + examples: + - "2024-01-15T12:34:56Z" + examples: + - name: main + head_commit_sha: vt1u8gdsovtj0qq2qmd6he7n5o4mq2qm + last_updated_at: "2024-01-15T12:34:56Z" + Tag: + type: object + title: Tag + description: >- + A tag in a database — a named, optionally annotated pointer to a specific commit. + v2 exposes the tag's identity and the commit it targets; the target commit's full + metadata (message, author, parents) belongs to the commit resource, not the tag list. + required: + - name + - commit_sha + properties: + name: + type: string + description: The tag name, unique within the database. + examples: + - v1.0.0 + commit_sha: + type: string + description: The hash of the commit the tag points at. + examples: + - vt1u8gdsovtj0qq2qmd6he7n5o4mq2qm + message: + type: string + description: The tag's annotation message; omitted when the tag has none. + examples: + - First public release. + tagged_at: + type: string + format: date-time + description: When the tag was created; absent if the backend didn't report it. + examples: + - "2024-01-15T12:34:56Z" + examples: + - name: v1.0.0 + commit_sha: vt1u8gdsovtj0qq2qmd6he7n5o4mq2qm + message: First public release. + tagged_at: "2024-01-15T12:34:56Z" + Release: + type: object + title: Release + description: >- + A named release of a database — a title and notes attached to a specific commit, often + but not always paired with a tag of the same name. v2 exposes the release's public + fields; the internal release id is omitted (the tag is the user-facing identifier). + required: + - tag + - title + - commit_sha + - created_at + - updated_at + properties: + tag: + type: string + description: The tag the release is published under, unique within the database. + examples: + - v1.0.0 + title: + type: string + description: The release's human-readable title. + examples: + - First public release + commit_sha: + type: string + description: The hash of the commit the release points at. + examples: + - vt1u8gdsovtj0qq2qmd6he7n5o4mq2qm + description: + type: string + description: The release notes body (markdown). Omitted when the release has none. + examples: + - "## Highlights\n- new join planner\n- breaking: deprecated `foo()`" + created_at: + type: string + format: date-time + description: When the release was first published. + examples: + - "2024-01-15T12:34:56Z" + updated_at: + type: string + format: date-time + description: When the release was last edited; equals `created_at` for never-edited releases. + examples: + - "2024-01-15T12:34:56Z" + examples: + - tag: v1.0.0 + title: First public release + commit_sha: vt1u8gdsovtj0qq2qmd6he7n5o4mq2qm + description: "## Highlights\n- new join planner" + created_at: "2024-01-15T12:34:56Z" + updated_at: "2024-01-15T12:34:56Z" + PullSummary: + type: object + title: PullSummary + description: >- + The lean list shape of a pull request — title, state, creator, timestamps. Companion + to the canonical `Pull` resource returned by the per-pull GET, which adds structured + `from_branch` / `to_branch` references (fork-aware owner / database) needed to + disambiguate cross-fork PRs. + required: + - pull_number + - title + - state + - created_at + - creator + properties: + pull_number: + type: integer + format: int64 + description: The per-database sequential identifier (à la GitHub PR numbers). + examples: + - 42 + title: + type: string + description: The pull request's human-readable title. + examples: + - Fix join planner regression + description: + type: string + description: The pull request description (markdown). Omitted when the pull has none. + examples: + - "Fixes #99." + state: + type: string + enum: + - open + - closed + - merged + description: The pull request's lifecycle state. + examples: + - open + created_at: + type: string + format: date-time + description: When the pull request was created. + examples: + - "2024-01-15T12:34:56Z" + creator: + type: string + description: The username of the user who created the pull request. + examples: + - dolthub + examples: + - pull_number: 42 + title: Fix join planner regression + description: "Fixes #99." + state: open + created_at: "2024-01-15T12:34:56Z" + creator: dolthub + BranchRef: + type: object + title: BranchRef + description: >- + A reference to a branch within a specific database. Carries the database so callers + can disambiguate cross-fork pull requests, where `from_branch` and `to_branch` may + live in different repositories. + required: + - database + - branch_name + properties: + database: + $ref: "#/components/schemas/DatabaseRef" + branch_name: + type: string + description: The branch name within the referenced database. + examples: + - my-feature + - main + examples: + - database: + owner: dolthub + name: us-jails + branch_name: my-feature + Pull: + type: object + title: Pull + description: >- + The canonical pull-request resource. Same public fields as the list `PullSummary` + plus structured `from_branch` / `to_branch` references that carry the database the + branch lives in (necessary for cross-fork pulls, where the source branch lives in a + different repository). + required: + - pull_number + - title + - state + - from_branch + - to_branch + - created_at + - creator + properties: + pull_number: + type: integer + format: int64 + description: The per-database sequential identifier (à la GitHub PR numbers). + examples: + - 42 + title: + type: string + description: The pull request's human-readable title. + examples: + - Fix join planner regression + description: + type: string + description: The pull request description (markdown). Omitted when the pull has none. + examples: + - "Fixes #99." + state: + type: string + enum: + - open + - closed + - merged + description: The pull request's lifecycle state. + examples: + - open + from_branch: + $ref: "#/components/schemas/BranchRef" + to_branch: + $ref: "#/components/schemas/BranchRef" + created_at: + type: string + format: date-time + description: When the pull request was created. + examples: + - "2024-01-15T12:34:56Z" + creator: + type: string + description: The username of the user who created the pull request. + examples: + - dolthub + examples: + - pull_number: 42 + title: Fix join planner regression + description: "Fixes #99." + state: open + from_branch: + database: + owner: dolthub + name: us-jails + branch_name: my-feature + to_branch: + database: + owner: dolthub + name: us-jails + branch_name: main + created_at: "2024-01-15T12:34:56Z" + creator: dolthub + PullComment: + type: object + title: PullComment + description: >- + A top-level comment on a pull request. Diff-line comments and review comments are + modeled as separate resources (not in v2 yet). + required: + - comment_id + - author + - body + - created_at + - updated_at + properties: + comment_id: + type: string + description: The opaque per-comment identifier, unique within the pull request. + examples: + - 1c8f3b1e-5d2e-4a3a-9f2b-0e7a6d5c4b3a + author: + type: string + description: The username of the comment's author. + examples: + - alice + body: + type: string + description: The comment text (markdown). + examples: + - "LGTM — one nit on the join planner case." + created_at: + type: string + format: date-time + description: When the comment was first posted. + examples: + - "2024-01-15T12:34:56Z" + updated_at: + type: string + format: date-time + description: When the comment was last edited (equals `created_at` if never edited). + examples: + - "2024-01-15T12:34:56Z" + examples: + - comment_id: 1c8f3b1e-5d2e-4a3a-9f2b-0e7a6d5c4b3a + author: alice + body: "LGTM — one nit on the join planner case." + created_at: "2024-01-15T12:34:56Z" + updated_at: "2024-01-15T12:34:56Z" + QueryColumn: + type: object + title: QueryColumn + description: One column in a query result's schema. + required: + - name + - type + properties: + name: + type: string + description: The column name. + examples: + - state_name + type: + type: string + description: >- + The column's SQL type — e.g. `VARCHAR(255)`, `BIGINT`, `DATETIME(6)`. Clients + parsing typed values are expected to read this and coerce `cells` accordingly. + examples: + - "VARCHAR(255)" + is_primary_key: + type: boolean + description: Whether the column is part of the source table's primary key. + source_table: + type: string + description: >- + The table this column came from. Empty for expressions or virtual columns + (e.g. `COUNT(*)`). + examples: + - jails + QueryResult: + type: object + title: QueryResult + description: >- + The result of a `runSqlReadQuery` call. SQL-level conditions (success, error, timeout, + row-limit) live in `status` and `message` — they are query-level, not transport-level. + required: + - columns + - rows + - status + properties: + columns: + type: array + description: The result schema — one entry per column, in the row's cell order. + items: + $ref: "#/components/schemas/QueryColumn" + rows: + type: array + description: >- + The result rows. Each row is an array of cell values, ordered to match the + `columns` schema. Non-NULL cells are serialized as strings regardless of the + underlying SQL type; clients can parse per `columns[i].type` to coerce typed + values. NULL cells are serialized as JSON `null`. BLOB-typed cells are returned + as the placeholder string `""` (the backend does not stream binary bytes + over this endpoint); clients can detect blob columns via `columns[i].type`. + items: + type: array + items: + type: + - string + - "null" + status: + type: string + description: >- + The query's execution status. `success` is the only status that guarantees + `rows` and `columns` are fully populated. + enum: + - success + - error + - timeout + - row_limit + - not_workspace + message: + type: string + description: >- + Server-supplied message describing the status. Always populated for non-`success` + statuses; usually empty on success. + warnings: + type: array + description: SQL-level warnings emitted by the query engine (e.g. truncated values). + items: + type: string + examples: + - columns: + - name: state_name + type: "VARCHAR(255)" + is_primary_key: true + source_table: jails + - name: count + type: BIGINT + is_primary_key: false + source_table: "" + rows: + - ["California", "162"] + - ["Texas", "108"] + - [null, "0"] + status: success + warnings: [] + EmailAddress: + type: object + title: EmailAddress + description: An email address registered to a DoltHub user. + required: + - address + - is_primary + - is_verified + properties: + address: + type: string + format: email + description: The email address. + examples: + - dolt-interest@dolthub.com + is_primary: + type: boolean + description: Whether this is the user's primary email address. + is_verified: + type: boolean + description: Whether this email address has been verified. + examples: + - address: dolt-interest@dolthub.com + is_primary: true + is_verified: true + User: + type: object + title: User + description: >- + A DoltHub user. `GET /api/v2/user` returns the authenticated user's profile. v2 + returns only the public-facing profile fields — internal flags (super-admin, + two-factor settings, API tokens) are never included. + required: + - username + - email_addresses + properties: + username: + type: string + description: The user's DoltHub username (unique handle). + examples: + - dolthub + display_name: + type: string + description: The user's display name. May be empty. + examples: + - DoltHub + bio: + type: string + description: The user's bio. May be empty. + location: + type: string + description: The user's stated location. May be empty. + website_url: + type: string + description: The user's website URL. May be empty. + examples: + - https://www.dolthub.com + profile_pic_url: + type: string + description: URL of the user's profile picture. May be empty. + email_addresses: + type: array + description: The user's registered email addresses. + items: + $ref: "#/components/schemas/EmailAddress" + examples: + - username: dolthub + display_name: DoltHub + bio: The database for agents. + location: San Mateo, CA + website_url: https://www.dolthub.com + profile_pic_url: https://www.dolthub.com/static/images/dolthub_logo.png + email_addresses: + - address: dolt-interest@dolthub.com + is_primary: true + is_verified: true + + # Reusable parameters — pulled out as components.parameters so every list endpoint $refs + # the same shape rather than redeclaring it. PageToken is the v2 pagination convention + # (§5.6, established by 2.b); the response side lives in components.schemas.Meta.next_page_token. + parameters: + PageToken: + name: page_token + in: query + required: false + description: >- + Opaque cursor returned in a prior response's `meta.next_page_token`. Pass it back to + fetch the next page; omit it on the first request. The token format is server-defined + — clients must treat it as an opaque string. + schema: + type: string + example: eyJvZmZzZXQiOjI1fQ + + # Reusable error responses — the status-code conventions for v2 (§5.3). Operations + # reference these so every endpoint returns the right code with one consistent body + # instead of the v1 "everything is 400" behavior. They are wired into operations as paths + # are added (first in 1.t). + responses: + BadRequest: + description: The request was malformed or failed input validation. + content: + application/json: + schema: + $ref: "#/components/schemas/Problem" + Unauthorized: + description: Authentication credentials were missing or invalid. + content: + application/json: + schema: + $ref: "#/components/schemas/Problem" + Forbidden: + description: Authenticated, but not permitted to perform this action. + content: + application/json: + schema: + $ref: "#/components/schemas/Problem" + NotFound: + description: The requested resource does not exist. + content: + application/json: + schema: + $ref: "#/components/schemas/Problem" + MethodNotAllowed: + description: The HTTP method is not supported for this resource. + headers: + Allow: + description: The HTTP methods supported by this resource. + schema: + type: string + content: + application/json: + schema: + $ref: "#/components/schemas/Problem" + Conflict: + description: The request conflicts with the current state of the resource (e.g. it already exists). + content: + application/json: + schema: + $ref: "#/components/schemas/Problem" + UnprocessableEntity: + description: The request was well-formed but semantically invalid. + content: + application/json: + schema: + $ref: "#/components/schemas/Problem" + TooManyRequests: + description: The client has exceeded its rate limit. + headers: + Retry-After: + description: The number of seconds to wait before retrying the request. + schema: + type: integer + format: int32 + content: + application/json: + schema: + $ref: "#/components/schemas/Problem" + InternalServerError: + description: An unexpected server error occurred. + content: + application/json: + schema: + $ref: "#/components/schemas/Problem" + ServiceUnavailable: + description: The service is temporarily unavailable. + content: + application/json: + schema: + $ref: "#/components/schemas/Problem"