From 46696478be93dac7069e3d3d8b5a25da193e9201 Mon Sep 17 00:00:00 2001 From: Aaron Boodman Date: Tue, 22 Jul 2025 07:03:19 -1000 Subject: [PATCH 01/28] wip: This adds og image generation. The URL /api/og?title=foo&subtitle=bar generates an OG image. It is not yet hooked up to actually serve the correct OG metadata. Need to modify the metadata generated in layout.tsx. --- app/api/og/route.tsx | 85 ++++++++++++++++ app/fonts/muoto-bold.woff | Bin 0 -> 46052 bytes package-lock.json | 207 ++++++++++++++++++++++++++++++++++++++ package.json | 1 + 4 files changed, 293 insertions(+) create mode 100644 app/api/og/route.tsx create mode 100644 app/fonts/muoto-bold.woff diff --git a/app/api/og/route.tsx b/app/api/og/route.tsx new file mode 100644 index 00000000..ea601b0e --- /dev/null +++ b/app/api/og/route.tsx @@ -0,0 +1,85 @@ +// app/api/og/route.tsx +import {ImageResponse} from '@vercel/og'; +import {NextRequest} from 'next/server'; + +export const runtime = 'edge'; // Required for @vercel/og + +const muotoBold = new URL('../../fonts/muoto-bold.woff', import.meta.url); +const zeroLogo = new URL( + '../../../public/images/zero-logo.svg', + import.meta.url, +); + +export async function GET(req: NextRequest) { + const {searchParams} = new URL(req.url); + const title = searchParams.get('title') ?? 'General Purpose Sync for the Web'; + const subtitle = searchParams.get('subtitle'); + + return new ImageResponse( + ( +
+
+ {title} +
+ {subtitle && ( +
+ {subtitle} +
+ )} + Zero +
+ ), + { + width: 1200, + height: 630, + fonts: [ + { + name: 'muoto-bold', + data: await loadFile(muotoBold), + }, + ], + }, + ); +} + +async function loadFileAsBase64URL(url: URL, mimetype: string) { + const buffer = await loadFile(url); + const b64 = Buffer.from(buffer).toString('base64'); + return `data:${mimetype};base64,${b64}`; +} + +async function loadFile(url: URL) { + const res = await fetch(url); + return await res.arrayBuffer(); +} diff --git a/app/fonts/muoto-bold.woff b/app/fonts/muoto-bold.woff new file mode 100644 index 0000000000000000000000000000000000000000..4fc3690c0e04666698ae95039db4d34132860cb9 GIT binary patch literal 46052 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
!Y@?RHCPb7KS_ifNYTRnd`Apcen#u31 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 10" + } + }, "node_modules/@rocicorp/prettier-config": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/@rocicorp/prettier-config/-/prettier-config-0.3.0.tgz", @@ -2485,6 +2495,22 @@ "integrity": "sha512-hw437iINopmQuxWPSUEvqE56NCPsiU8N4AYtfHmJFckclktzK9YQJieD3XkDCDH4OjL+C7zgPUh73R/nrcHrqw==", "dev": true }, + "node_modules/@shuding/opentype.js": { + "version": "1.4.0-beta.0", + "resolved": "https://registry.npmjs.org/@shuding/opentype.js/-/opentype.js-1.4.0-beta.0.tgz", + "integrity": "sha512-3NgmNyH3l/Hv6EvsWJbsvpcpUba6R8IREQ83nH83cyakCw7uM1arZKNfHwv1Wz6jgqrF/j4x5ELvR6PnK9nTcA==", + "license": "MIT", + "dependencies": { + "fflate": "^0.7.3", + "string.prototype.codepointat": "^0.2.1" + }, + "bin": { + "ot": "bin/ot" + }, + "engines": { + "node": ">= 8.0.0" + } + }, "node_modules/@swc/counter": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz", @@ -2799,6 +2825,19 @@ "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==" }, + "node_modules/@vercel/og": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/@vercel/og/-/og-0.8.2.tgz", + "integrity": "sha512-7B/futewgJj7TLDj6fMp+USBRIt3TqtwomEtX/jVS+g+dZySjXUYBsWD2Sz3Y6hFR34xAXWDQaMvIic313h0Nw==", + "license": "MPL-2.0", + "dependencies": { + "@resvg/resvg-wasm": "2.4.0", + "satori": "0.16.0" + }, + "engines": { + "node": ">=16" + } + }, "node_modules/abbrev": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", @@ -3188,6 +3227,15 @@ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, + "node_modules/base64-js": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-0.0.8.tgz", + "integrity": "sha512-3XSA2cR/h/73EzlXXdU6YNycmYI7+kicTxks4eJg2g39biHR84slg2+des+p7iHYhbRg/udIS4TD53WabcOUkw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/bhttp": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/bhttp/-/bhttp-1.2.8.tgz", @@ -3484,6 +3532,15 @@ "node": ">= 6" } }, + "node_modules/camelize": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/camelize/-/camelize-1.0.1.tgz", + "integrity": "sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/caniuse-lite": { "version": "1.0.30001710", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001710.tgz", @@ -3846,6 +3903,47 @@ "node": ">= 8" } }, + "node_modules/css-background-parser": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/css-background-parser/-/css-background-parser-0.1.0.tgz", + "integrity": "sha512-2EZLisiZQ+7m4wwur/qiYJRniHX4K5Tc9w93MT3AS0WS1u5kaZ4FKXlOTBhOjc+CgEgPiGY+fX1yWD8UwpEqUA==", + "license": "MIT" + }, + "node_modules/css-box-shadow": { + "version": "1.0.0-3", + "resolved": "https://registry.npmjs.org/css-box-shadow/-/css-box-shadow-1.0.0-3.tgz", + "integrity": "sha512-9jaqR6e7Ohds+aWwmhe6wILJ99xYQbfmK9QQB9CcMjDbTxPZjwEmUQpU91OG05Xgm8BahT5fW+svbsQGjS/zPg==", + "license": "MIT" + }, + "node_modules/css-color-keywords": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/css-color-keywords/-/css-color-keywords-1.0.0.tgz", + "integrity": "sha512-FyyrDHZKEjXDpNJYvVsV960FiqQyXc/LlYmsxl2BcdMb2WPx0OGRVgTg55rPSyLSNMqP52R9r8geSp7apN3Ofg==", + "license": "ISC", + "engines": { + "node": ">=4" + } + }, + "node_modules/css-gradient-parser": { + "version": "0.0.16", + "resolved": "https://registry.npmjs.org/css-gradient-parser/-/css-gradient-parser-0.0.16.tgz", + "integrity": "sha512-3O5QdqgFRUbXvK1x5INf1YkBz1UKSWqrd63vWsum8MNHDBYD5urm3QtxZbKU259OrEXNM26lP/MPY3d1IGkBgA==", + "license": "MIT", + "engines": { + "node": ">=16" + } + }, + "node_modules/css-to-react-native": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/css-to-react-native/-/css-to-react-native-3.2.0.tgz", + "integrity": "sha512-e8RKaLXMOFii+02mOlqwjbD00KSEKqblnpO9e++1aXS1fPQOpS1YoqdVHBqPjHNoxeF2mimzVqawm2KCbEdtHQ==", + "license": "MIT", + "dependencies": { + "camelize": "^1.0.0", + "css-color-keywords": "^1.0.0", + "postcss-value-parser": "^4.0.2" + } + }, "node_modules/cssesc": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", @@ -4093,6 +4191,15 @@ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" }, + "node_modules/emoji-regex-xs": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/emoji-regex-xs/-/emoji-regex-xs-2.0.1.tgz", + "integrity": "sha512-1QFuh8l7LqUcKe24LsPUNzjrzJQ7pgRwp1QMcZ5MX6mFplk2zQ08NVCM84++1cveaUUYtcCYHmeFEuNg16sU4g==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + } + }, "node_modules/enhanced-resolve": { "version": "5.16.0", "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.16.0.tgz", @@ -4349,6 +4456,12 @@ "node": ">=6" } }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "license": "MIT" + }, "node_modules/escape-string-regexp": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", @@ -4926,6 +5039,12 @@ "reusify": "^1.0.4" } }, + "node_modules/fflate": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.7.4.tgz", + "integrity": "sha512-5u2V/CDW15QM1XbbgS+0DfPxVB+jUKhWEKuuFuHncbk3tEEqzmoXL+2KyOFuKGqOnmdIy0/davWF1CkuwtibCw==", + "license": "MIT" + }, "node_modules/file-entry-cache": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", @@ -5673,6 +5792,18 @@ "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==", "license": "MIT" }, + "node_modules/hex-rgb": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/hex-rgb/-/hex-rgb-4.3.0.tgz", + "integrity": "sha512-Ox1pJVrDCyGHMG9CFg1tmrRUMRPRsAWYc/PinY0XzJU4K7y7vjNoLKIQ7BR5UJMCxNN8EM1MNDmHWA/B3aZUuw==", + "license": "MIT", + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/highlight.js": { "version": "11.10.0", "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-11.10.0.tgz", @@ -6402,6 +6533,16 @@ "node": ">= 0.10" } }, + "node_modules/linebreak": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/linebreak/-/linebreak-1.1.0.tgz", + "integrity": "sha512-MHp03UImeVhB7XZtjd0E4n6+3xr5Dq/9xI/5FptGk5FrbDR3zagPa2DS6U8ks/3HjbKWG9Q1M2ufOzxV2qLYSQ==", + "license": "MIT", + "dependencies": { + "base64-js": "0.0.8", + "unicode-trie": "^2.0.0" + } + }, "node_modules/lines-and-columns": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", @@ -8097,6 +8238,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/pako": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz", + "integrity": "sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA==", + "license": "MIT" + }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -8109,6 +8256,16 @@ "node": ">=6" } }, + "node_modules/parse-css-color": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/parse-css-color/-/parse-css-color-0.2.1.tgz", + "integrity": "sha512-bwS/GGIFV3b6KS4uwpzCFj4w297Yl3uqnSgIPsoQkx7GMLROXfMnWvxfNkL0oh8HVhZA4hvJoEoEIqonfJ3BWg==", + "license": "MIT", + "dependencies": { + "color-name": "^1.1.4", + "hex-rgb": "^4.1.0" + } + }, "node_modules/parse-domain": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/parse-domain/-/parse-domain-0.2.2.tgz", @@ -9098,6 +9255,28 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/satori": { + "version": "0.16.0", + "resolved": "https://registry.npmjs.org/satori/-/satori-0.16.0.tgz", + "integrity": "sha512-ZvHN3ygzZ8FuxjSNB+mKBiF/NIoqHzlBGbD0MJiT+MvSsFOvotnWOhdTjxKzhHRT2wPC1QbhLzx2q/Y83VhfYQ==", + "license": "MPL-2.0", + "dependencies": { + "@shuding/opentype.js": "1.4.0-beta.0", + "css-background-parser": "^0.1.0", + "css-box-shadow": "1.0.0-3", + "css-gradient-parser": "^0.0.16", + "css-to-react-native": "^3.0.0", + "emoji-regex-xs": "^2.0.1", + "escape-html": "^1.0.3", + "linebreak": "^1.1.0", + "parse-css-color": "^0.2.1", + "postcss-value-parser": "^4.2.0", + "yoga-layout": "^3.2.1" + }, + "engines": { + "node": ">=16" + } + }, "node_modules/scheduler": { "version": "0.23.2", "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", @@ -9375,6 +9554,12 @@ "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, + "node_modules/string.prototype.codepointat": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/string.prototype.codepointat/-/string.prototype.codepointat-0.2.1.tgz", + "integrity": "sha512-2cBVCj6I4IOvEnjgO/hWqXjqBGsY+zwPmHl12Srk9IXSZ56Jwwmy+66XO5Iut/oQVR7t5ihYdLB0GMa4alEUcg==", + "license": "MIT" + }, "node_modules/string.prototype.matchall": { "version": "4.0.11", "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.11.tgz", @@ -9743,6 +9928,12 @@ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", "integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==" }, + "node_modules/tiny-inflate": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tiny-inflate/-/tiny-inflate-1.0.3.tgz", + "integrity": "sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw==", + "license": "MIT" + }, "node_modules/tmp": { "version": "0.0.33", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", @@ -10037,6 +10228,16 @@ "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", "license": "MIT" }, + "node_modules/unicode-trie": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-trie/-/unicode-trie-2.0.0.tgz", + "integrity": "sha512-x7bc76x0bm4prf1VLg79uhAzKw8DVboClSN5VxJuQ+LKDOVEW9CdH+VY7SP+vX7xCYQqzzgQpFqz15zeLvAtZQ==", + "license": "MIT", + "dependencies": { + "pako": "^0.2.5", + "tiny-inflate": "^1.0.0" + } + }, "node_modules/unified": { "version": "11.0.4", "resolved": "https://registry.npmjs.org/unified/-/unified-11.0.4.tgz", @@ -10698,6 +10899,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/yoga-layout": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/yoga-layout/-/yoga-layout-3.2.1.tgz", + "integrity": "sha512-0LPOt3AxKqMdFBZA3HBAt/t/8vIKq7VaQYbuA8WxCgung+p9TVyKRYdpvCb80HcdTN2NkbIKbhNwKUfm3tQywQ==", + "license": "MIT" + }, "node_modules/zwitch": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz", diff --git a/package.json b/package.json index c40dc1d4..6cb47831 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,7 @@ "@radix-ui/react-scroll-area": "^1.1.0", "@radix-ui/react-slot": "^1.1.0", "@radix-ui/react-tooltip": "^1.2.7", + "@vercel/og": "^0.8.2", "broken-link-checker": "^0.7.8", "class-variance-authority": "^0.7.0", "clsx": "^2.1.1", From 4eceebbda40e6a20eb42781db2318acbc65fd23c Mon Sep 17 00:00:00 2001 From: Aaron Boodman Date: Tue, 22 Jul 2025 07:09:20 -1000 Subject: [PATCH 02/28] maybe this will work? --- app/docs/[[...slug]]/page.tsx | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/app/docs/[[...slug]]/page.tsx b/app/docs/[[...slug]]/page.tsx index 82d1f427..1f689937 100644 --- a/app/docs/[[...slug]]/page.tsx +++ b/app/docs/[[...slug]]/page.tsx @@ -41,7 +41,24 @@ export async function generateMetadata({params: {slug = []}}: PageProps) { const res = await getDocsForSlug(pathName); if (!res) return null; const {frontmatter} = res; - return {title: frontmatter.title, description: frontmatter.description}; + + const ogImageUrl = `/api/og?title=${encodeURIComponent(frontmatter.title)}`; + + return { + title: frontmatter.title, + description: frontmatter.description, + openGraph: { + title: frontmatter.title, + description: frontmatter.description, + images: ogImageUrl, + }, + twitter: { + card: 'summary_large_image', + title: frontmatter.title, + description: frontmatter.description, + images: ogImageUrl, + }, + }; } export function generateStaticParams() { From 029b082e12e25e6a37c815ab305e60993102fcac Mon Sep 17 00:00:00 2001 From: Aaron Boodman Date: Wed, 23 Jul 2025 18:35:41 -1000 Subject: [PATCH 03/28] ok --- app/api/og/route.tsx | 4 ++-- app/docs/[[...slug]]/page.tsx | 2 +- contents/docs/sync.mdx | 1 + contents/docs/when-to-use.mdx | 5 +++-- 4 files changed, 7 insertions(+), 5 deletions(-) diff --git a/app/api/og/route.tsx b/app/api/og/route.tsx index ea601b0e..70251f91 100644 --- a/app/api/og/route.tsx +++ b/app/api/og/route.tsx @@ -43,8 +43,8 @@ export async function GET(req: NextRequest) { {subtitle && (
Date: Fri, 25 Jul 2025 16:17:39 -1000 Subject: [PATCH 04/28] Fix "undefined" in og image when page lacks subtitle --- app/api/og/route.tsx | 4 ++-- app/docs/[[...slug]]/page.tsx | 7 ++++++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/app/api/og/route.tsx b/app/api/og/route.tsx index 70251f91..6b776652 100644 --- a/app/api/og/route.tsx +++ b/app/api/og/route.tsx @@ -43,8 +43,8 @@ export async function GET(req: NextRequest) { {subtitle && (
{ + if (!str) return ''; + return encodeURIComponent(str); + }; + + const ogImageUrl = `/api/og?title=${encode(frontmatter.title)}&subtitle=${encode(frontmatter.description)}`; return { title: frontmatter.title, From cfdb28fdc635e929565ae3a4cb971c0f36361042 Mon Sep 17 00:00:00 2001 From: Cory House Date: Mon, 28 Jul 2025 16:26:53 -0400 Subject: [PATCH 05/28] Update sync.mdx --- contents/docs/sync.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contents/docs/sync.mdx b/contents/docs/sync.mdx index 644c89df..4358235e 100644 --- a/contents/docs/sync.mdx +++ b/contents/docs/sync.mdx @@ -21,7 +21,7 @@ Let's say you have some data that you want to read and write from multiple devic This works, but has downsides: -* **Slow access.** Every read and write has to go to the server, addding hundreds of milliseconds to each interaction. +* **Slow access.** Every read and write has to go to the server, adding hundreds of milliseconds to each interaction. * **Stale data.** API responses are immediately stale. The client has no way to know when to refresh them. Users may make decisions based on old information, and the views on different devices diverge over time. * **Online-only.** If the server or the user's network connection is down, the app stops working completely. From 9ddbfed86313cdad9029c0302a5d834fa5ab7e66 Mon Sep 17 00:00:00 2001 From: Aaron Boodman Date: Mon, 28 Jul 2025 17:08:54 -1000 Subject: [PATCH 06/28] document cmplit --- contents/docs/permissions.mdx | 27 ++++++++++++++++++++++++--- contents/docs/reading-data.mdx | 30 ++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+), 3 deletions(-) diff --git a/contents/docs/permissions.mdx b/contents/docs/permissions.mdx index bc25d740..8d54ced9 100644 --- a/contents/docs/permissions.mdx +++ b/contents/docs/permissions.mdx @@ -161,11 +161,11 @@ definePermissions(schema, () => { If the issue table has two rows, one created by the user and one by someone else, the user will only see the row they created in any queries. -### Column permissions - -Zero does not currently support column based permissions. Select permission applies to every column. The recommended approach for now is to factor out private fields into a separate table, e.g. `user_private`. Column permissions are planned but currently not a high priority. + +Select permission applies to every column. The recommended approach for now is to factor out private fields into a separate table, e.g. `user_private`. Column permissions are planned but currently not a high priority. Note that although the same limitation applies to declarative insert/update permissions, [custom mutators](/docs/custom-mutators) support arbitrary server-side logic and so can easily control which columns are writable. + ## Insert Permissions @@ -272,6 +272,27 @@ definePermissions(schema, () => { Delete permissions work in the same way as `insert` permissions except they run _before_ the delete is applied. So if a delete rule queries the database, it will see that the deleted row is present. If any rule in the ruleset returns a row, the delete is allowed. +## Permissions Based on Auth Data + +You can use the [`cmpLit` helper](reading-data#comparing-literal-values) to define permissions based on a field of the `authData` parameter: + +```ts +definePermissions(schema, () => { + const allowIfAdmin = ( + authData: AuthData, + {cmpLit}: ExpressionBuilder, + ) => cmpLit(authData.role, 'admin'); + + return { + issue: { + row: { + select: [allowIfAdmin], + }, + }, + } satisfies PermissionsConfig; +}); +``` + ## Debugging See [Debugging Permissions](./debug/permissions). diff --git a/contents/docs/reading-data.mdx b/contents/docs/reading-data.mdx index 7f0d24f5..450659c3 100644 --- a/contents/docs/reading-data.mdx +++ b/contents/docs/reading-data.mdx @@ -236,6 +236,36 @@ Note that chaining `where()` is also a one-level `and`: z.query.issue.where('priority', '>=', 3).where('owner', 'aa'); ``` +### Comparing Literal Values + +The `where` clause always expects its first parameter to be a column name as a string. Same with the `cmp` helper: + +```ts +// "foo" is a column name, not a string: +z.query.issue.where('foo', 'bar'); + +// "foo" is a column name, not a string: +z.query.issue.where(({cmp}) => cmp('foo', 'bar')); +``` + +To compareto a literal value, use the `cmpLit` helper: + +```ts +z.query.issue.where(cmpLit('foobar', 'foo' + 'bar')); +``` + +By itself this is not very useful, but the first parameter can also be a JavaScript variable: + +```ts +z.query.issue.where(cmpLit(role, 'admin')); +``` + +Or, within a [permission rule](/docs/permissions#permissions-based-on-auth-data), you can compare to a field of the `authData` parameter: + +```ts +z.query.issue.where(cmpLit(authData.role, 'admin')); +``` + ### Relationship Filters Your filter can also test properties of relationships. Currently the only supported test is existence: From 70eefada49cdbc07d937e78b0b0d48d9fecaa712 Mon Sep 17 00:00:00 2001 From: Alexander King Date: Wed, 30 Jul 2025 16:10:26 -0400 Subject: [PATCH 07/28] New og logo and adjusting typography and layout --- app/api/og/route.tsx | 25 +++++++++++++++---------- app/fonts/muoto-regular.woff | Bin 0 -> 44724 bytes public/images/zero-docs-logo.svg | 12 ++++++++++++ 3 files changed, 27 insertions(+), 10 deletions(-) create mode 100644 app/fonts/muoto-regular.woff create mode 100644 public/images/zero-docs-logo.svg diff --git a/app/api/og/route.tsx b/app/api/og/route.tsx index 6b776652..8d5eb3d7 100644 --- a/app/api/og/route.tsx +++ b/app/api/og/route.tsx @@ -5,8 +5,9 @@ import {NextRequest} from 'next/server'; export const runtime = 'edge'; // Required for @vercel/og const muotoBold = new URL('../../fonts/muoto-bold.woff', import.meta.url); -const zeroLogo = new URL( - '../../../public/images/zero-logo.svg', +const muotoReg = new URL('../../fonts/muoto-regular.woff', import.meta.url); +const zeroDocsLogo = new URL( + '../../../public/images/zero-docs-logo.svg', import.meta.url, ); @@ -27,8 +28,7 @@ export async function GET(req: NextRequest) { backgroundColor: 'black', justifyContent: 'center', color: 'white', - fontFamily: 'muoto-bold', - padding: '0 200px', + padding: '0 300px', textAlign: 'center', }} > @@ -36,6 +36,7 @@ export async function GET(req: NextRequest) { style={{ fontSize: 86, letterSpacing: '-2.58px' /* 86 * -3% */, + fontFamily: 'muoto-bold', }} > {title} @@ -43,20 +44,20 @@ export async function GET(req: NextRequest) { {subtitle && (
{subtitle}
)} Zero
), @@ -68,6 +69,10 @@ export async function GET(req: NextRequest) { name: 'muoto-bold', data: await loadFile(muotoBold), }, + { + name: 'muoto-reg', + data: await loadFile(muotoReg), + }, ], }, ); diff --git a/app/fonts/muoto-regular.woff b/app/fonts/muoto-regular.woff new file mode 100644 index 0000000000000000000000000000000000000000..fee53a01aee20a8d77179faa8283e7f6d1f94a82 GIT binary patch literal 44724 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 literal 0 HcmV?d00001 diff --git a/public/images/zero-docs-logo.svg b/public/images/zero-docs-logo.svg new file mode 100644 index 00000000..31e191f6 --- /dev/null +++ b/public/images/zero-docs-logo.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + From 6bcc94b807c7f2172037cd600ed0c3c9091b9696 Mon Sep 17 00:00:00 2001 From: Alexander King Date: Wed, 30 Jul 2025 16:33:20 -0400 Subject: [PATCH 08/28] Adjustments to og image layout. Fixing status page. Adjusting h1 margin --- app/api/og/route.tsx | 4 +++- app/docs/[[...slug]]/page.tsx | 2 +- contents/docs/status.mdx | 3 +++ 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/app/api/og/route.tsx b/app/api/og/route.tsx index 8d5eb3d7..165d7e56 100644 --- a/app/api/og/route.tsx +++ b/app/api/og/route.tsx @@ -28,7 +28,7 @@ export async function GET(req: NextRequest) { backgroundColor: 'black', justifyContent: 'center', color: 'white', - padding: '0 300px', + padding: '0 200px', textAlign: 'center', }} > @@ -46,6 +46,8 @@ export async function GET(req: NextRequest) { style={{ fontSize: 48, marginTop: 36, + lineHeight: 1.4, + padding: '0 80px', color: 'white', fontWeight: 400, fontFamily: 'muoto-reg', diff --git a/app/docs/[[...slug]]/page.tsx b/app/docs/[[...slug]]/page.tsx index 8265a155..cdddc3d5 100644 --- a/app/docs/[[...slug]]/page.tsx +++ b/app/docs/[[...slug]]/page.tsx @@ -22,7 +22,7 @@ export default async function DocsPage({params: {slug = []}}: PageProps) {
-

{res.frontmatter.title}

+

{res.frontmatter.title}

{res.frontmatter.description}

diff --git a/contents/docs/status.mdx b/contents/docs/status.mdx index aa3346eb..a7b6a058 100644 --- a/contents/docs/status.mdx +++ b/contents/docs/status.mdx @@ -1,3 +1,6 @@ +--- +title: Project Status +--- Zero is a new sync engine based on a novel streaming query engine. This is an ambitious project at an early stage. From 4e04a915f60ab8cb5682715b9e7cb33d9eb55a2a Mon Sep 17 00:00:00 2001 From: Alexander King Date: Wed, 30 Jul 2025 16:51:28 -0400 Subject: [PATCH 09/28] Fixing subtitle distance --- app/docs/[[...slug]]/page.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/docs/[[...slug]]/page.tsx b/app/docs/[[...slug]]/page.tsx index cdddc3d5..c89dd384 100644 --- a/app/docs/[[...slug]]/page.tsx +++ b/app/docs/[[...slug]]/page.tsx @@ -23,7 +23,7 @@ export default async function DocsPage({params: {slug = []}}: PageProps) {

{res.frontmatter.title}

-

+

{res.frontmatter.description}

{/* Wrap content with CopyableContent */} From 8c6e59ffe8945833daccdd6c6482e4ef39de639a Mon Sep 17 00:00:00 2001 From: Alexander King Date: Wed, 30 Jul 2025 16:59:22 -0400 Subject: [PATCH 10/28] Fixing the h1 layout when no description present --- app/docs/[[...slug]]/page.tsx | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/app/docs/[[...slug]]/page.tsx b/app/docs/[[...slug]]/page.tsx index c89dd384..06fb3b9e 100644 --- a/app/docs/[[...slug]]/page.tsx +++ b/app/docs/[[...slug]]/page.tsx @@ -23,9 +23,11 @@ export default async function DocsPage({params: {slug = []}}: PageProps) {

{res.frontmatter.title}

-

- {res.frontmatter.description} -

+ {res.frontmatter.description && ( +

+ {res.frontmatter.description} +

+ )} {/* Wrap content with CopyableContent */} From 117dfa65c0aef30eafc9f710945a12d2edcac326 Mon Sep 17 00:00:00 2001 From: Aaron Boodman Date: Fri, 1 Aug 2025 17:06:34 -1000 Subject: [PATCH 11/28] 0.22 --- contents/docs/custom-mutators.mdx | 39 ++- contents/docs/offline.mdx | 18 +- contents/docs/reading-data.mdx | 264 +++++++++--------- contents/docs/release-notes/0.22.mdx | 63 +++++ contents/docs/release-notes/index.mdx | 1 + contents/docs/solidjs.mdx | 4 +- contents/docs/sync.mdx | 2 +- contents/docs/zero-cache-config.mdx | 154 +++++++--- .../images/reading-data/query-lifecycle.png | Bin 241695 -> 0 bytes .../images/reading-data/query-lifecycle.svg | 14 + 10 files changed, 374 insertions(+), 185 deletions(-) create mode 100644 contents/docs/release-notes/0.22.mdx delete mode 100644 public/images/reading-data/query-lifecycle.png create mode 100644 public/images/reading-data/query-lifecycle.svg diff --git a/contents/docs/custom-mutators.mdx b/contents/docs/custom-mutators.mdx index ff6f8855..a5ac4c57 100644 --- a/contents/docs/custom-mutators.mdx +++ b/contents/docs/custom-mutators.mdx @@ -295,7 +295,7 @@ You can use the `.client` promise in this case to wait for a write to complete o ```ts try { - const write = zero.mutate.issue.update({ + const write = zero.mutate.issue.insert({ id: 'issue-123', title: 'New title', }); @@ -318,12 +318,25 @@ You can also wait for the server write to succeed: ```ts try { - await zero.mutate.issue.update({ + const write = zero.mutate.issue.insert({ id: 'issue-123', title: 'New title', - }).server; + }); + + await write.client; - // issue-123 is written to server + // optimistic write guaranteed to be present here, but not + // server write. + const read1 = await zero.query.issue.where('id', 'issue-123').one(); + + // Await server write – this involves a round-trip. + await write.server; + + // issue-123 is written to server and any results are + // syned to this client. + // read2 could potentially be undefined here, for example if the + // server mutator rejected the write. + const read2 = await zero.query.issue.where('id', 'issue-123').one(); } catch (e) { console.error('Mutator failed on client or server', e); } @@ -339,20 +352,24 @@ If the client-side mutator fails, the `.server` promise is also rejected with th You will need a server somewhere you can run an endpoint on. This is typically a serverless function on a platform like Vercel or AWS but can really be anything. -Set the push URL with the [`ZERO_PUSH_URL` env var or `--push-url`](./zero-cache-config#push-url). - -If there is per-client configuration you need to send to the push endpoint, you can do that with `push.queryParams`: +Configure the push endpoint with the `push.url` parameter in your `Zero` constructor: ```ts -const z = new Zero({ +const zero = new Zero({ push: { - queryParams: { - workspaceID: '42', - }, + url: 'https://zero.my-server.com/push', }, }); ``` +You will also need to enable the server to be used as a push endpoint with the [`ZERO_PUSH_URL` environment variable or `--push-url` flag](./zero-cache-config#push-url): + +```bash +ZERO_PUSH_URL=https://*.my-server.com/push +``` + +The `ZERO_PUSH_URL` parameter accepts wildcards, enabling the client to pass runtime configuration to the push endpoint or to use a different push endpoint, e.g., for previews. See the [config docs](./zero-cache-config#push-url) for the full syntax. + The push endpoint receives a `PushRequest` as input describing one or more mutations to apply to the backend, and must return a `PushResponse` describing the results of those mutations. If you are implementing your server in TypeScript, you can use the `PushProcessor` class to trivially implement this endpoint. Here’s an example in a [Hono](https://hono.dev/) app: diff --git a/contents/docs/offline.mdx b/contents/docs/offline.mdx index 98ca0f4d..a60be666 100644 --- a/contents/docs/offline.mdx +++ b/contents/docs/offline.mdx @@ -61,7 +61,23 @@ We would like to revisit this in the future and really think through how to desi ## Dealing with Offline Today -Until Zero disables offline writes automatically, we recomment using the `onOnlineChange` parameter to the `Zero` constructor to detect connection loss and disable editing manually in your UI. +Until Zero disables offline writes automatically, use `useZeroOnline` to detect connection loss and manually disable writes in your UI: + +```tsx +const {online} = useZeroOnline(); + +return ; +``` + +... or use the underlying `zero.onOnline` event: + +```tsx +const unsubscribe = zero.onOnline(online => { + console.log('Online:', online); +}); +``` ## Even More Information diff --git a/contents/docs/reading-data.mdx b/contents/docs/reading-data.mdx index 450659c3..88c39fba 100644 --- a/contents/docs/reading-data.mdx +++ b/contents/docs/reading-data.mdx @@ -305,131 +305,6 @@ z.query.issue.where({cmp, or, exists} => ); ``` -## Data Lifetime and Reuse - -Zero reuses data synced from prior queries to answer new queries when possible. This is what enables instant UI transitions. - -But what controls the lifetime of this client-side data? How can you know whether any particular query will return instant results? How can you know whether those results will be up to date or stale? - -The answer is that the data on the client is simply the union of rows returned from queries which are currently syncing. Once a row is no longer returned by any syncing query, it is removed from the client. Thus, there is never any stale data in Zero. - -So when you are thinking about whether a query is going to return results instantly, you should think about _what other queries are syncing_, not about what data is local. Data exists locally if and only if there is a query syncing that returns that data. - - - This is why we often say that despite the name `zero-cache`, Zero is not technically a cache. It's a *replica*. - -A cache has a random set of rows with a random set of versions. There is no expectation that the cache any particular rows, or that the rows' have matching versions. Rows are simply updated as they are fetched. - -A replica by contrast is eagerly updated, whether or not any client has requested a row. A replica is always very close to up-to-date, and always self-consistent. - -Zero is a _partial_ replica because it only replicates rows that are returned by syncing queries. - - - -## Query Lifecycle - - - -Queries can be either _active_ or _backgrounded_. An active query is one that is currently being used by the application. Backgrounded queries are not currently in use, but continue syncing in case they are needed again soon. - -Active queries are created one of three ways: - -1. The app calls `q.materialize()` to get a `View`. -2. The app uses a platform binding like React's `useQuery(q)`. -3. The app calls [`preload()`](#preloading) to sync larger queries without a view. - -Active queries sync until they are _deactivated_. The way this happens depends on how the query was created: - -1. For `materialize()` queries, the UI calls `destroy()` on the view. -2. For `useQuery()`, the UI unmounts the component (which calls `destroy()` under the covers). -3. For `preload()`, the UI calls `cleanup()` on the return value of `preload()`. - -### Background Queries - -By default a deactivated query stops syncing immediately. - -But it's often useful to keep queries syncing beyond deactivation in case the UI needs the same or a similar query in the near future. This is accomplished with the `ttl` parameter: - -```ts -const [user] = useQuery(z.query.user.where('id', userId), {ttl: '1d'}); -``` - -The `ttl` parameter specifies how long the app developer wishes the query to run in the background. The following formats are allowed (where `%d` is a positive integer): - -| Format | Meaning | -| --------- | ------------------------------------------------------------------------------------ | -| `none` | No backgrounding. Query will immediately stop when deactivated. This is the default. | -| `%ds` | Number of seconds. | -| `%dm` | Number of minutes. | -| `%dh` | Number of hours. | -| `%dd` | Number of days. | - - -Zero currently also accepts `ttl` values of `forever` and `%dy` (number of years). These are not recommended and will be removed in the next release. They were a misfeature. - -We realized long `ttl` values can lead to a lot of queries running in the background unnecessarily. If a new app release is deployed with new queries, the old queries keep running until their `ttl` expires, even though the app will never use them. - -We will be reworking this API to be less of a footgun in the next Zero release. For now we do not recommend using a `ttl` greater than `1d`. - - -If the UI re-requests a background query, it becomes an active query again. Since the query was syncing in the background, the very first synchronous result that the UI receives after reactivation will be up-to-date with the server (i.e., it will have `resultType` of `complete`). - -Just like other types of queries, the data from background queries is available for use by new queries. A common pattern in to [preload](#preloading) a subset of most commonly needed data with `{ttl: 'forever'}` and then do more specific queries from the UI with, e.g., `{ttl: '1d'}`. Most often the preloaded data will be able to answer user queries, but if not, the new query will be answered by the server and backgrounded for a day in case the user revisits it. - -### Client Capacity Management - -Zero has a default soft limit of 20,000 rows on the client-side, or about 20MB of data assuming 1KB rows. - -This limit can be increased with the [`--target-client-row-count`](./zero-cache-config#target-client-row-count) flag, but we do not recommend setting it higher than 100,000. - - -Contrary to the design of other sync engines, we believe that storing tons of data client-side doesn't make sense. Here are some reasons why: - -- Initial sync will be slow, slowing down initial app load. -- Because storage in browser tabs is unreliable, initial sync can occur surprisingly often. -- We want to answer queries _instantly_ as often as possible. This requires client-side data in memory on the main thread. If we have to page to disk, we may as well go to the network and reduce complexity. -- Even though Zero's queries are very efficient, they do still have some cost, especially hydration. Massive client-side storage would result in hydrating tons of queries that are unlikely to be used every time the app starts. - -Most importantly, no matter how much data you store on the client, there will be cases where you have to fallback to the server: - -- Some users might have huge amounts of data. -- Some users might have tiny amounts of available client storage. -- You will likely want the app to start fast and sync in the background. - -Because you have to be able to fallback to server the question becomes _what is the **right** amount of data to store on the client?_, not _how can I store the absolute max possible data on the client?_ - -The goal with Zero is to answer 99% of queries on the client from memory. The remaining 1% of queries can fallback gracefully to the server. 20,000 rows was chosen somewhat arbitrarily as a number of rows that was likely to be able to do this for many applications. - -There is no hard limit at 20,000 or 100,000. Nothing terrible happens if you go above. The thing to keep in mind is that: - -1. All those queries will revalidate every time your app boots. -2. All data synced to the client is in memory in JS. - - - -Here is how this limit is managed: - -1. Active queries are never destroyed, even if the limit is exceeded. Developers are expected to keep active queries well under the limit. -2. The `ttl` value counts from the moment a query deactivates. Backgrounded queries are destroyed immediately when the `ttl` is reached, even if the limit hasn't been reached. -3. If the client exceeds its limit, Zero will destroy backgrounded queries, least-recently-used first, until the store is under the limit again. - -### Thinking in Queries - -Although IVM is a very efficient way to keep queries up to date relative to re-running them, it isn't free. You still need to think about how many queries you are creating, how long they are kept alive, and how expensive they are. - -This is why Zero defaults to _not_ backgrounding queries and doesn't try to aggressively fill its client datastore to capacity. You should put some thought into what queries you want to run in the background, and for how long. - -Zero currently provides a few basic tools to understand the cost of your queries: - -- The client logs a warning for slow query materializations. Look for `Slow query materialization` in your logs. The default threshold is `5s` (including network) but this is configurable with the `slowMaterializeThreshold` parameter. -- The client logs the materialization time of all queries at the `debug` level. Look for `Materialized query` in your logs. -- The server logs a warning for slow query materializations. Look for `Slow query materialization` in your logs. The default threshold is `5s` but this is configurable with the `log-slow-materialize-threshold` configuration parameter. - -We will be adding more tools over time. - ## Completeness Zero returns whatever data it has on the client immediately for a query, then falls back to the server for any missing data. Sometimes it's useful to know the difference between these two types of results. To do so, use the `result` from `useQuery`: @@ -545,6 +420,145 @@ z.query.issue .preload(); ``` +## Data Lifetime and Reuse + +Zero reuses data synced from prior queries to answer new queries when possible. This is what enables instant UI transitions. + +But what controls the lifetime of this client-side data? How can you know whether any particular query will return instant results? How can you know whether those results will be up to date or stale? + +The answer is that the data on the client is simply the union of rows returned from queries which are currently syncing. Once a row is no longer returned by any syncing query, it is removed from the client. Thus, there is never any stale data in Zero. + +So when you are thinking about whether a query is going to return results instantly, you should think about _what other queries are syncing_, not about what data is local. Data exists locally if and only if there is a query syncing that returns that data. + + + This is why we often say that despite the name `zero-cache`, Zero is not technically a cache. It's a *replica*. + +A cache has a random set of rows with a random set of versions. There is no expectation that the cache any particular rows, or that the rows' have matching versions. Rows are simply updated as they are fetched. + +A replica by contrast is eagerly updated, whether or not any client has requested a row. A replica is always very close to up-to-date, and always self-consistent. + +Zero is a _partial_ replica because it only replicates rows that are returned by syncing queries. + + + +## Query Lifecycle + + + +Queries can be either _active_ or _cached_. An active query is one that is currently being used by the application. Cached queries are not currently in use, but continue syncing in case they are needed again soon. + +Active queries are created one of four ways: + +1. The app calls `q.materialize()` to get a `View`. +2. The app uses a framework binding like React's `useQuery(q)`. +3. The app calls [`preload()`](#preloading) to sync larger queries without a view. +4. The app calls `q.run()` to get a single result. + +Active queries sync until they are _deactivated_. The way this happens depends on how the query was created: + +1. For `materialize()` queries, the UI calls `destroy()` on the view. +2. For `useQuery()`, the UI unmounts the component (which calls `destroy()` under the covers). +3. For `preload()`, the UI calls `cleanup()` on the return value of `preload()`. +4. For `run()`, queries are automatically deactivated immediately after the result is returned. + +Additionally when a Zero instance closes, all active queries are automatically deactivated. This also happens when the containing page or script is unloaded. + +## TTLs + +Each query has a `ttl` that controls how long it stays cached. + + +If the user closes all tabs for your app, Zero stops running and the time that elapses doesn't count toward any TTLs. + +You do not need to account for such time when choosing a TTL – you only need to account for time your app is running *without* a query. + + +## TTL Defaults + +In most cases, the default TTL should work well: + +* `preload()` queries default to `ttl:'none'`, meaning they are not cached at all, and will stop syncing immediately when deactivated. But because `preload()` queries are typically registered at app startup and never shutdown, and [because the ttl clock only ticks while Zero is running](#the-ttl-clock-only-ticks-while-zero-is-running), this means that preload queries never get unregistered. +* Other queries have a default `ttl` of `5m` (five minutes). + +## Setting Different TTLs + +You can override the default TTL with the `ttl` parameter: + +```ts +// With useQuery(): +const [user] = useQuery( + z.query.user.where('id', userId), + {ttl: '5m'}); + +// With preload(): +z.query.user.where('id', userId).preload( + {ttl: '5m'}); + +// With run(): +const user = await z.query.user.where('id', userId).run( + {ttl: '5m'}); + +// With materialize(): +const view = z.query.user.where('id', userId).materialize( + {ttl: '5m'}); +``` + +TTLs up to `10m` (ten minutes) are currently supported. The following formats are allowed: + +| Format | Meaning | +| --------- | --------------------------------------------------------- | +| `none` | No caching. Query will immediately stop when deactivated. | +| `%ds` | Number of seconds. | +| `%dm` | Number of minutes. | + +## Choosing a TTL + +If you choose a different TTL, you should consider how likely it is that the query will be reused, and how far into the future this reuse will occur. Here are some guidelines to help you choose a TTL for common query types: + +### Preload Queries + +These queries load the most commonly needed data for your app. They are typically larger, run with the `preload()` method, and stay running the entire time your app is running. + +Because these queries run the entire time Zero runs, they do not need any TTL to keep them alive. And using a `ttl` for them is wasteful since when your app changes its preload query, it will end up running the old preload query *and* the new preload query, even though the app only cares about the new one. + +**Recommendation:** `ttl: 'none'` *(the default for `preload()`)*. + +### Navigational Queries + +These queries load data specific to a route. They are typically smaller and run with the `useQuery()` method. It is useful to cache them for a short time, so that they can be reactivated quickly if the user navigates back to the route. + +**Recommendation:** `ttl: '5m'` *(the default for `useQuery()`)*. + +### Ephemeral Queries + +These queries load data for a specific, short-lived user interaction and often come in large numbers (e.g., typeahead search). + +The chance of any specific ephemeral query being reused is low, so the benefit of caching them is also low. + +**Recommendation:** `useQuery(..., {ttl: 'none'})`)*. + +### Why Zero TTLs are Short + +Zero queries are not free. + +Just as in any database, queries consume resources on both the client and server. Memory is used to keep metadata about the query, and disk storage is used to keep the query's current state. + +We do drop this state after we haven't heard from a client for awhile, but this is only a partial improvement. If the client returns, we have to re-run the query to get the latest data. + +This means that we do not actually *want* to keep queries active unless there is a good chance they will be needed again soon. + +The default Zero TTL values might initially seem too short, but they are designed to work well with the way Zero's TTL clock works and strike a good balance between keeping queries alive long enough to be useful, while not keeping them alive so long that they consume resources unnecessarily. + + +Previous versions of Zero allowed longer TTLs. The API still supports these, but they are clamped to `10m` and Zero prints a warning. + +If you think you need longer TTLs, please [let us know](https://discord.zerosync.dev). We are still iterating on these APIs and may have missed something. Alternately we may be able to help you achieve your goal a different way. + + ## Running Queries Once Usually subscribing to a query is what you want in a reactive UI, but every so often you'll need to run a query just once. To do this, use the `run()` method: diff --git a/contents/docs/release-notes/0.22.mdx b/contents/docs/release-notes/0.22.mdx new file mode 100644 index 00000000..6346a104 --- /dev/null +++ b/contents/docs/release-notes/0.22.mdx @@ -0,0 +1,63 @@ +--- +title: Zero 0.22 +description: Simplified TTLs +--- + +## Install + +```bash +npm install @rocicorp/zero@0.22 +``` + +## Upgrading + +This release simplifies the concept of TTLs in Zero. + +See [hello-zero](https://github.com/rocicorp/hello-zero/pull/48), [hello-zero-solid](https://github.com/rocicorp/hello-zero-solid/pull/23), or [ztunes](https://github.com/rocicorp/ztunes/pull/17) for example upgrades. + +This release also adds anonymous telemetry collection. You can opt-out with the [DO_NOT_TRACK=1](../zero-cache-config#enable-telemetry) environment variable. Though we hope you will not, as it helps us improve Zero. + +### How TTLs Used to Work + +Previously, the TTL of a query simply measured normal "wall clock time" from when a query inactivated, including any time the app wasn't running at all. + +With experience, we realized this was a misfeature because it encouraged the use of very long or infinite TTLs, especially for preload queries. Developers always want preload queries registered, but since they do not know how long the app will be offline, they had no real choice but to use the TTL `forever`. + +These infinite TTLs would remain registered even after the app's code changed such that it no longer wanted them, slowing connections and incremental updates to process queries that the app was not even using. + +Worse, the prevalence of infinite TTLs in turns meant we needed some way to limit the size of the client cache. We introduced the "client row limit" for this. But developers would frequently accidentally blow through this limit, causing cache thrash. + +### How TTLs Work Now + +Now, query TTLs measure *"TTL time"* which ***only elapses while Zero is running***. This means that preload queries usually don't need a TTL at all, since they run the entire time Zero is active. This in turn means we can clamp TTLs to low values, which means queries evict naturally, which means we no longer need the client row limit either. + +### Using New TTLs + +You don't need to do anything specific to upgrade. Zero [will clamp your TTLs at `10m`](../reading-data#longer-ttls-are-disallowed) and print a warning. + +But for best results, please review the [new TTL documentation](../reading-data#query-lifecycle). In particular, see [how to set your TTLs](../reading-data#choosing-a-ttl) (TL;DR: You can often just remove them – [the defaults usually just work](../reading-data#ttl-defaults)). + +## Features + +- Rework and simplify query TTLs ([docs](/docs/reading-data#query-lifecycle), [upgrading](#upgrading)). +- SolidJS bindings are now fine-grained, improving performance ([PR](https://github.com/rocicorp/mono/pull/4575)). +- Restore `ZERO_CHANGE_STREAMER_URI` option ([doc](../zero-cache-config#change-streamer-uri), [PR](https://github.com/rocicorp/mono/pull/4584)). +- Add `useZeroOnline` to React and SolidJS bindings ([doc](/docs/offline#dealing-with-offline-today)). +- Add `ttl` to `run()` ([PR](https://github.com/rocicorp/mono/pull/4603)). +- Allow client to specify `push.url` in the `Zero` constructor ([doc](../custom-mutators#setting-up-the-server)). +- Add anonymous telemetry collection to `zero-cache` ([doc](../zero-cache-config#enable-telemetry)). + +## Fixes + +- Handle `public` in aliases, like `.from('public.table')` ([PR](https://github.com/rocicorp/mono/pull/4548)). +- Sorting by columns with `null` values was incorrect in some cases ([PR](https://github.com/rocicorp/mono/pull/4562)). +- Fix fencepost issue editing queries with limits ([PR](https://github.com/rocicorp/mono/pull/4563)). +- Fix copy runner to more reliably reuse connections ([PR](https://github.com/rocicorp/mono/pull/4573)). +- Queries early in startup could not contain non-latin chars ([PR](https://github.com/rocicorp/mono/pull/4607)). +- SolidJS: Export `createUseZero` ([PR](https://github.com/rocicorp/mono/pull/4610)). +- Support parallel rollouts of replication-manager and view-syncer ([PR](https://github.com/rocicorp/mono/pull/4658)). +- Fix upgrade path for already replicated array types ([PR](https://github.com/rocicorp/mono/pull/4676)). + +## Breaking Changes + +- Require Node v22+ (see [discussion](https://discord.com/channels/830183651022471199/1367274189178015955/1391931944089948361)) diff --git a/contents/docs/release-notes/index.mdx b/contents/docs/release-notes/index.mdx index 974579bd..7ad73e28 100644 --- a/contents/docs/release-notes/index.mdx +++ b/contents/docs/release-notes/index.mdx @@ -2,6 +2,7 @@ title: Release Notes --- +- [Zero 0.22: Simplified TTLs](/docs/release-notes/0.22) - [Zero 0.21: PG arrays, TanStack starter, and more](/docs/release-notes/0.21) - [Zero 0.20: Full Supabase support, performance improvements](/docs/release-notes/0.20) - [Zero 0.19: Many, many bugfixes and cleanups](/docs/release-notes/0.19) diff --git a/contents/docs/solidjs.mdx b/contents/docs/solidjs.mdx index eb0551d1..78dcc5dd 100644 --- a/contents/docs/solidjs.mdx +++ b/contents/docs/solidjs.mdx @@ -5,9 +5,9 @@ title: SolidJS Zero has built-in support for Solid. Here’s what basic usage looks like: ```tsx -import {createQuery} from '@rocicorp/zero/solid'; +import {useQuery} from '@rocicorp/zero/solid'; -const issues = createQuery(() => { +const issues = useQuery(() => { let issueQuery = z.query.issue .related('creator') .related('labels') diff --git a/contents/docs/sync.mdx b/contents/docs/sync.mdx index 4358235e..d22ccf78 100644 --- a/contents/docs/sync.mdx +++ b/contents/docs/sync.mdx @@ -60,8 +60,8 @@ The first mass-market sync engine was probably [Lotus Notes](https://en.wikipedi * Microsoft Exchange (1996) * Google Docs (2006) * Dropbox (2007) -* Superhuman (2017) * Figma (2016) +* Superhuman (2017) * Linear (2019) But sync engines are very hard to build. Typically, a new custom sync engine is built for each application at great expense. Knowledge about the specific application and its data model must be built into each sync engine to correctly handle conflicts and partial sync. diff --git a/contents/docs/zero-cache-config.mdx b/contents/docs/zero-cache-config.mdx index 53061de3..211c3db4 100644 --- a/contents/docs/zero-cache-config.mdx +++ b/contents/docs/zero-cache-config.mdx @@ -143,6 +143,15 @@ flag: `--change-streamer-port`
env: `ZERO_CHANGE_STREAMER_PORT`
required: `false` +### Change Streamer URI + +When unset, the zero-cache runs its own replication-manager (i.e. change-streamer). In production, this should be set to the replication-manager URI, which runs a change-streamer on port 4849. + +flag: `--change-streamer-uri`
+env: `ZERO_CHANGE_STREAMER_URI`
+required: `false` + + ### CVR DB The Postgres database used to store CVRs. CVRs (client view records) keep track of the data synced to clients in order to determine the diff to send on reconnect. If unspecified, the upstream-db will be used. @@ -161,6 +170,21 @@ flag: `--cvr-max-conns`
env: `ZERO_CVR_MAX_CONNS`
default: `30` +### Enable Telemetry + +Zero collects anonymous telemetry data to help us understand usage. We collect: + +- Zero version +- Uptime +- General machine information, like the number of CPUs, OS, CI/CD environment, etc. +- Information about usage, such as number of queries or mutations processed per hour. + +This is completely optional and can be disabled at any time. You can also opt-out by setting [`DO_NOT_TRACK=1`](https://consoledonottrack.com/). + +flag: `--enable-telemetry`
+env: `ZERO_ENABLE_TELEMETRY`
+default: `true` + ### Initial Sync Table Copy Workers The number of parallel workers used to copy tables during initial sync. Each worker copies a single table at a time, fetching rows in batches of `initial-sync-row-batch-size`. @@ -181,14 +205,22 @@ flag: `--lazy-startup`
env: `ZERO_LAZY_STARTUP`
default: `false` -### Litestream Executable +### Litestream Backup URL -Path to the litestream executable. This option has no effect if litestream-backup-url is unspecified. +The location of the litestream backup, usually an s3:// URL. This is only consulted by the replication-manager. view-syncers receive this information from the replication-manager. -flag: `--litestream-executable`
-env: `ZERO_LITESTREAM_EXECUTABLE`
+flag: `--litestream-backup-url`
+env: `ZERO_LITESTREAM_BACKUP_URL`
required: `false` +### Litestream Checkpoint Threshold MB + +The size of the WAL file at which to perform an SQlite checkpoint to apply the writes in the WAL to the main database file. Each checkpoint creates a new WAL segment file that will be backed up by litestream. Smaller thresholds may improve read performance, at the expense of creating more files to download when restoring the replica from the backup. + +flag: `--litestream-checkpoint-threshold-mb`
+env: `ZERO_LITESTREAM_CHECKPOINT_THRESHOLD_MB`
+default: `40` + ### Litestream Config Path Path to the litestream yaml config file. zero-cache will run this with its environment variables, which can be referenced in the file via `${ENV}` substitution, for example: @@ -202,29 +234,14 @@ flag: `--litestream-config-path`
env: `ZERO_LITESTREAM_CONFIG_PATH`
default: `./src/services/litestream/config.yml` -### Litestream Log Level - -flag: `--litestream-log-level`
-env: `ZERO_LITESTREAM_LOG_LEVEL`
-default: `warn` -values: `debug`, `info`, `warn`, `error` - -### Litestream Backup URL +### Litestream Executable -The location of the litestream backup, usually an s3:// URL. This is only consulted by the replication-manager. view-syncers receive this information from the replication-manager. +Path to the litestream executable. This option has no effect if litestream-backup-url is unspecified. -flag: `--litestream-backup-url`
-env: `ZERO_LITESTREAM_BACKUP_URL`
+flag: `--litestream-executable`
+env: `ZERO_LITESTREAM_EXECUTABLE`
required: `false` -### Litestream Checkpoint Threshold MB - -The size of the WAL file at which to perform an SQlite checkpoint to apply the writes in the WAL to the main database file. Each checkpoint creates a new WAL segment file that will be backed up by litestream. Smaller thresholds may improve read performance, at the expense of creating more files to download when restoring the replica from the backup. - -flag: `--litestream-checkpoint-threshold-mb`
-env: `ZERO_LITESTREAM_CHECKPOINT_THRESHOLD_MB`
-default: `40` - ### Litestream Incremental Backup Interval Minutes The interval between incremental backups of the replica. Shorter intervals reduce the amount of change history that needs to be replayed when catching up a new view-syncer, at the expense of increasing the number of files needed to download for the initial litestream restore. @@ -233,13 +250,40 @@ flag: `--litestream-incremental-backup-interval-minutes`
env: `ZERO_LITESTREAM_INCREMENTAL_BACKUP_INTERVAL_MINUTES`
default: `15` -### Litestream Snapshot Backup Interval Hours -The interval between snapshot backups of the replica. Snapshot backups make a full copy of the database to a new litestream generation. This improves restore time at the expense of bandwidth. Applications with a large database and low write rate can increase this interval to reduce network usage for backups (litestream defaults to 24 hours). +### Litestream Multipart Concurrency -flag: `--litestream-snapshot-backup-interval-hours`
-env: `ZERO_LITESTREAM_SNAPSHOT_BACKUP_INTERVAL_HOURS`
-default: `12` +The number of parts (of size --litestream-multipart-size bytes) to upload or download in parallel when backing up or restoring the snapshot. + +flag: `--litestream-multipart-concurrency`
+env: `ZERO_LITESTREAM_MULTIPART_CONCURRENCY`
+default: `48` + +### Litestream Multipart Size + +The size of each part when uploading or downloading the snapshot with +`--litestream-multipart-concurrency`. Note that up to concurrency * size +bytes of memory are used when backing up or restoring the snapshot. + +flag: `--litestream-multipart-size`
+env: `ZERO_LITESTREAM_MULTIPART_SIZE`
+default: `16777216` (16 MiB) + +### Litestream Log Level + +flag: `--litestream-log-level`
+env: `ZERO_LITESTREAM_LOG_LEVEL`
+default: `warn` +values: `debug`, `info`, `warn`, `error` + +### Litestream Port + +Port on which litestream exports metrics, used to determine the replication +watermark up to which it is safe to purge change log records. + +flag: `--litestream-port`
+env: `ZERO_LITESTREAM_PORT`
+default: `--port + 2` ### Litestream Restore Parallelism @@ -249,6 +293,14 @@ flag: `--litestream-restore-parallelism`
env: `ZERO_LITESTREAM_RESTORE_PARALLELISM`
default: `48` +### Litestream Snapshot Backup Interval Hours + +The interval between snapshot backups of the replica. Snapshot backups make a full copy of the database to a new litestream generation. This improves restore time at the expense of bandwidth. Applications with a large database and low write rate can increase this interval to reduce network usage for backups (litestream defaults to 24 hours). + +flag: `--litestream-snapshot-backup-interval-hours`
+env: `ZERO_LITESTREAM_SNAPSHOT_BACKUP_INTERVAL_HOURS`
+default: `12` + ### Log Format Use text for developer-friendly console logging and json for consumption by structured-logging services. @@ -291,14 +343,6 @@ flag: `--log-slow-row-threshold`
env: `ZERO_LOG_SLOW_ROW_THRESHOLD`
default: `2` -### Log Trace Collector - -The URL of the trace collector to which to send trace data. Traces are sent over http. Port defaults to 4318 for most collectors. - -flag: `--log-trace-collector`
-env: `ZERO_LOG_TRACE_COLLECTOR`
-required: `false` - ### Number of Sync Workers The number of processes to use for view syncing. Leave this unset to use the maximum available parallelism. If set to 0, the server runs without sync workers, which is the configuration for running the replication-manager. @@ -331,9 +375,37 @@ flag: `--port`
env: `ZERO_PORT`
default: `4848` +### Push API Key + +An optional secret used to authorize zero-cache to call the API server handling writes. + +flag: `--push-api-key`
+env: `ZERO_PUSH_API_KEY`
+required: `false` + +### Push Forward Cookies + +If true, zero-cache will forward cookies from the request. This is useful for passing authentication cookies to the API server. If false, cookies are not forwarded. + +flag: `--push-forward-cookies`
+env: `ZERO_PUSH_FORWARD_COOKIES`
+default: `false` + ### Push URL -The URL of the API server to which zero-cache will push mutations. Required if you use [custom mutators](/docs/custom-mutators). +The URL of the API server to which zero-cache will push custom mutations. + +Can also be a pattern, or set of patterns, which is used in conjunction with the `push.url` paramter of the `Zero` constructor. In this case, the pattern specifies the URLs which Zero will allow the constructor to specify. + +Examples: + +* `https://*.example.com` matches `https://api.example.com` and `https://www.example.com` +* `https://*.example.com` does not match `https://example.com` (no subdomain) +* `https://*.example.com` does not match `https://api.example.com/path` (no trailing path) +* `https://*.*.example.com` matches `https://api.v1.example.com` and `https://www.v2.example.com` +* `https://*.*.example.com` does not match `https://api.example.com` (only one subdomain) + +Currently, wildcards are only allowed for subdomains. flag: `--push-url`
env: `ZERO_PUSH_URL`
@@ -373,14 +445,6 @@ flag: `--storage-db-tmp-dir`
env: `ZERO_STORAGE_DB_TMP_DIR`
required: `false` -### Target Client Row Count - -A soft limit on the number of rows Zero will keep on the client. 20k is a good default value for most applications, and we do not recommend exceeding 100k. See [Client Capacity Management](/docs/reading-data#client-capacity-management) for more details. - -flag: `--target-client-row-count`
-env: `ZERO_TARGET_CLIENT_ROW_COUNT`
-default: `20000` - ### Task ID Globally unique identifier for the zero-cache instance. Setting this to a platform specific task identifier can be useful for debugging. If unspecified, zero-cache will attempt to extract the TaskARN if run from within an AWS ECS container, and otherwise use a random string. diff --git a/public/images/reading-data/query-lifecycle.png b/public/images/reading-data/query-lifecycle.png deleted file mode 100644 index 868ec2398dc213d31016084c6274fe805ce083c7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 241695 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%0DuL$`}NZ=-=F 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 z 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 rkL>xMdHSDu`mp1Aixus2;{1LS6em?sss! diff --git a/public/images/reading-data/query-lifecycle.svg b/public/images/reading-data/query-lifecycle.svg new file mode 100644 index 00000000..8949e31c --- /dev/null +++ b/public/images/reading-data/query-lifecycle.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + From d04d03047cf520a5ff11a31b43f584cec71e5960 Mon Sep 17 00:00:00 2001 From: Aaron Boodman Date: Mon, 4 Aug 2025 13:05:45 -1000 Subject: [PATCH 12/28] spruce --- contents/docs/release-notes/0.22.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contents/docs/release-notes/0.22.mdx b/contents/docs/release-notes/0.22.mdx index 6346a104..9466319e 100644 --- a/contents/docs/release-notes/0.22.mdx +++ b/contents/docs/release-notes/0.22.mdx @@ -1,6 +1,6 @@ --- title: Zero 0.22 -description: Simplified TTLs +description: Simplified TTLs, fine-grained SolidJS, and more --- ## Install From feab86ba78a8d43c724daed3f0db11bb5764ec10 Mon Sep 17 00:00:00 2001 From: Darick Tong Date: Tue, 5 Aug 2025 12:22:48 +0900 Subject: [PATCH 13/28] chore: update sst deployment example --- contents/docs/deployment.mdx | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/contents/docs/deployment.mdx b/contents/docs/deployment.mdx index f9a23d0a..755600e7 100644 --- a/contents/docs/deployment.mdx +++ b/contents/docs/deployment.mdx @@ -166,7 +166,20 @@ export default $config({ ZERO_LITESTREAM_BACKUP_URL: $interpolate`s3://${replicationBucket.name}/backup`, ZERO_NUM_SYNC_WORKERS: '0', }, + loadBalancer: { + public: false, + ports: [ + { + listen: '80/http', + forward: '4849/http', + }, + ], + }, transform: { + service: { + // e.g. extend the grace period for initial sync of large databases + healthCheckGracePeriodSeconds: 600, + } target: { healthCheck: { enabled: true, @@ -197,12 +210,24 @@ export default $config({ }, environment: { ...commonEnv, - ZERO_CHANGE_STREAMER_MODE: 'discover', + ZERO_CHANGE_STREAMER_URI: replicationManager.url, + }, + loadBalancer: { + ports: [ + { + listen: '80/http', + forward: '4848/http', + }, + ], }, logging: { retention: '1 month', }, transform: { + service: { + // e.g. extend the grace period for initial sync of large databases + healthCheckGracePeriodSeconds: 600, + } target: { healthCheck: { enabled: true, @@ -220,11 +245,6 @@ export default $config({ }, }, }, - { - // Wait for replication-manager to come up first, for breaking changes - // to replication-manager interface. - dependsOn: [replicationManager], - }, ); // Permissions deployment From 05d2c8af521c2537455fdd29cbdbd74c72547d9c Mon Sep 17 00:00:00 2001 From: Darick Tong Date: Tue, 5 Aug 2025 12:51:39 +0900 Subject: [PATCH 14/28] chore: update raw aws docs back to CHANGE_STREAMER_URI --- contents/docs/deployment.mdx | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/contents/docs/deployment.mdx b/contents/docs/deployment.mdx index 755600e7..ad411594 100644 --- a/contents/docs/deployment.mdx +++ b/contents/docs/deployment.mdx @@ -458,7 +458,7 @@ Run `zero-cache` as two Fargate services (using the same [rocicorp/zero](https:/ #### view-syncer - `zero-cache` config: - - `ZERO_CHANGE_STREAMER_MODE=discover` + - `ZERO_CHANGE_STREAMER_URI=http://{replication-manager}` - Task count: **N** - You can also use dynamic scaling @@ -468,7 +468,10 @@ Run `zero-cache` as two Fargate services (using the same [rocicorp/zero](https:/ - Set `ZERO_CVR_MAX_CONNS` and `ZERO_UPSTREAM_MAX_CONNS` appropriately so that the total connections from both running and updating `view-syncers` (e.g. DesiredCount \* MaximumPercent) do not exceed your database’s `max_connections`. - The `{generation}` component of the `s3://{bucketName}/{generation}` URL is an arbitrary path component that can be modified to reset the replica (e.g. a date, a number, etc.). Setting this to a new path is the multi-node equivalent of deleting the replica file to resync. - Note: `zero-cache` does not manage cleanup of old generations. -- The `replication-manager` serves requests on port **4849**. Routing from the `view-syncer` to the `http://{replication-manager}` is handled internally by storing data in the `changedb`. +- The `replication-manager` serves requests on port **4849**. Routing from the `view-syncer` to the `http://{replication-manager}` can be achieved using the following mechanisms (in order of preference): + - An internal load balancer + - [Service Connect](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/service-connect.html) + - [Service Discovery](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/service-discovery.html) - Fargate ephemeral storage is used for the replica. - The default size is 20GB. This can be increased up to 200GB - Allocate at least twice the size of the database to support the internal VACUUM operation. From f01a74abbd63a7820297b10bd2e756f3b98d2052 Mon Sep 17 00:00:00 2001 From: Aaron Boodman Date: Mon, 4 Aug 2025 23:09:26 -1000 Subject: [PATCH 15/28] Fix broken links --- contents/docs/auth.mdx | 4 ++-- contents/docs/custom-mutators.mdx | 2 +- contents/docs/debug/slow-queries.mdx | 2 +- contents/docs/deployment.mdx | 12 ++++++------ contents/docs/introduction.mdx | 4 ++-- contents/docs/reading-data.mdx | 4 ++-- contents/docs/release-notes/0.21.mdx | 2 +- contents/docs/release-notes/0.5.mdx | 2 +- contents/docs/release-notes/0.6.mdx | 2 +- contents/docs/sync.mdx | 2 +- contents/docs/zero-schema.mdx | 6 +++--- package.json | 2 +- 12 files changed, 22 insertions(+), 22 deletions(-) diff --git a/contents/docs/auth.mdx b/contents/docs/auth.mdx index 2ce8593d..716d820b 100644 --- a/contents/docs/auth.mdx +++ b/contents/docs/auth.mdx @@ -139,8 +139,8 @@ Any data placed into your JWT (claims) can be used by permission rules on the ba const isAdminRule = (decodedJWT, {cmp}) => cmp(decodedJWT.role, '=', 'admin'); ``` -See the [permissions](permissions) section for more details. +See the [permissions](/docs/permissions) section for more details. ## Examples -See [zbugs](samples#zbugs) or [hello-zero](samples#hello-zero). +See [zbugs](/docs/samples#zbugs) or [hello-zero](/docs/samples#hello-zero). diff --git a/contents/docs/custom-mutators.mdx b/contents/docs/custom-mutators.mdx index a5ac4c57..899a025b 100644 --- a/contents/docs/custom-mutators.mdx +++ b/contents/docs/custom-mutators.mdx @@ -689,4 +689,4 @@ This will be documented in the future, but you can refer to the [PushProcessor]( ## Examples - Zbugs uses [custom mutators](https://github.com/rocicorp/mono/blob/a76c9a61670cc09e1a9fe7ab795749f3eef25577/apps/zbugs/shared/mutators.ts) for all mutations, [write permissions](https://github.com/rocicorp/mono/blob/a76c9a61670cc09e1a9fe7ab795749f3eef25577/apps/zbugs/shared/mutators.ts#L61), and [notifications](https://github.com/rocicorp/mono/blob/a76c9a61670cc09e1a9fe7ab795749f3eef25577/apps/zbugs/server/server-mutators.ts#L35). -- `hello-zero-solid` uses custom mutators for all [mutations](TODO), and for [permissions](TODO). +- [`hello-zero-solid`](./samples#hello-zero-solid) uses custom mutators for all mutations and for permissions. diff --git a/contents/docs/debug/slow-queries.mdx b/contents/docs/debug/slow-queries.mdx index 2100a5a4..ac0fdeab 100644 --- a/contents/docs/debug/slow-queries.mdx +++ b/contents/docs/debug/slow-queries.mdx @@ -31,7 +31,7 @@ If you are seeing unexpected UI flicker when moving between views, it is likely You may alternately want to [preload some data](https://zero.rocicorp.dev/docs/reading-data#preloading) at app startup. -Conversely, if you are setting `ttl` to long values, then it can happen that you have many backgrounded queries still running that the app is not using. You can see which queries are running using the [inspector](/docs/inspector). Ensure that only expected queries are running. See [long TTLs](/docs/reading-data#long-ttl-warning) for more information. +Conversely, if you are setting `ttl` to long values, then it can happen that you have many backgrounded queries still running that the app is not using. You can see which queries are running using the [inspector](./inspector). Ensure that only expected queries are running. See [long TTLs](/docs/reading-data#long-ttl-warning) for more information. ## Check Storage diff --git a/contents/docs/deployment.mdx b/contents/docs/deployment.mdx index ad411594..1cc55569 100644 --- a/contents/docs/deployment.mdx +++ b/contents/docs/deployment.mdx @@ -4,7 +4,7 @@ title: Deploying Zero To deploy a Zero app, you need to: -1. Deploy your backend database. Most standard Postgres hosts [work with Zero](connecting-to-postgres). +1. Deploy your backend database. Most standard Postgres hosts [work with Zero](/docs/connecting-to-postgres). 1. Deploy `zero-cache`. We provide a [Docker image](https://hub.docker.com/r/rocicorp/zero) that can work with most Docker hosts. 1. Deploy your frontend. You can use any hosting service like Vercel or Netlify. @@ -65,7 +65,7 @@ To upgrade Zero to a new major version, first deploy the new zero-cache, then th ## Configuration -The `zero-cache` image is configured via environment variables. See [zero-cache Config](./zero-cache-config) for available options. +The `zero-cache` image is configured via environment variables. See [zero-cache Config](/docs/zero-cache-config) for available options. When using custom mutators, don't forget to set the push api url with @@ -80,7 +80,7 @@ The setup below costs about $35/month. You can scale it up or down as needed by ### Setup Upstream -Create an upstream Postgres database server somewhere. See [Connecting to Postgres](connecting-to-postgres) for details. Populate the schema and any initial data for your application. +Create an upstream Postgres database server somewhere. See [Connecting to Postgres](/docs/connecting-to-postgres) for details. Populate the schema and any initial data for your application. ### Setup AWS @@ -296,11 +296,11 @@ If unsuccessful, you can get detailed logs with `npx sst deploy --verbose`. [Com ## Guide: Single-Node on Fly.io -Let's deploy the [Quickstart](quickstart) app to [Fly.io](https://fly.io). We'll use Fly.io for both the database and `zero-cache`. +Let's deploy the [Quickstart](/docs/quickstart) app to [Fly.io](https://fly.io). We'll use Fly.io for both the database and `zero-cache`. ### Setup Quickstart -Go through the [Quickstart](quickstart) guide to get the app running locally. +Go through the [Quickstart](/docs/quickstart) guide to get the app running locally. ### Setup Fly.io @@ -450,7 +450,7 @@ Run `zero-cache` as two Fargate services (using the same [rocicorp/zero](https:/ #### replication-manager -- `zero-cache` [config](https://zero.rocicorp.dev/docs/zero-cache-config): +- `zero-cache` config: - `ZERO_LITESTREAM_BACKUP_URL=s3://{bucketName}/{generation}` - `ZERO_NUM_SYNC_WORKERS=0` - Task count: **1** diff --git a/contents/docs/introduction.mdx b/contents/docs/introduction.mdx index 52e3c9f7..7ffac49d 100644 --- a/contents/docs/introduction.mdx +++ b/contents/docs/introduction.mdx @@ -2,7 +2,7 @@ title: Welcome to Zero Alpha --- -Zero is a new kind of [sync engine](./sync) powered by queries. +Zero is a new kind of [sync engine](/docs/sync) powered by queries. Rather than syncing entire tables to the client, or using static rules to carefully specify what to sync, you just write queries directly in your client code. Queries can access the entire backend database. @@ -10,4 +10,4 @@ Zero caches the data for queries locally on the device, and reuses that data aut For typical applications, the result is that almost all queries are answered locally, instantly. It feels like you have access to the entire backend database directly from the client in memory. Occasionally, when you do a more specific query, Zero falls back to the server. But this happens automatically without any extra work required. -Zero is made possible by a custom streaming query engine we built called [ZQL](reading-data), which uses [Incremental View Maintenance](https://www.vldb.org/pvldb/vol16/p1601-budiu.pdf) on both client and server to efficiently keep large, complex queries up to date. +Zero is made possible by a custom streaming query engine we built called [ZQL](/docs/reading-data), which uses [Incremental View Maintenance](https://www.vldb.org/pvldb/vol16/p1601-budiu.pdf) on both client and server to efficiently keep large, complex queries up to date. diff --git a/contents/docs/reading-data.mdx b/contents/docs/reading-data.mdx index 88c39fba..9a982ac5 100644 --- a/contents/docs/reading-data.mdx +++ b/contents/docs/reading-data.mdx @@ -8,7 +8,7 @@ Inspired by SQL, ZQL is expressed in TypeScript with heavy use of the builder pa ZQL queries are composed of one or more _clauses_ that are chained together into a _query_. -Unlike queries in classic databases, the result of a ZQL query is a _view_ that updates automatically and efficiently as the underlying data changes. You can call a query’s `materialize()` method to get a view, but more typically you run queries via some framework-specific bindings. For example see `useQuery` for [React](react) or [SolidJS](solidjs). +Unlike queries in classic databases, the result of a ZQL query is a _view_ that updates automatically and efficiently as the underlying data changes. You can call a query’s `materialize()` method to get a view, but more typically you run queries via some framework-specific bindings. For example see `useQuery` for [React](/docs/react) or [SolidJS](/docs/solidjs). This means you should not modify the data directly. Instead, clone the data and modify the clone. @@ -556,7 +556,7 @@ The default Zero TTL values might initially seem too short, but they are designe Previous versions of Zero allowed longer TTLs. The API still supports these, but they are clamped to `10m` and Zero prints a warning. -If you think you need longer TTLs, please [let us know](https://discord.zerosync.dev). We are still iterating on these APIs and may have missed something. Alternately we may be able to help you achieve your goal a different way. +If you think you need longer TTLs, please [let us know](https://discord.rocicorp.dev). We are still iterating on these APIs and may have missed something. Alternately we may be able to help you achieve your goal a different way. ## Running Queries Once diff --git a/contents/docs/release-notes/0.21.mdx b/contents/docs/release-notes/0.21.mdx index 3da33cd3..68bb372f 100644 --- a/contents/docs/release-notes/0.21.mdx +++ b/contents/docs/release-notes/0.21.mdx @@ -17,7 +17,7 @@ See [hello-zero](https://github.com/rocicorp/hello-zero/pull/44) for an example ## Features -- New _"ztunes"_ sample using TanStack, Drizzle, Better Auth, and Fly.io ([docs](/samples#ztunes)). +- New _"ztunes"_ sample using TanStack, Drizzle, Better Auth, and Fly.io ([docs](/docs/samples#ztunes)). - Add initial support for Postgres arrays ([docs](/docs/postgres-support#column-types), [bug](https://bugs.rocicorp.dev/issue/3617)). - Improved React lifecycle management with `ZeroProvider` ([docs](/docs/react#zero-provider), [PR](https://github.com/rocicorp/mono/pull/4527)). - Expose `Zero` instances automatically at `__zero` ([docs](/docs/debug/inspector#creating-an-inspector), [PR](https://github.com/rocicorp/mono/pull/4526)). diff --git a/contents/docs/release-notes/0.5.mdx b/contents/docs/release-notes/0.5.mdx index 4ab763d4..11b88330 100644 --- a/contents/docs/release-notes/0.5.mdx +++ b/contents/docs/release-notes/0.5.mdx @@ -24,7 +24,7 @@ Basically: ## Features - Added support for JSON columns in Postgres ([documentation](/docs/postgres-support)). -- Zero pacakage now includes `zero-sqlite3`, which can be used to explore our sqlite files ([documentation](/docs/recipes)). +- Zero pacakage now includes `zero-sqlite3`, which can be used to explore our sqlite files ([documentation](/docs/debug/replication#inspecting)). ## Fixes diff --git a/contents/docs/release-notes/0.6.mdx b/contents/docs/release-notes/0.6.mdx index 4995b8cf..9cb7e5e0 100644 --- a/contents/docs/release-notes/0.6.mdx +++ b/contents/docs/release-notes/0.6.mdx @@ -40,7 +40,7 @@ This release is a bit harder to upgrade to than previous alphas. For a step-by-s - Default max connections of zero-cache more conservatively so that it should fit with even common small Postgres configurations. - `zero-cache` now accepts requests with any base path, not just `/api`. The `server` parameter to the `Zero` client constructor can now be a host (`https://myapp-myteam.zero.ms`) or a host with a single path component (`https://myapp-myteam.zero.ms/zero`). These two changes together allow hosting `zero-cache` on same domain with an app that already uses the `/api` prefix ([bug](https://bugs.rocicorp.dev/issue/3115)). - Allow Postgres columns with default values, but don’t sync them ([documentation](/docs/postgres-support#column-defaults)). -- The `npx zero-sqlite` utility now accepts all the same flags and arguments that `sqlite3` does ([documentation](/docs/debugging/replication)). +- The `npx zero-sqlite` utility now accepts all the same flags and arguments that `sqlite3` does ([documentation](/docs/debug/replication#inspecting)). ## zbugs diff --git a/contents/docs/sync.mdx b/contents/docs/sync.mdx index d22ccf78..48dc7466 100644 --- a/contents/docs/sync.mdx +++ b/contents/docs/sync.mdx @@ -70,7 +70,7 @@ There have also been some attempts at general-purpose sync engines: * [Firebase Realtime Database](https://firebase.google.com/products/realtime-database) (2012) - a cloud-hosted database and that syncs. * [PouchDB](https://pouchdb.com/) (2013) - a sync engine attachment for CouchDB. -* [Realm](https://realm.io/) (2016) - a mobile database with sync capabilities. +* [Realm](https://github.com/realm) (2016) - a mobile database with sync capabilities. * [Replicache](https://replicache.dev/) (2020) - The predecessor to Zero, a JavaScript library for building collaborative applications with real-time sync. But all have suffered from one or more significant problems that have prevented widespread adoption: diff --git a/contents/docs/zero-schema.mdx b/contents/docs/zero-schema.mdx index 2f2ef13d..e0670156 100644 --- a/contents/docs/zero-schema.mdx +++ b/contents/docs/zero-schema.mdx @@ -13,7 +13,7 @@ Zero applications have both a _database schema_ (the normal backend database sch slug="generating" heading="You do not need to define the Zero schema by hand" > - [Community-contributed converters](./community#database-tools) exist for + [Community-contributed converters](/docs/community#database-tools) exist for Prisma and Drizzle that generate the tables and relationships. It is good to know how the underlying Zero schemas work, however, for debugging and conceptual understanding. @@ -101,7 +101,7 @@ An optional column can store a value of the specified type or `null` to mean _no ### Enumerations -Use the `enumeration` helper to define a column that can only take on a specific set of values. This is most often used alongside an [`enum` Postgres column type](postgres-support#column-types). +Use the `enumeration` helper to define a column that can only take on a specific set of values. This is most often used alongside an [`enum` Postgres column type](/docs/postgres-support#column-types). ```tsx import {table, string, enumeration} from '@rocicorp/zero'; @@ -164,7 +164,7 @@ const messageRelationships = relationships(message, ({one, many}) => ({ })); ``` -This creates "sender" and "replies" relationships that can later be queried with the [`related` ZQL clause](./reading-data#relationships): +This creates "sender" and "replies" relationships that can later be queried with the [`related` ZQL clause](/docs/reading-data#relationships): ```ts const messagesWithSenderAndReplies = z.query.messages diff --git a/package.json b/package.json index 6cb47831..be2c9ee7 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,7 @@ "start": "npm run build:search && next start", "lint": "next lint", "format": "prettier --write **/*.{ts,tsx,js,json,md,mdx}", - "links": "blc http://localhost:3000/ -ro --exclude 'https://discord.rocicorp.dev/' --exclude 'https://bsky.app/profile/zero.rocicorp.dev' --exclude 'https://x.com/rocicorp_zero'" + "links": "blc http://localhost:3000/ -ro --exclude 'https://discord.rocicorp.dev/' --exclude 'https://bsky.app/profile/zero.rocicorp.dev' --exclude 'https://x.com/rocicorp_zero' --exclude 'https://x.com/zero__ms'" }, "dependencies": { "@radix-ui/react-collapsible": "^1.1.0", From 322837b61ac2fa699d40eb34661afcf7d0bf0da7 Mon Sep 17 00:00:00 2001 From: Aaron Boodman Date: Wed, 6 Aug 2025 23:08:58 -1000 Subject: [PATCH 16/28] spruce --- contents/docs/when-to-use.mdx | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/contents/docs/when-to-use.mdx b/contents/docs/when-to-use.mdx index b9028860..f0238bb4 100644 --- a/contents/docs/when-to-use.mdx +++ b/contents/docs/when-to-use.mdx @@ -47,9 +47,15 @@ Zero doesn't support [offline writes](./offline) yet. Zero is written in TypeScript and only supports TypeScript clients. -### The total backend dataset is > ~1TB +### The total backend dataset is > ~100GB -Zero stores a replica of your database (at least the parts that can sync to client) in a SQLite database stored on attached SSD within the Zero server. The ultimate limit of this database size is the size of attached SSD. But 1TB is a reasonable practical limit today. +Zero stores a replica of your database (at least the subset you want to be syncable to clients) in a SQLite database owned by zero-cache. + +Zero's query engine is built assuming very fast local access to this replica (i.e., attached NVMe). But other setups are technically supported and work for smaller data. + +The ultimate size limit on the database that Zero can work with is the size limit of this SQLite database. So [up to 45TB on EC2](https://aws.amazon.com/ec2/instance-types/) at time of writing. + +However, most of our experience with Zero so far is with much smaller workloads. We currently recommend Zero for use with datasets smaller than 100GB, but are working to improve this in the beta timeframe. ## Zero Might Not be a Good Fit **Yet** From 6e5d2449cd5022cfb8c2d1d256f2a4baaa6c3450 Mon Sep 17 00:00:00 2001 From: Chase Adams Date: Thu, 7 Aug 2025 16:00:57 -0700 Subject: [PATCH 17/28] fix: changed fallback to 404 and not error --- assets/search-index.json | 96 +++++++++++++++++++++++----------------- lib/markdown.ts | 39 +++++++++------- next.config.mjs | 5 +++ 3 files changed, 83 insertions(+), 57 deletions(-) diff --git a/assets/search-index.json b/assets/search-index.json index b643b8bb..7ca3c43d 100644 --- a/assets/search-index.json +++ b/assets/search-index.json @@ -31,7 +31,7 @@ "id": "4-custom-mutators", "title": "Custom Mutators", "url": "/docs/custom-mutators", - "content": "Custom Mutators are a new way to write data in Zero that is much more powerful than the original \"CRUD\" mutator API. Instead of having only the few built-in insert/update/delete write operations for each table, custom mutators allow you to create your own write operations using arbitrary code. This makes it possible to do things that are impossible or awkward with other sync engines. For example, you can create custom mutators that: Perform arbitrary server-side validation Enforce fine-grained permissions Send email notifications Query LLMs Use Yjs for collaborative editing … and much, much more – custom mutators are just code, and they can do anything code can do! Despite their increased power, custom mutators still participate fully in sync. They execute instantly on the local device, immediately updating all active queries. They are then synced in the background to the server and to other clients. \\ 100) { throw new Error(`Title is too long`); } await tx.mutate.issue.update({id, title}); } ``` Each custom mutator gets two implementations: one on the client and one on the server. The client implementation must be written in TypeScript against the Zero Transaction interface, using ZQL for reads and a CRUD-style API for writes. The server implementation runs on your server, in your push endpoint, against your database. In principle, it can be written in any language and use any data access library. For example you could have the following Go-based server implementation of the same mutator: ```go func updateIssueOnServer(tx *sql.Tx, id string, title string) error { // Validate title length. if len(title) > 100 { return errors.New(\"Title is too long\") } _, err := tx.Exec(\"UPDATE issue SET title = $1 WHERE id = $2\", title, id) return err } ``` In practice however, most Zero apps use TypeScript on the server. For these users we provide a handy ServerTransaction that implements ZQL against Postgres, so that you can share code between client and server mutators naturally. So on a TypeScript server, that server mutator can just be: ```ts async function updateIssueOnServer( tx: ServerTransaction, {id, title}, {id: string, title: string}, ) { // Delegate to client mutator. // The `ServerTransaction` here has a different implementation // that runs the same ZQL queries against Postgres! await updateIssue(tx, {id, title}); } ``` Reusing ZQL on the server is a handy – and we expect frequently used – option, but not a requirement. Server Authority You may be wondering what happens if the client and server mutators implementations don't match. Zero is an example of a server-authoritative sync engine. This means that the server mutator always takes precedence over the client mutator. The result from the client mutator is considered speculative and is discarded as soon as the result from the server mutator is known. This is a very useful feature: it enables server-side validation, permissions, and other server-specific logic. Imagine that you wanted to use an LLM to detect whether an issue update is spammy, rather than a simple length check. We can just add that to our server mutator: ```ts async function updateIssueOnServer( tx: ServerTransaction, {id, title}: {id: string; title: string}, ) { const response = await llamaSession.prompt( `Is this title update likely spam?\\n\\n${title}\\n\\nResponse \"yes\" or \"no\"`, ); if (/yes/i.test(response)) { throw new Error(`Title is likely spam`); } // delegate rest of implementation to client mutator await updateIssue(tx, {id, title}); } ``` If the server detects that the mutation is spammy, the client will see the error message and the mutation will be rolled back. If the server mutator succeeds, the client mutator will be rolled back and the server result will be applied. Life of a Mutation Now that we understand what client and server mutations are, let's walk through how they work together with Zero to sync changes from a source client to the server and then other clients: When you call a custom mutator on the client, Zero runs your client-side mutator immediately on the local device, updating all active queries instantly. In the background, Zero then sends a mutation (a record of the mutator having run with certain arguments) to your server's push endpoint. Your push endpoint runs the push protocol, executing the server-side mutator in a transaction against your database and recording the fact that the mutation ran. Optionally, you use our PushProcessor class to handle this for you, but you can also implement it yourself. The changes to the database are replicated to zero-cache as normal. zero-cache calculates the updates to active queries and sends rows that have changed to each client. It also sends information about the mutations that have been applied to the database. Clients receive row updates and apply them to their local cache. Any pending mutations which have been applied to the server have their local effects rolled back. Client-side queries are updated and the user sees the changes. Using Custom Mutators Registering Client Mutators By convention, the client mutators are defined with a function called createMutators in a file called mutators.ts: ```ts // mutators.ts import {CustomMutatorDefs} from '@rocicorp/zero'; import {schema} from './schema'; export function createMutators() { return { issue: { update: async (tx, {id, title}: {id: string; title: string}) => { // Validate title length. Legacy issues are exempt. if (title.length > 100) { throw new Error(`Title is too long`); } await tx.mutate.issue.update({id, title}); }, }, } as const satisfies CustomMutatorDefs; } ``` The mutators.ts convention allows mutator implementations to be easily reused server-side. The createMutators function convention is used so that we can pass authentication information in to implement permissions. You are free to make different code layout choices – the only real requirement is that you register your map of mutators in the Zero constructor: ```ts // main.tsx import {Zero} from '@rocicorp/zero'; import {schema} from './schema'; import {createMutators} from './mutators'; const zero = new Zero({ schema, mutators: createMutators(), }); ``` Write Data on the Client The Transaction interface passed to client mutators exposes the same mutate API as the existing CRUD-style mutators: ```ts async function myMutator(tx: Transaction) { // Insert a new issue await tx.mutate.issue.insert({ id: 'issue-123', title: 'New title', description: 'New description', }); // Upsert a new issue await tx.mutate.issue.upsert({ id: 'issue-123', title: 'New title', description: 'New description', }); // Update an issue await tx.mutate.issue.update({ id: 'issue-123', title: 'New title', }); // Delete an issue await tx.mutate.issue.delete({ id: 'issue-123', }); } ``` See the CRUD docs for detailed semantics on these methods. Read Data on the Client You can read data within a client mutator using ZQL: ```ts export function createMutators() { return { issue: { update: async (tx, {id, title}: {id: string; title: string}) => { // Read existing issue const prev = await tx.query.issue.where('id', id).one(); // Validate title length. Legacy issues are exempt. if (!prev.isLegacy && title.length > 100) { throw new Error(`Title is too long`); } await tx.mutate.issue.update({id, title}); }, }, } as const satisfies CustomMutatorDefs; } ``` You have the full power of ZQL at your disposal, including relationships, filters, ordering, and limits. Reads and writes within a mutator are transactional, meaning that the datastore is guaranteed to not change while your mutator is running. And if the mutator throws, the entire mutation is rolled back. This parameter isn't supported within mutators, because waiting for server results makes no sense in an optimistic mutation – it defeats the purpose of running optimistically to begin with. When a mutator runs on the client (tx.location === \"client\"), ZQL reads only return data already cached on the client. When mutators run on the server (tx.location === \"server\"), ZQL reads always return all data. You can use run() within custom mutators, but the type argument does nothing. In the future, passing type in this situation will throw an error. Invoking Client Mutators Once you have registered your client mutators, you can call them from your client-side application: ```ts zero.mutate.issue.update({ id: 'issue-123', title: 'New title', }); ``` The result of a call to a mutator is a Promise. You do not usually need to await this promise as Zero mutators run very fast, usually completing in a tiny fraction of one frame. However because mutators ocassionally need to access browser storage, they are technically async. Reading a row that was written by a mutator immediately after it is written may not return the new data, because the mutator may not have completed writing to storage yet. Waiting for Mutator Result We typically recommend that you \"fire and forget\" mutators. Optimistic mutations make sense when the common case is that a mutation succeeds. If a mutation frequently fails, then showing the user an optimistic result doesn't make sense, because it will likely be wrong. That said there are cases where it is useful to know when a write succeeded on either the client or server. One example is if you need to read a row directly after writing it. Zero's local writes are very fast (almost always < 1 frame), but because Zero is backed by IndexedDB, writes are still technically asynchronous and reads directly after a write may not return the new data. You can use the .client promise in this case to wait for a write to complete on the client side: ```ts try { const write = zero.mutate.issue.update({ id: 'issue-123', title: 'New title', }); // issue-123 not guaranteed to be present here. read1 may be undefined. const read1 = await zero.query.issue.where('id', 'issue-123').one(); // Await client write – almost always less than 1 frame, and same // macrotask, so no browser paint will occur here. await write.client; // issue-123 definitely can be read now. const read2 = await zero.query.issue.where('id', 'issue-123').one(); } catch (e) { console.error('Mutator failed on client', e); } ``` You can also wait for the server write to succeed: ```ts try { await zero.mutate.issue.update({ id: 'issue-123', title: 'New title', }).server; // issue-123 is written to server } catch (e) { console.error('Mutator failed on client or server', e); } ``` If the client-side mutator fails, the .server promise is also rejected with the same error. You don't have to listen to both promises, the server promise covers both cases. Setting Up the Server You will need a server somewhere you can run an endpoint on. This is typically a serverless function on a platform like Vercel or AWS but can really be anything. Set the push URL with the ZERO\\_PUSH\\_URL env var or --push-url. If there is per-client configuration you need to send to the push endpoint, you can do that with push.queryParams: ```ts const z = new Zero({ push: { queryParams: { workspaceID: '42', }, }, }); ``` The push endpoint receives a PushRequest as input describing one or more mutations to apply to the backend, and must return a PushResponse describing the results of those mutations. If you are implementing your server in TypeScript, you can use the PushProcessor class to trivially implement this endpoint. Here’s an example in a Hono app: ```ts import {Hono} from 'hono'; import {handle} from 'hono/vercel'; import { PushProcessor, ZQLDatabase, PostgresJSConnection, } from '@rocicorp/zero/pg'; import postgres from 'postgres'; import {schema} from '../shared/schema'; import {createMutators} from '../shared/mutators'; // PushProcessor is provided by Zero to encapsulate a standard // implementation of the push protocol. const processor = new PushProcessor( new ZQLDatabase( new PostgresJSConnection(postgres(process.env.ZERO_UPSTREAM_DB! as string)), schema, ), ); export const app = new Hono().basePath('/api'); app.post('/push', async c => { const result = await processor.process(createMutators(), c.req.raw); return await c.json(result); }); export default handle(app); ``` PushProcessor depends on an abstract Database. This allows it to implement the push algorithm against any database. @rocicorp/zero/pg includes a ZQLDatabase implementation of this interface backed by Postgres. The implementation allows the same mutator functions to run on client and server, by providing an implementation of the ZQL APIs that custom mutators run on the client. ZQLDatabase in turn relies on an abstract DBConnection that provides raw access to a Postgres database. This allows you to use any Postgres library you like, as long as you provide a DBConnection implementation for it. The PostgresJSConnection class implements DBConnection for the excellent postgres.js library to connect to Postgres. To reuse the client mutators exactly as-is on the server just pass the result of the same createMutators function to PushProcessor. Server Error Handling The PushProcessor in @rocicorp/zero/pg skips any mutations that throw: ```ts app.post('/push', async c => { const result = await processor.process({ issue: { update: async (tx, data) => { // The mutation is skipped and the next mutation runs as normal. throw new Error('bonk'); }, }, }, ...); return await c.json(result); }) ``` PushProcessor catches such errors and turns them into a structured response that gets sent back to the client. You can recover the errors and show UI if you want. It is also of course possible for the entire push endpoint to return an HTTP error, or to not reply at all: ```ts app.post('/push', async c => { // This will cause the client to resend all queued mutations. throw new Error('zonk'); const result = await processor.process({ // ... }, ...); return await c.json(result); }) ``` If Zero recieves any response from the push endpoint other than HTTP 200, 401, or 403, it will disconnect, wait a few moments, reconnect, and then retry all unprocessed mutations. If Zero receives HTTP 401 or 403, the client refreshes the auth token if possible, then retries all queued mutations. If you want a different behavior, it is possible to implement your own PushProcessor and handle errors differently. Server-Specific Code To implement server-specific code, just run different mutators in your push endpoint! An approach we like is to create a separate server-mutators.ts file that wraps the client mutators: ```ts // server-mutators.ts import {CustomMutatorDefs} from '@rocicorp/zero'; import {schema} from './schema'; export function createMutators( clientMutators: CustomMutatorDefs, ) { return { // Reuse all client mutators except the ones in `issue` ...clientMutators, issue: { // Reuse all issue mutators except `update` ...clientMutators.issue, update: async (tx, {id, title}: {id: string; title: string}) => { // Call the shared mutator first await clientMutators.issue.update(tx, {id, title}); // Record a history of this operation happening in an audit // log table. await tx.mutate.auditLog.insert({ // Assuming you have an audit log table with fields for // `issueId`, `action`, and `timestamp`. issueId: id, action: 'update-title', timestamp: new Date().toISOString(), }); }, }, } as const satisfies CustomMutatorDefs; } ``` For simple things, we also expose a location field on the transaction object that you can use to branch your code: ```ts myMutator: (tx) => { if (tx.location === 'client') { // Client-side code } else { // Server-side code } }, ``` Permissions Because custom mutators are just arbitrary TypeScript functions, there is no need for a special permissions system. Therefore, you won't use Zero's write permissions when you use custom mutators. We hope to build custom queries next – a read analog to custom mutators. If we succeed, Zero's permission system will go away completely 🤯. In order to do permission checks, you'll need to know what user is making the request. You can pass this information to your mutators by adding a AuthData parameter to the createMutators function: ```ts type AuthData = { sub: string; }; export function createMutators(authData: AuthData | undefined) { return { issue: { launchMissiles: async (tx, args: {target: string}) => { if (!authData) { throw new Error('Users must be logged in to launch missiles'); } const hasPermission = await tx.query.user .where('id', authData.sub) .whereExists('permissions', q => q.where('name', 'launch-missiles')) .one(); if (!hasPermission) { throw new Error('User does not have permission to launch missiles'); } }, }, } as const satisfies CustomMutatorDefs; } ``` The AuthData parameter can be any data required for authorization, but is typically just the decoded JWT: ```ts // app.tsx const zero = new Zero({ schema, auth: encodedJWT, mutators: createMutators(decodedJWT), }); // hono-server.ts const processor = new PushProcessor( schema, connectionProvider(postgres(process.env.ZERO_UPSTREAM_DB as string)), ); processor.process( createMutators(decodedJWT), c.req.query(), await c.req.json(), ); ``` Dropping Down to Raw SQL The ServerTransaction interface has a dbTransaction property that exposes the underlying database connection. This allows you to run raw SQL queries directly against the database. This is useful for complex queries, or for using Postgres features that Zero doesn't support yet: ```ts markAllAsRead: async(tx: Transaction, {userId: string}) { // shared stuff ... if (tx.location === 'server') { // `tx` is now narrowed to `ServerTransaction`. // Do special server-only stuff with raw SQL. await tx.dbTransaction.query( ` UPDATE notification SET read = true WHERE user_id = $1 `, [userId], ); } } ``` As a convenience we also expose a special CustomMutatorDefs for use with server-mutators.ts that sets all the mutators to ServerTransaction by default: ```ts // server-mutators.ts import type { CustomMutatorDefs, // Special server-side CustomMutatorDefs PostgresJSTransaction, ServerTransaction, } from '@rocicorp/zero/pg'; import {Schema} from './schema'; export function createMutators(clientMutators: CustomMutatorDefs) { return { // Reuse all client mutators except the ones in `issue` ...clientMutators, issue: { // Reuse all issue mutators except `update` ...clientMutators.issue, markAllAsRead: async (tx, {userId: string}) { // No narrowing necessary – tx is already a `ServerTransaction` // assert(tx.location === 'server'); await tx.dbTransaction.query( ` UPDATE notification SET read = true WHERE user_id = $1 `, [userId], ); }, } } as const satisfies CustomMutatorDefs< ServerTransaction >; } ``` Notifications and Async Work It is bad practice to hold open database transactions while talking over the network, for example to send notifications. Instead, you should let the db transaction commit and do the work asynchronously. There is no specific support for this in custom mutators, but since mutators are just code, it’s easy to do: ```ts // server-mutators.ts export function createMutators( authData: AuthData, asyncTasks: Array<() => Promise>, ) { return { issue: { update: async (tx, {id, title}: {id: string; title: string}) => { await tx.mutate.issue.update({id, title}); asyncTasks.push(async () => { await sendEmailToSubscribers(args.id); }); }, }, } as const satisfies CustomMutatorDefs; } ``` Then in your push handler: ```ts app.post('/push', async c => { const asyncTasks: Array<() => Promise> = []; const result = await processor.process( createMutators(authData, asyncTasks), c.req.query(), await c.req.json(), ); await Promise.all(asyncTasks.map(task => task())); return await c.json(result); }); ``` Custom Database Connections You can implement an adapter to a different Postgres library, or even a different database entirely. To do so, provide a connectionProvider to PushProcessor that returns a different DBConnection implementation. For an example implementation, see the postgres implementation. Custom Push Implementation You can manually implement the push protocol in any programming language. This will be documented in the future, but you can refer to the PushProcessor source code for an example for now. Examples Zbugs uses custom mutators for all mutations, write permissions, and notifications. hello-zero-solid uses custom mutators for all mutations, and for permissions.", + "content": "Custom Mutators are a new way to write data in Zero that is much more powerful than the original \"CRUD\" mutator API. Instead of having only the few built-in insert/update/delete write operations for each table, custom mutators allow you to create your own write operations using arbitrary code. This makes it possible to do things that are impossible or awkward with other sync engines. For example, you can create custom mutators that: Perform arbitrary server-side validation Enforce fine-grained permissions Send email notifications Query LLMs Use Yjs for collaborative editing … and much, much more – custom mutators are just code, and they can do anything code can do! Despite their increased power, custom mutators still participate fully in sync. They execute instantly on the local device, immediately updating all active queries. They are then synced in the background to the server and to other clients. \\ 100) { throw new Error(`Title is too long`); } await tx.mutate.issue.update({id, title}); } ``` Each custom mutator gets two implementations: one on the client and one on the server. The client implementation must be written in TypeScript against the Zero Transaction interface, using ZQL for reads and a CRUD-style API for writes. The server implementation runs on your server, in your push endpoint, against your database. In principle, it can be written in any language and use any data access library. For example you could have the following Go-based server implementation of the same mutator: ```go func updateIssueOnServer(tx *sql.Tx, id string, title string) error { // Validate title length. if len(title) > 100 { return errors.New(\"Title is too long\") } _, err := tx.Exec(\"UPDATE issue SET title = $1 WHERE id = $2\", title, id) return err } ``` In practice however, most Zero apps use TypeScript on the server. For these users we provide a handy ServerTransaction that implements ZQL against Postgres, so that you can share code between client and server mutators naturally. So on a TypeScript server, that server mutator can just be: ```ts async function updateIssueOnServer( tx: ServerTransaction, {id, title}, {id: string, title: string}, ) { // Delegate to client mutator. // The `ServerTransaction` here has a different implementation // that runs the same ZQL queries against Postgres! await updateIssue(tx, {id, title}); } ``` Reusing ZQL on the server is a handy – and we expect frequently used – option, but not a requirement. Server Authority You may be wondering what happens if the client and server mutators implementations don't match. Zero is an example of a server-authoritative sync engine. This means that the server mutator always takes precedence over the client mutator. The result from the client mutator is considered speculative and is discarded as soon as the result from the server mutator is known. This is a very useful feature: it enables server-side validation, permissions, and other server-specific logic. Imagine that you wanted to use an LLM to detect whether an issue update is spammy, rather than a simple length check. We can just add that to our server mutator: ```ts async function updateIssueOnServer( tx: ServerTransaction, {id, title}: {id: string; title: string}, ) { const response = await llamaSession.prompt( `Is this title update likely spam?\\n\\n${title}\\n\\nResponse \"yes\" or \"no\"`, ); if (/yes/i.test(response)) { throw new Error(`Title is likely spam`); } // delegate rest of implementation to client mutator await updateIssue(tx, {id, title}); } ``` If the server detects that the mutation is spammy, the client will see the error message and the mutation will be rolled back. If the server mutator succeeds, the client mutator will be rolled back and the server result will be applied. Life of a Mutation Now that we understand what client and server mutations are, let's walk through how they work together with Zero to sync changes from a source client to the server and then other clients: When you call a custom mutator on the client, Zero runs your client-side mutator immediately on the local device, updating all active queries instantly. In the background, Zero then sends a mutation (a record of the mutator having run with certain arguments) to your server's push endpoint. Your push endpoint runs the push protocol, executing the server-side mutator in a transaction against your database and recording the fact that the mutation ran. Optionally, you use our PushProcessor class to handle this for you, but you can also implement it yourself. The changes to the database are replicated to zero-cache as normal. zero-cache calculates the updates to active queries and sends rows that have changed to each client. It also sends information about the mutations that have been applied to the database. Clients receive row updates and apply them to their local cache. Any pending mutations which have been applied to the server have their local effects rolled back. Client-side queries are updated and the user sees the changes. Using Custom Mutators Registering Client Mutators By convention, the client mutators are defined with a function called createMutators in a file called mutators.ts: ```ts // mutators.ts import {CustomMutatorDefs} from '@rocicorp/zero'; import {schema} from './schema'; export function createMutators() { return { issue: { update: async (tx, {id, title}: {id: string; title: string}) => { // Validate title length. Legacy issues are exempt. if (title.length > 100) { throw new Error(`Title is too long`); } await tx.mutate.issue.update({id, title}); }, }, } as const satisfies CustomMutatorDefs; } ``` The mutators.ts convention allows mutator implementations to be easily reused server-side. The createMutators function convention is used so that we can pass authentication information in to implement permissions. You are free to make different code layout choices – the only real requirement is that you register your map of mutators in the Zero constructor: ```ts // main.tsx import {Zero} from '@rocicorp/zero'; import {schema} from './schema'; import {createMutators} from './mutators'; const zero = new Zero({ schema, mutators: createMutators(), }); ``` Write Data on the Client The Transaction interface passed to client mutators exposes the same mutate API as the existing CRUD-style mutators: ```ts async function myMutator(tx: Transaction) { // Insert a new issue await tx.mutate.issue.insert({ id: 'issue-123', title: 'New title', description: 'New description', }); // Upsert a new issue await tx.mutate.issue.upsert({ id: 'issue-123', title: 'New title', description: 'New description', }); // Update an issue await tx.mutate.issue.update({ id: 'issue-123', title: 'New title', }); // Delete an issue await tx.mutate.issue.delete({ id: 'issue-123', }); } ``` See the CRUD docs for detailed semantics on these methods. Read Data on the Client You can read data within a client mutator using ZQL: ```ts export function createMutators() { return { issue: { update: async (tx, {id, title}: {id: string; title: string}) => { // Read existing issue const prev = await tx.query.issue.where('id', id).one(); // Validate title length. Legacy issues are exempt. if (!prev.isLegacy && title.length > 100) { throw new Error(`Title is too long`); } await tx.mutate.issue.update({id, title}); }, }, } as const satisfies CustomMutatorDefs; } ``` You have the full power of ZQL at your disposal, including relationships, filters, ordering, and limits. Reads and writes within a mutator are transactional, meaning that the datastore is guaranteed to not change while your mutator is running. And if the mutator throws, the entire mutation is rolled back. This parameter isn't supported within mutators, because waiting for server results makes no sense in an optimistic mutation – it defeats the purpose of running optimistically to begin with. When a mutator runs on the client (tx.location === \"client\"), ZQL reads only return data already cached on the client. When mutators run on the server (tx.location === \"server\"), ZQL reads always return all data. You can use run() within custom mutators, but the type argument does nothing. In the future, passing type in this situation will throw an error. Invoking Client Mutators Once you have registered your client mutators, you can call them from your client-side application: ```ts zero.mutate.issue.update({ id: 'issue-123', title: 'New title', }); ``` The result of a call to a mutator is a Promise. You do not usually need to await this promise as Zero mutators run very fast, usually completing in a tiny fraction of one frame. However because mutators ocassionally need to access browser storage, they are technically async. Reading a row that was written by a mutator immediately after it is written may not return the new data, because the mutator may not have completed writing to storage yet. Waiting for Mutator Result We typically recommend that you \"fire and forget\" mutators. Optimistic mutations make sense when the common case is that a mutation succeeds. If a mutation frequently fails, then showing the user an optimistic result doesn't make sense, because it will likely be wrong. That said there are cases where it is useful to know when a write succeeded on either the client or server. One example is if you need to read a row directly after writing it. Zero's local writes are very fast (almost always < 1 frame), but because Zero is backed by IndexedDB, writes are still technically asynchronous and reads directly after a write may not return the new data. You can use the .client promise in this case to wait for a write to complete on the client side: ```ts try { const write = zero.mutate.issue.insert({ id: 'issue-123', title: 'New title', }); // issue-123 not guaranteed to be present here. read1 may be undefined. const read1 = await zero.query.issue.where('id', 'issue-123').one(); // Await client write – almost always less than 1 frame, and same // macrotask, so no browser paint will occur here. await write.client; // issue-123 definitely can be read now. const read2 = await zero.query.issue.where('id', 'issue-123').one(); } catch (e) { console.error('Mutator failed on client', e); } ``` You can also wait for the server write to succeed: ```ts try { const write = zero.mutate.issue.insert({ id: 'issue-123', title: 'New title', }); await write.client; // optimistic write guaranteed to be present here, but not // server write. const read1 = await zero.query.issue.where('id', 'issue-123').one(); // Await server write – this involves a round-trip. await write.server; // issue-123 is written to server and any results are // syned to this client. // read2 could potentially be undefined here, for example if the // server mutator rejected the write. const read2 = await zero.query.issue.where('id', 'issue-123').one(); } catch (e) { console.error('Mutator failed on client or server', e); } ``` If the client-side mutator fails, the .server promise is also rejected with the same error. You don't have to listen to both promises, the server promise covers both cases. Setting Up the Server You will need a server somewhere you can run an endpoint on. This is typically a serverless function on a platform like Vercel or AWS but can really be anything. Configure the push endpoint with the push.url parameter in your Zero constructor: ```ts const zero = new Zero({ push: { url: 'https://zero.my-server.com/push', }, }); ``` You will also need to enable the server to be used as a push endpoint with the ZERO\\_PUSH\\_URL environment variable or --push-url flag: ```bash ZERO_PUSH_URL=https://*.my-server.com/push ``` The ZERO\\_PUSH\\_URL parameter accepts wildcards, enabling the client to pass runtime configuration to the push endpoint or to use a different push endpoint, e.g., for previews. See the config docs for the full syntax. The push endpoint receives a PushRequest as input describing one or more mutations to apply to the backend, and must return a PushResponse describing the results of those mutations. If you are implementing your server in TypeScript, you can use the PushProcessor class to trivially implement this endpoint. Here’s an example in a Hono app: ```ts import {Hono} from 'hono'; import {handle} from 'hono/vercel'; import { PushProcessor, ZQLDatabase, PostgresJSConnection, } from '@rocicorp/zero/pg'; import postgres from 'postgres'; import {schema} from '../shared/schema'; import {createMutators} from '../shared/mutators'; // PushProcessor is provided by Zero to encapsulate a standard // implementation of the push protocol. const processor = new PushProcessor( new ZQLDatabase( new PostgresJSConnection(postgres(process.env.ZERO_UPSTREAM_DB! as string)), schema, ), ); export const app = new Hono().basePath('/api'); app.post('/push', async c => { const result = await processor.process(createMutators(), c.req.raw); return await c.json(result); }); export default handle(app); ``` PushProcessor depends on an abstract Database. This allows it to implement the push algorithm against any database. @rocicorp/zero/pg includes a ZQLDatabase implementation of this interface backed by Postgres. The implementation allows the same mutator functions to run on client and server, by providing an implementation of the ZQL APIs that custom mutators run on the client. ZQLDatabase in turn relies on an abstract DBConnection that provides raw access to a Postgres database. This allows you to use any Postgres library you like, as long as you provide a DBConnection implementation for it. The PostgresJSConnection class implements DBConnection for the excellent postgres.js library to connect to Postgres. To reuse the client mutators exactly as-is on the server just pass the result of the same createMutators function to PushProcessor. Server Error Handling The PushProcessor in @rocicorp/zero/pg skips any mutations that throw: ```ts app.post('/push', async c => { const result = await processor.process({ issue: { update: async (tx, data) => { // The mutation is skipped and the next mutation runs as normal. throw new Error('bonk'); }, }, }, ...); return await c.json(result); }) ``` PushProcessor catches such errors and turns them into a structured response that gets sent back to the client. You can recover the errors and show UI if you want. It is also of course possible for the entire push endpoint to return an HTTP error, or to not reply at all: ```ts app.post('/push', async c => { // This will cause the client to resend all queued mutations. throw new Error('zonk'); const result = await processor.process({ // ... }, ...); return await c.json(result); }) ``` If Zero recieves any response from the push endpoint other than HTTP 200, 401, or 403, it will disconnect, wait a few moments, reconnect, and then retry all unprocessed mutations. If Zero receives HTTP 401 or 403, the client refreshes the auth token if possible, then retries all queued mutations. If you want a different behavior, it is possible to implement your own PushProcessor and handle errors differently. Server-Specific Code To implement server-specific code, just run different mutators in your push endpoint! An approach we like is to create a separate server-mutators.ts file that wraps the client mutators: ```ts // server-mutators.ts import {CustomMutatorDefs} from '@rocicorp/zero'; import {schema} from './schema'; export function createMutators( clientMutators: CustomMutatorDefs, ) { return { // Reuse all client mutators except the ones in `issue` ...clientMutators, issue: { // Reuse all issue mutators except `update` ...clientMutators.issue, update: async (tx, {id, title}: {id: string; title: string}) => { // Call the shared mutator first await clientMutators.issue.update(tx, {id, title}); // Record a history of this operation happening in an audit // log table. await tx.mutate.auditLog.insert({ // Assuming you have an audit log table with fields for // `issueId`, `action`, and `timestamp`. issueId: id, action: 'update-title', timestamp: new Date().toISOString(), }); }, }, } as const satisfies CustomMutatorDefs; } ``` For simple things, we also expose a location field on the transaction object that you can use to branch your code: ```ts myMutator: (tx) => { if (tx.location === 'client') { // Client-side code } else { // Server-side code } }, ``` Permissions Because custom mutators are just arbitrary TypeScript functions, there is no need for a special permissions system. Therefore, you won't use Zero's write permissions when you use custom mutators. We hope to build custom queries next – a read analog to custom mutators. If we succeed, Zero's permission system will go away completely 🤯. In order to do permission checks, you'll need to know what user is making the request. You can pass this information to your mutators by adding a AuthData parameter to the createMutators function: ```ts type AuthData = { sub: string; }; export function createMutators(authData: AuthData | undefined) { return { issue: { launchMissiles: async (tx, args: {target: string}) => { if (!authData) { throw new Error('Users must be logged in to launch missiles'); } const hasPermission = await tx.query.user .where('id', authData.sub) .whereExists('permissions', q => q.where('name', 'launch-missiles')) .one(); if (!hasPermission) { throw new Error('User does not have permission to launch missiles'); } }, }, } as const satisfies CustomMutatorDefs; } ``` The AuthData parameter can be any data required for authorization, but is typically just the decoded JWT: ```ts // app.tsx const zero = new Zero({ schema, auth: encodedJWT, mutators: createMutators(decodedJWT), }); // hono-server.ts const processor = new PushProcessor( schema, connectionProvider(postgres(process.env.ZERO_UPSTREAM_DB as string)), ); processor.process( createMutators(decodedJWT), c.req.query(), await c.req.json(), ); ``` Dropping Down to Raw SQL The ServerTransaction interface has a dbTransaction property that exposes the underlying database connection. This allows you to run raw SQL queries directly against the database. This is useful for complex queries, or for using Postgres features that Zero doesn't support yet: ```ts markAllAsRead: async(tx: Transaction, {userId: string}) { // shared stuff ... if (tx.location === 'server') { // `tx` is now narrowed to `ServerTransaction`. // Do special server-only stuff with raw SQL. await tx.dbTransaction.query( ` UPDATE notification SET read = true WHERE user_id = $1 `, [userId], ); } } ``` As a convenience we also expose a special CustomMutatorDefs for use with server-mutators.ts that sets all the mutators to ServerTransaction by default: ```ts // server-mutators.ts import type { CustomMutatorDefs, // Special server-side CustomMutatorDefs PostgresJSTransaction, ServerTransaction, } from '@rocicorp/zero/pg'; import {Schema} from './schema'; export function createMutators(clientMutators: CustomMutatorDefs) { return { // Reuse all client mutators except the ones in `issue` ...clientMutators, issue: { // Reuse all issue mutators except `update` ...clientMutators.issue, markAllAsRead: async (tx, {userId: string}) { // No narrowing necessary – tx is already a `ServerTransaction` // assert(tx.location === 'server'); await tx.dbTransaction.query( ` UPDATE notification SET read = true WHERE user_id = $1 `, [userId], ); }, } } as const satisfies CustomMutatorDefs< ServerTransaction >; } ``` Notifications and Async Work It is bad practice to hold open database transactions while talking over the network, for example to send notifications. Instead, you should let the db transaction commit and do the work asynchronously. There is no specific support for this in custom mutators, but since mutators are just code, it’s easy to do: ```ts // server-mutators.ts export function createMutators( authData: AuthData, asyncTasks: Array<() => Promise>, ) { return { issue: { update: async (tx, {id, title}: {id: string; title: string}) => { await tx.mutate.issue.update({id, title}); asyncTasks.push(async () => { await sendEmailToSubscribers(args.id); }); }, }, } as const satisfies CustomMutatorDefs; } ``` Then in your push handler: ```ts app.post('/push', async c => { const asyncTasks: Array<() => Promise> = []; const result = await processor.process( createMutators(authData, asyncTasks), c.req.query(), await c.req.json(), ); await Promise.all(asyncTasks.map(task => task())); return await c.json(result); }); ``` Custom Database Connections You can implement an adapter to a different Postgres library, or even a different database entirely. To do so, provide a connectionProvider to PushProcessor that returns a different DBConnection implementation. For an example implementation, see the postgres implementation. Custom Push Implementation You can manually implement the push protocol in any programming language. This will be documented in the future, but you can refer to the PushProcessor source code for an example for now. Examples Zbugs uses custom mutators for all mutations, write permissions, and notifications. hello-zero-solid uses custom mutators for all mutations and for permissions.", "headings": [] }, { @@ -80,7 +80,7 @@ "id": "11-deployment", "title": "Deploying Zero", "url": "/docs/deployment", - "content": "To deploy a Zero app, you need to: Deploy your backend database. Most standard Postgres hosts work with Zero. Deploy zero-cache. We provide a Docker image that can work with most Docker hosts. Deploy your frontend. You can use any hosting service like Vercel or Netlify. This page describes how to deploy zero-cache. Architecture zero-cache is a horizontally scalable, stateful web service that maintains a SQLite replica of your Postgres database. It uses this replica to sync ZQL queries to clients over WebSockets. You don't have to know the details of how zero-cache works to run it, but it helps to know the basic structure. A running zero-cache is composed of a single replication-manager node and multiple view-syncer nodes. It also depends on Postgres, S3, and attached SSD storage. Upstream: Your application's Postgres database. Change DB: A Postgres DB used by Zero to store a recent subset of the Postgres replication log. CVR DB: A Postgres DB used by Zero to store Client View Records (CVRs). CVRs track the state of each synced client. We allow separate DBs so that they can be scaled and tuned independently if desired. S3: Stores a canonical copy of the SQLite replica. File System: Used by both node types to store local copies of the SQLite replica. Can be ephemeral – Zero will re-initialize from S3 on startup. Recommended to use attached SSD storage for best performance. Replication Manager: Serves as the single consumer of the Postgres replication log. Stores a recent subset of the Postgres changelog in the Change DB for catching up ViewSyncers when they initialize. Also maintains the canonical replica, which ViewSyncers initialize from. View Syncers: Handle WebSocket connections from clients and run ZQL queries. Updates CVR DB with the latest state of each client as queries run. Uses CVR DB on client connection to compute the initial diff to catch clients up. Topology You should deploy zero-cache close to your database because the mutation implementation is chatty. In the future, mutations will move out of zero-cache. When that happens you can deploy zero-cache geographically distributed and it will double as a read-replica. Updating When run with multiple View Syncer nodes, zero-cache supports rolling, downtime-free updates. A new Replication Manager takes over the replication stream from the old Replication Manager, and connections from the old View Syncers are gradually drained and absorbed by active View Syncers. Client/Server Version Compatibility Servers are compatible with any client of same major version, and with clients one major version back. So for example: Server 0.2.\\* is compatible with client 0.2.\\* Server 0.2.\\* is compatible with client 0.1.\\* Server 2.\\*.\\* is compatible with client 2.\\*.\\* Server 2.\\*.\\* is compatible with client 1.\\*.\\* To upgrade Zero to a new major version, first deploy the new zero-cache, then the new frontend. Configuration The zero-cache image is configured via environment variables. See zero-cache Config for available options. Guide: Multi-Node on SST+AWS SST is our recommended way to deploy Zero. The setup below costs about $35/month. You can scale it up or down as needed by adjusting the amount of vCPUs and memory in each task. Setup Upstream Create an upstream Postgres database server somewhere. See Connecting to Postgres for details. Populate the schema and any initial data for your application. Setup AWS See AWS setup guide. The end result should be that you have a dev profile and SSO session defined in your ~/.aws/config file. Initialize SST ```bash npx sst init --yes ``` Choose \"aws\" for where to deploy. Then overwite /sst.config.ts with the following code: ```ts /* eslint-disable */ /// import {execSync} from 'child_process'; export default $config({ app(input) { return { name: 'hello-zero', removal: input?.stage === 'production' ? 'retain' : 'remove', home: 'aws', region: process.env.AWS_REGION || 'us-east-1', providers: { command: true, }, }; }, async run() { const zeroVersion = execSync('cat package.json | jq '.dependencies[\"@rocicorp/zero\"]') .toString() .trim(); // S3 Bucket const replicationBucket = new sst.aws.Bucket(`replication-bucket`); // VPC Configuration const vpc = new sst.aws.Vpc(`vpc`, { az: 2, }); // ECS Cluster const cluster = new sst.aws.Cluster(`cluster`, { vpc, }); const conn = new sst.Secret('PostgresConnectionString'); const zeroAuthSecret = new sst.Secret('ZeroAuthSecret'); // Common environment variables const commonEnv = { ZERO_PUSH_URL: '', // Your push api url when using custom mutators ZERO_UPSTREAM_DB: conn.value, ZERO_CVR_DB: conn.value, ZERO_CHANGE_DB: conn.value, ZERO_AUTH_SECRET: zeroAuthSecret.value, ZERO_REPLICA_FILE: 'sync-replica.db', ZERO_IMAGE_URL: `rocicorp/zero:${zeroVersion}`, ZERO_CVR_MAX_CONNS: '10', ZERO_UPSTREAM_MAX_CONNS: '10', }; // Replication Manager Service const replicationManager = cluster.addService(`replication-manager`, { cpu: '0.5 vCPU', memory: '1 GB', architecture: 'arm64', image: commonEnv.ZERO_IMAGE_URL, link: [replicationBucket], wait: true, health: { command: ['CMD-SHELL', 'curl -f http://localhost:4849/ || exit 1'], interval: '5 seconds', retries: 3, startPeriod: '300 seconds', }, environment: { ...commonEnv, ZERO_LITESTREAM_BACKUP_URL: $interpolate`s3://${replicationBucket.name}/backup`, ZERO_NUM_SYNC_WORKERS: '0', }, transform: { target: { healthCheck: { enabled: true, path: '/keepalive', protocol: 'HTTP', interval: 5, healthyThreshold: 2, timeout: 3, }, }, }, }); // View Syncer Service const viewSyncer = cluster.addService( `view-syncer`, { cpu: '1 vCPU', memory: '2 GB', architecture: 'arm64', image: commonEnv.ZERO_IMAGE_URL, link: [replicationBucket], health: { command: ['CMD-SHELL', 'curl -f http://localhost:4848/ || exit 1'], interval: '5 seconds', retries: 3, startPeriod: '300 seconds', }, environment: { ...commonEnv, ZERO_CHANGE_STREAMER_MODE: 'discover', }, logging: { retention: '1 month', }, transform: { target: { healthCheck: { enabled: true, path: '/keepalive', protocol: 'HTTP', interval: 5, healthyThreshold: 2, timeout: 3, }, stickiness: { enabled: true, type: 'lb_cookie', cookieDuration: 120, }, }, }, }, { // Wait for replication-manager to come up first, for breaking changes // to replication-manager interface. dependsOn: [replicationManager], }, ); // Permissions deployment // Note: this setup requires your CI/CD pipeline to have access to your // Postgres database. If you do not want to do this, you can also use // `npx zero-deploy-permissions --output-format=sql` during build to // generate a permissions.sql file, then run that file as part of your // deployment within your VPC. See hello-zero-solid for an example: // https://github.com/rocicorp/hello-zero-solid/blob/main/sst.config.ts#L141 new command.local.Command( 'zero-deploy-permissions', { create: `npx zero-deploy-permissions -p ../../src/schema.ts`, // Run the Command on every deploy ... triggers: [Date.now()], environment: { ZERO_UPSTREAM_DB: commonEnv.ZERO_UPSTREAM_DB, }, }, // after the view-syncer is deployed. {dependsOn: viewSyncer}, ); }, }); ``` Set SST Secrets Configure SST with your Postgres connection string and Zero Auth Secret. Note that if you use JWT-based auth, you'll need to change the environment variables in the sst.config.ts file above, then set a different secret here. ```bash npx sst secret set PostgresConnectionString \"YOUR-PG-CONN-STRING\" npx sst secret set ZeroAuthSecret \"YOUR-ZERO-AUTH-SECRET\" ``` Deploy ```bash npx sst deploy ``` This takes about 5-10 minutes. If successful, you should see a URL for the view-syncer service. This is the URL to pass to the server parameter of the Zero constructor on the client. If unsuccessful, you can get detailed logs with npx sst deploy --verbose. Come find us on Discord and we'll help get you sorted out. Guide: Single-Node on Fly.io Let's deploy the Quickstart app to Fly.io. We'll use Fly.io for both the database and zero-cache. Setup Quickstart Go through the Quickstart guide to get the app running locally. Setup Fly.io Create an account on Fly.io and install the Fly CLI. Create Postgres app ```bash INITIALS=aa PG_APP_NAME=$INITIALS-zstart-pg PG_PASSWORD=\"$(head -c 256 /dev/urandom | od -An -t x1 | tr -d ' \\n' | tr -dc 'a-zA-Z' | head -c 16)\" fly postgres create \\ --name $PG_APP_NAME \\ --region lax \\ --initial-cluster-size 1 \\ --vm-size shared-cpu-2x \\ --volume-size 40 \\ --password=$PG_PASSWORD ``` Seed Upstream database Populate the database with initial data and set its wal\\_level to logical to support replication to zero-cache. Then restart the database to apply the changes. ```bash (cat ./docker/seed.sql; echo \"\\q\") | fly pg connect -a $PG_APP_NAME echo \"ALTER SYSTEM SET wal_level = logical; \\q\" | fly pg connect -a $PG_APP_NAME fly postgres restart --app $PG_APP_NAME ``` Create zero-cache Fly.io app ```bash CACHE_APP_NAME=$INITIALS-zstart-cache fly app create $CACHE_APP_NAME ``` Publish zero-cache Create a fly.toml file. ```bash CONNECTION_STRING=\"postgres://postgres:$PG_PASSWORD@$PG_APP_NAME.flycast:5432\" ZERO_VERSION=$(npm list @rocicorp/zero | grep @rocicorp/zero | cut -f 3 -d @) cat < fly.toml app = \"$CACHE_APP_NAME\" primary_region = 'lax' [build] image = \"registry.hub.docker.com/rocicorp/zero:${ZERO_VERSION}\" [http_service] internal_port = 4848 force_https = true auto_stop_machines = 'off' min_machines_running = 1 [[http_service.checks]] grace_period = \"10s\" interval = \"30s\" method = \"GET\" timeout = \"5s\" path = \"/\" [[vm]] memory = '2gb' cpu_kind = 'shared' cpus = 2 [mounts] source = \"sqlite_db\" destination = \"/data\" [env] ZERO_REPLICA_FILE = \"/data/sync-replica.db\" ZERO_UPSTREAM_DB=\"${CONNECTION_STRING}/zstart?sslmode=disable\" ZERO_CVR_DB=\"${CONNECTION_STRING}/zstart_cvr?sslmode=disable\" ZERO_CHANGE_DB=\"${CONNECTION_STRING}/zstart_cdb?sslmode=disable\" ZERO_PUSH_URL=\"\" ZERO_AUTH_SECRET=\"secretkey\" LOG_LEVEL = \"debug\" EOF ``` Then publish zero-cache: ```bash fly deploy ``` Deploy Permissions Now zero-cache is running on Fly.io, but there are no permissions. If you run the app against this zero-cache, you'll see that no data is returned from any query. To fix this, deploy your permissions: ```bash npx zero-deploy-permissions --schema-path='./src/schema.ts' --output-file='/tmp/permissions.sql' (cat /tmp/permissions.sql; echo \"\\q\") | fly pg connect -a $PG_APP_NAME -d zstart ``` You will need to redo this step every time you change your app's permissions, likely as part of your CI/CD pipeline. Use Remote zero-cache ```bash VITE_PUBLIC_SERVER=\"https://${CACHE_APP_NAME}.fly.dev/\" npm run dev:ui ``` Now restart the frontend to pick up the env change, and refresh the app. You can stop your local database and zero-cache as we're not using them anymore. Open the web inspector to verify the app is talking to the remote zero-cache! You can deploy the frontend to any standard hosting service like Vercel or Netlify, or even to Fly.io! Deploy Frontend to Vercel If you've followed the above guide and deployed zero-cache to fly, you can simply run: ```sh vercel deploy --prod \\ -e ZERO_AUTH_SECRET=\"secretkey\" \\ -e VITE_PUBLIC_SERVER='https://${CACHE_APP_NAME}.fly.dev/' ``` to deploy your frontend to Vercel. Explaining the arguments above -- ZERO\\_AUTH\\_SECRET - The secret to create and verify JWTs. This is the same secret that was used when deploying zero-cache to fly. VITE\\_PUBLIC\\_SERVER - The URL the frontend will call to talk to the zero-cache server. This is the URL of the fly app. Guide: Multi-Node on Raw AWS S3 Bucket Create an S3 bucket. zero-cache uses S3 to backup its SQLite replica so that it survives task restarts. Fargate Services Run zero-cache as two Fargate services (using the same rocicorp/zero docker image): replication-manager zero-cache config: ZERO\\_LITESTREAM\\_BACKUP\\_URL=s3://{bucketName}/{generation} ZERO\\_NUM\\_SYNC\\_WORKERS=0 Task count: 1 view-syncer zero-cache config: ZERO\\_CHANGE\\_STREAMER\\_MODE=discover Task count: N You can also use dynamic scaling Notes Standard rolling restarts are fine for both services Set ZERO\\_CVR\\_MAX\\_CONNS and ZERO\\_UPSTREAM\\_MAX\\_CONNS appropriately so that the total connections from both running and updating view-syncers (e.g. DesiredCount \\* MaximumPercent) do not exceed your database’s max\\_connections. The {generation} component of the s3://{bucketName}/{generation} URL is an arbitrary path component that can be modified to reset the replica (e.g. a date, a number, etc.). Setting this to a new path is the multi-node equivalent of deleting the replica file to resync. Note: zero-cache does not manage cleanup of old generations. The replication-manager serves requests on port 4849. Routing from the view-syncer to the http://{replication-manager} is handled internally by storing data in the changedb. Fargate ephemeral storage is used for the replica. The default size is 20GB. This can be increased up to 200GB Allocate at least twice the size of the database to support the internal VACUUM operation. Guide: $PLATFORM Where should we deploy Zero next?? Let us know on Discord!", + "content": "To deploy a Zero app, you need to: Deploy your backend database. Most standard Postgres hosts work with Zero. Deploy zero-cache. We provide a Docker image that can work with most Docker hosts. Deploy your frontend. You can use any hosting service like Vercel or Netlify. This page describes how to deploy zero-cache. Architecture zero-cache is a horizontally scalable, stateful web service that maintains a SQLite replica of your Postgres database. It uses this replica to sync ZQL queries to clients over WebSockets. You don't have to know the details of how zero-cache works to run it, but it helps to know the basic structure. A running zero-cache is composed of a single replication-manager node and multiple view-syncer nodes. It also depends on Postgres, S3, and attached SSD storage. Upstream: Your application's Postgres database. Change DB: A Postgres DB used by Zero to store a recent subset of the Postgres replication log. CVR DB: A Postgres DB used by Zero to store Client View Records (CVRs). CVRs track the state of each synced client. We allow separate DBs so that they can be scaled and tuned independently if desired. S3: Stores a canonical copy of the SQLite replica. File System: Used by both node types to store local copies of the SQLite replica. Can be ephemeral – Zero will re-initialize from S3 on startup. Recommended to use attached SSD storage for best performance. Replication Manager: Serves as the single consumer of the Postgres replication log. Stores a recent subset of the Postgres changelog in the Change DB for catching up ViewSyncers when they initialize. Also maintains the canonical replica, which ViewSyncers initialize from. View Syncers: Handle WebSocket connections from clients and run ZQL queries. Updates CVR DB with the latest state of each client as queries run. Uses CVR DB on client connection to compute the initial diff to catch clients up. Topology You should deploy zero-cache close to your database because the mutation implementation is chatty. In the future, mutations will move out of zero-cache. When that happens you can deploy zero-cache geographically distributed and it will double as a read-replica. Updating When run with multiple View Syncer nodes, zero-cache supports rolling, downtime-free updates. A new Replication Manager takes over the replication stream from the old Replication Manager, and connections from the old View Syncers are gradually drained and absorbed by active View Syncers. Client/Server Version Compatibility Servers are compatible with any client of same major version, and with clients one major version back. So for example: Server 0.2.\\* is compatible with client 0.2.\\* Server 0.2.\\* is compatible with client 0.1.\\* Server 2.\\*.\\* is compatible with client 2.\\*.\\* Server 2.\\*.\\* is compatible with client 1.\\*.\\* To upgrade Zero to a new major version, first deploy the new zero-cache, then the new frontend. Configuration The zero-cache image is configured via environment variables. See zero-cache Config for available options. Guide: Multi-Node on SST+AWS SST is our recommended way to deploy Zero. The setup below costs about $35/month. You can scale it up or down as needed by adjusting the amount of vCPUs and memory in each task. Setup Upstream Create an upstream Postgres database server somewhere. See Connecting to Postgres for details. Populate the schema and any initial data for your application. Setup AWS See AWS setup guide. The end result should be that you have a dev profile and SSO session defined in your ~/.aws/config file. Initialize SST ```bash npx sst init --yes ``` Choose \"aws\" for where to deploy. Then overwite /sst.config.ts with the following code: ```ts /* eslint-disable */ /// import {execSync} from 'child_process'; export default $config({ app(input) { return { name: 'hello-zero', removal: input?.stage === 'production' ? 'retain' : 'remove', home: 'aws', region: process.env.AWS_REGION || 'us-east-1', providers: { command: true, }, }; }, async run() { const zeroVersion = execSync('cat package.json | jq '.dependencies[\"@rocicorp/zero\"]') .toString() .trim(); // S3 Bucket const replicationBucket = new sst.aws.Bucket(`replication-bucket`); // VPC Configuration const vpc = new sst.aws.Vpc(`vpc`, { az: 2, }); // ECS Cluster const cluster = new sst.aws.Cluster(`cluster`, { vpc, }); const conn = new sst.Secret('PostgresConnectionString'); const zeroAuthSecret = new sst.Secret('ZeroAuthSecret'); // Common environment variables const commonEnv = { ZERO_PUSH_URL: '', // Your push api url when using custom mutators ZERO_UPSTREAM_DB: conn.value, ZERO_CVR_DB: conn.value, ZERO_CHANGE_DB: conn.value, ZERO_AUTH_SECRET: zeroAuthSecret.value, ZERO_REPLICA_FILE: 'sync-replica.db', ZERO_IMAGE_URL: `rocicorp/zero:${zeroVersion}`, ZERO_CVR_MAX_CONNS: '10', ZERO_UPSTREAM_MAX_CONNS: '10', }; // Replication Manager Service const replicationManager = cluster.addService(`replication-manager`, { cpu: '0.5 vCPU', memory: '1 GB', architecture: 'arm64', image: commonEnv.ZERO_IMAGE_URL, link: [replicationBucket], wait: true, health: { command: ['CMD-SHELL', 'curl -f http://localhost:4849/ || exit 1'], interval: '5 seconds', retries: 3, startPeriod: '300 seconds', }, environment: { ...commonEnv, ZERO_LITESTREAM_BACKUP_URL: $interpolate`s3://${replicationBucket.name}/backup`, ZERO_NUM_SYNC_WORKERS: '0', }, loadBalancer: { public: false, ports: [ { listen: '80/http', forward: '4849/http', }, ], }, transform: { service: { // e.g. extend the grace period for initial sync of large databases healthCheckGracePeriodSeconds: 600, } target: { healthCheck: { enabled: true, path: '/keepalive', protocol: 'HTTP', interval: 5, healthyThreshold: 2, timeout: 3, }, }, }, }); // View Syncer Service const viewSyncer = cluster.addService( `view-syncer`, { cpu: '1 vCPU', memory: '2 GB', architecture: 'arm64', image: commonEnv.ZERO_IMAGE_URL, link: [replicationBucket], health: { command: ['CMD-SHELL', 'curl -f http://localhost:4848/ || exit 1'], interval: '5 seconds', retries: 3, startPeriod: '300 seconds', }, environment: { ...commonEnv, ZERO_CHANGE_STREAMER_URI: replicationManager.url, }, loadBalancer: { ports: [ { listen: '80/http', forward: '4848/http', }, ], }, logging: { retention: '1 month', }, transform: { service: { // e.g. extend the grace period for initial sync of large databases healthCheckGracePeriodSeconds: 600, } target: { healthCheck: { enabled: true, path: '/keepalive', protocol: 'HTTP', interval: 5, healthyThreshold: 2, timeout: 3, }, stickiness: { enabled: true, type: 'lb_cookie', cookieDuration: 120, }, }, }, }, ); // Permissions deployment // Note: this setup requires your CI/CD pipeline to have access to your // Postgres database. If you do not want to do this, you can also use // `npx zero-deploy-permissions --output-format=sql` during build to // generate a permissions.sql file, then run that file as part of your // deployment within your VPC. See hello-zero-solid for an example: // https://github.com/rocicorp/hello-zero-solid/blob/main/sst.config.ts#L141 new command.local.Command( 'zero-deploy-permissions', { create: `npx zero-deploy-permissions -p ../../src/schema.ts`, // Run the Command on every deploy ... triggers: [Date.now()], environment: { ZERO_UPSTREAM_DB: commonEnv.ZERO_UPSTREAM_DB, }, }, // after the view-syncer is deployed. {dependsOn: viewSyncer}, ); }, }); ``` Set SST Secrets Configure SST with your Postgres connection string and Zero Auth Secret. Note that if you use JWT-based auth, you'll need to change the environment variables in the sst.config.ts file above, then set a different secret here. ```bash npx sst secret set PostgresConnectionString \"YOUR-PG-CONN-STRING\" npx sst secret set ZeroAuthSecret \"YOUR-ZERO-AUTH-SECRET\" ``` Deploy ```bash npx sst deploy ``` This takes about 5-10 minutes. If successful, you should see a URL for the view-syncer service. This is the URL to pass to the server parameter of the Zero constructor on the client. If unsuccessful, you can get detailed logs with npx sst deploy --verbose. Come find us on Discord and we'll help get you sorted out. Guide: Single-Node on Fly.io Let's deploy the Quickstart app to Fly.io. We'll use Fly.io for both the database and zero-cache. Setup Quickstart Go through the Quickstart guide to get the app running locally. Setup Fly.io Create an account on Fly.io and install the Fly CLI. Create Postgres app ```bash INITIALS=aa PG_APP_NAME=$INITIALS-zstart-pg PG_PASSWORD=\"$(head -c 256 /dev/urandom | od -An -t x1 | tr -d ' \\n' | tr -dc 'a-zA-Z' | head -c 16)\" fly postgres create \\ --name $PG_APP_NAME \\ --region lax \\ --initial-cluster-size 1 \\ --vm-size shared-cpu-2x \\ --volume-size 40 \\ --password=$PG_PASSWORD ``` Seed Upstream database Populate the database with initial data and set its wal\\_level to logical to support replication to zero-cache. Then restart the database to apply the changes. ```bash (cat ./docker/seed.sql; echo \"\\q\") | fly pg connect -a $PG_APP_NAME echo \"ALTER SYSTEM SET wal_level = logical; \\q\" | fly pg connect -a $PG_APP_NAME fly postgres restart --app $PG_APP_NAME ``` Create zero-cache Fly.io app ```bash CACHE_APP_NAME=$INITIALS-zstart-cache fly app create $CACHE_APP_NAME ``` Publish zero-cache Create a fly.toml file. ```bash CONNECTION_STRING=\"postgres://postgres:$PG_PASSWORD@$PG_APP_NAME.flycast:5432\" ZERO_VERSION=$(npm list @rocicorp/zero | grep @rocicorp/zero | cut -f 3 -d @) cat < fly.toml app = \"$CACHE_APP_NAME\" primary_region = 'lax' [build] image = \"registry.hub.docker.com/rocicorp/zero:${ZERO_VERSION}\" [http_service] internal_port = 4848 force_https = true auto_stop_machines = 'off' min_machines_running = 1 [[http_service.checks]] grace_period = \"10s\" interval = \"30s\" method = \"GET\" timeout = \"5s\" path = \"/\" [[vm]] memory = '2gb' cpu_kind = 'shared' cpus = 2 [mounts] source = \"sqlite_db\" destination = \"/data\" [env] ZERO_REPLICA_FILE = \"/data/sync-replica.db\" ZERO_UPSTREAM_DB=\"${CONNECTION_STRING}/zstart?sslmode=disable\" ZERO_CVR_DB=\"${CONNECTION_STRING}/zstart_cvr?sslmode=disable\" ZERO_CHANGE_DB=\"${CONNECTION_STRING}/zstart_cdb?sslmode=disable\" ZERO_PUSH_URL=\"\" ZERO_AUTH_SECRET=\"secretkey\" LOG_LEVEL = \"debug\" EOF ``` Then publish zero-cache: ```bash fly deploy ``` Deploy Permissions Now zero-cache is running on Fly.io, but there are no permissions. If you run the app against this zero-cache, you'll see that no data is returned from any query. To fix this, deploy your permissions: ```bash npx zero-deploy-permissions --schema-path='./src/schema.ts' --output-file='/tmp/permissions.sql' (cat /tmp/permissions.sql; echo \"\\q\") | fly pg connect -a $PG_APP_NAME -d zstart ``` You will need to redo this step every time you change your app's permissions, likely as part of your CI/CD pipeline. Use Remote zero-cache ```bash VITE_PUBLIC_SERVER=\"https://${CACHE_APP_NAME}.fly.dev/\" npm run dev:ui ``` Now restart the frontend to pick up the env change, and refresh the app. You can stop your local database and zero-cache as we're not using them anymore. Open the web inspector to verify the app is talking to the remote zero-cache! You can deploy the frontend to any standard hosting service like Vercel or Netlify, or even to Fly.io! Deploy Frontend to Vercel If you've followed the above guide and deployed zero-cache to fly, you can simply run: ```sh vercel deploy --prod \\ -e ZERO_AUTH_SECRET=\"secretkey\" \\ -e VITE_PUBLIC_SERVER='https://${CACHE_APP_NAME}.fly.dev/' ``` to deploy your frontend to Vercel. Explaining the arguments above -- ZERO\\_AUTH\\_SECRET - The secret to create and verify JWTs. This is the same secret that was used when deploying zero-cache to fly. VITE\\_PUBLIC\\_SERVER - The URL the frontend will call to talk to the zero-cache server. This is the URL of the fly app. Guide: Multi-Node on Raw AWS S3 Bucket Create an S3 bucket. zero-cache uses S3 to backup its SQLite replica so that it survives task restarts. Fargate Services Run zero-cache as two Fargate services (using the same rocicorp/zero docker image): replication-manager zero-cache config: ZERO\\_LITESTREAM\\_BACKUP\\_URL=s3://{bucketName}/{generation} ZERO\\_NUM\\_SYNC\\_WORKERS=0 Task count: 1 view-syncer zero-cache config: ZERO\\_CHANGE\\_STREAMER\\_URI=http://{replication-manager} Task count: N You can also use dynamic scaling Notes Standard rolling restarts are fine for both services Set ZERO\\_CVR\\_MAX\\_CONNS and ZERO\\_UPSTREAM\\_MAX\\_CONNS appropriately so that the total connections from both running and updating view-syncers (e.g. DesiredCount \\* MaximumPercent) do not exceed your database’s max\\_connections. The {generation} component of the s3://{bucketName}/{generation} URL is an arbitrary path component that can be modified to reset the replica (e.g. a date, a number, etc.). Setting this to a new path is the multi-node equivalent of deleting the replica file to resync. Note: zero-cache does not manage cleanup of old generations. The replication-manager serves requests on port 4849. Routing from the view-syncer to the http://{replication-manager} can be achieved using the following mechanisms (in order of preference): An internal load balancer Service Connect Service Discovery Fargate ephemeral storage is used for the replica. The default size is 20GB. This can be increased up to 200GB Allocate at least twice the size of the database to support the internal VACUUM operation. Guide: $PLATFORM Where should we deploy Zero next?? Let us know on Discord!", "headings": [] }, { @@ -94,7 +94,7 @@ "id": "13-introduction", "title": "Welcome to Zero Alpha", "url": "/docs/introduction", - "content": "Zero is a new kind of sync engine powered by queries. Rather than syncing entire tables to the client, or using static rules to carefully specify what to sync, you just write queries directly in your client code. Queries can access the entire backend database. Zero caches the data for queries locally on the device, and reuses that data automatically to answer future queries whenever possible. For typical applications, the result is that almost all queries are answered locally, instantly. It feels like you have access to the entire backend database directly from the client in memory. Occasionally, when you do a more specific query, Zero falls back to the server. But this happens automatically without any extra work required. Zero is made possible by a custom streaming query engine we built called ZQL, which uses Incremental View Maintenance on both client and server to efficiently keep large, complex queries up to date. Status Zero is in alpha. There are still some rough edges, and to run it, you need to deploy it yourself to AWS or similar. Even so, Zero is already quite fun to work with. We are using it ourselves to build our very own Linear-style bug tracker. We find that Zero is already much more productive than alternatives, even having to occasionally work around a missing feature. If you are building a new web app that needs to be fast and reactive, and can do the deployment yourself, it's a great time to get started with Zero. We're working toward a beta release and full production readiness this year.", + "content": "Zero is a new kind of sync engine powered by queries. Rather than syncing entire tables to the client, or using static rules to carefully specify what to sync, you just write queries directly in your client code. Queries can access the entire backend database. Zero caches the data for queries locally on the device, and reuses that data automatically to answer future queries whenever possible. For typical applications, the result is that almost all queries are answered locally, instantly. It feels like you have access to the entire backend database directly from the client in memory. Occasionally, when you do a more specific query, Zero falls back to the server. But this happens automatically without any extra work required. Zero is made possible by a custom streaming query engine we built called ZQL, which uses Incremental View Maintenance on both client and server to efficiently keep large, complex queries up to date.", "headings": [] }, { @@ -108,7 +108,7 @@ "id": "15-offline", "title": "Offline", "url": "/docs/offline", - "content": "Zero currently supports offline reads, but not writes. We plan to support offline writes in the future, but we don't have a timeline for that yet. The lack of offline writes is often surprising to people familiar with sync engines, because offline is usually touted as something that comes for free with these tools. This page explains why Zero doesn't currently support offline writes, how we recommend you handle connectivity loss, and our future plans in this area. Offline Writes are a UX Problem While Zero can technically queue offline writes and replay them when reconnected (this happens by default in any sync engine, and is what Zero does today), that fact doesn't make supporting offline writes much easier. That's because a really hard part of offline writes is in handling conflicts, and no software tool can make that problem go away. For example, imagine two users are editing an article about cats. One goes offline and does a bunch of work on the article, while the other decides that the article should actually be about dogs and rewrites it. When the offline user reconnects, there is no way that any software algorithm can automatically resolve their conflict. One or the other of them is going to be upset. And while the above example may sound extreme, you can construct similar situations with the majority of common applications. Just take your own application and ask yourself what should really happen if one user takes their device offline for a week and makes arbitrarily complex changes while other users are working online. People who work on sync engines and related tools often say that offline is just extreme lag, but that's only true at a technical level. At a human level, being \"offline\" for a few seconds is very different from being offline for a few hours. The difference is how much knowledge you have about what your collaborators are doing, and how much of your work can be lost. The only way to support offline writes in general is to either: Make the logical datamodel append-only (i.e., users can create and mark tasks done, but cannot edit or delete them). Support custom UX to allow users to fork and merge conflicts when they occur. Only support editing from a single device. None of these is free. Buiding a good offline UX is a lot of work, and most of that work is borne by application developers. … And a Schema Problem But it's not just users that can diverge from each other. The server software and database schema can also diverge arbitrarily far from the client while the client is disconnected. When the client comes back online, the changes made may no longer be processable by the application, or may have a different effect than the user intended. So to support long offline periods, the server must also maintain backward compatibility with clients indefinitely. Similarly, the server can never reject an offline write (i.e., due to validation) because that could lead to a user losing huge amounts of work. … And a Sync Engine Problem Supporting offline writes also requires work in the sync engine. In Zero, there are a few specific impacts: The Zero client itself can get out of date while offline. On reconnect, the app might reload with a new version of the client. This new version must be able to read and process old data from arbitrarily long ago. An arbitrarily large number of pending mutations can be built up. These mutations must be replayed on reconnect, which can take a long time. When processing mutations on server we must consider what should happen if the database or application server are temporarily unavailable. We need to treat that kind of error differently from a validation error. These problems are surmountable, but significant effort. Their solutions might also be in tension with other goals of the sync engine, like online performance and scalability. These tradeoffs will take time to work through. Zero's Position For all of the above reasons, we plan to disable offline writes in Zero for beta. When the Zero client loses connection to zero-cache for several minutes (or when zero-cache cannot reach the customer API server), it will enter a special offline mode. In this mode, all writes to Zero will throw. While we recognize that offline writes would be useful for some applications, the reality is that for most of the apps we want to support, the user is online the vast majority of the time and the cost to support offline is extremely high. There is simply more value in making the online experience great first. We would like to revisit this in the future and really think through how to design APIs and patterns that allow developers to make successful offline-enabled apps. But it's not our priority right now. Dealing with Offline Today Until Zero disables offline writes automatically, we recomment using the onOnlineChange parameter to the Zero constructor to detect connection loss and disable editing manually in your UI. Even More Information Lies I was Told About Collaborative Editing: a detailed overview of the challenges around offline writes in any collaborative editing system. This Zero Discord thread covers some challenges specifically in the context of Zero. Patchwork by Ink & Switch is new and interesting research around how to support offline writes well in collaborative systems.", + "content": "Zero currently supports offline reads, but not writes. We plan to support offline writes in the future, but we don't have a timeline for that yet. The lack of offline writes is often surprising to people familiar with sync engines, because offline is usually touted as something that comes for free with these tools. This page explains why Zero doesn't currently support offline writes, how we recommend you handle connectivity loss, and our future plans in this area. Offline Writes are a UX Problem While Zero can technically queue offline writes and replay them when reconnected (this happens by default in any sync engine, and is what Zero does today), that fact doesn't make supporting offline writes much easier. That's because a really hard part of offline writes is in handling conflicts, and no software tool can make that problem go away. For example, imagine two users are editing an article about cats. One goes offline and does a bunch of work on the article, while the other decides that the article should actually be about dogs and rewrites it. When the offline user reconnects, there is no way that any software algorithm can automatically resolve their conflict. One or the other of them is going to be upset. And while the above example may sound extreme, you can construct similar situations with the majority of common applications. Just take your own application and ask yourself what should really happen if one user takes their device offline for a week and makes arbitrarily complex changes while other users are working online. People who work on sync engines and related tools often say that offline is just extreme lag, but that's only true at a technical level. At a human level, being \"offline\" for a few seconds is very different from being offline for a few hours. The difference is how much knowledge you have about what your collaborators are doing, and how much of your work can be lost. The only way to support offline writes in general is to either: Make the logical datamodel append-only (i.e., users can create and mark tasks done, but cannot edit or delete them). Support custom UX to allow users to fork and merge conflicts when they occur. Only support editing from a single device. None of these is free. Buiding a good offline UX is a lot of work, and most of that work is borne by application developers. … And a Schema Problem But it's not just users that can diverge from each other. The server software and database schema can also diverge arbitrarily far from the client while the client is disconnected. When the client comes back online, the changes made may no longer be processable by the application, or may have a different effect than the user intended. So to support long offline periods, the server must also maintain backward compatibility with clients indefinitely. Similarly, the server can never reject an offline write (i.e., due to validation) because that could lead to a user losing huge amounts of work. … And a Sync Engine Problem Supporting offline writes also requires work in the sync engine. In Zero, there are a few specific impacts: The Zero client itself can get out of date while offline. On reconnect, the app might reload with a new version of the client. This new version must be able to read and process old data from arbitrarily long ago. An arbitrarily large number of pending mutations can be built up. These mutations must be replayed on reconnect, which can take a long time. When processing mutations on server we must consider what should happen if the database or application server are temporarily unavailable. We need to treat that kind of error differently from a validation error. These problems are surmountable, but significant effort. Their solutions might also be in tension with other goals of the sync engine, like online performance and scalability. These tradeoffs will take time to work through. Zero's Position For all of the above reasons, we plan to disable offline writes in Zero for beta. When the Zero client loses connection to zero-cache for several minutes (or when zero-cache cannot reach the customer API server), it will enter a special offline mode. In this mode, all writes to Zero will throw. While we recognize that offline writes would be useful for some applications, the reality is that for most of the apps we want to support, the user is online the vast majority of the time and the cost to support offline is extremely high. There is simply more value in making the online experience great first. We would like to revisit this in the future and really think through how to design APIs and patterns that allow developers to make successful offline-enabled apps. But it's not our priority right now. Dealing with Offline Today Until Zero disables offline writes automatically, use useZeroOnline to detect connection loss and manually disable writes in your UI: ```tsx const {online} = useZeroOnline(); return ; ``` ... or use the underlying zero.onOnline event: ```tsx const unsubscribe = zero.onOnline(online => { console.log('Online:', online); }); ``` Even More Information Lies I was Told About Collaborative Editing: a detailed overview of the challenges around offline writes in any collaborative editing system. This Zero Discord thread covers some challenges specifically in the context of Zero. Patchwork by Ink & Switch is new and interesting research around how to support offline writes well in collaborative systems.", "headings": [] }, { @@ -119,145 +119,145 @@ "headings": [] }, { - "id": "17-overview", - "title": "Concepts (How Zero Works)", - "url": "/docs/overview", - "content": "", - "headings": [] - }, - { - "id": "18-permissions", + "id": "17-permissions", "title": "Permissions", "url": "/docs/permissions", - "content": "Permissions are expressed using ZQL and run automatically with every read and write. Permissions are currently row based. Zero will eventually also have column permissions. Define Permissions Permissions are defined in schema.ts using the definePermissions function. Here's an example of limiting reads to members of an organization and deletes to only the creator of an issue: ```ts // The decoded value of your JWT. type AuthData = { // The logged-in user. sub: string; }; export const permissions = definePermissions(schema, () => { // Checks if the user exists in a related organization const allowIfInOrganization = ( authData: AuthData, eb: ExpressionBuilder, ) => eb.exists('organization', q => q.whereExists('user', q => q.where('id', authData.sub)), ); // Checks if the user is the creator const allowIfIssueCreator = ( authData: AuthData, {cmp}: ExpressionBuilder, ) => cmp('creatorID', authData.sub); return { issue: { row: { select: [allowIfInOrganization], delete: [allowIfIssueCreator], }, }, } satisfies PermissionsConfig; }); ``` definePermission returns a policy object for each table in the schema. Each policy defines a ruleset for the operations that are possible on a table: select, insert, update, and delete. Access is Denied by Default If you don't specify any rules for an operation, it is denied by default. This is an important safety feature that helps ensure data isn't accidentally exposed. To enable full access to an action (i.e., during development) use the ANYONE\\_CAN helper: ```ts import {ANYONE_CAN} from '@rocicorp/zero'; const permissions = definePermissions(schema, () => { return { issue: { row: { select: ANYONE_CAN, // Other operations are denied by default. }, }, // Other tables are denied by default. } satisfies PermissionsConfig; }); ``` To do this for all actions, use ANYONE\\_CAN\\_DO\\_ANYTHING: ```ts import {ANYONE_CAN_DO_ANYTHING} from '@rocicorp/zero'; const permissions = definePermissions(schema, () => { return { // All operations on issue are allowed to all users. issue: ANYONE_CAN_DO_ANYTHING, // Other tables are denied by default. } satisfies PermissionsConfig; }); ``` Permission Evaluation Zero permissions are \"compiled\" into a JSON-based format at build-time. This file is stored in the {ZERO\\_APP\\_ID}.permissions table of your upstream database. Like other tables, it replicates live down to zero-cache. zero-cache then parses this file, and applies the encoded rules to every read and write operation. The end result is that you can't really use most features of JS in these rules. Specifically you cannot: Iterate over properties or array elements in the auth token Use any JS features beyond property access of AuthData Use any conditional or global state Basically only property access is allowed. This is really confusing and we're working on a better solution. Permission Deployment During development, permissions are compiled and uploaded to your database completely automatically as part of the zero-cache-dev script. For production, you need to call npx zero-deploy-permissions within your app to update the permissions in the production database whenever they change. You would typically do this as part of your normal schema migration or CI process. For example, the SST deployment script for zbugs looks like this: ```ts new command.local.Command( 'zero-deploy-permissions', { create: `npx zero-deploy-permissions -p ../../src/schema.ts`, // Run the Command on every deploy ... triggers: [Date.now()], environment: { ZERO_UPSTREAM_DB: commonEnv.ZERO_UPSTREAM_DB, // If the application has a non-default App ID ... ZERO_APP_ID: commonEnv.ZERO_APP_ID, }, }, // after the view-syncer is deployed. {dependsOn: viewSyncer}, ); ``` See the SST Deployment Guide for more details. Rules Each operation on a policy has a ruleset containing zero or more rules. A rule is just a TypeScript function that receives the logged in user's AuthData and generates a ZQL where expression. At least one rule in a ruleset must return a row for the operation to be allowed. Select Permissions You can limit the data a user can read by specifying a select ruleset. Select permissions act like filters. If a user does not have permission to read a row, it will be filtered out of the result set. It will not generate an error. For example, imagine a select permission that restricts reads to only issues created by the user: ```ts definePermissions(schema, () => { const allowIfIssueCreator = ( authData: AuthData, {cmp}: ExpressionBuilder, ) => cmp('creatorID', authData.sub); return { issue: { row: { select: [allowIfIssueCreator], }, }, } satisfies PermissionsConfig; }); ``` If the issue table has two rows, one created by the user and one by someone else, the user will only see the row they created in any queries. Column permissions Zero does not currently support column based permissions. Select permission applies to every column. The recommended approach for now is to factor out private fields into a separate table, e.g. user\\_private. Column permissions are planned but currently not a high priority. Note that although the same limitation applies to declarative insert/update permissions, custom mutators support arbitrary server-side logic and so can easily control which columns are writable. Insert Permissions You can limit what rows can be inserted and by whom by specifying an insert ruleset. Insert rules are evaluated after the entity is inserted. So if they query the database, they will see the inserted row present. If any rule in the insert ruleset returns a row, the insert is allowed. Here's an example of an insert rule that disallows inserting users that have the role 'admin'. ```ts definePermissions(schema, () => { const allowIfNonAdmin = ( authData: AuthData, {cmp}: ExpressionBuilder, ) => cmp('role', '!=', 'admin'); return { user: { row: { insert: [allowIfNonAdmin], }, }, } satisfies PermissionsConfig; }); ``` Update Permissions There are two types of update rulesets: preMutation and postMutation. Both rulesets must pass for an update to be allowed. preMutation rules see the version of a row before the mutation is applied. This is useful for things like checking whether a user owns an entity before editing it. postMutation rules see the version of a row after the mutation is applied. This is useful for things like ensuring a user can only mark themselves as the creator of an entity and not other users. Like other rulesets, preMutation and postMutation default to NOBODY\\_CAN. This means that every table must define both these rulesets in order for any updates to be allowed. For example, the following ruleset allows an issue's owner to edit, but not re-assign the issue. The postMutation rule enforces that the current user still own the issue after edit. ```ts definePermissions(schema, () => { const allowIfIssueOwner = ( authData: AuthData, {cmp}: ExpressionBuilder, ) => cmp('ownerID', authData.sub); return { issue: { row: { update: { preMutation: [allowIfIssueOwner], postMutation: [allowIfIssueOwner], }, }, }, } satisfies PermissionsConfig; }); ``` This ruleset allows an issue's owner to edit and re-assign the issue: ```ts definePermissions(schema, () => { const allowIfIssueOwner = ( authData: AuthData, {cmp}: ExpressionBuilder, ) => cmp('ownerID', authData.sub); return { issue: { row: { update: { preMutation: [allowIfIssueOwner], postMutation: ANYONE_CAN, }, }, }, } satisfies PermissionsConfig; }); ``` And this allows anyone to edit an issue, but only if they also assign it to themselves. Useful for enforcing \"patches welcome\"? 🙃 ```ts definePermissions(schema, () => { const allowIfIssueOwner = ( authData: AuthData, {cmp}: ExpressionBuilder, ) => cmp('ownerID', authData.sub); return { issue: { row: { update: { preMutation: ANYONE_CAN, postMutation: [allowIfIssueOwner], }, }, }, } satisfies PermissionsConfig; }); ``` Delete Permissions Delete permissions work in the same way as insert permissions except they run before the delete is applied. So if a delete rule queries the database, it will see that the deleted row is present. If any rule in the ruleset returns a row, the delete is allowed. Debugging See Debugging Permissions. Examples See hello-zero for a simple example of write auth and zbugs for a much more involved one.", + "content": "Permissions are expressed using ZQL and run automatically with every read and write. Permissions are currently row based. Zero will eventually also have column permissions. Define Permissions Permissions are defined in schema.ts using the definePermissions function. Here's an example of limiting reads to members of an organization and deletes to only the creator of an issue: ```ts // The decoded value of your JWT. type AuthData = { // The logged-in user. sub: string; }; export const permissions = definePermissions(schema, () => { // Checks if the user exists in a related organization const allowIfInOrganization = ( authData: AuthData, eb: ExpressionBuilder, ) => eb.exists('organization', q => q.whereExists('user', q => q.where('id', authData.sub)), ); // Checks if the user is the creator const allowIfIssueCreator = ( authData: AuthData, {cmp}: ExpressionBuilder, ) => cmp('creatorID', authData.sub); return { issue: { row: { select: [allowIfInOrganization], delete: [allowIfIssueCreator], }, }, } satisfies PermissionsConfig; }); ``` definePermission returns a policy object for each table in the schema. Each policy defines a ruleset for the operations that are possible on a table: select, insert, update, and delete. Access is Denied by Default If you don't specify any rules for an operation, it is denied by default. This is an important safety feature that helps ensure data isn't accidentally exposed. To enable full access to an action (i.e., during development) use the ANYONE\\_CAN helper: ```ts import {ANYONE_CAN} from '@rocicorp/zero'; const permissions = definePermissions(schema, () => { return { issue: { row: { select: ANYONE_CAN, // Other operations are denied by default. }, }, // Other tables are denied by default. } satisfies PermissionsConfig; }); ``` To do this for all actions, use ANYONE\\_CAN\\_DO\\_ANYTHING: ```ts import {ANYONE_CAN_DO_ANYTHING} from '@rocicorp/zero'; const permissions = definePermissions(schema, () => { return { // All operations on issue are allowed to all users. issue: ANYONE_CAN_DO_ANYTHING, // Other tables are denied by default. } satisfies PermissionsConfig; }); ``` Permission Evaluation Zero permissions are \"compiled\" into a JSON-based format at build-time. This file is stored in the {ZERO\\_APP\\_ID}.permissions table of your upstream database. Like other tables, it replicates live down to zero-cache. zero-cache then parses this file, and applies the encoded rules to every read and write operation. The end result is that you can't really use most features of JS in these rules. Specifically you cannot: Iterate over properties or array elements in the auth token Use any JS features beyond property access of AuthData Use any conditional or global state Basically only property access is allowed. This is really confusing and we're working on a better solution. Permission Deployment During development, permissions are compiled and uploaded to your database completely automatically as part of the zero-cache-dev script. For production, you need to call npx zero-deploy-permissions within your app to update the permissions in the production database whenever they change. You would typically do this as part of your normal schema migration or CI process. For example, the SST deployment script for zbugs looks like this: ```ts new command.local.Command( 'zero-deploy-permissions', { create: `npx zero-deploy-permissions -p ../../src/schema.ts`, // Run the Command on every deploy ... triggers: [Date.now()], environment: { ZERO_UPSTREAM_DB: commonEnv.ZERO_UPSTREAM_DB, // If the application has a non-default App ID ... ZERO_APP_ID: commonEnv.ZERO_APP_ID, }, }, // after the view-syncer is deployed. {dependsOn: viewSyncer}, ); ``` See the SST Deployment Guide for more details. Rules Each operation on a policy has a ruleset containing zero or more rules. A rule is just a TypeScript function that receives the logged in user's AuthData and generates a ZQL where expression. At least one rule in a ruleset must return a row for the operation to be allowed. Select Permissions You can limit the data a user can read by specifying a select ruleset. Select permissions act like filters. If a user does not have permission to read a row, it will be filtered out of the result set. It will not generate an error. For example, imagine a select permission that restricts reads to only issues created by the user: ```ts definePermissions(schema, () => { const allowIfIssueCreator = ( authData: AuthData, {cmp}: ExpressionBuilder, ) => cmp('creatorID', authData.sub); return { issue: { row: { select: [allowIfIssueCreator], }, }, } satisfies PermissionsConfig; }); ``` If the issue table has two rows, one created by the user and one by someone else, the user will only see the row they created in any queries. Note that although the same limitation applies to declarative insert/update permissions, custom mutators support arbitrary server-side logic and so can easily control which columns are writable. Insert Permissions You can limit what rows can be inserted and by whom by specifying an insert ruleset. Insert rules are evaluated after the entity is inserted. So if they query the database, they will see the inserted row present. If any rule in the insert ruleset returns a row, the insert is allowed. Here's an example of an insert rule that disallows inserting users that have the role 'admin'. ```ts definePermissions(schema, () => { const allowIfNonAdmin = ( authData: AuthData, {cmp}: ExpressionBuilder, ) => cmp('role', '!=', 'admin'); return { user: { row: { insert: [allowIfNonAdmin], }, }, } satisfies PermissionsConfig; }); ``` Update Permissions There are two types of update rulesets: preMutation and postMutation. Both rulesets must pass for an update to be allowed. preMutation rules see the version of a row before the mutation is applied. This is useful for things like checking whether a user owns an entity before editing it. postMutation rules see the version of a row after the mutation is applied. This is useful for things like ensuring a user can only mark themselves as the creator of an entity and not other users. Like other rulesets, preMutation and postMutation default to NOBODY\\_CAN. This means that every table must define both these rulesets in order for any updates to be allowed. For example, the following ruleset allows an issue's owner to edit, but not re-assign the issue. The postMutation rule enforces that the current user still own the issue after edit. ```ts definePermissions(schema, () => { const allowIfIssueOwner = ( authData: AuthData, {cmp}: ExpressionBuilder, ) => cmp('ownerID', authData.sub); return { issue: { row: { update: { preMutation: [allowIfIssueOwner], postMutation: [allowIfIssueOwner], }, }, }, } satisfies PermissionsConfig; }); ``` This ruleset allows an issue's owner to edit and re-assign the issue: ```ts definePermissions(schema, () => { const allowIfIssueOwner = ( authData: AuthData, {cmp}: ExpressionBuilder, ) => cmp('ownerID', authData.sub); return { issue: { row: { update: { preMutation: [allowIfIssueOwner], postMutation: ANYONE_CAN, }, }, }, } satisfies PermissionsConfig; }); ``` And this allows anyone to edit an issue, but only if they also assign it to themselves. Useful for enforcing \"patches welcome\"? 🙃 ```ts definePermissions(schema, () => { const allowIfIssueOwner = ( authData: AuthData, {cmp}: ExpressionBuilder, ) => cmp('ownerID', authData.sub); return { issue: { row: { update: { preMutation: ANYONE_CAN, postMutation: [allowIfIssueOwner], }, }, }, } satisfies PermissionsConfig; }); ``` Delete Permissions Delete permissions work in the same way as insert permissions except they run before the delete is applied. So if a delete rule queries the database, it will see that the deleted row is present. If any rule in the ruleset returns a row, the delete is allowed. Permissions Based on Auth Data You can use the cmpLit helper to define permissions based on a field of the authData parameter: ```ts definePermissions(schema, () => { const allowIfAdmin = ( authData: AuthData, {cmpLit}: ExpressionBuilder, ) => cmpLit(authData.role, 'admin'); return { issue: { row: { select: [allowIfAdmin], }, }, } satisfies PermissionsConfig; }); ``` Debugging See Debugging Permissions. Examples See hello-zero for a simple example of write auth and zbugs for a much more involved one.", "headings": [] }, { - "id": "19-postgres-support", + "id": "18-postgres-support", "title": "Supported Postgres Features", "url": "/docs/postgres-support", "content": "Postgres has a massive feature set, and Zero supports a growing subset of it. Object Names Table and column names must begin with a letter or underscore This can be followed by letters, numbers, underscores, and hyphens Regex: /^\\[A-Za-z\\_]+\\[A-Za-z0-9\\_-]\\*$/ The column name \\_0\\_version is reserved for internal use Object Types Tables are synced Views are not synced identity generated columns are synced All other generated columns are not synced Indexes aren't synced per-se, but we do implicitly add indexes to the replica that match the upstream indexes. In the future, this will be customizable. Column Types Zero will sync arrays to the client, but there is no support for filtering or joining on array elements yet in ZQL. Other Postgres column types aren’t supported. They will be ignored when replicating (the synced data will be missing that column) and you will get a warning when zero-cache starts up. If your schema has a pg type not listed here, you can support it in Zero by using a trigger to map it to some type that Zero can support. For example if you have a GIS polygon type in the column my\\_poly polygon, you can use a trigger to map it to a my\\_poly\\_json json column. You could either use another trigger to map in the reverse direction to support changes for writes, or you could use a custom mutator to write to the polygon type directly on the server. Let us know if the lack of a particular column type is hindering your use of Zero. It can likely be added. Column Defaults Default values are allowed in the Postgres schema, but there currently is no way to use them from a Zero app. An insert() mutation requires all columns to be specified, except when columns are nullable (in which case, they default to null). Since there is no way to leave non-nullable columns off the insert on the client, there is no way for PG to apply the default. This is a known issue and will be fixed in the future. IDs It is strongly recommended to use client-generated random strings like uuid, ulid, nanoid, etc for primary keys. This makes optimistic creation and updates much easier. You could sync the highest value seen for that table, but there are race conditions and it is possible for that ID to be taken by the time the creation makes it to the server. Your database can resolve this and assign the next ID, but now the relationships you created optimistically will be against the wrong row. Blech. GUIDs makes a lot more sense in synced applications. If your table has a natural key you can use that and it has less problems. But there is still the chance for a conflict. Imagine you are modeling orgs and you choose domainName as the natural key. It is possible for a race to happen and when the creation gets to the server, somebody has already chosen that domain name. In that case, the best thing to do is reject the write and show the user an error. If you want to have a short auto-incrementing numeric ID for UX reasons (i.e., a bug number), that is possible - see this video. Primary Keys Each table synced with Zero must have either a primary key or at least one unique index. This is needed so that Zero can identify rows during sync, to distinguish between an edit and a remove/add. Multi-column primary and foreign keys are supported. Limiting Replication You can use Permissions to limit tables and rows from replicating to Zero. In the near future, you'll also be able to use Permissions to limit individual columns. Until then, a workaround is to use the Postgres publication feature to control the tables and columns that are replicated into zero-cache. In your pg schema setup, create a Postgres publication with the tables and columns you want: ```sql CREATE PUBLICATION zero_data FOR TABLE users (col1, col2, col3, ...), issues, comments; ``` Then, specify this publication in the App Publications zero-cache option. (By default, Zero creates a publication that publishes the entire public schema.) To limit what is synced from the zero-cache replica to actual clients (e.g., web browsers) you can use read permissions. Schema changes Most Postgres schema changes are supported as is. Two cases require special handling: Adding columns Adding a column with a non-constant DEFAULT value is not supported. This includes any expression with parentheses, as well as the special functions CURRENT\\_TIME, CURRENT\\_DATE, and CURRENT\\_TIMESTAMP (due to a constraint of SQLite). However, the DEFAULT value of an existing column can be changed to any value, including non-constant expressions. To achieve the desired column default: Add the column with no DEFAULT value Backfill the column with desired values Set the column's DEFAULT value ```sql BEGIN; ALTER TABLE foo ADD bar ...; -- without a DEFAULT value UPDATE foo SET bar = ...; ALTER TABLE foo ALTER bar SET DEFAULT ...; COMMIT; ``` Changing publications Postgres allows you to change published tables/columns with an ALTER PUBLICATION statement. Zero automatically adjusts the table schemas on the replica, but it does not receive the pre-existing data. To stream the pre-existing data to Zero, make an innocuous UPDATE after adding the tables/columns to the publication: ```sql BEGIN; ALTER PUBLICATION zero_data ADD TABLE foo; ALTER TABLE foo REPLICA IDENTITY FULL; UPDATE foo SET id = id; -- For some column \"id\" in \"foo\" ALTER TABLE foo REPLICA IDENTITY DEFAULT; COMMIT; ``` Self-Referential Relationships See zero-schema", "headings": [] }, { - "id": "20-quickstart", + "id": "19-quickstart", "title": "Quickstart", "url": "/docs/quickstart", "content": "Prerequisites Docker Node 20+ Run In one terminal, install and start the database: ```bash git clone https://github.com/rocicorp/hello-zero.git cd hello-zero npm install npm run dev:db-up ``` In a second terminal, start zero-cache: ```bash cd hello-zero npm run dev:zero-cache ``` In a final terminal, start the UI: ```bash cd hello-zero npm run dev:ui ``` Quick Overview hello-zero is a demo app that allows querying over a small dataset of fake messages between early Zero users. Here are some things to try: Press the Add Messages button to add messages to the UI. Any logged-in or anonymous users are allowed to add messages. Press the Remove Messages button to remove messages. Only logged-in users are allowed to remove messages. You can hold shift to bypass the UI warning and see that write access control is being enforced server-side – the UI flickers as the optimistic write happens instantly and is then reverted by the server. Press login to login as a random user, then the remove button will work. Open two different browsers and see how fast sync propagates changes. Add a filter using the From and Contains controls. Notice that filters are fully dynamic and synced. Edit a message by pressing the pencil icon. You can only edit messages from the user you’re logged in as. As before you can attempt to bypass by holding shift. Check out the SQL schema for this database in seed.sql. Login to the database with psql postgresql://user:password@127.0.0.1:5430/postgres (or any other pg viewer) and delete or alter a row. Observe that it deletes from UI automatically. Detailed Walkthrough Deployment You can deploy Zero apps to most cloud providers that support Docker and Postgres. See Deployment for more information.", "headings": [] }, { - "id": "21-react", + "id": "20-react", "title": "React", "url": "/docs/react", "content": "Zero has built-in support for React. Here’s what basic usage looks like: ```tsx import {useQuery, useZero} from '@rocicorp/zero/react'; import {type Schema} from './schema.ts'; import {type Mutators} from './mutators.ts'; function IssueList() { const z = useZero(); let issueQuery = z.query.issue .related('creator') .related('labels') .limit(100); const userID = selectedUserID(); if (userID) { issueQuery = issueQuery.where('creatorID', '=', userID); } const [issues, issuesDetail] = useQuery(issueQuery); return ( <>
{issuesDetail.type === 'complete' ? 'Complete' : 'Partial'} results
{issues.map(issue => ( ))}
); } ``` ZeroProvider The useZero hook must be used within a ZeroProvider component. The ZeroProvider component is responsible for creating and destroying Zero instances reactively. ```tsx import {SessionProvider} from 'my-auth-provider'; import {ZeroProvider} from '@rocicorp/zero/react'; import {type Schema, schema} from './schema.ts'; import {type Mutators, createMutators} from './mutators.ts'; export function Root() { const session = useSession(); const {userID, authToken: auth} = session; const server = import.meta.env.VITE_PUBLIC_SERVER; const mutators = useMemo(() => { return createMutators(auth); }, [auth]); return ( // ZeroProvider will reactively create and destroy Zero instances // as needed when props change. ); } ``` You can also pass a Zero instance to the ZeroProvider if you want to control the lifecycle of the Zero instance yourself: ```tsx // ZeroProvider just sets up the context, it doesn't manage // the lifecycle of the Zero instance. ``` Complete quickstart here: https://github.com/rocicorp/hello-zero", "headings": [] }, { - "id": "22-reading-data", + "id": "21-reading-data", "title": "Reading Data with ZQL", "url": "/docs/reading-data", - "content": "ZQL is Zero’s query language. Inspired by SQL, ZQL is expressed in TypeScript with heavy use of the builder pattern. If you have used Drizzle or Kysely, ZQL will feel familiar. ZQL queries are composed of one or more clauses that are chained together into a query. Unlike queries in classic databases, the result of a ZQL query is a view that updates automatically and efficiently as the underlying data changes. You can call a query’s materialize() method to get a view, but more typically you run queries via some framework-specific bindings. For example see useQuery for React or SolidJS. ZQL caches values and returns them multiple times. If you modify a value returned from ZQL, you will modify it everywhere it is used. This can lead to subtle bugs. JavaScript and TypeScript lack true immutable types so we use readonly to help enforce it. But it's easy to cast away the readonly accidentally. In the future, we'll freeze all returned data in dev mode to help prevent this. Select ZQL queries start by selecting a table. There is no way to select a subset of columns; ZQL queries always return the entire row (modulo column permissions). ```tsx const z = new Zero(...); // Returns a query that selects all rows and columns from the issue table. z.query.issue; ``` This is a design tradeoff that allows Zero to better reuse the row locally for future queries. This also makes it easier to share types between different parts of the code. Ordering You can sort query results by adding an orderBy clause: ```tsx z.query.issue.orderBy('created', 'desc'); ``` Multiple orderBy clauses can be present, in which case the data is sorted by those clauses in order: ```tsx // Order by priority descending. For any rows with same priority, // then order by created desc. z.query.issue.orderBy('priority', 'desc').orderBy('created', 'desc'); ``` All queries in ZQL have a default final order of their primary key. Assuming the issue table has a primary key on the id column, then: ```tsx // Actually means: z.query.issue.orderBy('id', 'asc'); z.query.issue; // Actually means: z.query.issue.orderBy('priority', 'desc').orderBy('id', 'asc'); z.query.issue.orderBy('priority', 'desc'); ``` Limit You can limit the number of rows to return with limit(): ```tsx z.query.issue.orderBy('created', 'desc').limit(100); ``` Paging You can start the results at or after a particular row with start(): ```tsx let start: IssueRow | undefined; while (true) { let q = z.query.issue.orderBy('created', 'desc').limit(100); if (start) { q = q.start(start); } const batch = await q.run(); console.log('got batch', batch); if (batch.length < 100) { break; } start = batch[batch.length - 1]; } ``` By default start() is exclusive - it returns rows starting after the supplied reference row. This is what you usually want for paging. If you want inclusive results, you can do: ```tsx z.query.issue.start(row, {inclusive: true}); ``` Getting a Single Result If you want exactly zero or one results, use the one() clause. This causes ZQL to return Row|undefined rather than Row\\[]. ```tsx const result = await z.query.issue.where('id', 42).one().run(); if (!result) { console.error('not found'); } ``` one() overrides any limit() clause that is also present. Relationships You can query related rows using relationships that are defined in your Zero schema. ```tsx // Get all issues and their related comments z.query.issue.related('comments'); ``` Relationships are returned as hierarchical data. In the above example, each row will have a comments field which is itself an array of the corresponding comments row. You can fetch multiple relationships in a single query: ```tsx z.query.issue.related('comments').related('reactions').related('assignees'); ``` Refining Relationships By default all matching relationship rows are returned, but this can be refined. The related method accepts an optional second function which is itself a query. ```tsx z.query.issue.related( 'comments', // It is common to use the 'q' shorthand variable for this parameter, // but it is a _comment_ query in particular here, exactly as if you // had done z.query.comment. q => q.orderBy('modified', 'desc').limit(100).start(lastSeenComment), ); ``` This relationship query can have all the same clauses that top-level queries can have. You can sometimes work around this by making the junction relationship explicit, depending on your schema and usage. Nested Relationships You can nest relationships arbitrarily: ```tsx // Get all issues, first 100 comments for each (ordered by modified,desc), // and for each comment all of its reactions. z.query.issue.related('comments', q => q.orderBy('modified', 'desc').limit(100).related('reactions'), ); ``` Where You can filter a query with where(): ```tsx z.query.issue.where('priority', '=', 'high'); ``` The first parameter is always a column name from the table being queried. Intellisense will offer available options (sourced from your Zero Schema). Comparison Operators Where supports the following comparison operators: | Operator | Allowed Operand Types | Description | | ---------------------------------------- | ----------------------------- | ------------------------------------------------------------------------ | | = , != | boolean, number, string | JS strict equal (===) semantics | | < , <=, >, >= | number | JS number compare semantics | | LIKE, NOT LIKE, ILIKE, NOT ILIKE | string | SQL-compatible LIKE / ILIKE | | IN , NOT IN | boolean, number, string | RHS must be array. Returns true if rhs contains lhs by JS strict equals. | | IS , IS NOT | boolean, number, string, null | Same as = but also works for null | TypeScript will restrict you from using operators with types that don’t make sense – you can’t use > with boolean for example. Equals is the Default Comparison Operator Because comparing by = is so common, you can leave it out and where defaults to =. ```tsx z.query.issue.where('priority', 'high'); ``` Comparing to null As in SQL, ZQL’s null is not equal to itself (null ≠ null). This is required to make join semantics work: if you’re joining employee.orgID on org.id you do not want an employee in no organization to match an org that hasn’t yet been assigned an ID. When you purposely want to compare to null ZQL supports IS and IS NOT operators that work just like in SQL: ```tsx // Find employees not in any org. z.query.employee.where('orgID', 'IS', null); ``` TypeScript will prevent you from comparing to null with other operators. Compound Filters The argument to where can also be a callback that returns a complex expression: ```tsx // Get all issues that have priority 'critical' or else have both // priority 'medium' and not more than 100 votes. z.query.issue.where(({cmp, and, or, not}) => or( cmp('priority', 'critical'), and(cmp('priority', 'medium'), not(cmp('numVotes', '>', 100))), ), ); ``` cmp is short for compare and works the same as where at the top-level except that it can’t be chained and it only accepts comparison operators (no relationship filters – see below). Note that chaining where() is also a one-level and: ```tsx // Find issues with priority 3 or higher, owned by aa z.query.issue.where('priority', '>=', 3).where('owner', 'aa'); ``` Relationship Filters Your filter can also test properties of relationships. Currently the only supported test is existence: ```tsx // Find all orgs that have at least one employee z.query.organization.whereExists('employees'); ``` The argument to whereExists is a relationship, so just like other relationships it can be refined with a query: ```tsx // Find all orgs that have at least one cool employee z.query.organization.whereExists('employees', q => q.where('location', 'Hawaii'), ); ``` As with querying relationships, relationship filters can be arbitrarily nested: ```tsx // Get all issues that have comments that have reactions z.query.issue.whereExists('comments', q => q.whereExists('reactions')); ); ``` The exists helper is also provided which can be used with and, or, cmp, and not to build compound filters that check relationship existence: ```tsx // Find issues that have at least one comment or are high priority z.query.issue.where({cmp, or, exists} => or( cmp('priority', 'high'), exists('comments'), ), ); ``` Data Lifetime and Reuse Zero reuses data synced from prior queries to answer new queries when possible. This is what enables instant UI transitions. But what controls the lifetime of this client-side data? How can you know whether any particular query will return instant results? How can you know whether those results will be up to date or stale? The answer is that the data on the client is simply the union of rows returned from queries which are currently syncing. Once a row is no longer returned by any syncing query, it is removed from the client. Thus, there is never any stale data in Zero. So when you are thinking about whether a query is going to return results instantly, you should think about what other queries are syncing, not about what data is local. Data exists locally if and only if there is a query syncing that returns that data. A cache has a random set of rows with a random set of versions. There is no expectation that the cache any particular rows, or that the rows' have matching versions. Rows are simply updated as they are fetched. A replica by contrast is eagerly updated, whether or not any client has requested a row. A replica is always very close to up-to-date, and always self-consistent. Zero is a partial replica because it only replicates rows that are returned by syncing queries. Query Lifecycle Queries can be either active or backgrounded. An active query is one that is currently being used by the application. Backgrounded queries are not currently in use, but continue syncing in case they are needed again soon. Active queries are created one of three ways: The app calls q.materialize() to get a View. The app uses a platform binding like React's useQuery(q). The app calls preload() to sync larger queries without a view. Active queries sync until they are deactivated. The way this happens depends on how the query was created: For materialize() queries, the UI calls destroy() on the view. For useQuery(), the UI unmounts the component (which calls destroy() under the covers). For preload(), the UI calls cleanup() on the return value of preload(). Background Queries By default a deactivated query stops syncing immediately. But it's often useful to keep queries syncing beyond deactivation in case the UI needs the same or a similar query in the near future. This is accomplished with the ttl parameter: ```ts const [user] = useQuery(z.query.user.where('id', userId), {ttl: '1d'}); ``` The ttl parameter specifies how long the app developer wishes the query to run in the background. The following formats are allowed (where %d is a positive integer): | Format | Meaning | | --------- | ------------------------------------------------------------------------------------ | | none | No backgrounding. Query will immediately stop when deactivated. This is the default. | | %ds | Number of seconds. | | %dm | Number of minutes. | | %dh | Number of hours. | | %dd | Number of days. | We realized long ttl values can lead to a lot of queries running in the background unnecessarily. If a new app release is deployed with new queries, the old queries keep running until their ttl expires, even though the app will never use them. We will be reworking this API to be less of a footgun in the next Zero release. For now we do not recommend using a ttl greater than 1d. If the UI re-requests a background query, it becomes an active query again. Since the query was syncing in the background, the very first synchronous result that the UI receives after reactivation will be up-to-date with the server (i.e., it will have resultType of complete). Just like other types of queries, the data from background queries is available for use by new queries. A common pattern in to preload a subset of most commonly needed data with {ttl: 'forever'} and then do more specific queries from the UI with, e.g., {ttl: '1d'}. Most often the preloaded data will be able to answer user queries, but if not, the new query will be answered by the server and backgrounded for a day in case the user revisits it. Client Capacity Management Zero has a default soft limit of 20,000 rows on the client-side, or about 20MB of data assuming 1KB rows. This limit can be increased with the --target-client-row-count flag, but we do not recommend setting it higher than 100,000. Initial sync will be slow, slowing down initial app load. Because storage in browser tabs is unreliable, initial sync can occur surprisingly often. We want to answer queries instantly as often as possible. This requires client-side data in memory on the main thread. If we have to page to disk, we may as well go to the network and reduce complexity. Even though Zero's queries are very efficient, they do still have some cost, especially hydration. Massive client-side storage would result in hydrating tons of queries that are unlikely to be used every time the app starts. Most importantly, no matter how much data you store on the client, there will be cases where you have to fallback to the server: Some users might have huge amounts of data. Some users might have tiny amounts of available client storage. You will likely want the app to start fast and sync in the background. Because you have to be able to fallback to server the question becomes what is the right amount of data to store on the client?, not how can I store the absolute max possible data on the client? The goal with Zero is to answer 99% of queries on the client from memory. The remaining 1% of queries can fallback gracefully to the server. 20,000 rows was chosen somewhat arbitrarily as a number of rows that was likely to be able to do this for many applications. There is no hard limit at 20,000 or 100,000. Nothing terrible happens if you go above. The thing to keep in mind is that: All those queries will revalidate every time your app boots. All data synced to the client is in memory in JS. Here is how this limit is managed: Active queries are never destroyed, even if the limit is exceeded. Developers are expected to keep active queries well under the limit. The ttl value counts from the moment a query deactivates. Backgrounded queries are destroyed immediately when the ttl is reached, even if the limit hasn't been reached. If the client exceeds its limit, Zero will destroy backgrounded queries, least-recently-used first, until the store is under the limit again. Thinking in Queries Although IVM is a very efficient way to keep queries up to date relative to re-running them, it isn't free. You still need to think about how many queries you are creating, how long they are kept alive, and how expensive they are. This is why Zero defaults to not backgrounding queries and doesn't try to aggressively fill its client datastore to capacity. You should put some thought into what queries you want to run in the background, and for how long. Zero currently provides a few basic tools to understand the cost of your queries: The client logs a warning for slow query materializations. Look for Slow query materialization in your logs. The default threshold is 5s (including network) but this is configurable with the slowMaterializeThreshold parameter. The client logs the materialization time of all queries at the debug level. Look for Materialized query in your logs. The server logs a warning for slow query materializations. Look for Slow query materialization in your logs. The default threshold is 5s but this is configurable with the log-slow-materialize-threshold configuration parameter. We will be adding more tools over time. Completeness Zero returns whatever data it has on the client immediately for a query, then falls back to the server for any missing data. Sometimes it's useful to know the difference between these two types of results. To do so, use the result from useQuery: ```tsx const [issues, issuesResult] = useQuery(z.query.issue); if (issuesResult.type === 'complete') { console.log('All data is present'); } else { console.log('Some data is missing'); } ``` The possible values of result.type are currently complete and unknown. The complete value is currently only returned when Zero has received the server result. But in the future, Zero will be able to return this result type when it knows that all possible data for this query is already available locally. Additionally, we plan to add a prefix result for when the data is known to be a prefix of the complete result. See Consistency for more information. Handling Missing Data It is inevitable that there will be cases where the requested data cannot be found. Because Zero returns local results immediately, and server results asynchronously, displaying \"not found\" / 404 UI can be slightly tricky. If you just use a simple existence check, you will often see the 404 UI flicker while the server result loads: ```tsx const [issue, issuesResult] = useQuery( z.query.issue.where('id', 'some-id').one(), ); // ❌ This causes flickering of the UI if (!issue) { return
404 Not Found
; } else { return
{issue}
; } ``` The way to do this correctly is to only display the \"not found\" UI when the result type is complete. This way the 404 page is slow but pages with data are still just as fast. ```tsx const [issue, issuesResult] = useQuery( z.query.issue.where('id', 'some-id').one(), ); if (!issue && issueResult.type === 'complete') { return
404 Not Found
; } if (!issue) { return null; } return
{issue}
; ``` Listening to Changes Currently, the way to listen for changes in query results is not ideal. You can add a listener to a materialized view which has the new data and result as parameters: ```ts z.query.issue.materialize().addListener((issues, issuesResult) => { // do stuff... }); ``` However, using this method will maintain its own materialized view in memory which is wasteful. It also doesn't allow for granular listening to events like add and remove of rows. A better way would be to create your own view without actually storing the data which will also allow you to listen to specific events. Again, the API is not good and will be improved in the future. ```ts // Inside the View class // Instead of storing the change, we invoke some callback push(change: Change): void { switch (change.type) { case 'add': this.#onAdd?.(change) break case 'remove': this.#onRemove?.(change) break case 'edit': this.#onEdit?.(change) break case 'child': this.#onChild?.(change) break default: throw new Error(`Unknown change type: ${change['type']}`) } } ``` (see View implementations in zero-vue or zero-solid) Preloading Almost all Zero apps will want to preload some data in order to maximize the feel of instantaneous UI transitions. In Zero, preloading is done via queries – the same queries you use in the UI and for auth. However, because preload queries are usually much larger than a screenful of UI, Zero provides a special preload() helper to avoid the overhead of materializing the result into JS objects: ```tsx // Preload the first 1k issues + their creator, assignee, labels, and // the view state for the active user. // // There's no need to render this data, so we don't use `useQuery()`: // this avoids the overhead of pulling all this data into JS objects. z.query.issue .related('creator') .related('assignee') .related('labels') .related('viewState', q => q.where('userID', z.userID).one()) .orderBy('created', 'desc') .limit(1000) .preload(); ``` Running Queries Once Usually subscribing to a query is what you want in a reactive UI, but every so often you'll need to run a query just once. To do this, use the run() method: ```tsx const results = await z.query.issue.where('foo', 'bar').run(); ``` By default, run() only returns results that are currently available on the client. That is, it returns the data that would be given for result.type === 'unknown'. If you want to wait for the server to return results, pass {type: 'complete'} to run: ```tsx const results = await z.query.issue.where('foo', 'bar').run({type: 'complete'});await z.query.issue.where('foo', 'bar'); ``` This is the same as saying run() or run({type: 'unknown'}). Consistency Zero always syncs a consistent partial replica of the backend database to the client. This avoids many common consistency issues that come up in classic web applications. But there are still some consistency issues to be aware of when using Zero. For example, imagine that you have a bug database w/ 10k issues. You preload the first 1k issues sorted by created. The user then does a query of issues assigned to themselves, sorted by created. Among the 1k issues that were preloaded imagine 100 are found that match the query. Since the data we preloaded is in the same order as this query, we are guaranteed that any local results found will be a prefix of the server results. The UX that result is nice: the user will see initial results to the query instantly. If more results are found server-side, those results are guaranteed to sort below the local results. There's no shuffling of results when the server response comes in. Now imagine that the user switches the sort to ‘sort by modified’. This new query will run locally, and will again find some local matches. But it is now unlikely that the local results found are a prefix of the server results. When the server result comes in, the user will probably see the results shuffle around. To avoid this annoying effect, what you should do in this example is also preload the first 1k issues sorted by modified desc. In general for any query shape you intend to do, you should preload the first n results for that query shape with no filters, in each sort you intend to use. In the future, we will be implementing a consistency model that fixes these issues automatically. We will prevent Zero from returning local data when that data is not known to be a prefix of the server result. Once the consistency model is implemented, preloading can be thought of as purely a performance thing, and not required to avoid unsightly flickering.", + "content": "ZQL is Zero’s query language. Inspired by SQL, ZQL is expressed in TypeScript with heavy use of the builder pattern. If you have used Drizzle or Kysely, ZQL will feel familiar. ZQL queries are composed of one or more clauses that are chained together into a query. Unlike queries in classic databases, the result of a ZQL query is a view that updates automatically and efficiently as the underlying data changes. You can call a query’s materialize() method to get a view, but more typically you run queries via some framework-specific bindings. For example see useQuery for React or SolidJS. ZQL caches values and returns them multiple times. If you modify a value returned from ZQL, you will modify it everywhere it is used. This can lead to subtle bugs. JavaScript and TypeScript lack true immutable types so we use readonly to help enforce it. But it's easy to cast away the readonly accidentally. In the future, we'll freeze all returned data in dev mode to help prevent this. Select ZQL queries start by selecting a table. There is no way to select a subset of columns; ZQL queries always return the entire row (modulo column permissions). ```tsx const z = new Zero(...); // Returns a query that selects all rows and columns from the issue table. z.query.issue; ``` This is a design tradeoff that allows Zero to better reuse the row locally for future queries. This also makes it easier to share types between different parts of the code. Ordering You can sort query results by adding an orderBy clause: ```tsx z.query.issue.orderBy('created', 'desc'); ``` Multiple orderBy clauses can be present, in which case the data is sorted by those clauses in order: ```tsx // Order by priority descending. For any rows with same priority, // then order by created desc. z.query.issue.orderBy('priority', 'desc').orderBy('created', 'desc'); ``` All queries in ZQL have a default final order of their primary key. Assuming the issue table has a primary key on the id column, then: ```tsx // Actually means: z.query.issue.orderBy('id', 'asc'); z.query.issue; // Actually means: z.query.issue.orderBy('priority', 'desc').orderBy('id', 'asc'); z.query.issue.orderBy('priority', 'desc'); ``` Limit You can limit the number of rows to return with limit(): ```tsx z.query.issue.orderBy('created', 'desc').limit(100); ``` Paging You can start the results at or after a particular row with start(): ```tsx let start: IssueRow | undefined; while (true) { let q = z.query.issue.orderBy('created', 'desc').limit(100); if (start) { q = q.start(start); } const batch = await q.run(); console.log('got batch', batch); if (batch.length < 100) { break; } start = batch[batch.length - 1]; } ``` By default start() is exclusive - it returns rows starting after the supplied reference row. This is what you usually want for paging. If you want inclusive results, you can do: ```tsx z.query.issue.start(row, {inclusive: true}); ``` Getting a Single Result If you want exactly zero or one results, use the one() clause. This causes ZQL to return Row|undefined rather than Row\\[]. ```tsx const result = await z.query.issue.where('id', 42).one().run(); if (!result) { console.error('not found'); } ``` one() overrides any limit() clause that is also present. Relationships You can query related rows using relationships that are defined in your Zero schema. ```tsx // Get all issues and their related comments z.query.issue.related('comments'); ``` Relationships are returned as hierarchical data. In the above example, each row will have a comments field which is itself an array of the corresponding comments row. You can fetch multiple relationships in a single query: ```tsx z.query.issue.related('comments').related('reactions').related('assignees'); ``` Refining Relationships By default all matching relationship rows are returned, but this can be refined. The related method accepts an optional second function which is itself a query. ```tsx z.query.issue.related( 'comments', // It is common to use the 'q' shorthand variable for this parameter, // but it is a _comment_ query in particular here, exactly as if you // had done z.query.comment. q => q.orderBy('modified', 'desc').limit(100).start(lastSeenComment), ); ``` This relationship query can have all the same clauses that top-level queries can have. You can sometimes work around this by making the junction relationship explicit, depending on your schema and usage. Nested Relationships You can nest relationships arbitrarily: ```tsx // Get all issues, first 100 comments for each (ordered by modified,desc), // and for each comment all of its reactions. z.query.issue.related('comments', q => q.orderBy('modified', 'desc').limit(100).related('reactions'), ); ``` Where You can filter a query with where(): ```tsx z.query.issue.where('priority', '=', 'high'); ``` The first parameter is always a column name from the table being queried. Intellisense will offer available options (sourced from your Zero Schema). Comparison Operators Where supports the following comparison operators: | Operator | Allowed Operand Types | Description | | ---------------------------------------- | ----------------------------- | ------------------------------------------------------------------------ | | = , != | boolean, number, string | JS strict equal (===) semantics | | < , <=, >, >= | number | JS number compare semantics | | LIKE, NOT LIKE, ILIKE, NOT ILIKE | string | SQL-compatible LIKE / ILIKE | | IN , NOT IN | boolean, number, string | RHS must be array. Returns true if rhs contains lhs by JS strict equals. | | IS , IS NOT | boolean, number, string, null | Same as = but also works for null | TypeScript will restrict you from using operators with types that don’t make sense – you can’t use > with boolean for example. Equals is the Default Comparison Operator Because comparing by = is so common, you can leave it out and where defaults to =. ```tsx z.query.issue.where('priority', 'high'); ``` Comparing to null As in SQL, ZQL’s null is not equal to itself (null ≠ null). This is required to make join semantics work: if you’re joining employee.orgID on org.id you do not want an employee in no organization to match an org that hasn’t yet been assigned an ID. When you purposely want to compare to null ZQL supports IS and IS NOT operators that work just like in SQL: ```tsx // Find employees not in any org. z.query.employee.where('orgID', 'IS', null); ``` TypeScript will prevent you from comparing to null with other operators. Compound Filters The argument to where can also be a callback that returns a complex expression: ```tsx // Get all issues that have priority 'critical' or else have both // priority 'medium' and not more than 100 votes. z.query.issue.where(({cmp, and, or, not}) => or( cmp('priority', 'critical'), and(cmp('priority', 'medium'), not(cmp('numVotes', '>', 100))), ), ); ``` cmp is short for compare and works the same as where at the top-level except that it can’t be chained and it only accepts comparison operators (no relationship filters – see below). Note that chaining where() is also a one-level and: ```tsx // Find issues with priority 3 or higher, owned by aa z.query.issue.where('priority', '>=', 3).where('owner', 'aa'); ``` Comparing Literal Values The where clause always expects its first parameter to be a column name as a string. Same with the cmp helper: ```ts // \"foo\" is a column name, not a string: z.query.issue.where('foo', 'bar'); // \"foo\" is a column name, not a string: z.query.issue.where(({cmp}) => cmp('foo', 'bar')); ``` To compareto a literal value, use the cmpLit helper: ```ts z.query.issue.where(cmpLit('foobar', 'foo' + 'bar')); ``` By itself this is not very useful, but the first parameter can also be a JavaScript variable: ```ts z.query.issue.where(cmpLit(role, 'admin')); ``` Or, within a permission rule, you can compare to a field of the authData parameter: ```ts z.query.issue.where(cmpLit(authData.role, 'admin')); ``` Relationship Filters Your filter can also test properties of relationships. Currently the only supported test is existence: ```tsx // Find all orgs that have at least one employee z.query.organization.whereExists('employees'); ``` The argument to whereExists is a relationship, so just like other relationships it can be refined with a query: ```tsx // Find all orgs that have at least one cool employee z.query.organization.whereExists('employees', q => q.where('location', 'Hawaii'), ); ``` As with querying relationships, relationship filters can be arbitrarily nested: ```tsx // Get all issues that have comments that have reactions z.query.issue.whereExists('comments', q => q.whereExists('reactions')); ); ``` The exists helper is also provided which can be used with and, or, cmp, and not to build compound filters that check relationship existence: ```tsx // Find issues that have at least one comment or are high priority z.query.issue.where({cmp, or, exists} => or( cmp('priority', 'high'), exists('comments'), ), ); ``` Completeness Zero returns whatever data it has on the client immediately for a query, then falls back to the server for any missing data. Sometimes it's useful to know the difference between these two types of results. To do so, use the result from useQuery: ```tsx const [issues, issuesResult] = useQuery(z.query.issue); if (issuesResult.type === 'complete') { console.log('All data is present'); } else { console.log('Some data is missing'); } ``` The possible values of result.type are currently complete and unknown. The complete value is currently only returned when Zero has received the server result. But in the future, Zero will be able to return this result type when it knows that all possible data for this query is already available locally. Additionally, we plan to add a prefix result for when the data is known to be a prefix of the complete result. See Consistency for more information. Handling Missing Data It is inevitable that there will be cases where the requested data cannot be found. Because Zero returns local results immediately, and server results asynchronously, displaying \"not found\" / 404 UI can be slightly tricky. If you just use a simple existence check, you will often see the 404 UI flicker while the server result loads: ```tsx const [issue, issuesResult] = useQuery( z.query.issue.where('id', 'some-id').one(), ); // ❌ This causes flickering of the UI if (!issue) { return
404 Not Found
; } else { return
{issue}
; } ``` The way to do this correctly is to only display the \"not found\" UI when the result type is complete. This way the 404 page is slow but pages with data are still just as fast. ```tsx const [issue, issuesResult] = useQuery( z.query.issue.where('id', 'some-id').one(), ); if (!issue && issueResult.type === 'complete') { return
404 Not Found
; } if (!issue) { return null; } return
{issue}
; ``` Listening to Changes Currently, the way to listen for changes in query results is not ideal. You can add a listener to a materialized view which has the new data and result as parameters: ```ts z.query.issue.materialize().addListener((issues, issuesResult) => { // do stuff... }); ``` However, using this method will maintain its own materialized view in memory which is wasteful. It also doesn't allow for granular listening to events like add and remove of rows. A better way would be to create your own view without actually storing the data which will also allow you to listen to specific events. Again, the API is not good and will be improved in the future. ```ts // Inside the View class // Instead of storing the change, we invoke some callback push(change: Change): void { switch (change.type) { case 'add': this.#onAdd?.(change) break case 'remove': this.#onRemove?.(change) break case 'edit': this.#onEdit?.(change) break case 'child': this.#onChild?.(change) break default: throw new Error(`Unknown change type: ${change['type']}`) } } ``` (see View implementations in zero-vue or zero-solid) Preloading Almost all Zero apps will want to preload some data in order to maximize the feel of instantaneous UI transitions. In Zero, preloading is done via queries – the same queries you use in the UI and for auth. However, because preload queries are usually much larger than a screenful of UI, Zero provides a special preload() helper to avoid the overhead of materializing the result into JS objects: ```tsx // Preload the first 1k issues + their creator, assignee, labels, and // the view state for the active user. // // There's no need to render this data, so we don't use `useQuery()`: // this avoids the overhead of pulling all this data into JS objects. z.query.issue .related('creator') .related('assignee') .related('labels') .related('viewState', q => q.where('userID', z.userID).one()) .orderBy('created', 'desc') .limit(1000) .preload(); ``` Data Lifetime and Reuse Zero reuses data synced from prior queries to answer new queries when possible. This is what enables instant UI transitions. But what controls the lifetime of this client-side data? How can you know whether any particular query will return instant results? How can you know whether those results will be up to date or stale? The answer is that the data on the client is simply the union of rows returned from queries which are currently syncing. Once a row is no longer returned by any syncing query, it is removed from the client. Thus, there is never any stale data in Zero. So when you are thinking about whether a query is going to return results instantly, you should think about what other queries are syncing, not about what data is local. Data exists locally if and only if there is a query syncing that returns that data. A cache has a random set of rows with a random set of versions. There is no expectation that the cache any particular rows, or that the rows' have matching versions. Rows are simply updated as they are fetched. A replica by contrast is eagerly updated, whether or not any client has requested a row. A replica is always very close to up-to-date, and always self-consistent. Zero is a partial replica because it only replicates rows that are returned by syncing queries. Query Lifecycle Queries can be either active or cached. An active query is one that is currently being used by the application. Cached queries are not currently in use, but continue syncing in case they are needed again soon. Active queries are created one of four ways: The app calls q.materialize() to get a View. The app uses a framework binding like React's useQuery(q). The app calls preload() to sync larger queries without a view. The app calls q.run() to get a single result. Active queries sync until they are deactivated. The way this happens depends on how the query was created: For materialize() queries, the UI calls destroy() on the view. For useQuery(), the UI unmounts the component (which calls destroy() under the covers). For preload(), the UI calls cleanup() on the return value of preload(). For run(), queries are automatically deactivated immediately after the result is returned. Additionally when a Zero instance closes, all active queries are automatically deactivated. This also happens when the containing page or script is unloaded. TTLs Each query has a ttl that controls how long it stays cached. You do not need to account for such time when choosing a TTL – you only need to account for time your app is running without a query. TTL Defaults In most cases, the default TTL should work well: preload() queries default to ttl:'none', meaning they are not cached at all, and will stop syncing immediately when deactivated. But because preload() queries are typically registered at app startup and never shutdown, and because the ttl clock only ticks while Zero is running, this means that preload queries never get unregistered. Other queries have a default ttl of 5m (five minutes). Setting Different TTLs You can override the default TTL with the ttl parameter: ```ts // With useQuery(): const [user] = useQuery( z.query.user.where('id', userId), {ttl: '5m'}); // With preload(): z.query.user.where('id', userId).preload( {ttl: '5m'}); // With run(): const user = await z.query.user.where('id', userId).run( {ttl: '5m'}); // With materialize(): const view = z.query.user.where('id', userId).materialize( {ttl: '5m'}); ``` TTLs up to 10m (ten minutes) are currently supported. The following formats are allowed: | Format | Meaning | | --------- | --------------------------------------------------------- | | none | No caching. Query will immediately stop when deactivated. | | %ds | Number of seconds. | | %dm | Number of minutes. | Choosing a TTL If you choose a different TTL, you should consider how likely it is that the query will be reused, and how far into the future this reuse will occur. Here are some guidelines to help you choose a TTL for common query types: Preload Queries These queries load the most commonly needed data for your app. They are typically larger, run with the preload() method, and stay running the entire time your app is running. Because these queries run the entire time Zero runs, they do not need any TTL to keep them alive. And using a ttl for them is wasteful since when your app changes its preload query, it will end up running the old preload query and the new preload query, even though the app only cares about the new one. Recommendation: ttl: 'none' (the default for preload()). Navigational Queries These queries load data specific to a route. They are typically smaller and run with the useQuery() method. It is useful to cache them for a short time, so that they can be reactivated quickly if the user navigates back to the route. Recommendation: ttl: '5m' (the default for useQuery()). Ephemeral Queries These queries load data for a specific, short-lived user interaction and often come in large numbers (e.g., typeahead search). The chance of any specific ephemeral query being reused is low, so the benefit of caching them is also low. Recommendation: useQuery(..., {ttl: 'none'}))\\*. Why Zero TTLs are Short Zero queries are not free. Just as in any database, queries consume resources on both the client and server. Memory is used to keep metadata about the query, and disk storage is used to keep the query's current state. We do drop this state after we haven't heard from a client for awhile, but this is only a partial improvement. If the client returns, we have to re-run the query to get the latest data. This means that we do not actually want to keep queries active unless there is a good chance they will be needed again soon. The default Zero TTL values might initially seem too short, but they are designed to work well with the way Zero's TTL clock works and strike a good balance between keeping queries alive long enough to be useful, while not keeping them alive so long that they consume resources unnecessarily. If you think you need longer TTLs, please let us know. We are still iterating on these APIs and may have missed something. Alternately we may be able to help you achieve your goal a different way. Running Queries Once Usually subscribing to a query is what you want in a reactive UI, but every so often you'll need to run a query just once. To do this, use the run() method: ```tsx const results = await z.query.issue.where('foo', 'bar').run(); ``` By default, run() only returns results that are currently available on the client. That is, it returns the data that would be given for result.type === 'unknown'. If you want to wait for the server to return results, pass {type: 'complete'} to run: ```tsx const results = await z.query.issue.where('foo', 'bar').run({type: 'complete'});await z.query.issue.where('foo', 'bar'); ``` This is the same as saying run() or run({type: 'unknown'}). Consistency Zero always syncs a consistent partial replica of the backend database to the client. This avoids many common consistency issues that come up in classic web applications. But there are still some consistency issues to be aware of when using Zero. For example, imagine that you have a bug database w/ 10k issues. You preload the first 1k issues sorted by created. The user then does a query of issues assigned to themselves, sorted by created. Among the 1k issues that were preloaded imagine 100 are found that match the query. Since the data we preloaded is in the same order as this query, we are guaranteed that any local results found will be a prefix of the server results. The UX that result is nice: the user will see initial results to the query instantly. If more results are found server-side, those results are guaranteed to sort below the local results. There's no shuffling of results when the server response comes in. Now imagine that the user switches the sort to ‘sort by modified’. This new query will run locally, and will again find some local matches. But it is now unlikely that the local results found are a prefix of the server results. When the server result comes in, the user will probably see the results shuffle around. To avoid this annoying effect, what you should do in this example is also preload the first 1k issues sorted by modified desc. In general for any query shape you intend to do, you should preload the first n results for that query shape with no filters, in each sort you intend to use. In the future, we will be implementing a consistency model that fixes these issues automatically. We will prevent Zero from returning local data when that data is not known to be a prefix of the server result. Once the consistency model is implemented, preloading can be thought of as purely a performance thing, and not required to avoid unsightly flickering.", "headings": [] }, { - "id": "23-release-notes/0.1", + "id": "22-release-notes/0.1", "title": "Zero 0.1", "url": "/docs/release-notes/0.1", "content": "Breaking changes The name of some config keys in zero.config.json changed: upstreamUri → upstreamDBConnStr cvrDbUri → cvrDBConnStr changeDbUri → changeDBConnStr replicaDbFile → replicaDBFile Changed default port of zero-cache to 4848 . So your app startup should look like VITE\\_PUBLIC\\_SERVER=\"http://localhost:4848\". Features Print a warning to js console when Zero constructor server param is null or undefined zero-cache should now correctly bind to both ipv4 and ipv6 loopback addresses. This should fix the issue where using localhost to connect to zero-cache on some systems did not work. Check for presence of WebSocket early in startup of Zero. Print a clear error to catch people accidentally running Zero under SSR. Fix annoying error in js console in React strict mode from constructing and closing Replicache in quick succession. Source tree fixes These only apply if you were working in the Rocicorp monorepo. Fixed issue where zbugs didn’t rebuild when zero dependency changed - generally zbugs build normally again The zero binary has the right permissions bit so you don’t have to chmod u+x after build Remove overloaded name snapshot in use-query.tsx (thanks Scott 🙃)", "headings": [] }, { - "id": "24-release-notes/0.10", + "id": "23-release-notes/0.10", "title": "Zero 0.10", "url": "/docs/release-notes/0.10", "content": "Install ```bash npm install @rocicorp/zero@0.10 ``` Features None. Fixes Remove top-level await from zero-client. Various logging improvements. Don't throw error when WebSocket unavailable on server. Support building on Windows (running on Windows still doesn't work) Breaking Changes None.", "headings": [] }, { - "id": "25-release-notes/0.11", + "id": "24-release-notes/0.11", "title": "Zero 0.11", "url": "/docs/release-notes/0.11", "content": "Install ```bash npm install @rocicorp/zero@0.11 ``` Features Windows should work a lot better now. Thank you very much to aexylus and Sergio Leon for the testing and contributions here. Support nested property access in JWT auth tokens (docs). Make initial sync configurable (docs). Add query result type to SolidJS (docs) Docker image now contains native amd64 and arm64 binaries. Add storageKey constructor parameter to enable multiple Zero instances for same userID. Fixes Many, many fixes, including: Fix downstream replication of primitive values Fix replication of TRUNCATE messages Fix large storage use for idle pg instances Add runtime sanity checks for when a table is referenced but not synced Fix zero-cache-dev for multitenant Breaking Changes The addition of result types to SolidJS is a breaking API change on SolidJS only. See the changes to hello-zero-solid for upgrade example.", "headings": [] }, { - "id": "26-release-notes/0.12", + "id": "25-release-notes/0.12", "title": "Zero 0.12", "url": "/docs/release-notes/0.12", "content": "Install ```bash npm install @rocicorp/zero@0.12 ``` Features Schemas now support circular relationships (docs). Added one() and many() schema helpers to default relationship type (docs). Support for syncing tables without a primary key as long as there is a unique index. This enables Prisma's implicit many-to-many relations (docs). Zero has been confirmed to work with Aurora and Google Cloud SQL (docs) Client bundle size reduced from 55kb to 47kb (-15%). Fixes Windows: zero-cache was spawning emptying terminals and leaving listeners connected on exit. Incorrect warning in zero-cache about enums not being supported. Failure to handle the primary key of Postgres tables changing. Incorrect results when whereExists() is before where() in query (bug). Error: The inferred type of '...' cannot be named without a reference to .... Error: insufficient upstream connections. Several causes of flicker in React. Incorrect values for ResultType when unloading and loading a query quickly (bug). Error: Postgres is missing the column '...' but that column was part of a row. Pointless initial empty render in React when data is already available in memory. Error: Expected string at ... Got array during auth. where() incorrectly allows comparing to null with the = operator (bug). SolidJS: Only call setState once per transaction. Breaking Changes The schema definition syntax has changed to support circular relationships. See the changes to hello-zero and hello-zero-solid for upgrade examples.", "headings": [] }, { - "id": "27-release-notes/0.13", + "id": "26-release-notes/0.13", "title": "Zero 0.13", "url": "/docs/release-notes/0.13", "content": "Install ```bash npm install @rocicorp/zero@0.13 ``` Features Multinode deployment for horizontal scalability and zero-downtime deploys (docs). SST Deployment Guide (docs). Plain AWS Deployment Guide (docs). Various exports for external libraries Remove build hash from docker version for consistency with npm (discussion) Fixes Move heartbeat monitoring to separate path, not port Type instantiation is excessively deep and possibly infinite (bug). 20x improvement to whereExists performance (discussion) Breaking Changes Removing the hash from the version is a breaking change if you had scripts relying on that. Moving the heartbeat monitor to a path is a breaking change for deployments that were using that.", "headings": [] }, { - "id": "28-release-notes/0.14", + "id": "27-release-notes/0.14", "title": "Zero 0.14", "url": "/docs/release-notes/0.14", "content": "Install ```bash npm install @rocicorp/zero@0.14 ``` Features Use from() to map column or tables to a different name (docs). Sync from muliple Postgres schemas (docs) Fixes useQuery not working when server unset (bug) Error: \"single output already exists\" in hello-zero-solid (bug) Row helper doesn't work with query having one() (bug) Partitioned Postgres tables not replicating Breaking Changes None.", "headings": [] }, { - "id": "29-release-notes/0.15", + "id": "28-release-notes/0.15", "title": "Zero 0.15", "url": "/docs/release-notes/0.15", "content": "Install ```bash npm install @rocicorp/zero@0.15 ``` Upgrade Guide This release changes the way that permissions are sent to the server. Before, permissions were sent to the server by setting the ZERO\\_SCHEMA\\_JSON or ZERO\\_SCHEMA\\_FILE environment variables, which include the permissions. In 0.15, these variables go away and are replaced by a new command: npx zero-deploy-permissions. This command writes the permissions to a new table in the upstream database. This design allows live permission updates, without restarting the server. It also solves problems with max env var size that users were seeing. This release also flips the default permission from allow to deny for all rules. To upgrade your app: See the changes to hello-zero or hello-zero-solid for how to update your permissions. Remove the ZERO\\_SCHEMA\\_JSON and ZERO\\_SCHEMA\\_FILE environment variables from your setup. They aren't used anymore. Use npx zero-deploy-permissions to deploy permissions when necessary. You can hook this up to your CI to automate it. See the zbugs implementation as an example. Features Live-updating permissions (docs). Permissions now default to deny rather than allow (docs). Fixes Multiple whereExists in same query not working (PR) Allow overlapped mutators (bug) \"Immutable type too deep\" error (PR) Log server version at startup (PR) Eliminate quadratic CVR writes (PR) Handle numeric in the replication stream (PR) Make the auto-reset required error more prominent (PR) Add \"type\":\"module\" recommendation when schema load fails (PR) Throw error if multiple auth options set (PR) Handle NULL characters in JSON columns (PR) Breaking Changes Making permissions deny by default breaks existing apps. To fix add ANYONE\\_CAN or other appropriate permissions for your tables. See docs. The ZERO\\_SCHEMA\\_JSON and ZERO\\_SCHEMA\\_FILE environment variables are no longer used. Remove them from your setup and use npx zero-deploy-permissions instead.", "headings": [] }, { - "id": "30-release-notes/0.16", + "id": "29-release-notes/0.16", "title": "Zero 0.16", "url": "/docs/release-notes/0.16", "content": "Install ```bash npm install @rocicorp/zero@0.16 ``` Upgrading See the upgrade from hello-zero or hello-zero-solid for an example. Features Documented how to use lambdas to deploy permissions in SST, rather than needing CI/CD to have access to Postgres. (doc – search for \"permissionsDeployer\"). Added simple debugging logs for read and write permissions (doc). Fixes Improve performance of initial sync about 2x (PR 1, PR 2). IN should allow readonly array arguments (Report, PR). Export ANYONE\\_CAN\\_DO\\_ANYTHING (Report). Fix false-positive in schema change detection (Report, PR). Fix writes of numeric types (Report, PR) Fix bug where litestream was creating way too many files in s3 (PR) Fix memory leak in change-streamer noticeable under high write load (PR) Fix query already registered error (PR) Correctly handle optional booleans (PR) Ignore indexes with unpublished columns (PR) Breaking Changes None.", "headings": [] }, { - "id": "31-release-notes/0.17", + "id": "30-release-notes/0.17", "title": "Zero 0.17", "url": "/docs/release-notes/0.17", "content": "Install ```bash npm install @rocicorp/zero@0.17 ``` Upgrading See the upgrade from hello-zero or hello-zero-solid for an example. Features Queries now take an optional ttl argument. This argument backgrounds queries for some time after the app stops using them. Background queries continue syncing so they are instantly ready if the UI re-requests them. The data from background queries is also available to be used by new queries where possible (doc). Structural schema versioning. This is TypeScript, why are we versioning with numbers like cave-people?? We got rid of schemaVersion concept entirely and now determine schema compatibility completely automatically, TS-stylie (doc). Permissions now scoped to \"apps\". You can now have different Zero \"apps\" talking to the same upstream database. Each app gets completely separate configuration and permissions. This should also enable previewing zero-cache (each preview would be its own app). Apps replace the existing \"shard\" concept (doc). Initial replication is over 5x faster, up to about 50MB/second or 15k row/second in our tests. Added warnings for slow hydration in both client and server (doc). auto-reset is now enabled by default for databases that don't support event triggers (doc). Default cvr and change databases to upstream, so that you don't have to specify them in the common case where they are the same as upstream. This docs site now has search! Fixes Certain kinds of many:many joins were causing node already exists assertions Certain kinds of or queries were causing consistency issues Support replica identity full for PostgreSQL tables We now print a stack trace during close at debug level to enable debugging errors where Zero is accessed after close. We now print a warning when IndexedDB is missing rather than throwing. This makes it a little easier to use Zero in SSR setups. We now reset zero-cache implicitly in a few edge cases rather than halting replication. Fixed a deadlock in change-streamer. Breaking Changes query.run() now returns its result via promise. This is required for compatibility with upcoming custom mutators, but also will allow us to wait for server results in the future (though that (still 😢) doesn't exist yet).", "headings": [] }, { - "id": "32-release-notes/0.18", + "id": "31-release-notes/0.18", "title": "Zero 0.18", "url": "/docs/release-notes/0.18", "content": "Install ```bash npm install @rocicorp/zero@0.18 ``` Upgrading To try out custom mutators, see the changes to hello-zero-solid. Features Custom Mutators! Finally! Define arbitrary write operations in code (doc). Added inspector API for debugging sync, queries, and client storage (doc). Added analyze-query tool to debug query performance (doc). Added transform-query tool to debug permissions (doc). Added ast-to-zql script to prettify Zero's internal AST format (doc). Fixes Added backpressure to replication-manager to protect against Postgres moving faster than we can push to clients (PR). @rocicorp/zero/advanced has been deprecated. AdvancedQuery got folded into Query and ZeroAdvancedOptions got folded into ZeroOptions (PR). Support ALTER SCHEMA DDL changes (PR) Allow replication-manager to continue running while a new one re-replicates. (PR). Improve replication performance for some schema changes (PR). Make the log level of zero-deploy-permissions configurable (PR) Bind exists to the expression builder (PR) Fix single output already exists error (PR) Fix getBrowserGlobal('window')?.addEventListener not a function in Expo (thanks @andrewcoelho!) (PR). Fix Vue bindings ref counting bug. Bindings no longer need to pass RefCountMap (PR). Fix CVR ownership takeover race conditions (PR). Support REPLICA IDENTITY FULL in degraded-mode pg providers (PR). Handle corrupt sqlite db by re-replicating (PR). Don't send useless pokes to clients that are unchanged (PR). Add limit(1) to queries using a relation that is marked one() (PR). Export UseQueryOptions Breaking Changes None.", "headings": [] }, { - "id": "33-release-notes/0.19", + "id": "32-release-notes/0.19", "title": "Zero 0.19", "url": "/docs/release-notes/0.19", "content": "Install ```bash npm install @rocicorp/zero@0.19 ``` Upgrading If you use custom mutators, please see hello-zero-solid for how to update your push endpoint. If you use SolidJS, please switch to createQuery. If you are awaiting z.mutate.foo.bar(), you should switch to await z.mutate.foo.bar().client to be consistent with .server. If you were using a 0.19 canary, the .server property returns error by rejection again (like 0.18 did). Sorry about the thrash here. Features Add a type param to query.run() so it can wait for server results (doc, bug) await z.mutate.foo.bar() is now await z.mutate.foo.bar().client for consistency with .server, old API still works but deprecated (doc) Improve speed of litestream restore by about 7x Increase replication speed when using JSON by about 25% Add options to analyze-query to apply permissions and auth data (doc). Add option to --lazy-startup to zero-cache to delay connecting to upstram until first connection (doc) Add /statz endpoint for getting some health statistics from a running Zero instance (doc) Fixes Support passing Request to PushProccesor.process() (PR) Fix layering in PushProcessor to better support custom db implementations (thanks Erik Munson!) (PR) Fix socket disconnects in GCP (PR) Quote Postgres enum types to preserve casing (report) z2s: Return undefined for empty result set when using query.one() z2s: Allow accessing tables in non-public schemas z2s: Allow tx.foo.update({bar: undefined}) where bar is optional to match client behavior Fix broken replication when updating a key that is part of a unique (but non-PK) index solid: Rename useQuery to createQuery to fit Solid naming conventions (old name deprecated) Resync when publications are missing (PR) Fix missing NOT LIKE in query.where() (PR) Fix timezone shift when writing to timestamp/timestamptz and server is non-UTC timezone (thanks Tom Jenkinson!) (PR) Bound time spent in incremental updates to 1/2 hydration time Fix ttl being off by 1000 in some cases 😬 (PR) z2s: Relationships nested in a junction relationship were not working correctly (PR) Custom mutators: Due to multitab, client can receive multiple responses for same mutation Fix deadlock that could happen when pushing on a closed websocket (PR) Fix incorrect shutdown under heavy CPU load (thanks Erik Munson!) (PR) Fix case where deletes were getting reverted (thanks for reproduction Marc MacLeod!) (PR) z2s: Incorrect handling of self-join, and not exists not(exists()) is not supported on the client re-auth on 401s returned by push endpoint Added push.queryParams constructor parameter to allow passing query params to the push endpoint (doc) Breaking Changes The structure of setting up a PushProcesor has changed slightly. See push endpoint setup or upgrade guide. Not technically a breaking change from 0.18, but if you were using 0.19 canaries, the .server property returns error by rejection again (like 0.18 did) (doc).", "headings": [] }, { - "id": "34-release-notes/0.2", + "id": "33-release-notes/0.2", "title": "Zero 0.2", "url": "/docs/release-notes/0.2", "content": "Breaking changes None Features “Skip mode”: zero-cache now skips columns with unsupported datatypes. A warning is printed out when this happens: This makes it easy to use zero-cache with existing schemas that have columns Zero can’t handle. You can pair this with Postgres triggers to easily translate unsupported types into something Zero can sync. Zero now supports compound primary keys. You no longer need to include an extraneous id column on the junction tables. Fixes Change the way Zero detects unsupported environments to work in One (and any other supported env). Before, Zero was looking for WebSocket and indexedDB early on, but indexedDB won’t be present on RN as SQLite will be used. Instead look for indexedDB only at use. Require Node v20 explicitly in package.json to prevent accidentally compiling better-sqlite3 with different Node version than running with. Ensure error messages early in startup get printed out before shutting down in multiprocess mode. Docs Factored out the sample app from the docs into its own Github repo so you can just download it and poke around if you prefer that. Source tree fixes Run zero-cache from source. You no longer have to build zero before running zbugs, it picks up the changes automatically. zbugs Numerous polish/styling fixes Change default to ‘open’ bugs Add ‘assignee’ field", "headings": [] }, { - "id": "35-release-notes/0.20", + "id": "34-release-notes/0.20", "title": "Zero 0.20", "url": "/docs/release-notes/0.20", "content": "Install ```bash npm install @rocicorp/zero@0.20 ``` Upgrading There are two config changes for multinode deployments: Required: Remove view-syncer's ZERO\\_CHANGE\\_STREAMER\\_URI env var and replace it with ZERO\\_CHANGE\\_STREAMER\\_MODE: \"discover\". Optional: Change the ZERO\\_LITESTREAM\\_BACKUP\\_URL env var from being passed to both replication-manager and view-syncer nodes to being passed only to replication-manager. This config is no longer needed by view-syncer (and is ignored by it). See hello-zero for an upgrade example using SST. Additionally, the ZERO\\_TENANTS\\_JSON, feature was removed. We do not think anyone was using it, but if you were please reach out to us for options. Features Supabase is now fully supported. After upgrading, you should see that schema changes are incremental and don't reset the replica (docs). Improve performance of single-key reads on client. Scale depends on size of data but 100x improvement is common (PR). Implement short-circuiting for or queries. Because of permissions, one or more branches of or would often be empty, turning the entire or into a full-table scan. 100x improvement on chinook test dataset (PR). Remove DNF conversion. This was intended to make consistency easier in the future, but was resulting in some queries exploding in size (PR, bug). Autodiscovery for replication-manager. view-syncer nodes now find replication-manager using the Postgres changedb database, and no longer need an internal load balancer. See the new ZERO\\_CHANGE\\_STREAMER\\_MODE: \"discover\" config in the deployment docs (PR). Make ZERO\\_LITESTREAM\\_BACKUP\\_URL specific to replication-manager. view-syncer nodes now ignore this config and learn it from replication-manager instead. This makes restarting replication less error-prone (PR, discussion). OpenTelemetry support (docs). Fixes Allow dots in column names (only works with custom mutators) (PR). Fix websocket liveness check to avoid false negatives when busy (PR). Fix unhandled exception in zero-cache when processing query eviction (PR). Keep microsecond precision across timezones (PR). Fix unhandled exception in zero-cache during handleClose (PR). Fix NOT IN in z2s (PR). Mutators: assert provided columns actually exist (PR). Fix ordering of columns in replicated index (PR). Use a shorter keepalive for replication stream for compat with Neon (PR). Allow destructuring where in query.related (PR). Add flow control for large change DB transactions (PR). Fix z2s handling of pg types with params (char, varchar, numeric, etc) (PR). Support from and --schema-path in analyze-query (PR). Breaking Changes The autodiscovery feature for replication-manager is a breaking change for multinode deployments. See the upgrade instructions for details. The ZERO\\_TENANTS\\_JSON config was removed 🫗. The ZERO\\_INITIAL\\_SYNC\\_ROW\\_BATCH\\_SIZE config was removed. It is no longer needed because initial sync now adapts to available memory automatically.", "headings": [] }, { - "id": "36-release-notes/0.21", + "id": "35-release-notes/0.21", "title": "Zero 0.21", "url": "/docs/release-notes/0.21", "content": "Install ```bash npm install @rocicorp/zero@0.21 ``` Upgrading There is one breaking change in this release, but we think it is unlikely to affect anyone since the results were wrong already – the change just makes the error explicit. See hello-zero for an example of using arrays and the new ZeroProvider features. Features New \"ztunes\" sample using TanStack, Drizzle, Better Auth, and Fly.io (docs). Add initial support for Postgres arrays (docs, bug). Improved React lifecycle management with ZeroProvider (docs, PR). Expose Zero instances automatically at \\_\\_zero (docs, PR). Add --output-{synced|vended}-rows to analyze-query (PR). Technically a bug fix, but this was so annoying I'm calling it a feature: zero-sqlite3 now correctly supports the up/down arrow keys (commit). Another super annoying fix: logs from zero-cache are now level-colored (PR). Fixes Lazy-load otel. This was causing problems with pnpm (PR). Initial replication is now memory-bounded (PR). Change the way otel starts up in zero-cache-dev to not rely on npx (PR). Use existing --log-slow-hydrate-threshold as the threshold for --query-hydration-stats rather than hardcoded 200ms. Fix race condition starting up in multinode deployments (PR). Avoid site-local IPv6 addresses in auto-discovery (PR). Many z2s fixes found by fuzzing (PRs: 4415, 4416, 4417, 4421, 4422, 4423). Don't load prettier in analyze-query. This was causing problems when prettier config was cjs. (PR). Don't hydrate system relationships in analyze-query. This was causing incorrect results. (PR). Fix memory leaks from not cleaning up pusher and mutagen (PR). Fix handling of invalid websocket requests that were crashing server. (PR). Remove red error text when .env missing (PR). Allow zero-cache to startup without schema file, but print a warning (PR). Log a warning when auth token exceeds max allowed header size (PR). Breaking Changes Using order by and limit in many-to-many relationships now throws an error. It didn't work before but did the wrong thing silently. Now it throws a runtime error. See docs, bug.", "headings": [] }, + { + "id": "36-release-notes/0.22", + "title": "Zero 0.22", + "url": "/docs/release-notes/0.22", + "content": "Install ```bash npm install @rocicorp/zero@0.22 ``` Upgrading This release simplifies the concept of TTLs in Zero. See hello-zero, hello-zero-solid, or ztunes for example upgrades. This release also adds anonymous telemetry collection. You can opt-out with the DO\\_NOT\\_TRACK=1 environment variable. Though we hope you will not, as it helps us improve Zero. How TTLs Used to Work Previously, the TTL of a query simply measured normal \"wall clock time\" from when a query inactivated, including any time the app wasn't running at all. With experience, we realized this was a misfeature because it encouraged the use of very long or infinite TTLs, especially for preload queries. Developers always want preload queries registered, but since they do not know how long the app will be offline, they had no real choice but to use the TTL forever. These infinite TTLs would remain registered even after the app's code changed such that it no longer wanted them, slowing connections and incremental updates to process queries that the app was not even using. Worse, the prevalence of infinite TTLs in turns meant we needed some way to limit the size of the client cache. We introduced the \"client row limit\" for this. But developers would frequently accidentally blow through this limit, causing cache thrash. How TTLs Work Now Now, query TTLs measure \"TTL time\" which only elapses while Zero is running. This means that preload queries usually don't need a TTL at all, since they run the entire time Zero is active. This in turn means we can clamp TTLs to low values, which means queries evict naturally, which means we no longer need the client row limit either. Using New TTLs You don't need to do anything specific to upgrade. Zero will clamp your TTLs at 10m and print a warning. But for best results, please review the new TTL documentation. In particular, see how to set your TTLs (TL;DR: You can often just remove them – the defaults usually just work). Features Rework and simplify query TTLs (docs, upgrading). SolidJS bindings are now fine-grained, improving performance (PR). Restore ZERO\\_CHANGE\\_STREAMER\\_URI option (doc, PR). Add useZeroOnline to React and SolidJS bindings (doc). Add ttl to run() (PR). Allow client to specify push.url in the Zero constructor (doc). Add anonymous telemetry collection to zero-cache (doc). Fixes Handle public in aliases, like .from('public.table') (PR). Sorting by columns with null values was incorrect in some cases (PR). Fix fencepost issue editing queries with limits (PR). Fix copy runner to more reliably reuse connections (PR). Queries early in startup could not contain non-latin chars (PR). SolidJS: Export createUseZero (PR). Support parallel rollouts of replication-manager and view-syncer (PR). Fix upgrade path for already replicated array types (PR). Breaking Changes Require Node v22+ (see discussion)", + "headings": [] + }, { "id": "37-release-notes/0.3", "title": "Zero 0.3", @@ -311,7 +311,7 @@ "id": "44-release-notes/index", "title": "Release Notes", "url": "/docs/release-notes/index", - "content": "Zero 0.21: PG arrays, TanStack starter, and more Zero 0.20: Full Supabase support, performance improvements Zero 0.19: Many, many bugfixes and cleanups Zero 0.18: Custom Mutators Zero 0.17: Background Queries Zero 0.16: Lambda-Based Permission Deployment Zero 0.15: Live Permission Updates Zero 0.14: Name Mapping and Multischema Zero 0.13: Multinode and SST Zero 0.12: Circular Relationships Zero 0.11: Windows Zero 0.10: Remove Top-Level Await Zero 0.9: JWK Support Zero 0.8: Schema Autobuild, Result Types, and Enums Zero 0.7: Read Perms and Docker Zero 0.6: Relationship Filters Zero 0.5: JSON Columns Zero 0.4: Compound Filters Zero 0.3: Schema Migrations and Write Perms Zero 0.2: Skip Mode and Computed PKs Zero 0.1: First Release", + "content": "Zero 0.22: Simplified TTLs Zero 0.21: PG arrays, TanStack starter, and more Zero 0.20: Full Supabase support, performance improvements Zero 0.19: Many, many bugfixes and cleanups Zero 0.18: Custom Mutators Zero 0.17: Background Queries Zero 0.16: Lambda-Based Permission Deployment Zero 0.15: Live Permission Updates Zero 0.14: Name Mapping and Multischema Zero 0.13: Multinode and SST Zero 0.12: Circular Relationships Zero 0.11: Windows Zero 0.10: Remove Top-Level Await Zero 0.9: JWK Support Zero 0.8: Schema Autobuild, Result Types, and Enums Zero 0.7: Read Perms and Docker Zero 0.6: Relationship Filters Zero 0.5: JSON Columns Zero 0.4: Compound Filters Zero 0.3: Schema Migrations and Write Perms Zero 0.2: Skip Mode and Computed PKs Zero 0.1: First Release", "headings": [] }, { @@ -339,39 +339,53 @@ "id": "48-solidjs", "title": "SolidJS", "url": "/docs/solidjs", - "content": "Zero has built-in support for Solid. Here’s what basic usage looks like: ```tsx import {createQuery} from '@rocicorp/zero/solid'; const issues = createQuery(() => { let issueQuery = z.query.issue .related('creator') .related('labels') .limit(100); const userID = selectedUserID(); if (userID) { issueQuery = issueQuery.where('creatorID', '=', userID); } return issueQuery; }); ``` Complete quickstart here: https://github.com/rocicorp/hello-zero-solid", + "content": "Zero has built-in support for Solid. Here’s what basic usage looks like: ```tsx import {useQuery} from '@rocicorp/zero/solid'; const issues = useQuery(() => { let issueQuery = z.query.issue .related('creator') .related('labels') .limit(100); const userID = selectedUserID(); if (userID) { issueQuery = issueQuery.where('creatorID', '=', userID); } return issueQuery; }); ``` Complete quickstart here: https://github.com/rocicorp/hello-zero-solid", "headings": [] }, { - "id": "49-sync", + "id": "49-status", + "title": "Project Status", + "url": "/docs/status", + "content": "You will encounter bugs. You may encounter pathologically slow queries. You are likely to encounter situations where ZQL is not powerful enough to express the query you want. That said, we are building Zero live. It has been running our own bug tracker for months, and is used in production by a small set of customer applications that are an extremely good fit. This page describes the current state of Zero at a high level. To understand whether Zero makes sense for you, please also see When to Use Zero. Platforms and Frameworks React and SolidJS are fully-supported Svelte and Vue have community support React Native is not supported yet, but is planned Databases Most Postgres providers are supported Drizzle and Prisma have high-quality community-supported integrations Query Language Filters, sorts, limits, relationships, and exists are supported. Queries can have ttl to keep data synced across sesssions. Zero will stay within a (configurable) client-side row limit using LRU. Aggregates (count, min, max, group-by) are not yet supported. Full-text search is not yet supported (you can sometimes simulate with ILIKE, though it scales linearly). Infinite/virtual scroll is possible, but not easy or optimal. Performance We do not have a query analyzer, and do not do any join reordering. It's sometimes, but not always possible to manually reorder. Because of this, some queries (especially exists) can be pathological. We are actively working on this. Every query is a hybrid query. We haven't yet implemented \"client-only\" queries, meaning patterns like typeahead search can easily crush the server if the query is expensive. We have basic CLI tools to understand query performance, but we lack a full-featured inspector to understand at a glance what queries are open or slow. We share queries within a \"client group\" (e.g. all tabs in a browser), but not across groups. This means that if you have many users doing the same query, they will duplicate all that work server-side. Miscellaneous We do not have a way to limit queries to only expected/allowed forms (in progress). We do not have a good way to support previews (in progress). Running Zero requires deploying it yourself to AWS or similar. Running in a multinode, zero-downtime way is possible (we do it for zbugs), but significant effort. Running single node is easier, but updating the server takes it down for a minute or so (we are working on a SaaS solution).", + "headings": [] + }, + { + "id": "50-sync", "title": "What is Sync?", "url": "/docs/sync", - "content": "We say that Zero is a sync engine. But what even is that? And why does it matter? Problem Let's say you have some data that you want to read and write from multiple devices. The most common way to do this today is to put that data into a central database and expose access to it via APIs. This works, but has downsides: Slow access. Every read and write has to go to the server, addding hundreds of milliseconds to each interaction. Stale data. API responses are immediately stale. The client has no way to know when to refresh them. Users may make decisions based on old information, and the views on different devices diverge over time. Online-only. If the server or the user's network connection is down, the app stops working completely. Solution Sync engines can solve these problems by keeping a local copy of the data on each device. The app reads and writes only to the local copy, not to the network. The sync engine pushes changes back and forth between the local copy and the server in the background, when connectivity allows. Zero uses server reconciliation – an elegant and flexible technique pionneered by the video game industry. This architecture can enable: Instant UI. Reads and writes are to local storage, effectively instant. Realtime updates. By running the sync engine continuously, users can see updates from other devices and users in realtime. The data is always fresh. Offline support. Because data is stored locally, it is possible to support at least limited offline access. Read-only access is definitely possible, and with careful attention to conflict resolution, offline writes can also be supported in some applications. Sync engines also simplify the development of complex apps. Big parts of modern app development are just data plumbing: fetching data, updating data, caching data, invalidating caches, keeping different copies of data consistent, and so-on. A sync engine abstracts all this away and lets you focus on what your app actually does. History of Sync Sync Engines have been around a long time. The first mass-market sync engine was probably Lotus Notes, released way back in 1989! Since then, there has been a steady trickle of important software built on sync engines: Microsoft Exchange Dropbox Google Docs Linear Superhuman Figma But sync engines are very hard to build. Typically, a new custom sync engine was built for each application at great expense. Knowledge about the specific application and its data model has to be built into each sync engine to correctly handle conflicts and partial sync. There have been some attempts at general-purpose sync engines: Firebase Realtime Database (2012) - a cloud-hosted database and that syncs. PouchDB (2013) - a sync engine attachment for CouchDB. Realm (2016) - a mobile database with sync capabilities. Replicache (2020) - The predecessor to Zero, a JavaScript library for building collaborative applications with real-time sync. But all have suffered from one or more significant problems that have prevented widespread adoption: No support for fine-grained data authorization Limited support for partial sync – users have to sync all data, even if they only need a small subset Required adoption of non-standard backend databases Limited ability to put business logic on read or write paths We are building Zero to address these limitations, and bring the benefits of sync to many more applications.", + "content": "We say that Zero is a sync engine. But what even is that? And why does it matter? Problem Let's say you have some data that you want to read and write from multiple devices. The most common way to do this today is to put that data into a central database and expose access to it via APIs. This works, but has downsides: Slow access. Every read and write has to go to the server, adding hundreds of milliseconds to each interaction. Stale data. API responses are immediately stale. The client has no way to know when to refresh them. Users may make decisions based on old information, and the views on different devices diverge over time. Online-only. If the server or the user's network connection is down, the app stops working completely. Solution Sync engines can solve these problems by keeping a local copy of the data on each device. The app reads and writes only to the local copy, not to the network. The sync engine pushes changes back and forth between the local copy and the server in the background, when connectivity allows. Zero uses server reconciliation – an elegant and flexible technique pionneered by the video game industry. This architecture can enable: Instant UI. Reads and writes are to local storage, effectively instant. Realtime updates. By running the sync engine continuously, users can see updates from other devices and users in realtime. The data is always fresh. Offline support. Because data is stored locally, it is possible to support at least limited offline access. For example, Zero supports read-only access while offline, and other sync engines support some limited offline writes. Sync engines also simplify the development of complex apps. Big parts of modern app development are just data plumbing: fetching data, updating data, caching data, invalidating caches, keeping different copies of data consistent, and so-on. A sync engine abstracts all this away and lets you focus on what your app actually does. History of Sync Sync Engines have been around a long time. The first mass-market sync engine was probably Lotus Notes, released way back in 1989! Since then, there has been a steady trickle of important software built on sync engines: Microsoft Exchange (1996) Google Docs (2006) Dropbox (2007) Figma (2016) Superhuman (2017) Linear (2019) But sync engines are very hard to build. Typically, a new custom sync engine is built for each application at great expense. Knowledge about the specific application and its data model must be built into each sync engine to correctly handle conflicts and partial sync. There have also been some attempts at general-purpose sync engines: Firebase Realtime Database (2012) - a cloud-hosted database and that syncs. PouchDB (2013) - a sync engine attachment for CouchDB. Realm (2016) - a mobile database with sync capabilities. Replicache (2020) - The predecessor to Zero, a JavaScript library for building collaborative applications with real-time sync. But all have suffered from one or more significant problems that have prevented widespread adoption: No support for fine-grained authorization Limited support for partial sync – users have to sync all data, even if they only need a small subset Required adoption of non-standard backend databases or data models Limited ability to put custom business logic on read or write paths We are building Zero to address these limitations, and bring the benefits of sync to many more applications.", + "headings": [] + }, + { + "id": "51-when-to-use", + "title": "When To Use Zero", + "url": "/docs/when-to-use", + "content": "We are trying to make Zero a great choice for a wide variety of applications. But every tool has tradeoffs, and Zero especially so while in alpha. This page will help you understand if Zero is a good fit for you today. Zero Might be a Good Fit You want to sync only a small subset of data to client Zero's query-driven sync is a powerful solution for partial sync. You can sync any data you can express as a set of Zero queries. By using partial sync, Zero apps can commonly load in < 1s, yet still maintain the interaction perf of sync. You need fine-grained read or write permissions Zero's custom mutators allow you to run arbitrary authorization, validation, or business logic on the write path. You can enforce that a write depends on what group a user is in, what has been shared with them, their role, etc. Read permissions are very expressive, allowing similar control over what data is synced to the client. You are building a traditional client-server web app Zero was designed from the ground up to be as close to a classic web app as a sync engine can be. If you have a traditional web app, you can try Zero side-by-side with your existing REST or GraphQL API, and incrementally migrate over time. You use PostgreSQL Some tools in our space require you to use a non-standard backend database or data model. Zero works with PostgreSQL, and uses your existing schema. Your app is broadly \"like Linear\" Zero is currently best suited for productivity apps with lots of interactivity. Interaction performance is very important to you Zero was built by people obsessed with interaction performance. If you share this goal you'll be going with the grain of Zero's design choices. Zero Might Not be a Good Fit You need the privacy or data ownership benefits of local-first Zero is not local-first. It's a client-server system with an authoritative server. You need to support offline writes or long periods offline Zero doesn't support offline writes yet. You are building a native mobile app Zero is written in TypeScript and only supports TypeScript clients. The total backend dataset is > ~100GB Zero stores a replica of your database (at least the subset you want to be syncable to clients) in a SQLite database owned by zero-cache. Zero's query engine is built assuming very fast local access to this replica (i.e., attached NVMe). But other setups are technically supported and work for smaller data. The ultimate size limit on the database that Zero can work with is the size limit of this SQLite database. So up to 45TB on EC2 at time of writing. However, most of our experience with Zero so far is with much smaller workloads. We currently recommend Zero for use with datasets smaller than 100GB, but are working to improve this in the beta timeframe. Zero Might Not be a Good Fit Yet While Zero is in alpha, there are additional reasons not to choose it: You don't want to run server-side infra Zero is a Docker container that you currently have to self-host. We're working on a SaaS solution but it's not ready yet. You can't tolerate occasional downtime The easiest way to run Zero today is single-node, which requires downtime for updates. Also there are occasional regressions. You need immediate support for React Native Zero doesn't support React Native yet, but it is planned. You need support for SSR Zero doesn't support SSR yet, but it is planned. Alternatives If Zero isn't right for you, here are some good alternatives to consider: Automerge: Local-first, CRDT-based solution. Pioneering branch-based offline support. Convex: Not a sync engine (reads and writes are server-first), but a very nice reactive database that is in GA. Ditto: CRDT-based, with high quality offline support. Electric: Postgres-based sync engine with a SaaS cloud. LiveStore: Interesting event sourced design from one of the founders of Prisma. Jazz: Batteries-included local-first. PowerSync: Sync engine that works with Postgres, MySQL, and MongoDB.", "headings": [] }, { - "id": "50-writing-data", + "id": "52-writing-data", "title": "Writing Data with Mutators", "url": "/docs/writing-data", "content": "Zero generates basic CRUD mutators for every table you sync. Mutators are available at zero.mutate.\\: ```tsx const z = new Zero(...); z.mutate.user.insert({ id: nanoid(), username: 'abby', language: 'en-us', }); ``` Insert Create new records with insert: ```tsx z.mutate.user.insert({ id: nanoid(), username: 'sam', language: 'js', }); ``` Optional fields can be set to null to explicitly set the new field to null. They can also be set to undefined to take the default value (which is often null but can also be some generated value server-side). ```tsx // schema.ts import {createTableSchema} from '@rocicorp/zero'; const userSchema = createTableSchema({ tableName: 'user', columns: { id: {type: 'string'}, name: {type: 'string'}, language: {type: 'string', optional: true}, }, primaryKey: ['id'], relationships: {}, }); // app.tsx // Sets language to `null` specifically z.mutate.user.insert({ id: nanoid(), username: 'sam', language: null, }); // Sets language to the default server-side value. Could be null, or some // generated or constant default value too. z.mutate.user.insert({ id: nanoid(), username: 'sam', }); // Same as above z.mutate.user.insert({ id: nanoid(), username: 'sam', language: undefined, }); ``` Upsert Create new records or update existing ones with upsert: ```tsx z.mutate.user.upsert({ id: samID, username: 'sam', language: 'ts', }); ``` upsert supports the same null / undefined semantics for optional fields that insert does (see above). Update Update an existing record. Does nothing if the specified record (by PK) does not exist. You can pass a partial, leaving fields out that you don’t want to change. For example here we leave the username the same: ```tsx // Leaves username field to previous value. z.mutate.user.update({ id: samID, language: 'golang', }); // Same as above z.mutate.user.update({ id: samID, username: undefined, language: 'haskell', }); // Reset language field to `null` z.mutate.user.update({ id: samID, language: null, }); ``` Delete Delete an existing record. Does nothing if specified record does not exist. ```tsx z.mutate.user.delete({ id: samID, }); ``` You can read more about it in Authentication. Batch Mutate You can do multiple CRUD mutates in a single batch. If any of the mutations fails, all will. They also all appear together atomically in a single transaction to other clients. ```tsx z.mutateBatch(async tx => { const samID = nanoid(); tx.user.insert({ id: samID, username: 'sam', }); const langID = nanoid(); tx.language.insert({ id: langID, userID: samID, name: 'js', }); }); ```", "headings": [] }, { - "id": "51-zero-cache-config", + "id": "53-zero-cache-config", "title": "zero-cache Config", "url": "/docs/zero-cache-config", - "content": "zero-cache is configured either via CLI flag or environment variable. There is no separate zero.config file. You can also see all available flags by running zero-cache --help. Required Flags Auth One of Auth JWK, Auth JWK URL, or Auth Secret must be specified. See Authentication for more details. Replica File File path to the SQLite replica that zero-cache maintains. This can be lost, but if it is, zero-cache will have to re-replicate next time it starts up. flag: --replica-file env: ZERO\\_REPLICA\\_FILE required: true Upstream DB The \"upstream\" authoritative postgres database. In the future we will support other types of upstream besides PG. flag: --upstream-db env: ZERO\\_UPSTREAM\\_DB required: true Optional Flags Admin Password A password used to administer zero-cache server, for example to access the /statz endpoint. flag: --admin-password env: ZERO\\_ADMIN\\_PASSWORD required: false App ID Unique identifier for the app. Multiple zero-cache apps can run on a single upstream database, each of which is isolated from the others, with its own permissions, sharding (future feature), and change/cvr databases. The metadata of an app is stored in an upstream schema with the same name, e.g. zero, and the metadata for each app shard, e.g. client and mutation ids, is stored in the {app-id}\\_{#} schema. (Currently there is only a single \"0\" shard, but this will change with sharding). The CVR and Change data are managed in schemas named {app-id}\\_{shard-num}/cvr and {app-id}\\_{shard-num}/cdc, respectively, allowing multiple apps and shards to share the same database instance (e.g. a Postgres \"cluster\") for CVR and Change management. Due to constraints on replication slot names, an App ID may only consist of lower-case letters, numbers, and the underscore character. Note that this option is used by both zero-cache and zero-deploy-permissions. flag: --app-id env: ZERO\\_APP\\_ID default: zero App Publications Postgres PUBLICATIONs that define the tables and columns to replicate. Publication names may not begin with an underscore, as zero reserves that prefix for internal use. If unspecified, zero-cache will create and use an internal publication that publishes all tables in the public schema, i.e.: ``` CREATE PUBLICATION _{app-id}_public_0 FOR TABLES IN SCHEMA public; ``` Note that once an app has begun syncing data, this list of publications cannot be changed, and zero-cache will refuse to start if a specified value differs from what was originally synced. To use a different set of publications, a new app should be created. flag: --app-publications env: ZERO\\_APP\\_PUBLICATIONS default: \\[] Auth JWK A public key in JWK format used to verify JWTs. Only one of jwk, jwksUrl and secret may be set. flag: --auth-jwk env: ZERO\\_AUTH\\_JWK required: false Auth JWK URL A URL that returns a JWK set used to verify JWTs. Only one of jwk, jwksUrl and secret may be set. flag: --auth-jwks-url env: ZERO\\_AUTH\\_JWKS\\_URL required: false Auto Reset Automatically wipe and resync the replica when replication is halted. This situation can occur for configurations in which the upstream database provider prohibits event trigger creation, preventing the zero-cache from being able to correctly replicate schema changes. For such configurations, an upstream schema change will instead result in halting replication with an error indicating that the replica needs to be reset. When auto-reset is enabled, zero-cache will respond to such situations by shutting down, and when restarted, resetting the replica and all synced clients. This is a heavy-weight operation and can result in user-visible slowness or downtime if compute resources are scarce. flag: --auto-reset env: ZERO\\_AUTO\\_RESET default: true Auth Secret A symmetric key used to verify JWTs. Only one of jwk, jwksUrl and secret may be set. flag: --auth-secret env: ZERO\\_AUTH\\_SECRET required: false Change DB The Postgres database used to store recent replication log entries, in order to sync multiple view-syncers without requiring multiple replication slots on the upstream database. If unspecified, the upstream-db will be used. flag: --change-db env: ZERO\\_CHANGE\\_DB required: false Change Max Connections The maximum number of connections to open to the change database. This is used by the change-streamer for catching up zero-cache replication subscriptions. flag: --change-max-conns env: ZERO\\_CHANGE\\_MAX\\_CONNS default: 5 Change Streamer Mode The mode for running or connecting to the change-streamer: dedicated: runs the change-streamer and shuts down when another change-streamer takes over the replication slot. This is appropriate in a single-node configuration, or for the replication-manager in a multi-node configuration. discover: connects to the change-streamer as internally advertised in the change-db. This is appropriate for the view-syncers in a multi-node flag: --change-streamer-mode env: ZERO\\_CHANGE\\_STREAMER\\_MODE default: dedicated Change Streamer Port The port on which the change-streamer runs. This is an internal protocol between the replication-manager and zero-cache, which runs in the same process in local development. If unspecified, defaults to --port + 1. flag: --change-streamer-port env: ZERO\\_CHANGE\\_STREAMER\\_PORT required: false CVR DB The Postgres database used to store CVRs. CVRs (client view records) keep track of the data synced to clients in order to determine the diff to send on reconnect. If unspecified, the upstream-db will be used. flag: --cvr-db env: ZERO\\_CVR\\_DB required: false CVR Max Connections The maximum number of connections to open to the CVR database. This is divided evenly amongst sync workers. Note that this number must allow for at least one connection per sync worker, or zero-cache will fail to start. See num-sync-workers. flag: --cvr-max-conns env: ZERO\\_CVR\\_MAX\\_CONNS default: 30 Initial Sync Table Copy Workers The number of parallel workers used to copy tables during initial sync. Each worker copies a single table at a time, fetching rows in batches of initial-sync-row-batch-size. flag: --initial-sync-table-copy-workers env: ZERO\\_INITIAL\\_SYNC\\_TABLE\\_COPY\\_WORKERS default: 5 Lazy Startup Delay starting the majority of zero-cache until first request. This is mainly intended to avoid connecting to Postgres replication stream until the first request is received, which can be useful i.e., for preview instances. Currently only supported in single-node mode. flag: --lazy-startup env: ZERO\\_LAZY\\_STARTUP default: false Litestream Executable Path to the litestream executable. This option has no effect if litestream-backup-url is unspecified. flag: --litestream-executable env: ZERO\\_LITESTREAM\\_EXECUTABLE required: false Litestream Config Path Path to the litestream yaml config file. zero-cache will run this with its environment variables, which can be referenced in the file via ${ENV} substitution, for example: ZERO\\_REPLICA\\_FILE for the db Path ZERO\\_LITESTREAM\\_BACKUP\\_LOCATION for the db replica url ZERO\\_LITESTREAM\\_LOG\\_LEVEL for the log Level ZERO\\_LOG\\_FORMAT for the log type flag: --litestream-config-path env: ZERO\\_LITESTREAM\\_CONFIG\\_PATH default: ./src/services/litestream/config.yml Litestream Log Level flag: --litestream-log-level env: ZERO\\_LITESTREAM\\_LOG\\_LEVEL default: warn values: debug, info, warn, error Litestream Backup URL The location of the litestream backup, usually an s3:// URL. This is only consulted by the replication-manager. view-syncers receive this information from the replication-manager. flag: --litestream-backup-url env: ZERO\\_LITESTREAM\\_BACKUP\\_URL required: false Litestream Checkpoint Threshold MB The size of the WAL file at which to perform an SQlite checkpoint to apply the writes in the WAL to the main database file. Each checkpoint creates a new WAL segment file that will be backed up by litestream. Smaller thresholds may improve read performance, at the expense of creating more files to download when restoring the replica from the backup. flag: --litestream-checkpoint-threshold-mb env: ZERO\\_LITESTREAM\\_CHECKPOINT\\_THRESHOLD\\_MB default: 40 Litestream Incremental Backup Interval Minutes The interval between incremental backups of the replica. Shorter intervals reduce the amount of change history that needs to be replayed when catching up a new view-syncer, at the expense of increasing the number of files needed to download for the initial litestream restore. flag: --litestream-incremental-backup-interval-minutes env: ZERO\\_LITESTREAM\\_INCREMENTAL\\_BACKUP\\_INTERVAL\\_MINUTES default: 15 Litestream Snapshot Backup Interval Hours The interval between snapshot backups of the replica. Snapshot backups make a full copy of the database to a new litestream generation. This improves restore time at the expense of bandwidth. Applications with a large database and low write rate can increase this interval to reduce network usage for backups (litestream defaults to 24 hours). flag: --litestream-snapshot-backup-interval-hours env: ZERO\\_LITESTREAM\\_SNAPSHOT\\_BACKUP\\_INTERVAL\\_HOURS default: 12 Litestream Restore Parallelism The number of WAL files to download in parallel when performing the initial restore of the replica from the backup. flag: --litestream-restore-parallelism env: ZERO\\_LITESTREAM\\_RESTORE\\_PARALLELISM default: 48 Log Format Use text for developer-friendly console logging and json for consumption by structured-logging services. flag: --log-format env: ZERO\\_LOG\\_FORMAT default: \"text\" values: text, json Log IVM Sampling How often to collect IVM metrics. 1 out of N requests will be sampled where N is this value. flag: --log-ivm-sampling env: ZERO\\_LOG\\_IVM\\_SAMPLING default: 5000 Log Level Sets the logging level for the application. flag: --log-level env: ZERO\\_LOG\\_LEVEL default: \"info\" values: debug, info, warn, error Log Slow Hydrate Threshold The number of milliseconds a query hydration must take to print a slow warning. flag: --log-slow-hydrate-threshold env: ZERO\\_LOG\\_SLOW\\_HYDRATE\\_THRESHOLD default: 100 Log Slow Row Threshold The number of ms a row must take to fetch from table-source before it is considered slow. flag: --log-slow-row-threshold env: ZERO\\_LOG\\_SLOW\\_ROW\\_THRESHOLD default: 2 Log Trace Collector The URL of the trace collector to which to send trace data. Traces are sent over http. Port defaults to 4318 for most collectors. flag: --log-trace-collector env: ZERO\\_LOG\\_TRACE\\_COLLECTOR required: false Number of Sync Workers The number of processes to use for view syncing. Leave this unset to use the maximum available parallelism. If set to 0, the server runs without sync workers, which is the configuration for running the replication-manager. flag: --num-sync-workers env: ZERO\\_NUM\\_SYNC\\_WORKERS required: false Per User Mutation Limit Max The maximum mutations per user within the specified windowMs. flag: --per-user-mutation-limit-max env: ZERO\\_PER\\_USER\\_MUTATION\\_LIMIT\\_MAX required: false Per User Mutation Limit Window (ms) The sliding window over which the perUserMutationLimitMax is enforced. flag: --per-user-mutation-limit-window-ms env: ZERO\\_PER\\_USER\\_MUTATION\\_LIMIT\\_WINDOW\\_MS default: 60000 Port The port for sync connections. flag: --port env: ZERO\\_PORT default: 4848 Push URL The URL of the API server to which zero-cache will push mutations. Required if you use custom mutators. flag: --push-url env: ZERO\\_PUSH\\_URL required: false Query Hydration Stats Track and log the number of rows considered by query hydrations which take longer than log-slow-hydrate-threshold milliseconds. This is useful for debugging and performance tuning. flag: --query-hydration-stats env: ZERO\\_QUERY\\_HYDRATION\\_STATS required: false Replica Vacuum Interval Hours Performs a VACUUM at server startup if the specified number of hours has elapsed since the last VACUUM (or initial-sync). The VACUUM operation is heavyweight and requires double the size of the db in disk space. If unspecified, VACUUM operations are not performed. flag: --replica-vacuum-interval-hours env: ZERO\\_REPLICA\\_VACUUM\\_INTERVAL\\_HOURS required: false Server Version The version string outputted to logs when the server starts up. flag: --server-version env: ZERO\\_SERVER\\_VERSION required: false Storage DB Temp Dir Temporary directory for IVM operator storage. Leave unset to use os.tmpdir(). flag: --storage-db-tmp-dir env: ZERO\\_STORAGE\\_DB\\_TMP\\_DIR required: false Target Client Row Count A soft limit on the number of rows Zero will keep on the client. 20k is a good default value for most applications, and we do not recommend exceeding 100k. See Client Capacity Management for more details. flag: --target-client-row-count env: ZERO\\_TARGET\\_CLIENT\\_ROW\\_COUNT default: 20000 Task ID Globally unique identifier for the zero-cache instance. Setting this to a platform specific task identifier can be useful for debugging. If unspecified, zero-cache will attempt to extract the TaskARN if run from within an AWS ECS container, and otherwise use a random string. flag: --task-id env: ZERO\\_TASK\\_ID required: false Upstream Max Connections The maximum number of connections to open to the upstream database for committing mutations. This is divided evenly amongst sync workers. In addition to this number, zero-cache uses one connection for the replication stream. Note that this number must allow for at least one connection per sync worker, or zero-cache will fail to start. See num-sync-workers. flag: --upstream-max-conns env: ZERO\\_UPSTREAM\\_MAX\\_CONNS default: 20", + "content": "zero-cache is configured either via CLI flag or environment variable. There is no separate zero.config file. You can also see all available flags by running zero-cache --help. Required Flags Auth One of Auth JWK, Auth JWK URL, or Auth Secret must be specified. See Authentication for more details. Replica File File path to the SQLite replica that zero-cache maintains. This can be lost, but if it is, zero-cache will have to re-replicate next time it starts up. flag: --replica-file env: ZERO\\_REPLICA\\_FILE required: true Upstream DB The \"upstream\" authoritative postgres database. In the future we will support other types of upstream besides PG. flag: --upstream-db env: ZERO\\_UPSTREAM\\_DB required: true Optional Flags Admin Password A password used to administer zero-cache server, for example to access the /statz endpoint. flag: --admin-password env: ZERO\\_ADMIN\\_PASSWORD required: false App ID Unique identifier for the app. Multiple zero-cache apps can run on a single upstream database, each of which is isolated from the others, with its own permissions, sharding (future feature), and change/cvr databases. The metadata of an app is stored in an upstream schema with the same name, e.g. zero, and the metadata for each app shard, e.g. client and mutation ids, is stored in the {app-id}\\_{#} schema. (Currently there is only a single \"0\" shard, but this will change with sharding). The CVR and Change data are managed in schemas named {app-id}\\_{shard-num}/cvr and {app-id}\\_{shard-num}/cdc, respectively, allowing multiple apps and shards to share the same database instance (e.g. a Postgres \"cluster\") for CVR and Change management. Due to constraints on replication slot names, an App ID may only consist of lower-case letters, numbers, and the underscore character. Note that this option is used by both zero-cache and zero-deploy-permissions. flag: --app-id env: ZERO\\_APP\\_ID default: zero App Publications Postgres PUBLICATIONs that define the tables and columns to replicate. Publication names may not begin with an underscore, as zero reserves that prefix for internal use. If unspecified, zero-cache will create and use an internal publication that publishes all tables in the public schema, i.e.: ``` CREATE PUBLICATION _{app-id}_public_0 FOR TABLES IN SCHEMA public; ``` Note that once an app has begun syncing data, this list of publications cannot be changed, and zero-cache will refuse to start if a specified value differs from what was originally synced. To use a different set of publications, a new app should be created. flag: --app-publications env: ZERO\\_APP\\_PUBLICATIONS default: \\[] Auth JWK A public key in JWK format used to verify JWTs. Only one of jwk, jwksUrl and secret may be set. flag: --auth-jwk env: ZERO\\_AUTH\\_JWK required: false Auth JWK URL A URL that returns a JWK set used to verify JWTs. Only one of jwk, jwksUrl and secret may be set. flag: --auth-jwks-url env: ZERO\\_AUTH\\_JWKS\\_URL required: false Auto Reset Automatically wipe and resync the replica when replication is halted. This situation can occur for configurations in which the upstream database provider prohibits event trigger creation, preventing the zero-cache from being able to correctly replicate schema changes. For such configurations, an upstream schema change will instead result in halting replication with an error indicating that the replica needs to be reset. When auto-reset is enabled, zero-cache will respond to such situations by shutting down, and when restarted, resetting the replica and all synced clients. This is a heavy-weight operation and can result in user-visible slowness or downtime if compute resources are scarce. flag: --auto-reset env: ZERO\\_AUTO\\_RESET default: true Auth Secret A symmetric key used to verify JWTs. Only one of jwk, jwksUrl and secret may be set. flag: --auth-secret env: ZERO\\_AUTH\\_SECRET required: false Change DB The Postgres database used to store recent replication log entries, in order to sync multiple view-syncers without requiring multiple replication slots on the upstream database. If unspecified, the upstream-db will be used. flag: --change-db env: ZERO\\_CHANGE\\_DB required: false Change Max Connections The maximum number of connections to open to the change database. This is used by the change-streamer for catching up zero-cache replication subscriptions. flag: --change-max-conns env: ZERO\\_CHANGE\\_MAX\\_CONNS default: 5 Change Streamer Mode The mode for running or connecting to the change-streamer: dedicated: runs the change-streamer and shuts down when another change-streamer takes over the replication slot. This is appropriate in a single-node configuration, or for the replication-manager in a multi-node configuration. discover: connects to the change-streamer as internally advertised in the change-db. This is appropriate for the view-syncers in a multi-node flag: --change-streamer-mode env: ZERO\\_CHANGE\\_STREAMER\\_MODE default: dedicated Change Streamer Port The port on which the change-streamer runs. This is an internal protocol between the replication-manager and zero-cache, which runs in the same process in local development. If unspecified, defaults to --port + 1. flag: --change-streamer-port env: ZERO\\_CHANGE\\_STREAMER\\_PORT required: false Change Streamer URI When unset, the zero-cache runs its own replication-manager (i.e. change-streamer). In production, this should be set to the replication-manager URI, which runs a change-streamer on port 4849. flag: --change-streamer-uri env: ZERO\\_CHANGE\\_STREAMER\\_URI required: false CVR DB The Postgres database used to store CVRs. CVRs (client view records) keep track of the data synced to clients in order to determine the diff to send on reconnect. If unspecified, the upstream-db will be used. flag: --cvr-db env: ZERO\\_CVR\\_DB required: false CVR Max Connections The maximum number of connections to open to the CVR database. This is divided evenly amongst sync workers. Note that this number must allow for at least one connection per sync worker, or zero-cache will fail to start. See num-sync-workers. flag: --cvr-max-conns env: ZERO\\_CVR\\_MAX\\_CONNS default: 30 Enable Telemetry Zero collects anonymous telemetry data to help us understand usage. We collect: Zero version Uptime General machine information, like the number of CPUs, OS, CI/CD environment, etc. Information about usage, such as number of queries or mutations processed per hour. This is completely optional and can be disabled at any time. You can also opt-out by setting DO\\_NOT\\_TRACK=1. flag: --enable-telemetry env: ZERO\\_ENABLE\\_TELEMETRY default: true Initial Sync Table Copy Workers The number of parallel workers used to copy tables during initial sync. Each worker copies a single table at a time, fetching rows in batches of initial-sync-row-batch-size. flag: --initial-sync-table-copy-workers env: ZERO\\_INITIAL\\_SYNC\\_TABLE\\_COPY\\_WORKERS default: 5 Lazy Startup Delay starting the majority of zero-cache until first request. This is mainly intended to avoid connecting to Postgres replication stream until the first request is received, which can be useful i.e., for preview instances. Currently only supported in single-node mode. flag: --lazy-startup env: ZERO\\_LAZY\\_STARTUP default: false Litestream Backup URL The location of the litestream backup, usually an s3:// URL. This is only consulted by the replication-manager. view-syncers receive this information from the replication-manager. flag: --litestream-backup-url env: ZERO\\_LITESTREAM\\_BACKUP\\_URL required: false Litestream Checkpoint Threshold MB The size of the WAL file at which to perform an SQlite checkpoint to apply the writes in the WAL to the main database file. Each checkpoint creates a new WAL segment file that will be backed up by litestream. Smaller thresholds may improve read performance, at the expense of creating more files to download when restoring the replica from the backup. flag: --litestream-checkpoint-threshold-mb env: ZERO\\_LITESTREAM\\_CHECKPOINT\\_THRESHOLD\\_MB default: 40 Litestream Config Path Path to the litestream yaml config file. zero-cache will run this with its environment variables, which can be referenced in the file via ${ENV} substitution, for example: ZERO\\_REPLICA\\_FILE for the db Path ZERO\\_LITESTREAM\\_BACKUP\\_LOCATION for the db replica url ZERO\\_LITESTREAM\\_LOG\\_LEVEL for the log Level ZERO\\_LOG\\_FORMAT for the log type flag: --litestream-config-path env: ZERO\\_LITESTREAM\\_CONFIG\\_PATH default: ./src/services/litestream/config.yml Litestream Executable Path to the litestream executable. This option has no effect if litestream-backup-url is unspecified. flag: --litestream-executable env: ZERO\\_LITESTREAM\\_EXECUTABLE required: false Litestream Incremental Backup Interval Minutes The interval between incremental backups of the replica. Shorter intervals reduce the amount of change history that needs to be replayed when catching up a new view-syncer, at the expense of increasing the number of files needed to download for the initial litestream restore. flag: --litestream-incremental-backup-interval-minutes env: ZERO\\_LITESTREAM\\_INCREMENTAL\\_BACKUP\\_INTERVAL\\_MINUTES default: 15 Litestream Multipart Concurrency The number of parts (of size --litestream-multipart-size bytes) to upload or download in parallel when backing up or restoring the snapshot. flag: --litestream-multipart-concurrency env: ZERO\\_LITESTREAM\\_MULTIPART\\_CONCURRENCY default: 48 Litestream Multipart Size The size of each part when uploading or downloading the snapshot with \\--litestream-multipart-concurrency. Note that up to concurrency \\* size bytes of memory are used when backing up or restoring the snapshot. flag: --litestream-multipart-size env: ZERO\\_LITESTREAM\\_MULTIPART\\_SIZE default: 16777216 (16 MiB) Litestream Log Level flag: --litestream-log-level env: ZERO\\_LITESTREAM\\_LOG\\_LEVEL default: warn values: debug, info, warn, error Litestream Port Port on which litestream exports metrics, used to determine the replication watermark up to which it is safe to purge change log records. flag: --litestream-port env: ZERO\\_LITESTREAM\\_PORT default: --port + 2 Litestream Restore Parallelism The number of WAL files to download in parallel when performing the initial restore of the replica from the backup. flag: --litestream-restore-parallelism env: ZERO\\_LITESTREAM\\_RESTORE\\_PARALLELISM default: 48 Litestream Snapshot Backup Interval Hours The interval between snapshot backups of the replica. Snapshot backups make a full copy of the database to a new litestream generation. This improves restore time at the expense of bandwidth. Applications with a large database and low write rate can increase this interval to reduce network usage for backups (litestream defaults to 24 hours). flag: --litestream-snapshot-backup-interval-hours env: ZERO\\_LITESTREAM\\_SNAPSHOT\\_BACKUP\\_INTERVAL\\_HOURS default: 12 Log Format Use text for developer-friendly console logging and json for consumption by structured-logging services. flag: --log-format env: ZERO\\_LOG\\_FORMAT default: \"text\" values: text, json Log IVM Sampling How often to collect IVM metrics. 1 out of N requests will be sampled where N is this value. flag: --log-ivm-sampling env: ZERO\\_LOG\\_IVM\\_SAMPLING default: 5000 Log Level Sets the logging level for the application. flag: --log-level env: ZERO\\_LOG\\_LEVEL default: \"info\" values: debug, info, warn, error Log Slow Hydrate Threshold The number of milliseconds a query hydration must take to print a slow warning. flag: --log-slow-hydrate-threshold env: ZERO\\_LOG\\_SLOW\\_HYDRATE\\_THRESHOLD default: 100 Log Slow Row Threshold The number of ms a row must take to fetch from table-source before it is considered slow. flag: --log-slow-row-threshold env: ZERO\\_LOG\\_SLOW\\_ROW\\_THRESHOLD default: 2 Number of Sync Workers The number of processes to use for view syncing. Leave this unset to use the maximum available parallelism. If set to 0, the server runs without sync workers, which is the configuration for running the replication-manager. flag: --num-sync-workers env: ZERO\\_NUM\\_SYNC\\_WORKERS required: false Per User Mutation Limit Max The maximum mutations per user within the specified windowMs. flag: --per-user-mutation-limit-max env: ZERO\\_PER\\_USER\\_MUTATION\\_LIMIT\\_MAX required: false Per User Mutation Limit Window (ms) The sliding window over which the perUserMutationLimitMax is enforced. flag: --per-user-mutation-limit-window-ms env: ZERO\\_PER\\_USER\\_MUTATION\\_LIMIT\\_WINDOW\\_MS default: 60000 Port The port for sync connections. flag: --port env: ZERO\\_PORT default: 4848 Push API Key An optional secret used to authorize zero-cache to call the API server handling writes. flag: --push-api-key env: ZERO\\_PUSH\\_API\\_KEY required: false Push Forward Cookies If true, zero-cache will forward cookies from the request. This is useful for passing authentication cookies to the API server. If false, cookies are not forwarded. flag: --push-forward-cookies env: ZERO\\_PUSH\\_FORWARD\\_COOKIES default: false Push URL The URL of the API server to which zero-cache will push custom mutations. Can also be a pattern, or set of patterns, which is used in conjunction with the push.url paramter of the Zero constructor. In this case, the pattern specifies the URLs which Zero will allow the constructor to specify. Examples: https://\\*.example.com matches https://api.example.com and https://www.example.com https://\\*.example.com does not match https://example.com (no subdomain) https://\\*.example.com does not match https://api.example.com/path (no trailing path) https://\\*.\\*.example.com matches https://api.v1.example.com and https://www.v2.example.com https://\\*.\\*.example.com does not match https://api.example.com (only one subdomain) Currently, wildcards are only allowed for subdomains. flag: --push-url env: ZERO\\_PUSH\\_URL required: false Query Hydration Stats Track and log the number of rows considered by query hydrations which take longer than log-slow-hydrate-threshold milliseconds. This is useful for debugging and performance tuning. flag: --query-hydration-stats env: ZERO\\_QUERY\\_HYDRATION\\_STATS required: false Replica Vacuum Interval Hours Performs a VACUUM at server startup if the specified number of hours has elapsed since the last VACUUM (or initial-sync). The VACUUM operation is heavyweight and requires double the size of the db in disk space. If unspecified, VACUUM operations are not performed. flag: --replica-vacuum-interval-hours env: ZERO\\_REPLICA\\_VACUUM\\_INTERVAL\\_HOURS required: false Server Version The version string outputted to logs when the server starts up. flag: --server-version env: ZERO\\_SERVER\\_VERSION required: false Storage DB Temp Dir Temporary directory for IVM operator storage. Leave unset to use os.tmpdir(). flag: --storage-db-tmp-dir env: ZERO\\_STORAGE\\_DB\\_TMP\\_DIR required: false Task ID Globally unique identifier for the zero-cache instance. Setting this to a platform specific task identifier can be useful for debugging. If unspecified, zero-cache will attempt to extract the TaskARN if run from within an AWS ECS container, and otherwise use a random string. flag: --task-id env: ZERO\\_TASK\\_ID required: false Upstream Max Connections The maximum number of connections to open to the upstream database for committing mutations. This is divided evenly amongst sync workers. In addition to this number, zero-cache uses one connection for the replication stream. Note that this number must allow for at least one connection per sync worker, or zero-cache will fail to start. See num-sync-workers. flag: --upstream-max-conns env: ZERO\\_UPSTREAM\\_MAX\\_CONNS default: 20", "headings": [] }, { - "id": "52-zero-schema", + "id": "54-zero-schema", "title": "Zero Schema", "url": "/docs/zero-schema", "content": "Zero applications have both a database schema (the normal backend database schema that all web apps have) and a Zero schema. The purpose of the Zero schema is to: Provide typesafety for ZQL queries Define first-class relationships between tables Define permissions for access control \\(), }) .primaryKey('id'); ``` Custom JSON Types Use the json helper to define a column that stores a JSON-compatible value: ```tsx import {table, string, json} from '@rocicorp/zero'; const user = table('user') .columns({ id: string(), name: string(), settings: json<{theme: 'light' | 'dark'}>(), }) .primaryKey('id'); ``` Compound Primary Keys Pass multiple columns to primaryKey to define a compound primary key: ```ts const user = table('user') .columns({ orgID: string(), userID: string(), name: string(), }) .primaryKey('orgID', 'userID'); ``` Relationships Use the relationships function to define relationships between tables. Use the one and many helpers to define singular and plural relationships, respectively: ```ts const messageRelationships = relationships(message, ({one, many}) => ({ sender: one({ sourceField: ['senderID'], destField: ['id'], destSchema: user, }), replies: many({ sourceField: ['id'], destSchema: message, destField: ['parentMessageID'], }), })); ``` This creates \"sender\" and \"replies\" relationships that can later be queried with the related ZQL clause: ```ts const messagesWithSenderAndReplies = z.query.messages .related('sender') .related('replies'); ``` This will return an object for each message row. Each message will have a sender field that is a single User object or null, and a replies field that is an array of Message objects. Many-to-Many Relationships You can create many-to-many relationships by chaining the relationship definitions. Assuming issue and label tables, along with an issueLabel junction table, you can define a labels relationship like this: ```ts const issueRelationships = relationships(issue, ({many}) => ({ labels: many( { sourceField: ['id'], destSchema: issueLabel, destField: ['issueID'], }, { sourceField: ['labelID'], destSchema: label, destField: ['id'], }, ), })); ``` Compound Keys Relationships Relationships can traverse compound keys. Imagine a user table with a compound primary key of orgID and userID, and a message table with a related senderOrgID and senderUserID. This can be represented in your schema with: ```ts const messageRelationships = relationships(message, ({one}) => ({ sender: one({ sourceField: ['senderOrgID', 'senderUserID'], destSchema: user, destField: ['orgID', 'userID'], }), })); ``` Circular Relationships Circular relationships are fully supported: ```tsx const commentRelationships = relationships(comment, ({one}) => ({ parent: one({ sourceField: ['parentID'], destSchema: comment, destField: ['id'], }), })); ``` Database Schemas Use createSchema to define the entire Zero schema: ```tsx import {createSchema} from '@rocicorp/zero'; export const schema = createSchema({ tables: [user, medium, message], relationships: [userRelationships, mediumRelationships, messageRelationships], }); ``` Migrations Zero uses TypeScript-style structural typing to detect schema changes and implement smooth migrations. How it Works When the Zero client connects to zero-cache it sends a copy of the schema it was constructed with. zero-cache compares this schema to the one it has, and rejects the connection with a special error code if the schema is incompatible. By default, The Zero client handles this error code by calling location.reload(). The intent is to to get a newer version of the app that has been updated to handle the new server schema. If a reload loop does occur, Zero uses exponential backoff to avoid overloading the server. If you want to delay this reload, you can do so by providing the onUpdateNeeded constructor parameter: ```ts const z = new Zero({ onUpdateNeeded: updateReason => { if (reason.type === 'SchemaVersionNotSupported') { // Do something custom here, like show a banner. // When you're ready, call `location.reload()`. } }, }); ``` If the schema changes while a client is running in a compatible way, zero-cache syncs the schema change to the client so that it's ready when the app reloads and gets new code that needs it. If the schema changes while a client is running in an incompatible way, zero-cache will close the client connection with the same error code as above. Schema Change Process Like other database-backed applications, Zero schema migration generally follow an “expand/migrate/contract” pattern: Implement and run an “expand” migration on the backend that is backwards compatible with existing schemas. Add new rows, tables, as well as any defaults and triggers needed for backwards compatibility. Add any new permissions required for the new tables/columns by running zero-deploy-permissions. Update and deploy the client app to use the new schema. Optionally, after some grace period, implement and run a “contract” migration on the backend, deleting any obsolete rows/tables. Steps 1-3 can generally be done as part of one deploy by your CI pipeline, but step 4 would be weeks later when most open clients have refreshed and gotten new code.", "headings": [] }, { - "id": "53-zql-on-the-server", + "id": "55-zql-on-the-server", "title": "ZQL on the Server", "url": "/docs/zql-on-the-server", "content": "Custom Mutators use ZQL on the server as an implementation detail, but you can also use ZQL on the server directly, outside of Custom Mutators. This is useful for a variety of reasons: You can use ZQL to implement standard REST endpoints, allowing you to share code with custom mutators. You can use ZQL as part of schema migrations. In the future (but not yet implemented), this can support server-side rendering Here's a basic example: ```ts import { PushProcessor, ZQLDatabase, PostgresJSConnection, TransactionProviderInput, } from '@rocicorp/zero/pg'; const db = new ZQLDatabase( new PostgresJSConnection( postgres( must( process.env.ZERO_UPSTREAM_DB as string, 'required env var ZERO_UPSTREAM_DB', ), ), ), schema, ); // This is needed temporarily and will be cleaned up in the future. const dummyTransactionInput: TransactionProviderInput = { clientGroupID: 'unused', clientID: 'unused', mutationID: 42, upstreamSchema: 'unused', }; db.transaction(async tx => { // await tx.mutate... // await tx.query... // await myMutator(tx, ...args); }, dummyTransactionInput); ``` If ZQL does not have the featuers you need, you can use tx.dbTransaction to drop down to raw SQL. Custom Database Connection Zero only provides an adapter for postgres.js. It is possible to write your own adatapter by implementing DBTransaction and DBConnection. Node Postgres Here is an example for node-postgres by Jökull Sólberg (full example) ```ts import {Client, type ClientBase} from 'pg'; class PgConnection implements DBConnection { readonly #client: ClientBase; constructor(client: ClientBase) { this.#client = client; } async query(sql: string, params: unknown[]): Promise { const result = await this.#client.query(sql, params as JSONValue[]); return result.rows; } async transaction( fn: (tx: DBTransaction) => Promise, ): Promise { if (!(this.#client instanceof Client)) { throw new Error('Transactions require a non-pooled Client instance'); } const tx = new PgTransaction(this.#client); try { await this.#client.query('BEGIN'); const result = await fn(tx); await this.#client.query('COMMIT'); return result; } catch (error) { await this.#client.query('ROLLBACK'); throw error; } } } class PgTransaction implements DBTransaction { readonly wrappedTransaction: ClientBase; constructor(client: ClientBase) { this.wrappedTransaction = client; } async query(sql: string, params: unknown[]): Promise { const result = await this.wrappedTransaction.query( sql, params as JSONValue[], ); return result.rows; } } // Then you can use it just like postgres.js const client = new Client({ connectionString: process.env.ZERO_UPSTREAM_DB, }); await client.connect(); const db = new ZQLDatabase(new PgConnection(client), schema); ``` Drizzle ORM It is also possible to use ORMs like Drizzle. Wrap the drizzle transaction and now you can access drizzle's transaction within custom mutators. Blog post and full example by Jökull Sólberg (again 🙌) ```ts // Assuming $client is the raw pg.PoolClient, this type matches how // `drizzle()` inits when using `node-postgres` type Drizzle = NodePgDatabase & {$client: PoolClient}; // Extract the Drizzle-specific transaction type type DrizzleTransaction = Parameters[0]>[0]; class DrizzleConnection implements DBConnection { drizzle: Drizzle; constructor(drizzle: Drizzle) { this.drizzle = drizzle; } // `query` is used by Zero's ZQLDatabase for ZQL reads on the server query(sql: string, params: unknown[]): Promise { return this.drizzle.$client .query(sql, params) .then(({rows}) => rows); } // `transaction` wraps Drizzle's transaction transaction( fn: (tx: DBTransaction) => Promise, ): Promise { return this.drizzle.transaction(drizzleTx => // Pass a new Zero DBTransaction wrapper around Drizzle's one fn(new ZeroDrizzleTransaction(drizzleTx)), ); } } class ZeroDrizzleTransaction implements DBTransaction { readonly wrappedTransaction: DrizzleTransaction; constructor(drizzleTx: DrizzleTransaction) { this.wrappedTransaction = drizzleTx; } // This `query` method would be used if ZQL reads happen *within* // a custom mutator that is itself running inside this wrapped transaction. query(sql: string, params: unknown[]): Promise { // Drizzle's transaction object might hide the raw client, // this is one way to get at it for `pg` driver. Adjust if needed. const session = this.wrappedTransaction._.session as unknown as { client: Drizzle['$client']; }; return session.client .query(sql, params) .then(({rows}) => rows); } } ``` SSR Although you can run ZQL on the server, Zero does not yet have the wiring setup in its bindings layers to support server-side rendering (patches welcome though!). For now, you should use your framework's recommended pattern to prevent SSR execution. Next.js Add the use client directive. SolidStart Wrap components that use Zero with the clientOnly higher-order component. The standard clientOnly pattern uses dynamic imports, but note that this approach (similar to React's lazy) works with any function returning a Promise<{default: () => JSX.Element}>. If code splitting is unnecessary, you can skip the dynamic import. TanStack Start Use React's lazy for dynamic imports.", diff --git a/lib/markdown.ts b/lib/markdown.ts index 02ae5714..3dcc7e85 100644 --- a/lib/markdown.ts +++ b/lib/markdown.ts @@ -58,28 +58,35 @@ export async function getDocsForSlug(slug: string) { return await parseMdx(rawMdx); } catch (err) { console.error(`Error fetching docs for slug "${slug}":`, err); - throw err; + return null; } } // Generate a Table of Contents (TOC) from markdown headings export async function getDocsTocs(slug: string) { - const contentPath = await getDocsContentPath(slug); - const rawMdx = await fs.readFile(contentPath, 'utf-8'); - const headingsRegex = /^(#{2,4})\s(.+)$/gm; // Matches headings ## to #### - let match; - const extractedHeadings = []; - while ((match = headingsRegex.exec(rawMdx)) !== null) { - const headingLevel = match[1].length; - const headingText = match[2].trim(); - const slug = sluggify(headingText); - extractedHeadings.push({ - level: headingLevel, - text: headingText, - href: `#${slug}`, // Create anchor links - }); + let rawMdx: string; + try { + const contentPath = await getDocsContentPath(slug); + rawMdx = await fs.readFile(contentPath, 'utf-8'); + + const headingsRegex = /^(#{2,4})\s(.+)$/gm; // Matches headings ## to #### + let match; + const extractedHeadings = []; + while ((match = headingsRegex.exec(rawMdx)) !== null) { + const headingLevel = match[1].length; + const headingText = match[2].trim(); + const slug = sluggify(headingText); + extractedHeadings.push({ + level: headingLevel, + text: headingText, + href: `#${slug}`, // Create anchor links + }); + } + return extractedHeadings; + } catch (err) { + console.error(`Error fetching docs for slug "${slug}":`, err); + return []; } - return extractedHeadings; } export function getPreviousNext(path: string): { diff --git a/next.config.mjs b/next.config.mjs index f6b16bf0..0d1124f9 100644 --- a/next.config.mjs +++ b/next.config.mjs @@ -12,6 +12,11 @@ const nextConfig = { destination: '/docs/introduction', permanent: false, }, + { + source: '/docs/schema-migration', + destination: '/docs/zero-schema/#migrations', + permanent: true, + }, ]; }, }; From 00182f1a558687f088304bbcdf28530850ba4881 Mon Sep 17 00:00:00 2001 From: Chase Adams Date: Thu, 7 Aug 2025 16:11:54 -0700 Subject: [PATCH 18/28] fix: update packages --- app/docs/[[...slug]]/page.tsx | 13 +- app/docs/layout.tsx | 5 + package-lock.json | 5703 +++++++++++++++++++-------------- package.json | 48 +- tsconfig.json | 24 +- 5 files changed, 3297 insertions(+), 2496 deletions(-) diff --git a/app/docs/[[...slug]]/page.tsx b/app/docs/[[...slug]]/page.tsx index 06fb3b9e..8ed800ac 100644 --- a/app/docs/[[...slug]]/page.tsx +++ b/app/docs/[[...slug]]/page.tsx @@ -6,10 +6,12 @@ import {getDocsForSlug, getDocsTocs, getPreviousNext} from '@/lib/markdown'; import {Typography} from '@/components/typography'; import CopyContent from '@/components/ui/copy-content'; -type PageProps = {params: {slug: string[]}}; +type PageProps = {params: Promise<{slug: string[]}>}; -export default async function DocsPage({params: {slug = []}}: PageProps) { - const pathName = slug.join('/'); +export default async function DocsPage({params}: PageProps) { + const {slug: slugParams} = await params; + + const pathName = slugParams.join('/'); const [res, tocs, previousNext] = await Promise.all([ getDocsForSlug(pathName), getDocsTocs(pathName), @@ -38,8 +40,9 @@ export default async function DocsPage({params: {slug = []}}: PageProps) { ); } -export async function generateMetadata({params: {slug = []}}: PageProps) { - const pathName = slug.join('/'); +export async function generateMetadata({params}: PageProps) { + const {slug: slugParams} = await params; + const pathName = slugParams.join('/'); const res = await getDocsForSlug(pathName); if (!res) return null; const {frontmatter} = res; diff --git a/app/docs/layout.tsx b/app/docs/layout.tsx index 16ab553d..ed8772cd 100644 --- a/app/docs/layout.tsx +++ b/app/docs/layout.tsx @@ -1,5 +1,10 @@ import {Leftbar} from '@/components/leftbar'; +// Force this layout to be fully static at build time and restrict to generated params +export const dynamic = 'force-static'; +export const dynamicParams = false; +export const revalidate = false; + export default function DocsLayout({ children, }: Readonly<{ diff --git a/package-lock.json b/package-lock.json index 3a4b8351..7e074295 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,58 +8,58 @@ "name": "aria-docs", "version": "1.0.0", "dependencies": { - "@radix-ui/react-collapsible": "^1.1.0", - "@radix-ui/react-dialog": "^1.1.1", - "@radix-ui/react-dropdown-menu": "^2.1.1", - "@radix-ui/react-scroll-area": "^1.1.0", - "@radix-ui/react-slot": "^1.1.0", + "@radix-ui/react-collapsible": "^1.1.11", + "@radix-ui/react-dialog": "^1.1.14", + "@radix-ui/react-dropdown-menu": "^2.1.15", + "@radix-ui/react-scroll-area": "^1.2.9", + "@radix-ui/react-slot": "^1.2.3", "@radix-ui/react-tooltip": "^1.2.7", - "@vercel/og": "^0.8.2", + "@vercel/og": "^0.8.5", "broken-link-checker": "^0.7.8", - "class-variance-authority": "^0.7.0", + "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", "cmdk": "^1.1.1", "gray-matter": "^4.0.3", - "lucide-react": "^0.435.0", + "lucide-react": "^0.537.0", "lunr": "^2.3.9", "mdast-util-to-string": "^4.0.0", - "next": "^14.2.6", + "next": "^15.4.6", "next-mdx-remote": "^5.0.0", - "next-themes": "^0.3.0", - "react": "^18.3.1", - "react-dom": "^18.3.1", + "next-themes": "^0.4.6", + "react": "^19.1.1", + "react-dom": "^19.1.1", "react-hotkeys-hook": "^5.1.0", "rehype-autolink-headings": "^7.1.0", "rehype-code-titles": "^1.2.0", - "rehype-prism-plus": "^2.0.0", + "rehype-prism-plus": "^2.0.1", "rehype-slug": "^6.0.0", "remark": "^15.0.1", - "remark-gfm": "^4.0.0", + "remark-gfm": "^4.0.1", "remark-parse": "^11.0.0", "remark-stringify": "^11.0.0", "strip-markdown": "^6.0.0", - "tailwind-merge": "^2.5.2", + "tailwind-merge": "^3.3.1", "tailwindcss-animate": "^1.0.7", "unist-util-visit": "^5.0.0" }, "devDependencies": { "@rocicorp/prettier-config": "^0.3.0", - "@tailwindcss/typography": "^0.5.14", + "@tailwindcss/typography": "^0.5.16", "@types/hast": "^3.0.4", "@types/lunr": "^2.3.7", - "@types/node": "^20.17.19", - "@types/react": "^18", - "@types/react-dom": "^18", + "@types/node": "^24.2.0", + "@types/react": "^19", + "@types/react-dom": "^19", "@types/unist": "^3.0.3", - "autoprefixer": "^10.4.20", - "eslint": "^8", - "eslint-config-next": "^14.2.6", - "highlight.js": "^11.10.0", + "autoprefixer": "^10.4.21", + "eslint": "^9", + "eslint-config-next": "^15.4.6", + "highlight.js": "^11.11.1", "postcss": "^8", "react-highlight": "^0.15.0", "tailwindcss": "^3.4.10", "ts-node": "^10.9.2", - "tsx": "^4.19.3", + "tsx": "^4.20.3", "typescript": "^5" } }, @@ -76,6 +76,7 @@ "version": "5.2.0", "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", + "license": "MIT", "engines": { "node": ">=10" }, @@ -181,19 +182,6 @@ "node": ">=4" } }, - "node_modules/@babel/runtime": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.0.tgz", - "integrity": "sha512-VtPOkrdPHZsKc/clNqyi9WUA8TINkZ4cGk63UUE3u4pmB2k+ZMQRDuIOagv8UVd6j7k0T3+RRIb7beKTebNbcw==", - "dev": true, - "license": "MIT", - "dependencies": { - "regenerator-runtime": "^0.14.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@cspotcode/source-map-support": { "version": "0.8.1", "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", @@ -218,6 +206,39 @@ "@jridgewell/sourcemap-codec": "^1.4.10" } }, + "node_modules/@emnapi/core": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.4.5.tgz", + "integrity": "sha512-XsLw1dEOpkSX/WucdqUhPWP7hDxSvZiY+fsUC14h+FtQ2Ifni4znbBt8punRX+Uj2JG/uDb8nEHVKvrVlvdZ5Q==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/wasi-threads": "1.0.4", + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/runtime": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.4.5.tgz", + "integrity": "sha512-++LApOtY0pEEz1zrd9vy1/zXVaVJJ/EbAF3u0fXIzPJEDtnITsBGbbK0EkM72amhl/R5b+5xx0Y/QhcVOpuulg==", + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/wasi-threads": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.0.4.tgz", + "integrity": "sha512-PJR+bOmMOPH8AtcTGAyYNiuJ3/Fcoj2XN/gBEWzDIKh254XO+mM9XoXHk5GNEhodxeMznbg7BlRojVbKN+gC6g==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, "node_modules/@esbuild/aix-ppc64": { "version": "0.25.0", "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.0.tgz", @@ -644,39 +665,83 @@ } }, "node_modules/@eslint-community/eslint-utils": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", - "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.7.0.tgz", + "integrity": "sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw==", "dev": true, + "license": "MIT", "dependencies": { - "eslint-visitor-keys": "^3.3.0" + "eslint-visitor-keys": "^3.4.3" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, + "funding": { + "url": "https://opencollective.com/eslint" + }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, "node_modules/@eslint-community/regexpp": { - "version": "4.10.0", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", - "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", + "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", "dev": true, + "license": "MIT", "engines": { "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, + "node_modules/@eslint/config-array": { + "version": "0.21.0", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.0.tgz", + "integrity": "sha512-ENIdc4iLu0d93HeYirvKmrzshzofPw6VkZRKQGe9Nv46ZnWUzcF1xV01dcvEg/1wXUR61OmmlSfyeyO7EvjLxQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/object-schema": "^2.1.6", + "debug": "^4.3.1", + "minimatch": "^3.1.2" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/config-helpers": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.3.0.tgz", + "integrity": "sha512-ViuymvFmcJi04qdZeDc2whTHryouGcDlaxPqarTD0ZE10ISpxGUVZGZDx4w01upyIynL3iu6IXH2bS1NhclQMw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/core": { + "version": "0.15.1", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.15.1.tgz", + "integrity": "sha512-bkOp+iumZCCbt1K1CmWf0R9pM5yKpDv+ZXtvSyQpudrI9kuFLp+bM2WOPXImuD/ceQuaa8f5pj93Y7zyECIGNA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@types/json-schema": "^7.0.15" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, "node_modules/@eslint/eslintrc": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", - "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.1.tgz", + "integrity": "sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==", "dev": true, + "license": "MIT", "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", - "espree": "^9.6.0", - "globals": "^13.19.0", + "espree": "^10.0.1", + "globals": "^14.0.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", "js-yaml": "^4.1.0", @@ -684,44 +749,75 @@ "strip-json-comments": "^3.1.1" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" } }, "node_modules/@eslint/js": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", - "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", + "version": "9.32.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.32.0.tgz", + "integrity": "sha512-BBpRFZK3eX6uMLKz8WxFOBIFFcGFJ/g8XuwjTHCqHROSIsopI+ddn/d5Cfh36+7+e5edVS8dbSHnBNhrLEX0zg==", "dev": true, + "license": "MIT", "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + } + }, + "node_modules/@eslint/object-schema": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.6.tgz", + "integrity": "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/plugin-kit": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.3.4.tgz", + "integrity": "sha512-Ul5l+lHEcw3L5+k8POx6r74mxEYKG5kOb6Xpy2gCRW6zweT6TEhAf8vhxGgjhqrd/VO/Dirhsb+1hNpD1ue9hw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.15.1", + "levn": "^0.4.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, "node_modules/@floating-ui/core": { - "version": "1.6.7", - "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.7.tgz", - "integrity": "sha512-yDzVT/Lm101nQ5TCVeK65LtdN7Tj4Qpr9RTXJ2vPFLqtLxwOrpoxAHAJI8J3yYWUc40J0BDBheaitK5SJmno2g==", + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.3.tgz", + "integrity": "sha512-sGnvb5dmrJaKEZ+LDIpguvdX3bDlEllmv4/ClQ9awcmCZrlx5jQyyMWFM5kBI+EyNOCDDiKk8il0zeuX3Zlg/w==", + "license": "MIT", "dependencies": { - "@floating-ui/utils": "^0.2.7" + "@floating-ui/utils": "^0.2.10" } }, "node_modules/@floating-ui/dom": { - "version": "1.6.10", - "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.10.tgz", - "integrity": "sha512-fskgCFv8J8OamCmyun8MfjB1Olfn+uZKjOKZ0vhYF3gRmEUXcGOjxWL8bBr7i4kIuPZ2KD2S3EUIOxnjC8kl2A==", + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.3.tgz", + "integrity": "sha512-uZA413QEpNuhtb3/iIKoYMSK07keHPYeXF02Zhd6e213j+d1NamLix/mCLxBUDW/Gx52sPH2m+chlUsyaBs/Ag==", + "license": "MIT", "dependencies": { - "@floating-ui/core": "^1.6.0", - "@floating-ui/utils": "^0.2.7" + "@floating-ui/core": "^1.7.3", + "@floating-ui/utils": "^0.2.10" } }, "node_modules/@floating-ui/react-dom": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.1.tgz", - "integrity": "sha512-4h84MJt3CHrtG18mGsXuLCHMrug49d7DFkU0RMIyshRveBeyV2hmV/pDaF2Uxtu8kgq5r46llp5E5FQiR0K2Yg==", + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.5.tgz", + "integrity": "sha512-HDO/1/1oH9fjj4eLgegrlH3dklZpHtUYYFiVwMUwfGvk9jWDRWqkklA2/NFScknrcNSspbV868WjXORvreDX+Q==", + "license": "MIT", "dependencies": { - "@floating-ui/dom": "^1.0.0" + "@floating-ui/dom": "^1.7.3" }, "peerDependencies": { "react": ">=16.8.0", @@ -729,22 +825,47 @@ } }, "node_modules/@floating-ui/utils": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.7.tgz", - "integrity": "sha512-X8R8Oj771YRl/w+c1HqAC1szL8zWQRwFvgDwT129k9ACdBoud/+/rX9V0qiMl6LWUdP9voC2nDVZYPMQQsb6eA==" + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.10.tgz", + "integrity": "sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ==", + "license": "MIT" + }, + "node_modules/@humanfs/core": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", + "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18.0" + } }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.11.14", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", - "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", + "node_modules/@humanfs/node": { + "version": "0.16.6", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.6.tgz", + "integrity": "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==", "dev": true, + "license": "Apache-2.0", "dependencies": { - "@humanwhocodes/object-schema": "^2.0.2", - "debug": "^4.3.1", - "minimatch": "^3.0.5" + "@humanfs/core": "^0.19.1", + "@humanwhocodes/retry": "^0.3.0" }, "engines": { - "node": ">=10.10.0" + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node/node_modules/@humanwhocodes/retry": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz", + "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" } }, "node_modules/@humanwhocodes/module-importer": { @@ -760,975 +881,770 @@ "url": "https://github.com/sponsors/nzakas" } }, - "node_modules/@humanwhocodes/object-schema": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", - "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", - "dev": true - }, - "node_modules/@isaacs/cliui": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", - "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", - "dependencies": { - "string-width": "^5.1.2", - "string-width-cjs": "npm:string-width@^4.2.0", - "strip-ansi": "^7.0.1", - "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", - "wrap-ansi": "^8.1.0", - "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@isaacs/cliui/node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "node_modules/@humanwhocodes/retry": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", + "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", + "dev": true, + "license": "Apache-2.0", "engines": { - "node": ">=12" + "node": ">=18.18" }, "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" + "type": "github", + "url": "https://github.com/sponsors/nzakas" } }, - "node_modules/@isaacs/cliui/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dependencies": { - "ansi-regex": "^6.0.1" - }, + "node_modules/@img/sharp-darwin-arm64": { + "version": "0.34.3", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.3.tgz", + "integrity": "sha512-ryFMfvxxpQRsgZJqBd4wsttYQbCxsJksrv9Lw/v798JcQ8+w84mBWuXwl+TT0WJ/WrYOLaYpwQXi3sA9nTIaIg==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=12" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" }, "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", - "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", - "dependencies": { - "@jridgewell/set-array": "^1.2.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.24" + "url": "https://opencollective.com/libvips" }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "engines": { - "node": ">=6.0.0" + "optionalDependencies": { + "@img/sharp-libvips-darwin-arm64": "1.2.0" } }, - "node_modules/@jridgewell/set-array": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", - "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "node_modules/@img/sharp-darwin-x64": { + "version": "0.34.3", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.3.tgz", + "integrity": "sha512-yHpJYynROAj12TA6qil58hmPmAwxKKC7reUqtGLzsOHfP7/rniNGTL8tjWX6L3CTV4+5P4ypcS7Pp+7OB+8ihA==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.15", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", - "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==" - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.25", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", - "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, - "node_modules/@mdx-js/mdx": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@mdx-js/mdx/-/mdx-3.0.1.tgz", - "integrity": "sha512-eIQ4QTrOWyL3LWEe/bu6Taqzq2HQvHcyTMaOrI95P2/LmJE7AsfPfgJGuFLPVqBUE1BC1rik3VIhU+s9u72arA==", - "dependencies": { - "@types/estree": "^1.0.0", - "@types/estree-jsx": "^1.0.0", - "@types/hast": "^3.0.0", - "@types/mdx": "^2.0.0", - "collapse-white-space": "^2.0.0", - "devlop": "^1.0.0", - "estree-util-build-jsx": "^3.0.0", - "estree-util-is-identifier-name": "^3.0.0", - "estree-util-to-js": "^2.0.0", - "estree-walker": "^3.0.0", - "hast-util-to-estree": "^3.0.0", - "hast-util-to-jsx-runtime": "^2.0.0", - "markdown-extensions": "^2.0.0", - "periscopic": "^3.0.0", - "remark-mdx": "^3.0.0", - "remark-parse": "^11.0.0", - "remark-rehype": "^11.0.0", - "source-map": "^0.7.0", - "unified": "^11.0.0", - "unist-util-position-from-estree": "^2.0.0", - "unist-util-stringify-position": "^4.0.0", - "unist-util-visit": "^5.0.0", - "vfile": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/@mdx-js/react": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@mdx-js/react/-/react-3.0.1.tgz", - "integrity": "sha512-9ZrPIU4MGf6et1m1ov3zKf+q9+deetI51zprKB1D/z3NOb+rUxxtEl3mCjW5wTGh6VhRdwPueh1oRzi6ezkA8A==", - "dependencies": { - "@types/mdx": "^2.0.0" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "url": "https://opencollective.com/libvips" }, - "peerDependencies": { - "@types/react": ">=16", - "react": ">=16" - } - }, - "node_modules/@next/env": { - "version": "14.2.26", - "resolved": "https://registry.npmjs.org/@next/env/-/env-14.2.26.tgz", - "integrity": "sha512-vO//GJ/YBco+H7xdQhzJxF7ub3SUwft76jwaeOyVVQFHCi5DCnkP16WHB+JBylo4vOKPoZBlR94Z8xBxNBdNJA==", - "license": "MIT" - }, - "node_modules/@next/eslint-plugin-next": { - "version": "14.2.6", - "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-14.2.6.tgz", - "integrity": "sha512-d3+p4AjIYmhqzYHhhmkRYYN6ZU35TwZAKX08xKRfnHkz72KhWL2kxMFsDptpZs5e8bBGdepn7vn1+9DaF8iX+A==", - "dev": true, - "dependencies": { - "glob": "10.3.10" + "optionalDependencies": { + "@img/sharp-libvips-darwin-x64": "1.2.0" } }, - "node_modules/@next/swc-darwin-arm64": { - "version": "14.2.26", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.2.26.tgz", - "integrity": "sha512-zDJY8gsKEseGAxG+C2hTMT0w9Nk9N1Sk1qV7vXYz9MEiyRoF5ogQX2+vplyUMIfygnjn9/A04I6yrUTRTuRiyQ==", + "node_modules/@img/sharp-libvips-darwin-arm64": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.2.0.tgz", + "integrity": "sha512-sBZmpwmxqwlqG9ueWFXtockhsxefaV6O84BMOrhtg/YqbTaRdqDE7hxraVE3y6gVM4eExmfzW4a8el9ArLeEiQ==", "cpu": [ "arm64" ], - "license": "MIT", + "license": "LGPL-3.0-or-later", "optional": true, "os": [ "darwin" ], - "engines": { - "node": ">= 10" + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@next/swc-darwin-x64": { - "version": "14.2.26", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-14.2.26.tgz", - "integrity": "sha512-U0adH5ryLfmTDkahLwG9sUQG2L0a9rYux8crQeC92rPhi3jGQEY47nByQHrVrt3prZigadwj/2HZ1LUUimuSbg==", + "node_modules/@img/sharp-libvips-darwin-x64": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.2.0.tgz", + "integrity": "sha512-M64XVuL94OgiNHa5/m2YvEQI5q2cl9d/wk0qFTDVXcYzi43lxuiFTftMR1tOnFQovVXNZJ5TURSDK2pNe9Yzqg==", "cpu": [ "x64" ], - "license": "MIT", + "license": "LGPL-3.0-or-later", "optional": true, "os": [ "darwin" ], - "engines": { - "node": ">= 10" + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@next/swc-linux-arm64-gnu": { - "version": "14.2.26", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.2.26.tgz", - "integrity": "sha512-SINMl1I7UhfHGM7SoRiw0AbwnLEMUnJ/3XXVmhyptzriHbWvPPbbm0OEVG24uUKhuS1t0nvN/DBvm5kz6ZIqpg==", + "node_modules/@img/sharp-libvips-linux-arm": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.2.0.tgz", + "integrity": "sha512-mWd2uWvDtL/nvIzThLq3fr2nnGfyr/XMXlq8ZJ9WMR6PXijHlC3ksp0IpuhK6bougvQrchUAfzRLnbsen0Cqvw==", "cpu": [ - "arm64" + "arm" ], - "license": "MIT", + "license": "LGPL-3.0-or-later", "optional": true, "os": [ "linux" ], - "engines": { - "node": ">= 10" + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@next/swc-linux-arm64-musl": { - "version": "14.2.26", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.2.26.tgz", - "integrity": "sha512-s6JaezoyJK2DxrwHWxLWtJKlqKqTdi/zaYigDXUJ/gmx/72CrzdVZfMvUc6VqnZ7YEvRijvYo+0o4Z9DencduA==", + "node_modules/@img/sharp-libvips-linux-arm64": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.2.0.tgz", + "integrity": "sha512-RXwd0CgG+uPRX5YYrkzKyalt2OJYRiJQ8ED/fi1tq9WQW2jsQIn0tqrlR5l5dr/rjqq6AHAxURhj2DVjyQWSOA==", "cpu": [ "arm64" ], - "license": "MIT", + "license": "LGPL-3.0-or-later", "optional": true, "os": [ "linux" ], - "engines": { - "node": ">= 10" + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@next/swc-linux-x64-gnu": { - "version": "14.2.26", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.2.26.tgz", - "integrity": "sha512-FEXeUQi8/pLr/XI0hKbe0tgbLmHFRhgXOUiPScz2hk0hSmbGiU8aUqVslj/6C6KA38RzXnWoJXo4FMo6aBxjzg==", + "node_modules/@img/sharp-libvips-linux-ppc64": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.2.0.tgz", + "integrity": "sha512-Xod/7KaDDHkYu2phxxfeEPXfVXFKx70EAFZ0qyUdOjCcxbjqyJOEUpDe6RIyaunGxT34Anf9ue/wuWOqBW2WcQ==", "cpu": [ - "x64" + "ppc64" ], - "license": "MIT", + "license": "LGPL-3.0-or-later", "optional": true, "os": [ "linux" ], - "engines": { - "node": ">= 10" + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@next/swc-linux-x64-musl": { - "version": "14.2.26", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.2.26.tgz", - "integrity": "sha512-BUsomaO4d2DuXhXhgQCVt2jjX4B4/Thts8nDoIruEJkhE5ifeQFtvW5c9JkdOtYvE5p2G0hcwQ0UbRaQmQwaVg==", + "node_modules/@img/sharp-libvips-linux-s390x": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.2.0.tgz", + "integrity": "sha512-eMKfzDxLGT8mnmPJTNMcjfO33fLiTDsrMlUVcp6b96ETbnJmd4uvZxVJSKPQfS+odwfVaGifhsB07J1LynFehw==", + "cpu": [ + "s390x" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-x64": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.2.0.tgz", + "integrity": "sha512-ZW3FPWIc7K1sH9E3nxIGB3y3dZkpJlMnkk7z5tu1nSkBoCgw2nSRTFHI5pB/3CQaJM0pdzMF3paf9ckKMSE9Tg==", "cpu": [ "x64" ], - "license": "MIT", + "license": "LGPL-3.0-or-later", "optional": true, "os": [ "linux" ], - "engines": { - "node": ">= 10" + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@next/swc-win32-arm64-msvc": { - "version": "14.2.26", - "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.2.26.tgz", - "integrity": "sha512-5auwsMVzT7wbB2CZXQxDctpWbdEnEW/e66DyXO1DcgHxIyhP06awu+rHKshZE+lPLIGiwtjo7bsyeuubewwxMw==", + "node_modules/@img/sharp-libvips-linuxmusl-arm64": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.2.0.tgz", + "integrity": "sha512-UG+LqQJbf5VJ8NWJ5Z3tdIe/HXjuIdo4JeVNADXBFuG7z9zjoegpzzGIyV5zQKi4zaJjnAd2+g2nna8TZvuW9Q==", "cpu": [ "arm64" ], - "license": "MIT", + "license": "LGPL-3.0-or-later", "optional": true, "os": [ - "win32" + "linux" ], - "engines": { - "node": ">= 10" + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@next/swc-win32-ia32-msvc": { - "version": "14.2.26", - "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.2.26.tgz", - "integrity": "sha512-GQWg/Vbz9zUGi9X80lOeGsz1rMH/MtFO/XqigDznhhhTfDlDoynCM6982mPCbSlxJ/aveZcKtTlwfAjwhyxDpg==", + "node_modules/@img/sharp-libvips-linuxmusl-x64": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.2.0.tgz", + "integrity": "sha512-SRYOLR7CXPgNze8akZwjoGBoN1ThNZoqpOgfnOxmWsklTGVfJiGJoC/Lod7aNMGA1jSsKWM1+HRX43OP6p9+6Q==", "cpu": [ - "ia32" + "x64" ], - "license": "MIT", + "license": "LGPL-3.0-or-later", "optional": true, "os": [ - "win32" + "linux" ], - "engines": { - "node": ">= 10" + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@next/swc-win32-x64-msvc": { - "version": "14.2.26", - "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.2.26.tgz", - "integrity": "sha512-2rdB3T1/Gp7bv1eQTTm9d1Y1sv9UuJ2LAwOE0Pe2prHKe32UNscj7YS13fRB37d0GAiGNR+Y7ZcW8YjDI8Ns0w==", + "node_modules/@img/sharp-linux-arm": { + "version": "0.34.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.3.tgz", + "integrity": "sha512-oBK9l+h6KBN0i3dC8rYntLiVfW8D8wH+NPNT3O/WBHeW0OQWCjfWksLUaPidsrDKpJgXp3G3/hkmhptAW0I3+A==", "cpu": [ - "x64" + "arm" ], - "license": "MIT", + "license": "Apache-2.0", "optional": true, "os": [ - "win32" + "linux" ], "engines": { - "node": ">= 10" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm": "1.2.0" } }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, + "node_modules/@img/sharp-linux-arm64": { + "version": "0.34.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.3.tgz", + "integrity": "sha512-QdrKe3EvQrqwkDrtuTIjI0bu6YEJHTgEeqdzI3uWJOH6G1O8Nl1iEeVYRGdj1h5I21CqxSvQp1Yv7xeU3ZewbA==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">= 8" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm64": "1.2.0" } }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "node_modules/@img/sharp-linux-ppc64": { + "version": "0.34.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.34.3.tgz", + "integrity": "sha512-GLtbLQMCNC5nxuImPR2+RgrviwKwVql28FWZIW1zWruy6zLgA5/x2ZXk3mxj58X/tszVF69KK0Is83V8YgWhLA==", + "cpu": [ + "ppc64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">= 8" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-ppc64": "1.2.0" } }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, + "node_modules/@img/sharp-linux-s390x": { + "version": "0.34.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.3.tgz", + "integrity": "sha512-3gahT+A6c4cdc2edhsLHmIOXMb17ltffJlxR0aC2VPZfwKoTGZec6u5GrFgdR7ciJSsHT27BD3TIuGcuRT0KmQ==", + "cpu": [ + "s390x" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">= 8" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-s390x": "1.2.0" } }, - "node_modules/@pkgjs/parseargs": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", - "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "node_modules/@img/sharp-linux-x64": { + "version": "0.34.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.3.tgz", + "integrity": "sha512-8kYso8d806ypnSq3/Ly0QEw90V5ZoHh10yH0HnrzOCr6DKAPI6QVHvwleqMkVQ0m+fc7EH8ah0BB0QPuWY6zJQ==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0", "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=14" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-x64": "1.2.0" } }, - "node_modules/@radix-ui/number": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/number/-/number-1.1.0.tgz", - "integrity": "sha512-V3gRzhVNU1ldS5XhAPTom1fOIo4ccrjjJgmE+LI2h/WaFpHmx0MQApT+KZHnx8abG6Avtfcz4WoEciMnpFT3HQ==" - }, - "node_modules/@radix-ui/primitive": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.0.tgz", - "integrity": "sha512-4Z8dn6Upk0qk4P74xBhZ6Hd/w0mPEzOOLxy4xiPXOXqjF7jZS0VAKk7/x/H6FyY2zCkYJqePf1G5KmkmNJ4RBA==" - }, - "node_modules/@radix-ui/react-arrow": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.1.0.tgz", - "integrity": "sha512-FmlW1rCg7hBpEBwFbjHwCW6AmWLQM6g/v0Sn8XbP9NvmSZ2San1FpQeyPtufzOMSIx7Y4dzjlHoifhp+7NkZhw==", - "dependencies": { - "@radix-ui/react-primitive": "2.0.0" + "node_modules/@img/sharp-linuxmusl-arm64": { + "version": "0.34.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.3.tgz", + "integrity": "sha512-vAjbHDlr4izEiXM1OTggpCcPg9tn4YriK5vAjowJsHwdBIdx0fYRsURkxLG2RLm9gyBq66gwtWI8Gx0/ov+JKQ==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "funding": { + "url": "https://opencollective.com/libvips" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-arm64": "1.2.0" } }, - "node_modules/@radix-ui/react-collapsible": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-collapsible/-/react-collapsible-1.1.0.tgz", - "integrity": "sha512-zQY7Epa8sTL0mq4ajSJpjgn2YmCgyrG7RsQgLp3C0LQVkG7+Tf6Pv1CeNWZLyqMjhdPkBa5Lx7wYBeSu7uCSTA==", - "dependencies": { - "@radix-ui/primitive": "1.1.0", - "@radix-ui/react-compose-refs": "1.1.0", - "@radix-ui/react-context": "1.1.0", - "@radix-ui/react-id": "1.1.0", - "@radix-ui/react-presence": "1.1.0", - "@radix-ui/react-primitive": "2.0.0", - "@radix-ui/react-use-controllable-state": "1.1.0", - "@radix-ui/react-use-layout-effect": "1.1.0" + "node_modules/@img/sharp-linuxmusl-x64": { + "version": "0.34.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.3.tgz", + "integrity": "sha512-gCWUn9547K5bwvOn9l5XGAEjVTTRji4aPTqLzGXHvIr6bIDZKNTA34seMPgM0WmSf+RYBH411VavCejp3PkOeQ==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "funding": { + "url": "https://opencollective.com/libvips" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-x64": "1.2.0" } }, - "node_modules/@radix-ui/react-collection": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.1.0.tgz", - "integrity": "sha512-GZsZslMJEyo1VKm5L1ZJY8tGDxZNPAoUeQUIbKeJfoi7Q4kmig5AsgLMYYuyYbfjd8fBmFORAIwYAkXMnXZgZw==", + "node_modules/@img/sharp-wasm32": { + "version": "0.34.3", + "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.34.3.tgz", + "integrity": "sha512-+CyRcpagHMGteySaWos8IbnXcHgfDn7pO2fiC2slJxvNq9gDipYBN42/RagzctVRKgxATmfqOSulgZv5e1RdMg==", + "cpu": [ + "wasm32" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", + "optional": true, "dependencies": { - "@radix-ui/react-compose-refs": "1.1.0", - "@radix-ui/react-context": "1.1.0", - "@radix-ui/react-primitive": "2.0.0", - "@radix-ui/react-slot": "1.1.0" + "@emnapi/runtime": "^1.4.4" }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@radix-ui/react-compose-refs": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.0.tgz", - "integrity": "sha512-b4inOtiaOnYf9KWyO3jAeeCG6FeyfY6ldiEPanbUjWd+xIk5wZeHa8yVwmrJ2vderhu/BQvzCrJI0lHd+wIiqw==", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "node_modules/@img/sharp-win32-arm64": { + "version": "0.34.3", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.34.3.tgz", + "integrity": "sha512-MjnHPnbqMXNC2UgeLJtX4XqoVHHlZNd+nPt1kRPmj63wURegwBhZlApELdtxM2OIZDRv/DFtLcNhVbd1z8GYXQ==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@radix-ui/react-context": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.0.tgz", - "integrity": "sha512-OKrckBy+sMEgYM/sMmqmErVn0kZqrHPJze+Ql3DzYsDDp0hl0L62nx/2122/Bvps1qz645jlcu2tD9lrRSdf8A==", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "node_modules/@img/sharp-win32-ia32": { + "version": "0.34.3", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.3.tgz", + "integrity": "sha512-xuCdhH44WxuXgOM714hn4amodJMZl3OEvf0GVTm0BEyMeA2to+8HEdRPShH0SLYptJY1uBw+SCFP9WVQi1Q/cw==", + "cpu": [ + "ia32" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@radix-ui/react-dialog": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.1.14.tgz", - "integrity": "sha512-+CpweKjqpzTmwRwcYECQcNYbI8V9VSQt0SNFKeEBLgfucbsLssU6Ppq7wUdNXEGb573bMjFhVjKVll8rmV6zMw==", - "license": "MIT", - "dependencies": { - "@radix-ui/primitive": "1.1.2", - "@radix-ui/react-compose-refs": "1.1.2", - "@radix-ui/react-context": "1.1.2", - "@radix-ui/react-dismissable-layer": "1.1.10", - "@radix-ui/react-focus-guards": "1.1.2", - "@radix-ui/react-focus-scope": "1.1.7", - "@radix-ui/react-id": "1.1.1", - "@radix-ui/react-portal": "1.1.9", - "@radix-ui/react-presence": "1.1.4", - "@radix-ui/react-primitive": "2.1.3", - "@radix-ui/react-slot": "1.2.3", - "@radix-ui/react-use-controllable-state": "1.2.2", - "aria-hidden": "^1.2.4", - "react-remove-scroll": "^2.6.3" + "node_modules/@img/sharp-win32-x64": { + "version": "0.34.3", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.3.tgz", + "integrity": "sha512-OWwz05d++TxzLEv4VnsTz5CmZ6mI6S05sfQGEMrNrQcOEERbX46332IvE7pO/EUiw7jUrrS40z/M7kPyjfl04g==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/primitive": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.2.tgz", - "integrity": "sha512-XnbHrrprsNqZKQhStrSwgRUQzoCI1glLzdw79xiZPoofhGICeZRSQ3dIxAKH1gb3OHfNf4d6f+vAv3kil2eggA==", - "license": "MIT" - }, - "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-compose-refs": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.2.tgz", - "integrity": "sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg==", - "license": "MIT", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-context": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.2.tgz", - "integrity": "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==", - "license": "MIT", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "license": "ISC", + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "engines": { + "node": ">=12" } }, - "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-dismissable-layer": { - "version": "1.1.10", - "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.10.tgz", - "integrity": "sha512-IM1zzRV4W3HtVgftdQiiOmA0AdJlCtMLe00FXaHwgt3rAnNsIyDqshvkIW3hj/iu5hu8ERP7KIYki6NkqDxAwQ==", + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.12", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.12.tgz", + "integrity": "sha512-OuLGC46TjB5BbN1dH8JULVVZY4WTdkF7tV9Ys6wLL1rubZnCMstOhNHueU5bLCrnRuDhKPDM4g6sw4Bel5Gzqg==", "license": "MIT", "dependencies": { - "@radix-ui/primitive": "1.1.2", - "@radix-ui/react-compose-refs": "1.1.2", - "@radix-ui/react-primitive": "2.1.3", - "@radix-ui/react-use-callback-ref": "1.1.1", - "@radix-ui/react-use-escape-keydown": "1.1.1" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" } }, - "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-focus-guards": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.2.tgz", - "integrity": "sha512-fyjAACV62oPV925xFCrH8DR5xWhg9KYtJT4s3u54jxp+L/hbpTY2kIeEFFbFe+a/HCE94zGQMZLIpVTPVZDhaA==", - "license": "MIT", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "engines": { + "node": ">=6.0.0" } }, - "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-focus-scope": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.7.tgz", - "integrity": "sha512-t2ODlkXBQyn7jkl6TNaw/MtVEVvIGelJDCG41Okq/KwUsJBwQ4XVZsHAVUkK4mBv3ewiAS3PGuUWuY2BoK4ZUw==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-compose-refs": "1.1.2", - "@radix-ui/react-primitive": "2.1.3", - "@radix-ui/react-use-callback-ref": "1.1.1" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.4.tgz", + "integrity": "sha512-VT2+G1VQs/9oz078bLrYbecdZKs912zQlkelYpuf+SXF+QvZDYJlbx/LSx+meSAwdDFnF8FVXW92AVjjkVmgFw==", + "license": "MIT" }, - "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-id": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.1.1.tgz", - "integrity": "sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg==", + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.29", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.29.tgz", + "integrity": "sha512-uw6guiW/gcAGPDhLmd77/6lW8QLeiV5RUTsAX46Db6oLhGaVj4lhnPwb184s1bkc8kdVg/+h988dro8GRDpmYQ==", "license": "MIT", "dependencies": { - "@radix-ui/react-use-layout-effect": "1.1.1" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" } }, - "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-portal": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.9.tgz", - "integrity": "sha512-bpIxvq03if6UNwXZ+HTK71JLh4APvnXntDc6XOX8UVq4XQOVl7lwok0AvIl+b8zgCw3fSaVTZMpAPPagXbKmHQ==", - "license": "MIT", + "node_modules/@mdx-js/mdx": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@mdx-js/mdx/-/mdx-3.0.1.tgz", + "integrity": "sha512-eIQ4QTrOWyL3LWEe/bu6Taqzq2HQvHcyTMaOrI95P2/LmJE7AsfPfgJGuFLPVqBUE1BC1rik3VIhU+s9u72arA==", "dependencies": { - "@radix-ui/react-primitive": "2.1.3", - "@radix-ui/react-use-layout-effect": "1.1.1" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "@types/estree": "^1.0.0", + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdx": "^2.0.0", + "collapse-white-space": "^2.0.0", + "devlop": "^1.0.0", + "estree-util-build-jsx": "^3.0.0", + "estree-util-is-identifier-name": "^3.0.0", + "estree-util-to-js": "^2.0.0", + "estree-walker": "^3.0.0", + "hast-util-to-estree": "^3.0.0", + "hast-util-to-jsx-runtime": "^2.0.0", + "markdown-extensions": "^2.0.0", + "periscopic": "^3.0.0", + "remark-mdx": "^3.0.0", + "remark-parse": "^11.0.0", + "remark-rehype": "^11.0.0", + "source-map": "^0.7.0", + "unified": "^11.0.0", + "unist-util-position-from-estree": "^2.0.0", + "unist-util-stringify-position": "^4.0.0", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.0" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-presence": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.4.tgz", - "integrity": "sha512-ueDqRbdc4/bkaQT3GIpLQssRlFgWaL/U2z/S31qRwwLWoxHLgry3SIfCwhxeQNbirEUXFa+lq3RL3oBYXtcmIA==", - "license": "MIT", + "node_modules/@mdx-js/react": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@mdx-js/react/-/react-3.0.1.tgz", + "integrity": "sha512-9ZrPIU4MGf6et1m1ov3zKf+q9+deetI51zprKB1D/z3NOb+rUxxtEl3mCjW5wTGh6VhRdwPueh1oRzi6ezkA8A==", "dependencies": { - "@radix-ui/react-compose-refs": "1.1.2", - "@radix-ui/react-use-layout-effect": "1.1.1" + "@types/mdx": "^2.0.0" }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } + "peerDependencies": { + "@types/react": ">=16", + "react": ">=16" } }, - "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-primitive": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", - "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", + "node_modules/@napi-rs/wasm-runtime": { + "version": "0.2.12", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.12.tgz", + "integrity": "sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==", + "dev": true, "license": "MIT", + "optional": true, "dependencies": { - "@radix-ui/react-slot": "1.2.3" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } + "@emnapi/core": "^1.4.3", + "@emnapi/runtime": "^1.4.3", + "@tybys/wasm-util": "^0.10.0" } }, - "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-slot": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", - "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", + "node_modules/@next/env": { + "version": "15.4.6", + "resolved": "https://registry.npmjs.org/@next/env/-/env-15.4.6.tgz", + "integrity": "sha512-yHDKVTcHrZy/8TWhj0B23ylKv5ypocuCwey9ZqPyv4rPdUdRzpGCkSi03t04KBPyU96kxVtUqx6O3nE1kpxASQ==", + "license": "MIT" + }, + "node_modules/@next/eslint-plugin-next": { + "version": "15.4.6", + "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-15.4.6.tgz", + "integrity": "sha512-2NOu3ln+BTcpnbIDuxx6MNq+pRrCyey4WSXGaJIyt0D2TYicHeO9QrUENNjcf673n3B1s7hsiV5xBYRCK1Q8kA==", + "dev": true, "license": "MIT", "dependencies": { - "@radix-ui/react-compose-refs": "1.1.2" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "fast-glob": "3.3.1" } }, - "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-use-callback-ref": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.1.tgz", - "integrity": "sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg==", + "node_modules/@next/swc-darwin-arm64": { + "version": "15.4.6", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-15.4.6.tgz", + "integrity": "sha512-667R0RTP4DwxzmrqTs4Lr5dcEda9OxuZsVFsjVtxVMVhzSpo6nLclXejJVfQo2/g7/Z9qF3ETDmN3h65mTjpTQ==", + "cpu": [ + "arm64" + ], "license": "MIT", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" } }, - "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-use-controllable-state": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.2.2.tgz", - "integrity": "sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg==", + "node_modules/@next/swc-darwin-x64": { + "version": "15.4.6", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-15.4.6.tgz", + "integrity": "sha512-KMSFoistFkaiQYVQQnaU9MPWtp/3m0kn2Xed1Ces5ll+ag1+rlac20sxG+MqhH2qYWX1O2GFOATQXEyxKiIscg==", + "cpu": [ + "x64" + ], "license": "MIT", - "dependencies": { - "@radix-ui/react-use-effect-event": "0.0.2", - "@radix-ui/react-use-layout-effect": "1.1.1" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" } }, - "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-use-escape-keydown": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.1.1.tgz", - "integrity": "sha512-Il0+boE7w/XebUHyBjroE+DbByORGR9KKmITzbR7MyQ4akpORYP/ZmbhAr0DG7RmmBqoOnZdy2QlvajJ2QA59g==", + "node_modules/@next/swc-linux-arm64-gnu": { + "version": "15.4.6", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-15.4.6.tgz", + "integrity": "sha512-PnOx1YdO0W7m/HWFeYd2A6JtBO8O8Eb9h6nfJia2Dw1sRHoHpNf6lN1U4GKFRzRDBi9Nq2GrHk9PF3Vmwf7XVw==", + "cpu": [ + "arm64" + ], "license": "MIT", - "dependencies": { - "@radix-ui/react-use-callback-ref": "1.1.1" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" } }, - "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-use-layout-effect": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.1.tgz", - "integrity": "sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ==", + "node_modules/@next/swc-linux-arm64-musl": { + "version": "15.4.6", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-15.4.6.tgz", + "integrity": "sha512-XBbuQddtY1p5FGPc2naMO0kqs4YYtLYK/8aPausI5lyOjr4J77KTG9mtlU4P3NwkLI1+OjsPzKVvSJdMs3cFaw==", + "cpu": [ + "arm64" + ], "license": "MIT", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" } }, - "node_modules/@radix-ui/react-dialog/node_modules/react-remove-scroll": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.7.1.tgz", - "integrity": "sha512-HpMh8+oahmIdOuS5aFKKY6Pyog+FNaZV/XyJOq7b4YFwsFHe5yYfdbIalI4k3vU2nSDql7YskmUseHsRrJqIPA==", + "node_modules/@next/swc-linux-x64-gnu": { + "version": "15.4.6", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-15.4.6.tgz", + "integrity": "sha512-+WTeK7Qdw82ez3U9JgD+igBAP75gqZ1vbK6R8PlEEuY0OIe5FuYXA4aTjL811kWPf7hNeslD4hHK2WoM9W0IgA==", + "cpu": [ + "x64" + ], "license": "MIT", - "dependencies": { - "react-remove-scroll-bar": "^2.3.7", - "react-style-singleton": "^2.2.3", - "tslib": "^2.1.0", - "use-callback-ref": "^1.3.3", - "use-sidecar": "^1.1.3" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=10" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "node": ">= 10" } }, - "node_modules/@radix-ui/react-direction": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.1.0.tgz", - "integrity": "sha512-BUuBvgThEiAXh2DWu93XsT+a3aWrGqolGlqqw5VU1kG7p/ZH2cuDlM1sRLNnY3QcBS69UIz2mcKhMxDsdewhjg==", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "node_modules/@next/swc-linux-x64-musl": { + "version": "15.4.6", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-15.4.6.tgz", + "integrity": "sha512-XP824mCbgQsK20jlXKrUpZoh/iO3vUWhMpxCz8oYeagoiZ4V0TQiKy0ASji1KK6IAe3DYGfj5RfKP6+L2020OQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" } }, - "node_modules/@radix-ui/react-dismissable-layer": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.0.tgz", - "integrity": "sha512-/UovfmmXGptwGcBQawLzvn2jOfM0t4z3/uKffoBlj724+n3FvBbZ7M0aaBOmkp6pqFYpO4yx8tSVJjx3Fl2jig==", - "dependencies": { - "@radix-ui/primitive": "1.1.0", - "@radix-ui/react-compose-refs": "1.1.0", - "@radix-ui/react-primitive": "2.0.0", - "@radix-ui/react-use-callback-ref": "1.1.0", - "@radix-ui/react-use-escape-keydown": "1.1.0" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } + "node_modules/@next/swc-win32-arm64-msvc": { + "version": "15.4.6", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-15.4.6.tgz", + "integrity": "sha512-FxrsenhUz0LbgRkNWx6FRRJIPe/MI1JRA4W4EPd5leXO00AZ6YU8v5vfx4MDXTvN77lM/EqsE3+6d2CIeF5NYg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" } }, - "node_modules/@radix-ui/react-dropdown-menu": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-dropdown-menu/-/react-dropdown-menu-2.1.1.tgz", - "integrity": "sha512-y8E+x9fBq9qvteD2Zwa4397pUVhYsh9iq44b5RD5qu1GMJWBCBuVg1hMyItbc6+zH00TxGRqd9Iot4wzf3OoBQ==", + "node_modules/@next/swc-win32-x64-msvc": { + "version": "15.4.6", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-15.4.6.tgz", + "integrity": "sha512-T4ufqnZ4u88ZheczkBTtOF+eKaM14V8kbjud/XrAakoM5DKQWjW09vD6B9fsdsWS2T7D5EY31hRHdta7QKWOng==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "license": "MIT", "dependencies": { - "@radix-ui/primitive": "1.1.0", - "@radix-ui/react-compose-refs": "1.1.0", - "@radix-ui/react-context": "1.1.0", - "@radix-ui/react-id": "1.1.0", - "@radix-ui/react-menu": "2.1.1", - "@radix-ui/react-primitive": "2.0.0", - "@radix-ui/react-use-controllable-state": "1.1.0" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } + "engines": { + "node": ">= 8" } }, - "node_modules/@radix-ui/react-focus-guards": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.0.tgz", - "integrity": "sha512-w6XZNUPVv6xCpZUqb/yN9DL6auvpGX3C/ee6Hdi16v2UUy25HV2Q5bcflsiDyT/g5RwbPQ/GIT1vLkeRb+ITBw==", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "license": "MIT", + "engines": { + "node": ">= 8" } }, - "node_modules/@radix-ui/react-focus-scope": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.0.tgz", - "integrity": "sha512-200UD8zylvEyL8Bx+z76RJnASR2gRMuxlgFCPAe/Q/679a/r0eK3MBVYMb7vZODZcffZBdob1EGnky78xmVvcA==", + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "license": "MIT", "dependencies": { - "@radix-ui/react-compose-refs": "1.1.0", - "@radix-ui/react-primitive": "2.0.0", - "@radix-ui/react-use-callback-ref": "1.1.0" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } + "engines": { + "node": ">= 8" } }, - "node_modules/@radix-ui/react-id": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.1.0.tgz", - "integrity": "sha512-EJUrI8yYh7WOjNOqpoJaf1jlFIH2LvtgAl+YcFqNCa+4hj64ZXmPkAKOFs/ukjz3byN6bdb/AVUqHkI8/uWWMA==", - "dependencies": { - "@radix-ui/react-use-layout-effect": "1.1.0" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "node_modules/@nolyfill/is-core-module": { + "version": "1.0.39", + "resolved": "https://registry.npmjs.org/@nolyfill/is-core-module/-/is-core-module-1.0.39.tgz", + "integrity": "sha512-nn5ozdjYQpUCZlWGuxcJY/KpxkWQs4DcbMCmKojjyrYDEAGy4Ce19NN4v5MduafTwJlbKc99UA8YhSVqq9yPZA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.4.0" } }, - "node_modules/@radix-ui/react-menu": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-menu/-/react-menu-2.1.1.tgz", - "integrity": "sha512-oa3mXRRVjHi6DZu/ghuzdylyjaMXLymx83irM7hTxutQbD+7IhPKdMdRHD26Rm+kHRrWcrUkkRPv5pd47a2xFQ==", - "dependencies": { - "@radix-ui/primitive": "1.1.0", - "@radix-ui/react-collection": "1.1.0", - "@radix-ui/react-compose-refs": "1.1.0", - "@radix-ui/react-context": "1.1.0", - "@radix-ui/react-direction": "1.1.0", - "@radix-ui/react-dismissable-layer": "1.1.0", - "@radix-ui/react-focus-guards": "1.1.0", - "@radix-ui/react-focus-scope": "1.1.0", - "@radix-ui/react-id": "1.1.0", - "@radix-ui/react-popper": "1.2.0", - "@radix-ui/react-portal": "1.1.1", - "@radix-ui/react-presence": "1.1.0", - "@radix-ui/react-primitive": "2.0.0", - "@radix-ui/react-roving-focus": "1.1.0", - "@radix-ui/react-slot": "1.1.0", - "@radix-ui/react-use-callback-ref": "1.1.0", - "aria-hidden": "^1.1.1", - "react-remove-scroll": "2.5.7" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=14" } }, - "node_modules/@radix-ui/react-popper": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.2.0.tgz", - "integrity": "sha512-ZnRMshKF43aBxVWPWvbj21+7TQCvhuULWJ4gNIKYpRlQt5xGRhLx66tMp8pya2UkGHTSlhpXwmjqltDYHhw7Vg==", + "node_modules/@radix-ui/number": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/number/-/number-1.1.1.tgz", + "integrity": "sha512-MkKCwxlXTgz6CFoJx3pCwn07GKp36+aZyu/u2Ln2VrA5DcdyCZkASEDBTd8x5whTQQL5CiYf4prXKLcgQdv29g==", + "license": "MIT" + }, + "node_modules/@radix-ui/primitive": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.2.tgz", + "integrity": "sha512-XnbHrrprsNqZKQhStrSwgRUQzoCI1glLzdw79xiZPoofhGICeZRSQ3dIxAKH1gb3OHfNf4d6f+vAv3kil2eggA==", + "license": "MIT" + }, + "node_modules/@radix-ui/react-arrow": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.1.7.tgz", + "integrity": "sha512-F+M1tLhO+mlQaOWspE8Wstg+z6PwxwRd8oQ8IXceWz92kfAmalTRf0EjrouQeo7QssEPfCn05B4Ihs1K9WQ/7w==", + "license": "MIT", "dependencies": { - "@floating-ui/react-dom": "^2.0.0", - "@radix-ui/react-arrow": "1.1.0", - "@radix-ui/react-compose-refs": "1.1.0", - "@radix-ui/react-context": "1.1.0", - "@radix-ui/react-primitive": "2.0.0", - "@radix-ui/react-use-callback-ref": "1.1.0", - "@radix-ui/react-use-layout-effect": "1.1.0", - "@radix-ui/react-use-rect": "1.1.0", - "@radix-ui/react-use-size": "1.1.0", - "@radix-ui/rect": "1.1.0" + "@radix-ui/react-primitive": "2.1.3" }, "peerDependencies": { "@types/react": "*", @@ -1745,13 +1661,20 @@ } } }, - "node_modules/@radix-ui/react-portal": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.1.tgz", - "integrity": "sha512-A3UtLk85UtqhzFqtoC8Q0KvR2GbXF3mtPgACSazajqq6A41mEQgo53iPzY4i6BwDxlIFqWIhiQ2G729n+2aw/g==", + "node_modules/@radix-ui/react-collapsible": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/@radix-ui/react-collapsible/-/react-collapsible-1.1.11.tgz", + "integrity": "sha512-2qrRsVGSCYasSz1RFOorXwl0H7g7J1frQtgpQgYrt+MOidtPAINHn9CPovQXb83r8ahapdx3Tu0fa/pdFFSdPg==", + "license": "MIT", "dependencies": { - "@radix-ui/react-primitive": "2.0.0", - "@radix-ui/react-use-layout-effect": "1.1.0" + "@radix-ui/primitive": "1.1.2", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-presence": "1.1.4", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-controllable-state": "1.2.2", + "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", @@ -1768,13 +1691,16 @@ } } }, - "node_modules/@radix-ui/react-presence": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.0.tgz", - "integrity": "sha512-Gq6wuRN/asf9H/E/VzdKoUtT8GC9PQc9z40/vEr0VCJ4u5XvvhWIrSsCB6vD2/cH7ugTdSfYq9fLJCcM00acrQ==", + "node_modules/@radix-ui/react-collection": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.1.7.tgz", + "integrity": "sha512-Fh9rGN0MoI4ZFUNyfFVNU4y9LUz93u9/0K+yLgA2bwRojxM8JU1DyvvMBabnZPBgMWREAJvU2jjVzq+LrFUglw==", + "license": "MIT", "dependencies": { - "@radix-ui/react-compose-refs": "1.1.0", - "@radix-ui/react-use-layout-effect": "1.1.0" + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", @@ -1791,72 +1717,56 @@ } } }, - "node_modules/@radix-ui/react-primitive": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.0.0.tgz", - "integrity": "sha512-ZSpFm0/uHa8zTvKBDjLFWLo8dkr4MBsiDLz0g3gMUwqgLHz9rTaRRGYDgvZPtBJgYCBKXkS9fzmoySgr8CO6Cw==", - "dependencies": { - "@radix-ui/react-slot": "1.1.0" - }, + "node_modules/@radix-ui/react-compose-refs": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.2.tgz", + "integrity": "sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg==", + "license": "MIT", "peerDependencies": { "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "peerDependenciesMeta": { "@types/react": { "optional": true - }, - "@types/react-dom": { - "optional": true } } }, - "node_modules/@radix-ui/react-roving-focus": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.1.0.tgz", - "integrity": "sha512-EA6AMGeq9AEeQDeSH0aZgG198qkfHSbvWTf1HvoDmOB5bBG/qTxjYMWUKMnYiV6J/iP/J8MEFSuB2zRU2n7ODA==", - "dependencies": { - "@radix-ui/primitive": "1.1.0", - "@radix-ui/react-collection": "1.1.0", - "@radix-ui/react-compose-refs": "1.1.0", - "@radix-ui/react-context": "1.1.0", - "@radix-ui/react-direction": "1.1.0", - "@radix-ui/react-id": "1.1.0", - "@radix-ui/react-primitive": "2.0.0", - "@radix-ui/react-use-callback-ref": "1.1.0", - "@radix-ui/react-use-controllable-state": "1.1.0" - }, + "node_modules/@radix-ui/react-context": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.2.tgz", + "integrity": "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==", + "license": "MIT", "peerDependencies": { "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "peerDependenciesMeta": { "@types/react": { "optional": true - }, - "@types/react-dom": { - "optional": true } } }, - "node_modules/@radix-ui/react-scroll-area": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-scroll-area/-/react-scroll-area-1.1.0.tgz", - "integrity": "sha512-9ArIZ9HWhsrfqS765h+GZuLoxaRHD/j0ZWOWilsCvYTpYJp8XwCqNG7Dt9Nu/TItKOdgLGkOPCodQvDc+UMwYg==", - "dependencies": { - "@radix-ui/number": "1.1.0", - "@radix-ui/primitive": "1.1.0", - "@radix-ui/react-compose-refs": "1.1.0", - "@radix-ui/react-context": "1.1.0", - "@radix-ui/react-direction": "1.1.0", - "@radix-ui/react-presence": "1.1.0", - "@radix-ui/react-primitive": "2.0.0", - "@radix-ui/react-use-callback-ref": "1.1.0", - "@radix-ui/react-use-layout-effect": "1.1.0" + "node_modules/@radix-ui/react-dialog": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.1.14.tgz", + "integrity": "sha512-+CpweKjqpzTmwRwcYECQcNYbI8V9VSQt0SNFKeEBLgfucbsLssU6Ppq7wUdNXEGb573bMjFhVjKVll8rmV6zMw==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.2", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-dismissable-layer": "1.1.10", + "@radix-ui/react-focus-guards": "1.1.2", + "@radix-ui/react-focus-scope": "1.1.7", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-portal": "1.1.9", + "@radix-ui/react-presence": "1.1.4", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-slot": "1.2.3", + "@radix-ui/react-use-controllable-state": "1.2.2", + "aria-hidden": "^1.2.4", + "react-remove-scroll": "^2.6.3" }, "peerDependencies": { "@types/react": "*", @@ -1873,13 +1783,11 @@ } } }, - "node_modules/@radix-ui/react-slot": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.0.tgz", - "integrity": "sha512-FUCf5XMfmW4dtYl69pdS4DbxKy8nj4M7SafBgPllysxmdachynNflAdp/gCsnYWNDnge6tI9onzMp5ARYc1KNw==", - "dependencies": { - "@radix-ui/react-compose-refs": "1.1.0" - }, + "node_modules/@radix-ui/react-direction": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.1.1.tgz", + "integrity": "sha512-1UEWRX6jnOA2y4H5WczZ44gOOjTEmlqv1uNW4GAJEO5+bauCBhv8snY65Iw5/VOS/ghKN9gr2KjnLKxrsvoMVw==", + "license": "MIT", "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" @@ -1890,24 +1798,17 @@ } } }, - "node_modules/@radix-ui/react-tooltip": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/@radix-ui/react-tooltip/-/react-tooltip-1.2.7.tgz", - "integrity": "sha512-Ap+fNYwKTYJ9pzqW+Xe2HtMRbQ/EeWkj2qykZ6SuEV4iS/o1bZI5ssJbk4D2r8XuDuOBVz/tIx2JObtuqU+5Zw==", + "node_modules/@radix-ui/react-dismissable-layer": { + "version": "1.1.10", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.10.tgz", + "integrity": "sha512-IM1zzRV4W3HtVgftdQiiOmA0AdJlCtMLe00FXaHwgt3rAnNsIyDqshvkIW3hj/iu5hu8ERP7KIYki6NkqDxAwQ==", "license": "MIT", "dependencies": { "@radix-ui/primitive": "1.1.2", "@radix-ui/react-compose-refs": "1.1.2", - "@radix-ui/react-context": "1.1.2", - "@radix-ui/react-dismissable-layer": "1.1.10", - "@radix-ui/react-id": "1.1.1", - "@radix-ui/react-popper": "1.2.7", - "@radix-ui/react-portal": "1.1.9", - "@radix-ui/react-presence": "1.1.4", "@radix-ui/react-primitive": "2.1.3", - "@radix-ui/react-slot": "1.2.3", - "@radix-ui/react-use-controllable-state": "1.2.2", - "@radix-ui/react-visually-hidden": "1.2.3" + "@radix-ui/react-use-callback-ref": "1.1.1", + "@radix-ui/react-use-escape-keydown": "1.1.1" }, "peerDependencies": { "@types/react": "*", @@ -1924,19 +1825,19 @@ } } }, - "node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/primitive": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.2.tgz", - "integrity": "sha512-XnbHrrprsNqZKQhStrSwgRUQzoCI1glLzdw79xiZPoofhGICeZRSQ3dIxAKH1gb3OHfNf4d6f+vAv3kil2eggA==", - "license": "MIT" - }, - "node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-arrow": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.1.7.tgz", - "integrity": "sha512-F+M1tLhO+mlQaOWspE8Wstg+z6PwxwRd8oQ8IXceWz92kfAmalTRf0EjrouQeo7QssEPfCn05B4Ihs1K9WQ/7w==", + "node_modules/@radix-ui/react-dropdown-menu": { + "version": "2.1.15", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dropdown-menu/-/react-dropdown-menu-2.1.15.tgz", + "integrity": "sha512-mIBnOjgwo9AH3FyKaSWoSu/dYj6VdhJ7frEPiGTeXCdUFHjl9h3mFh2wwhEtINOmYXWhdpf1rY2minFsmaNgVQ==", "license": "MIT", "dependencies": { - "@radix-ui/react-primitive": "2.1.3" + "@radix-ui/primitive": "1.1.2", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-menu": "2.1.15", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-controllable-state": "1.2.2" }, "peerDependencies": { "@types/react": "*", @@ -1953,25 +1854,10 @@ } } }, - "node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-compose-refs": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.2.tgz", - "integrity": "sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg==", - "license": "MIT", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-context": { + "node_modules/@radix-ui/react-focus-guards": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.2.tgz", - "integrity": "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==", + "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.2.tgz", + "integrity": "sha512-fyjAACV62oPV925xFCrH8DR5xWhg9KYtJT4s3u54jxp+L/hbpTY2kIeEFFbFe+a/HCE94zGQMZLIpVTPVZDhaA==", "license": "MIT", "peerDependencies": { "@types/react": "*", @@ -1983,17 +1869,15 @@ } } }, - "node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-dismissable-layer": { - "version": "1.1.10", - "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.10.tgz", - "integrity": "sha512-IM1zzRV4W3HtVgftdQiiOmA0AdJlCtMLe00FXaHwgt3rAnNsIyDqshvkIW3hj/iu5hu8ERP7KIYki6NkqDxAwQ==", + "node_modules/@radix-ui/react-focus-scope": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.7.tgz", + "integrity": "sha512-t2ODlkXBQyn7jkl6TNaw/MtVEVvIGelJDCG41Okq/KwUsJBwQ4XVZsHAVUkK4mBv3ewiAS3PGuUWuY2BoK4ZUw==", "license": "MIT", "dependencies": { - "@radix-ui/primitive": "1.1.2", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-primitive": "2.1.3", - "@radix-ui/react-use-callback-ref": "1.1.1", - "@radix-ui/react-use-escape-keydown": "1.1.1" + "@radix-ui/react-use-callback-ref": "1.1.1" }, "peerDependencies": { "@types/react": "*", @@ -2010,7 +1894,7 @@ } } }, - "node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-id": { + "node_modules/@radix-ui/react-id": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.1.1.tgz", "integrity": "sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg==", @@ -2028,7 +1912,47 @@ } } }, - "node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-popper": { + "node_modules/@radix-ui/react-menu": { + "version": "2.1.15", + "resolved": "https://registry.npmjs.org/@radix-ui/react-menu/-/react-menu-2.1.15.tgz", + "integrity": "sha512-tVlmA3Vb9n8SZSd+YSbuFR66l87Wiy4du+YE+0hzKQEANA+7cWKH1WgqcEX4pXqxUFQKrWQGHdvEfw00TjFiew==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.2", + "@radix-ui/react-collection": "1.1.7", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-direction": "1.1.1", + "@radix-ui/react-dismissable-layer": "1.1.10", + "@radix-ui/react-focus-guards": "1.1.2", + "@radix-ui/react-focus-scope": "1.1.7", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-popper": "1.2.7", + "@radix-ui/react-portal": "1.1.9", + "@radix-ui/react-presence": "1.1.4", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-roving-focus": "1.1.10", + "@radix-ui/react-slot": "1.2.3", + "@radix-ui/react-use-callback-ref": "1.1.1", + "aria-hidden": "^1.2.4", + "react-remove-scroll": "^2.6.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-popper": { "version": "1.2.7", "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.2.7.tgz", "integrity": "sha512-IUFAccz1JyKcf/RjB552PlWwxjeCJB8/4KxT7EhBHOJM+mN7LdW+B3kacJXILm32xawcMMjb2i0cIZpo+f9kiQ==", @@ -2060,7 +1984,7 @@ } } }, - "node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-portal": { + "node_modules/@radix-ui/react-portal": { "version": "1.1.9", "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.9.tgz", "integrity": "sha512-bpIxvq03if6UNwXZ+HTK71JLh4APvnXntDc6XOX8UVq4XQOVl7lwok0AvIl+b8zgCw3fSaVTZMpAPPagXbKmHQ==", @@ -2084,7 +2008,7 @@ } } }, - "node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-presence": { + "node_modules/@radix-ui/react-presence": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.4.tgz", "integrity": "sha512-ueDqRbdc4/bkaQT3GIpLQssRlFgWaL/U2z/S31qRwwLWoxHLgry3SIfCwhxeQNbirEUXFa+lq3RL3oBYXtcmIA==", @@ -2108,7 +2032,7 @@ } } }, - "node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-primitive": { + "node_modules/@radix-ui/react-primitive": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", @@ -2131,98 +2055,75 @@ } } }, - "node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-slot": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", - "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", + "node_modules/@radix-ui/react-roving-focus": { + "version": "1.1.10", + "resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.1.10.tgz", + "integrity": "sha512-dT9aOXUen9JSsxnMPv/0VqySQf5eDQ6LCk5Sw28kamz8wSOW2bJdlX2Bg5VUIIcV+6XlHpWTIuTPCf/UNIyq8Q==", "license": "MIT", "dependencies": { - "@radix-ui/react-compose-refs": "1.1.2" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "@radix-ui/primitive": "1.1.2", + "@radix-ui/react-collection": "1.1.7", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-direction": "1.1.1", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-callback-ref": "1.1.1", + "@radix-ui/react-use-controllable-state": "1.2.2" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-use-callback-ref": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.1.tgz", - "integrity": "sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg==", - "license": "MIT", "peerDependencies": { "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "peerDependenciesMeta": { "@types/react": { "optional": true - } - } - }, - "node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-use-controllable-state": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.2.2.tgz", - "integrity": "sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-use-effect-event": "0.0.2", - "@radix-ui/react-use-layout-effect": "1.1.1" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { + }, + "@types/react-dom": { "optional": true } } }, - "node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-use-escape-keydown": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.1.1.tgz", - "integrity": "sha512-Il0+boE7w/XebUHyBjroE+DbByORGR9KKmITzbR7MyQ4akpORYP/ZmbhAr0DG7RmmBqoOnZdy2QlvajJ2QA59g==", + "node_modules/@radix-ui/react-scroll-area": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/@radix-ui/react-scroll-area/-/react-scroll-area-1.2.9.tgz", + "integrity": "sha512-YSjEfBXnhUELsO2VzjdtYYD4CfQjvao+lhhrX5XsHD7/cyUNzljF1FHEbgTPN7LH2MClfwRMIsYlqTYpKTTe2A==", "license": "MIT", "dependencies": { - "@radix-ui/react-use-callback-ref": "1.1.1" + "@radix-ui/number": "1.1.1", + "@radix-ui/primitive": "1.1.2", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-direction": "1.1.1", + "@radix-ui/react-presence": "1.1.4", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-callback-ref": "1.1.1", + "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "peerDependenciesMeta": { "@types/react": { "optional": true - } - } - }, - "node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-use-layout-effect": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.1.tgz", - "integrity": "sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ==", - "license": "MIT", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { + }, + "@types/react-dom": { "optional": true } } }, - "node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-use-rect": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-rect/-/react-use-rect-1.1.1.tgz", - "integrity": "sha512-QTYuDesS0VtuHNNvMh+CjlKJ4LJickCMUAqjlE3+j8w+RlRpwyX3apEQKGFzbZGdo7XNG1tXa+bQqIE7HIXT2w==", + "node_modules/@radix-ui/react-slot": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", + "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", "license": "MIT", "dependencies": { - "@radix-ui/rect": "1.1.1" + "@radix-ui/react-compose-refs": "1.1.2" }, "peerDependencies": { "@types/react": "*", @@ -2234,34 +2135,45 @@ } } }, - "node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-use-size": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-size/-/react-use-size-1.1.1.tgz", - "integrity": "sha512-ewrXRDTAqAXlkl6t/fkXWNAhFX9I+CkKlw6zjEwk86RSPKwZr3xpBRso655aqYafwtnbpHLj6toFzmd6xdVptQ==", + "node_modules/@radix-ui/react-tooltip": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-tooltip/-/react-tooltip-1.2.7.tgz", + "integrity": "sha512-Ap+fNYwKTYJ9pzqW+Xe2HtMRbQ/EeWkj2qykZ6SuEV4iS/o1bZI5ssJbk4D2r8XuDuOBVz/tIx2JObtuqU+5Zw==", "license": "MIT", "dependencies": { - "@radix-ui/react-use-layout-effect": "1.1.1" + "@radix-ui/primitive": "1.1.2", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-dismissable-layer": "1.1.10", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-popper": "1.2.7", + "@radix-ui/react-portal": "1.1.9", + "@radix-ui/react-presence": "1.1.4", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-slot": "1.2.3", + "@radix-ui/react-use-controllable-state": "1.2.2", + "@radix-ui/react-visually-hidden": "1.2.3" }, "peerDependencies": { "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "peerDependenciesMeta": { "@types/react": { "optional": true + }, + "@types/react-dom": { + "optional": true } } }, - "node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/rect": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/rect/-/rect-1.1.1.tgz", - "integrity": "sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw==", - "license": "MIT" - }, "node_modules/@radix-ui/react-use-callback-ref": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.0.tgz", - "integrity": "sha512-CasTfvsy+frcFkbXtSJ2Zu9JHpN8TYKxkgJGWbjiZhFivxaeW7rMeZt7QELGVLaYVfFMsKHjb7Ak0nMEe+2Vfw==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.1.tgz", + "integrity": "sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg==", + "license": "MIT", "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" @@ -2273,11 +2185,13 @@ } }, "node_modules/@radix-ui/react-use-controllable-state": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.1.0.tgz", - "integrity": "sha512-MtfMVJiSr2NjzS0Aa90NPTnvTSg6C/JLCV7ma0W6+OMV78vd8OyRpID+Ng9LxzsPbLeuBnWBA1Nq30AtBIDChw==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.2.2.tgz", + "integrity": "sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg==", + "license": "MIT", "dependencies": { - "@radix-ui/react-use-callback-ref": "1.1.0" + "@radix-ui/react-use-effect-event": "0.0.2", + "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", @@ -2307,27 +2221,13 @@ } } }, - "node_modules/@radix-ui/react-use-effect-event/node_modules/@radix-ui/react-use-layout-effect": { + "node_modules/@radix-ui/react-use-escape-keydown": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.1.tgz", - "integrity": "sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ==", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.1.1.tgz", + "integrity": "sha512-Il0+boE7w/XebUHyBjroE+DbByORGR9KKmITzbR7MyQ4akpORYP/ZmbhAr0DG7RmmBqoOnZdy2QlvajJ2QA59g==", "license": "MIT", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-use-escape-keydown": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.1.0.tgz", - "integrity": "sha512-L7vwWlR1kTTQ3oh7g1O0CBF3YCyyTj8NmhLR+phShpyA50HCfBFKVJTpshm9PzLiKmehsrQzTYTpX9HvmC9rhw==", "dependencies": { - "@radix-ui/react-use-callback-ref": "1.1.0" + "@radix-ui/react-use-callback-ref": "1.1.1" }, "peerDependencies": { "@types/react": "*", @@ -2340,9 +2240,10 @@ } }, "node_modules/@radix-ui/react-use-layout-effect": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.0.tgz", - "integrity": "sha512-+FPE0rOdziWSrH9athwI1R0HDVbWlEhd+FR+aSDk4uWGmSJ9Z54sdZVDQPZAinJhJXwfT+qnj969mCsT2gfm5w==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.1.tgz", + "integrity": "sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ==", + "license": "MIT", "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" @@ -2354,11 +2255,12 @@ } }, "node_modules/@radix-ui/react-use-rect": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-rect/-/react-use-rect-1.1.0.tgz", - "integrity": "sha512-0Fmkebhr6PiseyZlYAOtLS+nb7jLmpqTrJyv61Pe68MKYW6OWdRE2kI70TaYY27u7H0lajqM3hSMMLFq18Z7nQ==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-rect/-/react-use-rect-1.1.1.tgz", + "integrity": "sha512-QTYuDesS0VtuHNNvMh+CjlKJ4LJickCMUAqjlE3+j8w+RlRpwyX3apEQKGFzbZGdo7XNG1tXa+bQqIE7HIXT2w==", + "license": "MIT", "dependencies": { - "@radix-ui/rect": "1.1.0" + "@radix-ui/rect": "1.1.1" }, "peerDependencies": { "@types/react": "*", @@ -2371,11 +2273,12 @@ } }, "node_modules/@radix-ui/react-use-size": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-size/-/react-use-size-1.1.0.tgz", - "integrity": "sha512-XW3/vWuIXHa+2Uwcc2ABSfcCledmXhhQPlGbfcRXbiUQI5Icjcg19BGCZVKKInYbvUCut/ufbbLLPFC5cbb1hw==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-size/-/react-use-size-1.1.1.tgz", + "integrity": "sha512-ewrXRDTAqAXlkl6t/fkXWNAhFX9I+CkKlw6zjEwk86RSPKwZr3xpBRso655aqYafwtnbpHLj6toFzmd6xdVptQ==", + "license": "MIT", "dependencies": { - "@radix-ui/react-use-layout-effect": "1.1.0" + "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", @@ -2410,66 +2313,11 @@ } } }, - "node_modules/@radix-ui/react-visually-hidden/node_modules/@radix-ui/react-compose-refs": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.2.tgz", - "integrity": "sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg==", - "license": "MIT", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-visually-hidden/node_modules/@radix-ui/react-primitive": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", - "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-slot": "1.2.3" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-visually-hidden/node_modules/@radix-ui/react-slot": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", - "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-compose-refs": "1.1.2" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, "node_modules/@radix-ui/rect": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/rect/-/rect-1.1.0.tgz", - "integrity": "sha512-A9+lCBZoaMJlVKcRBz2YByCG+Cp2t6nAnMnNba+XiWxnj6r4JUFqfsgwocMBZU9LPtdxC6wB56ySYpc7LQIoJg==" + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/rect/-/rect-1.1.1.tgz", + "integrity": "sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw==", + "license": "MIT" }, "node_modules/@resvg/resvg-wasm": { "version": "2.4.0", @@ -2489,11 +2337,19 @@ "prettier": "^3.5.3" } }, + "node_modules/@rtsao/scc": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz", + "integrity": "sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==", + "dev": true, + "license": "MIT" + }, "node_modules/@rushstack/eslint-patch": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.10.2.tgz", - "integrity": "sha512-hw437iINopmQuxWPSUEvqE56NCPsiU8N4AYtfHmJFckclktzK9YQJieD3XkDCDH4OjL+C7zgPUh73R/nrcHrqw==", - "dev": true + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.12.0.tgz", + "integrity": "sha512-5EwMtOqvJMMa3HbmxLlF74e+3/HhwBTMcvt3nqVJgGCozO6hzIPOBlwm8mGVNR9SN2IJpxSnlxczyDjcn7qIyw==", + "dev": true, + "license": "MIT" }, "node_modules/@shuding/opentype.js": { "version": "1.4.0-beta.0", @@ -2511,25 +2367,21 @@ "node": ">= 8.0.0" } }, - "node_modules/@swc/counter": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz", - "integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==" - }, "node_modules/@swc/helpers": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.5.tgz", - "integrity": "sha512-KGYxvIOXcceOAbEk4bi/dVLEK9z8sZ0uBB3Il5b1rhfClSpcX0yfRO0KmTkqR2cnQDymwLB+25ZyMzICg/cm/A==", + "version": "0.5.15", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.15.tgz", + "integrity": "sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==", + "license": "Apache-2.0", "dependencies": { - "@swc/counter": "^0.1.3", - "tslib": "^2.4.0" + "tslib": "^2.8.0" } }, "node_modules/@tailwindcss/typography": { - "version": "0.5.14", - "resolved": "https://registry.npmjs.org/@tailwindcss/typography/-/typography-0.5.14.tgz", - "integrity": "sha512-ZvOCjUbsJBjL9CxQBn+VEnFpouzuKhxh2dH8xMIWHILL+HfOYtlAkWcyoon8LlzE53d2Yo6YO6pahKKNW3q1YQ==", + "version": "0.5.16", + "resolved": "https://registry.npmjs.org/@tailwindcss/typography/-/typography-0.5.16.tgz", + "integrity": "sha512-0wDLwCVF5V3x3b1SGXPCDcdsbDHMBe+lkFzBRaHeLvNi+nrrnZ1lA18u+OTWO8iSWU2GxUOCvlXtDuqftc1oiA==", "dev": true, + "license": "MIT", "dependencies": { "lodash.castarray": "^4.4.0", "lodash.isplainobject": "^4.0.6", @@ -2537,7 +2389,7 @@ "postcss-selector-parser": "6.0.10" }, "peerDependencies": { - "tailwindcss": ">=3.0.0 || insiders" + "tailwindcss": ">=3.0.0 || insiders || >=4.0.0-alpha.20 || >=4.0.0-beta.1" } }, "node_modules/@tailwindcss/typography/node_modules/postcss-selector-parser": { @@ -2581,6 +2433,17 @@ "devOptional": true, "license": "MIT" }, + "node_modules/@tybys/wasm-util": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.0.tgz", + "integrity": "sha512-VyyPYFlOMNylG45GoAe0xDoLwWuowvf92F9kySqzYh8vmYm7D2u4iUJKa1tOUpS70Ku13ASrOkS4ScXFsTaCNQ==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, "node_modules/@types/acorn": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/@types/acorn/-/acorn-4.0.6.tgz", @@ -2598,9 +2461,10 @@ } }, "node_modules/@types/estree": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", - "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==" + "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/@types/estree-jsx": { "version": "1.0.5", @@ -2619,11 +2483,19 @@ "@types/unist": "*" } }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/json5": { "version": "0.0.29", "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/lunr": { "version": "2.3.7", @@ -2651,12 +2523,12 @@ "integrity": "sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==" }, "node_modules/@types/node": { - "version": "20.17.19", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.17.19.tgz", - "integrity": "sha512-LEwC7o1ifqg/6r2gn9Dns0f1rhK+fPFDoMiceTJ6kWmVk6bgXBI/9IOWfVan4WiAavK9pIVWdX0/e3J+eEUh5A==", + "version": "24.2.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.2.0.tgz", + "integrity": "sha512-3xyG3pMCq3oYCNg7/ZP+E1ooTaGB4cG8JWRsqqOYQdbWNY4zbaV0Ennrd7stjiJEFZCaybcIgpTjJWHRfBSIDw==", "license": "MIT", "dependencies": { - "undici-types": "~6.19.2" + "undici-types": "~7.10.0" } }, "node_modules/@types/prismjs": { @@ -2664,27 +2536,23 @@ "resolved": "https://registry.npmjs.org/@types/prismjs/-/prismjs-1.26.3.tgz", "integrity": "sha512-A0D0aTXvjlqJ5ZILMz3rNfDBOx9hHxLZYv2by47Sm/pqW35zzjusrZTryatjN/Rf8Us2gZrJD+KeHbUSTux1Cw==" }, - "node_modules/@types/prop-types": { - "version": "15.7.12", - "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.12.tgz", - "integrity": "sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==" - }, "node_modules/@types/react": { - "version": "18.2.77", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.77.tgz", - "integrity": "sha512-CUT9KUUF+HytDM7WiXKLF9qUSg4tGImwy4FXTlfEDPEkkNUzJ7rVFolYweJ9fS1ljoIaP7M7Rdjc5eUm/Yu5AA==", + "version": "19.1.9", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.1.9.tgz", + "integrity": "sha512-WmdoynAX8Stew/36uTSVMcLJJ1KRh6L3IZRx1PZ7qJtBqT3dYTgyDTx8H1qoRghErydW7xw9mSJ3wS//tCRpFA==", + "license": "MIT", "dependencies": { - "@types/prop-types": "*", "csstype": "^3.0.2" } }, "node_modules/@types/react-dom": { - "version": "18.2.25", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.25.tgz", - "integrity": "sha512-o/V48vf4MQh7juIKZU2QGDfli6p1+OOi5oXx36Hffpc9adsHeXjVp8rHuPkjd8VT8sOJ2Zp05HR7CdpGTIUFUA==", + "version": "19.1.7", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.1.7.tgz", + "integrity": "sha512-i5ZzwYpqjmrKenzkoLM2Ibzt6mAsM7pxB6BCIouEVVmgiqaMj1TjaK7hnA36hbW5aZv20kx7Lw6hWzPWg0Rurw==", "devOptional": true, - "dependencies": { - "@types/react": "*" + "license": "MIT", + "peerDependencies": { + "@types/react": "^19.0.0" } }, "node_modules/@types/unist": { @@ -2693,58 +2561,161 @@ "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", "license": "MIT" }, - "node_modules/@typescript-eslint/parser": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.21.0.tgz", - "integrity": "sha512-tbsV1jPne5CkFQCgPBcDOt30ItF7aJoZL997JSF7MhGQqOeT3svWRYxiqlfA5RUdlHN6Fi+EI9bxqbdyAUZjYQ==", + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "8.39.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.39.0.tgz", + "integrity": "sha512-bhEz6OZeUR+O/6yx9Jk6ohX6H9JSFTaiY0v9/PuKT3oGK0rn0jNplLmyFUGV+a9gfYnVNwGDwS/UkLIuXNb2Rw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "8.39.0", + "@typescript-eslint/type-utils": "8.39.0", + "@typescript-eslint/utils": "8.39.0", + "@typescript-eslint/visitor-keys": "8.39.0", + "graphemer": "^1.4.0", + "ignore": "^7.0.0", + "natural-compare": "^1.4.0", + "ts-api-utils": "^2.1.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^8.39.0", + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", + "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "8.39.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.39.0.tgz", + "integrity": "sha512-g3WpVQHngx0aLXn6kfIYCZxM6rRJlWzEkVpqEFLT3SgEDsp9cpCbxxgwnE504q4H+ruSDh/VGS6nqZIDynP+vg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/scope-manager": "8.39.0", + "@typescript-eslint/types": "8.39.0", + "@typescript-eslint/typescript-estree": "8.39.0", + "@typescript-eslint/visitor-keys": "8.39.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/project-service": { + "version": "8.39.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.39.0.tgz", + "integrity": "sha512-CTzJqaSq30V/Z2Og9jogzZt8lJRR5TKlAdXmWgdu4hgcC9Kww5flQ+xFvMxIBWVNdxJO7OifgdOK4PokMIWPew==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/tsconfig-utils": "^8.39.0", + "@typescript-eslint/types": "^8.39.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "8.39.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.39.0.tgz", + "integrity": "sha512-8QOzff9UKxOh6npZQ/4FQu4mjdOCGSdO3p44ww0hk8Vu+IGbg0tB/H1LcTARRDzGCC8pDGbh2rissBuuoPgH8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.39.0", + "@typescript-eslint/visitor-keys": "8.39.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/tsconfig-utils": { + "version": "8.39.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.39.0.tgz", + "integrity": "sha512-Fd3/QjmFV2sKmvv3Mrj8r6N8CryYiCS8Wdb/6/rgOXAWGcFuc+VkQuG28uk/4kVNVZBQuuDHEDUpo/pQ32zsIQ==", "dev": true, - "dependencies": { - "@typescript-eslint/scope-manager": "6.21.0", - "@typescript-eslint/types": "6.21.0", - "@typescript-eslint/typescript-estree": "6.21.0", - "@typescript-eslint/visitor-keys": "6.21.0", - "debug": "^4.3.4" - }, + "license": "MIT", "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "typescript": ">=4.8.4 <6.0.0" } }, - "node_modules/@typescript-eslint/scope-manager": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz", - "integrity": "sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==", + "node_modules/@typescript-eslint/type-utils": { + "version": "8.39.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.39.0.tgz", + "integrity": "sha512-6B3z0c1DXVT2vYA9+z9axjtc09rqKUPRmijD5m9iv8iQpHBRYRMBcgxSiKTZKm6FwWw1/cI4v6em35OsKCiN5Q==", "dev": true, + "license": "MIT", "dependencies": { - "@typescript-eslint/types": "6.21.0", - "@typescript-eslint/visitor-keys": "6.21.0" + "@typescript-eslint/types": "8.39.0", + "@typescript-eslint/typescript-estree": "8.39.0", + "@typescript-eslint/utils": "8.39.0", + "debug": "^4.3.4", + "ts-api-utils": "^2.1.0" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" } }, "node_modules/@typescript-eslint/types": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.21.0.tgz", - "integrity": "sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==", + "version": "8.39.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.39.0.tgz", + "integrity": "sha512-ArDdaOllnCj3yn/lzKn9s0pBQYmmyme/v1HbGIGB0GB/knFI3fWMHloC+oYTJW46tVbYnGKTMDK4ah1sC2v0Kg==", "dev": true, + "license": "MIT", "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", @@ -2752,47 +2723,80 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz", - "integrity": "sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==", + "version": "8.39.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.39.0.tgz", + "integrity": "sha512-ndWdiflRMvfIgQRpckQQLiB5qAKQ7w++V4LlCHwp62eym1HLB/kw7D9f2e8ytONls/jt89TEasgvb+VwnRprsw==", "dev": true, + "license": "MIT", "dependencies": { - "@typescript-eslint/types": "6.21.0", - "@typescript-eslint/visitor-keys": "6.21.0", + "@typescript-eslint/project-service": "8.39.0", + "@typescript-eslint/tsconfig-utils": "8.39.0", + "@typescript-eslint/types": "8.39.0", + "@typescript-eslint/visitor-keys": "8.39.0", "debug": "^4.3.4", - "globby": "^11.1.0", + "fast-glob": "^3.3.2", "is-glob": "^4.0.3", - "minimatch": "9.0.3", - "semver": "^7.5.4", - "ts-api-utils": "^1.0.1" + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^2.1.0" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" } }, "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", "dev": true, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" } }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/fast-glob": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.8" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" }, @@ -2803,32 +2807,339 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/@typescript-eslint/utils": { + "version": "8.39.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.39.0.tgz", + "integrity": "sha512-4GVSvNA0Vx1Ktwvf4sFE+exxJ3QGUorQG1/A5mRfRNZtkBT2xrA/BCO2H0eALx/PnvCS6/vmYwRdDA41EoffkQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.7.0", + "@typescript-eslint/scope-manager": "8.39.0", + "@typescript-eslint/types": "8.39.0", + "@typescript-eslint/typescript-estree": "8.39.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz", - "integrity": "sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==", + "version": "8.39.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.39.0.tgz", + "integrity": "sha512-ldgiJ+VAhQCfIjeOgu8Kj5nSxds0ktPOSO9p4+0VDH2R2pLvQraaM5Oen2d7NxzMCm+Sn/vJT+mv2H5u6b/3fA==", "dev": true, + "license": "MIT", "dependencies": { - "@typescript-eslint/types": "6.21.0", - "eslint-visitor-keys": "^3.4.1" + "@typescript-eslint/types": "8.39.0", + "eslint-visitor-keys": "^4.2.1" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@ungap/structured-clone": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", - "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==" + "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@ungap/structured-clone": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==" + }, + "node_modules/@unrs/resolver-binding-android-arm-eabi": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm-eabi/-/resolver-binding-android-arm-eabi-1.11.1.tgz", + "integrity": "sha512-ppLRUgHVaGRWUx0R0Ut06Mjo9gBaBkg3v/8AxusGLhsIotbBLuRk51rAzqLC8gq6NyyAojEXglNjzf6R948DNw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@unrs/resolver-binding-android-arm64": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm64/-/resolver-binding-android-arm64-1.11.1.tgz", + "integrity": "sha512-lCxkVtb4wp1v+EoN+HjIG9cIIzPkX5OtM03pQYkG+U5O/wL53LC4QbIeazgiKqluGeVEeBlZahHalCaBvU1a2g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@unrs/resolver-binding-darwin-arm64": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-arm64/-/resolver-binding-darwin-arm64-1.11.1.tgz", + "integrity": "sha512-gPVA1UjRu1Y/IsB/dQEsp2V1pm44Of6+LWvbLc9SDk1c2KhhDRDBUkQCYVWe6f26uJb3fOK8saWMgtX8IrMk3g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@unrs/resolver-binding-darwin-x64": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-x64/-/resolver-binding-darwin-x64-1.11.1.tgz", + "integrity": "sha512-cFzP7rWKd3lZaCsDze07QX1SC24lO8mPty9vdP+YVa3MGdVgPmFc59317b2ioXtgCMKGiCLxJ4HQs62oz6GfRQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@unrs/resolver-binding-freebsd-x64": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-freebsd-x64/-/resolver-binding-freebsd-x64-1.11.1.tgz", + "integrity": "sha512-fqtGgak3zX4DCB6PFpsH5+Kmt/8CIi4Bry4rb1ho6Av2QHTREM+47y282Uqiu3ZRF5IQioJQ5qWRV6jduA+iGw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm-gnueabihf": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-gnueabihf/-/resolver-binding-linux-arm-gnueabihf-1.11.1.tgz", + "integrity": "sha512-u92mvlcYtp9MRKmP+ZvMmtPN34+/3lMHlyMj7wXJDeXxuM0Vgzz0+PPJNsro1m3IZPYChIkn944wW8TYgGKFHw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm-musleabihf": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-musleabihf/-/resolver-binding-linux-arm-musleabihf-1.11.1.tgz", + "integrity": "sha512-cINaoY2z7LVCrfHkIcmvj7osTOtm6VVT16b5oQdS4beibX2SYBwgYLmqhBjA1t51CarSaBuX5YNsWLjsqfW5Cw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm64-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-gnu/-/resolver-binding-linux-arm64-gnu-1.11.1.tgz", + "integrity": "sha512-34gw7PjDGB9JgePJEmhEqBhWvCiiWCuXsL9hYphDF7crW7UgI05gyBAi6MF58uGcMOiOqSJ2ybEeCvHcq0BCmQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm64-musl": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-musl/-/resolver-binding-linux-arm64-musl-1.11.1.tgz", + "integrity": "sha512-RyMIx6Uf53hhOtJDIamSbTskA99sPHS96wxVE/bJtePJJtpdKGXO1wY90oRdXuYOGOTuqjT8ACccMc4K6QmT3w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-ppc64-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-ppc64-gnu/-/resolver-binding-linux-ppc64-gnu-1.11.1.tgz", + "integrity": "sha512-D8Vae74A4/a+mZH0FbOkFJL9DSK2R6TFPC9M+jCWYia/q2einCubX10pecpDiTmkJVUH+y8K3BZClycD8nCShA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-riscv64-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-gnu/-/resolver-binding-linux-riscv64-gnu-1.11.1.tgz", + "integrity": "sha512-frxL4OrzOWVVsOc96+V3aqTIQl1O2TjgExV4EKgRY09AJ9leZpEg8Ak9phadbuX0BA4k8U5qtvMSQQGGmaJqcQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-riscv64-musl": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-musl/-/resolver-binding-linux-riscv64-musl-1.11.1.tgz", + "integrity": "sha512-mJ5vuDaIZ+l/acv01sHoXfpnyrNKOk/3aDoEdLO/Xtn9HuZlDD6jKxHlkN8ZhWyLJsRBxfv9GYM2utQ1SChKew==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-s390x-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-s390x-gnu/-/resolver-binding-linux-s390x-gnu-1.11.1.tgz", + "integrity": "sha512-kELo8ebBVtb9sA7rMe1Cph4QHreByhaZ2QEADd9NzIQsYNQpt9UkM9iqr2lhGr5afh885d/cB5QeTXSbZHTYPg==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-x64-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-gnu/-/resolver-binding-linux-x64-gnu-1.11.1.tgz", + "integrity": "sha512-C3ZAHugKgovV5YvAMsxhq0gtXuwESUKc5MhEtjBpLoHPLYM+iuwSj3lflFwK3DPm68660rZ7G8BMcwSro7hD5w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-x64-musl": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-musl/-/resolver-binding-linux-x64-musl-1.11.1.tgz", + "integrity": "sha512-rV0YSoyhK2nZ4vEswT/QwqzqQXw5I6CjoaYMOX0TqBlWhojUf8P94mvI7nuJTeaCkkds3QE4+zS8Ko+GdXuZtA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-wasm32-wasi": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-wasm32-wasi/-/resolver-binding-wasm32-wasi-1.11.1.tgz", + "integrity": "sha512-5u4RkfxJm+Ng7IWgkzi3qrFOvLvQYnPBmjmZQ8+szTK/b31fQCnleNl1GgEt7nIsZRIf5PLhPwT0WM+q45x/UQ==", + "cpu": [ + "wasm32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@napi-rs/wasm-runtime": "^0.2.11" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@unrs/resolver-binding-win32-arm64-msvc": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-arm64-msvc/-/resolver-binding-win32-arm64-msvc-1.11.1.tgz", + "integrity": "sha512-nRcz5Il4ln0kMhfL8S3hLkxI85BXs3o8EYoattsJNdsX4YUU89iOkVn7g0VHSRxFuVMdM4Q1jEpIId1Ihim/Uw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@unrs/resolver-binding-win32-ia32-msvc": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-ia32-msvc/-/resolver-binding-win32-ia32-msvc-1.11.1.tgz", + "integrity": "sha512-DCEI6t5i1NmAZp6pFonpD5m7i6aFrpofcp4LA2i8IIq60Jyo28hamKBxNrZcyOwVOZkgsRp9O2sXWBWP8MnvIQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@unrs/resolver-binding-win32-x64-msvc": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-1.11.1.tgz", + "integrity": "sha512-lrW200hZdbfRtztbygyaq/6jP6AKE8qQN2KvPcJ+x7wiD038YtnYtZ82IMNJ69GJibV7bwL3y9FgK+5w/pYt6g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] }, "node_modules/@vercel/og": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/@vercel/og/-/og-0.8.2.tgz", - "integrity": "sha512-7B/futewgJj7TLDj6fMp+USBRIt3TqtwomEtX/jVS+g+dZySjXUYBsWD2Sz3Y6hFR34xAXWDQaMvIic313h0Nw==", + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/@vercel/og/-/og-0.8.5.tgz", + "integrity": "sha512-fHqnxfBYcwkamlEgcIzaZqL8IHT09hR7FZL7UdMTdGJyoaBzM/dY6ulO5Swi4ig30FrBJI9I2C+GLV9sb9vexA==", "license": "MPL-2.0", "dependencies": { "@resvg/resvg-wasm": "2.4.0", @@ -2844,9 +3155,10 @@ "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" }, "node_modules/acorn": { - "version": "8.11.3", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", - "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "license": "MIT", "bin": { "acorn": "bin/acorn" }, @@ -2880,6 +3192,7 @@ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, + "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -2892,11 +3205,15 @@ } }, "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "license": "MIT", "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, "node_modules/ansi-styles": { @@ -2916,12 +3233,14 @@ "node_modules/any-promise": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", - "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==" + "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", + "license": "MIT" }, "node_modules/anymatch": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "license": "ISC", "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" @@ -2933,18 +3252,21 @@ "node_modules/arg": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", - "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==" + "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", + "license": "MIT" }, "node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true + "dev": true, + "license": "Python-2.0" }, "node_modules/aria-hidden": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/aria-hidden/-/aria-hidden-1.2.4.tgz", - "integrity": "sha512-y+CcFFwelSXpLZk/7fMB2mUbGtX9lKycf1MWJ7CaTIERyitVlyQx6C+sxcROU2BAJ24OiZyK+8wj2i8AlBoS3A==", + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/aria-hidden/-/aria-hidden-1.2.6.tgz", + "integrity": "sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA==", + "license": "MIT", "dependencies": { "tslib": "^2.0.0" }, @@ -2953,22 +3275,24 @@ } }, "node_modules/aria-query": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz", - "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==", + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz", + "integrity": "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==", "dev": true, - "dependencies": { - "dequal": "^2.0.3" + "license": "Apache-2.0", + "engines": { + "node": ">= 0.4" } }, "node_modules/array-buffer-byte-length": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", - "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz", + "integrity": "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.5", - "is-array-buffer": "^3.0.4" + "call-bound": "^1.0.3", + "is-array-buffer": "^3.0.5" }, "engines": { "node": ">= 0.4" @@ -2978,17 +3302,20 @@ } }, "node_modules/array-includes": { - "version": "3.1.8", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.8.tgz", - "integrity": "sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==", + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.9.tgz", + "integrity": "sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", - "es-object-atoms": "^1.0.0", - "get-intrinsic": "^1.2.4", - "is-string": "^1.0.7" + "es-abstract": "^1.24.0", + "es-object-atoms": "^1.1.1", + "get-intrinsic": "^1.3.0", + "is-string": "^1.1.1", + "math-intrinsics": "^1.1.0" }, "engines": { "node": ">= 0.4" @@ -2997,20 +3324,12 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/array.prototype.findlast": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz", "integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", @@ -3027,17 +3346,19 @@ } }, "node_modules/array.prototype.findlastindex": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.5.tgz", - "integrity": "sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ==", + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.6.tgz", + "integrity": "sha512-F/TKATkzseUExPlfvmwQKGITM3DGTK+vkAsCZoDc5daVygbJBnjEUCbgkAvVFsgfXfX4YIqZ/27G3k3tdXrTxQ==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", + "es-abstract": "^1.23.9", "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", - "es-shim-unscopables": "^1.0.2" + "es-object-atoms": "^1.1.1", + "es-shim-unscopables": "^1.1.0" }, "engines": { "node": ">= 0.4" @@ -3047,15 +3368,16 @@ } }, "node_modules/array.prototype.flat": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz", - "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.3.tgz", + "integrity": "sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0" + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-shim-unscopables": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -3065,15 +3387,16 @@ } }, "node_modules/array.prototype.flatmap": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz", - "integrity": "sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.3.tgz", + "integrity": "sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0" + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-shim-unscopables": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -3082,45 +3405,37 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/array.prototype.toreversed": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/array.prototype.toreversed/-/array.prototype.toreversed-1.1.2.tgz", - "integrity": "sha512-wwDCoT4Ck4Cz7sLtgUmzR5UV3YF5mFHUlbChCzZBQZ+0m2cl/DH3tKgvphv1nKgFsJ48oCSg6p91q2Vm0I/ZMA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0" - } - }, "node_modules/array.prototype.tosorted": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.3.tgz", - "integrity": "sha512-/DdH4TiTmOKzyQbp/eadcCVexiCb36xJg7HshYOYJnNZFDj33GEv0P7GxsynpShhq4OLYJzbGcBDkLsDt7MnNg==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz", + "integrity": "sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.5", + "call-bind": "^1.0.7", "define-properties": "^1.2.1", - "es-abstract": "^1.22.3", - "es-errors": "^1.1.0", + "es-abstract": "^1.23.3", + "es-errors": "^1.3.0", "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" } }, "node_modules/arraybuffer.prototype.slice": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz", - "integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.4.tgz", + "integrity": "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==", "dev": true, + "license": "MIT", "dependencies": { "array-buffer-byte-length": "^1.0.1", - "call-bind": "^1.0.5", + "call-bind": "^1.0.8", "define-properties": "^1.2.1", - "es-abstract": "^1.22.3", - "es-errors": "^1.2.1", - "get-intrinsic": "^1.2.3", - "is-array-buffer": "^3.0.4", - "is-shared-array-buffer": "^1.0.2" + "es-abstract": "^1.23.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "is-array-buffer": "^3.0.4" }, "engines": { "node": ">= 0.4" @@ -3133,7 +3448,8 @@ "version": "0.0.8", "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.8.tgz", "integrity": "sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/astring": { "version": "1.8.6", @@ -3143,10 +3459,20 @@ "astring": "bin/astring" } }, + "node_modules/async-function": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-function/-/async-function-1.0.0.tgz", + "integrity": "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/autoprefixer": { - "version": "10.4.20", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.20.tgz", - "integrity": "sha512-XY25y5xSv/wEoqzDyXXME4AFfkZI0P23z6Fs3YgymDnKJkCGOnkL0iTxCa85UTqaSgfcqyf3UA6+c7wUvx/16g==", + "version": "10.4.21", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.21.tgz", + "integrity": "sha512-O+A6LWV5LDHSJD3LjHYoNi4VLsj/Whi7k6zG12xTYaU4cQ8oxQGckXNX8cRHK5yOZ/ppVHe0ZBXGzSV9jXdVbQ==", "dev": true, "funding": [ { @@ -3162,12 +3488,13 @@ "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "dependencies": { - "browserslist": "^4.23.3", - "caniuse-lite": "^1.0.30001646", + "browserslist": "^4.24.4", + "caniuse-lite": "^1.0.30001702", "fraction.js": "^4.3.7", "normalize-range": "^0.1.2", - "picocolors": "^1.0.1", + "picocolors": "^1.1.1", "postcss-value-parser": "^4.2.0" }, "bin": { @@ -3196,21 +3523,23 @@ } }, "node_modules/axe-core": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.7.0.tgz", - "integrity": "sha512-M0JtH+hlOL5pLQwHOLNYZaXuhqmvS8oExsqB1SBYgA4Dk7u/xx+YdGHXaK5pyUfed5mYXdlYiphWq3G8cRi5JQ==", + "version": "4.10.3", + "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.10.3.tgz", + "integrity": "sha512-Xm7bpRXnDSX2YE2YFfBk2FnF0ep6tmG7xPh8iHee8MIcrgq762Nkce856dYtJYLkuIoYZvGfTs/PbZhideTcEg==", "dev": true, + "license": "MPL-2.0", "engines": { "node": ">=4" } }, "node_modules/axobject-query": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-3.2.1.tgz", - "integrity": "sha512-jsyHu61e6N4Vbz/v18DHwWYKK0bSWLqn47eeDSKPB7m8tqMHF9YJ+mhIk2lVteyZrY8tnSj/jHOv4YiTCuCJgg==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz", + "integrity": "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==", "dev": true, - "dependencies": { - "dequal": "^2.0.3" + "license": "Apache-2.0", + "engines": { + "node": ">= 0.4" } }, "node_modules/bail": { @@ -3279,6 +3608,7 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "license": "MIT", "engines": { "node": ">=8" }, @@ -3416,9 +3746,9 @@ } }, "node_modules/browserslist": { - "version": "4.23.3", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.3.tgz", - "integrity": "sha512-btwCFJVjI4YWDNfau8RhZ+B1Q/VLoUITrm3RlP6y1tYGWIOa+InuYiRGXUBXo8nA1qKmHMyLB/iVQg5TT4eFoA==", + "version": "4.25.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.25.1.tgz", + "integrity": "sha512-KGj0KoOMXLpSNkkEI6Z6mShmQy0bc1I+T7K9N81k4WWMrfz+6fQ6es80B/YLAeRoKvjYE1YSHHOW1qe9xIVzHw==", "dev": true, "funding": [ { @@ -3434,11 +3764,12 @@ "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "dependencies": { - "caniuse-lite": "^1.0.30001646", - "electron-to-chromium": "^1.5.4", - "node-releases": "^2.0.18", - "update-browserslist-db": "^1.1.0" + "caniuse-lite": "^1.0.30001726", + "electron-to-chromium": "^1.5.173", + "node-releases": "^2.0.19", + "update-browserslist-db": "^1.1.3" }, "bin": { "browserslist": "cli.js" @@ -3452,28 +3783,46 @@ "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" }, - "node_modules/busboy": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", - "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", + "node_modules/call-bind": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", + "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==", + "dev": true, + "license": "MIT", "dependencies": { - "streamsearch": "^1.1.0" + "call-bind-apply-helpers": "^1.0.0", + "es-define-property": "^1.0.0", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.2" }, "engines": { - "node": ">=10.16.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/call-bind": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", - "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", - "dev": true, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", "dependencies": { - "es-define-property": "^1.0.0", "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "set-function-length": "^1.2.1" + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" }, "engines": { "node": ">= 0.4" @@ -3506,6 +3855,7 @@ "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -3528,6 +3878,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", + "license": "MIT", "engines": { "node": ">= 6" } @@ -3542,9 +3893,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001710", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001710.tgz", - "integrity": "sha512-B5C0I0UmaGqHgo5FuqJ7hBd4L57A4dDD+Xi+XX1nXOoxGeDdY4Ko38qJYOyqznBVJEqON5p8P1x5zRR3+rsnxA==", + "version": "1.0.30001731", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001731.tgz", + "integrity": "sha512-lDdp2/wrOmTRWuoB5DpfNkC0rJDU8DqRa6nYL6HK6sytw70QMopt/NIc/9SM7ylItlBWfACXk0tEn37UWM/+mg==", "funding": [ { "type": "opencollective", @@ -3631,6 +3982,7 @@ "version": "3.6.0", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "license": "MIT", "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", @@ -3654,6 +4006,7 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "license": "ISC", "dependencies": { "is-glob": "^4.0.1" }, @@ -3662,22 +4015,15 @@ } }, "node_modules/class-variance-authority": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/class-variance-authority/-/class-variance-authority-0.7.0.tgz", - "integrity": "sha512-jFI8IQw4hczaL4ALINxqLEXQbWcNjoSkloa4IaufXCJr6QawJyw7tuRysRsrE8w2p/4gGaxKIt/hX3qz/IbD1A==", + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/class-variance-authority/-/class-variance-authority-0.7.1.tgz", + "integrity": "sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg==", + "license": "Apache-2.0", "dependencies": { - "clsx": "2.0.0" + "clsx": "^2.1.1" }, "funding": { - "url": "https://joebell.co.uk" - } - }, - "node_modules/class-variance-authority/node_modules/clsx": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.0.0.tgz", - "integrity": "sha512-rQ1+kcj+ttHG0MKVGBUXwayCCF1oh39BF5COIpRzuCEv8Mwjv0XucrI2ExNTOn9IlLifGClWQcU9BrZORvtw6Q==", - "engines": { - "node": ">=6" + "url": "https://polar.sh/cva" } }, "node_modules/cli-table": { @@ -3694,7 +4040,8 @@ "node_modules/client-only": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", - "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==" + "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==", + "license": "MIT" }, "node_modules/clsx": { "version": "2.1.1", @@ -3720,62 +4067,6 @@ "react-dom": "^18 || ^19 || ^19.0.0-rc" } }, - "node_modules/cmdk/node_modules/@radix-ui/react-compose-refs": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.2.tgz", - "integrity": "sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg==", - "license": "MIT", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/cmdk/node_modules/@radix-ui/react-primitive": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", - "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-slot": "1.2.3" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/cmdk/node_modules/@radix-ui/react-slot": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", - "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-compose-refs": "1.1.2" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, "node_modules/collapse-white-space": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/collapse-white-space/-/collapse-white-space-2.1.0.tgz", @@ -3785,6 +4076,20 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/color": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz", + "integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==", + "license": "MIT", + "optional": true, + "dependencies": { + "color-convert": "^2.0.1", + "color-string": "^1.9.0" + }, + "engines": { + "node": ">=12.5.0" + } + }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -3801,6 +4106,17 @@ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, + "node_modules/color-string": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", + "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", + "license": "MIT", + "optional": true, + "dependencies": { + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" + } + }, "node_modules/colors": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz", @@ -3845,6 +4161,7 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "license": "MIT", "engines": { "node": ">= 6" } @@ -3964,17 +4281,19 @@ "version": "1.0.8", "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==", - "dev": true + "dev": true, + "license": "BSD-2-Clause" }, "node_modules/data-view-buffer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz", - "integrity": "sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz", + "integrity": "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.6", + "call-bound": "^1.0.3", "es-errors": "^1.3.0", - "is-data-view": "^1.0.1" + "is-data-view": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -3984,29 +4303,31 @@ } }, "node_modules/data-view-byte-length": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz", - "integrity": "sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.2.tgz", + "integrity": "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", + "call-bound": "^1.0.3", "es-errors": "^1.3.0", - "is-data-view": "^1.0.1" + "is-data-view": "^1.0.2" }, "engines": { "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/inspect-js" } }, "node_modules/data-view-byte-offset": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz", - "integrity": "sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz", + "integrity": "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.6", + "call-bound": "^1.0.2", "es-errors": "^1.3.0", "is-data-view": "^1.0.1" }, @@ -4104,10 +4425,21 @@ "node": ">=6" } }, + "node_modules/detect-libc": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.4.tgz", + "integrity": "sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==", + "license": "Apache-2.0", + "optional": true, + "engines": { + "node": ">=8" + } + }, "node_modules/detect-node-es": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/detect-node-es/-/detect-node-es-1.1.0.tgz", - "integrity": "sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==" + "integrity": "sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==", + "license": "MIT" }, "node_modules/dev-null": { "version": "0.1.1", @@ -4129,7 +4461,8 @@ "node_modules/didyoumean": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", - "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==" + "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", + "license": "Apache-2.0" }, "node_modules/diff": { "version": "4.0.2", @@ -4141,33 +4474,37 @@ "node": ">=0.3.1" } }, - "node_modules/dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "node_modules/dlv": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", + "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", + "license": "MIT" + }, + "node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", "dev": true, + "license": "Apache-2.0", "dependencies": { - "path-type": "^4.0.0" + "esutils": "^2.0.2" }, "engines": { - "node": ">=8" + "node": ">=0.10.0" } }, - "node_modules/dlv": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", - "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==" - }, - "node_modules/doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", "dependencies": { - "esutils": "^2.0.2" + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" }, "engines": { - "node": ">=6.0.0" + "node": ">= 0.4" } }, "node_modules/duplexer": { @@ -4178,18 +4515,21 @@ "node_modules/eastasianwidth": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "license": "MIT" }, "node_modules/electron-to-chromium": { - "version": "1.5.13", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.13.tgz", - "integrity": "sha512-lbBcvtIJ4J6sS4tb5TLp1b4LyfCdMkwStzXPyAgVgTRAsep4bvrAGaBOP7ZJtQMNJpSQ9SqG4brWOroNaQtm7Q==", - "dev": true + "version": "1.5.199", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.199.tgz", + "integrity": "sha512-3gl0S7zQd88kCAZRO/DnxtBKuhMO4h0EaQIN3YgZfV6+pW+5+bf2AdQeHNESCoaQqo/gjGVYEf2YM4O5HJQqpQ==", + "dev": true, + "license": "ISC" }, "node_modules/emoji-regex": { "version": "9.2.2", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "license": "MIT" }, "node_modules/emoji-regex-xs": { "version": "2.0.1", @@ -4200,19 +4540,6 @@ "node": ">=10.0.0" } }, - "node_modules/enhanced-resolve": { - "version": "5.16.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.16.0.tgz", - "integrity": "sha512-O+QWCviPNSSLAD9Ucn8Awv+poAkqn3T1XY5/N7kR7rQO9yfSGWkYZDwpJ+iKF7B8rxaQKWngSqACpgzeapSyoA==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" - }, - "engines": { - "node": ">=10.13.0" - } - }, "node_modules/entities": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", @@ -4249,57 +4576,66 @@ } }, "node_modules/es-abstract": { - "version": "1.23.3", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.3.tgz", - "integrity": "sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==", + "version": "1.24.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.0.tgz", + "integrity": "sha512-WSzPgsdLtTcQwm4CROfS5ju2Wa1QQcVeT37jFjYzdFz1r9ahadC8B8/a4qxJxM+09F18iumCdRmlr96ZYkQvEg==", "dev": true, + "license": "MIT", "dependencies": { - "array-buffer-byte-length": "^1.0.1", - "arraybuffer.prototype.slice": "^1.0.3", + "array-buffer-byte-length": "^1.0.2", + "arraybuffer.prototype.slice": "^1.0.4", "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.7", - "data-view-buffer": "^1.0.1", - "data-view-byte-length": "^1.0.1", - "data-view-byte-offset": "^1.0.0", - "es-define-property": "^1.0.0", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "data-view-buffer": "^1.0.2", + "data-view-byte-length": "^1.0.2", + "data-view-byte-offset": "^1.0.1", + "es-define-property": "^1.0.1", "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", - "es-set-tostringtag": "^2.0.3", - "es-to-primitive": "^1.2.1", - "function.prototype.name": "^1.1.6", - "get-intrinsic": "^1.2.4", - "get-symbol-description": "^1.0.2", - "globalthis": "^1.0.3", - "gopd": "^1.0.1", + "es-object-atoms": "^1.1.1", + "es-set-tostringtag": "^2.1.0", + "es-to-primitive": "^1.3.0", + "function.prototype.name": "^1.1.8", + "get-intrinsic": "^1.3.0", + "get-proto": "^1.0.1", + "get-symbol-description": "^1.1.0", + "globalthis": "^1.0.4", + "gopd": "^1.2.0", "has-property-descriptors": "^1.0.2", - "has-proto": "^1.0.3", - "has-symbols": "^1.0.3", + "has-proto": "^1.2.0", + "has-symbols": "^1.1.0", "hasown": "^2.0.2", - "internal-slot": "^1.0.7", - "is-array-buffer": "^3.0.4", + "internal-slot": "^1.1.0", + "is-array-buffer": "^3.0.5", "is-callable": "^1.2.7", - "is-data-view": "^1.0.1", + "is-data-view": "^1.0.2", "is-negative-zero": "^2.0.3", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.3", - "is-string": "^1.0.7", - "is-typed-array": "^1.1.13", - "is-weakref": "^1.0.2", - "object-inspect": "^1.13.1", + "is-regex": "^1.2.1", + "is-set": "^2.0.3", + "is-shared-array-buffer": "^1.0.4", + "is-string": "^1.1.1", + "is-typed-array": "^1.1.15", + "is-weakref": "^1.1.1", + "math-intrinsics": "^1.1.0", + "object-inspect": "^1.13.4", "object-keys": "^1.1.1", - "object.assign": "^4.1.5", - "regexp.prototype.flags": "^1.5.2", - "safe-array-concat": "^1.1.2", - "safe-regex-test": "^1.0.3", - "string.prototype.trim": "^1.2.9", - "string.prototype.trimend": "^1.0.8", + "object.assign": "^4.1.7", + "own-keys": "^1.0.1", + "regexp.prototype.flags": "^1.5.4", + "safe-array-concat": "^1.1.3", + "safe-push-apply": "^1.0.0", + "safe-regex-test": "^1.1.0", + "set-proto": "^1.0.0", + "stop-iteration-iterator": "^1.1.0", + "string.prototype.trim": "^1.2.10", + "string.prototype.trimend": "^1.0.9", "string.prototype.trimstart": "^1.0.8", - "typed-array-buffer": "^1.0.2", - "typed-array-byte-length": "^1.0.1", - "typed-array-byte-offset": "^1.0.2", - "typed-array-length": "^1.0.6", - "unbox-primitive": "^1.0.2", - "which-typed-array": "^1.1.15" + "typed-array-buffer": "^1.0.3", + "typed-array-byte-length": "^1.0.3", + "typed-array-byte-offset": "^1.0.4", + "typed-array-length": "^1.0.7", + "unbox-primitive": "^1.1.0", + "which-typed-array": "^1.1.19" }, "engines": { "node": ">= 0.4" @@ -4309,13 +4645,10 @@ } }, "node_modules/es-define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", - "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", - "dev": true, - "dependencies": { - "get-intrinsic": "^1.2.4" - }, + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", "engines": { "node": ">= 0.4" } @@ -4324,41 +4657,43 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", - "dev": true, "engines": { "node": ">= 0.4" } }, "node_modules/es-iterator-helpers": { - "version": "1.0.18", - "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.0.18.tgz", - "integrity": "sha512-scxAJaewsahbqTYrGKJihhViaM6DDZDDoucfvzNbK0pOren1g/daDQ3IAhzn+1G14rBG7w+i5N+qul60++zlKA==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.2.1.tgz", + "integrity": "sha512-uDn+FE1yrDzyC0pCo961B2IHbdM8y/ACZsKD4dG6WqrjV53BADjwa7D+1aom2rsNVfLyDgU/eigvlJGJ08OQ4w==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", "define-properties": "^1.2.1", - "es-abstract": "^1.23.0", + "es-abstract": "^1.23.6", "es-errors": "^1.3.0", "es-set-tostringtag": "^2.0.3", "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "globalthis": "^1.0.3", + "get-intrinsic": "^1.2.6", + "globalthis": "^1.0.4", + "gopd": "^1.2.0", "has-property-descriptors": "^1.0.2", - "has-proto": "^1.0.3", - "has-symbols": "^1.0.3", - "internal-slot": "^1.0.7", - "iterator.prototype": "^1.1.2", - "safe-array-concat": "^1.1.2" + "has-proto": "^1.2.0", + "has-symbols": "^1.1.0", + "internal-slot": "^1.1.0", + "iterator.prototype": "^1.1.4", + "safe-array-concat": "^1.1.3" }, "engines": { "node": ">= 0.4" } }, "node_modules/es-object-atoms": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", - "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==", - "dev": true, + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "license": "MIT", "dependencies": { "es-errors": "^1.3.0" }, @@ -4367,37 +4702,44 @@ } }, "node_modules/es-set-tostringtag": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz", - "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", "dev": true, + "license": "MIT", "dependencies": { - "get-intrinsic": "^1.2.4", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", "has-tostringtag": "^1.0.2", - "hasown": "^2.0.1" + "hasown": "^2.0.2" }, "engines": { "node": ">= 0.4" } }, "node_modules/es-shim-unscopables": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz", - "integrity": "sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.1.0.tgz", + "integrity": "sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==", "dev": true, + "license": "MIT", "dependencies": { - "hasown": "^2.0.0" + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" } }, "node_modules/es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.3.0.tgz", + "integrity": "sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==", "dev": true, + "license": "MIT", "dependencies": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" + "is-callable": "^1.2.7", + "is-date-object": "^1.0.5", + "is-symbol": "^1.0.4" }, "engines": { "node": ">= 0.4" @@ -4448,10 +4790,11 @@ } }, "node_modules/escalade": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", - "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -4475,78 +4818,86 @@ } }, "node_modules/eslint": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", - "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", + "version": "9.32.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.32.0.tgz", + "integrity": "sha512-LSehfdpgMeWcTZkWZVIJl+tkZ2nuSkyyB9C27MZqFWXuph7DvaowgcTvKqxvpLW1JZIk8PN7hFY3Rj9LQ7m7lg==", "dev": true, + "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.57.0", - "@humanwhocodes/config-array": "^0.11.14", + "@eslint-community/regexpp": "^4.12.1", + "@eslint/config-array": "^0.21.0", + "@eslint/config-helpers": "^0.3.0", + "@eslint/core": "^0.15.0", + "@eslint/eslintrc": "^3.3.1", + "@eslint/js": "9.32.0", + "@eslint/plugin-kit": "^0.3.4", + "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", - "@nodelib/fs.walk": "^1.2.8", - "@ungap/structured-clone": "^1.2.0", + "@humanwhocodes/retry": "^0.4.2", + "@types/estree": "^1.0.6", + "@types/json-schema": "^7.0.15", "ajv": "^6.12.4", "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", + "cross-spawn": "^7.0.6", "debug": "^4.3.2", - "doctrine": "^3.0.0", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.2.2", - "eslint-visitor-keys": "^3.4.3", - "espree": "^9.6.1", - "esquery": "^1.4.2", + "eslint-scope": "^8.4.0", + "eslint-visitor-keys": "^4.2.1", + "espree": "^10.4.0", + "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", + "file-entry-cache": "^8.0.0", "find-up": "^5.0.0", "glob-parent": "^6.0.2", - "globals": "^13.19.0", - "graphemer": "^1.4.0", "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", - "is-path-inside": "^3.0.3", - "js-yaml": "^4.1.0", "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", "lodash.merge": "^4.6.2", "minimatch": "^3.1.2", "natural-compare": "^1.4.0", - "optionator": "^0.9.3", - "strip-ansi": "^6.0.1", - "text-table": "^0.2.0" + "optionator": "^0.9.3" }, "bin": { "eslint": "bin/eslint.js" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://opencollective.com/eslint" + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } } }, "node_modules/eslint-config-next": { - "version": "14.2.6", - "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-14.2.6.tgz", - "integrity": "sha512-z0URA5LO6y8lS/YLN0EDW/C4LEkDODjJzA37dvLVdzCPzuewjzTe1os5g3XclZAZrQ8X8hPaSMQ2JuVWwMmrTA==", + "version": "15.4.6", + "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-15.4.6.tgz", + "integrity": "sha512-4uznvw5DlTTjrZgYZjMciSdDDMO2SWIuQgUNaFyC2O3Zw3Z91XeIejeVa439yRq2CnJb/KEvE4U2AeN/66FpUA==", "dev": true, + "license": "MIT", "dependencies": { - "@next/eslint-plugin-next": "14.2.6", - "@rushstack/eslint-patch": "^1.3.3", - "@typescript-eslint/parser": "^5.4.2 || ^6.0.0 || 7.0.0 - 7.2.0", + "@next/eslint-plugin-next": "15.4.6", + "@rushstack/eslint-patch": "^1.10.3", + "@typescript-eslint/eslint-plugin": "^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0", + "@typescript-eslint/parser": "^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0", "eslint-import-resolver-node": "^0.3.6", "eslint-import-resolver-typescript": "^3.5.2", - "eslint-plugin-import": "^2.28.1", - "eslint-plugin-jsx-a11y": "^6.7.1", - "eslint-plugin-react": "^7.33.2", - "eslint-plugin-react-hooks": "^4.5.0 || 5.0.0-canary-7118f5dd7-20230705" + "eslint-plugin-import": "^2.31.0", + "eslint-plugin-jsx-a11y": "^6.10.0", + "eslint-plugin-react": "^7.37.0", + "eslint-plugin-react-hooks": "^5.0.0" }, "peerDependencies": { - "eslint": "^7.23.0 || ^8.0.0", + "eslint": "^7.23.0 || ^8.0.0 || ^9.0.0", "typescript": ">=3.3.1" }, "peerDependenciesMeta": { @@ -4576,35 +4927,71 @@ } }, "node_modules/eslint-import-resolver-typescript": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.6.1.tgz", - "integrity": "sha512-xgdptdoi5W3niYeuQxKmzVDTATvLYqhpwmykwsh7f6HIOStGWEIL9iqZgQDF9u9OEzrRwR8no5q2VT+bjAujTg==", + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.10.1.tgz", + "integrity": "sha512-A1rHYb06zjMGAxdLSkN2fXPBwuSaQ0iO5M/hdyS0Ajj1VBaRp0sPD3dn1FhME3c/JluGFbwSxyCfqdSbtQLAHQ==", "dev": true, + "license": "ISC", "dependencies": { - "debug": "^4.3.4", - "enhanced-resolve": "^5.12.0", - "eslint-module-utils": "^2.7.4", - "fast-glob": "^3.3.1", - "get-tsconfig": "^4.5.0", - "is-core-module": "^2.11.0", - "is-glob": "^4.0.3" + "@nolyfill/is-core-module": "1.0.39", + "debug": "^4.4.0", + "get-tsconfig": "^4.10.0", + "is-bun-module": "^2.0.0", + "stable-hash": "^0.0.5", + "tinyglobby": "^0.2.13", + "unrs-resolver": "^1.6.2" }, "engines": { "node": "^14.18.0 || >=16.0.0" }, "funding": { - "url": "https://opencollective.com/unts/projects/eslint-import-resolver-ts" + "url": "https://opencollective.com/eslint-import-resolver-typescript" }, "peerDependencies": { "eslint": "*", - "eslint-plugin-import": "*" + "eslint-plugin-import": "*", + "eslint-plugin-import-x": "*" + }, + "peerDependenciesMeta": { + "eslint-plugin-import": { + "optional": true + }, + "eslint-plugin-import-x": { + "optional": true + } + } + }, + "node_modules/eslint-import-resolver-typescript/node_modules/debug": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", + "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, + "node_modules/eslint-import-resolver-typescript/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, "node_modules/eslint-module-utils": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.1.tgz", - "integrity": "sha512-rXDXR3h7cs7dy9RNpUlQf80nX31XWJEyGq1tRMo+6GsO5VmTe4UTwtmonAD4ZkAsrfMVDA2wlGJ3790Ys+D49Q==", + "version": "2.12.1", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.12.1.tgz", + "integrity": "sha512-L8jSWTze7K2mTg0vos/RuLRS5soomksDPoJLXIslC7c8Wmut3bx7CPpJijDcBZtxQ5lrbUdM+s0OlNbz0DCDNw==", "dev": true, + "license": "MIT", "dependencies": { "debug": "^3.2.7" }, @@ -4627,34 +5014,37 @@ } }, "node_modules/eslint-plugin-import": { - "version": "2.29.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.29.1.tgz", - "integrity": "sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw==", + "version": "2.32.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.32.0.tgz", + "integrity": "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==", "dev": true, + "license": "MIT", "dependencies": { - "array-includes": "^3.1.7", - "array.prototype.findlastindex": "^1.2.3", - "array.prototype.flat": "^1.3.2", - "array.prototype.flatmap": "^1.3.2", + "@rtsao/scc": "^1.1.0", + "array-includes": "^3.1.9", + "array.prototype.findlastindex": "^1.2.6", + "array.prototype.flat": "^1.3.3", + "array.prototype.flatmap": "^1.3.3", "debug": "^3.2.7", "doctrine": "^2.1.0", "eslint-import-resolver-node": "^0.3.9", - "eslint-module-utils": "^2.8.0", - "hasown": "^2.0.0", - "is-core-module": "^2.13.1", + "eslint-module-utils": "^2.12.1", + "hasown": "^2.0.2", + "is-core-module": "^2.16.1", "is-glob": "^4.0.3", "minimatch": "^3.1.2", - "object.fromentries": "^2.0.7", - "object.groupby": "^1.0.1", - "object.values": "^1.1.7", + "object.fromentries": "^2.0.8", + "object.groupby": "^1.0.3", + "object.values": "^1.2.1", "semver": "^6.3.1", + "string.prototype.trimend": "^1.0.9", "tsconfig-paths": "^3.15.0" }, "engines": { "node": ">=4" }, "peerDependencies": { - "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8" + "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9" } }, "node_modules/eslint-plugin-import/node_modules/debug": { @@ -4662,115 +5052,95 @@ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, + "license": "MIT", "dependencies": { "ms": "^2.1.1" } }, - "node_modules/eslint-plugin-import/node_modules/doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", - "dev": true, - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/eslint-plugin-import/node_modules/semver": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, + "license": "ISC", "bin": { "semver": "bin/semver.js" } }, "node_modules/eslint-plugin-jsx-a11y": { - "version": "6.8.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.8.0.tgz", - "integrity": "sha512-Hdh937BS3KdwwbBaKd5+PLCOmYY6U4f2h9Z2ktwtNKvIdIEu137rjYbcb9ApSbVJfWxANNuiKTD/9tOKjK9qOA==", + "version": "6.10.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.10.2.tgz", + "integrity": "sha512-scB3nz4WmG75pV8+3eRUQOHZlNSUhFNq37xnpgRkCCELU3XMvXAxLk1eqWWyE22Ki4Q01Fnsw9BA3cJHDPgn2Q==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/runtime": "^7.23.2", - "aria-query": "^5.3.0", - "array-includes": "^3.1.7", + "aria-query": "^5.3.2", + "array-includes": "^3.1.8", "array.prototype.flatmap": "^1.3.2", "ast-types-flow": "^0.0.8", - "axe-core": "=4.7.0", - "axobject-query": "^3.2.1", + "axe-core": "^4.10.0", + "axobject-query": "^4.1.0", "damerau-levenshtein": "^1.0.8", "emoji-regex": "^9.2.2", - "es-iterator-helpers": "^1.0.15", - "hasown": "^2.0.0", + "hasown": "^2.0.2", "jsx-ast-utils": "^3.3.5", "language-tags": "^1.0.9", "minimatch": "^3.1.2", - "object.entries": "^1.1.7", - "object.fromentries": "^2.0.7" + "object.fromentries": "^2.0.8", + "safe-regex-test": "^1.0.3", + "string.prototype.includes": "^2.0.1" }, "engines": { "node": ">=4.0" }, "peerDependencies": { - "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9" } }, "node_modules/eslint-plugin-react": { - "version": "7.34.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.34.1.tgz", - "integrity": "sha512-N97CxlouPT1AHt8Jn0mhhN2RrADlUAsk1/atcT2KyA/l9Q/E6ll7OIGwNumFmWfZ9skV3XXccYS19h80rHtgkw==", + "version": "7.37.5", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.5.tgz", + "integrity": "sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA==", "dev": true, + "license": "MIT", "dependencies": { - "array-includes": "^3.1.7", - "array.prototype.findlast": "^1.2.4", - "array.prototype.flatmap": "^1.3.2", - "array.prototype.toreversed": "^1.1.2", - "array.prototype.tosorted": "^1.1.3", + "array-includes": "^3.1.8", + "array.prototype.findlast": "^1.2.5", + "array.prototype.flatmap": "^1.3.3", + "array.prototype.tosorted": "^1.1.4", "doctrine": "^2.1.0", - "es-iterator-helpers": "^1.0.17", + "es-iterator-helpers": "^1.2.1", "estraverse": "^5.3.0", + "hasown": "^2.0.2", "jsx-ast-utils": "^2.4.1 || ^3.0.0", "minimatch": "^3.1.2", - "object.entries": "^1.1.7", - "object.fromentries": "^2.0.7", - "object.hasown": "^1.1.3", - "object.values": "^1.1.7", + "object.entries": "^1.1.9", + "object.fromentries": "^2.0.8", + "object.values": "^1.2.1", "prop-types": "^15.8.1", "resolve": "^2.0.0-next.5", "semver": "^6.3.1", - "string.prototype.matchall": "^4.0.10" + "string.prototype.matchall": "^4.0.12", + "string.prototype.repeat": "^1.0.0" }, "engines": { "node": ">=4" }, "peerDependencies": { - "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7" } }, "node_modules/eslint-plugin-react-hooks": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.0.tgz", - "integrity": "sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-5.2.0.tgz", + "integrity": "sha512-+f15FfK64YQwZdJNELETdn5ibXEUQmW1DZL6KXhNnc2heoy/sg9VJJeT7n8TlMWouzWqSWavFkIhHyIbIAEapg==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, "peerDependencies": { - "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0" - } - }, - "node_modules/eslint-plugin-react/node_modules/doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", - "dev": true, - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=0.10.0" + "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0" } }, "node_modules/eslint-plugin-react/node_modules/resolve": { @@ -4778,6 +5148,7 @@ "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz", "integrity": "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==", "dev": true, + "license": "MIT", "dependencies": { "is-core-module": "^2.13.0", "path-parse": "^1.0.7", @@ -4795,21 +5166,23 @@ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, + "license": "ISC", "bin": { "semver": "bin/semver.js" } }, "node_modules/eslint-scope": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", - "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", + "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" @@ -4827,18 +5200,45 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/eslint/node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, "node_modules/espree": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", - "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", + "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { - "acorn": "^8.9.0", + "acorn": "^8.15.0", "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.1" + "eslint-visitor-keys": "^4.2.1" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/espree/node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" @@ -4874,6 +5274,7 @@ "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "estraverse": "^5.2.0" }, @@ -4991,12 +5392,15 @@ "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/fast-glob": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", - "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz", + "integrity": "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==", + "dev": true, + "license": "MIT", "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", @@ -5012,6 +5416,8 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", "dependencies": { "is-glob": "^4.0.1" }, @@ -5023,7 +5429,8 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/fast-levenshtein": { "version": "2.0.6", @@ -5032,9 +5439,10 @@ "dev": true }, "node_modules/fastq": { - "version": "1.17.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", - "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", + "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", + "license": "ISC", "dependencies": { "reusify": "^1.0.4" } @@ -5046,15 +5454,16 @@ "license": "MIT" }, "node_modules/file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", "dev": true, + "license": "MIT", "dependencies": { - "flat-cache": "^3.0.4" + "flat-cache": "^4.0.0" }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": ">=16.0.0" } }, "node_modules/fill-range": { @@ -5086,40 +5495,49 @@ } }, "node_modules/flat-cache": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", - "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", "dev": true, + "license": "MIT", "dependencies": { "flatted": "^3.2.9", - "keyv": "^4.5.3", - "rimraf": "^3.0.2" + "keyv": "^4.5.4" }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": ">=16" } }, "node_modules/flatted": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", - "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", - "dev": true + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", + "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", + "dev": true, + "license": "ISC" }, "node_modules/for-each": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", - "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", + "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==", "dev": true, + "license": "MIT", "dependencies": { - "is-callable": "^1.1.3" + "is-callable": "^1.2.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/foreground-child": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", - "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", + "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", + "license": "ISC", "dependencies": { - "cross-spawn": "^7.0.0", + "cross-spawn": "^7.0.6", "signal-exit": "^4.0.1" }, "engines": { @@ -5172,12 +5590,6 @@ "url": "https://github.com/sponsors/rawify" } }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true - }, "node_modules/fsevents": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", @@ -5201,15 +5613,18 @@ } }, "node_modules/function.prototype.name": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", - "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.8.tgz", + "integrity": "sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "functions-have-names": "^1.2.3" + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "functions-have-names": "^1.2.3", + "hasown": "^2.0.2", + "is-callable": "^1.2.7" }, "engines": { "node": ">= 0.4" @@ -5228,16 +5643,21 @@ } }, "node_modules/get-intrinsic": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", - "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", - "dev": true, + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "license": "MIT", "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", "function-bind": "^1.1.2", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "hasown": "^2.0.0" + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" }, "engines": { "node": ">= 0.4" @@ -5250,19 +5670,34 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/get-nonce/-/get-nonce-1.0.1.tgz", "integrity": "sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==", + "license": "MIT", "engines": { "node": ">=6" } }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/get-symbol-description": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz", - "integrity": "sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz", + "integrity": "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.5", + "call-bound": "^1.0.3", "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4" + "get-intrinsic": "^1.2.6" }, "engines": { "node": ">= 0.4" @@ -5290,22 +5725,21 @@ "integrity": "sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw==" }, "node_modules/glob": { - "version": "10.3.10", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", - "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "license": "ISC", "dependencies": { "foreground-child": "^3.1.0", - "jackspeak": "^2.3.5", - "minimatch": "^9.0.1", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", - "path-scurry": "^1.10.1" + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" }, "bin": { "glob": "dist/esm/bin.mjs" }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, "funding": { "url": "https://github.com/sponsors/isaacs" } @@ -5322,17 +5756,19 @@ } }, "node_modules/glob/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" } }, "node_modules/glob/node_modules/minimatch": { - "version": "9.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz", - "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==", + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" }, @@ -5344,77 +5780,53 @@ } }, "node_modules/globals": { - "version": "13.24.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", "dev": true, - "dependencies": { - "type-fest": "^0.20.2" - }, + "license": "MIT", "engines": { - "node": ">=8" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/globalthis": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", - "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", - "dev": true, - "dependencies": { - "define-properties": "^1.1.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", + "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", "dev": true, + "license": "MIT", "dependencies": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" + "define-properties": "^1.2.1", + "gopd": "^1.0.1" }, "engines": { - "node": ">=10" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/gopd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", - "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", - "dev": true, - "dependencies": { - "get-intrinsic": "^1.1.3" + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" - }, "node_modules/graphemer": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/gray-matter": { "version": "4.0.3", @@ -5503,10 +5915,14 @@ } }, "node_modules/has-proto": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", - "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.2.0.tgz", + "integrity": "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==", "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.0" + }, "engines": { "node": ">= 0.4" }, @@ -5515,9 +5931,10 @@ } }, "node_modules/has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -5805,9 +6222,9 @@ } }, "node_modules/highlight.js": { - "version": "11.10.0", - "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-11.10.0.tgz", - "integrity": "sha512-SYVnVFswQER+zu1laSya563s+F8VDGt7o35d4utbamowvUNLLMovFqwCLSocpZTz3MgaSRA1IbqRWZv97dtErQ==", + "version": "11.11.1", + "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-11.11.1.tgz", + "integrity": "sha512-Xwwo44whKBVCYoliBQwaPvtd/2tYFkRQtXDWj1nackaV2JPXx3L0+Jvd8/qCJ2p+ML0/XVkJ2q+Mr+UVdpJK5w==", "dev": true, "license": "BSD-3-Clause", "engines": { @@ -5837,10 +6254,11 @@ } }, "node_modules/import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", "dev": true, + "license": "MIT", "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" @@ -5861,16 +6279,6 @@ "node": ">=0.8.19" } }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "dev": true, - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", @@ -5882,14 +6290,15 @@ "integrity": "sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q==" }, "node_modules/internal-slot": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz", - "integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz", + "integrity": "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==", "dev": true, + "license": "MIT", "dependencies": { "es-errors": "^1.3.0", - "hasown": "^2.0.0", - "side-channel": "^1.0.4" + "hasown": "^2.0.2", + "side-channel": "^1.1.0" }, "engines": { "node": ">= 0.4" @@ -5918,13 +6327,15 @@ } }, "node_modules/is-array-buffer": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", - "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz", + "integrity": "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.1" + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" }, "engines": { "node": ">= 0.4" @@ -5933,13 +6344,25 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-arrayish": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", + "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==", + "license": "MIT", + "optional": true + }, "node_modules/is-async-function": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.0.0.tgz", - "integrity": "sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.1.tgz", + "integrity": "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==", "dev": true, + "license": "MIT", "dependencies": { - "has-tostringtag": "^1.0.0" + "async-function": "^1.0.0", + "call-bound": "^1.0.3", + "get-proto": "^1.0.1", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" }, "engines": { "node": ">= 0.4" @@ -5949,12 +6372,16 @@ } }, "node_modules/is-bigint": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", - "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.1.0.tgz", + "integrity": "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==", "dev": true, + "license": "MIT", "dependencies": { - "has-bigints": "^1.0.1" + "has-bigints": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -5964,6 +6391,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "license": "MIT", "dependencies": { "binary-extensions": "^2.0.0" }, @@ -5972,13 +6400,14 @@ } }, "node_modules/is-boolean-object": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", - "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.2.tgz", + "integrity": "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -5992,6 +6421,16 @@ "resolved": "https://registry.npmjs.org/is-browser/-/is-browser-2.1.0.tgz", "integrity": "sha512-F5rTJxDQ2sW81fcfOR1GnCXT6sVJC104fCyfj+mjpwNEwaPYSn5fte5jiHmBg3DHsIoL/l8Kvw5VN5SsTRcRFQ==" }, + "node_modules/is-bun-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-bun-module/-/is-bun-module-2.0.0.tgz", + "integrity": "sha512-gNCGbnnnnFAUGKeZ9PdbyeGYJqewpmc2aKHUEMO5nQPWU9lOmv7jcmQIv+qHD8fXW6W7qfuCwX4rY9LNRjXrkQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^7.7.1" + } + }, "node_modules/is-callable": { "version": "1.2.7", "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", @@ -6005,22 +6444,29 @@ } }, "node_modules/is-core-module": { - "version": "2.13.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", - "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", + "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", + "license": "MIT", "dependencies": { - "hasown": "^2.0.0" + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/is-data-view": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.1.tgz", - "integrity": "sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.2.tgz", + "integrity": "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==", "dev": true, + "license": "MIT", "dependencies": { + "call-bound": "^1.0.2", + "get-intrinsic": "^1.2.6", "is-typed-array": "^1.1.13" }, "engines": { @@ -6031,12 +6477,14 @@ } }, "node_modules/is-date-object": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", - "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.1.0.tgz", + "integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==", "dev": true, + "license": "MIT", "dependencies": { - "has-tostringtag": "^1.0.0" + "call-bound": "^1.0.2", + "has-tostringtag": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -6072,12 +6520,16 @@ } }, "node_modules/is-finalizationregistry": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.0.2.tgz", - "integrity": "sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz", + "integrity": "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2" + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -6087,17 +6539,22 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/is-generator-function": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", - "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.0.tgz", + "integrity": "sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ==", "dev": true, + "license": "MIT", "dependencies": { - "has-tostringtag": "^1.0.0" + "call-bound": "^1.0.3", + "get-proto": "^1.0.0", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" }, "engines": { "node": ">= 0.4" @@ -6131,6 +6588,7 @@ "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -6160,12 +6618,14 @@ } }, "node_modules/is-number-object": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", - "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.1.tgz", + "integrity": "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==", "dev": true, + "license": "MIT", "dependencies": { - "has-tostringtag": "^1.0.0" + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -6182,15 +6642,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/is-plain-obj": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", @@ -6211,13 +6662,16 @@ } }, "node_modules/is-regex": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", - "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", + "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" + "call-bound": "^1.0.2", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" }, "engines": { "node": ">= 0.4" @@ -6239,12 +6693,13 @@ } }, "node_modules/is-shared-array-buffer": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz", - "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz", + "integrity": "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.7" + "call-bound": "^1.0.3" }, "engines": { "node": ">= 0.4" @@ -6262,11 +6717,13 @@ } }, "node_modules/is-string": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", - "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz", + "integrity": "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==", + "license": "MIT", "dependencies": { - "has-tostringtag": "^1.0.0" + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -6276,12 +6733,15 @@ } }, "node_modules/is-symbol": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", - "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.1.1.tgz", + "integrity": "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==", "dev": true, + "license": "MIT", "dependencies": { - "has-symbols": "^1.0.2" + "call-bound": "^1.0.2", + "has-symbols": "^1.1.0", + "safe-regex-test": "^1.1.0" }, "engines": { "node": ">= 0.4" @@ -6291,12 +6751,13 @@ } }, "node_modules/is-typed-array": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", - "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz", + "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==", "dev": true, + "license": "MIT", "dependencies": { - "which-typed-array": "^1.1.14" + "which-typed-array": "^1.1.16" }, "engines": { "node": ">= 0.4" @@ -6310,6 +6771,7 @@ "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -6318,25 +6780,30 @@ } }, "node_modules/is-weakref": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", - "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.1.tgz", + "integrity": "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2" + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/is-weakset": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.3.tgz", - "integrity": "sha512-LvIm3/KWzS9oRFHugab7d+M/GcBXuXX5xZkzPmN+NxihdQlZUQ4dWuSV1xR/sq6upL1TJEDrfBgRepHFdBtSNQ==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.4.tgz", + "integrity": "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", - "get-intrinsic": "^1.2.4" + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" }, "engines": { "node": ">= 0.4" @@ -6365,28 +6832,31 @@ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" }, "node_modules/iterator.prototype": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.2.tgz", - "integrity": "sha512-DR33HMMr8EzwuRL8Y9D3u2BMj8+RqSE850jfGu59kS7tbmPLzGkZmVSfyCFSDxuZiEY6Rzt3T2NA/qU+NwVj1w==", + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.5.tgz", + "integrity": "sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==", "dev": true, + "license": "MIT", "dependencies": { - "define-properties": "^1.2.1", - "get-intrinsic": "^1.2.1", - "has-symbols": "^1.0.3", - "reflect.getprototypeof": "^1.0.4", - "set-function-name": "^2.0.1" + "define-data-property": "^1.1.4", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.6", + "get-proto": "^1.0.0", + "has-symbols": "^1.1.0", + "set-function-name": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" } }, "node_modules/jackspeak": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", - "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "license": "BlueOak-1.0.0", "dependencies": { "@isaacs/cliui": "^8.0.2" }, - "engines": { - "node": ">=14" - }, "funding": { "url": "https://github.com/sponsors/isaacs" }, @@ -6395,9 +6865,10 @@ } }, "node_modules/jiti": { - "version": "1.21.0", - "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.0.tgz", - "integrity": "sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q==", + "version": "1.21.7", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.7.tgz", + "integrity": "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==", + "license": "MIT", "bin": { "jiti": "bin/jiti.js" } @@ -6412,6 +6883,7 @@ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "dev": true, + "license": "MIT", "dependencies": { "argparse": "^2.0.1" }, @@ -6423,13 +6895,15 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/json-stable-stringify-without-jsonify": { "version": "1.0.1", @@ -6442,6 +6916,7 @@ "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", "dev": true, + "license": "MIT", "dependencies": { "minimist": "^1.2.0" }, @@ -6469,6 +6944,7 @@ "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", "dev": true, + "license": "MIT", "dependencies": { "json-buffer": "3.0.1" } @@ -6483,16 +6959,18 @@ } }, "node_modules/language-subtag-registry": { - "version": "0.3.22", - "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.22.tgz", - "integrity": "sha512-tN0MCzyWnoz/4nHS6uxdlFWoUZT7ABptwKPQ52Ea7URk6vll88bWBVhodtnlfEuCcKWNGoc+uGbw1cwa9IKh/w==", - "dev": true + "version": "0.3.23", + "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.23.tgz", + "integrity": "sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ==", + "dev": true, + "license": "CC0-1.0" }, "node_modules/language-tags": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.9.tgz", "integrity": "sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==", "dev": true, + "license": "MIT", "dependencies": { "language-subtag-registry": "^0.3.20" }, @@ -6514,11 +6992,15 @@ } }, "node_modules/lilconfig": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", - "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz", + "integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==", + "license": "MIT", "engines": { - "node": ">=10" + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antonk52" } }, "node_modules/limited-request-queue": { @@ -6546,7 +7028,8 @@ "node_modules/lines-and-columns": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==" + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "license": "MIT" }, "node_modules/link-types": { "version": "1.1.0", @@ -6606,6 +7089,8 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dev": true, + "license": "MIT", "dependencies": { "js-tokens": "^3.0.0 || ^4.0.0" }, @@ -6614,19 +7099,18 @@ } }, "node_modules/lru-cache": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.0.tgz", - "integrity": "sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==", - "engines": { - "node": "14 || >=16.14" - } + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "license": "ISC" }, "node_modules/lucide-react": { - "version": "0.435.0", - "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.435.0.tgz", - "integrity": "sha512-we5GKfzjMDw9m9SsyZJvWim9qaT+Ya5kaRS+OGFqgLqXUrPM1h+7CiMw5pKdEIoaBqfXz2pyv9TASAdpIAJs0Q==", + "version": "0.537.0", + "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.537.0.tgz", + "integrity": "sha512-VxWsdxBGeFnlC+HwMg/l08HptN4YRU9o/lRog156jOmRxI1ERKqN+rJiNY/mPcKAdWdM0UbyO8ft1o0jq69SSQ==", + "license": "ISC", "peerDependencies": { - "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0-rc" + "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "node_modules/lunr": { @@ -6662,6 +7146,15 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/maybe-callback": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/maybe-callback/-/maybe-callback-2.1.0.tgz", @@ -6991,6 +7484,7 @@ "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "license": "MIT", "engines": { "node": ">= 8" } @@ -7722,9 +8216,10 @@ } }, "node_modules/minipass": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", - "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "license": "ISC", "engines": { "node": ">=16 || 14 >=14.17" } @@ -7738,6 +8233,7 @@ "version": "2.7.0", "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", + "license": "MIT", "dependencies": { "any-promise": "^1.0.0", "object-assign": "^4.0.1", @@ -7762,6 +8258,22 @@ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, + "node_modules/napi-postinstall": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/napi-postinstall/-/napi-postinstall-0.3.2.tgz", + "integrity": "sha512-tWVJxJHmBWLy69PvO96TZMZDrzmw5KeiZBz3RHmiM2XZ9grBJ2WgMAFVVg25nqp3ZjTFUs2Ftw1JhscL3Teliw==", + "dev": true, + "license": "MIT", + "bin": { + "napi-postinstall": "lib/cli.js" + }, + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/napi-postinstall" + } + }, "node_modules/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -7769,41 +8281,40 @@ "dev": true }, "node_modules/next": { - "version": "14.2.26", - "resolved": "https://registry.npmjs.org/next/-/next-14.2.26.tgz", - "integrity": "sha512-b81XSLihMwCfwiUVRRja3LphLo4uBBMZEzBBWMaISbKTwOmq3wPknIETy/8000tr7Gq4WmbuFYPS7jOYIf+ZJw==", + "version": "15.4.6", + "resolved": "https://registry.npmjs.org/next/-/next-15.4.6.tgz", + "integrity": "sha512-us++E/Q80/8+UekzB3SAGs71AlLDsadpFMXVNM/uQ0BMwsh9m3mr0UNQIfjKed8vpWXsASe+Qifrnu1oLIcKEQ==", "license": "MIT", "dependencies": { - "@next/env": "14.2.26", - "@swc/helpers": "0.5.5", - "busboy": "1.6.0", + "@next/env": "15.4.6", + "@swc/helpers": "0.5.15", "caniuse-lite": "^1.0.30001579", - "graceful-fs": "^4.2.11", "postcss": "8.4.31", - "styled-jsx": "5.1.1" + "styled-jsx": "5.1.6" }, "bin": { "next": "dist/bin/next" }, "engines": { - "node": ">=18.17.0" + "node": "^18.18.0 || ^19.8.0 || >= 20.0.0" }, "optionalDependencies": { - "@next/swc-darwin-arm64": "14.2.26", - "@next/swc-darwin-x64": "14.2.26", - "@next/swc-linux-arm64-gnu": "14.2.26", - "@next/swc-linux-arm64-musl": "14.2.26", - "@next/swc-linux-x64-gnu": "14.2.26", - "@next/swc-linux-x64-musl": "14.2.26", - "@next/swc-win32-arm64-msvc": "14.2.26", - "@next/swc-win32-ia32-msvc": "14.2.26", - "@next/swc-win32-x64-msvc": "14.2.26" + "@next/swc-darwin-arm64": "15.4.6", + "@next/swc-darwin-x64": "15.4.6", + "@next/swc-linux-arm64-gnu": "15.4.6", + "@next/swc-linux-arm64-musl": "15.4.6", + "@next/swc-linux-x64-gnu": "15.4.6", + "@next/swc-linux-x64-musl": "15.4.6", + "@next/swc-win32-arm64-msvc": "15.4.6", + "@next/swc-win32-x64-msvc": "15.4.6", + "sharp": "^0.34.3" }, "peerDependencies": { "@opentelemetry/api": "^1.1.0", - "@playwright/test": "^1.41.2", - "react": "^18.2.0", - "react-dom": "^18.2.0", + "@playwright/test": "^1.51.1", + "babel-plugin-react-compiler": "*", + "react": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", + "react-dom": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", "sass": "^1.3.0" }, "peerDependenciesMeta": { @@ -7813,6 +8324,9 @@ "@playwright/test": { "optional": true }, + "babel-plugin-react-compiler": { + "optional": true + }, "sass": { "optional": true } @@ -7839,12 +8353,13 @@ } }, "node_modules/next-themes": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/next-themes/-/next-themes-0.3.0.tgz", - "integrity": "sha512-/QHIrsYpd6Kfk7xakK4svpDI5mmXP0gfvCoJdGpZQ2TOrQZmsW0QxjaiLn8wbIKjtm4BTSqLoix4lxYYOnLJ/w==", + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/next-themes/-/next-themes-0.4.6.tgz", + "integrity": "sha512-pZvgD5L0IEvX5/9GWyHMf3m8BKiVQwsCMHfoFosXtXBMnaS0ZnIJ9ST4b4NqLVKDEm8QBxoNNGNaBv2JNF6XNA==", + "license": "MIT", "peerDependencies": { - "react": "^16.8 || ^17 || ^18", - "react-dom": "^16.8 || ^17 || ^18" + "react": "^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc" } }, "node_modules/next/node_modules/postcss": { @@ -7875,10 +8390,11 @@ } }, "node_modules/node-releases": { - "version": "2.0.18", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz", - "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==", - "dev": true + "version": "2.0.19", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", + "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==", + "dev": true, + "license": "MIT" }, "node_modules/nopt": { "version": "3.0.6", @@ -8000,6 +8516,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -8025,15 +8542,20 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", + "license": "MIT", "engines": { "node": ">= 6" } }, "node_modules/object-inspect": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", - "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -8048,14 +8570,17 @@ } }, "node_modules/object.assign": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", - "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz", + "integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.5", + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", "define-properties": "^1.2.1", - "has-symbols": "^1.0.3", + "es-object-atoms": "^1.0.0", + "has-symbols": "^1.1.0", "object-keys": "^1.1.1" }, "engines": { @@ -8066,14 +8591,16 @@ } }, "node_modules/object.entries": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.8.tgz", - "integrity": "sha512-cmopxi8VwRIAw/fkijJohSfpef5PdN0pMQJN6VC/ZKvn0LIknWD8KtgY6KlQdEc4tIjcQ3HxSMmnvtzIscdaYQ==", + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.9.tgz", + "integrity": "sha512-8u/hfXFRBD1O0hPUjioLhoWFHRmt6tKA4/vZPyckBr18l1KE9uHrFaFaUi8MDRTpi4uak2goyPTSNJLXX2k2Hw==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0" + "es-object-atoms": "^1.1.1" }, "engines": { "node": ">= 0.4" @@ -8102,6 +8629,7 @@ "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz", "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", @@ -8111,30 +8639,15 @@ "node": ">= 0.4" } }, - "node_modules/object.hasown": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/object.hasown/-/object.hasown-1.1.4.tgz", - "integrity": "sha512-FZ9LZt9/RHzGySlBARE3VF+gE26TxR38SdmqOqliuTnl9wrKulaQs+4dee1V+Io8VfxqzAfHu6YuRgUy8OHoTg==", - "dev": true, - "dependencies": { - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/object.values": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.0.tgz", - "integrity": "sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.1.tgz", + "integrity": "sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", "define-properties": "^1.2.1", "es-object-atoms": "^1.0.0" }, @@ -8145,15 +8658,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, - "dependencies": { - "wrappy": "1" - } - }, "node_modules/optionator": { "version": "0.9.3", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", @@ -8208,6 +8712,24 @@ "node": ">=0.10.0" } }, + "node_modules/own-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/own-keys/-/own-keys-1.0.1.tgz", + "integrity": "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "get-intrinsic": "^1.2.6", + "object-keys": "^1.1.1", + "safe-push-apply": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/p-limit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", @@ -8238,6 +8760,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "license": "BlueOak-1.0.0" + }, "node_modules/pako": { "version": "0.2.9", "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz", @@ -8249,6 +8777,7 @@ "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", "dev": true, + "license": "MIT", "dependencies": { "callsites": "^3.0.0" }, @@ -8321,15 +8850,6 @@ "node": ">=8" } }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", @@ -8344,27 +8864,19 @@ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" }, "node_modules/path-scurry": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.2.tgz", - "integrity": "sha512-7xTavNy5RQXnsjANvVvMkEjvloOinkAjv/Z6Ildz9v2RinZ4SBKTWFOVRbaF8p0vpHnyjV/UwNDdKuUv6M5qcA==", + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "license": "BlueOak-1.0.0", "dependencies": { "lru-cache": "^10.2.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true, + }, "engines": { - "node": ">=8" + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/periscopic": { @@ -8378,14 +8890,16 @@ } }, "node_modules/picocolors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz", - "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==" + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "license": "ISC" }, "node_modules/picomatch": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "license": "MIT", "engines": { "node": ">=8.6" }, @@ -8397,14 +8911,16 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/pirates": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", - "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz", + "integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==", + "license": "MIT", "engines": { "node": ">= 6" } @@ -8419,9 +8935,9 @@ } }, "node_modules/postcss": { - "version": "8.4.38", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.38.tgz", - "integrity": "sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==", + "version": "8.5.6", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", + "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", "funding": [ { "type": "opencollective", @@ -8436,10 +8952,11 @@ "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "dependencies": { - "nanoid": "^3.3.7", - "picocolors": "^1.0.0", - "source-map-js": "^1.2.0" + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" }, "engines": { "node": "^10 || ^12 || >=14" @@ -8449,6 +8966,7 @@ "version": "15.1.0", "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz", "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==", + "license": "MIT", "dependencies": { "postcss-value-parser": "^4.0.0", "read-cache": "^1.0.0", @@ -8465,6 +8983,7 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz", "integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==", + "license": "MIT", "dependencies": { "camelcase-css": "^2.0.1" }, @@ -8493,6 +9012,7 @@ "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "dependencies": { "lilconfig": "^3.0.0", "yaml": "^2.3.4" @@ -8513,39 +9033,36 @@ } } }, - "node_modules/postcss-load-config/node_modules/lilconfig": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.1.tgz", - "integrity": "sha512-O18pf7nyvHTckunPWCV1XUNXU1piu01y2b7ATJ0ppkUkk8ocqVWBrYjJBCwHDjD/ZWcfyrA0P4gKhzWGi5EINQ==", - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/antonk52" - } - }, "node_modules/postcss-nested": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.0.1.tgz", - "integrity": "sha512-mEp4xPMi5bSWiMbsgoPfcP74lsWLHkQbZc3sY+jWYd65CUwXrUaTp0fmNpa01ZcETKlIgUdFN/MpS2xZtqL9dQ==", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz", + "integrity": "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", "dependencies": { - "postcss-selector-parser": "^6.0.11" + "postcss-selector-parser": "^6.1.1" }, "engines": { "node": ">=12.0" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, "peerDependencies": { "postcss": "^8.2.14" } }, "node_modules/postcss-selector-parser": { - "version": "6.0.16", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.16.tgz", - "integrity": "sha512-A0RVJrX+IUkVZbW3ClroRWurercFhieevHB38sr2+l9eUClMqome3LmEmnhlNy+5Mr2EYN6B2Kaw9wYdd+VHiw==", + "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==", + "license": "MIT", "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -8594,6 +9111,7 @@ "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", "dev": true, + "license": "MIT", "dependencies": { "loose-envify": "^1.4.0", "object-assign": "^4.1.1", @@ -8655,29 +9173,28 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "license": "MIT" }, "node_modules/react": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", - "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", - "dependencies": { - "loose-envify": "^1.1.0" - }, + "version": "19.1.1", + "resolved": "https://registry.npmjs.org/react/-/react-19.1.1.tgz", + "integrity": "sha512-w8nqGImo45dmMIfljjMwOGtbmC/mk4CMYhWIicdSflH91J9TyCyczcPFXJzrZ/ZXcgGRFeP6BU0BEJTw6tZdfQ==", + "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/react-dom": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", - "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", + "version": "19.1.1", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.1.1.tgz", + "integrity": "sha512-Dlq/5LAZgF0Gaz6yiqZCf6VCcZs1ghAJyrsu84Q/GT0gV+mCxbfmKNoGRKBYMJ8IEdGPqu49YWXD02GCknEDkw==", + "license": "MIT", "dependencies": { - "loose-envify": "^1.1.0", - "scheduler": "^0.23.2" + "scheduler": "^0.26.0" }, "peerDependencies": { - "react": "^18.3.1" + "react": "^19.1.1" } }, "node_modules/react-highlight": { @@ -8717,25 +9234,27 @@ "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/react-remove-scroll": { - "version": "2.5.7", - "resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.5.7.tgz", - "integrity": "sha512-FnrTWO4L7/Bhhf3CYBNArEG/yROV0tKmTv7/3h9QCFvH6sndeFf1wPqOcbFVu5VAulS5dV1wGT3GZZ/1GawqiA==", + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.7.1.tgz", + "integrity": "sha512-HpMh8+oahmIdOuS5aFKKY6Pyog+FNaZV/XyJOq7b4YFwsFHe5yYfdbIalI4k3vU2nSDql7YskmUseHsRrJqIPA==", + "license": "MIT", "dependencies": { - "react-remove-scroll-bar": "^2.3.4", - "react-style-singleton": "^2.2.1", + "react-remove-scroll-bar": "^2.3.7", + "react-style-singleton": "^2.2.3", "tslib": "^2.1.0", - "use-callback-ref": "^1.3.0", - "use-sidecar": "^1.1.2" + "use-callback-ref": "^1.3.3", + "use-sidecar": "^1.1.3" }, "engines": { "node": ">=10" }, "peerDependencies": { - "@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" }, "peerDependenciesMeta": { "@types/react": { @@ -8791,6 +9310,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", + "license": "MIT", "dependencies": { "pify": "^2.3.0" } @@ -8818,6 +9338,7 @@ "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "license": "MIT", "dependencies": { "picomatch": "^2.2.1" }, @@ -8826,18 +9347,20 @@ } }, "node_modules/reflect.getprototypeof": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.6.tgz", - "integrity": "sha512-fmfw4XgoDke3kdI6h4xcUz1dG8uaiv5q9gcEwLS4Pnth2kxT+GZ7YehS1JTMGBQmtV7Y4GFGbs2re2NqhdozUg==", + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz", + "integrity": "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", "define-properties": "^1.2.1", - "es-abstract": "^1.23.1", + "es-abstract": "^1.23.9", "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4", - "globalthis": "^1.0.3", - "which-builtin-type": "^1.1.3" + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.7", + "get-proto": "^1.0.1", + "which-builtin-type": "^1.2.1" }, "engines": { "node": ">= 0.4" @@ -8876,22 +9399,19 @@ "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==", "license": "MIT" }, - "node_modules/regenerator-runtime": { - "version": "0.14.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", - "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==", - "dev": true - }, "node_modules/regexp.prototype.flags": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz", - "integrity": "sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==", + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz", + "integrity": "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.6", + "call-bind": "^1.0.8", "define-properties": "^1.2.1", "es-errors": "^1.3.0", - "set-function-name": "^2.0.1" + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "set-function-name": "^2.0.2" }, "engines": { "node": ">= 0.4" @@ -8965,9 +9485,10 @@ } }, "node_modules/rehype-prism-plus": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/rehype-prism-plus/-/rehype-prism-plus-2.0.0.tgz", - "integrity": "sha512-FeM/9V2N7EvDZVdR2dqhAzlw5YI49m9Tgn7ZrYJeYHIahM6gcXpH0K1y2gNnKanZCydOMluJvX2cB9z3lhY8XQ==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/rehype-prism-plus/-/rehype-prism-plus-2.0.1.tgz", + "integrity": "sha512-Wglct0OW12tksTUseAPyWPo3srjBOY7xKlql/DPKi7HbsdZTyaLCAoO58QBKSczFQxElTsQlOY3JDOFzB/K++Q==", + "license": "MIT", "dependencies": { "hast-util-to-string": "^3.0.0", "parse-numeric-range": "^1.3.0", @@ -9011,9 +9532,10 @@ } }, "node_modules/remark-gfm": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/remark-gfm/-/remark-gfm-4.0.0.tgz", - "integrity": "sha512-U92vJgBPkbw4Zfu/IiW2oTZLSL3Zpv+uI7My2eq8JxKgqraFdU8YUGicEJCEgSbeaG+QDFqIcwwfMTOEelPxuA==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/remark-gfm/-/remark-gfm-4.0.1.tgz", + "integrity": "sha512-1quofZ2RQ9EWdeN34S79+KExV1764+wCUGop5CPL1WGdD0ocPpu91lzPGbwWMECpEpd42kJGQwzRfyov9j4yNg==", + "license": "MIT", "dependencies": { "@types/mdast": "^4.0.0", "mdast-util-gfm": "^3.0.0", @@ -9108,6 +9630,7 @@ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } @@ -9122,49 +9645,15 @@ } }, "node_modules/reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", + "license": "MIT", "engines": { "iojs": ">=1.0.0", "node": ">=0.10.0" } }, - "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/rimraf/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/robot-directives": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/robot-directives/-/robot-directives-0.3.0.tgz", @@ -9211,19 +9700,22 @@ "url": "https://feross.org/support" } ], + "license": "MIT", "dependencies": { "queue-microtask": "^1.2.2" } }, "node_modules/safe-array-concat": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.2.tgz", - "integrity": "sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.3.tgz", + "integrity": "sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", - "get-intrinsic": "^1.2.4", - "has-symbols": "^1.0.3", + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "get-intrinsic": "^1.2.6", + "has-symbols": "^1.1.0", "isarray": "^2.0.5" }, "engines": { @@ -9238,15 +9730,33 @@ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" }, + "node_modules/safe-push-apply": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz", + "integrity": "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/safe-regex-test": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz", - "integrity": "sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz", + "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.6", + "call-bound": "^1.0.2", "es-errors": "^1.3.0", - "is-regex": "^1.1.4" + "is-regex": "^1.2.1" }, "engines": { "node": ">= 0.4" @@ -9278,12 +9788,10 @@ } }, "node_modules/scheduler": { - "version": "0.23.2", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", - "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", - "dependencies": { - "loose-envify": "^1.1.0" - } + "version": "0.26.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.26.0.tgz", + "integrity": "sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA==", + "license": "MIT" }, "node_modules/section-matter": { "version": "1.0.0", @@ -9299,13 +9807,11 @@ } }, "node_modules/semver": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", - "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "devOptional": true, + "license": "ISC", "bin": { "semver": "bin/semver.js" }, @@ -9313,18 +9819,6 @@ "node": ">=10" } }, - "node_modules/semver/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/set-function-length": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", @@ -9357,6 +9851,64 @@ "node": ">= 0.4" } }, + "node_modules/set-proto": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/set-proto/-/set-proto-1.0.0.tgz", + "integrity": "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/sharp": { + "version": "0.34.3", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.3.tgz", + "integrity": "sha512-eX2IQ6nFohW4DbvHIOLRB3MHFpYqaqvXd3Tp5e/T/dSH83fxaNJQRvDMhASmkNTsNTVF2/OOopzRCt7xokgPfg==", + "hasInstallScript": true, + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "color": "^4.2.3", + "detect-libc": "^2.0.4", + "semver": "^7.7.2" + }, + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-darwin-arm64": "0.34.3", + "@img/sharp-darwin-x64": "0.34.3", + "@img/sharp-libvips-darwin-arm64": "1.2.0", + "@img/sharp-libvips-darwin-x64": "1.2.0", + "@img/sharp-libvips-linux-arm": "1.2.0", + "@img/sharp-libvips-linux-arm64": "1.2.0", + "@img/sharp-libvips-linux-ppc64": "1.2.0", + "@img/sharp-libvips-linux-s390x": "1.2.0", + "@img/sharp-libvips-linux-x64": "1.2.0", + "@img/sharp-libvips-linuxmusl-arm64": "1.2.0", + "@img/sharp-libvips-linuxmusl-x64": "1.2.0", + "@img/sharp-linux-arm": "0.34.3", + "@img/sharp-linux-arm64": "0.34.3", + "@img/sharp-linux-ppc64": "0.34.3", + "@img/sharp-linux-s390x": "0.34.3", + "@img/sharp-linux-x64": "0.34.3", + "@img/sharp-linuxmusl-arm64": "0.34.3", + "@img/sharp-linuxmusl-x64": "0.34.3", + "@img/sharp-wasm32": "0.34.3", + "@img/sharp-win32-arm64": "0.34.3", + "@img/sharp-win32-ia32": "0.34.3", + "@img/sharp-win32-x64": "0.34.3" + } + }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -9377,15 +9929,73 @@ } }, "node_modules/side-channel": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", - "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4", - "object-inspect": "^1.13.1" + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" }, "engines": { "node": ">= 0.4" @@ -9398,6 +10008,7 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "license": "ISC", "engines": { "node": ">=14" }, @@ -9405,13 +10016,14 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true, - "engines": { - "node": ">=8" + "node_modules/simple-swizzle": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", + "integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==", + "license": "MIT", + "optional": true, + "dependencies": { + "is-arrayish": "^0.3.1" } }, "node_modules/source-map": { @@ -9423,9 +10035,10 @@ } }, "node_modules/source-map-js": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", - "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" } @@ -9461,6 +10074,27 @@ "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", "license": "BSD-3-Clause" }, + "node_modules/stable-hash": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/stable-hash/-/stable-hash-0.0.5.tgz", + "integrity": "sha512-+L3ccpzibovGXFK+Ap/f8LOS0ahMrHTf3xu7mMLSpEGU0EO9ucaysSylKo9eRDFNhWve/y275iPmIZ4z39a9iA==", + "dev": true, + "license": "MIT" + }, + "node_modules/stop-iteration-iterator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.1.0.tgz", + "integrity": "sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "internal-slot": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/stream-combiner": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.2.2.tgz", @@ -9478,14 +10112,6 @@ "bluebird": "^2.6.2" } }, - "node_modules/streamsearch": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", - "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", - "engines": { - "node": ">=10.0.0" - } - }, "node_modules/string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", @@ -9498,6 +10124,7 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "license": "MIT", "dependencies": { "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", @@ -9515,6 +10142,7 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -9524,34 +10152,31 @@ "node": ">=8" } }, - "node_modules/string-width-cjs/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" - }, - "node_modules/string-width/node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "node_modules/string-width-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" + "node": ">=8" } }, - "node_modules/string-width/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "node_modules/string-width-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" + }, + "node_modules/string-width-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", "dependencies": { - "ansi-regex": "^6.0.1" + "ansi-regex": "^5.0.1" }, "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" + "node": ">=8" } }, "node_modules/string.prototype.codepointat": { @@ -9560,24 +10185,41 @@ "integrity": "sha512-2cBVCj6I4IOvEnjgO/hWqXjqBGsY+zwPmHl12Srk9IXSZ56Jwwmy+66XO5Iut/oQVR7t5ihYdLB0GMa4alEUcg==", "license": "MIT" }, - "node_modules/string.prototype.matchall": { - "version": "4.0.11", - "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.11.tgz", - "integrity": "sha512-NUdh0aDavY2og7IbBPenWqR9exH+E26Sv8e0/eTe1tltDGZL+GtBkDAnnyBtmekfK6/Dq3MkcGtzXFEd1LQrtg==", + "node_modules/string.prototype.includes": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/string.prototype.includes/-/string.prototype.includes-2.0.1.tgz", + "integrity": "sha512-o7+c9bW6zpAdJHTtujeePODAhkuicdAryFsfVKwA+wGw89wJ4GTY484WTucM9hLtDEOpOvI+aHnzqnC5lHp4Rg==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", + "es-abstract": "^1.23.3" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/string.prototype.matchall": { + "version": "4.0.12", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.12.tgz", + "integrity": "sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.6", "es-errors": "^1.3.0", "es-object-atoms": "^1.0.0", - "get-intrinsic": "^1.2.4", - "gopd": "^1.0.1", - "has-symbols": "^1.0.3", - "internal-slot": "^1.0.7", - "regexp.prototype.flags": "^1.5.2", + "get-intrinsic": "^1.2.6", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "internal-slot": "^1.1.0", + "regexp.prototype.flags": "^1.5.3", "set-function-name": "^2.0.2", - "side-channel": "^1.0.6" + "side-channel": "^1.1.0" }, "engines": { "node": ">= 0.4" @@ -9586,16 +10228,31 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/string.prototype.repeat": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/string.prototype.repeat/-/string.prototype.repeat-1.0.0.tgz", + "integrity": "sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + } + }, "node_modules/string.prototype.trim": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz", - "integrity": "sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==", + "version": "1.2.10", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.10.tgz", + "integrity": "sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "define-data-property": "^1.1.4", "define-properties": "^1.2.1", - "es-abstract": "^1.23.0", - "es-object-atoms": "^1.0.0" + "es-abstract": "^1.23.5", + "es-object-atoms": "^1.0.0", + "has-property-descriptors": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -9605,15 +10262,20 @@ } }, "node_modules/string.prototype.trimend": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz", - "integrity": "sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==", + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.9.tgz", + "integrity": "sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", "define-properties": "^1.2.1", "es-object-atoms": "^1.0.0" }, + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -9649,14 +10311,18 @@ } }, "node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "license": "MIT", "dependencies": { - "ansi-regex": "^5.0.1" + "ansi-regex": "^6.0.1" }, "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, "node_modules/strip-ansi-cjs": { @@ -9664,6 +10330,7 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", "dependencies": { "ansi-regex": "^5.0.1" }, @@ -9671,11 +10338,21 @@ "node": ">=8" } }, + "node_modules/strip-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/strip-bom": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } @@ -9694,6 +10371,7 @@ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" }, @@ -9723,9 +10401,10 @@ } }, "node_modules/styled-jsx": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.1.tgz", - "integrity": "sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw==", + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.6.tgz", + "integrity": "sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA==", + "license": "MIT", "dependencies": { "client-only": "0.0.1" }, @@ -9733,7 +10412,7 @@ "node": ">= 12.0.0" }, "peerDependencies": { - "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0" + "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0 || ^19.0.0-0" }, "peerDependenciesMeta": { "@babel/core": { @@ -9748,6 +10427,7 @@ "version": "3.35.0", "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz", "integrity": "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==", + "license": "MIT", "dependencies": { "@jridgewell/gen-mapping": "^0.3.2", "commander": "^4.0.0", @@ -9789,41 +10469,43 @@ } }, "node_modules/tailwind-merge": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-2.5.2.tgz", - "integrity": "sha512-kjEBm+pvD+6eAwzJL2Bi+02/9LFLal1Gs61+QB7HvTfQQ0aXwC5LGT8PEt1gS0CWKktKe6ysPTAy3cBC5MeiIg==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-3.3.1.tgz", + "integrity": "sha512-gBXpgUm/3rp1lMZZrM/w7D8GKqshif0zAymAhbCyIt8KMe+0v9DQ7cdYLR4FHH/cKpdTXb+A/tKKU3eolfsI+g==", + "license": "MIT", "funding": { "type": "github", "url": "https://github.com/sponsors/dcastil" } }, "node_modules/tailwindcss": { - "version": "3.4.10", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.10.tgz", - "integrity": "sha512-KWZkVPm7yJRhdu4SRSl9d4AK2wM3a50UsvgHZO7xY77NQr2V+fIrEuoDGQcbvswWvFGbS2f6e+jC/6WJm1Dl0w==", + "version": "3.4.17", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.17.tgz", + "integrity": "sha512-w33E2aCvSDP0tW9RZuNXadXlkHXqFzSkQew/aIa2i/Sj8fThxwovwlXHSPXTbAHwEIhBFXAedUhP2tueAKP8Og==", + "license": "MIT", "dependencies": { "@alloc/quick-lru": "^5.2.0", "arg": "^5.0.2", - "chokidar": "^3.5.3", + "chokidar": "^3.6.0", "didyoumean": "^1.2.2", "dlv": "^1.1.3", - "fast-glob": "^3.3.0", + "fast-glob": "^3.3.2", "glob-parent": "^6.0.2", "is-glob": "^4.0.3", - "jiti": "^1.21.0", - "lilconfig": "^2.1.0", - "micromatch": "^4.0.5", + "jiti": "^1.21.6", + "lilconfig": "^3.1.3", + "micromatch": "^4.0.8", "normalize-path": "^3.0.0", "object-hash": "^3.0.0", - "picocolors": "^1.0.0", - "postcss": "^8.4.23", + "picocolors": "^1.1.1", + "postcss": "^8.4.47", "postcss-import": "^15.1.0", "postcss-js": "^4.0.1", - "postcss-load-config": "^4.0.1", - "postcss-nested": "^6.0.1", - "postcss-selector-parser": "^6.0.11", - "resolve": "^1.22.2", - "sucrase": "^3.32.0" + "postcss-load-config": "^4.0.2", + "postcss-nested": "^6.2.0", + "postcss-selector-parser": "^6.1.2", + "resolve": "^1.22.8", + "sucrase": "^3.35.0" }, "bin": { "tailwind": "lib/cli.js", @@ -9841,25 +10523,39 @@ "tailwindcss": ">=3.0.0 || insiders" } }, - "node_modules/tapable": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", - "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", - "dev": true, + "node_modules/tailwindcss/node_modules/fast-glob": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.8" + }, "engines": { - "node": ">=6" + "node": ">=8.6.0" } }, - "node_modules/text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", - "dev": true + "node_modules/tailwindcss/node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } }, "node_modules/thenify": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", + "license": "MIT", "dependencies": { "any-promise": "^1.0.0" } @@ -9868,6 +10564,7 @@ "version": "1.6.0", "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", + "license": "MIT", "dependencies": { "thenify": ">= 3.1.0 < 4" }, @@ -9934,6 +10631,51 @@ "integrity": "sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw==", "license": "MIT" }, + "node_modules/tinyglobby": { + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.14.tgz", + "integrity": "sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.4.4", + "picomatch": "^4.0.2" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tinyglobby/node_modules/fdir": { + "version": "6.4.6", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.6.tgz", + "integrity": "sha512-hiFoqpyZcfNm1yc4u8oWCf9A2c4D3QjCrks3zmoVKVxpQRzmPNar1hUJcBG2RQHvEVGDN+Jm81ZheVLAQMK6+w==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/tinyglobby/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/tmp": { "version": "0.0.33", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", @@ -9988,21 +10730,23 @@ } }, "node_modules/ts-api-utils": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", - "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz", + "integrity": "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==", "dev": true, + "license": "MIT", "engines": { - "node": ">=16" + "node": ">=18.12" }, "peerDependencies": { - "typescript": ">=4.2.0" + "typescript": ">=4.8.4" } }, "node_modules/ts-interface-checker": { "version": "0.1.13", "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", - "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==" + "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", + "license": "Apache-2.0" }, "node_modules/ts-node": { "version": "10.9.2", @@ -10060,6 +10804,7 @@ "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", "dev": true, + "license": "MIT", "dependencies": { "@types/json5": "^0.0.29", "json5": "^1.0.2", @@ -10068,14 +10813,15 @@ } }, "node_modules/tslib": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", - "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" }, "node_modules/tsx": { - "version": "4.19.3", - "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.19.3.tgz", - "integrity": "sha512-4H8vUNGNjQ4V2EOoGw005+c+dGuPSnhpPBPHBtsZdGZBk/iJb4kguGlPWaZTZ3q5nMtFOEsY0nRDlh9PJyd6SQ==", + "version": "4.20.3", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.20.3.tgz", + "integrity": "sha512-qjbnuR9Tr+FJOMBqJCW5ehvIo/buZq7vH7qD7JziU98h6l3qGy0a/yPFjwO+y0/T7GFpNgNAvEcPPVfyT8rrPQ==", "dev": true, "license": "MIT", "dependencies": { @@ -10104,43 +10850,33 @@ "node": ">= 0.8.0" } }, - "node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/typed-array-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz", - "integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", + "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", + "call-bound": "^1.0.3", "es-errors": "^1.3.0", - "is-typed-array": "^1.1.13" + "is-typed-array": "^1.1.14" }, "engines": { "node": ">= 0.4" } }, "node_modules/typed-array-byte-length": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz", - "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz", + "integrity": "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-proto": "^1.0.3", - "is-typed-array": "^1.1.13" + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.14" }, "engines": { "node": ">= 0.4" @@ -10150,17 +10886,19 @@ } }, "node_modules/typed-array-byte-offset": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz", - "integrity": "sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.4.tgz", + "integrity": "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==", "dev": true, + "license": "MIT", "dependencies": { "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-proto": "^1.0.3", - "is-typed-array": "^1.1.13" + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.15", + "reflect.getprototypeof": "^1.0.9" }, "engines": { "node": ">= 0.4" @@ -10170,17 +10908,18 @@ } }, "node_modules/typed-array-length": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.6.tgz", - "integrity": "sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.7.tgz", + "integrity": "sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.7", "for-each": "^0.3.3", "gopd": "^1.0.1", - "has-proto": "^1.0.3", "is-typed-array": "^1.1.13", - "possible-typed-array-names": "^1.0.0" + "possible-typed-array-names": "^1.0.0", + "reflect.getprototypeof": "^1.0.6" }, "engines": { "node": ">= 0.4" @@ -10208,24 +10947,28 @@ } }, "node_modules/unbox-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", - "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz", + "integrity": "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", + "call-bound": "^1.0.3", "has-bigints": "^1.0.2", - "has-symbols": "^1.0.3", - "which-boxed-primitive": "^1.0.2" + "has-symbols": "^1.1.0", + "which-boxed-primitive": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/undici-types": { - "version": "6.19.8", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", - "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", + "version": "7.10.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.10.0.tgz", + "integrity": "sha512-t5Fy/nfn+14LuOc2KNYg75vZqClpAiqscVvMygNnlsHBFpSXdJaYtXMcdNLpl/Qvc3P2cB3s6lOV51nqsFq4ag==", "license": "MIT" }, "node_modules/unicode-trie": { @@ -10437,10 +11180,45 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/unrs-resolver": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/unrs-resolver/-/unrs-resolver-1.11.1.tgz", + "integrity": "sha512-bSjt9pjaEBnNiGgc9rUiHGKv5l4/TGzDmYw3RhnkJGtLhbnnA/5qJj7x3dNDCRx/PJxu774LlH8lCOlB4hEfKg==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "napi-postinstall": "^0.3.0" + }, + "funding": { + "url": "https://opencollective.com/unrs-resolver" + }, + "optionalDependencies": { + "@unrs/resolver-binding-android-arm-eabi": "1.11.1", + "@unrs/resolver-binding-android-arm64": "1.11.1", + "@unrs/resolver-binding-darwin-arm64": "1.11.1", + "@unrs/resolver-binding-darwin-x64": "1.11.1", + "@unrs/resolver-binding-freebsd-x64": "1.11.1", + "@unrs/resolver-binding-linux-arm-gnueabihf": "1.11.1", + "@unrs/resolver-binding-linux-arm-musleabihf": "1.11.1", + "@unrs/resolver-binding-linux-arm64-gnu": "1.11.1", + "@unrs/resolver-binding-linux-arm64-musl": "1.11.1", + "@unrs/resolver-binding-linux-ppc64-gnu": "1.11.1", + "@unrs/resolver-binding-linux-riscv64-gnu": "1.11.1", + "@unrs/resolver-binding-linux-riscv64-musl": "1.11.1", + "@unrs/resolver-binding-linux-s390x-gnu": "1.11.1", + "@unrs/resolver-binding-linux-x64-gnu": "1.11.1", + "@unrs/resolver-binding-linux-x64-musl": "1.11.1", + "@unrs/resolver-binding-wasm32-wasi": "1.11.1", + "@unrs/resolver-binding-win32-arm64-msvc": "1.11.1", + "@unrs/resolver-binding-win32-ia32-msvc": "1.11.1", + "@unrs/resolver-binding-win32-x64-msvc": "1.11.1" + } + }, "node_modules/update-browserslist-db": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz", - "integrity": "sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", + "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==", "dev": true, "funding": [ { @@ -10456,9 +11234,10 @@ "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "dependencies": { - "escalade": "^3.1.2", - "picocolors": "^1.0.1" + "escalade": "^3.2.0", + "picocolors": "^1.1.1" }, "bin": { "update-browserslist-db": "cli.js" @@ -10472,6 +11251,7 @@ "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "punycode": "^2.1.0" } @@ -10662,39 +11442,45 @@ } }, "node_modules/which-boxed-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", - "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz", + "integrity": "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==", "dev": true, + "license": "MIT", "dependencies": { - "is-bigint": "^1.0.1", - "is-boolean-object": "^1.1.0", - "is-number-object": "^1.0.4", - "is-string": "^1.0.5", - "is-symbol": "^1.0.3" + "is-bigint": "^1.1.0", + "is-boolean-object": "^1.2.1", + "is-number-object": "^1.1.1", + "is-string": "^1.1.1", + "is-symbol": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/which-builtin-type": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.1.3.tgz", - "integrity": "sha512-YmjsSMDBYsM1CaFiayOVT06+KJeXf0o5M/CAd4o1lTadFAtacTUM49zoYxr/oroopFDfhvN6iEcBxUyc3gvKmw==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.2.1.tgz", + "integrity": "sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==", "dev": true, + "license": "MIT", "dependencies": { - "function.prototype.name": "^1.1.5", - "has-tostringtag": "^1.0.0", + "call-bound": "^1.0.2", + "function.prototype.name": "^1.1.6", + "has-tostringtag": "^1.0.2", "is-async-function": "^2.0.0", - "is-date-object": "^1.0.5", - "is-finalizationregistry": "^1.0.2", + "is-date-object": "^1.1.0", + "is-finalizationregistry": "^1.1.0", "is-generator-function": "^1.0.10", - "is-regex": "^1.1.4", + "is-regex": "^1.2.1", "is-weakref": "^1.0.2", "isarray": "^2.0.5", - "which-boxed-primitive": "^1.0.2", - "which-collection": "^1.0.1", - "which-typed-array": "^1.1.9" + "which-boxed-primitive": "^1.1.0", + "which-collection": "^1.0.2", + "which-typed-array": "^1.1.16" }, "engines": { "node": ">= 0.4" @@ -10708,6 +11494,7 @@ "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", "dev": true, + "license": "MIT", "dependencies": { "is-map": "^2.0.3", "is-set": "^2.0.3", @@ -10722,15 +11509,18 @@ } }, "node_modules/which-typed-array": { - "version": "1.1.15", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz", - "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==", + "version": "1.1.19", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.19.tgz", + "integrity": "sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==", "dev": true, + "license": "MIT", "dependencies": { "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.7", - "for-each": "^0.3.3", - "gopd": "^1.0.1", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "for-each": "^0.3.5", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", "has-tostringtag": "^1.0.2" }, "engines": { @@ -10763,6 +11553,7 @@ "version": "8.1.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "license": "MIT", "dependencies": { "ansi-styles": "^6.1.0", "string-width": "^5.0.1", @@ -10780,6 +11571,7 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "license": "MIT", "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -10792,15 +11584,26 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" }, "node_modules/wrap-ansi-cjs/node_modules/string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -10810,21 +11613,23 @@ "node": ">=8" } }, - "node_modules/wrap-ansi/node_modules/ansi-regex": { + "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": { "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "engines": { - "node": ">=12" + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" + "engines": { + "node": ">=8" } }, "node_modules/wrap-ansi/node_modules/ansi-styles": { "version": "6.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "license": "MIT", "engines": { "node": ">=12" }, @@ -10832,26 +11637,6 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/wrap-ansi/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true - }, "node_modules/xtend": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/xtend/-/xtend-3.0.0.tgz", @@ -10860,12 +11645,6 @@ "node": ">=0.4" } }, - "node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, "node_modules/yaml": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.4.1.tgz", diff --git a/package.json b/package.json index be2c9ee7..6f8a1df1 100644 --- a/package.json +++ b/package.json @@ -13,58 +13,58 @@ "links": "blc http://localhost:3000/ -ro --exclude 'https://discord.rocicorp.dev/' --exclude 'https://bsky.app/profile/zero.rocicorp.dev' --exclude 'https://x.com/rocicorp_zero' --exclude 'https://x.com/zero__ms'" }, "dependencies": { - "@radix-ui/react-collapsible": "^1.1.0", - "@radix-ui/react-dialog": "^1.1.1", - "@radix-ui/react-dropdown-menu": "^2.1.1", - "@radix-ui/react-scroll-area": "^1.1.0", - "@radix-ui/react-slot": "^1.1.0", + "@radix-ui/react-collapsible": "^1.1.11", + "@radix-ui/react-dialog": "^1.1.14", + "@radix-ui/react-dropdown-menu": "^2.1.15", + "@radix-ui/react-scroll-area": "^1.2.9", + "@radix-ui/react-slot": "^1.2.3", "@radix-ui/react-tooltip": "^1.2.7", - "@vercel/og": "^0.8.2", + "@vercel/og": "^0.8.5", "broken-link-checker": "^0.7.8", - "class-variance-authority": "^0.7.0", + "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", "cmdk": "^1.1.1", "gray-matter": "^4.0.3", - "lucide-react": "^0.435.0", + "lucide-react": "^0.537.0", "lunr": "^2.3.9", "mdast-util-to-string": "^4.0.0", - "next": "^14.2.6", + "next": "^15.4.6", "next-mdx-remote": "^5.0.0", - "next-themes": "^0.3.0", - "react": "^18.3.1", - "react-dom": "^18.3.1", + "next-themes": "^0.4.6", + "react": "^19.1.1", + "react-dom": "^19.1.1", "react-hotkeys-hook": "^5.1.0", "rehype-autolink-headings": "^7.1.0", "rehype-code-titles": "^1.2.0", - "rehype-prism-plus": "^2.0.0", + "rehype-prism-plus": "^2.0.1", "rehype-slug": "^6.0.0", "remark": "^15.0.1", - "remark-gfm": "^4.0.0", + "remark-gfm": "^4.0.1", "remark-parse": "^11.0.0", "remark-stringify": "^11.0.0", "strip-markdown": "^6.0.0", - "tailwind-merge": "^2.5.2", + "tailwind-merge": "^3.3.1", "tailwindcss-animate": "^1.0.7", "unist-util-visit": "^5.0.0" }, "devDependencies": { "@rocicorp/prettier-config": "^0.3.0", - "@tailwindcss/typography": "^0.5.14", + "@tailwindcss/typography": "^0.5.16", "@types/hast": "^3.0.4", "@types/lunr": "^2.3.7", - "@types/node": "^20.17.19", - "@types/react": "^18", - "@types/react-dom": "^18", + "@types/node": "^24.2.0", + "@types/react": "^19", + "@types/react-dom": "^19", "@types/unist": "^3.0.3", - "autoprefixer": "^10.4.20", - "eslint": "^8", - "eslint-config-next": "^14.2.6", - "highlight.js": "^11.10.0", + "autoprefixer": "^10.4.21", + "eslint": "^9", + "eslint-config-next": "^15.4.6", + "highlight.js": "^11.11.1", "postcss": "^8", "react-highlight": "^0.15.0", "tailwindcss": "^3.4.10", "ts-node": "^10.9.2", - "tsx": "^4.19.3", + "tsx": "^4.20.3", "typescript": "^5" }, "prettier": "@rocicorp/prettier-config" diff --git a/tsconfig.json b/tsconfig.json index e7ff90fd..d81d4ee1 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,6 +1,10 @@ { "compilerOptions": { - "lib": ["dom", "dom.iterable", "esnext"], + "lib": [ + "dom", + "dom.iterable", + "esnext" + ], "allowJs": true, "skipLibCheck": true, "strict": true, @@ -18,9 +22,19 @@ } ], "paths": { - "@/*": ["./*"] - } + "@/*": [ + "./*" + ] + }, + "target": "ES2017" }, - "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], - "exclude": ["node_modules"] + "include": [ + "next-env.d.ts", + "**/*.ts", + "**/*.tsx", + ".next/types/**/*.ts" + ], + "exclude": [ + "node_modules" + ] } From 0be4bc4625dd21059814353332e6b7398dd52f1f Mon Sep 17 00:00:00 2001 From: Chase Adams Date: Thu, 7 Aug 2025 16:19:00 -0700 Subject: [PATCH 19/28] fix: build errors --- .eslintrc.json | 3 +- app/page.tsx | 8 +-- assets/search-index.json | 86 ++++++++++++++++---------------- components/CodeBlock.tsx | 2 +- components/search.tsx | 8 +-- components/sublink.tsx | 1 - components/theme-provider.tsx | 2 +- components/ui/ActiveHashLink.tsx | 1 - lib/generateSearchIndex.ts | 23 ++++----- lib/icons.tsx | 1 - lib/routes-config.ts | 2 - 11 files changed, 65 insertions(+), 72 deletions(-) diff --git a/.eslintrc.json b/.eslintrc.json index f5729a76..a3df1bec 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -3,6 +3,7 @@ "parser": "@typescript-eslint/parser", "plugins": ["@typescript-eslint"], "rules": { - "@typescript-eslint/no-explicit-any": "warn" + "@typescript-eslint/no-explicit-any": "warn", + "@next/next/no-img-element": "off" } } diff --git a/app/page.tsx b/app/page.tsx index 28fd1d44..d08bd515 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -155,9 +155,9 @@ export default function Home() { server-rendered web app.

diff --git a/assets/search-index.json b/assets/search-index.json index 7ca3c43d..368ca0c5 100644 --- a/assets/search-index.json +++ b/assets/search-index.json @@ -3,14 +3,14 @@ "id": "0-add-to-existing-project", "title": "Add to Existing Project", "url": "/docs/add-to-existing-project", - "content": "Zero integrates easily into most JavaScript or TypeScript projects, whether you're using React, Vue, Svelte, Solid, or vanilla JavaScript. Prerequisites A PostgreSQL database with Write-Ahead Logging (WAL) enabled. See Connecting to Postgres for setup instructions. If you are using TypeScript ensure that strictNullChecks is set to true in tsconfig.json. If this is not set then the advanced types Zero uses do not work as expected. Installation Install the Zero package: ```bash npm install @rocicorp/zero ``` Zero's server component depends on @rocicorp/zero-sqlite3, which contains a binary that requires running a postinstall script. Most alternative package managers (non-npm) disable these scripts by default for security reasons. Here's how to enable installation for common alternatives: pnpm For pnpm, either: Run pnpm approve-builds to approve all build scripts, or Add the specific dependency to your package.json: ```json \"pnpm\": { \"onlyBuiltDependencies\": [ \"@rocicorp/zero-sqlite3\" ] } ``` Bun For Bun, add the dependency to your trusted dependencies list: ```json \"trustedDependencies\": [ \"@rocicorp/zero-sqlite3\" ], ``` Environment Variables Configure Zero by creating a .env file in your project root: ```bash ZERO_UPSTREAM_DB=\"postgresql://user:password@127.0.0.1/postgres\" ZERO_REPLICA_FILE=\"/tmp/sync-replica.db\" ``` Replace the placeholders with your database connection details. For more options, see configuration options. Starting the Server Start the Zero server using the CLI: ```bash npx zero-cache-dev ``` The server runs on port 4848 by default. To verify, open http://localhost:4848 in your browser. If everything is configured correctly, you'll see \"OK\". Defining Your Schema Define your data model schema as described in the Zero schema documentation. Example: ```ts // schema.ts import {createSchema, table, string} from '@rocicorp/zero'; const message = table('message') .columns({ id: string(), body: string(), }) .primaryKey('id'); export const schema = createSchema({ tables: [message], }); export type Schema = typeof schema; ``` If you're using Prisma or Drizzle, you can convert their schemas to Zero schemas using tools listed in the community section. Permissions Update schema.ts to include permissions for your tables. For example, to allow all users to read and write to the message table, add the following: ```ts // schema.ts import {ANYONE_CAN_DO_ANYTHING, definePermissions} from '@rocicorp/zero'; export const permissions = definePermissions(schema, () => ({ message: ANYONE_CAN_DO_ANYTHING, })); ``` For more details, see permissions. Creating a Zero Instance To create a Zero client instance: ```js import {Zero} from '@rocicorp/zero'; const z = new Zero({ userID: 'anon', server: 'http://localhost:4848', schema, }); ``` In production, avoid hardcoding the server URL. Use environment variables like import.meta.env.VITE\\_PUBLIC\\_SERVER or process.env.NEXT\\_PUBLIC\\_SERVER. Reading Data To read data, use the materialize method on a Query from the Zero instance. This creates a materialized view that listens for real-time updates to the data: ```js const view = z.query.message.materialize(); view.addListener(data => console.log('Data updated:', data)); ``` When the view is no longer needed, ensure you clean up by destroying it: ```js view.destroy(); ``` For more details, see Reading Data with ZQL. React React developers can use the useZero hook for seamless integration. See Integrations React for more details. SolidJS For SolidJS, use the createZero function instead of new Zero. Refer to Integrations SolidJS for additional information. Other Frameworks For other frameworks, see the UI frameworks documentation. Writing Data Zero supports both simple and advanced data mutations. For basic use cases, use the CRUD mutator: ```ts z.mutate.message.insert({id: nanoid(), body: 'Hello World!'}); ``` For more complex scenarios, such as custom business logic, use custom mutators to define tailored mutation behavior. Server-Side Rendering (SSR) Zero does not yet support SSR. See SSR for details on disabling SSR for your framework. Deployment Ensure all .env variables are set in the production environment. For Zero cache deployment, see Deployment. For frontend deployment, consult your framework's documentation.", + "content": "Zero integrates easily into most JavaScript or TypeScript projects, whether you're using React, Vue, Svelte, Solid, or vanilla JavaScript. Prerequisites A PostgreSQL database with Write-Ahead Logging (WAL) enabled. See Connecting to Postgres for setup instructions. If you are using TypeScript ensure that strictNullChecks is set to true in tsconfig.json. If this is not set then the advanced types Zero uses do not work as expected. Installation Install the Zero package: npm install @rocicorp/zero Zero's server component depends on @rocicorp/zero-sqlite3, which contains a binary that requires running a postinstall script. Most alternative package managers (non-npm) disable these scripts by default for security reasons. Here's how to enable installation for common alternatives: pnpm For pnpm, either: Run pnpm approve-builds to approve all build scripts, or Add the specific dependency to your package.json: \"pnpm\": { \"onlyBuiltDependencies\": [ \"@rocicorp/zero-sqlite3\" ] } Bun For Bun, add the dependency to your trusted dependencies list: \"trustedDependencies\": [ \"@rocicorp/zero-sqlite3\" ], Environment Variables Configure Zero by creating a .env file in your project root: ZERO_UPSTREAM_DB=\"postgresql://user:password@127.0.0.1/postgres\" ZERO_REPLICA_FILE=\"/tmp/sync-replica.db\" Replace the placeholders with your database connection details. For more options, see configuration options. Starting the Server Start the Zero server using the CLI: npx zero-cache-dev The server runs on port 4848 by default. To verify, open http://localhost:4848 in your browser. If everything is configured correctly, you'll see \"OK\". Defining Your Schema Define your data model schema as described in the Zero schema documentation. Example: // schema.ts import {createSchema, table, string} from '@rocicorp/zero'; const message = table('message') .columns({ id: string(), body: string(), }) .primaryKey('id'); export const schema = createSchema({ tables: [message], }); export type Schema = typeof schema; If you're using Prisma or Drizzle, you can convert their schemas to Zero schemas using tools listed in the community section. Permissions Update schema.ts to include permissions for your tables. For example, to allow all users to read and write to the message table, add the following: // schema.ts import {ANYONE_CAN_DO_ANYTHING, definePermissions} from '@rocicorp/zero'; export const permissions = definePermissions(schema, () => ({ message: ANYONE_CAN_DO_ANYTHING, })); For more details, see permissions. Creating a Zero Instance To create a Zero client instance: import {Zero} from '@rocicorp/zero'; const z = new Zero({ userID: 'anon', server: 'http://localhost:4848', schema, }); In production, avoid hardcoding the server URL. Use environment variables like import.meta.env.VITE\\_PUBLIC\\_SERVER or process.env.NEXT\\_PUBLIC\\_SERVER. Reading Data To read data, use the materialize method on a Query from the Zero instance. This creates a materialized view that listens for real-time updates to the data: const view = z.query.message.materialize(); view.addListener(data => console.log('Data updated:', data)); When the view is no longer needed, ensure you clean up by destroying it: view.destroy(); For more details, see Reading Data with ZQL. React React developers can use the useZero hook for seamless integration. See Integrations React for more details. SolidJS For SolidJS, use the createZero function instead of new Zero. Refer to Integrations SolidJS for additional information. Other Frameworks For other frameworks, see the UI frameworks documentation. Writing Data Zero supports both simple and advanced data mutations. For basic use cases, use the CRUD mutator: z.mutate.message.insert({id: nanoid(), body: 'Hello World!'}); For more complex scenarios, such as custom business logic, use custom mutators to define tailored mutation behavior. Server-Side Rendering (SSR) Zero does not yet support SSR. See SSR for details on disabling SSR for your framework. Deployment Ensure all .env variables are set in the production environment. For Zero cache deployment, see Deployment. For frontend deployment, consult your framework's documentation.", "headings": [] }, { "id": "1-auth", "title": "Authentication", "url": "/docs/auth", - "content": "Zero uses a JWT-based flow to authenticate connections to zero-cache. Frontend During login: Your API server creates a JWT and sends it to your client. Your client constructs a Zero instance with this token by passing it to the auth option. ```ts const zero = new Zero({ ..., auth: token, // your JWT userID, // this must match the `sub` field from `token` }); ``` Server For zero-cache to be able to verify the JWT, one of the following environment variables needs to be set: ZERO\\_AUTH\\_SECRET - If your API server uses a symmetric key (secret) to create JWTs then this is that same key. ZERO\\_AUTH\\_JWK - If your API server uses a private key to create JWTs then this is the corresponding public key, in JWK format. ZERO\\_AUTH\\_JWKS\\_URL - Many auth providers host the public keys used to verify the JWTs they create at a public URL. If you use a provider that does this, or you publish your own keys publicly, set this to that URL. Refresh The auth parameter to Zero can also be a function: ```ts const zero = new Zero({ ..., auth: async () => { const token = await fetchNewToken(); return token; }, userID, }); ``` In this case, Zero will call this function to get a new JWT if verification fails. Client-Side Data Storage Zero stores client-side data in IndexedDB by default, but this is customizable with the kvStore parameter: ```ts const zero = new Zero({ // Store data in React Native's SQLite database // See https://github.com/Braden1996/react-native-replicache kvStore: createReplicacheReactNativeOPSQLiteKVStore, }); const zero = new Zero({ // Store data in memory, it disappears on refresh kvStore: 'mem', }); ``` Because multiple users can share the same browser, Zero requires that you provide a userID parameter on construction: ```ts const zero = new Zero({ ..., userID: \"user-123\", }); ``` Zero stores each user's data in a different IndexedDB instance. This allows users to quickly switch between multiple users and accounts without resyncing. \\ cmp(decodedJWT.role, '=', 'admin'); ``` See the permissions section for more details. Examples See zbugs or hello-zero.", + "content": "Zero uses a JWT-based flow to authenticate connections to zero-cache. Frontend During login: Your API server creates a JWT and sends it to your client. Your client constructs a Zero instance with this token by passing it to the auth option. const zero = new Zero({ ..., auth: token, // your JWT userID, // this must match the `sub` field from `token` }); Server For zero-cache to be able to verify the JWT, one of the following environment variables needs to be set: ZERO\\_AUTH\\_SECRET - If your API server uses a symmetric key (secret) to create JWTs then this is that same key. ZERO\\_AUTH\\_JWK - If your API server uses a private key to create JWTs then this is the corresponding public key, in JWK format. ZERO\\_AUTH\\_JWKS\\_URL - Many auth providers host the public keys used to verify the JWTs they create at a public URL. If you use a provider that does this, or you publish your own keys publicly, set this to that URL. Refresh The auth parameter to Zero can also be a function: const zero = new Zero({ ..., auth: async () => { const token = await fetchNewToken(); return token; }, userID, }); In this case, Zero will call this function to get a new JWT if verification fails. Client-Side Data Storage Zero stores client-side data in IndexedDB by default, but this is customizable with the kvStore parameter: const zero = new Zero({ // Store data in React Native's SQLite database // See https://github.com/Braden1996/react-native-replicache kvStore: createReplicacheReactNativeOPSQLiteKVStore, }); const zero = new Zero({ // Store data in memory, it disappears on refresh kvStore: 'mem', }); Because multiple users can share the same browser, Zero requires that you provide a userID parameter on construction: const zero = new Zero({ ..., userID: \"user-123\", }); Zero stores each user's data in a different IndexedDB instance. This allows users to quickly switch between multiple users and accounts without resyncing. \\ cmp(decodedJWT.role, '=', 'admin'); See the permissions section for more details. Examples See zbugs or hello-zero.", "headings": [] }, { @@ -24,70 +24,70 @@ "id": "3-connecting-to-postgres", "title": "Connecting to Postgres", "url": "/docs/connecting-to-postgres", - "content": "In the future, Zero will work with many different backend databases. Today only Postgres is supported. Specifically, Zero requires Postgres v15.0 or higher, and support for logical replication. Here are some common Postgres options and what we know about their support level: | Postgres | Support Status | | --------------------------------- | ------------------------------------------------------------------------------------------------ | | AWS RDS | ✅ | | AWS Aurora | ✅ v15.6+ | | Google Cloud SQL | ✅ See notes below | | Fly.io Postgres | ✅ See notes below | | Neon | ✅ See notes below | | Postgres.app | ✅ | | postgres:16.2-alpine docker image | ✅ | | Supabase | ✅ See notes below | | PlanetScale for Postgres | 🤷‍♂️ No event triggers, see notes below | | Render | 🤷‍♂️ No event triggers | | Heroku | 🤷‍♂️ No event triggers | Event Triggers Zero uses Postgres “Event Triggers” when possible to implement high-quality, efficient schema migration. Some hosted Postgres providers don’t provide access to Event Triggers. Zero still works out of the box with these providers, but for correctness, any schema change triggers a full reset of all server-side and client-side state. For small databases (< 10GB) this can be OK, but for bigger databases we recommend choosing a provider that grants access to Event Triggers. Configuration WAL Level The Postgres wal\\_level config parameter has to be set to logical. You can check what level your pg has with this command: ```bash psql -c 'SHOW wal_level' ``` If it doesn’t output logical then you need to change the wal level. To do this, run: ```bash psql -c \"ALTER SYSTEM SET wal_level = 'logical';\" ``` Then restart Postgres. On most pg systems you can do this like so: ```bash data_dir=$(psql -t -A -c 'SHOW data_directory') pg_ctl -D \"$data_dir\" restart ``` After your server restarts, show the wal\\_level again to ensure it has changed: ```bash psql -c 'SHOW wal_level' ``` Bounding WAL Size For development databases, you can set a max\\_slot\\_wal\\_keep\\_size value in Postgres. This will help limit the amount of WAL kept around. This is a configuration parameter that bounds the amount of WAL kept around for replication slots, and invalidates the slots that are too far behind. zero-cache will automatically detect if the replication slot has been invalidated and re-sync replicas from scratch. This configuration can cause problems like slot has been invalidated because it exceeded the maximum reserved size and is not recommended for production databases. Provider-Specific Notes Google Cloud SQL To use Google Cloud SQL you must manually create a PUBLICATION and specify that publication name in the App Publications option when running zero-cache. (Google Cloud SQL does not provide sufficient permissions for zero-cache to create its default publication.) Fly.io Fly does not support TLS on their internal networks. If you run both zero-cache and Postgres on Fly, you need to stop zero-cache from trying to use TLS to talk to Postgres. You can do this by adding the sslmode=disable query parameter to your connection strings from zero-cache. Supabase In order to connect to Supabase you must use the \"Direct Connection\" style connection string, not the pooler: This is because Zero sets up a logical replication slot, which is only supported with a direct connection. Additionally, you may need to assign an IPv4 address to your Supabase instance: This will be required if you cannot use IPv6 from wherever zero-cache is running. Most cloud providers support IPv6, but some do not. For example, if you are running zero-cache in AWS, it is possible to use IPv6 but difficult. IPv4 addresses are only supported on the Pro plan and are an extra $4/month. PlanetScale for Postgres PlanetScale doesn't support event triggers yet, but they say this is something they are working on. PlanetScale also doesn't support creating publications with the FOR ALL TABLES clause. Zero typically uses this to create an initial default publication during setup. You can workaround this by creating a publication explicitly listing the tables you want to replicate. Neon Neon fully supports Zero, but you should be aware of how Neon's pricing model and Zero interact. Because Zero keeps an open connection to Postgres to replicate changes, as long as zero-cache is running, Postgres will be running and you will be charged by Neon. For production databases that have enough usage to always be running anyway, this is fine. But for smaller applications that would otherwise not always be running, this can create a surprisingly high bill. You may want to choose a provider that charge a flat monthly rate instead. Also some users choose Neon because they hope to use branching for previews. Note that Zero doesn't support this usage model well yet, and if not done with care, Zero can end up keeping each Neon preview branch running too 😳. We are actively working on better preview support.", + "content": "In the future, Zero will work with many different backend databases. Today only Postgres is supported. Specifically, Zero requires Postgres v15.0 or higher, and support for logical replication. Here are some common Postgres options and what we know about their support level: | Postgres | Support Status | | --------------------------------- | ------------------------------------------------------------------------------------------------ | | AWS RDS | ✅ | | AWS Aurora | ✅ v15.6+ | | Google Cloud SQL | ✅ See notes below | | Fly.io Postgres | ✅ See notes below | | Neon | ✅ See notes below | | Postgres.app | ✅ | | postgres:16.2-alpine docker image | ✅ | | Supabase | ✅ See notes below | | PlanetScale for Postgres | 🤷‍♂️ No event triggers, see notes below | | Render | 🤷‍♂️ No event triggers | | Heroku | 🤷‍♂️ No event triggers | Event Triggers Zero uses Postgres “Event Triggers” when possible to implement high-quality, efficient schema migration. Some hosted Postgres providers don’t provide access to Event Triggers. Zero still works out of the box with these providers, but for correctness, any schema change triggers a full reset of all server-side and client-side state. For small databases (< 10GB) this can be OK, but for bigger databases we recommend choosing a provider that grants access to Event Triggers. Configuration WAL Level The Postgres wal\\_level config parameter has to be set to logical. You can check what level your pg has with this command: psql -c 'SHOW wal_level' If it doesn’t output logical then you need to change the wal level. To do this, run: psql -c \"ALTER SYSTEM SET wal_level = 'logical';\" Then restart Postgres. On most pg systems you can do this like so: data_dir=$(psql -t -A -c 'SHOW data_directory') pg_ctl -D \"$data_dir\" restart After your server restarts, show the wal\\_level again to ensure it has changed: psql -c 'SHOW wal_level' Bounding WAL Size For development databases, you can set a max\\_slot\\_wal\\_keep\\_size value in Postgres. This will help limit the amount of WAL kept around. This is a configuration parameter that bounds the amount of WAL kept around for replication slots, and invalidates the slots that are too far behind. zero-cache will automatically detect if the replication slot has been invalidated and re-sync replicas from scratch. This configuration can cause problems like slot has been invalidated because it exceeded the maximum reserved size and is not recommended for production databases. Provider-Specific Notes Google Cloud SQL To use Google Cloud SQL you must manually create a PUBLICATION and specify that publication name in the App Publications option when running zero-cache. (Google Cloud SQL does not provide sufficient permissions for zero-cache to create its default publication.) Fly.io Fly does not support TLS on their internal networks. If you run both zero-cache and Postgres on Fly, you need to stop zero-cache from trying to use TLS to talk to Postgres. You can do this by adding the sslmode=disable query parameter to your connection strings from zero-cache. Supabase In order to connect to Supabase you must use the \"Direct Connection\" style connection string, not the pooler: This is because Zero sets up a logical replication slot, which is only supported with a direct connection. Additionally, you may need to assign an IPv4 address to your Supabase instance: This will be required if you cannot use IPv6 from wherever zero-cache is running. Most cloud providers support IPv6, but some do not. For example, if you are running zero-cache in AWS, it is possible to use IPv6 but difficult. IPv4 addresses are only supported on the Pro plan and are an extra $4/month. PlanetScale for Postgres PlanetScale doesn't support event triggers yet, but they say this is something they are working on. PlanetScale also doesn't support creating publications with the FOR ALL TABLES clause. Zero typically uses this to create an initial default publication during setup. You can workaround this by creating a publication explicitly listing the tables you want to replicate. Neon Neon fully supports Zero, but you should be aware of how Neon's pricing model and Zero interact. Because Zero keeps an open connection to Postgres to replicate changes, as long as zero-cache is running, Postgres will be running and you will be charged by Neon. For production databases that have enough usage to always be running anyway, this is fine. But for smaller applications that would otherwise not always be running, this can create a surprisingly high bill. You may want to choose a provider that charge a flat monthly rate instead. Also some users choose Neon because they hope to use branching for previews. Note that Zero doesn't support this usage model well yet, and if not done with care, Zero can end up keeping each Neon preview branch running too 😳. We are actively working on better preview support.", "headings": [] }, { "id": "4-custom-mutators", "title": "Custom Mutators", "url": "/docs/custom-mutators", - "content": "Custom Mutators are a new way to write data in Zero that is much more powerful than the original \"CRUD\" mutator API. Instead of having only the few built-in insert/update/delete write operations for each table, custom mutators allow you to create your own write operations using arbitrary code. This makes it possible to do things that are impossible or awkward with other sync engines. For example, you can create custom mutators that: Perform arbitrary server-side validation Enforce fine-grained permissions Send email notifications Query LLMs Use Yjs for collaborative editing … and much, much more – custom mutators are just code, and they can do anything code can do! Despite their increased power, custom mutators still participate fully in sync. They execute instantly on the local device, immediately updating all active queries. They are then synced in the background to the server and to other clients. \\ 100) { throw new Error(`Title is too long`); } await tx.mutate.issue.update({id, title}); } ``` Each custom mutator gets two implementations: one on the client and one on the server. The client implementation must be written in TypeScript against the Zero Transaction interface, using ZQL for reads and a CRUD-style API for writes. The server implementation runs on your server, in your push endpoint, against your database. In principle, it can be written in any language and use any data access library. For example you could have the following Go-based server implementation of the same mutator: ```go func updateIssueOnServer(tx *sql.Tx, id string, title string) error { // Validate title length. if len(title) > 100 { return errors.New(\"Title is too long\") } _, err := tx.Exec(\"UPDATE issue SET title = $1 WHERE id = $2\", title, id) return err } ``` In practice however, most Zero apps use TypeScript on the server. For these users we provide a handy ServerTransaction that implements ZQL against Postgres, so that you can share code between client and server mutators naturally. So on a TypeScript server, that server mutator can just be: ```ts async function updateIssueOnServer( tx: ServerTransaction, {id, title}, {id: string, title: string}, ) { // Delegate to client mutator. // The `ServerTransaction` here has a different implementation // that runs the same ZQL queries against Postgres! await updateIssue(tx, {id, title}); } ``` Reusing ZQL on the server is a handy – and we expect frequently used – option, but not a requirement. Server Authority You may be wondering what happens if the client and server mutators implementations don't match. Zero is an example of a server-authoritative sync engine. This means that the server mutator always takes precedence over the client mutator. The result from the client mutator is considered speculative and is discarded as soon as the result from the server mutator is known. This is a very useful feature: it enables server-side validation, permissions, and other server-specific logic. Imagine that you wanted to use an LLM to detect whether an issue update is spammy, rather than a simple length check. We can just add that to our server mutator: ```ts async function updateIssueOnServer( tx: ServerTransaction, {id, title}: {id: string; title: string}, ) { const response = await llamaSession.prompt( `Is this title update likely spam?\\n\\n${title}\\n\\nResponse \"yes\" or \"no\"`, ); if (/yes/i.test(response)) { throw new Error(`Title is likely spam`); } // delegate rest of implementation to client mutator await updateIssue(tx, {id, title}); } ``` If the server detects that the mutation is spammy, the client will see the error message and the mutation will be rolled back. If the server mutator succeeds, the client mutator will be rolled back and the server result will be applied. Life of a Mutation Now that we understand what client and server mutations are, let's walk through how they work together with Zero to sync changes from a source client to the server and then other clients: When you call a custom mutator on the client, Zero runs your client-side mutator immediately on the local device, updating all active queries instantly. In the background, Zero then sends a mutation (a record of the mutator having run with certain arguments) to your server's push endpoint. Your push endpoint runs the push protocol, executing the server-side mutator in a transaction against your database and recording the fact that the mutation ran. Optionally, you use our PushProcessor class to handle this for you, but you can also implement it yourself. The changes to the database are replicated to zero-cache as normal. zero-cache calculates the updates to active queries and sends rows that have changed to each client. It also sends information about the mutations that have been applied to the database. Clients receive row updates and apply them to their local cache. Any pending mutations which have been applied to the server have their local effects rolled back. Client-side queries are updated and the user sees the changes. Using Custom Mutators Registering Client Mutators By convention, the client mutators are defined with a function called createMutators in a file called mutators.ts: ```ts // mutators.ts import {CustomMutatorDefs} from '@rocicorp/zero'; import {schema} from './schema'; export function createMutators() { return { issue: { update: async (tx, {id, title}: {id: string; title: string}) => { // Validate title length. Legacy issues are exempt. if (title.length > 100) { throw new Error(`Title is too long`); } await tx.mutate.issue.update({id, title}); }, }, } as const satisfies CustomMutatorDefs; } ``` The mutators.ts convention allows mutator implementations to be easily reused server-side. The createMutators function convention is used so that we can pass authentication information in to implement permissions. You are free to make different code layout choices – the only real requirement is that you register your map of mutators in the Zero constructor: ```ts // main.tsx import {Zero} from '@rocicorp/zero'; import {schema} from './schema'; import {createMutators} from './mutators'; const zero = new Zero({ schema, mutators: createMutators(), }); ``` Write Data on the Client The Transaction interface passed to client mutators exposes the same mutate API as the existing CRUD-style mutators: ```ts async function myMutator(tx: Transaction) { // Insert a new issue await tx.mutate.issue.insert({ id: 'issue-123', title: 'New title', description: 'New description', }); // Upsert a new issue await tx.mutate.issue.upsert({ id: 'issue-123', title: 'New title', description: 'New description', }); // Update an issue await tx.mutate.issue.update({ id: 'issue-123', title: 'New title', }); // Delete an issue await tx.mutate.issue.delete({ id: 'issue-123', }); } ``` See the CRUD docs for detailed semantics on these methods. Read Data on the Client You can read data within a client mutator using ZQL: ```ts export function createMutators() { return { issue: { update: async (tx, {id, title}: {id: string; title: string}) => { // Read existing issue const prev = await tx.query.issue.where('id', id).one(); // Validate title length. Legacy issues are exempt. if (!prev.isLegacy && title.length > 100) { throw new Error(`Title is too long`); } await tx.mutate.issue.update({id, title}); }, }, } as const satisfies CustomMutatorDefs; } ``` You have the full power of ZQL at your disposal, including relationships, filters, ordering, and limits. Reads and writes within a mutator are transactional, meaning that the datastore is guaranteed to not change while your mutator is running. And if the mutator throws, the entire mutation is rolled back. This parameter isn't supported within mutators, because waiting for server results makes no sense in an optimistic mutation – it defeats the purpose of running optimistically to begin with. When a mutator runs on the client (tx.location === \"client\"), ZQL reads only return data already cached on the client. When mutators run on the server (tx.location === \"server\"), ZQL reads always return all data. You can use run() within custom mutators, but the type argument does nothing. In the future, passing type in this situation will throw an error. Invoking Client Mutators Once you have registered your client mutators, you can call them from your client-side application: ```ts zero.mutate.issue.update({ id: 'issue-123', title: 'New title', }); ``` The result of a call to a mutator is a Promise. You do not usually need to await this promise as Zero mutators run very fast, usually completing in a tiny fraction of one frame. However because mutators ocassionally need to access browser storage, they are technically async. Reading a row that was written by a mutator immediately after it is written may not return the new data, because the mutator may not have completed writing to storage yet. Waiting for Mutator Result We typically recommend that you \"fire and forget\" mutators. Optimistic mutations make sense when the common case is that a mutation succeeds. If a mutation frequently fails, then showing the user an optimistic result doesn't make sense, because it will likely be wrong. That said there are cases where it is useful to know when a write succeeded on either the client or server. One example is if you need to read a row directly after writing it. Zero's local writes are very fast (almost always < 1 frame), but because Zero is backed by IndexedDB, writes are still technically asynchronous and reads directly after a write may not return the new data. You can use the .client promise in this case to wait for a write to complete on the client side: ```ts try { const write = zero.mutate.issue.insert({ id: 'issue-123', title: 'New title', }); // issue-123 not guaranteed to be present here. read1 may be undefined. const read1 = await zero.query.issue.where('id', 'issue-123').one(); // Await client write – almost always less than 1 frame, and same // macrotask, so no browser paint will occur here. await write.client; // issue-123 definitely can be read now. const read2 = await zero.query.issue.where('id', 'issue-123').one(); } catch (e) { console.error('Mutator failed on client', e); } ``` You can also wait for the server write to succeed: ```ts try { const write = zero.mutate.issue.insert({ id: 'issue-123', title: 'New title', }); await write.client; // optimistic write guaranteed to be present here, but not // server write. const read1 = await zero.query.issue.where('id', 'issue-123').one(); // Await server write – this involves a round-trip. await write.server; // issue-123 is written to server and any results are // syned to this client. // read2 could potentially be undefined here, for example if the // server mutator rejected the write. const read2 = await zero.query.issue.where('id', 'issue-123').one(); } catch (e) { console.error('Mutator failed on client or server', e); } ``` If the client-side mutator fails, the .server promise is also rejected with the same error. You don't have to listen to both promises, the server promise covers both cases. Setting Up the Server You will need a server somewhere you can run an endpoint on. This is typically a serverless function on a platform like Vercel or AWS but can really be anything. Configure the push endpoint with the push.url parameter in your Zero constructor: ```ts const zero = new Zero({ push: { url: 'https://zero.my-server.com/push', }, }); ``` You will also need to enable the server to be used as a push endpoint with the ZERO\\_PUSH\\_URL environment variable or --push-url flag: ```bash ZERO_PUSH_URL=https://*.my-server.com/push ``` The ZERO\\_PUSH\\_URL parameter accepts wildcards, enabling the client to pass runtime configuration to the push endpoint or to use a different push endpoint, e.g., for previews. See the config docs for the full syntax. The push endpoint receives a PushRequest as input describing one or more mutations to apply to the backend, and must return a PushResponse describing the results of those mutations. If you are implementing your server in TypeScript, you can use the PushProcessor class to trivially implement this endpoint. Here’s an example in a Hono app: ```ts import {Hono} from 'hono'; import {handle} from 'hono/vercel'; import { PushProcessor, ZQLDatabase, PostgresJSConnection, } from '@rocicorp/zero/pg'; import postgres from 'postgres'; import {schema} from '../shared/schema'; import {createMutators} from '../shared/mutators'; // PushProcessor is provided by Zero to encapsulate a standard // implementation of the push protocol. const processor = new PushProcessor( new ZQLDatabase( new PostgresJSConnection(postgres(process.env.ZERO_UPSTREAM_DB! as string)), schema, ), ); export const app = new Hono().basePath('/api'); app.post('/push', async c => { const result = await processor.process(createMutators(), c.req.raw); return await c.json(result); }); export default handle(app); ``` PushProcessor depends on an abstract Database. This allows it to implement the push algorithm against any database. @rocicorp/zero/pg includes a ZQLDatabase implementation of this interface backed by Postgres. The implementation allows the same mutator functions to run on client and server, by providing an implementation of the ZQL APIs that custom mutators run on the client. ZQLDatabase in turn relies on an abstract DBConnection that provides raw access to a Postgres database. This allows you to use any Postgres library you like, as long as you provide a DBConnection implementation for it. The PostgresJSConnection class implements DBConnection for the excellent postgres.js library to connect to Postgres. To reuse the client mutators exactly as-is on the server just pass the result of the same createMutators function to PushProcessor. Server Error Handling The PushProcessor in @rocicorp/zero/pg skips any mutations that throw: ```ts app.post('/push', async c => { const result = await processor.process({ issue: { update: async (tx, data) => { // The mutation is skipped and the next mutation runs as normal. throw new Error('bonk'); }, }, }, ...); return await c.json(result); }) ``` PushProcessor catches such errors and turns them into a structured response that gets sent back to the client. You can recover the errors and show UI if you want. It is also of course possible for the entire push endpoint to return an HTTP error, or to not reply at all: ```ts app.post('/push', async c => { // This will cause the client to resend all queued mutations. throw new Error('zonk'); const result = await processor.process({ // ... }, ...); return await c.json(result); }) ``` If Zero recieves any response from the push endpoint other than HTTP 200, 401, or 403, it will disconnect, wait a few moments, reconnect, and then retry all unprocessed mutations. If Zero receives HTTP 401 or 403, the client refreshes the auth token if possible, then retries all queued mutations. If you want a different behavior, it is possible to implement your own PushProcessor and handle errors differently. Server-Specific Code To implement server-specific code, just run different mutators in your push endpoint! An approach we like is to create a separate server-mutators.ts file that wraps the client mutators: ```ts // server-mutators.ts import {CustomMutatorDefs} from '@rocicorp/zero'; import {schema} from './schema'; export function createMutators( clientMutators: CustomMutatorDefs, ) { return { // Reuse all client mutators except the ones in `issue` ...clientMutators, issue: { // Reuse all issue mutators except `update` ...clientMutators.issue, update: async (tx, {id, title}: {id: string; title: string}) => { // Call the shared mutator first await clientMutators.issue.update(tx, {id, title}); // Record a history of this operation happening in an audit // log table. await tx.mutate.auditLog.insert({ // Assuming you have an audit log table with fields for // `issueId`, `action`, and `timestamp`. issueId: id, action: 'update-title', timestamp: new Date().toISOString(), }); }, }, } as const satisfies CustomMutatorDefs; } ``` For simple things, we also expose a location field on the transaction object that you can use to branch your code: ```ts myMutator: (tx) => { if (tx.location === 'client') { // Client-side code } else { // Server-side code } }, ``` Permissions Because custom mutators are just arbitrary TypeScript functions, there is no need for a special permissions system. Therefore, you won't use Zero's write permissions when you use custom mutators. We hope to build custom queries next – a read analog to custom mutators. If we succeed, Zero's permission system will go away completely 🤯. In order to do permission checks, you'll need to know what user is making the request. You can pass this information to your mutators by adding a AuthData parameter to the createMutators function: ```ts type AuthData = { sub: string; }; export function createMutators(authData: AuthData | undefined) { return { issue: { launchMissiles: async (tx, args: {target: string}) => { if (!authData) { throw new Error('Users must be logged in to launch missiles'); } const hasPermission = await tx.query.user .where('id', authData.sub) .whereExists('permissions', q => q.where('name', 'launch-missiles')) .one(); if (!hasPermission) { throw new Error('User does not have permission to launch missiles'); } }, }, } as const satisfies CustomMutatorDefs; } ``` The AuthData parameter can be any data required for authorization, but is typically just the decoded JWT: ```ts // app.tsx const zero = new Zero({ schema, auth: encodedJWT, mutators: createMutators(decodedJWT), }); // hono-server.ts const processor = new PushProcessor( schema, connectionProvider(postgres(process.env.ZERO_UPSTREAM_DB as string)), ); processor.process( createMutators(decodedJWT), c.req.query(), await c.req.json(), ); ``` Dropping Down to Raw SQL The ServerTransaction interface has a dbTransaction property that exposes the underlying database connection. This allows you to run raw SQL queries directly against the database. This is useful for complex queries, or for using Postgres features that Zero doesn't support yet: ```ts markAllAsRead: async(tx: Transaction, {userId: string}) { // shared stuff ... if (tx.location === 'server') { // `tx` is now narrowed to `ServerTransaction`. // Do special server-only stuff with raw SQL. await tx.dbTransaction.query( ` UPDATE notification SET read = true WHERE user_id = $1 `, [userId], ); } } ``` As a convenience we also expose a special CustomMutatorDefs for use with server-mutators.ts that sets all the mutators to ServerTransaction by default: ```ts // server-mutators.ts import type { CustomMutatorDefs, // Special server-side CustomMutatorDefs PostgresJSTransaction, ServerTransaction, } from '@rocicorp/zero/pg'; import {Schema} from './schema'; export function createMutators(clientMutators: CustomMutatorDefs) { return { // Reuse all client mutators except the ones in `issue` ...clientMutators, issue: { // Reuse all issue mutators except `update` ...clientMutators.issue, markAllAsRead: async (tx, {userId: string}) { // No narrowing necessary – tx is already a `ServerTransaction` // assert(tx.location === 'server'); await tx.dbTransaction.query( ` UPDATE notification SET read = true WHERE user_id = $1 `, [userId], ); }, } } as const satisfies CustomMutatorDefs< ServerTransaction >; } ``` Notifications and Async Work It is bad practice to hold open database transactions while talking over the network, for example to send notifications. Instead, you should let the db transaction commit and do the work asynchronously. There is no specific support for this in custom mutators, but since mutators are just code, it’s easy to do: ```ts // server-mutators.ts export function createMutators( authData: AuthData, asyncTasks: Array<() => Promise>, ) { return { issue: { update: async (tx, {id, title}: {id: string; title: string}) => { await tx.mutate.issue.update({id, title}); asyncTasks.push(async () => { await sendEmailToSubscribers(args.id); }); }, }, } as const satisfies CustomMutatorDefs; } ``` Then in your push handler: ```ts app.post('/push', async c => { const asyncTasks: Array<() => Promise> = []; const result = await processor.process( createMutators(authData, asyncTasks), c.req.query(), await c.req.json(), ); await Promise.all(asyncTasks.map(task => task())); return await c.json(result); }); ``` Custom Database Connections You can implement an adapter to a different Postgres library, or even a different database entirely. To do so, provide a connectionProvider to PushProcessor that returns a different DBConnection implementation. For an example implementation, see the postgres implementation. Custom Push Implementation You can manually implement the push protocol in any programming language. This will be documented in the future, but you can refer to the PushProcessor source code for an example for now. Examples Zbugs uses custom mutators for all mutations, write permissions, and notifications. hello-zero-solid uses custom mutators for all mutations and for permissions.", + "content": "Custom Mutators are a new way to write data in Zero that is much more powerful than the original \"CRUD\" mutator API. Instead of having only the few built-in insert/update/delete write operations for each table, custom mutators allow you to create your own write operations using arbitrary code. This makes it possible to do things that are impossible or awkward with other sync engines. For example, you can create custom mutators that: Perform arbitrary server-side validation Enforce fine-grained permissions Send email notifications Query LLMs Use Yjs for collaborative editing … and much, much more – custom mutators are just code, and they can do anything code can do! Despite their increased power, custom mutators still participate fully in sync. They execute instantly on the local device, immediately updating all active queries. They are then synced in the background to the server and to other clients. \\ 100) { throw new Error(`Title is too long`); } await tx.mutate.issue.update({id, title}); } Each custom mutator gets two implementations: one on the client and one on the server. The client implementation must be written in TypeScript against the Zero Transaction interface, using ZQL for reads and a CRUD-style API for writes. The server implementation runs on your server, in your push endpoint, against your database. In principle, it can be written in any language and use any data access library. For example you could have the following Go-based server implementation of the same mutator: func updateIssueOnServer(tx *sql.Tx, id string, title string) error { // Validate title length. if len(title) > 100 { return errors.New(\"Title is too long\") } _, err := tx.Exec(\"UPDATE issue SET title = $1 WHERE id = $2\", title, id) return err } In practice however, most Zero apps use TypeScript on the server. For these users we provide a handy ServerTransaction that implements ZQL against Postgres, so that you can share code between client and server mutators naturally. So on a TypeScript server, that server mutator can just be: async function updateIssueOnServer( tx: ServerTransaction, {id, title}, {id: string, title: string}, ) { // Delegate to client mutator. // The `ServerTransaction` here has a different implementation // that runs the same ZQL queries against Postgres! await updateIssue(tx, {id, title}); } Reusing ZQL on the server is a handy – and we expect frequently used – option, but not a requirement. Server Authority You may be wondering what happens if the client and server mutators implementations don't match. Zero is an example of a server-authoritative sync engine. This means that the server mutator always takes precedence over the client mutator. The result from the client mutator is considered speculative and is discarded as soon as the result from the server mutator is known. This is a very useful feature: it enables server-side validation, permissions, and other server-specific logic. Imagine that you wanted to use an LLM to detect whether an issue update is spammy, rather than a simple length check. We can just add that to our server mutator: async function updateIssueOnServer( tx: ServerTransaction, {id, title}: {id: string; title: string}, ) { const response = await llamaSession.prompt( `Is this title update likely spam?\\n\\n${title}\\n\\nResponse \"yes\" or \"no\"`, ); if (/yes/i.test(response)) { throw new Error(`Title is likely spam`); } // delegate rest of implementation to client mutator await updateIssue(tx, {id, title}); } If the server detects that the mutation is spammy, the client will see the error message and the mutation will be rolled back. If the server mutator succeeds, the client mutator will be rolled back and the server result will be applied. Life of a Mutation Now that we understand what client and server mutations are, let's walk through how they work together with Zero to sync changes from a source client to the server and then other clients: When you call a custom mutator on the client, Zero runs your client-side mutator immediately on the local device, updating all active queries instantly. In the background, Zero then sends a mutation (a record of the mutator having run with certain arguments) to your server's push endpoint. Your push endpoint runs the push protocol, executing the server-side mutator in a transaction against your database and recording the fact that the mutation ran. Optionally, you use our PushProcessor class to handle this for you, but you can also implement it yourself. The changes to the database are replicated to zero-cache as normal. zero-cache calculates the updates to active queries and sends rows that have changed to each client. It also sends information about the mutations that have been applied to the database. Clients receive row updates and apply them to their local cache. Any pending mutations which have been applied to the server have their local effects rolled back. Client-side queries are updated and the user sees the changes. Using Custom Mutators Registering Client Mutators By convention, the client mutators are defined with a function called createMutators in a file called mutators.ts: // mutators.ts import {CustomMutatorDefs} from '@rocicorp/zero'; import {schema} from './schema'; export function createMutators() { return { issue: { update: async (tx, {id, title}: {id: string; title: string}) => { // Validate title length. Legacy issues are exempt. if (title.length > 100) { throw new Error(`Title is too long`); } await tx.mutate.issue.update({id, title}); }, }, } as const satisfies CustomMutatorDefs; } The mutators.ts convention allows mutator implementations to be easily reused server-side. The createMutators function convention is used so that we can pass authentication information in to implement permissions. You are free to make different code layout choices – the only real requirement is that you register your map of mutators in the Zero constructor: // main.tsx import {Zero} from '@rocicorp/zero'; import {schema} from './schema'; import {createMutators} from './mutators'; const zero = new Zero({ schema, mutators: createMutators(), }); Write Data on the Client The Transaction interface passed to client mutators exposes the same mutate API as the existing CRUD-style mutators: async function myMutator(tx: Transaction) { // Insert a new issue await tx.mutate.issue.insert({ id: 'issue-123', title: 'New title', description: 'New description', }); // Upsert a new issue await tx.mutate.issue.upsert({ id: 'issue-123', title: 'New title', description: 'New description', }); // Update an issue await tx.mutate.issue.update({ id: 'issue-123', title: 'New title', }); // Delete an issue await tx.mutate.issue.delete({ id: 'issue-123', }); } See the CRUD docs for detailed semantics on these methods. Read Data on the Client You can read data within a client mutator using ZQL: export function createMutators() { return { issue: { update: async (tx, {id, title}: {id: string; title: string}) => { // Read existing issue const prev = await tx.query.issue.where('id', id).one(); // Validate title length. Legacy issues are exempt. if (!prev.isLegacy && title.length > 100) { throw new Error(`Title is too long`); } await tx.mutate.issue.update({id, title}); }, }, } as const satisfies CustomMutatorDefs; } You have the full power of ZQL at your disposal, including relationships, filters, ordering, and limits. Reads and writes within a mutator are transactional, meaning that the datastore is guaranteed to not change while your mutator is running. And if the mutator throws, the entire mutation is rolled back. This parameter isn't supported within mutators, because waiting for server results makes no sense in an optimistic mutation – it defeats the purpose of running optimistically to begin with. When a mutator runs on the client (tx.location === \"client\"), ZQL reads only return data already cached on the client. When mutators run on the server (tx.location === \"server\"), ZQL reads always return all data. You can use run() within custom mutators, but the type argument does nothing. In the future, passing type in this situation will throw an error. Invoking Client Mutators Once you have registered your client mutators, you can call them from your client-side application: zero.mutate.issue.update({ id: 'issue-123', title: 'New title', }); The result of a call to a mutator is a Promise. You do not usually need to await this promise as Zero mutators run very fast, usually completing in a tiny fraction of one frame. However because mutators ocassionally need to access browser storage, they are technically async. Reading a row that was written by a mutator immediately after it is written may not return the new data, because the mutator may not have completed writing to storage yet. Waiting for Mutator Result We typically recommend that you \"fire and forget\" mutators. Optimistic mutations make sense when the common case is that a mutation succeeds. If a mutation frequently fails, then showing the user an optimistic result doesn't make sense, because it will likely be wrong. That said there are cases where it is useful to know when a write succeeded on either the client or server. One example is if you need to read a row directly after writing it. Zero's local writes are very fast (almost always < 1 frame), but because Zero is backed by IndexedDB, writes are still technically asynchronous and reads directly after a write may not return the new data. You can use the .client promise in this case to wait for a write to complete on the client side: try { const write = zero.mutate.issue.insert({ id: 'issue-123', title: 'New title', }); // issue-123 not guaranteed to be present here. read1 may be undefined. const read1 = await zero.query.issue.where('id', 'issue-123').one(); // Await client write – almost always less than 1 frame, and same // macrotask, so no browser paint will occur here. await write.client; // issue-123 definitely can be read now. const read2 = await zero.query.issue.where('id', 'issue-123').one(); } catch (e) { console.error('Mutator failed on client', e); } You can also wait for the server write to succeed: try { const write = zero.mutate.issue.insert({ id: 'issue-123', title: 'New title', }); await write.client; // optimistic write guaranteed to be present here, but not // server write. const read1 = await zero.query.issue.where('id', 'issue-123').one(); // Await server write – this involves a round-trip. await write.server; // issue-123 is written to server and any results are // syned to this client. // read2 could potentially be undefined here, for example if the // server mutator rejected the write. const read2 = await zero.query.issue.where('id', 'issue-123').one(); } catch (e) { console.error('Mutator failed on client or server', e); } If the client-side mutator fails, the .server promise is also rejected with the same error. You don't have to listen to both promises, the server promise covers both cases. Setting Up the Server You will need a server somewhere you can run an endpoint on. This is typically a serverless function on a platform like Vercel or AWS but can really be anything. Configure the push endpoint with the push.url parameter in your Zero constructor: const zero = new Zero({ push: { url: 'https://zero.my-server.com/push', }, }); You will also need to enable the server to be used as a push endpoint with the ZERO\\_PUSH\\_URL environment variable or --push-url flag: ZERO_PUSH_URL=https://*.my-server.com/push The ZERO\\_PUSH\\_URL parameter accepts wildcards, enabling the client to pass runtime configuration to the push endpoint or to use a different push endpoint, e.g., for previews. See the config docs for the full syntax. The push endpoint receives a PushRequest as input describing one or more mutations to apply to the backend, and must return a PushResponse describing the results of those mutations. If you are implementing your server in TypeScript, you can use the PushProcessor class to trivially implement this endpoint. Here’s an example in a Hono app: import {Hono} from 'hono'; import {handle} from 'hono/vercel'; import { PushProcessor, ZQLDatabase, PostgresJSConnection, } from '@rocicorp/zero/pg'; import postgres from 'postgres'; import {schema} from '../shared/schema'; import {createMutators} from '../shared/mutators'; // PushProcessor is provided by Zero to encapsulate a standard // implementation of the push protocol. const processor = new PushProcessor( new ZQLDatabase( new PostgresJSConnection(postgres(process.env.ZERO_UPSTREAM_DB! as string)), schema, ), ); export const app = new Hono().basePath('/api'); app.post('/push', async c => { const result = await processor.process(createMutators(), c.req.raw); return await c.json(result); }); export default handle(app); PushProcessor depends on an abstract Database. This allows it to implement the push algorithm against any database. @rocicorp/zero/pg includes a ZQLDatabase implementation of this interface backed by Postgres. The implementation allows the same mutator functions to run on client and server, by providing an implementation of the ZQL APIs that custom mutators run on the client. ZQLDatabase in turn relies on an abstract DBConnection that provides raw access to a Postgres database. This allows you to use any Postgres library you like, as long as you provide a DBConnection implementation for it. The PostgresJSConnection class implements DBConnection for the excellent postgres.js library to connect to Postgres. To reuse the client mutators exactly as-is on the server just pass the result of the same createMutators function to PushProcessor. Server Error Handling The PushProcessor in @rocicorp/zero/pg skips any mutations that throw: app.post('/push', async c => { const result = await processor.process({ issue: { update: async (tx, data) => { // The mutation is skipped and the next mutation runs as normal. throw new Error('bonk'); }, }, }, ...); return await c.json(result); }) PushProcessor catches such errors and turns them into a structured response that gets sent back to the client. You can recover the errors and show UI if you want. It is also of course possible for the entire push endpoint to return an HTTP error, or to not reply at all: app.post('/push', async c => { // This will cause the client to resend all queued mutations. throw new Error('zonk'); const result = await processor.process({ // ... }, ...); return await c.json(result); }) If Zero recieves any response from the push endpoint other than HTTP 200, 401, or 403, it will disconnect, wait a few moments, reconnect, and then retry all unprocessed mutations. If Zero receives HTTP 401 or 403, the client refreshes the auth token if possible, then retries all queued mutations. If you want a different behavior, it is possible to implement your own PushProcessor and handle errors differently. Server-Specific Code To implement server-specific code, just run different mutators in your push endpoint! An approach we like is to create a separate server-mutators.ts file that wraps the client mutators: // server-mutators.ts import {CustomMutatorDefs} from '@rocicorp/zero'; import {schema} from './schema'; export function createMutators( clientMutators: CustomMutatorDefs, ) { return { // Reuse all client mutators except the ones in `issue` ...clientMutators, issue: { // Reuse all issue mutators except `update` ...clientMutators.issue, update: async (tx, {id, title}: {id: string; title: string}) => { // Call the shared mutator first await clientMutators.issue.update(tx, {id, title}); // Record a history of this operation happening in an audit // log table. await tx.mutate.auditLog.insert({ // Assuming you have an audit log table with fields for // `issueId`, `action`, and `timestamp`. issueId: id, action: 'update-title', timestamp: new Date().toISOString(), }); }, }, } as const satisfies CustomMutatorDefs; } For simple things, we also expose a location field on the transaction object that you can use to branch your code: myMutator: (tx) => { if (tx.location === 'client') { // Client-side code } else { // Server-side code } }, Permissions Because custom mutators are just arbitrary TypeScript functions, there is no need for a special permissions system. Therefore, you won't use Zero's write permissions when you use custom mutators. We hope to build custom queries next – a read analog to custom mutators. If we succeed, Zero's permission system will go away completely 🤯. In order to do permission checks, you'll need to know what user is making the request. You can pass this information to your mutators by adding a AuthData parameter to the createMutators function: type AuthData = { sub: string; }; export function createMutators(authData: AuthData | undefined) { return { issue: { launchMissiles: async (tx, args: {target: string}) => { if (!authData) { throw new Error('Users must be logged in to launch missiles'); } const hasPermission = await tx.query.user .where('id', authData.sub) .whereExists('permissions', q => q.where('name', 'launch-missiles')) .one(); if (!hasPermission) { throw new Error('User does not have permission to launch missiles'); } }, }, } as const satisfies CustomMutatorDefs; } The AuthData parameter can be any data required for authorization, but is typically just the decoded JWT: // app.tsx const zero = new Zero({ schema, auth: encodedJWT, mutators: createMutators(decodedJWT), }); // hono-server.ts const processor = new PushProcessor( schema, connectionProvider(postgres(process.env.ZERO_UPSTREAM_DB as string)), ); processor.process( createMutators(decodedJWT), c.req.query(), await c.req.json(), ); Dropping Down to Raw SQL The ServerTransaction interface has a dbTransaction property that exposes the underlying database connection. This allows you to run raw SQL queries directly against the database. This is useful for complex queries, or for using Postgres features that Zero doesn't support yet: markAllAsRead: async(tx: Transaction, {userId: string}) { // shared stuff ... if (tx.location === 'server') { // `tx` is now narrowed to `ServerTransaction`. // Do special server-only stuff with raw SQL. await tx.dbTransaction.query( ` UPDATE notification SET read = true WHERE user_id = $1 `, [userId], ); } } As a convenience we also expose a special CustomMutatorDefs for use with server-mutators.ts that sets all the mutators to ServerTransaction by default: // server-mutators.ts import type { CustomMutatorDefs, // Special server-side CustomMutatorDefs PostgresJSTransaction, ServerTransaction, } from '@rocicorp/zero/pg'; import {Schema} from './schema'; export function createMutators(clientMutators: CustomMutatorDefs) { return { // Reuse all client mutators except the ones in `issue` ...clientMutators, issue: { // Reuse all issue mutators except `update` ...clientMutators.issue, markAllAsRead: async (tx, {userId: string}) { // No narrowing necessary – tx is already a `ServerTransaction` // assert(tx.location === 'server'); await tx.dbTransaction.query( ` UPDATE notification SET read = true WHERE user_id = $1 `, [userId], ); }, } } as const satisfies CustomMutatorDefs< ServerTransaction >; } Notifications and Async Work It is bad practice to hold open database transactions while talking over the network, for example to send notifications. Instead, you should let the db transaction commit and do the work asynchronously. There is no specific support for this in custom mutators, but since mutators are just code, it’s easy to do: // server-mutators.ts export function createMutators( authData: AuthData, asyncTasks: Array<() => Promise>, ) { return { issue: { update: async (tx, {id, title}: {id: string; title: string}) => { await tx.mutate.issue.update({id, title}); asyncTasks.push(async () => { await sendEmailToSubscribers(args.id); }); }, }, } as const satisfies CustomMutatorDefs; } Then in your push handler: app.post('/push', async c => { const asyncTasks: Array<() => Promise> = []; const result = await processor.process( createMutators(authData, asyncTasks), c.req.query(), await c.req.json(), ); await Promise.all(asyncTasks.map(task => task())); return await c.json(result); }); Custom Database Connections You can implement an adapter to a different Postgres library, or even a different database entirely. To do so, provide a connectionProvider to PushProcessor that returns a different DBConnection implementation. For an example implementation, see the postgres implementation. Custom Push Implementation You can manually implement the push protocol in any programming language. This will be documented in the future, but you can refer to the PushProcessor source code for an example for now. Examples Zbugs uses custom mutators for all mutations, write permissions, and notifications. hello-zero-solid uses custom mutators for all mutations and for permissions.", "headings": [] }, { "id": "5-debug/inspector", "title": "Inspector API", "url": "/docs/debug/inspector", - "content": "The Zero instance provides an API to gather information about the client's current state, such as: All active queries Query TTL Active clients Client database contents This can help figuring out why you hit loading states, how many queries are active at a time, if you have any resource leaks due to failing to clean up queries or if expected data is missing on the client. Creating an Inspector Each Zero instance has an inspect method that will return the inspector. The inspect method is asynchronous because it performs lazy loading of inspect-only related code. For convenience, the active Zero instance is automatically exposed at \\_\\_zero, so you can access the inspector in the console like this: ```ts const inspector = await __zero.inspect(); ``` If you are using React, you can use React.lazy to dynamically load components that depend on the inspect API. Once you have an inspector you can inspect the current client and client group. For example to see active queries for the current client: ```ts console.table(await inspector.client.queries()); ``` To inspect other clients within the group: ```ts const allClients = await inspector.clients(); ``` Dumping Data In addition to information about queries, you can see the contents of the client side database. ```ts const inspector = await zero.inspect(); const client = inspector.client; // All raw k/v data currently synced to client console.log('client map:'); console.log(await client.map()); // kv table extracted into tables // This is same info that is in z.query[tableName].run() for (const tableName of Object.keys(schema.tables)) { console.log(`table ${tableName}:`); console.table(await client.rows(tableName)); } ```", + "content": "The Zero instance provides an API to gather information about the client's current state, such as: All active queries Query TTL Active clients Client database contents This can help figuring out why you hit loading states, how many queries are active at a time, if you have any resource leaks due to failing to clean up queries or if expected data is missing on the client. Creating an Inspector Each Zero instance has an inspect method that will return the inspector. The inspect method is asynchronous because it performs lazy loading of inspect-only related code. For convenience, the active Zero instance is automatically exposed at \\_\\_zero, so you can access the inspector in the console like this: const inspector = await __zero.inspect(); If you are using React, you can use React.lazy to dynamically load components that depend on the inspect API. Once you have an inspector you can inspect the current client and client group. For example to see active queries for the current client: console.table(await inspector.client.queries()); To inspect other clients within the group: const allClients = await inspector.clients(); Dumping Data In addition to information about queries, you can see the contents of the client side database. const inspector = await zero.inspect(); const client = inspector.client; // All raw k/v data currently synced to client console.log('client map:'); console.log(await client.map()); // kv table extracted into tables // This is same info that is in z.query[tableName].run() for (const tableName of Object.keys(schema.tables)) { console.log(`table ${tableName}:`); console.table(await client.rows(tableName)); }", "headings": [] }, { "id": "6-debug/otel", "title": "OpenTelemetry", "url": "/docs/debug/otel", - "content": "The zero-cache service embeds the JavaScript OTLP Exporter and can send logs, traces, and metrics to any standard otel collector. To enable otel, set the following environment variables then run zero-cache as normal: ```sh OTEL_EXPORTER_OTLP_ENDPOINT=\"\" OTEL_EXPORTER_OTLP_HEADERS=\"\" OTEL_RESOURCE_ATTRIBUTES=\"\" OTEL_NODE_RESOURCE_DETECTORS=\"env,host,os\" ``` Grafana Cloud Walkthrough Here are instructions to setup Grafana Cloud, but the setup for other otel collectors should be similar. Sign up for Grafana Cloud (Free Tier) Click Connections > Add Connection in the left sidebar add-connection Search for \"OpenTelemetry\" and select it Click \"Quickstart\" quickstart Select \"JavaScript\" javascript Create a new token Copy the environment variables into your .env file or similar copy-env Start zero-cache Look for logs under \"Drilldown\" > \"Logs\" in left sidebar", + "content": "The zero-cache service embeds the JavaScript OTLP Exporter and can send logs, traces, and metrics to any standard otel collector. To enable otel, set the following environment variables then run zero-cache as normal: OTEL_EXPORTER_OTLP_ENDPOINT=\"\" OTEL_EXPORTER_OTLP_HEADERS=\"\" OTEL_RESOURCE_ATTRIBUTES=\"\" OTEL_NODE_RESOURCE_DETECTORS=\"env,host,os\" Grafana Cloud Walkthrough Here are instructions to setup Grafana Cloud, but the setup for other otel collectors should be similar. Sign up for Grafana Cloud (Free Tier) Click Connections > Add Connection in the left sidebar add-connection Search for \"OpenTelemetry\" and select it Click \"Quickstart\" quickstart Select \"JavaScript\" javascript Create a new token Copy the environment variables into your .env file or similar copy-env Start zero-cache Look for logs under \"Drilldown\" > \"Logs\" in left sidebar", "headings": [] }, { "id": "7-debug/permissions", "title": "Debugging Permissions", "url": "/docs/debug/permissions", - "content": "Given that permissions are defined in their own file and internally applied to queries, it might be hard to figure out if or why a permission check is failing. Read Permissions You can use the analyze-query utility with the --apply-permissions flag to see the complete query Zero runs, including read permissions. ```bash npx analyze-query --schema-path='./shared/schema.ts' --query='issue.related(\"comments\")' --apply-permissions --auth-data='{\"userId\":\"user-123\"}' ``` If the result looks right, the problem may be that Zero is not receiving the AuthData that you think it is. You can retrieve a query hash from websocket or server logs, then ask Zero for the details on that specific query. Run this command with the same environment you run zero-cache with. It will use your upstream or cvr configuration to look up the query hash in the cvr database. ```bash npx analyze-query --schema-path='./shared/schema.ts' --hash='3rhuw19xt9vry' --apply-permissions --auth-data='{\"userId\":\"user-123\"}' ``` Write Permissions Look for a WARN level log in the output from zero-cache like this: ``` Permission check failed for {\"op\":\"update\",\"tableName\":\"message\",...}, action update, phase preMutation, authData: {...}, rowPolicies: [...], cellPolicies: [] ``` Zero prints the row, auth data, and permission policies that was applied to any failed writes.", + "content": "Given that permissions are defined in their own file and internally applied to queries, it might be hard to figure out if or why a permission check is failing. Read Permissions You can use the analyze-query utility with the --apply-permissions flag to see the complete query Zero runs, including read permissions. npx analyze-query --schema-path='./shared/schema.ts' --query='issue.related(\"comments\")' --apply-permissions --auth-data='{\"userId\":\"user-123\"}' If the result looks right, the problem may be that Zero is not receiving the AuthData that you think it is. You can retrieve a query hash from websocket or server logs, then ask Zero for the details on that specific query. Run this command with the same environment you run zero-cache with. It will use your upstream or cvr configuration to look up the query hash in the cvr database. npx analyze-query --schema-path='./shared/schema.ts' --hash='3rhuw19xt9vry' --apply-permissions --auth-data='{\"userId\":\"user-123\"}' Write Permissions Look for a WARN level log in the output from zero-cache like this: Permission check failed for {\"op\":\"update\",\"tableName\":\"message\",...}, action update, phase preMutation, authData: {...}, rowPolicies: [...], cellPolicies: [] Zero prints the row, auth data, and permission policies that was applied to any failed writes.", "headings": [] }, { "id": "8-debug/query-asts", "title": "Query ASTs", "url": "/docs/debug/query-asts", - "content": "An AST (Abstract Syntax Tree) is a representation of a query that is used internally by Zero. It is not meant to be human readable, but it sometimes shows up in logs and other places. If you need to read one of these, save the AST to a json file. Then run the following command: ```bash cat ast.json | npx ast-to-zql ``` The returned ZQL query will be using server names, rather than client names, to identify columns and tables. If you provide the schema file as an option you will get mapped back to client names: ```bash cat ast.json | npx ast-to-zql --schema schema.ts ``` This comes into play if, in your schema.ts, you use the from feature to have different names on the client than your backend DB.", + "content": "An AST (Abstract Syntax Tree) is a representation of a query that is used internally by Zero. It is not meant to be human readable, but it sometimes shows up in logs and other places. If you need to read one of these, save the AST to a json file. Then run the following command: cat ast.json | npx ast-to-zql The returned ZQL query will be using server names, rather than client names, to identify columns and tables. If you provide the schema file as an option you will get mapped back to client names: cat ast.json | npx ast-to-zql --schema schema.ts This comes into play if, in your schema.ts, you use the from feature to have different names on the client than your backend DB.", "headings": [] }, { "id": "9-debug/replication", "title": "Replication", "url": "/docs/debug/replication", - "content": "Resetting During development we all do strange things (unsafely changing schemas, removing files, etc.). If the replica ever gets wedged (stops replicating, acts strange) you can wipe it and start over. If you copied your setup from hello-zero or hello-zero-solid, you can also run npm run dev:clean Otherwise you can run rm /tmp/my-zero-replica.db\\* (see your .env file for the replica file location) to clear the contents of the replica. It is always safe to wipe the replica. Wiping will have no impact on your upstream database. Downstream zero-clients will get re-synced when they connect. Inspecting For data to be synced to the client it must first be replicated to zero-cache. You can check the contents of zero-cache via: ```bash $ npx @rocicorp/zero-sqlite3 /tmp/my-zero-replica.db ``` To inspect your Zero database, you have two options: Use our pre-compiled SQLite build @rocicorp/zero-sqlite3 as described above Build SQLite from the SQLite bedrock branch yourself This will drop you into a sqlite3 shell with which you can use to explore the contents of the replica. ```sql sqlite> .tables _zero.changeLog emoji viewState _zero.replicationConfig issue zero.permissions _zero.replicationState issueLabel zero.schemaVersions _zero.runtimeEvents label zero_0.clients _zero.versionHistory user comment userPref sqlite> .mode qbox sqlite> SELECT * FROM label; ┌─────────────────────────┬──────────────────────────┬────────────┐ │ id │ name │ _0_version │ ├─────────────────────────┼──────────────────────────┼────────────┤ │ 'ic_g-DZTYDApZR_v7Cdcy' │ 'bug' │ '4ehreg' │ ... ``` Miscellaneous If you see FATAL: sorry, too many clients already in logs, it’s because you have two zero-cache instances running against dev. One is probably in a background tab somewhere. In production, zero-cache can run horizontally scaled but on dev it doesn’t run in the config that allows that.", + "content": "Resetting During development we all do strange things (unsafely changing schemas, removing files, etc.). If the replica ever gets wedged (stops replicating, acts strange) you can wipe it and start over. If you copied your setup from hello-zero or hello-zero-solid, you can also run npm run dev:clean Otherwise you can run rm /tmp/my-zero-replica.db\\* (see your .env file for the replica file location) to clear the contents of the replica. It is always safe to wipe the replica. Wiping will have no impact on your upstream database. Downstream zero-clients will get re-synced when they connect. Inspecting For data to be synced to the client it must first be replicated to zero-cache. You can check the contents of zero-cache via: $ npx @rocicorp/zero-sqlite3 /tmp/my-zero-replica.db To inspect your Zero database, you have two options: Use our pre-compiled SQLite build @rocicorp/zero-sqlite3 as described above Build SQLite from the SQLite bedrock branch yourself This will drop you into a sqlite3 shell with which you can use to explore the contents of the replica. sqlite> .tables _zero.changeLog emoji viewState _zero.replicationConfig issue zero.permissions _zero.replicationState issueLabel zero.schemaVersions _zero.runtimeEvents label zero_0.clients _zero.versionHistory user comment userPref sqlite> .mode qbox sqlite> SELECT * FROM label; ┌─────────────────────────┬──────────────────────────┬────────────┐ │ id │ name │ _0_version │ ├─────────────────────────┼──────────────────────────┼────────────┤ │ 'ic_g-DZTYDApZR_v7Cdcy' │ 'bug' │ '4ehreg' │ ... Miscellaneous If you see FATAL: sorry, too many clients already in logs, it’s because you have two zero-cache instances running against dev. One is probably in a background tab somewhere. In production, zero-cache can run horizontally scaled but on dev it doesn’t run in the config that allows that.", "headings": [] }, { "id": "10-debug/slow-queries", "title": "Slow Queries", "url": "/docs/debug/slow-queries", - "content": "In the zero-cache logs, you may see statements indicating a query is slow: ```shell { \"level\": \"DEBUG\", \"worker\": \"syncer\", \"component\": \"view-syncer\", \"hydrationTimeMs\": 1339, \"message\": \"Total rows considered: 146\" }, ``` or: ```shell hash=3rhuw19xt9vry transformationHash=1nv7ot74gxfl7 Slow query materialization 325.46865100000286 ``` Or, you may just notice queries taking longer than expected in the UI. Here are some tips to help debug such slow queries. Check ttl If you are seeing unexpected UI flicker when moving between views, it is likely that the queries backing these views have the default ttl of never. Set the ttl to something like 5m to keep data cached across navigations. You may alternately want to preload some data at app startup. Conversely, if you are setting ttl to long values, then it can happen that you have many backgrounded queries still running that the app is not using. You can see which queries are running using the inspector. Ensure that only expected queries are running. See long TTLs for more information. Check Storage zero-cache is effectively a database. It requires fast (low latency and high bandwidth) disk access to perform well. If you're running on network attached storage with high latency, or on AWS with low IOPS, then this is the most likely culprit. The default deployment of Zero currently uses Fargate which scales IOPS with vCPU. Increasing the vCPU will increase storage throughput and likely resolve the issue. Fly.io provides physically attached SSDs, even for their smallest VMs. Deploying zero-cache there (or any other provider that offers physically attached SSDs) is another option. Locality If you see log lines like: ```shell flushed cvr ... (124ms) ``` this indicates that zero-cache is likely deployed too far away from your CVR database. If you did not configure a CVR database URL then this will be your product's Postgres DB. A slow CVR flush can slow down Zero, since it must complete the flush before sending query result(s) to clients. Try moving zero-cache to be deployed as close as possible to the CVR database. Query Plan If neither (1) nor (2) is a problem, then the query itself is the most likely culprit. The @rocicorp/zero package ships with a query analyzer to help debug this. The analyzer should be run in the directory that contains the .env file for zero-cache as it will use the .env file to find your replica. Example: ```shell npx analyze-query \\ --schema-path=./shared/schema.ts \\ --query='issue.related(\"comments\")' ``` This will output the query plan and time to execute each phase of that plan. Note that query performance can also be affected by read permissions. See Debugging Permissions for information on how to analyze queries with read permissions applied. /statz zero-cache makes some internal health statistics available via the /statz endpoint of zero-cache. In order to access this, you must configure an admin password.", + "content": "In the zero-cache logs, you may see statements indicating a query is slow: { \"level\": \"DEBUG\", \"worker\": \"syncer\", \"component\": \"view-syncer\", \"hydrationTimeMs\": 1339, \"message\": \"Total rows considered: 146\" }, or: hash=3rhuw19xt9vry transformationHash=1nv7ot74gxfl7 Slow query materialization 325.46865100000286 Or, you may just notice queries taking longer than expected in the UI. Here are some tips to help debug such slow queries. Check ttl If you are seeing unexpected UI flicker when moving between views, it is likely that the queries backing these views have the default ttl of never. Set the ttl to something like 5m to keep data cached across navigations. You may alternately want to preload some data at app startup. Conversely, if you are setting ttl to long values, then it can happen that you have many backgrounded queries still running that the app is not using. You can see which queries are running using the inspector. Ensure that only expected queries are running. See long TTLs for more information. Check Storage zero-cache is effectively a database. It requires fast (low latency and high bandwidth) disk access to perform well. If you're running on network attached storage with high latency, or on AWS with low IOPS, then this is the most likely culprit. The default deployment of Zero currently uses Fargate which scales IOPS with vCPU. Increasing the vCPU will increase storage throughput and likely resolve the issue. Fly.io provides physically attached SSDs, even for their smallest VMs. Deploying zero-cache there (or any other provider that offers physically attached SSDs) is another option. Locality If you see log lines like: flushed cvr ... (124ms) this indicates that zero-cache is likely deployed too far away from your CVR database. If you did not configure a CVR database URL then this will be your product's Postgres DB. A slow CVR flush can slow down Zero, since it must complete the flush before sending query result(s) to clients. Try moving zero-cache to be deployed as close as possible to the CVR database. Query Plan If neither (1) nor (2) is a problem, then the query itself is the most likely culprit. The @rocicorp/zero package ships with a query analyzer to help debug this. The analyzer should be run in the directory that contains the .env file for zero-cache as it will use the .env file to find your replica. Example: npx analyze-query \\ --schema-path=./shared/schema.ts \\ --query='issue.related(\"comments\")' This will output the query plan and time to execute each phase of that plan. Note that query performance can also be affected by read permissions. See Debugging Permissions for information on how to analyze queries with read permissions applied. /statz zero-cache makes some internal health statistics available via the /statz endpoint of zero-cache. In order to access this, you must configure an admin password.", "headings": [] }, { "id": "11-deployment", "title": "Deploying Zero", "url": "/docs/deployment", - "content": "To deploy a Zero app, you need to: Deploy your backend database. Most standard Postgres hosts work with Zero. Deploy zero-cache. We provide a Docker image that can work with most Docker hosts. Deploy your frontend. You can use any hosting service like Vercel or Netlify. This page describes how to deploy zero-cache. Architecture zero-cache is a horizontally scalable, stateful web service that maintains a SQLite replica of your Postgres database. It uses this replica to sync ZQL queries to clients over WebSockets. You don't have to know the details of how zero-cache works to run it, but it helps to know the basic structure. A running zero-cache is composed of a single replication-manager node and multiple view-syncer nodes. It also depends on Postgres, S3, and attached SSD storage. Upstream: Your application's Postgres database. Change DB: A Postgres DB used by Zero to store a recent subset of the Postgres replication log. CVR DB: A Postgres DB used by Zero to store Client View Records (CVRs). CVRs track the state of each synced client. We allow separate DBs so that they can be scaled and tuned independently if desired. S3: Stores a canonical copy of the SQLite replica. File System: Used by both node types to store local copies of the SQLite replica. Can be ephemeral – Zero will re-initialize from S3 on startup. Recommended to use attached SSD storage for best performance. Replication Manager: Serves as the single consumer of the Postgres replication log. Stores a recent subset of the Postgres changelog in the Change DB for catching up ViewSyncers when they initialize. Also maintains the canonical replica, which ViewSyncers initialize from. View Syncers: Handle WebSocket connections from clients and run ZQL queries. Updates CVR DB with the latest state of each client as queries run. Uses CVR DB on client connection to compute the initial diff to catch clients up. Topology You should deploy zero-cache close to your database because the mutation implementation is chatty. In the future, mutations will move out of zero-cache. When that happens you can deploy zero-cache geographically distributed and it will double as a read-replica. Updating When run with multiple View Syncer nodes, zero-cache supports rolling, downtime-free updates. A new Replication Manager takes over the replication stream from the old Replication Manager, and connections from the old View Syncers are gradually drained and absorbed by active View Syncers. Client/Server Version Compatibility Servers are compatible with any client of same major version, and with clients one major version back. So for example: Server 0.2.\\* is compatible with client 0.2.\\* Server 0.2.\\* is compatible with client 0.1.\\* Server 2.\\*.\\* is compatible with client 2.\\*.\\* Server 2.\\*.\\* is compatible with client 1.\\*.\\* To upgrade Zero to a new major version, first deploy the new zero-cache, then the new frontend. Configuration The zero-cache image is configured via environment variables. See zero-cache Config for available options. Guide: Multi-Node on SST+AWS SST is our recommended way to deploy Zero. The setup below costs about $35/month. You can scale it up or down as needed by adjusting the amount of vCPUs and memory in each task. Setup Upstream Create an upstream Postgres database server somewhere. See Connecting to Postgres for details. Populate the schema and any initial data for your application. Setup AWS See AWS setup guide. The end result should be that you have a dev profile and SSO session defined in your ~/.aws/config file. Initialize SST ```bash npx sst init --yes ``` Choose \"aws\" for where to deploy. Then overwite /sst.config.ts with the following code: ```ts /* eslint-disable */ /// import {execSync} from 'child_process'; export default $config({ app(input) { return { name: 'hello-zero', removal: input?.stage === 'production' ? 'retain' : 'remove', home: 'aws', region: process.env.AWS_REGION || 'us-east-1', providers: { command: true, }, }; }, async run() { const zeroVersion = execSync('cat package.json | jq '.dependencies[\"@rocicorp/zero\"]') .toString() .trim(); // S3 Bucket const replicationBucket = new sst.aws.Bucket(`replication-bucket`); // VPC Configuration const vpc = new sst.aws.Vpc(`vpc`, { az: 2, }); // ECS Cluster const cluster = new sst.aws.Cluster(`cluster`, { vpc, }); const conn = new sst.Secret('PostgresConnectionString'); const zeroAuthSecret = new sst.Secret('ZeroAuthSecret'); // Common environment variables const commonEnv = { ZERO_PUSH_URL: '', // Your push api url when using custom mutators ZERO_UPSTREAM_DB: conn.value, ZERO_CVR_DB: conn.value, ZERO_CHANGE_DB: conn.value, ZERO_AUTH_SECRET: zeroAuthSecret.value, ZERO_REPLICA_FILE: 'sync-replica.db', ZERO_IMAGE_URL: `rocicorp/zero:${zeroVersion}`, ZERO_CVR_MAX_CONNS: '10', ZERO_UPSTREAM_MAX_CONNS: '10', }; // Replication Manager Service const replicationManager = cluster.addService(`replication-manager`, { cpu: '0.5 vCPU', memory: '1 GB', architecture: 'arm64', image: commonEnv.ZERO_IMAGE_URL, link: [replicationBucket], wait: true, health: { command: ['CMD-SHELL', 'curl -f http://localhost:4849/ || exit 1'], interval: '5 seconds', retries: 3, startPeriod: '300 seconds', }, environment: { ...commonEnv, ZERO_LITESTREAM_BACKUP_URL: $interpolate`s3://${replicationBucket.name}/backup`, ZERO_NUM_SYNC_WORKERS: '0', }, loadBalancer: { public: false, ports: [ { listen: '80/http', forward: '4849/http', }, ], }, transform: { service: { // e.g. extend the grace period for initial sync of large databases healthCheckGracePeriodSeconds: 600, } target: { healthCheck: { enabled: true, path: '/keepalive', protocol: 'HTTP', interval: 5, healthyThreshold: 2, timeout: 3, }, }, }, }); // View Syncer Service const viewSyncer = cluster.addService( `view-syncer`, { cpu: '1 vCPU', memory: '2 GB', architecture: 'arm64', image: commonEnv.ZERO_IMAGE_URL, link: [replicationBucket], health: { command: ['CMD-SHELL', 'curl -f http://localhost:4848/ || exit 1'], interval: '5 seconds', retries: 3, startPeriod: '300 seconds', }, environment: { ...commonEnv, ZERO_CHANGE_STREAMER_URI: replicationManager.url, }, loadBalancer: { ports: [ { listen: '80/http', forward: '4848/http', }, ], }, logging: { retention: '1 month', }, transform: { service: { // e.g. extend the grace period for initial sync of large databases healthCheckGracePeriodSeconds: 600, } target: { healthCheck: { enabled: true, path: '/keepalive', protocol: 'HTTP', interval: 5, healthyThreshold: 2, timeout: 3, }, stickiness: { enabled: true, type: 'lb_cookie', cookieDuration: 120, }, }, }, }, ); // Permissions deployment // Note: this setup requires your CI/CD pipeline to have access to your // Postgres database. If you do not want to do this, you can also use // `npx zero-deploy-permissions --output-format=sql` during build to // generate a permissions.sql file, then run that file as part of your // deployment within your VPC. See hello-zero-solid for an example: // https://github.com/rocicorp/hello-zero-solid/blob/main/sst.config.ts#L141 new command.local.Command( 'zero-deploy-permissions', { create: `npx zero-deploy-permissions -p ../../src/schema.ts`, // Run the Command on every deploy ... triggers: [Date.now()], environment: { ZERO_UPSTREAM_DB: commonEnv.ZERO_UPSTREAM_DB, }, }, // after the view-syncer is deployed. {dependsOn: viewSyncer}, ); }, }); ``` Set SST Secrets Configure SST with your Postgres connection string and Zero Auth Secret. Note that if you use JWT-based auth, you'll need to change the environment variables in the sst.config.ts file above, then set a different secret here. ```bash npx sst secret set PostgresConnectionString \"YOUR-PG-CONN-STRING\" npx sst secret set ZeroAuthSecret \"YOUR-ZERO-AUTH-SECRET\" ``` Deploy ```bash npx sst deploy ``` This takes about 5-10 minutes. If successful, you should see a URL for the view-syncer service. This is the URL to pass to the server parameter of the Zero constructor on the client. If unsuccessful, you can get detailed logs with npx sst deploy --verbose. Come find us on Discord and we'll help get you sorted out. Guide: Single-Node on Fly.io Let's deploy the Quickstart app to Fly.io. We'll use Fly.io for both the database and zero-cache. Setup Quickstart Go through the Quickstart guide to get the app running locally. Setup Fly.io Create an account on Fly.io and install the Fly CLI. Create Postgres app ```bash INITIALS=aa PG_APP_NAME=$INITIALS-zstart-pg PG_PASSWORD=\"$(head -c 256 /dev/urandom | od -An -t x1 | tr -d ' \\n' | tr -dc 'a-zA-Z' | head -c 16)\" fly postgres create \\ --name $PG_APP_NAME \\ --region lax \\ --initial-cluster-size 1 \\ --vm-size shared-cpu-2x \\ --volume-size 40 \\ --password=$PG_PASSWORD ``` Seed Upstream database Populate the database with initial data and set its wal\\_level to logical to support replication to zero-cache. Then restart the database to apply the changes. ```bash (cat ./docker/seed.sql; echo \"\\q\") | fly pg connect -a $PG_APP_NAME echo \"ALTER SYSTEM SET wal_level = logical; \\q\" | fly pg connect -a $PG_APP_NAME fly postgres restart --app $PG_APP_NAME ``` Create zero-cache Fly.io app ```bash CACHE_APP_NAME=$INITIALS-zstart-cache fly app create $CACHE_APP_NAME ``` Publish zero-cache Create a fly.toml file. ```bash CONNECTION_STRING=\"postgres://postgres:$PG_PASSWORD@$PG_APP_NAME.flycast:5432\" ZERO_VERSION=$(npm list @rocicorp/zero | grep @rocicorp/zero | cut -f 3 -d @) cat < fly.toml app = \"$CACHE_APP_NAME\" primary_region = 'lax' [build] image = \"registry.hub.docker.com/rocicorp/zero:${ZERO_VERSION}\" [http_service] internal_port = 4848 force_https = true auto_stop_machines = 'off' min_machines_running = 1 [[http_service.checks]] grace_period = \"10s\" interval = \"30s\" method = \"GET\" timeout = \"5s\" path = \"/\" [[vm]] memory = '2gb' cpu_kind = 'shared' cpus = 2 [mounts] source = \"sqlite_db\" destination = \"/data\" [env] ZERO_REPLICA_FILE = \"/data/sync-replica.db\" ZERO_UPSTREAM_DB=\"${CONNECTION_STRING}/zstart?sslmode=disable\" ZERO_CVR_DB=\"${CONNECTION_STRING}/zstart_cvr?sslmode=disable\" ZERO_CHANGE_DB=\"${CONNECTION_STRING}/zstart_cdb?sslmode=disable\" ZERO_PUSH_URL=\"\" ZERO_AUTH_SECRET=\"secretkey\" LOG_LEVEL = \"debug\" EOF ``` Then publish zero-cache: ```bash fly deploy ``` Deploy Permissions Now zero-cache is running on Fly.io, but there are no permissions. If you run the app against this zero-cache, you'll see that no data is returned from any query. To fix this, deploy your permissions: ```bash npx zero-deploy-permissions --schema-path='./src/schema.ts' --output-file='/tmp/permissions.sql' (cat /tmp/permissions.sql; echo \"\\q\") | fly pg connect -a $PG_APP_NAME -d zstart ``` You will need to redo this step every time you change your app's permissions, likely as part of your CI/CD pipeline. Use Remote zero-cache ```bash VITE_PUBLIC_SERVER=\"https://${CACHE_APP_NAME}.fly.dev/\" npm run dev:ui ``` Now restart the frontend to pick up the env change, and refresh the app. You can stop your local database and zero-cache as we're not using them anymore. Open the web inspector to verify the app is talking to the remote zero-cache! You can deploy the frontend to any standard hosting service like Vercel or Netlify, or even to Fly.io! Deploy Frontend to Vercel If you've followed the above guide and deployed zero-cache to fly, you can simply run: ```sh vercel deploy --prod \\ -e ZERO_AUTH_SECRET=\"secretkey\" \\ -e VITE_PUBLIC_SERVER='https://${CACHE_APP_NAME}.fly.dev/' ``` to deploy your frontend to Vercel. Explaining the arguments above -- ZERO\\_AUTH\\_SECRET - The secret to create and verify JWTs. This is the same secret that was used when deploying zero-cache to fly. VITE\\_PUBLIC\\_SERVER - The URL the frontend will call to talk to the zero-cache server. This is the URL of the fly app. Guide: Multi-Node on Raw AWS S3 Bucket Create an S3 bucket. zero-cache uses S3 to backup its SQLite replica so that it survives task restarts. Fargate Services Run zero-cache as two Fargate services (using the same rocicorp/zero docker image): replication-manager zero-cache config: ZERO\\_LITESTREAM\\_BACKUP\\_URL=s3://{bucketName}/{generation} ZERO\\_NUM\\_SYNC\\_WORKERS=0 Task count: 1 view-syncer zero-cache config: ZERO\\_CHANGE\\_STREAMER\\_URI=http://{replication-manager} Task count: N You can also use dynamic scaling Notes Standard rolling restarts are fine for both services Set ZERO\\_CVR\\_MAX\\_CONNS and ZERO\\_UPSTREAM\\_MAX\\_CONNS appropriately so that the total connections from both running and updating view-syncers (e.g. DesiredCount \\* MaximumPercent) do not exceed your database’s max\\_connections. The {generation} component of the s3://{bucketName}/{generation} URL is an arbitrary path component that can be modified to reset the replica (e.g. a date, a number, etc.). Setting this to a new path is the multi-node equivalent of deleting the replica file to resync. Note: zero-cache does not manage cleanup of old generations. The replication-manager serves requests on port 4849. Routing from the view-syncer to the http://{replication-manager} can be achieved using the following mechanisms (in order of preference): An internal load balancer Service Connect Service Discovery Fargate ephemeral storage is used for the replica. The default size is 20GB. This can be increased up to 200GB Allocate at least twice the size of the database to support the internal VACUUM operation. Guide: $PLATFORM Where should we deploy Zero next?? Let us know on Discord!", + "content": "To deploy a Zero app, you need to: Deploy your backend database. Most standard Postgres hosts work with Zero. Deploy zero-cache. We provide a Docker image that can work with most Docker hosts. Deploy your frontend. You can use any hosting service like Vercel or Netlify. This page describes how to deploy zero-cache. Architecture zero-cache is a horizontally scalable, stateful web service that maintains a SQLite replica of your Postgres database. It uses this replica to sync ZQL queries to clients over WebSockets. You don't have to know the details of how zero-cache works to run it, but it helps to know the basic structure. A running zero-cache is composed of a single replication-manager node and multiple view-syncer nodes. It also depends on Postgres, S3, and attached SSD storage. Upstream: Your application's Postgres database. Change DB: A Postgres DB used by Zero to store a recent subset of the Postgres replication log. CVR DB: A Postgres DB used by Zero to store Client View Records (CVRs). CVRs track the state of each synced client. We allow separate DBs so that they can be scaled and tuned independently if desired. S3: Stores a canonical copy of the SQLite replica. File System: Used by both node types to store local copies of the SQLite replica. Can be ephemeral – Zero will re-initialize from S3 on startup. Recommended to use attached SSD storage for best performance. Replication Manager: Serves as the single consumer of the Postgres replication log. Stores a recent subset of the Postgres changelog in the Change DB for catching up ViewSyncers when they initialize. Also maintains the canonical replica, which ViewSyncers initialize from. View Syncers: Handle WebSocket connections from clients and run ZQL queries. Updates CVR DB with the latest state of each client as queries run. Uses CVR DB on client connection to compute the initial diff to catch clients up. Topology You should deploy zero-cache close to your database because the mutation implementation is chatty. In the future, mutations will move out of zero-cache. When that happens you can deploy zero-cache geographically distributed and it will double as a read-replica. Updating When run with multiple View Syncer nodes, zero-cache supports rolling, downtime-free updates. A new Replication Manager takes over the replication stream from the old Replication Manager, and connections from the old View Syncers are gradually drained and absorbed by active View Syncers. Client/Server Version Compatibility Servers are compatible with any client of same major version, and with clients one major version back. So for example: Server 0.2.\\* is compatible with client 0.2.\\* Server 0.2.\\* is compatible with client 0.1.\\* Server 2.\\*.\\* is compatible with client 2.\\*.\\* Server 2.\\*.\\* is compatible with client 1.\\*.\\* To upgrade Zero to a new major version, first deploy the new zero-cache, then the new frontend. Configuration The zero-cache image is configured via environment variables. See zero-cache Config for available options. Guide: Multi-Node on SST+AWS SST is our recommended way to deploy Zero. The setup below costs about $35/month. You can scale it up or down as needed by adjusting the amount of vCPUs and memory in each task. Setup Upstream Create an upstream Postgres database server somewhere. See Connecting to Postgres for details. Populate the schema and any initial data for your application. Setup AWS See AWS setup guide. The end result should be that you have a dev profile and SSO session defined in your ~/.aws/config file. Initialize SST npx sst init --yes Choose \"aws\" for where to deploy. Then overwite /sst.config.ts with the following code: /* eslint-disable */ /// import {execSync} from 'child_process'; export default $config({ app(input) { return { name: 'hello-zero', removal: input?.stage === 'production' ? 'retain' : 'remove', home: 'aws', region: process.env.AWS_REGION || 'us-east-1', providers: { command: true, }, }; }, async run() { const zeroVersion = execSync('cat package.json | jq '.dependencies[\"@rocicorp/zero\"]') .toString() .trim(); // S3 Bucket const replicationBucket = new sst.aws.Bucket(`replication-bucket`); // VPC Configuration const vpc = new sst.aws.Vpc(`vpc`, { az: 2, }); // ECS Cluster const cluster = new sst.aws.Cluster(`cluster`, { vpc, }); const conn = new sst.Secret('PostgresConnectionString'); const zeroAuthSecret = new sst.Secret('ZeroAuthSecret'); // Common environment variables const commonEnv = { ZERO_PUSH_URL: '', // Your push api url when using custom mutators ZERO_UPSTREAM_DB: conn.value, ZERO_CVR_DB: conn.value, ZERO_CHANGE_DB: conn.value, ZERO_AUTH_SECRET: zeroAuthSecret.value, ZERO_REPLICA_FILE: 'sync-replica.db', ZERO_IMAGE_URL: `rocicorp/zero:${zeroVersion}`, ZERO_CVR_MAX_CONNS: '10', ZERO_UPSTREAM_MAX_CONNS: '10', }; // Replication Manager Service const replicationManager = cluster.addService(`replication-manager`, { cpu: '0.5 vCPU', memory: '1 GB', architecture: 'arm64', image: commonEnv.ZERO_IMAGE_URL, link: [replicationBucket], wait: true, health: { command: ['CMD-SHELL', 'curl -f http://localhost:4849/ || exit 1'], interval: '5 seconds', retries: 3, startPeriod: '300 seconds', }, environment: { ...commonEnv, ZERO_LITESTREAM_BACKUP_URL: $interpolate`s3://${replicationBucket.name}/backup`, ZERO_NUM_SYNC_WORKERS: '0', }, loadBalancer: { public: false, ports: [ { listen: '80/http', forward: '4849/http', }, ], }, transform: { service: { // e.g. extend the grace period for initial sync of large databases healthCheckGracePeriodSeconds: 600, } target: { healthCheck: { enabled: true, path: '/keepalive', protocol: 'HTTP', interval: 5, healthyThreshold: 2, timeout: 3, }, }, }, }); // View Syncer Service const viewSyncer = cluster.addService( `view-syncer`, { cpu: '1 vCPU', memory: '2 GB', architecture: 'arm64', image: commonEnv.ZERO_IMAGE_URL, link: [replicationBucket], health: { command: ['CMD-SHELL', 'curl -f http://localhost:4848/ || exit 1'], interval: '5 seconds', retries: 3, startPeriod: '300 seconds', }, environment: { ...commonEnv, ZERO_CHANGE_STREAMER_URI: replicationManager.url, }, loadBalancer: { ports: [ { listen: '80/http', forward: '4848/http', }, ], }, logging: { retention: '1 month', }, transform: { service: { // e.g. extend the grace period for initial sync of large databases healthCheckGracePeriodSeconds: 600, } target: { healthCheck: { enabled: true, path: '/keepalive', protocol: 'HTTP', interval: 5, healthyThreshold: 2, timeout: 3, }, stickiness: { enabled: true, type: 'lb_cookie', cookieDuration: 120, }, }, }, }, ); // Permissions deployment // Note: this setup requires your CI/CD pipeline to have access to your // Postgres database. If you do not want to do this, you can also use // `npx zero-deploy-permissions --output-format=sql` during build to // generate a permissions.sql file, then run that file as part of your // deployment within your VPC. See hello-zero-solid for an example: // https://github.com/rocicorp/hello-zero-solid/blob/main/sst.config.ts#L141 new command.local.Command( 'zero-deploy-permissions', { create: `npx zero-deploy-permissions -p ../../src/schema.ts`, // Run the Command on every deploy ... triggers: [Date.now()], environment: { ZERO_UPSTREAM_DB: commonEnv.ZERO_UPSTREAM_DB, }, }, // after the view-syncer is deployed. {dependsOn: viewSyncer}, ); }, }); Set SST Secrets Configure SST with your Postgres connection string and Zero Auth Secret. Note that if you use JWT-based auth, you'll need to change the environment variables in the sst.config.ts file above, then set a different secret here. npx sst secret set PostgresConnectionString \"YOUR-PG-CONN-STRING\" npx sst secret set ZeroAuthSecret \"YOUR-ZERO-AUTH-SECRET\" Deploy npx sst deploy This takes about 5-10 minutes. If successful, you should see a URL for the view-syncer service. This is the URL to pass to the server parameter of the Zero constructor on the client. If unsuccessful, you can get detailed logs with npx sst deploy --verbose. Come find us on Discord and we'll help get you sorted out. Guide: Single-Node on Fly.io Let's deploy the Quickstart app to Fly.io. We'll use Fly.io for both the database and zero-cache. Setup Quickstart Go through the Quickstart guide to get the app running locally. Setup Fly.io Create an account on Fly.io and install the Fly CLI. Create Postgres app INITIALS=aa PG_APP_NAME=$INITIALS-zstart-pg PG_PASSWORD=\"$(head -c 256 /dev/urandom | od -An -t x1 | tr -d ' \\n' | tr -dc 'a-zA-Z' | head -c 16)\" fly postgres create \\ --name $PG_APP_NAME \\ --region lax \\ --initial-cluster-size 1 \\ --vm-size shared-cpu-2x \\ --volume-size 40 \\ --password=$PG_PASSWORD Seed Upstream database Populate the database with initial data and set its wal\\_level to logical to support replication to zero-cache. Then restart the database to apply the changes. (cat ./docker/seed.sql; echo \"\\q\") | fly pg connect -a $PG_APP_NAME echo \"ALTER SYSTEM SET wal_level = logical; \\q\" | fly pg connect -a $PG_APP_NAME fly postgres restart --app $PG_APP_NAME Create zero-cache Fly.io app CACHE_APP_NAME=$INITIALS-zstart-cache fly app create $CACHE_APP_NAME Publish zero-cache Create a fly.toml file. CONNECTION_STRING=\"postgres://postgres:$PG_PASSWORD@$PG_APP_NAME.flycast:5432\" ZERO_VERSION=$(npm list @rocicorp/zero | grep @rocicorp/zero | cut -f 3 -d @) cat < fly.toml app = \"$CACHE_APP_NAME\" primary_region = 'lax' [build] image = \"registry.hub.docker.com/rocicorp/zero:${ZERO_VERSION}\" [http_service] internal_port = 4848 force_https = true auto_stop_machines = 'off' min_machines_running = 1 [[http_service.checks]] grace_period = \"10s\" interval = \"30s\" method = \"GET\" timeout = \"5s\" path = \"/\" [[vm]] memory = '2gb' cpu_kind = 'shared' cpus = 2 [mounts] source = \"sqlite_db\" destination = \"/data\" [env] ZERO_REPLICA_FILE = \"/data/sync-replica.db\" ZERO_UPSTREAM_DB=\"${CONNECTION_STRING}/zstart?sslmode=disable\" ZERO_CVR_DB=\"${CONNECTION_STRING}/zstart_cvr?sslmode=disable\" ZERO_CHANGE_DB=\"${CONNECTION_STRING}/zstart_cdb?sslmode=disable\" ZERO_PUSH_URL=\"\" ZERO_AUTH_SECRET=\"secretkey\" LOG_LEVEL = \"debug\" EOF Then publish zero-cache: fly deploy Deploy Permissions Now zero-cache is running on Fly.io, but there are no permissions. If you run the app against this zero-cache, you'll see that no data is returned from any query. To fix this, deploy your permissions: npx zero-deploy-permissions --schema-path='./src/schema.ts' --output-file='/tmp/permissions.sql' (cat /tmp/permissions.sql; echo \"\\q\") | fly pg connect -a $PG_APP_NAME -d zstart You will need to redo this step every time you change your app's permissions, likely as part of your CI/CD pipeline. Use Remote zero-cache VITE_PUBLIC_SERVER=\"https://${CACHE_APP_NAME}.fly.dev/\" npm run dev:ui Now restart the frontend to pick up the env change, and refresh the app. You can stop your local database and zero-cache as we're not using them anymore. Open the web inspector to verify the app is talking to the remote zero-cache! You can deploy the frontend to any standard hosting service like Vercel or Netlify, or even to Fly.io! Deploy Frontend to Vercel If you've followed the above guide and deployed zero-cache to fly, you can simply run: vercel deploy --prod \\ -e ZERO_AUTH_SECRET=\"secretkey\" \\ -e VITE_PUBLIC_SERVER='https://${CACHE_APP_NAME}.fly.dev/' to deploy your frontend to Vercel. Explaining the arguments above -- ZERO\\_AUTH\\_SECRET - The secret to create and verify JWTs. This is the same secret that was used when deploying zero-cache to fly. VITE\\_PUBLIC\\_SERVER - The URL the frontend will call to talk to the zero-cache server. This is the URL of the fly app. Guide: Multi-Node on Raw AWS S3 Bucket Create an S3 bucket. zero-cache uses S3 to backup its SQLite replica so that it survives task restarts. Fargate Services Run zero-cache as two Fargate services (using the same rocicorp/zero docker image): replication-manager zero-cache config: ZERO\\_LITESTREAM\\_BACKUP\\_URL=s3://{bucketName}/{generation} ZERO\\_NUM\\_SYNC\\_WORKERS=0 Task count: 1 view-syncer zero-cache config: ZERO\\_CHANGE\\_STREAMER\\_URI=http://{replication-manager} Task count: N You can also use dynamic scaling Notes Standard rolling restarts are fine for both services Set ZERO\\_CVR\\_MAX\\_CONNS and ZERO\\_UPSTREAM\\_MAX\\_CONNS appropriately so that the total connections from both running and updating view-syncers (e.g. DesiredCount \\* MaximumPercent) do not exceed your database’s max\\_connections. The {generation} component of the s3://{bucketName}/{generation} URL is an arbitrary path component that can be modified to reset the replica (e.g. a date, a number, etc.). Setting this to a new path is the multi-node equivalent of deleting the replica file to resync. Note: zero-cache does not manage cleanup of old generations. The replication-manager serves requests on port 4849. Routing from the view-syncer to the http://{replication-manager} can be achieved using the following mechanisms (in order of preference): An internal load balancer Service Connect Service Discovery Fargate ephemeral storage is used for the replica. The default size is 20GB. This can be increased up to 200GB Allocate at least twice the size of the database to support the internal VACUUM operation. Guide: $PLATFORM Where should we deploy Zero next?? Let us know on Discord!", "headings": [] }, { "id": "12-errors", "title": "Error Handling", "url": "/docs/errors", - "content": "Errors from mutators and queries are thrown in response to method calls where possible, but many Zero errors occur asynchronously, during sync. You can catch these errors with the onError constructor parameter: ```ts const z = new Zero({ upstream: 'https://my-upstream-db.com', onError: (msg, ...rest) => { reportToSentry('Zero error:', msg, ...rest); }, }); ``` You can use this to send errors to Sentry, show custom UI, etc. The first parameter to onError is a descriptive message. Additional parameters provide more detail, for example an Error object (with a stack), or a JSON object.", + "content": "Errors from mutators and queries are thrown in response to method calls where possible, but many Zero errors occur asynchronously, during sync. You can catch these errors with the onError constructor parameter: const z = new Zero({ upstream: 'https://my-upstream-db.com', onError: (msg, ...rest) => { reportToSentry('Zero error:', msg, ...rest); }, }); You can use this to send errors to Sentry, show custom UI, etc. The first parameter to onError is a descriptive message. Additional parameters provide more detail, for example an Error object (with a stack), or a JSON object.", "headings": [] }, { @@ -108,7 +108,7 @@ "id": "15-offline", "title": "Offline", "url": "/docs/offline", - "content": "Zero currently supports offline reads, but not writes. We plan to support offline writes in the future, but we don't have a timeline for that yet. The lack of offline writes is often surprising to people familiar with sync engines, because offline is usually touted as something that comes for free with these tools. This page explains why Zero doesn't currently support offline writes, how we recommend you handle connectivity loss, and our future plans in this area. Offline Writes are a UX Problem While Zero can technically queue offline writes and replay them when reconnected (this happens by default in any sync engine, and is what Zero does today), that fact doesn't make supporting offline writes much easier. That's because a really hard part of offline writes is in handling conflicts, and no software tool can make that problem go away. For example, imagine two users are editing an article about cats. One goes offline and does a bunch of work on the article, while the other decides that the article should actually be about dogs and rewrites it. When the offline user reconnects, there is no way that any software algorithm can automatically resolve their conflict. One or the other of them is going to be upset. And while the above example may sound extreme, you can construct similar situations with the majority of common applications. Just take your own application and ask yourself what should really happen if one user takes their device offline for a week and makes arbitrarily complex changes while other users are working online. People who work on sync engines and related tools often say that offline is just extreme lag, but that's only true at a technical level. At a human level, being \"offline\" for a few seconds is very different from being offline for a few hours. The difference is how much knowledge you have about what your collaborators are doing, and how much of your work can be lost. The only way to support offline writes in general is to either: Make the logical datamodel append-only (i.e., users can create and mark tasks done, but cannot edit or delete them). Support custom UX to allow users to fork and merge conflicts when they occur. Only support editing from a single device. None of these is free. Buiding a good offline UX is a lot of work, and most of that work is borne by application developers. … And a Schema Problem But it's not just users that can diverge from each other. The server software and database schema can also diverge arbitrarily far from the client while the client is disconnected. When the client comes back online, the changes made may no longer be processable by the application, or may have a different effect than the user intended. So to support long offline periods, the server must also maintain backward compatibility with clients indefinitely. Similarly, the server can never reject an offline write (i.e., due to validation) because that could lead to a user losing huge amounts of work. … And a Sync Engine Problem Supporting offline writes also requires work in the sync engine. In Zero, there are a few specific impacts: The Zero client itself can get out of date while offline. On reconnect, the app might reload with a new version of the client. This new version must be able to read and process old data from arbitrarily long ago. An arbitrarily large number of pending mutations can be built up. These mutations must be replayed on reconnect, which can take a long time. When processing mutations on server we must consider what should happen if the database or application server are temporarily unavailable. We need to treat that kind of error differently from a validation error. These problems are surmountable, but significant effort. Their solutions might also be in tension with other goals of the sync engine, like online performance and scalability. These tradeoffs will take time to work through. Zero's Position For all of the above reasons, we plan to disable offline writes in Zero for beta. When the Zero client loses connection to zero-cache for several minutes (or when zero-cache cannot reach the customer API server), it will enter a special offline mode. In this mode, all writes to Zero will throw. While we recognize that offline writes would be useful for some applications, the reality is that for most of the apps we want to support, the user is online the vast majority of the time and the cost to support offline is extremely high. There is simply more value in making the online experience great first. We would like to revisit this in the future and really think through how to design APIs and patterns that allow developers to make successful offline-enabled apps. But it's not our priority right now. Dealing with Offline Today Until Zero disables offline writes automatically, use useZeroOnline to detect connection loss and manually disable writes in your UI: ```tsx const {online} = useZeroOnline(); return ; ``` ... or use the underlying zero.onOnline event: ```tsx const unsubscribe = zero.onOnline(online => { console.log('Online:', online); }); ``` Even More Information Lies I was Told About Collaborative Editing: a detailed overview of the challenges around offline writes in any collaborative editing system. This Zero Discord thread covers some challenges specifically in the context of Zero. Patchwork by Ink & Switch is new and interesting research around how to support offline writes well in collaborative systems.", + "content": "Zero currently supports offline reads, but not writes. We plan to support offline writes in the future, but we don't have a timeline for that yet. The lack of offline writes is often surprising to people familiar with sync engines, because offline is usually touted as something that comes for free with these tools. This page explains why Zero doesn't currently support offline writes, how we recommend you handle connectivity loss, and our future plans in this area. Offline Writes are a UX Problem While Zero can technically queue offline writes and replay them when reconnected (this happens by default in any sync engine, and is what Zero does today), that fact doesn't make supporting offline writes much easier. That's because a really hard part of offline writes is in handling conflicts, and no software tool can make that problem go away. For example, imagine two users are editing an article about cats. One goes offline and does a bunch of work on the article, while the other decides that the article should actually be about dogs and rewrites it. When the offline user reconnects, there is no way that any software algorithm can automatically resolve their conflict. One or the other of them is going to be upset. And while the above example may sound extreme, you can construct similar situations with the majority of common applications. Just take your own application and ask yourself what should really happen if one user takes their device offline for a week and makes arbitrarily complex changes while other users are working online. People who work on sync engines and related tools often say that offline is just extreme lag, but that's only true at a technical level. At a human level, being \"offline\" for a few seconds is very different from being offline for a few hours. The difference is how much knowledge you have about what your collaborators are doing, and how much of your work can be lost. The only way to support offline writes in general is to either: Make the logical datamodel append-only (i.e., users can create and mark tasks done, but cannot edit or delete them). Support custom UX to allow users to fork and merge conflicts when they occur. Only support editing from a single device. None of these is free. Buiding a good offline UX is a lot of work, and most of that work is borne by application developers. … And a Schema Problem But it's not just users that can diverge from each other. The server software and database schema can also diverge arbitrarily far from the client while the client is disconnected. When the client comes back online, the changes made may no longer be processable by the application, or may have a different effect than the user intended. So to support long offline periods, the server must also maintain backward compatibility with clients indefinitely. Similarly, the server can never reject an offline write (i.e., due to validation) because that could lead to a user losing huge amounts of work. … And a Sync Engine Problem Supporting offline writes also requires work in the sync engine. In Zero, there are a few specific impacts: The Zero client itself can get out of date while offline. On reconnect, the app might reload with a new version of the client. This new version must be able to read and process old data from arbitrarily long ago. An arbitrarily large number of pending mutations can be built up. These mutations must be replayed on reconnect, which can take a long time. When processing mutations on server we must consider what should happen if the database or application server are temporarily unavailable. We need to treat that kind of error differently from a validation error. These problems are surmountable, but significant effort. Their solutions might also be in tension with other goals of the sync engine, like online performance and scalability. These tradeoffs will take time to work through. Zero's Position For all of the above reasons, we plan to disable offline writes in Zero for beta. When the Zero client loses connection to zero-cache for several minutes (or when zero-cache cannot reach the customer API server), it will enter a special offline mode. In this mode, all writes to Zero will throw. While we recognize that offline writes would be useful for some applications, the reality is that for most of the apps we want to support, the user is online the vast majority of the time and the cost to support offline is extremely high. There is simply more value in making the online experience great first. We would like to revisit this in the future and really think through how to design APIs and patterns that allow developers to make successful offline-enabled apps. But it's not our priority right now. Dealing with Offline Today Until Zero disables offline writes automatically, use useZeroOnline to detect connection loss and manually disable writes in your UI: const {online} = useZeroOnline(); return ; ... or use the underlying zero.onOnline event: const unsubscribe = zero.onOnline(online => { console.log('Online:', online); }); Even More Information Lies I was Told About Collaborative Editing: a detailed overview of the challenges around offline writes in any collaborative editing system. This Zero Discord thread covers some challenges specifically in the context of Zero. Patchwork by Ink & Switch is new and interesting research around how to support offline writes well in collaborative systems.", "headings": [] }, { @@ -122,35 +122,35 @@ "id": "17-permissions", "title": "Permissions", "url": "/docs/permissions", - "content": "Permissions are expressed using ZQL and run automatically with every read and write. Permissions are currently row based. Zero will eventually also have column permissions. Define Permissions Permissions are defined in schema.ts using the definePermissions function. Here's an example of limiting reads to members of an organization and deletes to only the creator of an issue: ```ts // The decoded value of your JWT. type AuthData = { // The logged-in user. sub: string; }; export const permissions = definePermissions(schema, () => { // Checks if the user exists in a related organization const allowIfInOrganization = ( authData: AuthData, eb: ExpressionBuilder, ) => eb.exists('organization', q => q.whereExists('user', q => q.where('id', authData.sub)), ); // Checks if the user is the creator const allowIfIssueCreator = ( authData: AuthData, {cmp}: ExpressionBuilder, ) => cmp('creatorID', authData.sub); return { issue: { row: { select: [allowIfInOrganization], delete: [allowIfIssueCreator], }, }, } satisfies PermissionsConfig; }); ``` definePermission returns a policy object for each table in the schema. Each policy defines a ruleset for the operations that are possible on a table: select, insert, update, and delete. Access is Denied by Default If you don't specify any rules for an operation, it is denied by default. This is an important safety feature that helps ensure data isn't accidentally exposed. To enable full access to an action (i.e., during development) use the ANYONE\\_CAN helper: ```ts import {ANYONE_CAN} from '@rocicorp/zero'; const permissions = definePermissions(schema, () => { return { issue: { row: { select: ANYONE_CAN, // Other operations are denied by default. }, }, // Other tables are denied by default. } satisfies PermissionsConfig; }); ``` To do this for all actions, use ANYONE\\_CAN\\_DO\\_ANYTHING: ```ts import {ANYONE_CAN_DO_ANYTHING} from '@rocicorp/zero'; const permissions = definePermissions(schema, () => { return { // All operations on issue are allowed to all users. issue: ANYONE_CAN_DO_ANYTHING, // Other tables are denied by default. } satisfies PermissionsConfig; }); ``` Permission Evaluation Zero permissions are \"compiled\" into a JSON-based format at build-time. This file is stored in the {ZERO\\_APP\\_ID}.permissions table of your upstream database. Like other tables, it replicates live down to zero-cache. zero-cache then parses this file, and applies the encoded rules to every read and write operation. The end result is that you can't really use most features of JS in these rules. Specifically you cannot: Iterate over properties or array elements in the auth token Use any JS features beyond property access of AuthData Use any conditional or global state Basically only property access is allowed. This is really confusing and we're working on a better solution. Permission Deployment During development, permissions are compiled and uploaded to your database completely automatically as part of the zero-cache-dev script. For production, you need to call npx zero-deploy-permissions within your app to update the permissions in the production database whenever they change. You would typically do this as part of your normal schema migration or CI process. For example, the SST deployment script for zbugs looks like this: ```ts new command.local.Command( 'zero-deploy-permissions', { create: `npx zero-deploy-permissions -p ../../src/schema.ts`, // Run the Command on every deploy ... triggers: [Date.now()], environment: { ZERO_UPSTREAM_DB: commonEnv.ZERO_UPSTREAM_DB, // If the application has a non-default App ID ... ZERO_APP_ID: commonEnv.ZERO_APP_ID, }, }, // after the view-syncer is deployed. {dependsOn: viewSyncer}, ); ``` See the SST Deployment Guide for more details. Rules Each operation on a policy has a ruleset containing zero or more rules. A rule is just a TypeScript function that receives the logged in user's AuthData and generates a ZQL where expression. At least one rule in a ruleset must return a row for the operation to be allowed. Select Permissions You can limit the data a user can read by specifying a select ruleset. Select permissions act like filters. If a user does not have permission to read a row, it will be filtered out of the result set. It will not generate an error. For example, imagine a select permission that restricts reads to only issues created by the user: ```ts definePermissions(schema, () => { const allowIfIssueCreator = ( authData: AuthData, {cmp}: ExpressionBuilder, ) => cmp('creatorID', authData.sub); return { issue: { row: { select: [allowIfIssueCreator], }, }, } satisfies PermissionsConfig; }); ``` If the issue table has two rows, one created by the user and one by someone else, the user will only see the row they created in any queries. Note that although the same limitation applies to declarative insert/update permissions, custom mutators support arbitrary server-side logic and so can easily control which columns are writable. Insert Permissions You can limit what rows can be inserted and by whom by specifying an insert ruleset. Insert rules are evaluated after the entity is inserted. So if they query the database, they will see the inserted row present. If any rule in the insert ruleset returns a row, the insert is allowed. Here's an example of an insert rule that disallows inserting users that have the role 'admin'. ```ts definePermissions(schema, () => { const allowIfNonAdmin = ( authData: AuthData, {cmp}: ExpressionBuilder, ) => cmp('role', '!=', 'admin'); return { user: { row: { insert: [allowIfNonAdmin], }, }, } satisfies PermissionsConfig; }); ``` Update Permissions There are two types of update rulesets: preMutation and postMutation. Both rulesets must pass for an update to be allowed. preMutation rules see the version of a row before the mutation is applied. This is useful for things like checking whether a user owns an entity before editing it. postMutation rules see the version of a row after the mutation is applied. This is useful for things like ensuring a user can only mark themselves as the creator of an entity and not other users. Like other rulesets, preMutation and postMutation default to NOBODY\\_CAN. This means that every table must define both these rulesets in order for any updates to be allowed. For example, the following ruleset allows an issue's owner to edit, but not re-assign the issue. The postMutation rule enforces that the current user still own the issue after edit. ```ts definePermissions(schema, () => { const allowIfIssueOwner = ( authData: AuthData, {cmp}: ExpressionBuilder, ) => cmp('ownerID', authData.sub); return { issue: { row: { update: { preMutation: [allowIfIssueOwner], postMutation: [allowIfIssueOwner], }, }, }, } satisfies PermissionsConfig; }); ``` This ruleset allows an issue's owner to edit and re-assign the issue: ```ts definePermissions(schema, () => { const allowIfIssueOwner = ( authData: AuthData, {cmp}: ExpressionBuilder, ) => cmp('ownerID', authData.sub); return { issue: { row: { update: { preMutation: [allowIfIssueOwner], postMutation: ANYONE_CAN, }, }, }, } satisfies PermissionsConfig; }); ``` And this allows anyone to edit an issue, but only if they also assign it to themselves. Useful for enforcing \"patches welcome\"? 🙃 ```ts definePermissions(schema, () => { const allowIfIssueOwner = ( authData: AuthData, {cmp}: ExpressionBuilder, ) => cmp('ownerID', authData.sub); return { issue: { row: { update: { preMutation: ANYONE_CAN, postMutation: [allowIfIssueOwner], }, }, }, } satisfies PermissionsConfig; }); ``` Delete Permissions Delete permissions work in the same way as insert permissions except they run before the delete is applied. So if a delete rule queries the database, it will see that the deleted row is present. If any rule in the ruleset returns a row, the delete is allowed. Permissions Based on Auth Data You can use the cmpLit helper to define permissions based on a field of the authData parameter: ```ts definePermissions(schema, () => { const allowIfAdmin = ( authData: AuthData, {cmpLit}: ExpressionBuilder, ) => cmpLit(authData.role, 'admin'); return { issue: { row: { select: [allowIfAdmin], }, }, } satisfies PermissionsConfig; }); ``` Debugging See Debugging Permissions. Examples See hello-zero for a simple example of write auth and zbugs for a much more involved one.", + "content": "Permissions are expressed using ZQL and run automatically with every read and write. Permissions are currently row based. Zero will eventually also have column permissions. Define Permissions Permissions are defined in schema.ts using the definePermissions function. Here's an example of limiting reads to members of an organization and deletes to only the creator of an issue: // The decoded value of your JWT. type AuthData = { // The logged-in user. sub: string; }; export const permissions = definePermissions(schema, () => { // Checks if the user exists in a related organization const allowIfInOrganization = ( authData: AuthData, eb: ExpressionBuilder, ) => eb.exists('organization', q => q.whereExists('user', q => q.where('id', authData.sub)), ); // Checks if the user is the creator const allowIfIssueCreator = ( authData: AuthData, {cmp}: ExpressionBuilder, ) => cmp('creatorID', authData.sub); return { issue: { row: { select: [allowIfInOrganization], delete: [allowIfIssueCreator], }, }, } satisfies PermissionsConfig; }); definePermission returns a policy object for each table in the schema. Each policy defines a ruleset for the operations that are possible on a table: select, insert, update, and delete. Access is Denied by Default If you don't specify any rules for an operation, it is denied by default. This is an important safety feature that helps ensure data isn't accidentally exposed. To enable full access to an action (i.e., during development) use the ANYONE\\_CAN helper: import {ANYONE_CAN} from '@rocicorp/zero'; const permissions = definePermissions(schema, () => { return { issue: { row: { select: ANYONE_CAN, // Other operations are denied by default. }, }, // Other tables are denied by default. } satisfies PermissionsConfig; }); To do this for all actions, use ANYONE\\_CAN\\_DO\\_ANYTHING: import {ANYONE_CAN_DO_ANYTHING} from '@rocicorp/zero'; const permissions = definePermissions(schema, () => { return { // All operations on issue are allowed to all users. issue: ANYONE_CAN_DO_ANYTHING, // Other tables are denied by default. } satisfies PermissionsConfig; }); Permission Evaluation Zero permissions are \"compiled\" into a JSON-based format at build-time. This file is stored in the {ZERO\\_APP\\_ID}.permissions table of your upstream database. Like other tables, it replicates live down to zero-cache. zero-cache then parses this file, and applies the encoded rules to every read and write operation. The end result is that you can't really use most features of JS in these rules. Specifically you cannot: Iterate over properties or array elements in the auth token Use any JS features beyond property access of AuthData Use any conditional or global state Basically only property access is allowed. This is really confusing and we're working on a better solution. Permission Deployment During development, permissions are compiled and uploaded to your database completely automatically as part of the zero-cache-dev script. For production, you need to call npx zero-deploy-permissions within your app to update the permissions in the production database whenever they change. You would typically do this as part of your normal schema migration or CI process. For example, the SST deployment script for zbugs looks like this: new command.local.Command( 'zero-deploy-permissions', { create: `npx zero-deploy-permissions -p ../../src/schema.ts`, // Run the Command on every deploy ... triggers: [Date.now()], environment: { ZERO_UPSTREAM_DB: commonEnv.ZERO_UPSTREAM_DB, // If the application has a non-default App ID ... ZERO_APP_ID: commonEnv.ZERO_APP_ID, }, }, // after the view-syncer is deployed. {dependsOn: viewSyncer}, ); See the SST Deployment Guide for more details. Rules Each operation on a policy has a ruleset containing zero or more rules. A rule is just a TypeScript function that receives the logged in user's AuthData and generates a ZQL where expression. At least one rule in a ruleset must return a row for the operation to be allowed. Select Permissions You can limit the data a user can read by specifying a select ruleset. Select permissions act like filters. If a user does not have permission to read a row, it will be filtered out of the result set. It will not generate an error. For example, imagine a select permission that restricts reads to only issues created by the user: definePermissions(schema, () => { const allowIfIssueCreator = ( authData: AuthData, {cmp}: ExpressionBuilder, ) => cmp('creatorID', authData.sub); return { issue: { row: { select: [allowIfIssueCreator], }, }, } satisfies PermissionsConfig; }); If the issue table has two rows, one created by the user and one by someone else, the user will only see the row they created in any queries. Note that although the same limitation applies to declarative insert/update permissions, custom mutators support arbitrary server-side logic and so can easily control which columns are writable. Insert Permissions You can limit what rows can be inserted and by whom by specifying an insert ruleset. Insert rules are evaluated after the entity is inserted. So if they query the database, they will see the inserted row present. If any rule in the insert ruleset returns a row, the insert is allowed. Here's an example of an insert rule that disallows inserting users that have the role 'admin'. definePermissions(schema, () => { const allowIfNonAdmin = ( authData: AuthData, {cmp}: ExpressionBuilder, ) => cmp('role', '!=', 'admin'); return { user: { row: { insert: [allowIfNonAdmin], }, }, } satisfies PermissionsConfig; }); Update Permissions There are two types of update rulesets: preMutation and postMutation. Both rulesets must pass for an update to be allowed. preMutation rules see the version of a row before the mutation is applied. This is useful for things like checking whether a user owns an entity before editing it. postMutation rules see the version of a row after the mutation is applied. This is useful for things like ensuring a user can only mark themselves as the creator of an entity and not other users. Like other rulesets, preMutation and postMutation default to NOBODY\\_CAN. This means that every table must define both these rulesets in order for any updates to be allowed. For example, the following ruleset allows an issue's owner to edit, but not re-assign the issue. The postMutation rule enforces that the current user still own the issue after edit. definePermissions(schema, () => { const allowIfIssueOwner = ( authData: AuthData, {cmp}: ExpressionBuilder, ) => cmp('ownerID', authData.sub); return { issue: { row: { update: { preMutation: [allowIfIssueOwner], postMutation: [allowIfIssueOwner], }, }, }, } satisfies PermissionsConfig; }); This ruleset allows an issue's owner to edit and re-assign the issue: definePermissions(schema, () => { const allowIfIssueOwner = ( authData: AuthData, {cmp}: ExpressionBuilder, ) => cmp('ownerID', authData.sub); return { issue: { row: { update: { preMutation: [allowIfIssueOwner], postMutation: ANYONE_CAN, }, }, }, } satisfies PermissionsConfig; }); And this allows anyone to edit an issue, but only if they also assign it to themselves. Useful for enforcing \"patches welcome\"? 🙃 definePermissions(schema, () => { const allowIfIssueOwner = ( authData: AuthData, {cmp}: ExpressionBuilder, ) => cmp('ownerID', authData.sub); return { issue: { row: { update: { preMutation: ANYONE_CAN, postMutation: [allowIfIssueOwner], }, }, }, } satisfies PermissionsConfig; }); Delete Permissions Delete permissions work in the same way as insert permissions except they run before the delete is applied. So if a delete rule queries the database, it will see that the deleted row is present. If any rule in the ruleset returns a row, the delete is allowed. Permissions Based on Auth Data You can use the cmpLit helper to define permissions based on a field of the authData parameter: definePermissions(schema, () => { const allowIfAdmin = ( authData: AuthData, {cmpLit}: ExpressionBuilder, ) => cmpLit(authData.role, 'admin'); return { issue: { row: { select: [allowIfAdmin], }, }, } satisfies PermissionsConfig; }); Debugging See Debugging Permissions. Examples See hello-zero for a simple example of write auth and zbugs for a much more involved one.", "headings": [] }, { "id": "18-postgres-support", "title": "Supported Postgres Features", "url": "/docs/postgres-support", - "content": "Postgres has a massive feature set, and Zero supports a growing subset of it. Object Names Table and column names must begin with a letter or underscore This can be followed by letters, numbers, underscores, and hyphens Regex: /^\\[A-Za-z\\_]+\\[A-Za-z0-9\\_-]\\*$/ The column name \\_0\\_version is reserved for internal use Object Types Tables are synced Views are not synced identity generated columns are synced All other generated columns are not synced Indexes aren't synced per-se, but we do implicitly add indexes to the replica that match the upstream indexes. In the future, this will be customizable. Column Types Zero will sync arrays to the client, but there is no support for filtering or joining on array elements yet in ZQL. Other Postgres column types aren’t supported. They will be ignored when replicating (the synced data will be missing that column) and you will get a warning when zero-cache starts up. If your schema has a pg type not listed here, you can support it in Zero by using a trigger to map it to some type that Zero can support. For example if you have a GIS polygon type in the column my\\_poly polygon, you can use a trigger to map it to a my\\_poly\\_json json column. You could either use another trigger to map in the reverse direction to support changes for writes, or you could use a custom mutator to write to the polygon type directly on the server. Let us know if the lack of a particular column type is hindering your use of Zero. It can likely be added. Column Defaults Default values are allowed in the Postgres schema, but there currently is no way to use them from a Zero app. An insert() mutation requires all columns to be specified, except when columns are nullable (in which case, they default to null). Since there is no way to leave non-nullable columns off the insert on the client, there is no way for PG to apply the default. This is a known issue and will be fixed in the future. IDs It is strongly recommended to use client-generated random strings like uuid, ulid, nanoid, etc for primary keys. This makes optimistic creation and updates much easier. You could sync the highest value seen for that table, but there are race conditions and it is possible for that ID to be taken by the time the creation makes it to the server. Your database can resolve this and assign the next ID, but now the relationships you created optimistically will be against the wrong row. Blech. GUIDs makes a lot more sense in synced applications. If your table has a natural key you can use that and it has less problems. But there is still the chance for a conflict. Imagine you are modeling orgs and you choose domainName as the natural key. It is possible for a race to happen and when the creation gets to the server, somebody has already chosen that domain name. In that case, the best thing to do is reject the write and show the user an error. If you want to have a short auto-incrementing numeric ID for UX reasons (i.e., a bug number), that is possible - see this video. Primary Keys Each table synced with Zero must have either a primary key or at least one unique index. This is needed so that Zero can identify rows during sync, to distinguish between an edit and a remove/add. Multi-column primary and foreign keys are supported. Limiting Replication You can use Permissions to limit tables and rows from replicating to Zero. In the near future, you'll also be able to use Permissions to limit individual columns. Until then, a workaround is to use the Postgres publication feature to control the tables and columns that are replicated into zero-cache. In your pg schema setup, create a Postgres publication with the tables and columns you want: ```sql CREATE PUBLICATION zero_data FOR TABLE users (col1, col2, col3, ...), issues, comments; ``` Then, specify this publication in the App Publications zero-cache option. (By default, Zero creates a publication that publishes the entire public schema.) To limit what is synced from the zero-cache replica to actual clients (e.g., web browsers) you can use read permissions. Schema changes Most Postgres schema changes are supported as is. Two cases require special handling: Adding columns Adding a column with a non-constant DEFAULT value is not supported. This includes any expression with parentheses, as well as the special functions CURRENT\\_TIME, CURRENT\\_DATE, and CURRENT\\_TIMESTAMP (due to a constraint of SQLite). However, the DEFAULT value of an existing column can be changed to any value, including non-constant expressions. To achieve the desired column default: Add the column with no DEFAULT value Backfill the column with desired values Set the column's DEFAULT value ```sql BEGIN; ALTER TABLE foo ADD bar ...; -- without a DEFAULT value UPDATE foo SET bar = ...; ALTER TABLE foo ALTER bar SET DEFAULT ...; COMMIT; ``` Changing publications Postgres allows you to change published tables/columns with an ALTER PUBLICATION statement. Zero automatically adjusts the table schemas on the replica, but it does not receive the pre-existing data. To stream the pre-existing data to Zero, make an innocuous UPDATE after adding the tables/columns to the publication: ```sql BEGIN; ALTER PUBLICATION zero_data ADD TABLE foo; ALTER TABLE foo REPLICA IDENTITY FULL; UPDATE foo SET id = id; -- For some column \"id\" in \"foo\" ALTER TABLE foo REPLICA IDENTITY DEFAULT; COMMIT; ``` Self-Referential Relationships See zero-schema", + "content": "Postgres has a massive feature set, and Zero supports a growing subset of it. Object Names Table and column names must begin with a letter or underscore This can be followed by letters, numbers, underscores, and hyphens Regex: /^\\[A-Za-z\\_]+\\[A-Za-z0-9\\_-]\\*$/ The column name \\_0\\_version is reserved for internal use Object Types Tables are synced Views are not synced identity generated columns are synced All other generated columns are not synced Indexes aren't synced per-se, but we do implicitly add indexes to the replica that match the upstream indexes. In the future, this will be customizable. Column Types Zero will sync arrays to the client, but there is no support for filtering or joining on array elements yet in ZQL. Other Postgres column types aren’t supported. They will be ignored when replicating (the synced data will be missing that column) and you will get a warning when zero-cache starts up. If your schema has a pg type not listed here, you can support it in Zero by using a trigger to map it to some type that Zero can support. For example if you have a GIS polygon type in the column my\\_poly polygon, you can use a trigger to map it to a my\\_poly\\_json json column. You could either use another trigger to map in the reverse direction to support changes for writes, or you could use a custom mutator to write to the polygon type directly on the server. Let us know if the lack of a particular column type is hindering your use of Zero. It can likely be added. Column Defaults Default values are allowed in the Postgres schema, but there currently is no way to use them from a Zero app. An insert() mutation requires all columns to be specified, except when columns are nullable (in which case, they default to null). Since there is no way to leave non-nullable columns off the insert on the client, there is no way for PG to apply the default. This is a known issue and will be fixed in the future. IDs It is strongly recommended to use client-generated random strings like uuid, ulid, nanoid, etc for primary keys. This makes optimistic creation and updates much easier. You could sync the highest value seen for that table, but there are race conditions and it is possible for that ID to be taken by the time the creation makes it to the server. Your database can resolve this and assign the next ID, but now the relationships you created optimistically will be against the wrong row. Blech. GUIDs makes a lot more sense in synced applications. If your table has a natural key you can use that and it has less problems. But there is still the chance for a conflict. Imagine you are modeling orgs and you choose domainName as the natural key. It is possible for a race to happen and when the creation gets to the server, somebody has already chosen that domain name. In that case, the best thing to do is reject the write and show the user an error. If you want to have a short auto-incrementing numeric ID for UX reasons (i.e., a bug number), that is possible - see this video. Primary Keys Each table synced with Zero must have either a primary key or at least one unique index. This is needed so that Zero can identify rows during sync, to distinguish between an edit and a remove/add. Multi-column primary and foreign keys are supported. Limiting Replication You can use Permissions to limit tables and rows from replicating to Zero. In the near future, you'll also be able to use Permissions to limit individual columns. Until then, a workaround is to use the Postgres publication feature to control the tables and columns that are replicated into zero-cache. In your pg schema setup, create a Postgres publication with the tables and columns you want: CREATE PUBLICATION zero_data FOR TABLE users (col1, col2, col3, ...), issues, comments; Then, specify this publication in the App Publications zero-cache option. (By default, Zero creates a publication that publishes the entire public schema.) To limit what is synced from the zero-cache replica to actual clients (e.g., web browsers) you can use read permissions. Schema changes Most Postgres schema changes are supported as is. Two cases require special handling: Adding columns Adding a column with a non-constant DEFAULT value is not supported. This includes any expression with parentheses, as well as the special functions CURRENT\\_TIME, CURRENT\\_DATE, and CURRENT\\_TIMESTAMP (due to a constraint of SQLite). However, the DEFAULT value of an existing column can be changed to any value, including non-constant expressions. To achieve the desired column default: Add the column with no DEFAULT value Backfill the column with desired values Set the column's DEFAULT value BEGIN; ALTER TABLE foo ADD bar ...; -- without a DEFAULT value UPDATE foo SET bar = ...; ALTER TABLE foo ALTER bar SET DEFAULT ...; COMMIT; Changing publications Postgres allows you to change published tables/columns with an ALTER PUBLICATION statement. Zero automatically adjusts the table schemas on the replica, but it does not receive the pre-existing data. To stream the pre-existing data to Zero, make an innocuous UPDATE after adding the tables/columns to the publication: BEGIN; ALTER PUBLICATION zero_data ADD TABLE foo; ALTER TABLE foo REPLICA IDENTITY FULL; UPDATE foo SET id = id; -- For some column \"id\" in \"foo\" ALTER TABLE foo REPLICA IDENTITY DEFAULT; COMMIT; Self-Referential Relationships See zero-schema", "headings": [] }, { "id": "19-quickstart", "title": "Quickstart", "url": "/docs/quickstart", - "content": "Prerequisites Docker Node 20+ Run In one terminal, install and start the database: ```bash git clone https://github.com/rocicorp/hello-zero.git cd hello-zero npm install npm run dev:db-up ``` In a second terminal, start zero-cache: ```bash cd hello-zero npm run dev:zero-cache ``` In a final terminal, start the UI: ```bash cd hello-zero npm run dev:ui ``` Quick Overview hello-zero is a demo app that allows querying over a small dataset of fake messages between early Zero users. Here are some things to try: Press the Add Messages button to add messages to the UI. Any logged-in or anonymous users are allowed to add messages. Press the Remove Messages button to remove messages. Only logged-in users are allowed to remove messages. You can hold shift to bypass the UI warning and see that write access control is being enforced server-side – the UI flickers as the optimistic write happens instantly and is then reverted by the server. Press login to login as a random user, then the remove button will work. Open two different browsers and see how fast sync propagates changes. Add a filter using the From and Contains controls. Notice that filters are fully dynamic and synced. Edit a message by pressing the pencil icon. You can only edit messages from the user you’re logged in as. As before you can attempt to bypass by holding shift. Check out the SQL schema for this database in seed.sql. Login to the database with psql postgresql://user:password@127.0.0.1:5430/postgres (or any other pg viewer) and delete or alter a row. Observe that it deletes from UI automatically. Detailed Walkthrough Deployment You can deploy Zero apps to most cloud providers that support Docker and Postgres. See Deployment for more information.", + "content": "Prerequisites Docker Node 20+ Run In one terminal, install and start the database: git clone https://github.com/rocicorp/hello-zero.git cd hello-zero npm install npm run dev:db-up In a second terminal, start zero-cache: cd hello-zero npm run dev:zero-cache In a final terminal, start the UI: cd hello-zero npm run dev:ui Quick Overview hello-zero is a demo app that allows querying over a small dataset of fake messages between early Zero users. Here are some things to try: Press the Add Messages button to add messages to the UI. Any logged-in or anonymous users are allowed to add messages. Press the Remove Messages button to remove messages. Only logged-in users are allowed to remove messages. You can hold shift to bypass the UI warning and see that write access control is being enforced server-side – the UI flickers as the optimistic write happens instantly and is then reverted by the server. Press login to login as a random user, then the remove button will work. Open two different browsers and see how fast sync propagates changes. Add a filter using the From and Contains controls. Notice that filters are fully dynamic and synced. Edit a message by pressing the pencil icon. You can only edit messages from the user you’re logged in as. As before you can attempt to bypass by holding shift. Check out the SQL schema for this database in seed.sql. Login to the database with psql postgresql://user:password@127.0.0.1:5430/postgres (or any other pg viewer) and delete or alter a row. Observe that it deletes from UI automatically. Detailed Walkthrough Deployment You can deploy Zero apps to most cloud providers that support Docker and Postgres. See Deployment for more information.", "headings": [] }, { "id": "20-react", "title": "React", "url": "/docs/react", - "content": "Zero has built-in support for React. Here’s what basic usage looks like: ```tsx import {useQuery, useZero} from '@rocicorp/zero/react'; import {type Schema} from './schema.ts'; import {type Mutators} from './mutators.ts'; function IssueList() { const z = useZero(); let issueQuery = z.query.issue .related('creator') .related('labels') .limit(100); const userID = selectedUserID(); if (userID) { issueQuery = issueQuery.where('creatorID', '=', userID); } const [issues, issuesDetail] = useQuery(issueQuery); return ( <>
{issuesDetail.type === 'complete' ? 'Complete' : 'Partial'} results
{issues.map(issue => ( ))}
); } ``` ZeroProvider The useZero hook must be used within a ZeroProvider component. The ZeroProvider component is responsible for creating and destroying Zero instances reactively. ```tsx import {SessionProvider} from 'my-auth-provider'; import {ZeroProvider} from '@rocicorp/zero/react'; import {type Schema, schema} from './schema.ts'; import {type Mutators, createMutators} from './mutators.ts'; export function Root() { const session = useSession(); const {userID, authToken: auth} = session; const server = import.meta.env.VITE_PUBLIC_SERVER; const mutators = useMemo(() => { return createMutators(auth); }, [auth]); return ( // ZeroProvider will reactively create and destroy Zero instances // as needed when props change. ); } ``` You can also pass a Zero instance to the ZeroProvider if you want to control the lifecycle of the Zero instance yourself: ```tsx // ZeroProvider just sets up the context, it doesn't manage // the lifecycle of the Zero instance. ``` Complete quickstart here: https://github.com/rocicorp/hello-zero", + "content": "Zero has built-in support for React. Here’s what basic usage looks like: import {useQuery, useZero} from '@rocicorp/zero/react'; import {type Schema} from './schema.ts'; import {type Mutators} from './mutators.ts'; function IssueList() { const z = useZero(); let issueQuery = z.query.issue .related('creator') .related('labels') .limit(100); const userID = selectedUserID(); if (userID) { issueQuery = issueQuery.where('creatorID', '=', userID); } const [issues, issuesDetail] = useQuery(issueQuery); return ( <>
{issuesDetail.type === 'complete' ? 'Complete' : 'Partial'} results
{issues.map(issue => ( ))}
); } ZeroProvider The useZero hook must be used within a ZeroProvider component. The ZeroProvider component is responsible for creating and destroying Zero instances reactively. import {SessionProvider} from 'my-auth-provider'; import {ZeroProvider} from '@rocicorp/zero/react'; import {type Schema, schema} from './schema.ts'; import {type Mutators, createMutators} from './mutators.ts'; export function Root() { const session = useSession(); const {userID, authToken: auth} = session; const server = import.meta.env.VITE_PUBLIC_SERVER; const mutators = useMemo(() => { return createMutators(auth); }, [auth]); return ( // ZeroProvider will reactively create and destroy Zero instances // as needed when props change. ); } You can also pass a Zero instance to the ZeroProvider if you want to control the lifecycle of the Zero instance yourself: // ZeroProvider just sets up the context, it doesn't manage // the lifecycle of the Zero instance. Complete quickstart here: https://github.com/rocicorp/hello-zero", "headings": [] }, { "id": "21-reading-data", "title": "Reading Data with ZQL", "url": "/docs/reading-data", - "content": "ZQL is Zero’s query language. Inspired by SQL, ZQL is expressed in TypeScript with heavy use of the builder pattern. If you have used Drizzle or Kysely, ZQL will feel familiar. ZQL queries are composed of one or more clauses that are chained together into a query. Unlike queries in classic databases, the result of a ZQL query is a view that updates automatically and efficiently as the underlying data changes. You can call a query’s materialize() method to get a view, but more typically you run queries via some framework-specific bindings. For example see useQuery for React or SolidJS. ZQL caches values and returns them multiple times. If you modify a value returned from ZQL, you will modify it everywhere it is used. This can lead to subtle bugs. JavaScript and TypeScript lack true immutable types so we use readonly to help enforce it. But it's easy to cast away the readonly accidentally. In the future, we'll freeze all returned data in dev mode to help prevent this. Select ZQL queries start by selecting a table. There is no way to select a subset of columns; ZQL queries always return the entire row (modulo column permissions). ```tsx const z = new Zero(...); // Returns a query that selects all rows and columns from the issue table. z.query.issue; ``` This is a design tradeoff that allows Zero to better reuse the row locally for future queries. This also makes it easier to share types between different parts of the code. Ordering You can sort query results by adding an orderBy clause: ```tsx z.query.issue.orderBy('created', 'desc'); ``` Multiple orderBy clauses can be present, in which case the data is sorted by those clauses in order: ```tsx // Order by priority descending. For any rows with same priority, // then order by created desc. z.query.issue.orderBy('priority', 'desc').orderBy('created', 'desc'); ``` All queries in ZQL have a default final order of their primary key. Assuming the issue table has a primary key on the id column, then: ```tsx // Actually means: z.query.issue.orderBy('id', 'asc'); z.query.issue; // Actually means: z.query.issue.orderBy('priority', 'desc').orderBy('id', 'asc'); z.query.issue.orderBy('priority', 'desc'); ``` Limit You can limit the number of rows to return with limit(): ```tsx z.query.issue.orderBy('created', 'desc').limit(100); ``` Paging You can start the results at or after a particular row with start(): ```tsx let start: IssueRow | undefined; while (true) { let q = z.query.issue.orderBy('created', 'desc').limit(100); if (start) { q = q.start(start); } const batch = await q.run(); console.log('got batch', batch); if (batch.length < 100) { break; } start = batch[batch.length - 1]; } ``` By default start() is exclusive - it returns rows starting after the supplied reference row. This is what you usually want for paging. If you want inclusive results, you can do: ```tsx z.query.issue.start(row, {inclusive: true}); ``` Getting a Single Result If you want exactly zero or one results, use the one() clause. This causes ZQL to return Row|undefined rather than Row\\[]. ```tsx const result = await z.query.issue.where('id', 42).one().run(); if (!result) { console.error('not found'); } ``` one() overrides any limit() clause that is also present. Relationships You can query related rows using relationships that are defined in your Zero schema. ```tsx // Get all issues and their related comments z.query.issue.related('comments'); ``` Relationships are returned as hierarchical data. In the above example, each row will have a comments field which is itself an array of the corresponding comments row. You can fetch multiple relationships in a single query: ```tsx z.query.issue.related('comments').related('reactions').related('assignees'); ``` Refining Relationships By default all matching relationship rows are returned, but this can be refined. The related method accepts an optional second function which is itself a query. ```tsx z.query.issue.related( 'comments', // It is common to use the 'q' shorthand variable for this parameter, // but it is a _comment_ query in particular here, exactly as if you // had done z.query.comment. q => q.orderBy('modified', 'desc').limit(100).start(lastSeenComment), ); ``` This relationship query can have all the same clauses that top-level queries can have. You can sometimes work around this by making the junction relationship explicit, depending on your schema and usage. Nested Relationships You can nest relationships arbitrarily: ```tsx // Get all issues, first 100 comments for each (ordered by modified,desc), // and for each comment all of its reactions. z.query.issue.related('comments', q => q.orderBy('modified', 'desc').limit(100).related('reactions'), ); ``` Where You can filter a query with where(): ```tsx z.query.issue.where('priority', '=', 'high'); ``` The first parameter is always a column name from the table being queried. Intellisense will offer available options (sourced from your Zero Schema). Comparison Operators Where supports the following comparison operators: | Operator | Allowed Operand Types | Description | | ---------------------------------------- | ----------------------------- | ------------------------------------------------------------------------ | | = , != | boolean, number, string | JS strict equal (===) semantics | | < , <=, >, >= | number | JS number compare semantics | | LIKE, NOT LIKE, ILIKE, NOT ILIKE | string | SQL-compatible LIKE / ILIKE | | IN , NOT IN | boolean, number, string | RHS must be array. Returns true if rhs contains lhs by JS strict equals. | | IS , IS NOT | boolean, number, string, null | Same as = but also works for null | TypeScript will restrict you from using operators with types that don’t make sense – you can’t use > with boolean for example. Equals is the Default Comparison Operator Because comparing by = is so common, you can leave it out and where defaults to =. ```tsx z.query.issue.where('priority', 'high'); ``` Comparing to null As in SQL, ZQL’s null is not equal to itself (null ≠ null). This is required to make join semantics work: if you’re joining employee.orgID on org.id you do not want an employee in no organization to match an org that hasn’t yet been assigned an ID. When you purposely want to compare to null ZQL supports IS and IS NOT operators that work just like in SQL: ```tsx // Find employees not in any org. z.query.employee.where('orgID', 'IS', null); ``` TypeScript will prevent you from comparing to null with other operators. Compound Filters The argument to where can also be a callback that returns a complex expression: ```tsx // Get all issues that have priority 'critical' or else have both // priority 'medium' and not more than 100 votes. z.query.issue.where(({cmp, and, or, not}) => or( cmp('priority', 'critical'), and(cmp('priority', 'medium'), not(cmp('numVotes', '>', 100))), ), ); ``` cmp is short for compare and works the same as where at the top-level except that it can’t be chained and it only accepts comparison operators (no relationship filters – see below). Note that chaining where() is also a one-level and: ```tsx // Find issues with priority 3 or higher, owned by aa z.query.issue.where('priority', '>=', 3).where('owner', 'aa'); ``` Comparing Literal Values The where clause always expects its first parameter to be a column name as a string. Same with the cmp helper: ```ts // \"foo\" is a column name, not a string: z.query.issue.where('foo', 'bar'); // \"foo\" is a column name, not a string: z.query.issue.where(({cmp}) => cmp('foo', 'bar')); ``` To compareto a literal value, use the cmpLit helper: ```ts z.query.issue.where(cmpLit('foobar', 'foo' + 'bar')); ``` By itself this is not very useful, but the first parameter can also be a JavaScript variable: ```ts z.query.issue.where(cmpLit(role, 'admin')); ``` Or, within a permission rule, you can compare to a field of the authData parameter: ```ts z.query.issue.where(cmpLit(authData.role, 'admin')); ``` Relationship Filters Your filter can also test properties of relationships. Currently the only supported test is existence: ```tsx // Find all orgs that have at least one employee z.query.organization.whereExists('employees'); ``` The argument to whereExists is a relationship, so just like other relationships it can be refined with a query: ```tsx // Find all orgs that have at least one cool employee z.query.organization.whereExists('employees', q => q.where('location', 'Hawaii'), ); ``` As with querying relationships, relationship filters can be arbitrarily nested: ```tsx // Get all issues that have comments that have reactions z.query.issue.whereExists('comments', q => q.whereExists('reactions')); ); ``` The exists helper is also provided which can be used with and, or, cmp, and not to build compound filters that check relationship existence: ```tsx // Find issues that have at least one comment or are high priority z.query.issue.where({cmp, or, exists} => or( cmp('priority', 'high'), exists('comments'), ), ); ``` Completeness Zero returns whatever data it has on the client immediately for a query, then falls back to the server for any missing data. Sometimes it's useful to know the difference between these two types of results. To do so, use the result from useQuery: ```tsx const [issues, issuesResult] = useQuery(z.query.issue); if (issuesResult.type === 'complete') { console.log('All data is present'); } else { console.log('Some data is missing'); } ``` The possible values of result.type are currently complete and unknown. The complete value is currently only returned when Zero has received the server result. But in the future, Zero will be able to return this result type when it knows that all possible data for this query is already available locally. Additionally, we plan to add a prefix result for when the data is known to be a prefix of the complete result. See Consistency for more information. Handling Missing Data It is inevitable that there will be cases where the requested data cannot be found. Because Zero returns local results immediately, and server results asynchronously, displaying \"not found\" / 404 UI can be slightly tricky. If you just use a simple existence check, you will often see the 404 UI flicker while the server result loads: ```tsx const [issue, issuesResult] = useQuery( z.query.issue.where('id', 'some-id').one(), ); // ❌ This causes flickering of the UI if (!issue) { return
404 Not Found
; } else { return
{issue}
; } ``` The way to do this correctly is to only display the \"not found\" UI when the result type is complete. This way the 404 page is slow but pages with data are still just as fast. ```tsx const [issue, issuesResult] = useQuery( z.query.issue.where('id', 'some-id').one(), ); if (!issue && issueResult.type === 'complete') { return
404 Not Found
; } if (!issue) { return null; } return
{issue}
; ``` Listening to Changes Currently, the way to listen for changes in query results is not ideal. You can add a listener to a materialized view which has the new data and result as parameters: ```ts z.query.issue.materialize().addListener((issues, issuesResult) => { // do stuff... }); ``` However, using this method will maintain its own materialized view in memory which is wasteful. It also doesn't allow for granular listening to events like add and remove of rows. A better way would be to create your own view without actually storing the data which will also allow you to listen to specific events. Again, the API is not good and will be improved in the future. ```ts // Inside the View class // Instead of storing the change, we invoke some callback push(change: Change): void { switch (change.type) { case 'add': this.#onAdd?.(change) break case 'remove': this.#onRemove?.(change) break case 'edit': this.#onEdit?.(change) break case 'child': this.#onChild?.(change) break default: throw new Error(`Unknown change type: ${change['type']}`) } } ``` (see View implementations in zero-vue or zero-solid) Preloading Almost all Zero apps will want to preload some data in order to maximize the feel of instantaneous UI transitions. In Zero, preloading is done via queries – the same queries you use in the UI and for auth. However, because preload queries are usually much larger than a screenful of UI, Zero provides a special preload() helper to avoid the overhead of materializing the result into JS objects: ```tsx // Preload the first 1k issues + their creator, assignee, labels, and // the view state for the active user. // // There's no need to render this data, so we don't use `useQuery()`: // this avoids the overhead of pulling all this data into JS objects. z.query.issue .related('creator') .related('assignee') .related('labels') .related('viewState', q => q.where('userID', z.userID).one()) .orderBy('created', 'desc') .limit(1000) .preload(); ``` Data Lifetime and Reuse Zero reuses data synced from prior queries to answer new queries when possible. This is what enables instant UI transitions. But what controls the lifetime of this client-side data? How can you know whether any particular query will return instant results? How can you know whether those results will be up to date or stale? The answer is that the data on the client is simply the union of rows returned from queries which are currently syncing. Once a row is no longer returned by any syncing query, it is removed from the client. Thus, there is never any stale data in Zero. So when you are thinking about whether a query is going to return results instantly, you should think about what other queries are syncing, not about what data is local. Data exists locally if and only if there is a query syncing that returns that data. A cache has a random set of rows with a random set of versions. There is no expectation that the cache any particular rows, or that the rows' have matching versions. Rows are simply updated as they are fetched. A replica by contrast is eagerly updated, whether or not any client has requested a row. A replica is always very close to up-to-date, and always self-consistent. Zero is a partial replica because it only replicates rows that are returned by syncing queries. Query Lifecycle Queries can be either active or cached. An active query is one that is currently being used by the application. Cached queries are not currently in use, but continue syncing in case they are needed again soon. Active queries are created one of four ways: The app calls q.materialize() to get a View. The app uses a framework binding like React's useQuery(q). The app calls preload() to sync larger queries without a view. The app calls q.run() to get a single result. Active queries sync until they are deactivated. The way this happens depends on how the query was created: For materialize() queries, the UI calls destroy() on the view. For useQuery(), the UI unmounts the component (which calls destroy() under the covers). For preload(), the UI calls cleanup() on the return value of preload(). For run(), queries are automatically deactivated immediately after the result is returned. Additionally when a Zero instance closes, all active queries are automatically deactivated. This also happens when the containing page or script is unloaded. TTLs Each query has a ttl that controls how long it stays cached. You do not need to account for such time when choosing a TTL – you only need to account for time your app is running without a query. TTL Defaults In most cases, the default TTL should work well: preload() queries default to ttl:'none', meaning they are not cached at all, and will stop syncing immediately when deactivated. But because preload() queries are typically registered at app startup and never shutdown, and because the ttl clock only ticks while Zero is running, this means that preload queries never get unregistered. Other queries have a default ttl of 5m (five minutes). Setting Different TTLs You can override the default TTL with the ttl parameter: ```ts // With useQuery(): const [user] = useQuery( z.query.user.where('id', userId), {ttl: '5m'}); // With preload(): z.query.user.where('id', userId).preload( {ttl: '5m'}); // With run(): const user = await z.query.user.where('id', userId).run( {ttl: '5m'}); // With materialize(): const view = z.query.user.where('id', userId).materialize( {ttl: '5m'}); ``` TTLs up to 10m (ten minutes) are currently supported. The following formats are allowed: | Format | Meaning | | --------- | --------------------------------------------------------- | | none | No caching. Query will immediately stop when deactivated. | | %ds | Number of seconds. | | %dm | Number of minutes. | Choosing a TTL If you choose a different TTL, you should consider how likely it is that the query will be reused, and how far into the future this reuse will occur. Here are some guidelines to help you choose a TTL for common query types: Preload Queries These queries load the most commonly needed data for your app. They are typically larger, run with the preload() method, and stay running the entire time your app is running. Because these queries run the entire time Zero runs, they do not need any TTL to keep them alive. And using a ttl for them is wasteful since when your app changes its preload query, it will end up running the old preload query and the new preload query, even though the app only cares about the new one. Recommendation: ttl: 'none' (the default for preload()). Navigational Queries These queries load data specific to a route. They are typically smaller and run with the useQuery() method. It is useful to cache them for a short time, so that they can be reactivated quickly if the user navigates back to the route. Recommendation: ttl: '5m' (the default for useQuery()). Ephemeral Queries These queries load data for a specific, short-lived user interaction and often come in large numbers (e.g., typeahead search). The chance of any specific ephemeral query being reused is low, so the benefit of caching them is also low. Recommendation: useQuery(..., {ttl: 'none'}))\\*. Why Zero TTLs are Short Zero queries are not free. Just as in any database, queries consume resources on both the client and server. Memory is used to keep metadata about the query, and disk storage is used to keep the query's current state. We do drop this state after we haven't heard from a client for awhile, but this is only a partial improvement. If the client returns, we have to re-run the query to get the latest data. This means that we do not actually want to keep queries active unless there is a good chance they will be needed again soon. The default Zero TTL values might initially seem too short, but they are designed to work well with the way Zero's TTL clock works and strike a good balance between keeping queries alive long enough to be useful, while not keeping them alive so long that they consume resources unnecessarily. If you think you need longer TTLs, please let us know. We are still iterating on these APIs and may have missed something. Alternately we may be able to help you achieve your goal a different way. Running Queries Once Usually subscribing to a query is what you want in a reactive UI, but every so often you'll need to run a query just once. To do this, use the run() method: ```tsx const results = await z.query.issue.where('foo', 'bar').run(); ``` By default, run() only returns results that are currently available on the client. That is, it returns the data that would be given for result.type === 'unknown'. If you want to wait for the server to return results, pass {type: 'complete'} to run: ```tsx const results = await z.query.issue.where('foo', 'bar').run({type: 'complete'});await z.query.issue.where('foo', 'bar'); ``` This is the same as saying run() or run({type: 'unknown'}). Consistency Zero always syncs a consistent partial replica of the backend database to the client. This avoids many common consistency issues that come up in classic web applications. But there are still some consistency issues to be aware of when using Zero. For example, imagine that you have a bug database w/ 10k issues. You preload the first 1k issues sorted by created. The user then does a query of issues assigned to themselves, sorted by created. Among the 1k issues that were preloaded imagine 100 are found that match the query. Since the data we preloaded is in the same order as this query, we are guaranteed that any local results found will be a prefix of the server results. The UX that result is nice: the user will see initial results to the query instantly. If more results are found server-side, those results are guaranteed to sort below the local results. There's no shuffling of results when the server response comes in. Now imagine that the user switches the sort to ‘sort by modified’. This new query will run locally, and will again find some local matches. But it is now unlikely that the local results found are a prefix of the server results. When the server result comes in, the user will probably see the results shuffle around. To avoid this annoying effect, what you should do in this example is also preload the first 1k issues sorted by modified desc. In general for any query shape you intend to do, you should preload the first n results for that query shape with no filters, in each sort you intend to use. In the future, we will be implementing a consistency model that fixes these issues automatically. We will prevent Zero from returning local data when that data is not known to be a prefix of the server result. Once the consistency model is implemented, preloading can be thought of as purely a performance thing, and not required to avoid unsightly flickering.", + "content": "ZQL is Zero’s query language. Inspired by SQL, ZQL is expressed in TypeScript with heavy use of the builder pattern. If you have used Drizzle or Kysely, ZQL will feel familiar. ZQL queries are composed of one or more clauses that are chained together into a query. Unlike queries in classic databases, the result of a ZQL query is a view that updates automatically and efficiently as the underlying data changes. You can call a query’s materialize() method to get a view, but more typically you run queries via some framework-specific bindings. For example see useQuery for React or SolidJS. ZQL caches values and returns them multiple times. If you modify a value returned from ZQL, you will modify it everywhere it is used. This can lead to subtle bugs. JavaScript and TypeScript lack true immutable types so we use readonly to help enforce it. But it's easy to cast away the readonly accidentally. In the future, we'll freeze all returned data in dev mode to help prevent this. Select ZQL queries start by selecting a table. There is no way to select a subset of columns; ZQL queries always return the entire row (modulo column permissions). const z = new Zero(...); // Returns a query that selects all rows and columns from the issue table. z.query.issue; This is a design tradeoff that allows Zero to better reuse the row locally for future queries. This also makes it easier to share types between different parts of the code. Ordering You can sort query results by adding an orderBy clause: z.query.issue.orderBy('created', 'desc'); Multiple orderBy clauses can be present, in which case the data is sorted by those clauses in order: // Order by priority descending. For any rows with same priority, // then order by created desc. z.query.issue.orderBy('priority', 'desc').orderBy('created', 'desc'); All queries in ZQL have a default final order of their primary key. Assuming the issue table has a primary key on the id column, then: // Actually means: z.query.issue.orderBy('id', 'asc'); z.query.issue; // Actually means: z.query.issue.orderBy('priority', 'desc').orderBy('id', 'asc'); z.query.issue.orderBy('priority', 'desc'); Limit You can limit the number of rows to return with limit(): z.query.issue.orderBy('created', 'desc').limit(100); Paging You can start the results at or after a particular row with start(): let start: IssueRow | undefined; while (true) { let q = z.query.issue.orderBy('created', 'desc').limit(100); if (start) { q = q.start(start); } const batch = await q.run(); console.log('got batch', batch); if (batch.length < 100) { break; } start = batch[batch.length - 1]; } By default start() is exclusive - it returns rows starting after the supplied reference row. This is what you usually want for paging. If you want inclusive results, you can do: z.query.issue.start(row, {inclusive: true}); Getting a Single Result If you want exactly zero or one results, use the one() clause. This causes ZQL to return Row|undefined rather than Row\\[]. const result = await z.query.issue.where('id', 42).one().run(); if (!result) { console.error('not found'); } one() overrides any limit() clause that is also present. Relationships You can query related rows using relationships that are defined in your Zero schema. // Get all issues and their related comments z.query.issue.related('comments'); Relationships are returned as hierarchical data. In the above example, each row will have a comments field which is itself an array of the corresponding comments row. You can fetch multiple relationships in a single query: z.query.issue.related('comments').related('reactions').related('assignees'); Refining Relationships By default all matching relationship rows are returned, but this can be refined. The related method accepts an optional second function which is itself a query. z.query.issue.related( 'comments', // It is common to use the 'q' shorthand variable for this parameter, // but it is a _comment_ query in particular here, exactly as if you // had done z.query.comment. q => q.orderBy('modified', 'desc').limit(100).start(lastSeenComment), ); This relationship query can have all the same clauses that top-level queries can have. You can sometimes work around this by making the junction relationship explicit, depending on your schema and usage. Nested Relationships You can nest relationships arbitrarily: // Get all issues, first 100 comments for each (ordered by modified,desc), // and for each comment all of its reactions. z.query.issue.related('comments', q => q.orderBy('modified', 'desc').limit(100).related('reactions'), ); Where You can filter a query with where(): z.query.issue.where('priority', '=', 'high'); The first parameter is always a column name from the table being queried. Intellisense will offer available options (sourced from your Zero Schema). Comparison Operators Where supports the following comparison operators: | Operator | Allowed Operand Types | Description | | ---------------------------------------- | ----------------------------- | ------------------------------------------------------------------------ | | = , != | boolean, number, string | JS strict equal (===) semantics | | < , <=, >, >= | number | JS number compare semantics | | LIKE, NOT LIKE, ILIKE, NOT ILIKE | string | SQL-compatible LIKE / ILIKE | | IN , NOT IN | boolean, number, string | RHS must be array. Returns true if rhs contains lhs by JS strict equals. | | IS , IS NOT | boolean, number, string, null | Same as = but also works for null | TypeScript will restrict you from using operators with types that don’t make sense – you can’t use > with boolean for example. Equals is the Default Comparison Operator Because comparing by = is so common, you can leave it out and where defaults to =. z.query.issue.where('priority', 'high'); Comparing to null As in SQL, ZQL’s null is not equal to itself (null ≠ null). This is required to make join semantics work: if you’re joining employee.orgID on org.id you do not want an employee in no organization to match an org that hasn’t yet been assigned an ID. When you purposely want to compare to null ZQL supports IS and IS NOT operators that work just like in SQL: // Find employees not in any org. z.query.employee.where('orgID', 'IS', null); TypeScript will prevent you from comparing to null with other operators. Compound Filters The argument to where can also be a callback that returns a complex expression: // Get all issues that have priority 'critical' or else have both // priority 'medium' and not more than 100 votes. z.query.issue.where(({cmp, and, or, not}) => or( cmp('priority', 'critical'), and(cmp('priority', 'medium'), not(cmp('numVotes', '>', 100))), ), ); cmp is short for compare and works the same as where at the top-level except that it can’t be chained and it only accepts comparison operators (no relationship filters – see below). Note that chaining where() is also a one-level and: // Find issues with priority 3 or higher, owned by aa z.query.issue.where('priority', '>=', 3).where('owner', 'aa'); Comparing Literal Values The where clause always expects its first parameter to be a column name as a string. Same with the cmp helper: // \"foo\" is a column name, not a string: z.query.issue.where('foo', 'bar'); // \"foo\" is a column name, not a string: z.query.issue.where(({cmp}) => cmp('foo', 'bar')); To compareto a literal value, use the cmpLit helper: z.query.issue.where(cmpLit('foobar', 'foo' + 'bar')); By itself this is not very useful, but the first parameter can also be a JavaScript variable: z.query.issue.where(cmpLit(role, 'admin')); Or, within a permission rule, you can compare to a field of the authData parameter: z.query.issue.where(cmpLit(authData.role, 'admin')); Relationship Filters Your filter can also test properties of relationships. Currently the only supported test is existence: // Find all orgs that have at least one employee z.query.organization.whereExists('employees'); The argument to whereExists is a relationship, so just like other relationships it can be refined with a query: // Find all orgs that have at least one cool employee z.query.organization.whereExists('employees', q => q.where('location', 'Hawaii'), ); As with querying relationships, relationship filters can be arbitrarily nested: // Get all issues that have comments that have reactions z.query.issue.whereExists('comments', q => q.whereExists('reactions')); ); The exists helper is also provided which can be used with and, or, cmp, and not to build compound filters that check relationship existence: // Find issues that have at least one comment or are high priority z.query.issue.where({cmp, or, exists} => or( cmp('priority', 'high'), exists('comments'), ), ); Completeness Zero returns whatever data it has on the client immediately for a query, then falls back to the server for any missing data. Sometimes it's useful to know the difference between these two types of results. To do so, use the result from useQuery: const [issues, issuesResult] = useQuery(z.query.issue); if (issuesResult.type === 'complete') { console.log('All data is present'); } else { console.log('Some data is missing'); } The possible values of result.type are currently complete and unknown. The complete value is currently only returned when Zero has received the server result. But in the future, Zero will be able to return this result type when it knows that all possible data for this query is already available locally. Additionally, we plan to add a prefix result for when the data is known to be a prefix of the complete result. See Consistency for more information. Handling Missing Data It is inevitable that there will be cases where the requested data cannot be found. Because Zero returns local results immediately, and server results asynchronously, displaying \"not found\" / 404 UI can be slightly tricky. If you just use a simple existence check, you will often see the 404 UI flicker while the server result loads: const [issue, issuesResult] = useQuery( z.query.issue.where('id', 'some-id').one(), ); // ❌ This causes flickering of the UI if (!issue) { return
404 Not Found
; } else { return
{issue}
; } The way to do this correctly is to only display the \"not found\" UI when the result type is complete. This way the 404 page is slow but pages with data are still just as fast. const [issue, issuesResult] = useQuery( z.query.issue.where('id', 'some-id').one(), ); if (!issue && issueResult.type === 'complete') { return
404 Not Found
; } if (!issue) { return null; } return
{issue}
; Listening to Changes Currently, the way to listen for changes in query results is not ideal. You can add a listener to a materialized view which has the new data and result as parameters: z.query.issue.materialize().addListener((issues, issuesResult) => { // do stuff... }); However, using this method will maintain its own materialized view in memory which is wasteful. It also doesn't allow for granular listening to events like add and remove of rows. A better way would be to create your own view without actually storing the data which will also allow you to listen to specific events. Again, the API is not good and will be improved in the future. // Inside the View class // Instead of storing the change, we invoke some callback push(change: Change): void { switch (change.type) { case 'add': this.#onAdd?.(change) break case 'remove': this.#onRemove?.(change) break case 'edit': this.#onEdit?.(change) break case 'child': this.#onChild?.(change) break default: throw new Error(`Unknown change type: ${change['type']}`) } } (see View implementations in zero-vue or zero-solid) Preloading Almost all Zero apps will want to preload some data in order to maximize the feel of instantaneous UI transitions. In Zero, preloading is done via queries – the same queries you use in the UI and for auth. However, because preload queries are usually much larger than a screenful of UI, Zero provides a special preload() helper to avoid the overhead of materializing the result into JS objects: // Preload the first 1k issues + their creator, assignee, labels, and // the view state for the active user. // // There's no need to render this data, so we don't use `useQuery()`: // this avoids the overhead of pulling all this data into JS objects. z.query.issue .related('creator') .related('assignee') .related('labels') .related('viewState', q => q.where('userID', z.userID).one()) .orderBy('created', 'desc') .limit(1000) .preload(); Data Lifetime and Reuse Zero reuses data synced from prior queries to answer new queries when possible. This is what enables instant UI transitions. But what controls the lifetime of this client-side data? How can you know whether any particular query will return instant results? How can you know whether those results will be up to date or stale? The answer is that the data on the client is simply the union of rows returned from queries which are currently syncing. Once a row is no longer returned by any syncing query, it is removed from the client. Thus, there is never any stale data in Zero. So when you are thinking about whether a query is going to return results instantly, you should think about what other queries are syncing, not about what data is local. Data exists locally if and only if there is a query syncing that returns that data. A cache has a random set of rows with a random set of versions. There is no expectation that the cache any particular rows, or that the rows' have matching versions. Rows are simply updated as they are fetched. A replica by contrast is eagerly updated, whether or not any client has requested a row. A replica is always very close to up-to-date, and always self-consistent. Zero is a partial replica because it only replicates rows that are returned by syncing queries. Query Lifecycle Queries can be either active or cached. An active query is one that is currently being used by the application. Cached queries are not currently in use, but continue syncing in case they are needed again soon. Active queries are created one of four ways: The app calls q.materialize() to get a View. The app uses a framework binding like React's useQuery(q). The app calls preload() to sync larger queries without a view. The app calls q.run() to get a single result. Active queries sync until they are deactivated. The way this happens depends on how the query was created: For materialize() queries, the UI calls destroy() on the view. For useQuery(), the UI unmounts the component (which calls destroy() under the covers). For preload(), the UI calls cleanup() on the return value of preload(). For run(), queries are automatically deactivated immediately after the result is returned. Additionally when a Zero instance closes, all active queries are automatically deactivated. This also happens when the containing page or script is unloaded. TTLs Each query has a ttl that controls how long it stays cached. You do not need to account for such time when choosing a TTL – you only need to account for time your app is running without a query. TTL Defaults In most cases, the default TTL should work well: preload() queries default to ttl:'none', meaning they are not cached at all, and will stop syncing immediately when deactivated. But because preload() queries are typically registered at app startup and never shutdown, and because the ttl clock only ticks while Zero is running, this means that preload queries never get unregistered. Other queries have a default ttl of 5m (five minutes). Setting Different TTLs You can override the default TTL with the ttl parameter: // With useQuery(): const [user] = useQuery( z.query.user.where('id', userId), {ttl: '5m'}); // With preload(): z.query.user.where('id', userId).preload( {ttl: '5m'}); // With run(): const user = await z.query.user.where('id', userId).run( {ttl: '5m'}); // With materialize(): const view = z.query.user.where('id', userId).materialize( {ttl: '5m'}); TTLs up to 10m (ten minutes) are currently supported. The following formats are allowed: | Format | Meaning | | --------- | --------------------------------------------------------- | | none | No caching. Query will immediately stop when deactivated. | | %ds | Number of seconds. | | %dm | Number of minutes. | Choosing a TTL If you choose a different TTL, you should consider how likely it is that the query will be reused, and how far into the future this reuse will occur. Here are some guidelines to help you choose a TTL for common query types: Preload Queries These queries load the most commonly needed data for your app. They are typically larger, run with the preload() method, and stay running the entire time your app is running. Because these queries run the entire time Zero runs, they do not need any TTL to keep them alive. And using a ttl for them is wasteful since when your app changes its preload query, it will end up running the old preload query and the new preload query, even though the app only cares about the new one. Recommendation: ttl: 'none' (the default for preload()). Navigational Queries These queries load data specific to a route. They are typically smaller and run with the useQuery() method. It is useful to cache them for a short time, so that they can be reactivated quickly if the user navigates back to the route. Recommendation: ttl: '5m' (the default for useQuery()). Ephemeral Queries These queries load data for a specific, short-lived user interaction and often come in large numbers (e.g., typeahead search). The chance of any specific ephemeral query being reused is low, so the benefit of caching them is also low. Recommendation: useQuery(..., {ttl: 'none'}))\\*. Why Zero TTLs are Short Zero queries are not free. Just as in any database, queries consume resources on both the client and server. Memory is used to keep metadata about the query, and disk storage is used to keep the query's current state. We do drop this state after we haven't heard from a client for awhile, but this is only a partial improvement. If the client returns, we have to re-run the query to get the latest data. This means that we do not actually want to keep queries active unless there is a good chance they will be needed again soon. The default Zero TTL values might initially seem too short, but they are designed to work well with the way Zero's TTL clock works and strike a good balance between keeping queries alive long enough to be useful, while not keeping them alive so long that they consume resources unnecessarily. If you think you need longer TTLs, please let us know. We are still iterating on these APIs and may have missed something. Alternately we may be able to help you achieve your goal a different way. Running Queries Once Usually subscribing to a query is what you want in a reactive UI, but every so often you'll need to run a query just once. To do this, use the run() method: const results = await z.query.issue.where('foo', 'bar').run(); By default, run() only returns results that are currently available on the client. That is, it returns the data that would be given for result.type === 'unknown'. If you want to wait for the server to return results, pass {type: 'complete'} to run: const results = await z.query.issue.where('foo', 'bar').run({type: 'complete'});await z.query.issue.where('foo', 'bar'); This is the same as saying run() or run({type: 'unknown'}). Consistency Zero always syncs a consistent partial replica of the backend database to the client. This avoids many common consistency issues that come up in classic web applications. But there are still some consistency issues to be aware of when using Zero. For example, imagine that you have a bug database w/ 10k issues. You preload the first 1k issues sorted by created. The user then does a query of issues assigned to themselves, sorted by created. Among the 1k issues that were preloaded imagine 100 are found that match the query. Since the data we preloaded is in the same order as this query, we are guaranteed that any local results found will be a prefix of the server results. The UX that result is nice: the user will see initial results to the query instantly. If more results are found server-side, those results are guaranteed to sort below the local results. There's no shuffling of results when the server response comes in. Now imagine that the user switches the sort to ‘sort by modified’. This new query will run locally, and will again find some local matches. But it is now unlikely that the local results found are a prefix of the server results. When the server result comes in, the user will probably see the results shuffle around. To avoid this annoying effect, what you should do in this example is also preload the first 1k issues sorted by modified desc. In general for any query shape you intend to do, you should preload the first n results for that query shape with no filters, in each sort you intend to use. In the future, we will be implementing a consistency model that fixes these issues automatically. We will prevent Zero from returning local data when that data is not known to be a prefix of the server result. Once the consistency model is implemented, preloading can be thought of as purely a performance thing, and not required to avoid unsightly flickering.", "headings": [] }, { @@ -164,70 +164,70 @@ "id": "23-release-notes/0.10", "title": "Zero 0.10", "url": "/docs/release-notes/0.10", - "content": "Install ```bash npm install @rocicorp/zero@0.10 ``` Features None. Fixes Remove top-level await from zero-client. Various logging improvements. Don't throw error when WebSocket unavailable on server. Support building on Windows (running on Windows still doesn't work) Breaking Changes None.", + "content": "Install npm install @rocicorp/zero@0.10 Features None. Fixes Remove top-level await from zero-client. Various logging improvements. Don't throw error when WebSocket unavailable on server. Support building on Windows (running on Windows still doesn't work) Breaking Changes None.", "headings": [] }, { "id": "24-release-notes/0.11", "title": "Zero 0.11", "url": "/docs/release-notes/0.11", - "content": "Install ```bash npm install @rocicorp/zero@0.11 ``` Features Windows should work a lot better now. Thank you very much to aexylus and Sergio Leon for the testing and contributions here. Support nested property access in JWT auth tokens (docs). Make initial sync configurable (docs). Add query result type to SolidJS (docs) Docker image now contains native amd64 and arm64 binaries. Add storageKey constructor parameter to enable multiple Zero instances for same userID. Fixes Many, many fixes, including: Fix downstream replication of primitive values Fix replication of TRUNCATE messages Fix large storage use for idle pg instances Add runtime sanity checks for when a table is referenced but not synced Fix zero-cache-dev for multitenant Breaking Changes The addition of result types to SolidJS is a breaking API change on SolidJS only. See the changes to hello-zero-solid for upgrade example.", + "content": "Install npm install @rocicorp/zero@0.11 Features Windows should work a lot better now. Thank you very much to aexylus and Sergio Leon for the testing and contributions here. Support nested property access in JWT auth tokens (docs). Make initial sync configurable (docs). Add query result type to SolidJS (docs) Docker image now contains native amd64 and arm64 binaries. Add storageKey constructor parameter to enable multiple Zero instances for same userID. Fixes Many, many fixes, including: Fix downstream replication of primitive values Fix replication of TRUNCATE messages Fix large storage use for idle pg instances Add runtime sanity checks for when a table is referenced but not synced Fix zero-cache-dev for multitenant Breaking Changes The addition of result types to SolidJS is a breaking API change on SolidJS only. See the changes to hello-zero-solid for upgrade example.", "headings": [] }, { "id": "25-release-notes/0.12", "title": "Zero 0.12", "url": "/docs/release-notes/0.12", - "content": "Install ```bash npm install @rocicorp/zero@0.12 ``` Features Schemas now support circular relationships (docs). Added one() and many() schema helpers to default relationship type (docs). Support for syncing tables without a primary key as long as there is a unique index. This enables Prisma's implicit many-to-many relations (docs). Zero has been confirmed to work with Aurora and Google Cloud SQL (docs) Client bundle size reduced from 55kb to 47kb (-15%). Fixes Windows: zero-cache was spawning emptying terminals and leaving listeners connected on exit. Incorrect warning in zero-cache about enums not being supported. Failure to handle the primary key of Postgres tables changing. Incorrect results when whereExists() is before where() in query (bug). Error: The inferred type of '...' cannot be named without a reference to .... Error: insufficient upstream connections. Several causes of flicker in React. Incorrect values for ResultType when unloading and loading a query quickly (bug). Error: Postgres is missing the column '...' but that column was part of a row. Pointless initial empty render in React when data is already available in memory. Error: Expected string at ... Got array during auth. where() incorrectly allows comparing to null with the = operator (bug). SolidJS: Only call setState once per transaction. Breaking Changes The schema definition syntax has changed to support circular relationships. See the changes to hello-zero and hello-zero-solid for upgrade examples.", + "content": "Install npm install @rocicorp/zero@0.12 Features Schemas now support circular relationships (docs). Added one() and many() schema helpers to default relationship type (docs). Support for syncing tables without a primary key as long as there is a unique index. This enables Prisma's implicit many-to-many relations (docs). Zero has been confirmed to work with Aurora and Google Cloud SQL (docs) Client bundle size reduced from 55kb to 47kb (-15%). Fixes Windows: zero-cache was spawning emptying terminals and leaving listeners connected on exit. Incorrect warning in zero-cache about enums not being supported. Failure to handle the primary key of Postgres tables changing. Incorrect results when whereExists() is before where() in query (bug). Error: The inferred type of '...' cannot be named without a reference to .... Error: insufficient upstream connections. Several causes of flicker in React. Incorrect values for ResultType when unloading and loading a query quickly (bug). Error: Postgres is missing the column '...' but that column was part of a row. Pointless initial empty render in React when data is already available in memory. Error: Expected string at ... Got array during auth. where() incorrectly allows comparing to null with the = operator (bug). SolidJS: Only call setState once per transaction. Breaking Changes The schema definition syntax has changed to support circular relationships. See the changes to hello-zero and hello-zero-solid for upgrade examples.", "headings": [] }, { "id": "26-release-notes/0.13", "title": "Zero 0.13", "url": "/docs/release-notes/0.13", - "content": "Install ```bash npm install @rocicorp/zero@0.13 ``` Features Multinode deployment for horizontal scalability and zero-downtime deploys (docs). SST Deployment Guide (docs). Plain AWS Deployment Guide (docs). Various exports for external libraries Remove build hash from docker version for consistency with npm (discussion) Fixes Move heartbeat monitoring to separate path, not port Type instantiation is excessively deep and possibly infinite (bug). 20x improvement to whereExists performance (discussion) Breaking Changes Removing the hash from the version is a breaking change if you had scripts relying on that. Moving the heartbeat monitor to a path is a breaking change for deployments that were using that.", + "content": "Install npm install @rocicorp/zero@0.13 Features Multinode deployment for horizontal scalability and zero-downtime deploys (docs). SST Deployment Guide (docs). Plain AWS Deployment Guide (docs). Various exports for external libraries Remove build hash from docker version for consistency with npm (discussion) Fixes Move heartbeat monitoring to separate path, not port Type instantiation is excessively deep and possibly infinite (bug). 20x improvement to whereExists performance (discussion) Breaking Changes Removing the hash from the version is a breaking change if you had scripts relying on that. Moving the heartbeat monitor to a path is a breaking change for deployments that were using that.", "headings": [] }, { "id": "27-release-notes/0.14", "title": "Zero 0.14", "url": "/docs/release-notes/0.14", - "content": "Install ```bash npm install @rocicorp/zero@0.14 ``` Features Use from() to map column or tables to a different name (docs). Sync from muliple Postgres schemas (docs) Fixes useQuery not working when server unset (bug) Error: \"single output already exists\" in hello-zero-solid (bug) Row helper doesn't work with query having one() (bug) Partitioned Postgres tables not replicating Breaking Changes None.", + "content": "Install npm install @rocicorp/zero@0.14 Features Use from() to map column or tables to a different name (docs). Sync from muliple Postgres schemas (docs) Fixes useQuery not working when server unset (bug) Error: \"single output already exists\" in hello-zero-solid (bug) Row helper doesn't work with query having one() (bug) Partitioned Postgres tables not replicating Breaking Changes None.", "headings": [] }, { "id": "28-release-notes/0.15", "title": "Zero 0.15", "url": "/docs/release-notes/0.15", - "content": "Install ```bash npm install @rocicorp/zero@0.15 ``` Upgrade Guide This release changes the way that permissions are sent to the server. Before, permissions were sent to the server by setting the ZERO\\_SCHEMA\\_JSON or ZERO\\_SCHEMA\\_FILE environment variables, which include the permissions. In 0.15, these variables go away and are replaced by a new command: npx zero-deploy-permissions. This command writes the permissions to a new table in the upstream database. This design allows live permission updates, without restarting the server. It also solves problems with max env var size that users were seeing. This release also flips the default permission from allow to deny for all rules. To upgrade your app: See the changes to hello-zero or hello-zero-solid for how to update your permissions. Remove the ZERO\\_SCHEMA\\_JSON and ZERO\\_SCHEMA\\_FILE environment variables from your setup. They aren't used anymore. Use npx zero-deploy-permissions to deploy permissions when necessary. You can hook this up to your CI to automate it. See the zbugs implementation as an example. Features Live-updating permissions (docs). Permissions now default to deny rather than allow (docs). Fixes Multiple whereExists in same query not working (PR) Allow overlapped mutators (bug) \"Immutable type too deep\" error (PR) Log server version at startup (PR) Eliminate quadratic CVR writes (PR) Handle numeric in the replication stream (PR) Make the auto-reset required error more prominent (PR) Add \"type\":\"module\" recommendation when schema load fails (PR) Throw error if multiple auth options set (PR) Handle NULL characters in JSON columns (PR) Breaking Changes Making permissions deny by default breaks existing apps. To fix add ANYONE\\_CAN or other appropriate permissions for your tables. See docs. The ZERO\\_SCHEMA\\_JSON and ZERO\\_SCHEMA\\_FILE environment variables are no longer used. Remove them from your setup and use npx zero-deploy-permissions instead.", + "content": "Install npm install @rocicorp/zero@0.15 Upgrade Guide This release changes the way that permissions are sent to the server. Before, permissions were sent to the server by setting the ZERO\\_SCHEMA\\_JSON or ZERO\\_SCHEMA\\_FILE environment variables, which include the permissions. In 0.15, these variables go away and are replaced by a new command: npx zero-deploy-permissions. This command writes the permissions to a new table in the upstream database. This design allows live permission updates, without restarting the server. It also solves problems with max env var size that users were seeing. This release also flips the default permission from allow to deny for all rules. To upgrade your app: See the changes to hello-zero or hello-zero-solid for how to update your permissions. Remove the ZERO\\_SCHEMA\\_JSON and ZERO\\_SCHEMA\\_FILE environment variables from your setup. They aren't used anymore. Use npx zero-deploy-permissions to deploy permissions when necessary. You can hook this up to your CI to automate it. See the zbugs implementation as an example. Features Live-updating permissions (docs). Permissions now default to deny rather than allow (docs). Fixes Multiple whereExists in same query not working (PR) Allow overlapped mutators (bug) \"Immutable type too deep\" error (PR) Log server version at startup (PR) Eliminate quadratic CVR writes (PR) Handle numeric in the replication stream (PR) Make the auto-reset required error more prominent (PR) Add \"type\":\"module\" recommendation when schema load fails (PR) Throw error if multiple auth options set (PR) Handle NULL characters in JSON columns (PR) Breaking Changes Making permissions deny by default breaks existing apps. To fix add ANYONE\\_CAN or other appropriate permissions for your tables. See docs. The ZERO\\_SCHEMA\\_JSON and ZERO\\_SCHEMA\\_FILE environment variables are no longer used. Remove them from your setup and use npx zero-deploy-permissions instead.", "headings": [] }, { "id": "29-release-notes/0.16", "title": "Zero 0.16", "url": "/docs/release-notes/0.16", - "content": "Install ```bash npm install @rocicorp/zero@0.16 ``` Upgrading See the upgrade from hello-zero or hello-zero-solid for an example. Features Documented how to use lambdas to deploy permissions in SST, rather than needing CI/CD to have access to Postgres. (doc – search for \"permissionsDeployer\"). Added simple debugging logs for read and write permissions (doc). Fixes Improve performance of initial sync about 2x (PR 1, PR 2). IN should allow readonly array arguments (Report, PR). Export ANYONE\\_CAN\\_DO\\_ANYTHING (Report). Fix false-positive in schema change detection (Report, PR). Fix writes of numeric types (Report, PR) Fix bug where litestream was creating way too many files in s3 (PR) Fix memory leak in change-streamer noticeable under high write load (PR) Fix query already registered error (PR) Correctly handle optional booleans (PR) Ignore indexes with unpublished columns (PR) Breaking Changes None.", + "content": "Install npm install @rocicorp/zero@0.16 Upgrading See the upgrade from hello-zero or hello-zero-solid for an example. Features Documented how to use lambdas to deploy permissions in SST, rather than needing CI/CD to have access to Postgres. (doc – search for \"permissionsDeployer\"). Added simple debugging logs for read and write permissions (doc). Fixes Improve performance of initial sync about 2x (PR 1, PR 2). IN should allow readonly array arguments (Report, PR). Export ANYONE\\_CAN\\_DO\\_ANYTHING (Report). Fix false-positive in schema change detection (Report, PR). Fix writes of numeric types (Report, PR) Fix bug where litestream was creating way too many files in s3 (PR) Fix memory leak in change-streamer noticeable under high write load (PR) Fix query already registered error (PR) Correctly handle optional booleans (PR) Ignore indexes with unpublished columns (PR) Breaking Changes None.", "headings": [] }, { "id": "30-release-notes/0.17", "title": "Zero 0.17", "url": "/docs/release-notes/0.17", - "content": "Install ```bash npm install @rocicorp/zero@0.17 ``` Upgrading See the upgrade from hello-zero or hello-zero-solid for an example. Features Queries now take an optional ttl argument. This argument backgrounds queries for some time after the app stops using them. Background queries continue syncing so they are instantly ready if the UI re-requests them. The data from background queries is also available to be used by new queries where possible (doc). Structural schema versioning. This is TypeScript, why are we versioning with numbers like cave-people?? We got rid of schemaVersion concept entirely and now determine schema compatibility completely automatically, TS-stylie (doc). Permissions now scoped to \"apps\". You can now have different Zero \"apps\" talking to the same upstream database. Each app gets completely separate configuration and permissions. This should also enable previewing zero-cache (each preview would be its own app). Apps replace the existing \"shard\" concept (doc). Initial replication is over 5x faster, up to about 50MB/second or 15k row/second in our tests. Added warnings for slow hydration in both client and server (doc). auto-reset is now enabled by default for databases that don't support event triggers (doc). Default cvr and change databases to upstream, so that you don't have to specify them in the common case where they are the same as upstream. This docs site now has search! Fixes Certain kinds of many:many joins were causing node already exists assertions Certain kinds of or queries were causing consistency issues Support replica identity full for PostgreSQL tables We now print a stack trace during close at debug level to enable debugging errors where Zero is accessed after close. We now print a warning when IndexedDB is missing rather than throwing. This makes it a little easier to use Zero in SSR setups. We now reset zero-cache implicitly in a few edge cases rather than halting replication. Fixed a deadlock in change-streamer. Breaking Changes query.run() now returns its result via promise. This is required for compatibility with upcoming custom mutators, but also will allow us to wait for server results in the future (though that (still 😢) doesn't exist yet).", + "content": "Install npm install @rocicorp/zero@0.17 Upgrading See the upgrade from hello-zero or hello-zero-solid for an example. Features Queries now take an optional ttl argument. This argument backgrounds queries for some time after the app stops using them. Background queries continue syncing so they are instantly ready if the UI re-requests them. The data from background queries is also available to be used by new queries where possible (doc). Structural schema versioning. This is TypeScript, why are we versioning with numbers like cave-people?? We got rid of schemaVersion concept entirely and now determine schema compatibility completely automatically, TS-stylie (doc). Permissions now scoped to \"apps\". You can now have different Zero \"apps\" talking to the same upstream database. Each app gets completely separate configuration and permissions. This should also enable previewing zero-cache (each preview would be its own app). Apps replace the existing \"shard\" concept (doc). Initial replication is over 5x faster, up to about 50MB/second or 15k row/second in our tests. Added warnings for slow hydration in both client and server (doc). auto-reset is now enabled by default for databases that don't support event triggers (doc). Default cvr and change databases to upstream, so that you don't have to specify them in the common case where they are the same as upstream. This docs site now has search! Fixes Certain kinds of many:many joins were causing node already exists assertions Certain kinds of or queries were causing consistency issues Support replica identity full for PostgreSQL tables We now print a stack trace during close at debug level to enable debugging errors where Zero is accessed after close. We now print a warning when IndexedDB is missing rather than throwing. This makes it a little easier to use Zero in SSR setups. We now reset zero-cache implicitly in a few edge cases rather than halting replication. Fixed a deadlock in change-streamer. Breaking Changes query.run() now returns its result via promise. This is required for compatibility with upcoming custom mutators, but also will allow us to wait for server results in the future (though that (still 😢) doesn't exist yet).", "headings": [] }, { "id": "31-release-notes/0.18", "title": "Zero 0.18", "url": "/docs/release-notes/0.18", - "content": "Install ```bash npm install @rocicorp/zero@0.18 ``` Upgrading To try out custom mutators, see the changes to hello-zero-solid. Features Custom Mutators! Finally! Define arbitrary write operations in code (doc). Added inspector API for debugging sync, queries, and client storage (doc). Added analyze-query tool to debug query performance (doc). Added transform-query tool to debug permissions (doc). Added ast-to-zql script to prettify Zero's internal AST format (doc). Fixes Added backpressure to replication-manager to protect against Postgres moving faster than we can push to clients (PR). @rocicorp/zero/advanced has been deprecated. AdvancedQuery got folded into Query and ZeroAdvancedOptions got folded into ZeroOptions (PR). Support ALTER SCHEMA DDL changes (PR) Allow replication-manager to continue running while a new one re-replicates. (PR). Improve replication performance for some schema changes (PR). Make the log level of zero-deploy-permissions configurable (PR) Bind exists to the expression builder (PR) Fix single output already exists error (PR) Fix getBrowserGlobal('window')?.addEventListener not a function in Expo (thanks @andrewcoelho!) (PR). Fix Vue bindings ref counting bug. Bindings no longer need to pass RefCountMap (PR). Fix CVR ownership takeover race conditions (PR). Support REPLICA IDENTITY FULL in degraded-mode pg providers (PR). Handle corrupt sqlite db by re-replicating (PR). Don't send useless pokes to clients that are unchanged (PR). Add limit(1) to queries using a relation that is marked one() (PR). Export UseQueryOptions Breaking Changes None.", + "content": "Install npm install @rocicorp/zero@0.18 Upgrading To try out custom mutators, see the changes to hello-zero-solid. Features Custom Mutators! Finally! Define arbitrary write operations in code (doc). Added inspector API for debugging sync, queries, and client storage (doc). Added analyze-query tool to debug query performance (doc). Added transform-query tool to debug permissions (doc). Added ast-to-zql script to prettify Zero's internal AST format (doc). Fixes Added backpressure to replication-manager to protect against Postgres moving faster than we can push to clients (PR). @rocicorp/zero/advanced has been deprecated. AdvancedQuery got folded into Query and ZeroAdvancedOptions got folded into ZeroOptions (PR). Support ALTER SCHEMA DDL changes (PR) Allow replication-manager to continue running while a new one re-replicates. (PR). Improve replication performance for some schema changes (PR). Make the log level of zero-deploy-permissions configurable (PR) Bind exists to the expression builder (PR) Fix single output already exists error (PR) Fix getBrowserGlobal('window')?.addEventListener not a function in Expo (thanks @andrewcoelho!) (PR). Fix Vue bindings ref counting bug. Bindings no longer need to pass RefCountMap (PR). Fix CVR ownership takeover race conditions (PR). Support REPLICA IDENTITY FULL in degraded-mode pg providers (PR). Handle corrupt sqlite db by re-replicating (PR). Don't send useless pokes to clients that are unchanged (PR). Add limit(1) to queries using a relation that is marked one() (PR). Export UseQueryOptions Breaking Changes None.", "headings": [] }, { "id": "32-release-notes/0.19", "title": "Zero 0.19", "url": "/docs/release-notes/0.19", - "content": "Install ```bash npm install @rocicorp/zero@0.19 ``` Upgrading If you use custom mutators, please see hello-zero-solid for how to update your push endpoint. If you use SolidJS, please switch to createQuery. If you are awaiting z.mutate.foo.bar(), you should switch to await z.mutate.foo.bar().client to be consistent with .server. If you were using a 0.19 canary, the .server property returns error by rejection again (like 0.18 did). Sorry about the thrash here. Features Add a type param to query.run() so it can wait for server results (doc, bug) await z.mutate.foo.bar() is now await z.mutate.foo.bar().client for consistency with .server, old API still works but deprecated (doc) Improve speed of litestream restore by about 7x Increase replication speed when using JSON by about 25% Add options to analyze-query to apply permissions and auth data (doc). Add option to --lazy-startup to zero-cache to delay connecting to upstram until first connection (doc) Add /statz endpoint for getting some health statistics from a running Zero instance (doc) Fixes Support passing Request to PushProccesor.process() (PR) Fix layering in PushProcessor to better support custom db implementations (thanks Erik Munson!) (PR) Fix socket disconnects in GCP (PR) Quote Postgres enum types to preserve casing (report) z2s: Return undefined for empty result set when using query.one() z2s: Allow accessing tables in non-public schemas z2s: Allow tx.foo.update({bar: undefined}) where bar is optional to match client behavior Fix broken replication when updating a key that is part of a unique (but non-PK) index solid: Rename useQuery to createQuery to fit Solid naming conventions (old name deprecated) Resync when publications are missing (PR) Fix missing NOT LIKE in query.where() (PR) Fix timezone shift when writing to timestamp/timestamptz and server is non-UTC timezone (thanks Tom Jenkinson!) (PR) Bound time spent in incremental updates to 1/2 hydration time Fix ttl being off by 1000 in some cases 😬 (PR) z2s: Relationships nested in a junction relationship were not working correctly (PR) Custom mutators: Due to multitab, client can receive multiple responses for same mutation Fix deadlock that could happen when pushing on a closed websocket (PR) Fix incorrect shutdown under heavy CPU load (thanks Erik Munson!) (PR) Fix case where deletes were getting reverted (thanks for reproduction Marc MacLeod!) (PR) z2s: Incorrect handling of self-join, and not exists not(exists()) is not supported on the client re-auth on 401s returned by push endpoint Added push.queryParams constructor parameter to allow passing query params to the push endpoint (doc) Breaking Changes The structure of setting up a PushProcesor has changed slightly. See push endpoint setup or upgrade guide. Not technically a breaking change from 0.18, but if you were using 0.19 canaries, the .server property returns error by rejection again (like 0.18 did) (doc).", + "content": "Install npm install @rocicorp/zero@0.19 Upgrading If you use custom mutators, please see hello-zero-solid for how to update your push endpoint. If you use SolidJS, please switch to createQuery. If you are awaiting z.mutate.foo.bar(), you should switch to await z.mutate.foo.bar().client to be consistent with .server. If you were using a 0.19 canary, the .server property returns error by rejection again (like 0.18 did). Sorry about the thrash here. Features Add a type param to query.run() so it can wait for server results (doc, bug) await z.mutate.foo.bar() is now await z.mutate.foo.bar().client for consistency with .server, old API still works but deprecated (doc) Improve speed of litestream restore by about 7x Increase replication speed when using JSON by about 25% Add options to analyze-query to apply permissions and auth data (doc). Add option to --lazy-startup to zero-cache to delay connecting to upstram until first connection (doc) Add /statz endpoint for getting some health statistics from a running Zero instance (doc) Fixes Support passing Request to PushProccesor.process() (PR) Fix layering in PushProcessor to better support custom db implementations (thanks Erik Munson!) (PR) Fix socket disconnects in GCP (PR) Quote Postgres enum types to preserve casing (report) z2s: Return undefined for empty result set when using query.one() z2s: Allow accessing tables in non-public schemas z2s: Allow tx.foo.update({bar: undefined}) where bar is optional to match client behavior Fix broken replication when updating a key that is part of a unique (but non-PK) index solid: Rename useQuery to createQuery to fit Solid naming conventions (old name deprecated) Resync when publications are missing (PR) Fix missing NOT LIKE in query.where() (PR) Fix timezone shift when writing to timestamp/timestamptz and server is non-UTC timezone (thanks Tom Jenkinson!) (PR) Bound time spent in incremental updates to 1/2 hydration time Fix ttl being off by 1000 in some cases 😬 (PR) z2s: Relationships nested in a junction relationship were not working correctly (PR) Custom mutators: Due to multitab, client can receive multiple responses for same mutation Fix deadlock that could happen when pushing on a closed websocket (PR) Fix incorrect shutdown under heavy CPU load (thanks Erik Munson!) (PR) Fix case where deletes were getting reverted (thanks for reproduction Marc MacLeod!) (PR) z2s: Incorrect handling of self-join, and not exists not(exists()) is not supported on the client re-auth on 401s returned by push endpoint Added push.queryParams constructor parameter to allow passing query params to the push endpoint (doc) Breaking Changes The structure of setting up a PushProcesor has changed slightly. See push endpoint setup or upgrade guide. Not technically a breaking change from 0.18, but if you were using 0.19 canaries, the .server property returns error by rejection again (like 0.18 did) (doc).", "headings": [] }, { @@ -241,70 +241,70 @@ "id": "34-release-notes/0.20", "title": "Zero 0.20", "url": "/docs/release-notes/0.20", - "content": "Install ```bash npm install @rocicorp/zero@0.20 ``` Upgrading There are two config changes for multinode deployments: Required: Remove view-syncer's ZERO\\_CHANGE\\_STREAMER\\_URI env var and replace it with ZERO\\_CHANGE\\_STREAMER\\_MODE: \"discover\". Optional: Change the ZERO\\_LITESTREAM\\_BACKUP\\_URL env var from being passed to both replication-manager and view-syncer nodes to being passed only to replication-manager. This config is no longer needed by view-syncer (and is ignored by it). See hello-zero for an upgrade example using SST. Additionally, the ZERO\\_TENANTS\\_JSON, feature was removed. We do not think anyone was using it, but if you were please reach out to us for options. Features Supabase is now fully supported. After upgrading, you should see that schema changes are incremental and don't reset the replica (docs). Improve performance of single-key reads on client. Scale depends on size of data but 100x improvement is common (PR). Implement short-circuiting for or queries. Because of permissions, one or more branches of or would often be empty, turning the entire or into a full-table scan. 100x improvement on chinook test dataset (PR). Remove DNF conversion. This was intended to make consistency easier in the future, but was resulting in some queries exploding in size (PR, bug). Autodiscovery for replication-manager. view-syncer nodes now find replication-manager using the Postgres changedb database, and no longer need an internal load balancer. See the new ZERO\\_CHANGE\\_STREAMER\\_MODE: \"discover\" config in the deployment docs (PR). Make ZERO\\_LITESTREAM\\_BACKUP\\_URL specific to replication-manager. view-syncer nodes now ignore this config and learn it from replication-manager instead. This makes restarting replication less error-prone (PR, discussion). OpenTelemetry support (docs). Fixes Allow dots in column names (only works with custom mutators) (PR). Fix websocket liveness check to avoid false negatives when busy (PR). Fix unhandled exception in zero-cache when processing query eviction (PR). Keep microsecond precision across timezones (PR). Fix unhandled exception in zero-cache during handleClose (PR). Fix NOT IN in z2s (PR). Mutators: assert provided columns actually exist (PR). Fix ordering of columns in replicated index (PR). Use a shorter keepalive for replication stream for compat with Neon (PR). Allow destructuring where in query.related (PR). Add flow control for large change DB transactions (PR). Fix z2s handling of pg types with params (char, varchar, numeric, etc) (PR). Support from and --schema-path in analyze-query (PR). Breaking Changes The autodiscovery feature for replication-manager is a breaking change for multinode deployments. See the upgrade instructions for details. The ZERO\\_TENANTS\\_JSON config was removed 🫗. The ZERO\\_INITIAL\\_SYNC\\_ROW\\_BATCH\\_SIZE config was removed. It is no longer needed because initial sync now adapts to available memory automatically.", + "content": "Install npm install @rocicorp/zero@0.20 Upgrading There are two config changes for multinode deployments: Required: Remove view-syncer's ZERO\\_CHANGE\\_STREAMER\\_URI env var and replace it with ZERO\\_CHANGE\\_STREAMER\\_MODE: \"discover\". Optional: Change the ZERO\\_LITESTREAM\\_BACKUP\\_URL env var from being passed to both replication-manager and view-syncer nodes to being passed only to replication-manager. This config is no longer needed by view-syncer (and is ignored by it). See hello-zero for an upgrade example using SST. Additionally, the ZERO\\_TENANTS\\_JSON, feature was removed. We do not think anyone was using it, but if you were please reach out to us for options. Features Supabase is now fully supported. After upgrading, you should see that schema changes are incremental and don't reset the replica (docs). Improve performance of single-key reads on client. Scale depends on size of data but 100x improvement is common (PR). Implement short-circuiting for or queries. Because of permissions, one or more branches of or would often be empty, turning the entire or into a full-table scan. 100x improvement on chinook test dataset (PR). Remove DNF conversion. This was intended to make consistency easier in the future, but was resulting in some queries exploding in size (PR, bug). Autodiscovery for replication-manager. view-syncer nodes now find replication-manager using the Postgres changedb database, and no longer need an internal load balancer. See the new ZERO\\_CHANGE\\_STREAMER\\_MODE: \"discover\" config in the deployment docs (PR). Make ZERO\\_LITESTREAM\\_BACKUP\\_URL specific to replication-manager. view-syncer nodes now ignore this config and learn it from replication-manager instead. This makes restarting replication less error-prone (PR, discussion). OpenTelemetry support (docs). Fixes Allow dots in column names (only works with custom mutators) (PR). Fix websocket liveness check to avoid false negatives when busy (PR). Fix unhandled exception in zero-cache when processing query eviction (PR). Keep microsecond precision across timezones (PR). Fix unhandled exception in zero-cache during handleClose (PR). Fix NOT IN in z2s (PR). Mutators: assert provided columns actually exist (PR). Fix ordering of columns in replicated index (PR). Use a shorter keepalive for replication stream for compat with Neon (PR). Allow destructuring where in query.related (PR). Add flow control for large change DB transactions (PR). Fix z2s handling of pg types with params (char, varchar, numeric, etc) (PR). Support from and --schema-path in analyze-query (PR). Breaking Changes The autodiscovery feature for replication-manager is a breaking change for multinode deployments. See the upgrade instructions for details. The ZERO\\_TENANTS\\_JSON config was removed 🫗. The ZERO\\_INITIAL\\_SYNC\\_ROW\\_BATCH\\_SIZE config was removed. It is no longer needed because initial sync now adapts to available memory automatically.", "headings": [] }, { "id": "35-release-notes/0.21", "title": "Zero 0.21", "url": "/docs/release-notes/0.21", - "content": "Install ```bash npm install @rocicorp/zero@0.21 ``` Upgrading There is one breaking change in this release, but we think it is unlikely to affect anyone since the results were wrong already – the change just makes the error explicit. See hello-zero for an example of using arrays and the new ZeroProvider features. Features New \"ztunes\" sample using TanStack, Drizzle, Better Auth, and Fly.io (docs). Add initial support for Postgres arrays (docs, bug). Improved React lifecycle management with ZeroProvider (docs, PR). Expose Zero instances automatically at \\_\\_zero (docs, PR). Add --output-{synced|vended}-rows to analyze-query (PR). Technically a bug fix, but this was so annoying I'm calling it a feature: zero-sqlite3 now correctly supports the up/down arrow keys (commit). Another super annoying fix: logs from zero-cache are now level-colored (PR). Fixes Lazy-load otel. This was causing problems with pnpm (PR). Initial replication is now memory-bounded (PR). Change the way otel starts up in zero-cache-dev to not rely on npx (PR). Use existing --log-slow-hydrate-threshold as the threshold for --query-hydration-stats rather than hardcoded 200ms. Fix race condition starting up in multinode deployments (PR). Avoid site-local IPv6 addresses in auto-discovery (PR). Many z2s fixes found by fuzzing (PRs: 4415, 4416, 4417, 4421, 4422, 4423). Don't load prettier in analyze-query. This was causing problems when prettier config was cjs. (PR). Don't hydrate system relationships in analyze-query. This was causing incorrect results. (PR). Fix memory leaks from not cleaning up pusher and mutagen (PR). Fix handling of invalid websocket requests that were crashing server. (PR). Remove red error text when .env missing (PR). Allow zero-cache to startup without schema file, but print a warning (PR). Log a warning when auth token exceeds max allowed header size (PR). Breaking Changes Using order by and limit in many-to-many relationships now throws an error. It didn't work before but did the wrong thing silently. Now it throws a runtime error. See docs, bug.", + "content": "Install npm install @rocicorp/zero@0.21 Upgrading There is one breaking change in this release, but we think it is unlikely to affect anyone since the results were wrong already – the change just makes the error explicit. See hello-zero for an example of using arrays and the new ZeroProvider features. Features New \"ztunes\" sample using TanStack, Drizzle, Better Auth, and Fly.io (docs). Add initial support for Postgres arrays (docs, bug). Improved React lifecycle management with ZeroProvider (docs, PR). Expose Zero instances automatically at \\_\\_zero (docs, PR). Add --output-{synced|vended}-rows to analyze-query (PR). Technically a bug fix, but this was so annoying I'm calling it a feature: zero-sqlite3 now correctly supports the up/down arrow keys (commit). Another super annoying fix: logs from zero-cache are now level-colored (PR). Fixes Lazy-load otel. This was causing problems with pnpm (PR). Initial replication is now memory-bounded (PR). Change the way otel starts up in zero-cache-dev to not rely on npx (PR). Use existing --log-slow-hydrate-threshold as the threshold for --query-hydration-stats rather than hardcoded 200ms. Fix race condition starting up in multinode deployments (PR). Avoid site-local IPv6 addresses in auto-discovery (PR). Many z2s fixes found by fuzzing (PRs: 4415, 4416, 4417, 4421, 4422, 4423). Don't load prettier in analyze-query. This was causing problems when prettier config was cjs. (PR). Don't hydrate system relationships in analyze-query. This was causing incorrect results. (PR). Fix memory leaks from not cleaning up pusher and mutagen (PR). Fix handling of invalid websocket requests that were crashing server. (PR). Remove red error text when .env missing (PR). Allow zero-cache to startup without schema file, but print a warning (PR). Log a warning when auth token exceeds max allowed header size (PR). Breaking Changes Using order by and limit in many-to-many relationships now throws an error. It didn't work before but did the wrong thing silently. Now it throws a runtime error. See docs, bug.", "headings": [] }, { "id": "36-release-notes/0.22", "title": "Zero 0.22", "url": "/docs/release-notes/0.22", - "content": "Install ```bash npm install @rocicorp/zero@0.22 ``` Upgrading This release simplifies the concept of TTLs in Zero. See hello-zero, hello-zero-solid, or ztunes for example upgrades. This release also adds anonymous telemetry collection. You can opt-out with the DO\\_NOT\\_TRACK=1 environment variable. Though we hope you will not, as it helps us improve Zero. How TTLs Used to Work Previously, the TTL of a query simply measured normal \"wall clock time\" from when a query inactivated, including any time the app wasn't running at all. With experience, we realized this was a misfeature because it encouraged the use of very long or infinite TTLs, especially for preload queries. Developers always want preload queries registered, but since they do not know how long the app will be offline, they had no real choice but to use the TTL forever. These infinite TTLs would remain registered even after the app's code changed such that it no longer wanted them, slowing connections and incremental updates to process queries that the app was not even using. Worse, the prevalence of infinite TTLs in turns meant we needed some way to limit the size of the client cache. We introduced the \"client row limit\" for this. But developers would frequently accidentally blow through this limit, causing cache thrash. How TTLs Work Now Now, query TTLs measure \"TTL time\" which only elapses while Zero is running. This means that preload queries usually don't need a TTL at all, since they run the entire time Zero is active. This in turn means we can clamp TTLs to low values, which means queries evict naturally, which means we no longer need the client row limit either. Using New TTLs You don't need to do anything specific to upgrade. Zero will clamp your TTLs at 10m and print a warning. But for best results, please review the new TTL documentation. In particular, see how to set your TTLs (TL;DR: You can often just remove them – the defaults usually just work). Features Rework and simplify query TTLs (docs, upgrading). SolidJS bindings are now fine-grained, improving performance (PR). Restore ZERO\\_CHANGE\\_STREAMER\\_URI option (doc, PR). Add useZeroOnline to React and SolidJS bindings (doc). Add ttl to run() (PR). Allow client to specify push.url in the Zero constructor (doc). Add anonymous telemetry collection to zero-cache (doc). Fixes Handle public in aliases, like .from('public.table') (PR). Sorting by columns with null values was incorrect in some cases (PR). Fix fencepost issue editing queries with limits (PR). Fix copy runner to more reliably reuse connections (PR). Queries early in startup could not contain non-latin chars (PR). SolidJS: Export createUseZero (PR). Support parallel rollouts of replication-manager and view-syncer (PR). Fix upgrade path for already replicated array types (PR). Breaking Changes Require Node v22+ (see discussion)", + "content": "Install npm install @rocicorp/zero@0.22 Upgrading This release simplifies the concept of TTLs in Zero. See hello-zero, hello-zero-solid, or ztunes for example upgrades. This release also adds anonymous telemetry collection. You can opt-out with the DO\\_NOT\\_TRACK=1 environment variable. Though we hope you will not, as it helps us improve Zero. How TTLs Used to Work Previously, the TTL of a query simply measured normal \"wall clock time\" from when a query inactivated, including any time the app wasn't running at all. With experience, we realized this was a misfeature because it encouraged the use of very long or infinite TTLs, especially for preload queries. Developers always want preload queries registered, but since they do not know how long the app will be offline, they had no real choice but to use the TTL forever. These infinite TTLs would remain registered even after the app's code changed such that it no longer wanted them, slowing connections and incremental updates to process queries that the app was not even using. Worse, the prevalence of infinite TTLs in turns meant we needed some way to limit the size of the client cache. We introduced the \"client row limit\" for this. But developers would frequently accidentally blow through this limit, causing cache thrash. How TTLs Work Now Now, query TTLs measure \"TTL time\" which only elapses while Zero is running. This means that preload queries usually don't need a TTL at all, since they run the entire time Zero is active. This in turn means we can clamp TTLs to low values, which means queries evict naturally, which means we no longer need the client row limit either. Using New TTLs You don't need to do anything specific to upgrade. Zero will clamp your TTLs at 10m and print a warning. But for best results, please review the new TTL documentation. In particular, see how to set your TTLs (TL;DR: You can often just remove them – the defaults usually just work). Features Rework and simplify query TTLs (docs, upgrading). SolidJS bindings are now fine-grained, improving performance (PR). Restore ZERO\\_CHANGE\\_STREAMER\\_URI option (doc, PR). Add useZeroOnline to React and SolidJS bindings (doc). Add ttl to run() (PR). Allow client to specify push.url in the Zero constructor (doc). Add anonymous telemetry collection to zero-cache (doc). Fixes Handle public in aliases, like .from('public.table') (PR). Sorting by columns with null values was incorrect in some cases (PR). Fix fencepost issue editing queries with limits (PR). Fix copy runner to more reliably reuse connections (PR). Queries early in startup could not contain non-latin chars (PR). SolidJS: Export createUseZero (PR). Support parallel rollouts of replication-manager and view-syncer (PR). Fix upgrade path for already replicated array types (PR). Breaking Changes Require Node v22+ (see discussion)", "headings": [] }, { "id": "37-release-notes/0.3", "title": "Zero 0.3", "url": "/docs/release-notes/0.3", - "content": "Install ```bash npm install @rocicorp/zero@0.3 ``` Breaking changes zero.config file is now TypeScript, not JSON. See: https://github.com/rocicorp/hello-zero/blob/07c08b1f86b526a96e281ee65af672f52a59bcee/zero.config.ts. Features Schema Migrations: Zero now has first-class support for schema migration (documentation). Write Permissions: First-class write permissions based on ZQL (documentation). Date/Time related types: Zero now natively supports the TIMESTAMP and DATE Postgres types (sample app, documentation). SolidJS: We now have first-class support for SolidJS (documentation). Intellisense for Schema Definition: Introduce createSchema and createTableSchema helper functions to enable intellisense when defining shemas. See Sample App. escapeLike() : Add helper to properly escape strings for use in LIKE filters. See Sample App. New QuickStart App: Entirely rewrote the setup/sample flow to (a) make it much faster to get started playing with Zero, and (b) demonstrate more features. Fixes The @rocicorp/zero package now downloads a prebuilt sqlite instead of compiling it locally. This significantly speeds up install. Support rds.force\\_ssl=1 RDS configuration. Fixed bug where sibling subqueries could be lost on edit changes. Fixes to error handling to ensure zero-cache prints errors when crashing in multiprocess mode. If zero-cache hears from a client with an unknown CVR/cookie, zero-cache forces that client to reset itself and reload automatically. Useful during development when server-state is frequently getting cleared. Docs Started work to make real docs. Not quite done yet. zbugs https://bugs.rocicorp.dev/ (pw: zql) Improve startup perf: ~3s → ~1.5s Hawaii ↔ US East. More work to do here but good progress. Responsive design for mobile. “Short IDs”: Bugs now have a short numeric ID, not a random hash. See Demo Video. First-class label picker. Unread indicators. Finish j/k support for paging through issues. It’s now “search-aware”, it pages through issues in order of search you clicked through to detail page in. Text search (slash to activate — needs better discoverability) Emojis on issues and comments Sort controls on list view remove fps meter temporarily numerous other UI polish", + "content": "Install npm install @rocicorp/zero@0.3 Breaking changes zero.config file is now TypeScript, not JSON. See: https://github.com/rocicorp/hello-zero/blob/07c08b1f86b526a96e281ee65af672f52a59bcee/zero.config.ts. Features Schema Migrations: Zero now has first-class support for schema migration (documentation). Write Permissions: First-class write permissions based on ZQL (documentation). Date/Time related types: Zero now natively supports the TIMESTAMP and DATE Postgres types (sample app, documentation). SolidJS: We now have first-class support for SolidJS (documentation). Intellisense for Schema Definition: Introduce createSchema and createTableSchema helper functions to enable intellisense when defining shemas. See Sample App. escapeLike() : Add helper to properly escape strings for use in LIKE filters. See Sample App. New QuickStart App: Entirely rewrote the setup/sample flow to (a) make it much faster to get started playing with Zero, and (b) demonstrate more features. Fixes The @rocicorp/zero package now downloads a prebuilt sqlite instead of compiling it locally. This significantly speeds up install. Support rds.force\\_ssl=1 RDS configuration. Fixed bug where sibling subqueries could be lost on edit changes. Fixes to error handling to ensure zero-cache prints errors when crashing in multiprocess mode. If zero-cache hears from a client with an unknown CVR/cookie, zero-cache forces that client to reset itself and reload automatically. Useful during development when server-state is frequently getting cleared. Docs Started work to make real docs. Not quite done yet. zbugs https://bugs.rocicorp.dev/ (pw: zql) Improve startup perf: ~3s → ~1.5s Hawaii ↔ US East. More work to do here but good progress. Responsive design for mobile. “Short IDs”: Bugs now have a short numeric ID, not a random hash. See Demo Video. First-class label picker. Unread indicators. Finish j/k support for paging through issues. It’s now “search-aware”, it pages through issues in order of search you clicked through to detail page in. Text search (slash to activate — needs better discoverability) Emojis on issues and comments Sort controls on list view remove fps meter temporarily numerous other UI polish", "headings": [] }, { "id": "38-release-notes/0.4", "title": "Zero 0.4", "url": "/docs/release-notes/0.4", - "content": "Install ```bash npm install @rocicorp/zero@0.4 ``` Breaking changes The or changes modified the client/server protocol. You’ll need to restart zero-cache and clear browser data after updating. Added or , and , and not to ZQL (documentation). Added query.run() method (documentation). Fixes Use batch() method in zero-solid to improve performance when multiple updates happen in same frame. To take advantage of this you must use the createZero helper from @rocicorp/zero/solid, instead of instantiating Zero directly. See the solid sample app. Postgres tables that were reserved words in SQLite but not Postgres caused crash during replication. LIKE was not matching correctly in the case of multiline subjects. Upstream database and zero database can now be same Postgres db (don’t need separate ports). Docs nothing notable zbugs Use or to run text search over both titles and bodies prevent j/k in emoji preload emojis", + "content": "Install npm install @rocicorp/zero@0.4 Breaking changes The or changes modified the client/server protocol. You’ll need to restart zero-cache and clear browser data after updating. Added or , and , and not to ZQL (documentation). Added query.run() method (documentation). Fixes Use batch() method in zero-solid to improve performance when multiple updates happen in same frame. To take advantage of this you must use the createZero helper from @rocicorp/zero/solid, instead of instantiating Zero directly. See the solid sample app. Postgres tables that were reserved words in SQLite but not Postgres caused crash during replication. LIKE was not matching correctly in the case of multiline subjects. Upstream database and zero database can now be same Postgres db (don’t need separate ports). Docs nothing notable zbugs Use or to run text search over both titles and bodies prevent j/k in emoji preload emojis", "headings": [] }, { "id": "39-release-notes/0.5", "title": "Zero 0.5", "url": "/docs/release-notes/0.5", - "content": "Install ```bash npm install @rocicorp/zero@0.5 ``` Breaking changes createTableSchema and createSchema moved to @rocicorp/zero/schema subpackage. This is in preparation to moving authorization into the schema file. SchemaToRow helper type was renamed TableSchemaToRow and moved into @rocicorp/zero/schema. Basically: ```diff - import { createSchema, createTableSchema, SchemaToRow } from \"@rocicorp/zero\"; + import { createSchema, createTableSchema, TableSchemaToRow } from \"@rocicorp/zero/schema\"; ``` Features Added support for JSON columns in Postgres (documentation). Zero pacakage now includes zero-sqlite3, which can be used to explore our sqlite files (documentation). Fixes We were not correctly replicating the char(n) type, despite documenting that we were. Docs nothing notable zbugs nothing notable", + "content": "Install npm install @rocicorp/zero@0.5 Breaking changes createTableSchema and createSchema moved to @rocicorp/zero/schema subpackage. This is in preparation to moving authorization into the schema file. SchemaToRow helper type was renamed TableSchemaToRow and moved into @rocicorp/zero/schema. Basically: - import { createSchema, createTableSchema, SchemaToRow } from \"@rocicorp/zero\"; + import { createSchema, createTableSchema, TableSchemaToRow } from \"@rocicorp/zero/schema\"; Features Added support for JSON columns in Postgres (documentation). Zero pacakage now includes zero-sqlite3, which can be used to explore our sqlite files (documentation). Fixes We were not correctly replicating the char(n) type, despite documenting that we were. Docs nothing notable zbugs nothing notable", "headings": [] }, { "id": "40-release-notes/0.6", "title": "Zero 0.6", "url": "/docs/release-notes/0.6", - "content": "Install ```bash npm install @rocicorp/zero@0.6 ``` Upgrade Guide This release is a bit harder to upgrade to than previous alphas. For a step-by-step guide, please refer to the commits that upgrade the React and Solid quickstart apps: Upgrading hello-zero from Zero 0.5 to 0.6 Upgrading hello-zero-solid from Zero 0.5 to 0.6 Breaking Changes Totally new configuration system. zero.config.ts is no more – config is now via env vars (documentation). Permissions rules moved into schema (documentation). Renamed CRUD mutators to be consistent with SQL naming (bug, documentation). z.mutate.\\.create -> insert z.mutate.\\
.put -> upsert Removed select from ZQL. It wasn’t doing anything (documentation) Moved batch mutation to its own mutateBatch method. Before the mutate field also doubled as a method. This made intellisense hard to understand since z.mutate had all the tables as fields but also all the fields of a function. Features Relationship filters. Queries can now include whereExists (bug, documentation). Reworked syntax for compound where filters, including ergonomically building or expressions with dynamic number of clauses (bug, documentation). Support using Postgres databases without superuser access for smaller apps (documentation). Support for running Zero client under Cloudflare Durable Objects (documentation). Reworked support for null / undefined to properly support optional fields (bug, documentation). Added IS / IS NOT to ZQL to support checking for null (bug, documentation). Improved intellisense for mutators. Added --port flag and ZERO\\_PORT environment variable (bug, documentation). Default max connections of zero-cache more conservatively so that it should fit with even common small Postgres configurations. zero-cache now accepts requests with any base path, not just /api. The server parameter to the Zero client constructor can now be a host (https://myapp-myteam.zero.ms) or a host with a single path component (https://myapp-myteam.zero.ms/zero). These two changes together allow hosting zero-cache on same domain with an app that already uses the /api prefix (bug). Allow Postgres columns with default values, but don’t sync them (documentation). The npx zero-sqlite utility now accepts all the same flags and arguments that sqlite3 does (documentation). zbugs Added tooltip describing who submitted which emoji reactions Updated implementation of label, assignee, and owner filters to use relationship filters Updated text filter implementation to use or to search description and comments too Docs Added new ZQL reference Added new mutators reference Added new config reference", + "content": "Install npm install @rocicorp/zero@0.6 Upgrade Guide This release is a bit harder to upgrade to than previous alphas. For a step-by-step guide, please refer to the commits that upgrade the React and Solid quickstart apps: Upgrading hello-zero from Zero 0.5 to 0.6 Upgrading hello-zero-solid from Zero 0.5 to 0.6 Breaking Changes Totally new configuration system. zero.config.ts is no more – config is now via env vars (documentation). Permissions rules moved into schema (documentation). Renamed CRUD mutators to be consistent with SQL naming (bug, documentation). z.mutate.\\
.create -> insert z.mutate.\\
.put -> upsert Removed select from ZQL. It wasn’t doing anything (documentation) Moved batch mutation to its own mutateBatch method. Before the mutate field also doubled as a method. This made intellisense hard to understand since z.mutate had all the tables as fields but also all the fields of a function. Features Relationship filters. Queries can now include whereExists (bug, documentation). Reworked syntax for compound where filters, including ergonomically building or expressions with dynamic number of clauses (bug, documentation). Support using Postgres databases without superuser access for smaller apps (documentation). Support for running Zero client under Cloudflare Durable Objects (documentation). Reworked support for null / undefined to properly support optional fields (bug, documentation). Added IS / IS NOT to ZQL to support checking for null (bug, documentation). Improved intellisense for mutators. Added --port flag and ZERO\\_PORT environment variable (bug, documentation). Default max connections of zero-cache more conservatively so that it should fit with even common small Postgres configurations. zero-cache now accepts requests with any base path, not just /api. The server parameter to the Zero client constructor can now be a host (https://myapp-myteam.zero.ms) or a host with a single path component (https://myapp-myteam.zero.ms/zero). These two changes together allow hosting zero-cache on same domain with an app that already uses the /api prefix (bug). Allow Postgres columns with default values, but don’t sync them (documentation). The npx zero-sqlite utility now accepts all the same flags and arguments that sqlite3 does (documentation). zbugs Added tooltip describing who submitted which emoji reactions Updated implementation of label, assignee, and owner filters to use relationship filters Updated text filter implementation to use or to search description and comments too Docs Added new ZQL reference Added new mutators reference Added new config reference", "headings": [] }, { "id": "41-release-notes/0.7", "title": "Zero 0.7", "url": "/docs/release-notes/0.7", - "content": "Install ```bash npm install @rocicorp/zero@0.7 ``` Features Read permissions. You can now control read access to data using ZQL (docs). Deployment. We now have a single-node Docker container (docs). Future work will add multinode support. Compound FKs. Zero already supported compound primary keys, but now it also supports compound foreign keys (docs). Schema DX: Columns types can use bare strings now if optional is not needed (example). PK can be a single string in the common case where it’s non-compound (example). Breaking Changes Several changes to schema.ts. See update to hello-zero for overview. Details: defineAuthorization was renamed to definedPermissions to avoid confusion with authentication. The way that many:many relationships are defined has changed to be more general and easy to remember. See example. The signature of definePermissions and the related rule functions have changed: Now rules return an expression instead of full query. This was required to make read permissions work and we did it for write permissions for consitency (see example). The update policy now has two child policies: preMutation and postMutation. The rules we used to have were preMutation. They run before a change and can be used to validate a user has permission to change a row. The postMutation rules run after and can be used to limit the changes a user is allowed to make. The schema.ts file should export an object having two fields: schema and permissions. The way that schema.ts is consumed has also changed. Rather than zero-cache directly reading the typescript source, we compile it to JSON and read that. ZERO\\_SCHEMA\\_FILE should now point to a JSON file, not .ts. It defaults to ./zero-schema.json which we’ve found to be pretty useful so you’ll probably just remove this key from your .env entirely. Use npx zero-build-schema to generate the JSON. You must currently do this manually each time you change the schema, we will automate it soon. zbugs Comments now have permalinks. Implementing permalinks in a synced SPA is fun! Private issues. Zbugs now supports private (to team only) issues. I wonder what’s in them … 👀. Docs The docs have moved. Please don’t use Notion anymore, they won’t be updated.", + "content": "Install npm install @rocicorp/zero@0.7 Features Read permissions. You can now control read access to data using ZQL (docs). Deployment. We now have a single-node Docker container (docs). Future work will add multinode support. Compound FKs. Zero already supported compound primary keys, but now it also supports compound foreign keys (docs). Schema DX: Columns types can use bare strings now if optional is not needed (example). PK can be a single string in the common case where it’s non-compound (example). Breaking Changes Several changes to schema.ts. See update to hello-zero for overview. Details: defineAuthorization was renamed to definedPermissions to avoid confusion with authentication. The way that many:many relationships are defined has changed to be more general and easy to remember. See example. The signature of definePermissions and the related rule functions have changed: Now rules return an expression instead of full query. This was required to make read permissions work and we did it for write permissions for consitency (see example). The update policy now has two child policies: preMutation and postMutation. The rules we used to have were preMutation. They run before a change and can be used to validate a user has permission to change a row. The postMutation rules run after and can be used to limit the changes a user is allowed to make. The schema.ts file should export an object having two fields: schema and permissions. The way that schema.ts is consumed has also changed. Rather than zero-cache directly reading the typescript source, we compile it to JSON and read that. ZERO\\_SCHEMA\\_FILE should now point to a JSON file, not .ts. It defaults to ./zero-schema.json which we’ve found to be pretty useful so you’ll probably just remove this key from your .env entirely. Use npx zero-build-schema to generate the JSON. You must currently do this manually each time you change the schema, we will automate it soon. zbugs Comments now have permalinks. Implementing permalinks in a synced SPA is fun! Private issues. Zbugs now supports private (to team only) issues. I wonder what’s in them … 👀. Docs The docs have moved. Please don’t use Notion anymore, they won’t be updated.", "headings": [] }, { "id": "42-release-notes/0.8", "title": "Zero 0.8", "url": "/docs/release-notes/0.8", - "content": "Install ```bash npm install @rocicorp/zero@0.8 ``` See the changes to hello-zero or hello-zero-solid for example updates. Features Schema Autobuild. There's now a zero-cache-dev script that automatically rebuilds the schema and restarts zero-cache on changes to schema.ts. (docs) Result Type. You can now tell whether a query is complete or partial. (docs) Enums. Enums are now supported in Postgres schemas and on client. (docs) Custom Types. You can define custom JSON types in your schema. (docs) OTEL Tracing. Initial tracing support. (docs) timestampz. Add support for timestampz Postgres column type. (docs) SSLMode. You can disable TLS when zero-cache connects to DB with sslmode=disable. (docs) Permission Helpers. ANYONE\\_CAN and NOBODY\\_CAN helpers were added to make these cases more readable. (docs) Multitenant Support. A single zero-cache can now front separate Postgres databases. This is useful for customers that have one \"dev\" database in production per-developer. (docs) Fixes Crash with JSON Columns. Fixed a crash when a JSON column was used in a Zero app with write permissions (bug) Better Connection Error Reporting. Some connection errors would cause zero-cache to exit silently. Now they are returned to client and logged. Breaking Changes useQuery in React now returns a 2-tuple of \\[rows, result] where result is an object with a type field. postProposedMutation in write permissions for update renamed to postMutation for consistency. TableScheamToRow renamed to Row to not be so silly long.", + "content": "Install npm install @rocicorp/zero@0.8 See the changes to hello-zero or hello-zero-solid for example updates. Features Schema Autobuild. There's now a zero-cache-dev script that automatically rebuilds the schema and restarts zero-cache on changes to schema.ts. (docs) Result Type. You can now tell whether a query is complete or partial. (docs) Enums. Enums are now supported in Postgres schemas and on client. (docs) Custom Types. You can define custom JSON types in your schema. (docs) OTEL Tracing. Initial tracing support. (docs) timestampz. Add support for timestampz Postgres column type. (docs) SSLMode. You can disable TLS when zero-cache connects to DB with sslmode=disable. (docs) Permission Helpers. ANYONE\\_CAN and NOBODY\\_CAN helpers were added to make these cases more readable. (docs) Multitenant Support. A single zero-cache can now front separate Postgres databases. This is useful for customers that have one \"dev\" database in production per-developer. (docs) Fixes Crash with JSON Columns. Fixed a crash when a JSON column was used in a Zero app with write permissions (bug) Better Connection Error Reporting. Some connection errors would cause zero-cache to exit silently. Now they are returned to client and logged. Breaking Changes useQuery in React now returns a 2-tuple of \\[rows, result] where result is an object with a type field. postProposedMutation in write permissions for update renamed to postMutation for consistency. TableScheamToRow renamed to Row to not be so silly long.", "headings": [] }, { "id": "43-release-notes/0.9", "title": "Zero 0.9", "url": "/docs/release-notes/0.9", - "content": "Install ```bash npm install @rocicorp/zero@0.9 ``` See the changes to hello-zero or hello-zero-solid for example updates. Features JWK Support. For auth, you can now specify a JWK containing a public key, or a JWKS url to support autodiscovery of keys. (docs) UUID column. Zero now supports the uuid Postgres column type. (docs) Fixes Readonly Values. Type of values returned from Zero queries are marked readonly. The system always considered them readonly, but now the types reflect that. (docs) Breaking Changes The zero-cache config ZERO\\_JWT\\_SECRET has been renamed to ZERO\\_AUTH\\_SECRET for consistency with the new JWK-related keys. If you were using the old name, you'll need to update your .env file. All values returned by Zero are now readonly. You'll probably have to add this TS modifier various places. If you find yourself casting away readonly you probably should be cloing the value instead.", + "content": "Install npm install @rocicorp/zero@0.9 See the changes to hello-zero or hello-zero-solid for example updates. Features JWK Support. For auth, you can now specify a JWK containing a public key, or a JWKS url to support autodiscovery of keys. (docs) UUID column. Zero now supports the uuid Postgres column type. (docs) Fixes Readonly Values. Type of values returned from Zero queries are marked readonly. The system always considered them readonly, but now the types reflect that. (docs) Breaking Changes The zero-cache config ZERO\\_JWT\\_SECRET has been renamed to ZERO\\_AUTH\\_SECRET for consistency with the new JWK-related keys. If you were using the old name, you'll need to update your .env file. All values returned by Zero are now readonly. You'll probably have to add this TS modifier various places. If you find yourself casting away readonly you probably should be cloing the value instead.", "headings": [] }, { @@ -339,7 +339,7 @@ "id": "48-solidjs", "title": "SolidJS", "url": "/docs/solidjs", - "content": "Zero has built-in support for Solid. Here’s what basic usage looks like: ```tsx import {useQuery} from '@rocicorp/zero/solid'; const issues = useQuery(() => { let issueQuery = z.query.issue .related('creator') .related('labels') .limit(100); const userID = selectedUserID(); if (userID) { issueQuery = issueQuery.where('creatorID', '=', userID); } return issueQuery; }); ``` Complete quickstart here: https://github.com/rocicorp/hello-zero-solid", + "content": "Zero has built-in support for Solid. Here’s what basic usage looks like: import {useQuery} from '@rocicorp/zero/solid'; const issues = useQuery(() => { let issueQuery = z.query.issue .related('creator') .related('labels') .limit(100); const userID = selectedUserID(); if (userID) { issueQuery = issueQuery.where('creatorID', '=', userID); } return issueQuery; }); Complete quickstart here: https://github.com/rocicorp/hello-zero-solid", "headings": [] }, { @@ -367,28 +367,28 @@ "id": "52-writing-data", "title": "Writing Data with Mutators", "url": "/docs/writing-data", - "content": "Zero generates basic CRUD mutators for every table you sync. Mutators are available at zero.mutate.\\: ```tsx const z = new Zero(...); z.mutate.user.insert({ id: nanoid(), username: 'abby', language: 'en-us', }); ``` Insert Create new records with insert: ```tsx z.mutate.user.insert({ id: nanoid(), username: 'sam', language: 'js', }); ``` Optional fields can be set to null to explicitly set the new field to null. They can also be set to undefined to take the default value (which is often null but can also be some generated value server-side). ```tsx // schema.ts import {createTableSchema} from '@rocicorp/zero'; const userSchema = createTableSchema({ tableName: 'user', columns: { id: {type: 'string'}, name: {type: 'string'}, language: {type: 'string', optional: true}, }, primaryKey: ['id'], relationships: {}, }); // app.tsx // Sets language to `null` specifically z.mutate.user.insert({ id: nanoid(), username: 'sam', language: null, }); // Sets language to the default server-side value. Could be null, or some // generated or constant default value too. z.mutate.user.insert({ id: nanoid(), username: 'sam', }); // Same as above z.mutate.user.insert({ id: nanoid(), username: 'sam', language: undefined, }); ``` Upsert Create new records or update existing ones with upsert: ```tsx z.mutate.user.upsert({ id: samID, username: 'sam', language: 'ts', }); ``` upsert supports the same null / undefined semantics for optional fields that insert does (see above). Update Update an existing record. Does nothing if the specified record (by PK) does not exist. You can pass a partial, leaving fields out that you don’t want to change. For example here we leave the username the same: ```tsx // Leaves username field to previous value. z.mutate.user.update({ id: samID, language: 'golang', }); // Same as above z.mutate.user.update({ id: samID, username: undefined, language: 'haskell', }); // Reset language field to `null` z.mutate.user.update({ id: samID, language: null, }); ``` Delete Delete an existing record. Does nothing if specified record does not exist. ```tsx z.mutate.user.delete({ id: samID, }); ``` You can read more about it in Authentication. Batch Mutate You can do multiple CRUD mutates in a single batch. If any of the mutations fails, all will. They also all appear together atomically in a single transaction to other clients. ```tsx z.mutateBatch(async tx => { const samID = nanoid(); tx.user.insert({ id: samID, username: 'sam', }); const langID = nanoid(); tx.language.insert({ id: langID, userID: samID, name: 'js', }); }); ```", + "content": "Zero generates basic CRUD mutators for every table you sync. Mutators are available at zero.mutate.\\: const z = new Zero(...); z.mutate.user.insert({ id: nanoid(), username: 'abby', language: 'en-us', }); Insert Create new records with insert: z.mutate.user.insert({ id: nanoid(), username: 'sam', language: 'js', }); Optional fields can be set to null to explicitly set the new field to null. They can also be set to undefined to take the default value (which is often null but can also be some generated value server-side). // schema.ts import {createTableSchema} from '@rocicorp/zero'; const userSchema = createTableSchema({ tableName: 'user', columns: { id: {type: 'string'}, name: {type: 'string'}, language: {type: 'string', optional: true}, }, primaryKey: ['id'], relationships: {}, }); // app.tsx // Sets language to `null` specifically z.mutate.user.insert({ id: nanoid(), username: 'sam', language: null, }); // Sets language to the default server-side value. Could be null, or some // generated or constant default value too. z.mutate.user.insert({ id: nanoid(), username: 'sam', }); // Same as above z.mutate.user.insert({ id: nanoid(), username: 'sam', language: undefined, }); Upsert Create new records or update existing ones with upsert: z.mutate.user.upsert({ id: samID, username: 'sam', language: 'ts', }); upsert supports the same null / undefined semantics for optional fields that insert does (see above). Update Update an existing record. Does nothing if the specified record (by PK) does not exist. You can pass a partial, leaving fields out that you don’t want to change. For example here we leave the username the same: // Leaves username field to previous value. z.mutate.user.update({ id: samID, language: 'golang', }); // Same as above z.mutate.user.update({ id: samID, username: undefined, language: 'haskell', }); // Reset language field to `null` z.mutate.user.update({ id: samID, language: null, }); Delete Delete an existing record. Does nothing if specified record does not exist. z.mutate.user.delete({ id: samID, }); You can read more about it in Authentication. Batch Mutate You can do multiple CRUD mutates in a single batch. If any of the mutations fails, all will. They also all appear together atomically in a single transaction to other clients. z.mutateBatch(async tx => { const samID = nanoid(); tx.user.insert({ id: samID, username: 'sam', }); const langID = nanoid(); tx.language.insert({ id: langID, userID: samID, name: 'js', }); });", "headings": [] }, { "id": "53-zero-cache-config", "title": "zero-cache Config", "url": "/docs/zero-cache-config", - "content": "zero-cache is configured either via CLI flag or environment variable. There is no separate zero.config file. You can also see all available flags by running zero-cache --help. Required Flags Auth One of Auth JWK, Auth JWK URL, or Auth Secret must be specified. See Authentication for more details. Replica File File path to the SQLite replica that zero-cache maintains. This can be lost, but if it is, zero-cache will have to re-replicate next time it starts up. flag: --replica-file env: ZERO\\_REPLICA\\_FILE required: true Upstream DB The \"upstream\" authoritative postgres database. In the future we will support other types of upstream besides PG. flag: --upstream-db env: ZERO\\_UPSTREAM\\_DB required: true Optional Flags Admin Password A password used to administer zero-cache server, for example to access the /statz endpoint. flag: --admin-password env: ZERO\\_ADMIN\\_PASSWORD required: false App ID Unique identifier for the app. Multiple zero-cache apps can run on a single upstream database, each of which is isolated from the others, with its own permissions, sharding (future feature), and change/cvr databases. The metadata of an app is stored in an upstream schema with the same name, e.g. zero, and the metadata for each app shard, e.g. client and mutation ids, is stored in the {app-id}\\_{#} schema. (Currently there is only a single \"0\" shard, but this will change with sharding). The CVR and Change data are managed in schemas named {app-id}\\_{shard-num}/cvr and {app-id}\\_{shard-num}/cdc, respectively, allowing multiple apps and shards to share the same database instance (e.g. a Postgres \"cluster\") for CVR and Change management. Due to constraints on replication slot names, an App ID may only consist of lower-case letters, numbers, and the underscore character. Note that this option is used by both zero-cache and zero-deploy-permissions. flag: --app-id env: ZERO\\_APP\\_ID default: zero App Publications Postgres PUBLICATIONs that define the tables and columns to replicate. Publication names may not begin with an underscore, as zero reserves that prefix for internal use. If unspecified, zero-cache will create and use an internal publication that publishes all tables in the public schema, i.e.: ``` CREATE PUBLICATION _{app-id}_public_0 FOR TABLES IN SCHEMA public; ``` Note that once an app has begun syncing data, this list of publications cannot be changed, and zero-cache will refuse to start if a specified value differs from what was originally synced. To use a different set of publications, a new app should be created. flag: --app-publications env: ZERO\\_APP\\_PUBLICATIONS default: \\[] Auth JWK A public key in JWK format used to verify JWTs. Only one of jwk, jwksUrl and secret may be set. flag: --auth-jwk env: ZERO\\_AUTH\\_JWK required: false Auth JWK URL A URL that returns a JWK set used to verify JWTs. Only one of jwk, jwksUrl and secret may be set. flag: --auth-jwks-url env: ZERO\\_AUTH\\_JWKS\\_URL required: false Auto Reset Automatically wipe and resync the replica when replication is halted. This situation can occur for configurations in which the upstream database provider prohibits event trigger creation, preventing the zero-cache from being able to correctly replicate schema changes. For such configurations, an upstream schema change will instead result in halting replication with an error indicating that the replica needs to be reset. When auto-reset is enabled, zero-cache will respond to such situations by shutting down, and when restarted, resetting the replica and all synced clients. This is a heavy-weight operation and can result in user-visible slowness or downtime if compute resources are scarce. flag: --auto-reset env: ZERO\\_AUTO\\_RESET default: true Auth Secret A symmetric key used to verify JWTs. Only one of jwk, jwksUrl and secret may be set. flag: --auth-secret env: ZERO\\_AUTH\\_SECRET required: false Change DB The Postgres database used to store recent replication log entries, in order to sync multiple view-syncers without requiring multiple replication slots on the upstream database. If unspecified, the upstream-db will be used. flag: --change-db env: ZERO\\_CHANGE\\_DB required: false Change Max Connections The maximum number of connections to open to the change database. This is used by the change-streamer for catching up zero-cache replication subscriptions. flag: --change-max-conns env: ZERO\\_CHANGE\\_MAX\\_CONNS default: 5 Change Streamer Mode The mode for running or connecting to the change-streamer: dedicated: runs the change-streamer and shuts down when another change-streamer takes over the replication slot. This is appropriate in a single-node configuration, or for the replication-manager in a multi-node configuration. discover: connects to the change-streamer as internally advertised in the change-db. This is appropriate for the view-syncers in a multi-node flag: --change-streamer-mode env: ZERO\\_CHANGE\\_STREAMER\\_MODE default: dedicated Change Streamer Port The port on which the change-streamer runs. This is an internal protocol between the replication-manager and zero-cache, which runs in the same process in local development. If unspecified, defaults to --port + 1. flag: --change-streamer-port env: ZERO\\_CHANGE\\_STREAMER\\_PORT required: false Change Streamer URI When unset, the zero-cache runs its own replication-manager (i.e. change-streamer). In production, this should be set to the replication-manager URI, which runs a change-streamer on port 4849. flag: --change-streamer-uri env: ZERO\\_CHANGE\\_STREAMER\\_URI required: false CVR DB The Postgres database used to store CVRs. CVRs (client view records) keep track of the data synced to clients in order to determine the diff to send on reconnect. If unspecified, the upstream-db will be used. flag: --cvr-db env: ZERO\\_CVR\\_DB required: false CVR Max Connections The maximum number of connections to open to the CVR database. This is divided evenly amongst sync workers. Note that this number must allow for at least one connection per sync worker, or zero-cache will fail to start. See num-sync-workers. flag: --cvr-max-conns env: ZERO\\_CVR\\_MAX\\_CONNS default: 30 Enable Telemetry Zero collects anonymous telemetry data to help us understand usage. We collect: Zero version Uptime General machine information, like the number of CPUs, OS, CI/CD environment, etc. Information about usage, such as number of queries or mutations processed per hour. This is completely optional and can be disabled at any time. You can also opt-out by setting DO\\_NOT\\_TRACK=1. flag: --enable-telemetry env: ZERO\\_ENABLE\\_TELEMETRY default: true Initial Sync Table Copy Workers The number of parallel workers used to copy tables during initial sync. Each worker copies a single table at a time, fetching rows in batches of initial-sync-row-batch-size. flag: --initial-sync-table-copy-workers env: ZERO\\_INITIAL\\_SYNC\\_TABLE\\_COPY\\_WORKERS default: 5 Lazy Startup Delay starting the majority of zero-cache until first request. This is mainly intended to avoid connecting to Postgres replication stream until the first request is received, which can be useful i.e., for preview instances. Currently only supported in single-node mode. flag: --lazy-startup env: ZERO\\_LAZY\\_STARTUP default: false Litestream Backup URL The location of the litestream backup, usually an s3:// URL. This is only consulted by the replication-manager. view-syncers receive this information from the replication-manager. flag: --litestream-backup-url env: ZERO\\_LITESTREAM\\_BACKUP\\_URL required: false Litestream Checkpoint Threshold MB The size of the WAL file at which to perform an SQlite checkpoint to apply the writes in the WAL to the main database file. Each checkpoint creates a new WAL segment file that will be backed up by litestream. Smaller thresholds may improve read performance, at the expense of creating more files to download when restoring the replica from the backup. flag: --litestream-checkpoint-threshold-mb env: ZERO\\_LITESTREAM\\_CHECKPOINT\\_THRESHOLD\\_MB default: 40 Litestream Config Path Path to the litestream yaml config file. zero-cache will run this with its environment variables, which can be referenced in the file via ${ENV} substitution, for example: ZERO\\_REPLICA\\_FILE for the db Path ZERO\\_LITESTREAM\\_BACKUP\\_LOCATION for the db replica url ZERO\\_LITESTREAM\\_LOG\\_LEVEL for the log Level ZERO\\_LOG\\_FORMAT for the log type flag: --litestream-config-path env: ZERO\\_LITESTREAM\\_CONFIG\\_PATH default: ./src/services/litestream/config.yml Litestream Executable Path to the litestream executable. This option has no effect if litestream-backup-url is unspecified. flag: --litestream-executable env: ZERO\\_LITESTREAM\\_EXECUTABLE required: false Litestream Incremental Backup Interval Minutes The interval between incremental backups of the replica. Shorter intervals reduce the amount of change history that needs to be replayed when catching up a new view-syncer, at the expense of increasing the number of files needed to download for the initial litestream restore. flag: --litestream-incremental-backup-interval-minutes env: ZERO\\_LITESTREAM\\_INCREMENTAL\\_BACKUP\\_INTERVAL\\_MINUTES default: 15 Litestream Multipart Concurrency The number of parts (of size --litestream-multipart-size bytes) to upload or download in parallel when backing up or restoring the snapshot. flag: --litestream-multipart-concurrency env: ZERO\\_LITESTREAM\\_MULTIPART\\_CONCURRENCY default: 48 Litestream Multipart Size The size of each part when uploading or downloading the snapshot with \\--litestream-multipart-concurrency. Note that up to concurrency \\* size bytes of memory are used when backing up or restoring the snapshot. flag: --litestream-multipart-size env: ZERO\\_LITESTREAM\\_MULTIPART\\_SIZE default: 16777216 (16 MiB) Litestream Log Level flag: --litestream-log-level env: ZERO\\_LITESTREAM\\_LOG\\_LEVEL default: warn values: debug, info, warn, error Litestream Port Port on which litestream exports metrics, used to determine the replication watermark up to which it is safe to purge change log records. flag: --litestream-port env: ZERO\\_LITESTREAM\\_PORT default: --port + 2 Litestream Restore Parallelism The number of WAL files to download in parallel when performing the initial restore of the replica from the backup. flag: --litestream-restore-parallelism env: ZERO\\_LITESTREAM\\_RESTORE\\_PARALLELISM default: 48 Litestream Snapshot Backup Interval Hours The interval between snapshot backups of the replica. Snapshot backups make a full copy of the database to a new litestream generation. This improves restore time at the expense of bandwidth. Applications with a large database and low write rate can increase this interval to reduce network usage for backups (litestream defaults to 24 hours). flag: --litestream-snapshot-backup-interval-hours env: ZERO\\_LITESTREAM\\_SNAPSHOT\\_BACKUP\\_INTERVAL\\_HOURS default: 12 Log Format Use text for developer-friendly console logging and json for consumption by structured-logging services. flag: --log-format env: ZERO\\_LOG\\_FORMAT default: \"text\" values: text, json Log IVM Sampling How often to collect IVM metrics. 1 out of N requests will be sampled where N is this value. flag: --log-ivm-sampling env: ZERO\\_LOG\\_IVM\\_SAMPLING default: 5000 Log Level Sets the logging level for the application. flag: --log-level env: ZERO\\_LOG\\_LEVEL default: \"info\" values: debug, info, warn, error Log Slow Hydrate Threshold The number of milliseconds a query hydration must take to print a slow warning. flag: --log-slow-hydrate-threshold env: ZERO\\_LOG\\_SLOW\\_HYDRATE\\_THRESHOLD default: 100 Log Slow Row Threshold The number of ms a row must take to fetch from table-source before it is considered slow. flag: --log-slow-row-threshold env: ZERO\\_LOG\\_SLOW\\_ROW\\_THRESHOLD default: 2 Number of Sync Workers The number of processes to use for view syncing. Leave this unset to use the maximum available parallelism. If set to 0, the server runs without sync workers, which is the configuration for running the replication-manager. flag: --num-sync-workers env: ZERO\\_NUM\\_SYNC\\_WORKERS required: false Per User Mutation Limit Max The maximum mutations per user within the specified windowMs. flag: --per-user-mutation-limit-max env: ZERO\\_PER\\_USER\\_MUTATION\\_LIMIT\\_MAX required: false Per User Mutation Limit Window (ms) The sliding window over which the perUserMutationLimitMax is enforced. flag: --per-user-mutation-limit-window-ms env: ZERO\\_PER\\_USER\\_MUTATION\\_LIMIT\\_WINDOW\\_MS default: 60000 Port The port for sync connections. flag: --port env: ZERO\\_PORT default: 4848 Push API Key An optional secret used to authorize zero-cache to call the API server handling writes. flag: --push-api-key env: ZERO\\_PUSH\\_API\\_KEY required: false Push Forward Cookies If true, zero-cache will forward cookies from the request. This is useful for passing authentication cookies to the API server. If false, cookies are not forwarded. flag: --push-forward-cookies env: ZERO\\_PUSH\\_FORWARD\\_COOKIES default: false Push URL The URL of the API server to which zero-cache will push custom mutations. Can also be a pattern, or set of patterns, which is used in conjunction with the push.url paramter of the Zero constructor. In this case, the pattern specifies the URLs which Zero will allow the constructor to specify. Examples: https://\\*.example.com matches https://api.example.com and https://www.example.com https://\\*.example.com does not match https://example.com (no subdomain) https://\\*.example.com does not match https://api.example.com/path (no trailing path) https://\\*.\\*.example.com matches https://api.v1.example.com and https://www.v2.example.com https://\\*.\\*.example.com does not match https://api.example.com (only one subdomain) Currently, wildcards are only allowed for subdomains. flag: --push-url env: ZERO\\_PUSH\\_URL required: false Query Hydration Stats Track and log the number of rows considered by query hydrations which take longer than log-slow-hydrate-threshold milliseconds. This is useful for debugging and performance tuning. flag: --query-hydration-stats env: ZERO\\_QUERY\\_HYDRATION\\_STATS required: false Replica Vacuum Interval Hours Performs a VACUUM at server startup if the specified number of hours has elapsed since the last VACUUM (or initial-sync). The VACUUM operation is heavyweight and requires double the size of the db in disk space. If unspecified, VACUUM operations are not performed. flag: --replica-vacuum-interval-hours env: ZERO\\_REPLICA\\_VACUUM\\_INTERVAL\\_HOURS required: false Server Version The version string outputted to logs when the server starts up. flag: --server-version env: ZERO\\_SERVER\\_VERSION required: false Storage DB Temp Dir Temporary directory for IVM operator storage. Leave unset to use os.tmpdir(). flag: --storage-db-tmp-dir env: ZERO\\_STORAGE\\_DB\\_TMP\\_DIR required: false Task ID Globally unique identifier for the zero-cache instance. Setting this to a platform specific task identifier can be useful for debugging. If unspecified, zero-cache will attempt to extract the TaskARN if run from within an AWS ECS container, and otherwise use a random string. flag: --task-id env: ZERO\\_TASK\\_ID required: false Upstream Max Connections The maximum number of connections to open to the upstream database for committing mutations. This is divided evenly amongst sync workers. In addition to this number, zero-cache uses one connection for the replication stream. Note that this number must allow for at least one connection per sync worker, or zero-cache will fail to start. See num-sync-workers. flag: --upstream-max-conns env: ZERO\\_UPSTREAM\\_MAX\\_CONNS default: 20", + "content": "zero-cache is configured either via CLI flag or environment variable. There is no separate zero.config file. You can also see all available flags by running zero-cache --help. Required Flags Auth One of Auth JWK, Auth JWK URL, or Auth Secret must be specified. See Authentication for more details. Replica File File path to the SQLite replica that zero-cache maintains. This can be lost, but if it is, zero-cache will have to re-replicate next time it starts up. flag: --replica-file env: ZERO\\_REPLICA\\_FILE required: true Upstream DB The \"upstream\" authoritative postgres database. In the future we will support other types of upstream besides PG. flag: --upstream-db env: ZERO\\_UPSTREAM\\_DB required: true Optional Flags Admin Password A password used to administer zero-cache server, for example to access the /statz endpoint. flag: --admin-password env: ZERO\\_ADMIN\\_PASSWORD required: false App ID Unique identifier for the app. Multiple zero-cache apps can run on a single upstream database, each of which is isolated from the others, with its own permissions, sharding (future feature), and change/cvr databases. The metadata of an app is stored in an upstream schema with the same name, e.g. zero, and the metadata for each app shard, e.g. client and mutation ids, is stored in the {app-id}\\_{#} schema. (Currently there is only a single \"0\" shard, but this will change with sharding). The CVR and Change data are managed in schemas named {app-id}\\_{shard-num}/cvr and {app-id}\\_{shard-num}/cdc, respectively, allowing multiple apps and shards to share the same database instance (e.g. a Postgres \"cluster\") for CVR and Change management. Due to constraints on replication slot names, an App ID may only consist of lower-case letters, numbers, and the underscore character. Note that this option is used by both zero-cache and zero-deploy-permissions. flag: --app-id env: ZERO\\_APP\\_ID default: zero App Publications Postgres PUBLICATIONs that define the tables and columns to replicate. Publication names may not begin with an underscore, as zero reserves that prefix for internal use. If unspecified, zero-cache will create and use an internal publication that publishes all tables in the public schema, i.e.: CREATE PUBLICATION _{app-id}_public_0 FOR TABLES IN SCHEMA public; Note that once an app has begun syncing data, this list of publications cannot be changed, and zero-cache will refuse to start if a specified value differs from what was originally synced. To use a different set of publications, a new app should be created. flag: --app-publications env: ZERO\\_APP\\_PUBLICATIONS default: \\[] Auth JWK A public key in JWK format used to verify JWTs. Only one of jwk, jwksUrl and secret may be set. flag: --auth-jwk env: ZERO\\_AUTH\\_JWK required: false Auth JWK URL A URL that returns a JWK set used to verify JWTs. Only one of jwk, jwksUrl and secret may be set. flag: --auth-jwks-url env: ZERO\\_AUTH\\_JWKS\\_URL required: false Auto Reset Automatically wipe and resync the replica when replication is halted. This situation can occur for configurations in which the upstream database provider prohibits event trigger creation, preventing the zero-cache from being able to correctly replicate schema changes. For such configurations, an upstream schema change will instead result in halting replication with an error indicating that the replica needs to be reset. When auto-reset is enabled, zero-cache will respond to such situations by shutting down, and when restarted, resetting the replica and all synced clients. This is a heavy-weight operation and can result in user-visible slowness or downtime if compute resources are scarce. flag: --auto-reset env: ZERO\\_AUTO\\_RESET default: true Auth Secret A symmetric key used to verify JWTs. Only one of jwk, jwksUrl and secret may be set. flag: --auth-secret env: ZERO\\_AUTH\\_SECRET required: false Change DB The Postgres database used to store recent replication log entries, in order to sync multiple view-syncers without requiring multiple replication slots on the upstream database. If unspecified, the upstream-db will be used. flag: --change-db env: ZERO\\_CHANGE\\_DB required: false Change Max Connections The maximum number of connections to open to the change database. This is used by the change-streamer for catching up zero-cache replication subscriptions. flag: --change-max-conns env: ZERO\\_CHANGE\\_MAX\\_CONNS default: 5 Change Streamer Mode The mode for running or connecting to the change-streamer: dedicated: runs the change-streamer and shuts down when another change-streamer takes over the replication slot. This is appropriate in a single-node configuration, or for the replication-manager in a multi-node configuration. discover: connects to the change-streamer as internally advertised in the change-db. This is appropriate for the view-syncers in a multi-node flag: --change-streamer-mode env: ZERO\\_CHANGE\\_STREAMER\\_MODE default: dedicated Change Streamer Port The port on which the change-streamer runs. This is an internal protocol between the replication-manager and zero-cache, which runs in the same process in local development. If unspecified, defaults to --port + 1. flag: --change-streamer-port env: ZERO\\_CHANGE\\_STREAMER\\_PORT required: false Change Streamer URI When unset, the zero-cache runs its own replication-manager (i.e. change-streamer). In production, this should be set to the replication-manager URI, which runs a change-streamer on port 4849. flag: --change-streamer-uri env: ZERO\\_CHANGE\\_STREAMER\\_URI required: false CVR DB The Postgres database used to store CVRs. CVRs (client view records) keep track of the data synced to clients in order to determine the diff to send on reconnect. If unspecified, the upstream-db will be used. flag: --cvr-db env: ZERO\\_CVR\\_DB required: false CVR Max Connections The maximum number of connections to open to the CVR database. This is divided evenly amongst sync workers. Note that this number must allow for at least one connection per sync worker, or zero-cache will fail to start. See num-sync-workers. flag: --cvr-max-conns env: ZERO\\_CVR\\_MAX\\_CONNS default: 30 Enable Telemetry Zero collects anonymous telemetry data to help us understand usage. We collect: Zero version Uptime General machine information, like the number of CPUs, OS, CI/CD environment, etc. Information about usage, such as number of queries or mutations processed per hour. This is completely optional and can be disabled at any time. You can also opt-out by setting DO\\_NOT\\_TRACK=1. flag: --enable-telemetry env: ZERO\\_ENABLE\\_TELEMETRY default: true Initial Sync Table Copy Workers The number of parallel workers used to copy tables during initial sync. Each worker copies a single table at a time, fetching rows in batches of initial-sync-row-batch-size. flag: --initial-sync-table-copy-workers env: ZERO\\_INITIAL\\_SYNC\\_TABLE\\_COPY\\_WORKERS default: 5 Lazy Startup Delay starting the majority of zero-cache until first request. This is mainly intended to avoid connecting to Postgres replication stream until the first request is received, which can be useful i.e., for preview instances. Currently only supported in single-node mode. flag: --lazy-startup env: ZERO\\_LAZY\\_STARTUP default: false Litestream Backup URL The location of the litestream backup, usually an s3:// URL. This is only consulted by the replication-manager. view-syncers receive this information from the replication-manager. flag: --litestream-backup-url env: ZERO\\_LITESTREAM\\_BACKUP\\_URL required: false Litestream Checkpoint Threshold MB The size of the WAL file at which to perform an SQlite checkpoint to apply the writes in the WAL to the main database file. Each checkpoint creates a new WAL segment file that will be backed up by litestream. Smaller thresholds may improve read performance, at the expense of creating more files to download when restoring the replica from the backup. flag: --litestream-checkpoint-threshold-mb env: ZERO\\_LITESTREAM\\_CHECKPOINT\\_THRESHOLD\\_MB default: 40 Litestream Config Path Path to the litestream yaml config file. zero-cache will run this with its environment variables, which can be referenced in the file via ${ENV} substitution, for example: ZERO\\_REPLICA\\_FILE for the db Path ZERO\\_LITESTREAM\\_BACKUP\\_LOCATION for the db replica url ZERO\\_LITESTREAM\\_LOG\\_LEVEL for the log Level ZERO\\_LOG\\_FORMAT for the log type flag: --litestream-config-path env: ZERO\\_LITESTREAM\\_CONFIG\\_PATH default: ./src/services/litestream/config.yml Litestream Executable Path to the litestream executable. This option has no effect if litestream-backup-url is unspecified. flag: --litestream-executable env: ZERO\\_LITESTREAM\\_EXECUTABLE required: false Litestream Incremental Backup Interval Minutes The interval between incremental backups of the replica. Shorter intervals reduce the amount of change history that needs to be replayed when catching up a new view-syncer, at the expense of increasing the number of files needed to download for the initial litestream restore. flag: --litestream-incremental-backup-interval-minutes env: ZERO\\_LITESTREAM\\_INCREMENTAL\\_BACKUP\\_INTERVAL\\_MINUTES default: 15 Litestream Multipart Concurrency The number of parts (of size --litestream-multipart-size bytes) to upload or download in parallel when backing up or restoring the snapshot. flag: --litestream-multipart-concurrency env: ZERO\\_LITESTREAM\\_MULTIPART\\_CONCURRENCY default: 48 Litestream Multipart Size The size of each part when uploading or downloading the snapshot with \\--litestream-multipart-concurrency. Note that up to concurrency \\* size bytes of memory are used when backing up or restoring the snapshot. flag: --litestream-multipart-size env: ZERO\\_LITESTREAM\\_MULTIPART\\_SIZE default: 16777216 (16 MiB) Litestream Log Level flag: --litestream-log-level env: ZERO\\_LITESTREAM\\_LOG\\_LEVEL default: warn values: debug, info, warn, error Litestream Port Port on which litestream exports metrics, used to determine the replication watermark up to which it is safe to purge change log records. flag: --litestream-port env: ZERO\\_LITESTREAM\\_PORT default: --port + 2 Litestream Restore Parallelism The number of WAL files to download in parallel when performing the initial restore of the replica from the backup. flag: --litestream-restore-parallelism env: ZERO\\_LITESTREAM\\_RESTORE\\_PARALLELISM default: 48 Litestream Snapshot Backup Interval Hours The interval between snapshot backups of the replica. Snapshot backups make a full copy of the database to a new litestream generation. This improves restore time at the expense of bandwidth. Applications with a large database and low write rate can increase this interval to reduce network usage for backups (litestream defaults to 24 hours). flag: --litestream-snapshot-backup-interval-hours env: ZERO\\_LITESTREAM\\_SNAPSHOT\\_BACKUP\\_INTERVAL\\_HOURS default: 12 Log Format Use text for developer-friendly console logging and json for consumption by structured-logging services. flag: --log-format env: ZERO\\_LOG\\_FORMAT default: \"text\" values: text, json Log IVM Sampling How often to collect IVM metrics. 1 out of N requests will be sampled where N is this value. flag: --log-ivm-sampling env: ZERO\\_LOG\\_IVM\\_SAMPLING default: 5000 Log Level Sets the logging level for the application. flag: --log-level env: ZERO\\_LOG\\_LEVEL default: \"info\" values: debug, info, warn, error Log Slow Hydrate Threshold The number of milliseconds a query hydration must take to print a slow warning. flag: --log-slow-hydrate-threshold env: ZERO\\_LOG\\_SLOW\\_HYDRATE\\_THRESHOLD default: 100 Log Slow Row Threshold The number of ms a row must take to fetch from table-source before it is considered slow. flag: --log-slow-row-threshold env: ZERO\\_LOG\\_SLOW\\_ROW\\_THRESHOLD default: 2 Number of Sync Workers The number of processes to use for view syncing. Leave this unset to use the maximum available parallelism. If set to 0, the server runs without sync workers, which is the configuration for running the replication-manager. flag: --num-sync-workers env: ZERO\\_NUM\\_SYNC\\_WORKERS required: false Per User Mutation Limit Max The maximum mutations per user within the specified windowMs. flag: --per-user-mutation-limit-max env: ZERO\\_PER\\_USER\\_MUTATION\\_LIMIT\\_MAX required: false Per User Mutation Limit Window (ms) The sliding window over which the perUserMutationLimitMax is enforced. flag: --per-user-mutation-limit-window-ms env: ZERO\\_PER\\_USER\\_MUTATION\\_LIMIT\\_WINDOW\\_MS default: 60000 Port The port for sync connections. flag: --port env: ZERO\\_PORT default: 4848 Push API Key An optional secret used to authorize zero-cache to call the API server handling writes. flag: --push-api-key env: ZERO\\_PUSH\\_API\\_KEY required: false Push Forward Cookies If true, zero-cache will forward cookies from the request. This is useful for passing authentication cookies to the API server. If false, cookies are not forwarded. flag: --push-forward-cookies env: ZERO\\_PUSH\\_FORWARD\\_COOKIES default: false Push URL The URL of the API server to which zero-cache will push custom mutations. Can also be a pattern, or set of patterns, which is used in conjunction with the push.url paramter of the Zero constructor. In this case, the pattern specifies the URLs which Zero will allow the constructor to specify. Examples: https://\\*.example.com matches https://api.example.com and https://www.example.com https://\\*.example.com does not match https://example.com (no subdomain) https://\\*.example.com does not match https://api.example.com/path (no trailing path) https://\\*.\\*.example.com matches https://api.v1.example.com and https://www.v2.example.com https://\\*.\\*.example.com does not match https://api.example.com (only one subdomain) Currently, wildcards are only allowed for subdomains. flag: --push-url env: ZERO\\_PUSH\\_URL required: false Query Hydration Stats Track and log the number of rows considered by query hydrations which take longer than log-slow-hydrate-threshold milliseconds. This is useful for debugging and performance tuning. flag: --query-hydration-stats env: ZERO\\_QUERY\\_HYDRATION\\_STATS required: false Replica Vacuum Interval Hours Performs a VACUUM at server startup if the specified number of hours has elapsed since the last VACUUM (or initial-sync). The VACUUM operation is heavyweight and requires double the size of the db in disk space. If unspecified, VACUUM operations are not performed. flag: --replica-vacuum-interval-hours env: ZERO\\_REPLICA\\_VACUUM\\_INTERVAL\\_HOURS required: false Server Version The version string outputted to logs when the server starts up. flag: --server-version env: ZERO\\_SERVER\\_VERSION required: false Storage DB Temp Dir Temporary directory for IVM operator storage. Leave unset to use os.tmpdir(). flag: --storage-db-tmp-dir env: ZERO\\_STORAGE\\_DB\\_TMP\\_DIR required: false Task ID Globally unique identifier for the zero-cache instance. Setting this to a platform specific task identifier can be useful for debugging. If unspecified, zero-cache will attempt to extract the TaskARN if run from within an AWS ECS container, and otherwise use a random string. flag: --task-id env: ZERO\\_TASK\\_ID required: false Upstream Max Connections The maximum number of connections to open to the upstream database for committing mutations. This is divided evenly amongst sync workers. In addition to this number, zero-cache uses one connection for the replication stream. Note that this number must allow for at least one connection per sync worker, or zero-cache will fail to start. See num-sync-workers. flag: --upstream-max-conns env: ZERO\\_UPSTREAM\\_MAX\\_CONNS default: 20", "headings": [] }, { "id": "54-zero-schema", "title": "Zero Schema", "url": "/docs/zero-schema", - "content": "Zero applications have both a database schema (the normal backend database schema that all web apps have) and a Zero schema. The purpose of the Zero schema is to: Provide typesafety for ZQL queries Define first-class relationships between tables Define permissions for access control \\(), }) .primaryKey('id'); ``` Custom JSON Types Use the json helper to define a column that stores a JSON-compatible value: ```tsx import {table, string, json} from '@rocicorp/zero'; const user = table('user') .columns({ id: string(), name: string(), settings: json<{theme: 'light' | 'dark'}>(), }) .primaryKey('id'); ``` Compound Primary Keys Pass multiple columns to primaryKey to define a compound primary key: ```ts const user = table('user') .columns({ orgID: string(), userID: string(), name: string(), }) .primaryKey('orgID', 'userID'); ``` Relationships Use the relationships function to define relationships between tables. Use the one and many helpers to define singular and plural relationships, respectively: ```ts const messageRelationships = relationships(message, ({one, many}) => ({ sender: one({ sourceField: ['senderID'], destField: ['id'], destSchema: user, }), replies: many({ sourceField: ['id'], destSchema: message, destField: ['parentMessageID'], }), })); ``` This creates \"sender\" and \"replies\" relationships that can later be queried with the related ZQL clause: ```ts const messagesWithSenderAndReplies = z.query.messages .related('sender') .related('replies'); ``` This will return an object for each message row. Each message will have a sender field that is a single User object or null, and a replies field that is an array of Message objects. Many-to-Many Relationships You can create many-to-many relationships by chaining the relationship definitions. Assuming issue and label tables, along with an issueLabel junction table, you can define a labels relationship like this: ```ts const issueRelationships = relationships(issue, ({many}) => ({ labels: many( { sourceField: ['id'], destSchema: issueLabel, destField: ['issueID'], }, { sourceField: ['labelID'], destSchema: label, destField: ['id'], }, ), })); ``` Compound Keys Relationships Relationships can traverse compound keys. Imagine a user table with a compound primary key of orgID and userID, and a message table with a related senderOrgID and senderUserID. This can be represented in your schema with: ```ts const messageRelationships = relationships(message, ({one}) => ({ sender: one({ sourceField: ['senderOrgID', 'senderUserID'], destSchema: user, destField: ['orgID', 'userID'], }), })); ``` Circular Relationships Circular relationships are fully supported: ```tsx const commentRelationships = relationships(comment, ({one}) => ({ parent: one({ sourceField: ['parentID'], destSchema: comment, destField: ['id'], }), })); ``` Database Schemas Use createSchema to define the entire Zero schema: ```tsx import {createSchema} from '@rocicorp/zero'; export const schema = createSchema({ tables: [user, medium, message], relationships: [userRelationships, mediumRelationships, messageRelationships], }); ``` Migrations Zero uses TypeScript-style structural typing to detect schema changes and implement smooth migrations. How it Works When the Zero client connects to zero-cache it sends a copy of the schema it was constructed with. zero-cache compares this schema to the one it has, and rejects the connection with a special error code if the schema is incompatible. By default, The Zero client handles this error code by calling location.reload(). The intent is to to get a newer version of the app that has been updated to handle the new server schema. If a reload loop does occur, Zero uses exponential backoff to avoid overloading the server. If you want to delay this reload, you can do so by providing the onUpdateNeeded constructor parameter: ```ts const z = new Zero({ onUpdateNeeded: updateReason => { if (reason.type === 'SchemaVersionNotSupported') { // Do something custom here, like show a banner. // When you're ready, call `location.reload()`. } }, }); ``` If the schema changes while a client is running in a compatible way, zero-cache syncs the schema change to the client so that it's ready when the app reloads and gets new code that needs it. If the schema changes while a client is running in an incompatible way, zero-cache will close the client connection with the same error code as above. Schema Change Process Like other database-backed applications, Zero schema migration generally follow an “expand/migrate/contract” pattern: Implement and run an “expand” migration on the backend that is backwards compatible with existing schemas. Add new rows, tables, as well as any defaults and triggers needed for backwards compatibility. Add any new permissions required for the new tables/columns by running zero-deploy-permissions. Update and deploy the client app to use the new schema. Optionally, after some grace period, implement and run a “contract” migration on the backend, deleting any obsolete rows/tables. Steps 1-3 can generally be done as part of one deploy by your CI pipeline, but step 4 would be weeks later when most open clients have refreshed and gotten new code.", + "content": "Zero applications have both a database schema (the normal backend database schema that all web apps have) and a Zero schema. The purpose of the Zero schema is to: Provide typesafety for ZQL queries Define first-class relationships between tables Define permissions for access control \\(), }) .primaryKey('id'); Custom JSON Types Use the json helper to define a column that stores a JSON-compatible value: import {table, string, json} from '@rocicorp/zero'; const user = table('user') .columns({ id: string(), name: string(), settings: json<{theme: 'light' | 'dark'}>(), }) .primaryKey('id'); Compound Primary Keys Pass multiple columns to primaryKey to define a compound primary key: const user = table('user') .columns({ orgID: string(), userID: string(), name: string(), }) .primaryKey('orgID', 'userID'); Relationships Use the relationships function to define relationships between tables. Use the one and many helpers to define singular and plural relationships, respectively: const messageRelationships = relationships(message, ({one, many}) => ({ sender: one({ sourceField: ['senderID'], destField: ['id'], destSchema: user, }), replies: many({ sourceField: ['id'], destSchema: message, destField: ['parentMessageID'], }), })); This creates \"sender\" and \"replies\" relationships that can later be queried with the related ZQL clause: const messagesWithSenderAndReplies = z.query.messages .related('sender') .related('replies'); This will return an object for each message row. Each message will have a sender field that is a single User object or null, and a replies field that is an array of Message objects. Many-to-Many Relationships You can create many-to-many relationships by chaining the relationship definitions. Assuming issue and label tables, along with an issueLabel junction table, you can define a labels relationship like this: const issueRelationships = relationships(issue, ({many}) => ({ labels: many( { sourceField: ['id'], destSchema: issueLabel, destField: ['issueID'], }, { sourceField: ['labelID'], destSchema: label, destField: ['id'], }, ), })); Compound Keys Relationships Relationships can traverse compound keys. Imagine a user table with a compound primary key of orgID and userID, and a message table with a related senderOrgID and senderUserID. This can be represented in your schema with: const messageRelationships = relationships(message, ({one}) => ({ sender: one({ sourceField: ['senderOrgID', 'senderUserID'], destSchema: user, destField: ['orgID', 'userID'], }), })); Circular Relationships Circular relationships are fully supported: const commentRelationships = relationships(comment, ({one}) => ({ parent: one({ sourceField: ['parentID'], destSchema: comment, destField: ['id'], }), })); Database Schemas Use createSchema to define the entire Zero schema: import {createSchema} from '@rocicorp/zero'; export const schema = createSchema({ tables: [user, medium, message], relationships: [userRelationships, mediumRelationships, messageRelationships], }); Migrations Zero uses TypeScript-style structural typing to detect schema changes and implement smooth migrations. How it Works When the Zero client connects to zero-cache it sends a copy of the schema it was constructed with. zero-cache compares this schema to the one it has, and rejects the connection with a special error code if the schema is incompatible. By default, The Zero client handles this error code by calling location.reload(). The intent is to to get a newer version of the app that has been updated to handle the new server schema. If a reload loop does occur, Zero uses exponential backoff to avoid overloading the server. If you want to delay this reload, you can do so by providing the onUpdateNeeded constructor parameter: const z = new Zero({ onUpdateNeeded: updateReason => { if (reason.type === 'SchemaVersionNotSupported') { // Do something custom here, like show a banner. // When you're ready, call `location.reload()`. } }, }); If the schema changes while a client is running in a compatible way, zero-cache syncs the schema change to the client so that it's ready when the app reloads and gets new code that needs it. If the schema changes while a client is running in an incompatible way, zero-cache will close the client connection with the same error code as above. Schema Change Process Like other database-backed applications, Zero schema migration generally follow an “expand/migrate/contract” pattern: Implement and run an “expand” migration on the backend that is backwards compatible with existing schemas. Add new rows, tables, as well as any defaults and triggers needed for backwards compatibility. Add any new permissions required for the new tables/columns by running zero-deploy-permissions. Update and deploy the client app to use the new schema. Optionally, after some grace period, implement and run a “contract” migration on the backend, deleting any obsolete rows/tables. Steps 1-3 can generally be done as part of one deploy by your CI pipeline, but step 4 would be weeks later when most open clients have refreshed and gotten new code.", "headings": [] }, { "id": "55-zql-on-the-server", "title": "ZQL on the Server", "url": "/docs/zql-on-the-server", - "content": "Custom Mutators use ZQL on the server as an implementation detail, but you can also use ZQL on the server directly, outside of Custom Mutators. This is useful for a variety of reasons: You can use ZQL to implement standard REST endpoints, allowing you to share code with custom mutators. You can use ZQL as part of schema migrations. In the future (but not yet implemented), this can support server-side rendering Here's a basic example: ```ts import { PushProcessor, ZQLDatabase, PostgresJSConnection, TransactionProviderInput, } from '@rocicorp/zero/pg'; const db = new ZQLDatabase( new PostgresJSConnection( postgres( must( process.env.ZERO_UPSTREAM_DB as string, 'required env var ZERO_UPSTREAM_DB', ), ), ), schema, ); // This is needed temporarily and will be cleaned up in the future. const dummyTransactionInput: TransactionProviderInput = { clientGroupID: 'unused', clientID: 'unused', mutationID: 42, upstreamSchema: 'unused', }; db.transaction(async tx => { // await tx.mutate... // await tx.query... // await myMutator(tx, ...args); }, dummyTransactionInput); ``` If ZQL does not have the featuers you need, you can use tx.dbTransaction to drop down to raw SQL. Custom Database Connection Zero only provides an adapter for postgres.js. It is possible to write your own adatapter by implementing DBTransaction and DBConnection. Node Postgres Here is an example for node-postgres by Jökull Sólberg (full example) ```ts import {Client, type ClientBase} from 'pg'; class PgConnection implements DBConnection { readonly #client: ClientBase; constructor(client: ClientBase) { this.#client = client; } async query(sql: string, params: unknown[]): Promise { const result = await this.#client.query(sql, params as JSONValue[]); return result.rows; } async transaction( fn: (tx: DBTransaction) => Promise, ): Promise { if (!(this.#client instanceof Client)) { throw new Error('Transactions require a non-pooled Client instance'); } const tx = new PgTransaction(this.#client); try { await this.#client.query('BEGIN'); const result = await fn(tx); await this.#client.query('COMMIT'); return result; } catch (error) { await this.#client.query('ROLLBACK'); throw error; } } } class PgTransaction implements DBTransaction { readonly wrappedTransaction: ClientBase; constructor(client: ClientBase) { this.wrappedTransaction = client; } async query(sql: string, params: unknown[]): Promise { const result = await this.wrappedTransaction.query( sql, params as JSONValue[], ); return result.rows; } } // Then you can use it just like postgres.js const client = new Client({ connectionString: process.env.ZERO_UPSTREAM_DB, }); await client.connect(); const db = new ZQLDatabase(new PgConnection(client), schema); ``` Drizzle ORM It is also possible to use ORMs like Drizzle. Wrap the drizzle transaction and now you can access drizzle's transaction within custom mutators. Blog post and full example by Jökull Sólberg (again 🙌) ```ts // Assuming $client is the raw pg.PoolClient, this type matches how // `drizzle()` inits when using `node-postgres` type Drizzle = NodePgDatabase & {$client: PoolClient}; // Extract the Drizzle-specific transaction type type DrizzleTransaction = Parameters[0]>[0]; class DrizzleConnection implements DBConnection { drizzle: Drizzle; constructor(drizzle: Drizzle) { this.drizzle = drizzle; } // `query` is used by Zero's ZQLDatabase for ZQL reads on the server query(sql: string, params: unknown[]): Promise { return this.drizzle.$client .query(sql, params) .then(({rows}) => rows); } // `transaction` wraps Drizzle's transaction transaction( fn: (tx: DBTransaction) => Promise, ): Promise { return this.drizzle.transaction(drizzleTx => // Pass a new Zero DBTransaction wrapper around Drizzle's one fn(new ZeroDrizzleTransaction(drizzleTx)), ); } } class ZeroDrizzleTransaction implements DBTransaction { readonly wrappedTransaction: DrizzleTransaction; constructor(drizzleTx: DrizzleTransaction) { this.wrappedTransaction = drizzleTx; } // This `query` method would be used if ZQL reads happen *within* // a custom mutator that is itself running inside this wrapped transaction. query(sql: string, params: unknown[]): Promise { // Drizzle's transaction object might hide the raw client, // this is one way to get at it for `pg` driver. Adjust if needed. const session = this.wrappedTransaction._.session as unknown as { client: Drizzle['$client']; }; return session.client .query(sql, params) .then(({rows}) => rows); } } ``` SSR Although you can run ZQL on the server, Zero does not yet have the wiring setup in its bindings layers to support server-side rendering (patches welcome though!). For now, you should use your framework's recommended pattern to prevent SSR execution. Next.js Add the use client directive. SolidStart Wrap components that use Zero with the clientOnly higher-order component. The standard clientOnly pattern uses dynamic imports, but note that this approach (similar to React's lazy) works with any function returning a Promise<{default: () => JSX.Element}>. If code splitting is unnecessary, you can skip the dynamic import. TanStack Start Use React's lazy for dynamic imports.", + "content": "Custom Mutators use ZQL on the server as an implementation detail, but you can also use ZQL on the server directly, outside of Custom Mutators. This is useful for a variety of reasons: You can use ZQL to implement standard REST endpoints, allowing you to share code with custom mutators. You can use ZQL as part of schema migrations. In the future (but not yet implemented), this can support server-side rendering Here's a basic example: import { PushProcessor, ZQLDatabase, PostgresJSConnection, TransactionProviderInput, } from '@rocicorp/zero/pg'; const db = new ZQLDatabase( new PostgresJSConnection( postgres( must( process.env.ZERO_UPSTREAM_DB as string, 'required env var ZERO_UPSTREAM_DB', ), ), ), schema, ); // This is needed temporarily and will be cleaned up in the future. const dummyTransactionInput: TransactionProviderInput = { clientGroupID: 'unused', clientID: 'unused', mutationID: 42, upstreamSchema: 'unused', }; db.transaction(async tx => { // await tx.mutate... // await tx.query... // await myMutator(tx, ...args); }, dummyTransactionInput); If ZQL does not have the featuers you need, you can use tx.dbTransaction to drop down to raw SQL. Custom Database Connection Zero only provides an adapter for postgres.js. It is possible to write your own adatapter by implementing DBTransaction and DBConnection. Node Postgres Here is an example for node-postgres by Jökull Sólberg (full example) import {Client, type ClientBase} from 'pg'; class PgConnection implements DBConnection { readonly #client: ClientBase; constructor(client: ClientBase) { this.#client = client; } async query(sql: string, params: unknown[]): Promise { const result = await this.#client.query(sql, params as JSONValue[]); return result.rows; } async transaction( fn: (tx: DBTransaction) => Promise, ): Promise { if (!(this.#client instanceof Client)) { throw new Error('Transactions require a non-pooled Client instance'); } const tx = new PgTransaction(this.#client); try { await this.#client.query('BEGIN'); const result = await fn(tx); await this.#client.query('COMMIT'); return result; } catch (error) { await this.#client.query('ROLLBACK'); throw error; } } } class PgTransaction implements DBTransaction { readonly wrappedTransaction: ClientBase; constructor(client: ClientBase) { this.wrappedTransaction = client; } async query(sql: string, params: unknown[]): Promise { const result = await this.wrappedTransaction.query( sql, params as JSONValue[], ); return result.rows; } } // Then you can use it just like postgres.js const client = new Client({ connectionString: process.env.ZERO_UPSTREAM_DB, }); await client.connect(); const db = new ZQLDatabase(new PgConnection(client), schema); Drizzle ORM It is also possible to use ORMs like Drizzle. Wrap the drizzle transaction and now you can access drizzle's transaction within custom mutators. Blog post and full example by Jökull Sólberg (again 🙌) // Assuming $client is the raw pg.PoolClient, this type matches how // `drizzle()` inits when using `node-postgres` type Drizzle = NodePgDatabase & {$client: PoolClient}; // Extract the Drizzle-specific transaction type type DrizzleTransaction = Parameters[0]>[0]; class DrizzleConnection implements DBConnection { drizzle: Drizzle; constructor(drizzle: Drizzle) { this.drizzle = drizzle; } // `query` is used by Zero's ZQLDatabase for ZQL reads on the server query(sql: string, params: unknown[]): Promise { return this.drizzle.$client .query(sql, params) .then(({rows}) => rows); } // `transaction` wraps Drizzle's transaction transaction( fn: (tx: DBTransaction) => Promise, ): Promise { return this.drizzle.transaction(drizzleTx => // Pass a new Zero DBTransaction wrapper around Drizzle's one fn(new ZeroDrizzleTransaction(drizzleTx)), ); } } class ZeroDrizzleTransaction implements DBTransaction { readonly wrappedTransaction: DrizzleTransaction; constructor(drizzleTx: DrizzleTransaction) { this.wrappedTransaction = drizzleTx; } // This `query` method would be used if ZQL reads happen *within* // a custom mutator that is itself running inside this wrapped transaction. query(sql: string, params: unknown[]): Promise { // Drizzle's transaction object might hide the raw client, // this is one way to get at it for `pg` driver. Adjust if needed. const session = this.wrappedTransaction._.session as unknown as { client: Drizzle['$client']; }; return session.client .query(sql, params) .then(({rows}) => rows); } } SSR Although you can run ZQL on the server, Zero does not yet have the wiring setup in its bindings layers to support server-side rendering (patches welcome though!). For now, you should use your framework's recommended pattern to prevent SSR execution. Next.js Add the use client directive. SolidStart Wrap components that use Zero with the clientOnly higher-order component. The standard clientOnly pattern uses dynamic imports, but note that this approach (similar to React's lazy) works with any function returning a Promise<{default: () => JSX.Element}>. If code splitting is unnecessary, you can skip the dynamic import. TanStack Start Use React's lazy for dynamic imports.", "headings": [] } ] \ No newline at end of file diff --git a/components/CodeBlock.tsx b/components/CodeBlock.tsx index 1dea76c7..35324a30 100644 --- a/components/CodeBlock.tsx +++ b/components/CodeBlock.tsx @@ -1,6 +1,6 @@ 'use client'; -import React, {useEffect} from 'react'; +import React from 'react'; import hljs from 'highlight.js'; type CodeBlockProps = { diff --git a/components/search.tsx b/components/search.tsx index edc7807d..82a01695 100644 --- a/components/search.tsx +++ b/components/search.tsx @@ -143,7 +143,7 @@ export default function Search() { const doc = searchDocs.find(d => d.id === ref); if (!doc) return null; - let snippet = extractSnippet(doc.content, sanitizedInput); + const snippet = extractSnippet(doc.content, sanitizedInput); const snippetIndex = doc.content .toLowerCase() @@ -224,7 +224,7 @@ export default function Search() { }, 20); return () => clearTimeout(delayDebounce); - }, [searchedInput]); + }, [searchedInput, lunrIndex]); // Toggle the menu when ⌘K is pressed useHotkeys( @@ -333,13 +333,13 @@ const PreloadCurrentItem = () => { const activeItem = useMemo(() => { return searchDocs.find(item => item.id === value); - }, [value, searchDocs]); + }, [value]); useEffect(() => { if (activeItem) { router.prefetch(activeItem.url); } - }, [activeItem]); + }, [activeItem, router]); return <>; }; diff --git a/components/sublink.tsx b/components/sublink.tsx index fc93f9d8..4dc64fdb 100644 --- a/components/sublink.tsx +++ b/components/sublink.tsx @@ -6,7 +6,6 @@ import { CollapsibleTrigger, } from '@/components/ui/collapsible'; import {SheetClose} from '@/components/ui/sheet'; -import {icons} from '@/lib/icons'; import {EachRoute} from '@/lib/routes-config'; import {cn} from '@/lib/utils'; import {ChevronRight} from 'lucide-react'; diff --git a/components/theme-provider.tsx b/components/theme-provider.tsx index efcca84e..e0f112d6 100644 --- a/components/theme-provider.tsx +++ b/components/theme-provider.tsx @@ -2,7 +2,7 @@ import * as React from 'react'; import {ThemeProvider as NextThemesProvider} from 'next-themes'; -import {type ThemeProviderProps} from 'next-themes/dist/types'; +import type {ThemeProviderProps} from 'next-themes'; export function ThemeProvider({children, ...props}: ThemeProviderProps) { return ( diff --git a/components/ui/ActiveHashLink.tsx b/components/ui/ActiveHashLink.tsx index e9e6b06d..35369e1a 100644 --- a/components/ui/ActiveHashLink.tsx +++ b/components/ui/ActiveHashLink.tsx @@ -1,6 +1,5 @@ 'use client'; -import clsx from 'clsx'; import Link from 'next/link'; import {useEffect, useRef} from 'react'; import useHash from '../hooks/useHash'; diff --git a/lib/generateSearchIndex.ts b/lib/generateSearchIndex.ts index 6e0b13fb..ee3bd0ff 100644 --- a/lib/generateSearchIndex.ts +++ b/lib/generateSearchIndex.ts @@ -5,9 +5,7 @@ import remarkParse from 'remark-parse'; import remarkStringify from 'remark-stringify'; import {unified} from 'unified'; import {visit} from 'unist-util-visit'; -import {page_routes} from './routes-config'; -import {toString} from 'mdast-util-to-string'; -import {Root} from 'mdast'; +import {Nodes, Root} from 'mdast'; import strip from 'strip-markdown'; // Define the root directory where docs are stored @@ -49,11 +47,14 @@ function getAllMDXFiles(dir: string): string[] { function extractHeadings(tree: Root): {text: string; id: string}[] { const headings: {text: string; id: string}[] = []; - visit(tree, 'heading', (node: any) => { - const text = node.children - .filter((child: any) => child.type === 'text') - .map((child: any) => child.value) - .join(''); + visit(tree, 'heading', (node: Nodes) => { + const text = + 'children' in node + ? node.children + .filter((child: Nodes) => child.type === 'text') + .map((child: Nodes) => ('value' in child ? child.value : '')) + .join('') + : ''; // Extract the slug ID from the heading node const id = text @@ -100,10 +101,6 @@ async function extractTextFromMDX(filePath: string): Promise { .replace(/\.mdx$/, ''); const url = `/docs/${pathWithoutExtension}`; - const route = page_routes.find( - route => route.href && url.endsWith(route.href), - ); - const cleanedContent = plainText .replace(/```.*$/gm, '') .replace(/\n+/g, ' ') @@ -114,7 +111,7 @@ async function extractTextFromMDX(filePath: string): Promise { id: `${index++}-${pathWithoutExtension}`, // Use file name as ID title: data.title || pathWithoutExtension, // Use frontmatter title or fallback to path url, - content: plainText.replace(/\n+/g, ' ').replace(/\s+/g, ' ').trim(), + content: cleanedContent, headings, // Include extracted headings with IDs }; } diff --git a/lib/icons.tsx b/lib/icons.tsx index 525470fa..ffc298bf 100644 --- a/lib/icons.tsx +++ b/lib/icons.tsx @@ -17,7 +17,6 @@ import { CopyIcon, Database, Eclipse, - File, FileCode, KeyRound, Link2, diff --git a/lib/routes-config.ts b/lib/routes-config.ts index cb7b2d01..1e7980e6 100644 --- a/lib/routes-config.ts +++ b/lib/routes-config.ts @@ -1,7 +1,5 @@ // for page navigation & to sort on leftbar -import {IconKey} from './icons'; - export type EachRoute = { title: string; href: string | null; From c7fcc2fe318247d51cbb864b76675c99fe73bdeb Mon Sep 17 00:00:00 2001 From: Chase Adams Date: Thu, 7 Aug 2025 16:20:20 -0700 Subject: [PATCH 20/28] fix: others --- next.config.mjs | 5 ----- tsconfig.json | 21 ++++----------------- 2 files changed, 4 insertions(+), 22 deletions(-) diff --git a/next.config.mjs b/next.config.mjs index 0d1124f9..f6b16bf0 100644 --- a/next.config.mjs +++ b/next.config.mjs @@ -12,11 +12,6 @@ const nextConfig = { destination: '/docs/introduction', permanent: false, }, - { - source: '/docs/schema-migration', - destination: '/docs/zero-schema/#migrations', - permanent: true, - }, ]; }, }; diff --git a/tsconfig.json b/tsconfig.json index d81d4ee1..64c21044 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,10 +1,6 @@ { "compilerOptions": { - "lib": [ - "dom", - "dom.iterable", - "esnext" - ], + "lib": ["dom", "dom.iterable", "esnext"], "allowJs": true, "skipLibCheck": true, "strict": true, @@ -22,19 +18,10 @@ } ], "paths": { - "@/*": [ - "./*" - ] + "@/*": ["./*"] }, "target": "ES2017" }, - "include": [ - "next-env.d.ts", - "**/*.ts", - "**/*.tsx", - ".next/types/**/*.ts" - ], - "exclude": [ - "node_modules" - ] + "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], + "exclude": ["node_modules"] } From 44501baf147848bb9c5c9f7161f8a7b10538525b Mon Sep 17 00:00:00 2001 From: Chase Adams Date: Thu, 7 Aug 2025 16:37:09 -0700 Subject: [PATCH 21/28] fix: update release notes to be included in static pages --- app/docs/[[...slug]]/page.tsx | 4 +-- lib/get-slugs.ts | 50 +++++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+), 2 deletions(-) create mode 100644 lib/get-slugs.ts diff --git a/app/docs/[[...slug]]/page.tsx b/app/docs/[[...slug]]/page.tsx index 8ed800ac..ea7103be 100644 --- a/app/docs/[[...slug]]/page.tsx +++ b/app/docs/[[...slug]]/page.tsx @@ -1,10 +1,10 @@ import Toc from '@/components/toc'; import Pagination from '@/components/Pagination'; -import {page_routes} from '@/lib/routes-config'; import {notFound} from 'next/navigation'; import {getDocsForSlug, getDocsTocs, getPreviousNext} from '@/lib/markdown'; import {Typography} from '@/components/typography'; import CopyContent from '@/components/ui/copy-content'; +import {getAllPageSlugs} from '@/lib/get-slugs'; type PageProps = {params: Promise<{slug: string[]}>}; @@ -72,5 +72,5 @@ export async function generateMetadata({params}: PageProps) { } export function generateStaticParams() { - return page_routes.map(item => ({slug: item.href.split('/').slice(1)})); + return getAllPageSlugs(); } diff --git a/lib/get-slugs.ts b/lib/get-slugs.ts new file mode 100644 index 00000000..b38af4ac --- /dev/null +++ b/lib/get-slugs.ts @@ -0,0 +1,50 @@ +import fs from 'fs'; +import path from 'path'; +import {page_routes} from './routes-config'; + +export type StaticParam = {slug: string[]}; + +/** + * Returns all static params (slug arrays) for docs pages, including all routes from `page_routes` + * and one entry per release note file under `contents/docs/release-notes/*.mdx` + */ +export const getAllPageSlugs = (): StaticParam[] => { + const releaseNotesDir = path.join( + process.cwd(), + 'contents/docs/release-notes', + ); + + const releaseNotesFiles = fs.existsSync(releaseNotesDir) + ? fs + .readdirSync(releaseNotesDir) + .filter(name => name.toLowerCase().endsWith('.mdx')) + : []; + + const releaseNotesIndex: StaticParam[] = releaseNotesFiles.includes( + 'index.mdx', + ) + ? [{slug: ['release-notes']}] + : []; + + const releaseNotesSlugs: StaticParam[] = releaseNotesFiles + .filter(name => name !== 'index.mdx') + .map(file => ({slug: ['release-notes', file.replace(/\.mdx$/, '')]})); + + const routeSlugs: StaticParam[] = page_routes + .map(item => ({slug: item.href.split('/').slice(1)})) + .filter(p => p.slug.length > 0); + + const merged: StaticParam[] = [ + ...routeSlugs, + ...releaseNotesIndex, + ...releaseNotesSlugs, + ]; + + const seen = new Set(); + return merged.filter(param => { + const key = param.slug.join('/'); + if (seen.has(key)) return false; + seen.add(key); + return true; + }); +}; From a66d608d95e06a76366a2115aa500d0abc2734ce Mon Sep 17 00:00:00 2001 From: Chase Adams Date: Thu, 7 Aug 2025 16:43:11 -0700 Subject: [PATCH 22/28] fix: shared code --- lib/generateSearchIndex.ts | 9 ++++--- lib/get-slugs.ts | 53 +++++++++++++------------------------- 2 files changed, 24 insertions(+), 38 deletions(-) diff --git a/lib/generateSearchIndex.ts b/lib/generateSearchIndex.ts index ee3bd0ff..6c1edac7 100644 --- a/lib/generateSearchIndex.ts +++ b/lib/generateSearchIndex.ts @@ -24,7 +24,7 @@ interface SearchDocument { /** * Recursively find all `index.mdx` files in subdirectories */ -function getAllMDXFiles(dir: string): string[] { +export function getAllMDXFiles(dir: string): string[] { let files: string[] = []; fs.readdirSync(dir, {withFileTypes: true}).forEach(entry => { @@ -129,5 +129,8 @@ async function generateSearchIndex() { console.log(`✅ Search index generated: ${OUTPUT_FILE}`); } -// Run the script -generateSearchIndex().catch(console.error); +// Run the script only when explicitly enabled to avoid side effects on import +if (process.env.GENERATE_SEARCH_INDEX === 'true') { + // eslint-disable-next-line no-console + generateSearchIndex().catch(console.error); +} diff --git a/lib/get-slugs.ts b/lib/get-slugs.ts index b38af4ac..049ba2e2 100644 --- a/lib/get-slugs.ts +++ b/lib/get-slugs.ts @@ -1,48 +1,31 @@ -import fs from 'fs'; import path from 'path'; -import {page_routes} from './routes-config'; +import {getAllMDXFiles} from './generateSearchIndex'; export type StaticParam = {slug: string[]}; /** - * Returns all static params (slug arrays) for docs pages, including all routes from `page_routes` - * and one entry per release note file under `contents/docs/release-notes/*.mdx` + * Returns all static params (slug arrays) for docs pages - all files under `contents/docs/*.mdx` */ export const getAllPageSlugs = (): StaticParam[] => { - const releaseNotesDir = path.join( - process.cwd(), - 'contents/docs/release-notes', - ); - - const releaseNotesFiles = fs.existsSync(releaseNotesDir) - ? fs - .readdirSync(releaseNotesDir) - .filter(name => name.toLowerCase().endsWith('.mdx')) - : []; - - const releaseNotesIndex: StaticParam[] = releaseNotesFiles.includes( - 'index.mdx', - ) - ? [{slug: ['release-notes']}] - : []; - - const releaseNotesSlugs: StaticParam[] = releaseNotesFiles - .filter(name => name !== 'index.mdx') - .map(file => ({slug: ['release-notes', file.replace(/\.mdx$/, '')]})); - - const routeSlugs: StaticParam[] = page_routes - .map(item => ({slug: item.href.split('/').slice(1)})) + const DOCS_ROOT = path.join(process.cwd(), 'contents/docs'); + const files = getAllMDXFiles(DOCS_ROOT); + + const params: StaticParam[] = files + .map(fullPath => path.relative(DOCS_ROOT, fullPath)) + .map(relPath => { + if (relPath.toLowerCase().endsWith('/index.mdx')) { + const withoutIndex = relPath.replace(/\/index\.mdx$/i, ''); + const segments = withoutIndex === '' ? [] : withoutIndex.split('/'); + return {slug: segments}; + } + const withoutExt = relPath.replace(/\.mdx$/i, ''); + return {slug: withoutExt.split('/')}; + }) .filter(p => p.slug.length > 0); - const merged: StaticParam[] = [ - ...routeSlugs, - ...releaseNotesIndex, - ...releaseNotesSlugs, - ]; - const seen = new Set(); - return merged.filter(param => { - const key = param.slug.join('/'); + return params.filter(p => { + const key = p.slug.join('/'); if (seen.has(key)) return false; seen.add(key); return true; From 86bd2eac9cd85aac267669667b5e93a2ae7d168b Mon Sep 17 00:00:00 2001 From: Chase Adams Date: Thu, 7 Aug 2025 16:56:01 -0700 Subject: [PATCH 23/28] fix: build --- assets/search-index.json | 4 ++-- lib/generateSearchIndex.ts | 28 +++------------------------- lib/get-slugs.ts | 24 ++++++++++++++++++++++-- package.json | 2 +- 4 files changed, 28 insertions(+), 30 deletions(-) diff --git a/assets/search-index.json b/assets/search-index.json index 368ca0c5..80e4c990 100644 --- a/assets/search-index.json +++ b/assets/search-index.json @@ -308,9 +308,9 @@ "headings": [] }, { - "id": "44-release-notes/index", + "id": "44-release-notes", "title": "Release Notes", - "url": "/docs/release-notes/index", + "url": "/docs/release-notes", "content": "Zero 0.22: Simplified TTLs Zero 0.21: PG arrays, TanStack starter, and more Zero 0.20: Full Supabase support, performance improvements Zero 0.19: Many, many bugfixes and cleanups Zero 0.18: Custom Mutators Zero 0.17: Background Queries Zero 0.16: Lambda-Based Permission Deployment Zero 0.15: Live Permission Updates Zero 0.14: Name Mapping and Multischema Zero 0.13: Multinode and SST Zero 0.12: Circular Relationships Zero 0.11: Windows Zero 0.10: Remove Top-Level Await Zero 0.9: JWK Support Zero 0.8: Schema Autobuild, Result Types, and Enums Zero 0.7: Read Perms and Docker Zero 0.6: Relationship Filters Zero 0.5: JSON Columns Zero 0.4: Compound Filters Zero 0.3: Schema Migrations and Write Perms Zero 0.2: Skip Mode and Computed PKs Zero 0.1: First Release", "headings": [] }, diff --git a/lib/generateSearchIndex.ts b/lib/generateSearchIndex.ts index 6c1edac7..c1fa3931 100644 --- a/lib/generateSearchIndex.ts +++ b/lib/generateSearchIndex.ts @@ -7,6 +7,7 @@ import {unified} from 'unified'; import {visit} from 'unist-util-visit'; import {Nodes, Root} from 'mdast'; import strip from 'strip-markdown'; +import {getAllMDXFiles} from './get-slugs'; // Define the root directory where docs are stored const DOCS_ROOT = path.join(process.cwd(), 'contents/docs'); @@ -21,26 +22,6 @@ interface SearchDocument { headings: {text: string; id: string}[]; } -/** - * Recursively find all `index.mdx` files in subdirectories - */ -export function getAllMDXFiles(dir: string): string[] { - let files: string[] = []; - - fs.readdirSync(dir, {withFileTypes: true}).forEach(entry => { - const fullPath = path.join(dir, entry.name); - - if (entry.isDirectory()) { - // If it's a directory, recurse into it - files = files.concat(getAllMDXFiles(fullPath)); - } else if (entry.isFile() && entry.name.endsWith('.mdx')) { - files.push(fullPath); - } - }); - - return files; -} - /** * Extract headings with IDs from MDX content */ @@ -98,6 +79,7 @@ async function extractTextFromMDX(filePath: string): Promise { // Derive a URL from the file name const pathWithoutExtension = path .relative(DOCS_ROOT, filePath) + .replace(/\/index\.mdx$/, '') .replace(/\.mdx$/, ''); const url = `/docs/${pathWithoutExtension}`; @@ -129,8 +111,4 @@ async function generateSearchIndex() { console.log(`✅ Search index generated: ${OUTPUT_FILE}`); } -// Run the script only when explicitly enabled to avoid side effects on import -if (process.env.GENERATE_SEARCH_INDEX === 'true') { - // eslint-disable-next-line no-console - generateSearchIndex().catch(console.error); -} +generateSearchIndex().catch(console.error); diff --git a/lib/get-slugs.ts b/lib/get-slugs.ts index 049ba2e2..510e4965 100644 --- a/lib/get-slugs.ts +++ b/lib/get-slugs.ts @@ -1,10 +1,10 @@ import path from 'path'; -import {getAllMDXFiles} from './generateSearchIndex'; +import fs from 'fs'; export type StaticParam = {slug: string[]}; /** - * Returns all static params (slug arrays) for docs pages - all files under `contents/docs/*.mdx` + * Returns all static params (slug arrays) for docs pages all files under `contents/docs/*.mdx` */ export const getAllPageSlugs = (): StaticParam[] => { const DOCS_ROOT = path.join(process.cwd(), 'contents/docs'); @@ -31,3 +31,23 @@ export const getAllPageSlugs = (): StaticParam[] => { return true; }); }; + +/** + * Recursively find all `*.mdx` files in subdirectories + */ +export function getAllMDXFiles(dir: string): string[] { + let files: string[] = []; + + fs.readdirSync(dir, {withFileTypes: true}).forEach(entry => { + const fullPath = path.join(dir, entry.name); + + if (entry.isDirectory()) { + // If it's a directory, recurse into it + files = files.concat(getAllMDXFiles(fullPath)); + } else if (entry.isFile() && entry.name.endsWith('.mdx')) { + files.push(fullPath); + } + }); + + return files; +} \ No newline at end of file diff --git a/package.json b/package.json index 6f8a1df1..16f317ea 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "name": "aria-docs", + "name": "@rocicorp/zero-docs", "version": "1.0.0", "private": true, "scripts": { From 72aced3c425d5d556958ac532ec449d72722aeac Mon Sep 17 00:00:00 2001 From: miguelrk Date: Fri, 8 Aug 2025 16:34:51 +0200 Subject: [PATCH 24/28] Adds guide on deploying `zero-cache` to Sevalla.com This pull request adds a new section to the deployment documentation for `zero-cache`, providing a step-by-step guide on how to deploy it to Sevalla.com. This is analogous to the existing Fly.io guide and offers an alternative for users. The guide covers setting up the Sevalla app, configuring environment variables, setting up the persistent disk, and ensuring the correct networking and memory settings for a successful deployment. It also includes a reference to the Dockerfile used. See original [thread](https://discord.com/channels/830183651022471199/1401968889620987915). --- contents/docs/deployment.mdx | 41 ++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/contents/docs/deployment.mdx b/contents/docs/deployment.mdx index 1cc55569..3b51391c 100644 --- a/contents/docs/deployment.mdx +++ b/contents/docs/deployment.mdx @@ -438,6 +438,47 @@ Explaining the arguments above -- - `ZERO_AUTH_SECRET` - The secret to create and verify JWTs. This is the same secret that was used when deploying zero-cache to fly. - `VITE_PUBLIC_SERVER` - The URL the frontend will call to talk to the zero-cache server. This is the URL of the fly app. +## Guide: Single-Node on Sevalla.com + +Let's deploy a single-node `zero-cache` to [Sevalla](https://sevalla.com). Sevalla provides a simple, Heroku-like developer experience (DX) for deploying Docker containers. It is a good alternative to Fly.io for single-node deployments. + +Note that this guide assumes you already have a PostgreSQL (upstream) database available at `ZERO_UPSTREAM_DB`. + +--- + +### Create a Sevalla application + +First, [create a new application](https://docs.sevalla.com/applications/create) on Sevalla using the official [Docker image](https://hub.docker.com/r/rocicorp/zero). + + + **Note:** `zero-cache` can be memory intensive during startup, especially when dealing with a large database. The recommended memory allocation for a single-node setup is **2GB**. Sevalla's M1 plan (2GB RAM) has been verified to work. + + +### Configure environment variables + +Sevalla lets you configure environment variables through its dashboard. You'll need to set the following: + +- `ZERO_UPSTREAM_DB`: Your upstream Postgres database connection string. +- `ZERO_REPLICA_FILE`: Set this to `./sync-replica.db` to store the replica file in the application's working directory, which is `/opt/app`. +- `ZERO_PUSH_URL`: The URL for your custom mutators, if applicable. +- `ZERO_AUTH_JWKS_URL` or `ZERO_AUTH_SECRET`: Your authentication secrets. +- `LOG_LEVEL`: Set to `debug` for detailed logs. + +### Add a persistent disk (optional) + +`zero-cache` needs a persistent disk to persist its SQLite replica. Add a disk at `/opt/app` to ensure the data is saved across restarts. This is where the replica file, specified by `ZERO_REPLICA_FILE=./sync-replica.db`, will be stored by default. You can always change this, but be sure `ZERO_REPLICA_FILE` is within it. + +### Configure networking and health checks + +`zero-cache` runs on port **4848** in single-node mode. You need to configure Sevalla's networking settings to expose this port. + +Set up the public HTTP traffic to forward to port **4848**. Sevalla's health check will also need to be configured to handle `zero-cache`'s startup time. + +- **Listen:** `80/http` +- **Forward:** `4848/http` +- **Health Check Path:** `/` +- **Start Period:** Since `zero-cache` can take some time to start up, it's crucial to set the health check's `startPeriod` to a higher value (e.g., 300 seconds) to prevent Sevalla from restarting the container prematurely. + ## Guide: Multi-Node on Raw AWS ### S3 Bucket From 22d7e627a0e5c02ec7f192f970182c18547ee90a Mon Sep 17 00:00:00 2001 From: miguelrk Date: Fri, 8 Aug 2025 14:46:05 +0000 Subject: [PATCH 25/28] docs: update guide for deploying to sevalla.com --- contents/docs/deployment.mdx | 69 ++++++++++++++++++++++++------------ 1 file changed, 46 insertions(+), 23 deletions(-) diff --git a/contents/docs/deployment.mdx b/contents/docs/deployment.mdx index 3b51391c..055abe75 100644 --- a/contents/docs/deployment.mdx +++ b/contents/docs/deployment.mdx @@ -440,44 +440,67 @@ Explaining the arguments above -- ## Guide: Single-Node on Sevalla.com -Let's deploy a single-node `zero-cache` to [Sevalla](https://sevalla.com). Sevalla provides a simple, Heroku-like developer experience (DX) for deploying Docker containers. It is a good alternative to Fly.io for single-node deployments. +[Sevalla.com](https://sevalla.com) is a modern Platform as a Service (PaaS) that can be used to deploy `zero-cache` in a single-node configuration, similar to Fly.io. -Note that this guide assumes you already have a PostgreSQL (upstream) database available at `ZERO_UPSTREAM_DB`. +This guide will walk you through deploying `zero-cache` to Sevalla using its web dashboard. ---- +### Setup + +First, create an account on [Sevalla.com](https://sevalla.com). You will also need an upstream Postgres database. You can use any hosted Postgres provider like Supabase or Neon. Ensure you have the connection string handy. + +### 1. Create a New Application + +1. From the Sevalla dashboard, create a new Application. +2. Choose **Deploy from a public Docker image**. +3. For the **Image URL**, enter `rocicorp/zero`. You can append a specific version tag like `rocicorp/zero:0.22.2025080201`, or use `latest` to get the newest version. +4. Click **Continue**. + +### 2. Configure Your Application -### Create a Sevalla application +On the configuration screen, you will set up the necessary resources, networking, and environment variables. -First, [create a new application](https://docs.sevalla.com/applications/create) on Sevalla using the official [Docker image](https://hub.docker.com/r/rocicorp/zero). +#### Resources - - **Note:** `zero-cache` can be memory intensive during startup, especially when dealing with a large database. The recommended memory allocation for a single-node setup is **2GB**. Sevalla's M1 plan (2GB RAM) has been verified to work. +Under the **Resources** section, it is critical to allocate enough memory. `zero-cache` can be memory-intensive during startup. + +- **RAM**: Set to at least **2 GB**. +- **vCPU**: Set to at least **1 vCPU**. + + + **Note:** Running with less than 2GB of RAM may cause the deployment to fail with an Out-Of-Memory (OOM) error (exit code 137). The process may fail silently and enter a restart loop, making it difficult to debug. -### Configure environment variables +#### Storage + +`zero-cache` requires a persistent disk to store the SQLite replica. -Sevalla lets you configure environment variables through its dashboard. You'll need to set the following: +1. Under the **Storage** section, click **Add disk**. +2. **Name** your disk (e.g., `sqlite-db`). +3. Set the **Mount path** to `/opt/app`. This is the working directory inside the `zero-cache` Docker container. +4. Choose a sufficient size (e.g., 5 GB). -- `ZERO_UPSTREAM_DB`: Your upstream Postgres database connection string. -- `ZERO_REPLICA_FILE`: Set this to `./sync-replica.db` to store the replica file in the application's working directory, which is `/opt/app`. -- `ZERO_PUSH_URL`: The URL for your custom mutators, if applicable. -- `ZERO_AUTH_JWKS_URL` or `ZERO_AUTH_SECRET`: Your authentication secrets. -- `LOG_LEVEL`: Set to `debug` for detailed logs. +#### Networking -### Add a persistent disk (optional) +Expose `zero-cache` to the internet so your frontend client can connect to it. -`zero-cache` needs a persistent disk to persist its SQLite replica. Add a disk at `/opt/app` to ensure the data is saved across restarts. This is where the replica file, specified by `ZERO_REPLICA_FILE=./sync-replica.db`, will be stored by default. You can always change this, but be sure `ZERO_REPLICA_FILE` is within it. +1. Under the **Networking** section, ensure the **Web (HTTP)** service is enabled. +2. Set the **Port** to `4848`. This is the default port `zero-cache` listens on in single-node mode. +3. You can leave the other settings at their defaults. Sevalla automatically handles HTTPS termination and WebSocket proxying. -### Configure networking and health checks +#### Environment Variables -`zero-cache` runs on port **4848** in single-node mode. You need to configure Sevalla's networking settings to expose this port. +This is where you'll configure `zero-cache` to connect to your database. -Set up the public HTTP traffic to forward to port **4848**. Sevalla's health check will also need to be configured to handle `zero-cache`'s startup time. +1. Under the **Environment variables** section, add the following variables, replacing them with their corresponding values. +``` +ZERO_UPSTREAM_DB="..." +ZERO_REPLICA_FILE="./sync-replica.db" +ZERO_PUSH_URL="..." +ZERO_AUTH_JWKS_URL="..." # or `ZERO_AUTH_SECRET` alternatively +ZERO_LOG_FORMAT="text" # required by Sevalla.com to properly display logs +``` -- **Listen:** `80/http` -- **Forward:** `4848/http` -- **Health Check Path:** `/` -- **Start Period:** Since `zero-cache` can take some time to start up, it's crucial to set the health check's `startPeriod` to a higher value (e.g., 300 seconds) to prevent Sevalla from restarting the container prematurely. +#### ## Guide: Multi-Node on Raw AWS From 5a37bb129deabb00695efa5bb8ae5121d714eef0 Mon Sep 17 00:00:00 2001 From: miguelrk Date: Fri, 8 Aug 2025 16:54:03 +0200 Subject: [PATCH 26/28] docs: enhance Sevalla deployment guide with additional steps and clarity --- bun.lock | 1808 ++++++++++++++++++++++++++++++++++ contents/docs/deployment.mdx | 36 +- 2 files changed, 1837 insertions(+), 7 deletions(-) create mode 100644 bun.lock diff --git a/bun.lock b/bun.lock new file mode 100644 index 00000000..99cc28dd --- /dev/null +++ b/bun.lock @@ -0,0 +1,1808 @@ +{ + "lockfileVersion": 1, + "workspaces": { + "": { + "name": "aria-docs", + "dependencies": { + "@radix-ui/react-collapsible": "^1.1.11", + "@radix-ui/react-dialog": "^1.1.14", + "@radix-ui/react-dropdown-menu": "^2.1.15", + "@radix-ui/react-scroll-area": "^1.2.9", + "@radix-ui/react-slot": "^1.2.3", + "@radix-ui/react-tooltip": "^1.2.7", + "@vercel/og": "^0.8.5", + "broken-link-checker": "^0.7.8", + "class-variance-authority": "^0.7.1", + "clsx": "^2.1.1", + "cmdk": "^1.1.1", + "gray-matter": "^4.0.3", + "lucide-react": "^0.537.0", + "lunr": "^2.3.9", + "mdast-util-to-string": "^4.0.0", + "next": "^15.4.6", + "next-mdx-remote": "^5.0.0", + "next-themes": "^0.4.6", + "react": "^19.1.1", + "react-dom": "^19.1.1", + "react-hotkeys-hook": "^5.1.0", + "rehype-autolink-headings": "^7.1.0", + "rehype-code-titles": "^1.2.0", + "rehype-prism-plus": "^2.0.1", + "rehype-slug": "^6.0.0", + "remark": "^15.0.1", + "remark-gfm": "^4.0.1", + "remark-parse": "^11.0.0", + "remark-stringify": "^11.0.0", + "strip-markdown": "^6.0.0", + "tailwind-merge": "^3.3.1", + "tailwindcss-animate": "^1.0.7", + "unist-util-visit": "^5.0.0", + }, + "devDependencies": { + "@rocicorp/prettier-config": "^0.3.0", + "@tailwindcss/typography": "^0.5.16", + "@types/hast": "^3.0.4", + "@types/lunr": "^2.3.7", + "@types/node": "^24.2.0", + "@types/react": "^19", + "@types/react-dom": "^19", + "@types/unist": "^3.0.3", + "autoprefixer": "^10.4.21", + "eslint": "^9", + "eslint-config-next": "^15.4.6", + "highlight.js": "^11.11.1", + "postcss": "^8", + "react-highlight": "^0.15.0", + "tailwindcss": "^3.4.10", + "ts-node": "^10.9.2", + "tsx": "^4.20.3", + "typescript": "^5", + }, + }, + }, + "packages": { + "@aashutoshrathi/word-wrap": ["@aashutoshrathi/word-wrap@1.2.6", "", {}, "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA=="], + + "@alloc/quick-lru": ["@alloc/quick-lru@5.2.0", "", {}, "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw=="], + + "@babel/code-frame": ["@babel/code-frame@7.24.7", "", { "dependencies": { "@babel/highlight": "^7.24.7", "picocolors": "^1.0.0" } }, "sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA=="], + + "@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.24.7", "", {}, "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w=="], + + "@babel/highlight": ["@babel/highlight@7.24.7", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.24.7", "chalk": "^2.4.2", "js-tokens": "^4.0.0", "picocolors": "^1.0.0" } }, "sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw=="], + + "@cspotcode/source-map-support": ["@cspotcode/source-map-support@0.8.1", "", { "dependencies": { "@jridgewell/trace-mapping": "0.3.9" } }, "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw=="], + + "@emnapi/core": ["@emnapi/core@1.4.5", "", { "dependencies": { "@emnapi/wasi-threads": "1.0.4", "tslib": "^2.4.0" } }, "sha512-XsLw1dEOpkSX/WucdqUhPWP7hDxSvZiY+fsUC14h+FtQ2Ifni4znbBt8punRX+Uj2JG/uDb8nEHVKvrVlvdZ5Q=="], + + "@emnapi/runtime": ["@emnapi/runtime@1.4.5", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-++LApOtY0pEEz1zrd9vy1/zXVaVJJ/EbAF3u0fXIzPJEDtnITsBGbbK0EkM72amhl/R5b+5xx0Y/QhcVOpuulg=="], + + "@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.0.4", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-PJR+bOmMOPH8AtcTGAyYNiuJ3/Fcoj2XN/gBEWzDIKh254XO+mM9XoXHk5GNEhodxeMznbg7BlRojVbKN+gC6g=="], + + "@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.25.0", "", { "os": "aix", "cpu": "ppc64" }, "sha512-O7vun9Sf8DFjH2UtqK8Ku3LkquL9SZL8OLY1T5NZkA34+wG3OQF7cl4Ql8vdNzM6fzBbYfLaiRLIOZ+2FOCgBQ=="], + + "@esbuild/android-arm": ["@esbuild/android-arm@0.25.0", "", { "os": "android", "cpu": "arm" }, "sha512-PTyWCYYiU0+1eJKmw21lWtC+d08JDZPQ5g+kFyxP0V+es6VPPSUhM6zk8iImp2jbV6GwjX4pap0JFbUQN65X1g=="], + + "@esbuild/android-arm64": ["@esbuild/android-arm64@0.25.0", "", { "os": "android", "cpu": "arm64" }, "sha512-grvv8WncGjDSyUBjN9yHXNt+cq0snxXbDxy5pJtzMKGmmpPxeAmAhWxXI+01lU5rwZomDgD3kJwulEnhTRUd6g=="], + + "@esbuild/android-x64": ["@esbuild/android-x64@0.25.0", "", { "os": "android", "cpu": "x64" }, "sha512-m/ix7SfKG5buCnxasr52+LI78SQ+wgdENi9CqyCXwjVR2X4Jkz+BpC3le3AoBPYTC9NHklwngVXvbJ9/Akhrfg=="], + + "@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.25.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-mVwdUb5SRkPayVadIOI78K7aAnPamoeFR2bT5nszFUZ9P8UpK4ratOdYbZZXYSqPKMHfS1wdHCJk1P1EZpRdvw=="], + + "@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.25.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-DgDaYsPWFTS4S3nWpFcMn/33ZZwAAeAFKNHNa1QN0rI4pUjgqf0f7ONmXf6d22tqTY+H9FNdgeaAa+YIFUn2Rg=="], + + "@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.25.0", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-VN4ocxy6dxefN1MepBx/iD1dH5K8qNtNe227I0mnTRjry8tj5MRk4zprLEdG8WPyAPb93/e4pSgi1SoHdgOa4w=="], + + "@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.25.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-mrSgt7lCh07FY+hDD1TxiTyIHyttn6vnjesnPoVDNmDfOmggTLXRv8Id5fNZey1gl/V2dyVK1VXXqVsQIiAk+A=="], + + "@esbuild/linux-arm": ["@esbuild/linux-arm@0.25.0", "", { "os": "linux", "cpu": "arm" }, "sha512-vkB3IYj2IDo3g9xX7HqhPYxVkNQe8qTK55fraQyTzTX/fxaDtXiEnavv9geOsonh2Fd2RMB+i5cbhu2zMNWJwg=="], + + "@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.25.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-9QAQjTWNDM/Vk2bgBl17yWuZxZNQIF0OUUuPZRKoDtqF2k4EtYbpyiG5/Dk7nqeK6kIJWPYldkOcBqjXjrUlmg=="], + + "@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.25.0", "", { "os": "linux", "cpu": "ia32" }, "sha512-43ET5bHbphBegyeqLb7I1eYn2P/JYGNmzzdidq/w0T8E2SsYL1U6un2NFROFRg1JZLTzdCoRomg8Rvf9M6W6Gg=="], + + "@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.25.0", "", { "os": "linux", "cpu": "none" }, "sha512-fC95c/xyNFueMhClxJmeRIj2yrSMdDfmqJnyOY4ZqsALkDrrKJfIg5NTMSzVBr5YW1jf+l7/cndBfP3MSDpoHw=="], + + "@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.25.0", "", { "os": "linux", "cpu": "none" }, "sha512-nkAMFju7KDW73T1DdH7glcyIptm95a7Le8irTQNO/qtkoyypZAnjchQgooFUDQhNAy4iu08N79W4T4pMBwhPwQ=="], + + "@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.25.0", "", { "os": "linux", "cpu": "ppc64" }, "sha512-NhyOejdhRGS8Iwv+KKR2zTq2PpysF9XqY+Zk77vQHqNbo/PwZCzB5/h7VGuREZm1fixhs4Q/qWRSi5zmAiO4Fw=="], + + "@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.25.0", "", { "os": "linux", "cpu": "none" }, "sha512-5S/rbP5OY+GHLC5qXp1y/Mx//e92L1YDqkiBbO9TQOvuFXM+iDqUNG5XopAnXoRH3FjIUDkeGcY1cgNvnXp/kA=="], + + "@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.25.0", "", { "os": "linux", "cpu": "s390x" }, "sha512-XM2BFsEBz0Fw37V0zU4CXfcfuACMrppsMFKdYY2WuTS3yi8O1nFOhil/xhKTmE1nPmVyvQJjJivgDT+xh8pXJA=="], + + "@esbuild/linux-x64": ["@esbuild/linux-x64@0.25.0", "", { "os": "linux", "cpu": "x64" }, "sha512-9yl91rHw/cpwMCNytUDxwj2XjFpxML0y9HAOH9pNVQDpQrBxHy01Dx+vaMu0N1CKa/RzBD2hB4u//nfc+Sd3Cw=="], + + "@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.25.0", "", { "os": "none", "cpu": "arm64" }, "sha512-RuG4PSMPFfrkH6UwCAqBzauBWTygTvb1nxWasEJooGSJ/NwRw7b2HOwyRTQIU97Hq37l3npXoZGYMy3b3xYvPw=="], + + "@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.25.0", "", { "os": "none", "cpu": "x64" }, "sha512-jl+qisSB5jk01N5f7sPCsBENCOlPiS/xptD5yxOx2oqQfyourJwIKLRA2yqWdifj3owQZCL2sn6o08dBzZGQzA=="], + + "@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.25.0", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-21sUNbq2r84YE+SJDfaQRvdgznTD8Xc0oc3p3iW/a1EVWeNj/SdUCbm5U0itZPQYRuRTW20fPMWMpcrciH2EJw=="], + + "@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.25.0", "", { "os": "openbsd", "cpu": "x64" }, "sha512-2gwwriSMPcCFRlPlKx3zLQhfN/2WjJ2NSlg5TKLQOJdV0mSxIcYNTMhk3H3ulL/cak+Xj0lY1Ym9ysDV1igceg=="], + + "@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.25.0", "", { "os": "sunos", "cpu": "x64" }, "sha512-bxI7ThgLzPrPz484/S9jLlvUAHYMzy6I0XiU1ZMeAEOBcS0VePBFxh1JjTQt3Xiat5b6Oh4x7UC7IwKQKIJRIg=="], + + "@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.25.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-ZUAc2YK6JW89xTbXvftxdnYy3m4iHIkDtK3CLce8wg8M2L+YZhIvO1DKpxrd0Yr59AeNNkTiic9YLf6FTtXWMw=="], + + "@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.25.0", "", { "os": "win32", "cpu": "ia32" }, "sha512-eSNxISBu8XweVEWG31/JzjkIGbGIJN/TrRoiSVZwZ6pkC6VX4Im/WV2cz559/TXLcYbcrDN8JtKgd9DJVIo8GA=="], + + "@esbuild/win32-x64": ["@esbuild/win32-x64@0.25.0", "", { "os": "win32", "cpu": "x64" }, "sha512-ZENoHJBxA20C2zFzh6AI4fT6RraMzjYw4xKWemRTRmRVtN9c5DcH9r/f2ihEkMjOW5eGgrwCslG/+Y/3bL+DHQ=="], + + "@eslint-community/eslint-utils": ["@eslint-community/eslint-utils@4.7.0", "", { "dependencies": { "eslint-visitor-keys": "^3.4.3" }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, "sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw=="], + + "@eslint-community/regexpp": ["@eslint-community/regexpp@4.12.1", "", {}, "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ=="], + + "@eslint/config-array": ["@eslint/config-array@0.21.0", "", { "dependencies": { "@eslint/object-schema": "^2.1.6", "debug": "^4.3.1", "minimatch": "^3.1.2" } }, "sha512-ENIdc4iLu0d93HeYirvKmrzshzofPw6VkZRKQGe9Nv46ZnWUzcF1xV01dcvEg/1wXUR61OmmlSfyeyO7EvjLxQ=="], + + "@eslint/config-helpers": ["@eslint/config-helpers@0.3.0", "", {}, "sha512-ViuymvFmcJi04qdZeDc2whTHryouGcDlaxPqarTD0ZE10ISpxGUVZGZDx4w01upyIynL3iu6IXH2bS1NhclQMw=="], + + "@eslint/core": ["@eslint/core@0.15.1", "", { "dependencies": { "@types/json-schema": "^7.0.15" } }, "sha512-bkOp+iumZCCbt1K1CmWf0R9pM5yKpDv+ZXtvSyQpudrI9kuFLp+bM2WOPXImuD/ceQuaa8f5pj93Y7zyECIGNA=="], + + "@eslint/eslintrc": ["@eslint/eslintrc@3.3.1", "", { "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", "espree": "^10.0.1", "globals": "^14.0.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", "js-yaml": "^4.1.0", "minimatch": "^3.1.2", "strip-json-comments": "^3.1.1" } }, "sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ=="], + + "@eslint/js": ["@eslint/js@9.32.0", "", {}, "sha512-BBpRFZK3eX6uMLKz8WxFOBIFFcGFJ/g8XuwjTHCqHROSIsopI+ddn/d5Cfh36+7+e5edVS8dbSHnBNhrLEX0zg=="], + + "@eslint/object-schema": ["@eslint/object-schema@2.1.6", "", {}, "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA=="], + + "@eslint/plugin-kit": ["@eslint/plugin-kit@0.3.4", "", { "dependencies": { "@eslint/core": "^0.15.1", "levn": "^0.4.1" } }, "sha512-Ul5l+lHEcw3L5+k8POx6r74mxEYKG5kOb6Xpy2gCRW6zweT6TEhAf8vhxGgjhqrd/VO/Dirhsb+1hNpD1ue9hw=="], + + "@floating-ui/core": ["@floating-ui/core@1.7.3", "", { "dependencies": { "@floating-ui/utils": "^0.2.10" } }, "sha512-sGnvb5dmrJaKEZ+LDIpguvdX3bDlEllmv4/ClQ9awcmCZrlx5jQyyMWFM5kBI+EyNOCDDiKk8il0zeuX3Zlg/w=="], + + "@floating-ui/dom": ["@floating-ui/dom@1.7.3", "", { "dependencies": { "@floating-ui/core": "^1.7.3", "@floating-ui/utils": "^0.2.10" } }, "sha512-uZA413QEpNuhtb3/iIKoYMSK07keHPYeXF02Zhd6e213j+d1NamLix/mCLxBUDW/Gx52sPH2m+chlUsyaBs/Ag=="], + + "@floating-ui/react-dom": ["@floating-ui/react-dom@2.1.5", "", { "dependencies": { "@floating-ui/dom": "^1.7.3" }, "peerDependencies": { "react": ">=16.8.0", "react-dom": ">=16.8.0" } }, "sha512-HDO/1/1oH9fjj4eLgegrlH3dklZpHtUYYFiVwMUwfGvk9jWDRWqkklA2/NFScknrcNSspbV868WjXORvreDX+Q=="], + + "@floating-ui/utils": ["@floating-ui/utils@0.2.10", "", {}, "sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ=="], + + "@humanfs/core": ["@humanfs/core@0.19.1", "", {}, "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA=="], + + "@humanfs/node": ["@humanfs/node@0.16.6", "", { "dependencies": { "@humanfs/core": "^0.19.1", "@humanwhocodes/retry": "^0.3.0" } }, "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw=="], + + "@humanwhocodes/module-importer": ["@humanwhocodes/module-importer@1.0.1", "", {}, "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA=="], + + "@humanwhocodes/retry": ["@humanwhocodes/retry@0.4.3", "", {}, "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ=="], + + "@img/sharp-darwin-arm64": ["@img/sharp-darwin-arm64@0.34.3", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-arm64": "1.2.0" }, "os": "darwin", "cpu": "arm64" }, "sha512-ryFMfvxxpQRsgZJqBd4wsttYQbCxsJksrv9Lw/v798JcQ8+w84mBWuXwl+TT0WJ/WrYOLaYpwQXi3sA9nTIaIg=="], + + "@img/sharp-darwin-x64": ["@img/sharp-darwin-x64@0.34.3", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-x64": "1.2.0" }, "os": "darwin", "cpu": "x64" }, "sha512-yHpJYynROAj12TA6qil58hmPmAwxKKC7reUqtGLzsOHfP7/rniNGTL8tjWX6L3CTV4+5P4ypcS7Pp+7OB+8ihA=="], + + "@img/sharp-libvips-darwin-arm64": ["@img/sharp-libvips-darwin-arm64@1.2.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-sBZmpwmxqwlqG9ueWFXtockhsxefaV6O84BMOrhtg/YqbTaRdqDE7hxraVE3y6gVM4eExmfzW4a8el9ArLeEiQ=="], + + "@img/sharp-libvips-darwin-x64": ["@img/sharp-libvips-darwin-x64@1.2.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-M64XVuL94OgiNHa5/m2YvEQI5q2cl9d/wk0qFTDVXcYzi43lxuiFTftMR1tOnFQovVXNZJ5TURSDK2pNe9Yzqg=="], + + "@img/sharp-libvips-linux-arm": ["@img/sharp-libvips-linux-arm@1.2.0", "", { "os": "linux", "cpu": "arm" }, "sha512-mWd2uWvDtL/nvIzThLq3fr2nnGfyr/XMXlq8ZJ9WMR6PXijHlC3ksp0IpuhK6bougvQrchUAfzRLnbsen0Cqvw=="], + + "@img/sharp-libvips-linux-arm64": ["@img/sharp-libvips-linux-arm64@1.2.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-RXwd0CgG+uPRX5YYrkzKyalt2OJYRiJQ8ED/fi1tq9WQW2jsQIn0tqrlR5l5dr/rjqq6AHAxURhj2DVjyQWSOA=="], + + "@img/sharp-libvips-linux-ppc64": ["@img/sharp-libvips-linux-ppc64@1.2.0", "", { "os": "linux", "cpu": "ppc64" }, "sha512-Xod/7KaDDHkYu2phxxfeEPXfVXFKx70EAFZ0qyUdOjCcxbjqyJOEUpDe6RIyaunGxT34Anf9ue/wuWOqBW2WcQ=="], + + "@img/sharp-libvips-linux-s390x": ["@img/sharp-libvips-linux-s390x@1.2.0", "", { "os": "linux", "cpu": "s390x" }, "sha512-eMKfzDxLGT8mnmPJTNMcjfO33fLiTDsrMlUVcp6b96ETbnJmd4uvZxVJSKPQfS+odwfVaGifhsB07J1LynFehw=="], + + "@img/sharp-libvips-linux-x64": ["@img/sharp-libvips-linux-x64@1.2.0", "", { "os": "linux", "cpu": "x64" }, "sha512-ZW3FPWIc7K1sH9E3nxIGB3y3dZkpJlMnkk7z5tu1nSkBoCgw2nSRTFHI5pB/3CQaJM0pdzMF3paf9ckKMSE9Tg=="], + + "@img/sharp-libvips-linuxmusl-arm64": ["@img/sharp-libvips-linuxmusl-arm64@1.2.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-UG+LqQJbf5VJ8NWJ5Z3tdIe/HXjuIdo4JeVNADXBFuG7z9zjoegpzzGIyV5zQKi4zaJjnAd2+g2nna8TZvuW9Q=="], + + "@img/sharp-libvips-linuxmusl-x64": ["@img/sharp-libvips-linuxmusl-x64@1.2.0", "", { "os": "linux", "cpu": "x64" }, "sha512-SRYOLR7CXPgNze8akZwjoGBoN1ThNZoqpOgfnOxmWsklTGVfJiGJoC/Lod7aNMGA1jSsKWM1+HRX43OP6p9+6Q=="], + + "@img/sharp-linux-arm": ["@img/sharp-linux-arm@0.34.3", "", { "optionalDependencies": { "@img/sharp-libvips-linux-arm": "1.2.0" }, "os": "linux", "cpu": "arm" }, "sha512-oBK9l+h6KBN0i3dC8rYntLiVfW8D8wH+NPNT3O/WBHeW0OQWCjfWksLUaPidsrDKpJgXp3G3/hkmhptAW0I3+A=="], + + "@img/sharp-linux-arm64": ["@img/sharp-linux-arm64@0.34.3", "", { "optionalDependencies": { "@img/sharp-libvips-linux-arm64": "1.2.0" }, "os": "linux", "cpu": "arm64" }, "sha512-QdrKe3EvQrqwkDrtuTIjI0bu6YEJHTgEeqdzI3uWJOH6G1O8Nl1iEeVYRGdj1h5I21CqxSvQp1Yv7xeU3ZewbA=="], + + "@img/sharp-linux-ppc64": ["@img/sharp-linux-ppc64@0.34.3", "", { "optionalDependencies": { "@img/sharp-libvips-linux-ppc64": "1.2.0" }, "os": "linux", "cpu": "ppc64" }, "sha512-GLtbLQMCNC5nxuImPR2+RgrviwKwVql28FWZIW1zWruy6zLgA5/x2ZXk3mxj58X/tszVF69KK0Is83V8YgWhLA=="], + + "@img/sharp-linux-s390x": ["@img/sharp-linux-s390x@0.34.3", "", { "optionalDependencies": { "@img/sharp-libvips-linux-s390x": "1.2.0" }, "os": "linux", "cpu": "s390x" }, "sha512-3gahT+A6c4cdc2edhsLHmIOXMb17ltffJlxR0aC2VPZfwKoTGZec6u5GrFgdR7ciJSsHT27BD3TIuGcuRT0KmQ=="], + + "@img/sharp-linux-x64": ["@img/sharp-linux-x64@0.34.3", "", { "optionalDependencies": { "@img/sharp-libvips-linux-x64": "1.2.0" }, "os": "linux", "cpu": "x64" }, "sha512-8kYso8d806ypnSq3/Ly0QEw90V5ZoHh10yH0HnrzOCr6DKAPI6QVHvwleqMkVQ0m+fc7EH8ah0BB0QPuWY6zJQ=="], + + "@img/sharp-linuxmusl-arm64": ["@img/sharp-linuxmusl-arm64@0.34.3", "", { "optionalDependencies": { "@img/sharp-libvips-linuxmusl-arm64": "1.2.0" }, "os": "linux", "cpu": "arm64" }, "sha512-vAjbHDlr4izEiXM1OTggpCcPg9tn4YriK5vAjowJsHwdBIdx0fYRsURkxLG2RLm9gyBq66gwtWI8Gx0/ov+JKQ=="], + + "@img/sharp-linuxmusl-x64": ["@img/sharp-linuxmusl-x64@0.34.3", "", { "optionalDependencies": { "@img/sharp-libvips-linuxmusl-x64": "1.2.0" }, "os": "linux", "cpu": "x64" }, "sha512-gCWUn9547K5bwvOn9l5XGAEjVTTRji4aPTqLzGXHvIr6bIDZKNTA34seMPgM0WmSf+RYBH411VavCejp3PkOeQ=="], + + "@img/sharp-wasm32": ["@img/sharp-wasm32@0.34.3", "", { "dependencies": { "@emnapi/runtime": "^1.4.4" }, "cpu": "none" }, "sha512-+CyRcpagHMGteySaWos8IbnXcHgfDn7pO2fiC2slJxvNq9gDipYBN42/RagzctVRKgxATmfqOSulgZv5e1RdMg=="], + + "@img/sharp-win32-arm64": ["@img/sharp-win32-arm64@0.34.3", "", { "os": "win32", "cpu": "arm64" }, "sha512-MjnHPnbqMXNC2UgeLJtX4XqoVHHlZNd+nPt1kRPmj63wURegwBhZlApELdtxM2OIZDRv/DFtLcNhVbd1z8GYXQ=="], + + "@img/sharp-win32-ia32": ["@img/sharp-win32-ia32@0.34.3", "", { "os": "win32", "cpu": "ia32" }, "sha512-xuCdhH44WxuXgOM714hn4amodJMZl3OEvf0GVTm0BEyMeA2to+8HEdRPShH0SLYptJY1uBw+SCFP9WVQi1Q/cw=="], + + "@img/sharp-win32-x64": ["@img/sharp-win32-x64@0.34.3", "", { "os": "win32", "cpu": "x64" }, "sha512-OWwz05d++TxzLEv4VnsTz5CmZ6mI6S05sfQGEMrNrQcOEERbX46332IvE7pO/EUiw7jUrrS40z/M7kPyjfl04g=="], + + "@isaacs/cliui": ["@isaacs/cliui@8.0.2", "", { "dependencies": { "string-width": "^5.1.2", "string-width-cjs": "npm:string-width@^4.2.0", "strip-ansi": "^7.0.1", "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", "wrap-ansi": "^8.1.0", "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" } }, "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA=="], + + "@jridgewell/gen-mapping": ["@jridgewell/gen-mapping@0.3.12", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-OuLGC46TjB5BbN1dH8JULVVZY4WTdkF7tV9Ys6wLL1rubZnCMstOhNHueU5bLCrnRuDhKPDM4g6sw4Bel5Gzqg=="], + + "@jridgewell/resolve-uri": ["@jridgewell/resolve-uri@3.1.2", "", {}, "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw=="], + + "@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.4", "", {}, "sha512-VT2+G1VQs/9oz078bLrYbecdZKs912zQlkelYpuf+SXF+QvZDYJlbx/LSx+meSAwdDFnF8FVXW92AVjjkVmgFw=="], + + "@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.9", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.0.3", "@jridgewell/sourcemap-codec": "^1.4.10" } }, "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ=="], + + "@mdx-js/mdx": ["@mdx-js/mdx@3.0.1", "", { "dependencies": { "@types/estree": "^1.0.0", "@types/estree-jsx": "^1.0.0", "@types/hast": "^3.0.0", "@types/mdx": "^2.0.0", "collapse-white-space": "^2.0.0", "devlop": "^1.0.0", "estree-util-build-jsx": "^3.0.0", "estree-util-is-identifier-name": "^3.0.0", "estree-util-to-js": "^2.0.0", "estree-walker": "^3.0.0", "hast-util-to-estree": "^3.0.0", "hast-util-to-jsx-runtime": "^2.0.0", "markdown-extensions": "^2.0.0", "periscopic": "^3.0.0", "remark-mdx": "^3.0.0", "remark-parse": "^11.0.0", "remark-rehype": "^11.0.0", "source-map": "^0.7.0", "unified": "^11.0.0", "unist-util-position-from-estree": "^2.0.0", "unist-util-stringify-position": "^4.0.0", "unist-util-visit": "^5.0.0", "vfile": "^6.0.0" } }, "sha512-eIQ4QTrOWyL3LWEe/bu6Taqzq2HQvHcyTMaOrI95P2/LmJE7AsfPfgJGuFLPVqBUE1BC1rik3VIhU+s9u72arA=="], + + "@mdx-js/react": ["@mdx-js/react@3.0.1", "", { "dependencies": { "@types/mdx": "^2.0.0" }, "peerDependencies": { "@types/react": ">=16", "react": ">=16" } }, "sha512-9ZrPIU4MGf6et1m1ov3zKf+q9+deetI51zprKB1D/z3NOb+rUxxtEl3mCjW5wTGh6VhRdwPueh1oRzi6ezkA8A=="], + + "@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@0.2.12", "", { "dependencies": { "@emnapi/core": "^1.4.3", "@emnapi/runtime": "^1.4.3", "@tybys/wasm-util": "^0.10.0" } }, "sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ=="], + + "@next/env": ["@next/env@15.4.6", "", {}, "sha512-yHDKVTcHrZy/8TWhj0B23ylKv5ypocuCwey9ZqPyv4rPdUdRzpGCkSi03t04KBPyU96kxVtUqx6O3nE1kpxASQ=="], + + "@next/eslint-plugin-next": ["@next/eslint-plugin-next@15.4.6", "", { "dependencies": { "fast-glob": "3.3.1" } }, "sha512-2NOu3ln+BTcpnbIDuxx6MNq+pRrCyey4WSXGaJIyt0D2TYicHeO9QrUENNjcf673n3B1s7hsiV5xBYRCK1Q8kA=="], + + "@next/swc-darwin-arm64": ["@next/swc-darwin-arm64@15.4.6", "", { "os": "darwin", "cpu": "arm64" }, "sha512-667R0RTP4DwxzmrqTs4Lr5dcEda9OxuZsVFsjVtxVMVhzSpo6nLclXejJVfQo2/g7/Z9qF3ETDmN3h65mTjpTQ=="], + + "@next/swc-darwin-x64": ["@next/swc-darwin-x64@15.4.6", "", { "os": "darwin", "cpu": "x64" }, "sha512-KMSFoistFkaiQYVQQnaU9MPWtp/3m0kn2Xed1Ces5ll+ag1+rlac20sxG+MqhH2qYWX1O2GFOATQXEyxKiIscg=="], + + "@next/swc-linux-arm64-gnu": ["@next/swc-linux-arm64-gnu@15.4.6", "", { "os": "linux", "cpu": "arm64" }, "sha512-PnOx1YdO0W7m/HWFeYd2A6JtBO8O8Eb9h6nfJia2Dw1sRHoHpNf6lN1U4GKFRzRDBi9Nq2GrHk9PF3Vmwf7XVw=="], + + "@next/swc-linux-arm64-musl": ["@next/swc-linux-arm64-musl@15.4.6", "", { "os": "linux", "cpu": "arm64" }, "sha512-XBbuQddtY1p5FGPc2naMO0kqs4YYtLYK/8aPausI5lyOjr4J77KTG9mtlU4P3NwkLI1+OjsPzKVvSJdMs3cFaw=="], + + "@next/swc-linux-x64-gnu": ["@next/swc-linux-x64-gnu@15.4.6", "", { "os": "linux", "cpu": "x64" }, "sha512-+WTeK7Qdw82ez3U9JgD+igBAP75gqZ1vbK6R8PlEEuY0OIe5FuYXA4aTjL811kWPf7hNeslD4hHK2WoM9W0IgA=="], + + "@next/swc-linux-x64-musl": ["@next/swc-linux-x64-musl@15.4.6", "", { "os": "linux", "cpu": "x64" }, "sha512-XP824mCbgQsK20jlXKrUpZoh/iO3vUWhMpxCz8oYeagoiZ4V0TQiKy0ASji1KK6IAe3DYGfj5RfKP6+L2020OQ=="], + + "@next/swc-win32-arm64-msvc": ["@next/swc-win32-arm64-msvc@15.4.6", "", { "os": "win32", "cpu": "arm64" }, "sha512-FxrsenhUz0LbgRkNWx6FRRJIPe/MI1JRA4W4EPd5leXO00AZ6YU8v5vfx4MDXTvN77lM/EqsE3+6d2CIeF5NYg=="], + + "@next/swc-win32-x64-msvc": ["@next/swc-win32-x64-msvc@15.4.6", "", { "os": "win32", "cpu": "x64" }, "sha512-T4ufqnZ4u88ZheczkBTtOF+eKaM14V8kbjud/XrAakoM5DKQWjW09vD6B9fsdsWS2T7D5EY31hRHdta7QKWOng=="], + + "@nodelib/fs.scandir": ["@nodelib/fs.scandir@2.1.5", "", { "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" } }, "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g=="], + + "@nodelib/fs.stat": ["@nodelib/fs.stat@2.0.5", "", {}, "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A=="], + + "@nodelib/fs.walk": ["@nodelib/fs.walk@1.2.8", "", { "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" } }, "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg=="], + + "@nolyfill/is-core-module": ["@nolyfill/is-core-module@1.0.39", "", {}, "sha512-nn5ozdjYQpUCZlWGuxcJY/KpxkWQs4DcbMCmKojjyrYDEAGy4Ce19NN4v5MduafTwJlbKc99UA8YhSVqq9yPZA=="], + + "@pkgjs/parseargs": ["@pkgjs/parseargs@0.11.0", "", {}, "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg=="], + + "@radix-ui/number": ["@radix-ui/number@1.1.1", "", {}, "sha512-MkKCwxlXTgz6CFoJx3pCwn07GKp36+aZyu/u2Ln2VrA5DcdyCZkASEDBTd8x5whTQQL5CiYf4prXKLcgQdv29g=="], + + "@radix-ui/primitive": ["@radix-ui/primitive@1.1.2", "", {}, "sha512-XnbHrrprsNqZKQhStrSwgRUQzoCI1glLzdw79xiZPoofhGICeZRSQ3dIxAKH1gb3OHfNf4d6f+vAv3kil2eggA=="], + + "@radix-ui/react-arrow": ["@radix-ui/react-arrow@1.1.7", "", { "dependencies": { "@radix-ui/react-primitive": "2.1.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-F+M1tLhO+mlQaOWspE8Wstg+z6PwxwRd8oQ8IXceWz92kfAmalTRf0EjrouQeo7QssEPfCn05B4Ihs1K9WQ/7w=="], + + "@radix-ui/react-collapsible": ["@radix-ui/react-collapsible@1.1.11", "", { "dependencies": { "@radix-ui/primitive": "1.1.2", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-presence": "1.1.4", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-controllable-state": "1.2.2", "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-2qrRsVGSCYasSz1RFOorXwl0H7g7J1frQtgpQgYrt+MOidtPAINHn9CPovQXb83r8ahapdx3Tu0fa/pdFFSdPg=="], + + "@radix-ui/react-collection": ["@radix-ui/react-collection@1.1.7", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-Fh9rGN0MoI4ZFUNyfFVNU4y9LUz93u9/0K+yLgA2bwRojxM8JU1DyvvMBabnZPBgMWREAJvU2jjVzq+LrFUglw=="], + + "@radix-ui/react-compose-refs": ["@radix-ui/react-compose-refs@1.1.2", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg=="], + + "@radix-ui/react-context": ["@radix-ui/react-context@1.1.2", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA=="], + + "@radix-ui/react-dialog": ["@radix-ui/react-dialog@1.1.14", "", { "dependencies": { "@radix-ui/primitive": "1.1.2", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-dismissable-layer": "1.1.10", "@radix-ui/react-focus-guards": "1.1.2", "@radix-ui/react-focus-scope": "1.1.7", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-portal": "1.1.9", "@radix-ui/react-presence": "1.1.4", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-slot": "1.2.3", "@radix-ui/react-use-controllable-state": "1.2.2", "aria-hidden": "^1.2.4", "react-remove-scroll": "^2.6.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-+CpweKjqpzTmwRwcYECQcNYbI8V9VSQt0SNFKeEBLgfucbsLssU6Ppq7wUdNXEGb573bMjFhVjKVll8rmV6zMw=="], + + "@radix-ui/react-direction": ["@radix-ui/react-direction@1.1.1", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-1UEWRX6jnOA2y4H5WczZ44gOOjTEmlqv1uNW4GAJEO5+bauCBhv8snY65Iw5/VOS/ghKN9gr2KjnLKxrsvoMVw=="], + + "@radix-ui/react-dismissable-layer": ["@radix-ui/react-dismissable-layer@1.1.10", "", { "dependencies": { "@radix-ui/primitive": "1.1.2", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-callback-ref": "1.1.1", "@radix-ui/react-use-escape-keydown": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-IM1zzRV4W3HtVgftdQiiOmA0AdJlCtMLe00FXaHwgt3rAnNsIyDqshvkIW3hj/iu5hu8ERP7KIYki6NkqDxAwQ=="], + + "@radix-ui/react-dropdown-menu": ["@radix-ui/react-dropdown-menu@2.1.15", "", { "dependencies": { "@radix-ui/primitive": "1.1.2", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-menu": "2.1.15", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-controllable-state": "1.2.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-mIBnOjgwo9AH3FyKaSWoSu/dYj6VdhJ7frEPiGTeXCdUFHjl9h3mFh2wwhEtINOmYXWhdpf1rY2minFsmaNgVQ=="], + + "@radix-ui/react-focus-guards": ["@radix-ui/react-focus-guards@1.1.2", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-fyjAACV62oPV925xFCrH8DR5xWhg9KYtJT4s3u54jxp+L/hbpTY2kIeEFFbFe+a/HCE94zGQMZLIpVTPVZDhaA=="], + + "@radix-ui/react-focus-scope": ["@radix-ui/react-focus-scope@1.1.7", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-callback-ref": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-t2ODlkXBQyn7jkl6TNaw/MtVEVvIGelJDCG41Okq/KwUsJBwQ4XVZsHAVUkK4mBv3ewiAS3PGuUWuY2BoK4ZUw=="], + + "@radix-ui/react-id": ["@radix-ui/react-id@1.1.1", "", { "dependencies": { "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg=="], + + "@radix-ui/react-menu": ["@radix-ui/react-menu@2.1.15", "", { "dependencies": { "@radix-ui/primitive": "1.1.2", "@radix-ui/react-collection": "1.1.7", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-dismissable-layer": "1.1.10", "@radix-ui/react-focus-guards": "1.1.2", "@radix-ui/react-focus-scope": "1.1.7", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-popper": "1.2.7", "@radix-ui/react-portal": "1.1.9", "@radix-ui/react-presence": "1.1.4", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-roving-focus": "1.1.10", "@radix-ui/react-slot": "1.2.3", "@radix-ui/react-use-callback-ref": "1.1.1", "aria-hidden": "^1.2.4", "react-remove-scroll": "^2.6.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-tVlmA3Vb9n8SZSd+YSbuFR66l87Wiy4du+YE+0hzKQEANA+7cWKH1WgqcEX4pXqxUFQKrWQGHdvEfw00TjFiew=="], + + "@radix-ui/react-popper": ["@radix-ui/react-popper@1.2.7", "", { "dependencies": { "@floating-ui/react-dom": "^2.0.0", "@radix-ui/react-arrow": "1.1.7", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-callback-ref": "1.1.1", "@radix-ui/react-use-layout-effect": "1.1.1", "@radix-ui/react-use-rect": "1.1.1", "@radix-ui/react-use-size": "1.1.1", "@radix-ui/rect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-IUFAccz1JyKcf/RjB552PlWwxjeCJB8/4KxT7EhBHOJM+mN7LdW+B3kacJXILm32xawcMMjb2i0cIZpo+f9kiQ=="], + + "@radix-ui/react-portal": ["@radix-ui/react-portal@1.1.9", "", { "dependencies": { "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-bpIxvq03if6UNwXZ+HTK71JLh4APvnXntDc6XOX8UVq4XQOVl7lwok0AvIl+b8zgCw3fSaVTZMpAPPagXbKmHQ=="], + + "@radix-ui/react-presence": ["@radix-ui/react-presence@1.1.4", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-ueDqRbdc4/bkaQT3GIpLQssRlFgWaL/U2z/S31qRwwLWoxHLgry3SIfCwhxeQNbirEUXFa+lq3RL3oBYXtcmIA=="], + + "@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="], + + "@radix-ui/react-roving-focus": ["@radix-ui/react-roving-focus@1.1.10", "", { "dependencies": { "@radix-ui/primitive": "1.1.2", "@radix-ui/react-collection": "1.1.7", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-callback-ref": "1.1.1", "@radix-ui/react-use-controllable-state": "1.2.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-dT9aOXUen9JSsxnMPv/0VqySQf5eDQ6LCk5Sw28kamz8wSOW2bJdlX2Bg5VUIIcV+6XlHpWTIuTPCf/UNIyq8Q=="], + + "@radix-ui/react-scroll-area": ["@radix-ui/react-scroll-area@1.2.9", "", { "dependencies": { "@radix-ui/number": "1.1.1", "@radix-ui/primitive": "1.1.2", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-presence": "1.1.4", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-callback-ref": "1.1.1", "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-YSjEfBXnhUELsO2VzjdtYYD4CfQjvao+lhhrX5XsHD7/cyUNzljF1FHEbgTPN7LH2MClfwRMIsYlqTYpKTTe2A=="], + + "@radix-ui/react-slot": ["@radix-ui/react-slot@1.2.3", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A=="], + + "@radix-ui/react-tooltip": ["@radix-ui/react-tooltip@1.2.7", "", { "dependencies": { "@radix-ui/primitive": "1.1.2", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-dismissable-layer": "1.1.10", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-popper": "1.2.7", "@radix-ui/react-portal": "1.1.9", "@radix-ui/react-presence": "1.1.4", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-slot": "1.2.3", "@radix-ui/react-use-controllable-state": "1.2.2", "@radix-ui/react-visually-hidden": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-Ap+fNYwKTYJ9pzqW+Xe2HtMRbQ/EeWkj2qykZ6SuEV4iS/o1bZI5ssJbk4D2r8XuDuOBVz/tIx2JObtuqU+5Zw=="], + + "@radix-ui/react-use-callback-ref": ["@radix-ui/react-use-callback-ref@1.1.1", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg=="], + + "@radix-ui/react-use-controllable-state": ["@radix-ui/react-use-controllable-state@1.2.2", "", { "dependencies": { "@radix-ui/react-use-effect-event": "0.0.2", "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg=="], + + "@radix-ui/react-use-effect-event": ["@radix-ui/react-use-effect-event@0.0.2", "", { "dependencies": { "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-Qp8WbZOBe+blgpuUT+lw2xheLP8q0oatc9UpmiemEICxGvFLYmHm9QowVZGHtJlGbS6A6yJ3iViad/2cVjnOiA=="], + + "@radix-ui/react-use-escape-keydown": ["@radix-ui/react-use-escape-keydown@1.1.1", "", { "dependencies": { "@radix-ui/react-use-callback-ref": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-Il0+boE7w/XebUHyBjroE+DbByORGR9KKmITzbR7MyQ4akpORYP/ZmbhAr0DG7RmmBqoOnZdy2QlvajJ2QA59g=="], + + "@radix-ui/react-use-layout-effect": ["@radix-ui/react-use-layout-effect@1.1.1", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ=="], + + "@radix-ui/react-use-rect": ["@radix-ui/react-use-rect@1.1.1", "", { "dependencies": { "@radix-ui/rect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-QTYuDesS0VtuHNNvMh+CjlKJ4LJickCMUAqjlE3+j8w+RlRpwyX3apEQKGFzbZGdo7XNG1tXa+bQqIE7HIXT2w=="], + + "@radix-ui/react-use-size": ["@radix-ui/react-use-size@1.1.1", "", { "dependencies": { "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-ewrXRDTAqAXlkl6t/fkXWNAhFX9I+CkKlw6zjEwk86RSPKwZr3xpBRso655aqYafwtnbpHLj6toFzmd6xdVptQ=="], + + "@radix-ui/react-visually-hidden": ["@radix-ui/react-visually-hidden@1.2.3", "", { "dependencies": { "@radix-ui/react-primitive": "2.1.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-pzJq12tEaaIhqjbzpCuv/OypJY/BPavOofm+dbab+MHLajy277+1lLm6JFcGgF5eskJ6mquGirhXY2GD/8u8Ug=="], + + "@radix-ui/rect": ["@radix-ui/rect@1.1.1", "", {}, "sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw=="], + + "@resvg/resvg-wasm": ["@resvg/resvg-wasm@2.4.0", "", {}, "sha512-C7c51Nn4yTxXFKvgh2txJFNweaVcfUPQxwEUFw4aWsCmfiBDJsTSwviIF8EcwjQ6k8bPyMWCl1vw4BdxE569Cg=="], + + "@rocicorp/prettier-config": ["@rocicorp/prettier-config@0.3.0", "", { "dependencies": { "prettier": "^3.5.3" } }, "sha512-w5xyMZjy32Xb3kgcZs28u/T1Q8XWi4kwWstyvF9ROsa9hNsJxP8g7LeaxwGHFJ7tPx7OXV3bexp1J3XKtoBgPg=="], + + "@rtsao/scc": ["@rtsao/scc@1.1.0", "", {}, "sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g=="], + + "@rushstack/eslint-patch": ["@rushstack/eslint-patch@1.12.0", "", {}, "sha512-5EwMtOqvJMMa3HbmxLlF74e+3/HhwBTMcvt3nqVJgGCozO6hzIPOBlwm8mGVNR9SN2IJpxSnlxczyDjcn7qIyw=="], + + "@shuding/opentype.js": ["@shuding/opentype.js@1.4.0-beta.0", "", { "dependencies": { "fflate": "^0.7.3", "string.prototype.codepointat": "^0.2.1" }, "bin": { "ot": "bin/ot" } }, "sha512-3NgmNyH3l/Hv6EvsWJbsvpcpUba6R8IREQ83nH83cyakCw7uM1arZKNfHwv1Wz6jgqrF/j4x5ELvR6PnK9nTcA=="], + + "@swc/helpers": ["@swc/helpers@0.5.15", "", { "dependencies": { "tslib": "^2.8.0" } }, "sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g=="], + + "@tailwindcss/typography": ["@tailwindcss/typography@0.5.16", "", { "dependencies": { "lodash.castarray": "^4.4.0", "lodash.isplainobject": "^4.0.6", "lodash.merge": "^4.6.2", "postcss-selector-parser": "6.0.10" }, "peerDependencies": { "tailwindcss": ">=3.0.0 || insiders || >=4.0.0-alpha.20 || >=4.0.0-beta.1" } }, "sha512-0wDLwCVF5V3x3b1SGXPCDcdsbDHMBe+lkFzBRaHeLvNi+nrrnZ1lA18u+OTWO8iSWU2GxUOCvlXtDuqftc1oiA=="], + + "@tsconfig/node10": ["@tsconfig/node10@1.0.11", "", {}, "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw=="], + + "@tsconfig/node12": ["@tsconfig/node12@1.0.11", "", {}, "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag=="], + + "@tsconfig/node14": ["@tsconfig/node14@1.0.3", "", {}, "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow=="], + + "@tsconfig/node16": ["@tsconfig/node16@1.0.4", "", {}, "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA=="], + + "@tybys/wasm-util": ["@tybys/wasm-util@0.10.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-VyyPYFlOMNylG45GoAe0xDoLwWuowvf92F9kySqzYh8vmYm7D2u4iUJKa1tOUpS70Ku13ASrOkS4ScXFsTaCNQ=="], + + "@types/acorn": ["@types/acorn@4.0.6", "", { "dependencies": { "@types/estree": "*" } }, "sha512-veQTnWP+1D/xbxVrPC3zHnCZRjSrKfhbMUlEA43iMZLu7EsnTtkJklIuwrCPbOi8YkvDQAiW05VQQFvvz9oieQ=="], + + "@types/debug": ["@types/debug@4.1.12", "", { "dependencies": { "@types/ms": "*" } }, "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ=="], + + "@types/estree": ["@types/estree@1.0.8", "", {}, "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="], + + "@types/estree-jsx": ["@types/estree-jsx@1.0.5", "", { "dependencies": { "@types/estree": "*" } }, "sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg=="], + + "@types/hast": ["@types/hast@3.0.4", "", { "dependencies": { "@types/unist": "*" } }, "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ=="], + + "@types/json-schema": ["@types/json-schema@7.0.15", "", {}, "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA=="], + + "@types/json5": ["@types/json5@0.0.29", "", {}, "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ=="], + + "@types/lunr": ["@types/lunr@2.3.7", "", {}, "sha512-Tb/kUm38e8gmjahQzdCKhbdsvQ9/ppzHFfsJ0dMs3ckqQsRj+P5IkSAwFTBrBxdyr3E/LoMUUrZngjDYAjiE3A=="], + + "@types/mdast": ["@types/mdast@4.0.4", "", { "dependencies": { "@types/unist": "*" } }, "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA=="], + + "@types/mdx": ["@types/mdx@2.0.13", "", {}, "sha512-+OWZQfAYyio6YkJb3HLxDrvnx6SWWDbC0zVPfBRzUk0/nqoDyf6dNxQi3eArPe8rJ473nobTMQ/8Zk+LxJ+Yuw=="], + + "@types/ms": ["@types/ms@0.7.34", "", {}, "sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g=="], + + "@types/node": ["@types/node@24.2.0", "", { "dependencies": { "undici-types": "~7.10.0" } }, "sha512-3xyG3pMCq3oYCNg7/ZP+E1ooTaGB4cG8JWRsqqOYQdbWNY4zbaV0Ennrd7stjiJEFZCaybcIgpTjJWHRfBSIDw=="], + + "@types/prismjs": ["@types/prismjs@1.26.3", "", {}, "sha512-A0D0aTXvjlqJ5ZILMz3rNfDBOx9hHxLZYv2by47Sm/pqW35zzjusrZTryatjN/Rf8Us2gZrJD+KeHbUSTux1Cw=="], + + "@types/react": ["@types/react@19.1.9", "", { "dependencies": { "csstype": "^3.0.2" } }, "sha512-WmdoynAX8Stew/36uTSVMcLJJ1KRh6L3IZRx1PZ7qJtBqT3dYTgyDTx8H1qoRghErydW7xw9mSJ3wS//tCRpFA=="], + + "@types/react-dom": ["@types/react-dom@19.1.7", "", { "peerDependencies": { "@types/react": "^19.0.0" } }, "sha512-i5ZzwYpqjmrKenzkoLM2Ibzt6mAsM7pxB6BCIouEVVmgiqaMj1TjaK7hnA36hbW5aZv20kx7Lw6hWzPWg0Rurw=="], + + "@types/unist": ["@types/unist@3.0.3", "", {}, "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q=="], + + "@typescript-eslint/eslint-plugin": ["@typescript-eslint/eslint-plugin@8.39.0", "", { "dependencies": { "@eslint-community/regexpp": "^4.10.0", "@typescript-eslint/scope-manager": "8.39.0", "@typescript-eslint/type-utils": "8.39.0", "@typescript-eslint/utils": "8.39.0", "@typescript-eslint/visitor-keys": "8.39.0", "graphemer": "^1.4.0", "ignore": "^7.0.0", "natural-compare": "^1.4.0", "ts-api-utils": "^2.1.0" }, "peerDependencies": { "@typescript-eslint/parser": "^8.39.0", "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-bhEz6OZeUR+O/6yx9Jk6ohX6H9JSFTaiY0v9/PuKT3oGK0rn0jNplLmyFUGV+a9gfYnVNwGDwS/UkLIuXNb2Rw=="], + + "@typescript-eslint/parser": ["@typescript-eslint/parser@8.39.0", "", { "dependencies": { "@typescript-eslint/scope-manager": "8.39.0", "@typescript-eslint/types": "8.39.0", "@typescript-eslint/typescript-estree": "8.39.0", "@typescript-eslint/visitor-keys": "8.39.0", "debug": "^4.3.4" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-g3WpVQHngx0aLXn6kfIYCZxM6rRJlWzEkVpqEFLT3SgEDsp9cpCbxxgwnE504q4H+ruSDh/VGS6nqZIDynP+vg=="], + + "@typescript-eslint/project-service": ["@typescript-eslint/project-service@8.39.0", "", { "dependencies": { "@typescript-eslint/tsconfig-utils": "^8.39.0", "@typescript-eslint/types": "^8.39.0", "debug": "^4.3.4" }, "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-CTzJqaSq30V/Z2Og9jogzZt8lJRR5TKlAdXmWgdu4hgcC9Kww5flQ+xFvMxIBWVNdxJO7OifgdOK4PokMIWPew=="], + + "@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.39.0", "", { "dependencies": { "@typescript-eslint/types": "8.39.0", "@typescript-eslint/visitor-keys": "8.39.0" } }, "sha512-8QOzff9UKxOh6npZQ/4FQu4mjdOCGSdO3p44ww0hk8Vu+IGbg0tB/H1LcTARRDzGCC8pDGbh2rissBuuoPgH8A=="], + + "@typescript-eslint/tsconfig-utils": ["@typescript-eslint/tsconfig-utils@8.39.0", "", { "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-Fd3/QjmFV2sKmvv3Mrj8r6N8CryYiCS8Wdb/6/rgOXAWGcFuc+VkQuG28uk/4kVNVZBQuuDHEDUpo/pQ32zsIQ=="], + + "@typescript-eslint/type-utils": ["@typescript-eslint/type-utils@8.39.0", "", { "dependencies": { "@typescript-eslint/types": "8.39.0", "@typescript-eslint/typescript-estree": "8.39.0", "@typescript-eslint/utils": "8.39.0", "debug": "^4.3.4", "ts-api-utils": "^2.1.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-6B3z0c1DXVT2vYA9+z9axjtc09rqKUPRmijD5m9iv8iQpHBRYRMBcgxSiKTZKm6FwWw1/cI4v6em35OsKCiN5Q=="], + + "@typescript-eslint/types": ["@typescript-eslint/types@8.39.0", "", {}, "sha512-ArDdaOllnCj3yn/lzKn9s0pBQYmmyme/v1HbGIGB0GB/knFI3fWMHloC+oYTJW46tVbYnGKTMDK4ah1sC2v0Kg=="], + + "@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.39.0", "", { "dependencies": { "@typescript-eslint/project-service": "8.39.0", "@typescript-eslint/tsconfig-utils": "8.39.0", "@typescript-eslint/types": "8.39.0", "@typescript-eslint/visitor-keys": "8.39.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", "minimatch": "^9.0.4", "semver": "^7.6.0", "ts-api-utils": "^2.1.0" }, "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-ndWdiflRMvfIgQRpckQQLiB5qAKQ7w++V4LlCHwp62eym1HLB/kw7D9f2e8ytONls/jt89TEasgvb+VwnRprsw=="], + + "@typescript-eslint/utils": ["@typescript-eslint/utils@8.39.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.7.0", "@typescript-eslint/scope-manager": "8.39.0", "@typescript-eslint/types": "8.39.0", "@typescript-eslint/typescript-estree": "8.39.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-4GVSvNA0Vx1Ktwvf4sFE+exxJ3QGUorQG1/A5mRfRNZtkBT2xrA/BCO2H0eALx/PnvCS6/vmYwRdDA41EoffkQ=="], + + "@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.39.0", "", { "dependencies": { "@typescript-eslint/types": "8.39.0", "eslint-visitor-keys": "^4.2.1" } }, "sha512-ldgiJ+VAhQCfIjeOgu8Kj5nSxds0ktPOSO9p4+0VDH2R2pLvQraaM5Oen2d7NxzMCm+Sn/vJT+mv2H5u6b/3fA=="], + + "@ungap/structured-clone": ["@ungap/structured-clone@1.2.0", "", {}, "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ=="], + + "@unrs/resolver-binding-android-arm-eabi": ["@unrs/resolver-binding-android-arm-eabi@1.11.1", "", { "os": "android", "cpu": "arm" }, "sha512-ppLRUgHVaGRWUx0R0Ut06Mjo9gBaBkg3v/8AxusGLhsIotbBLuRk51rAzqLC8gq6NyyAojEXglNjzf6R948DNw=="], + + "@unrs/resolver-binding-android-arm64": ["@unrs/resolver-binding-android-arm64@1.11.1", "", { "os": "android", "cpu": "arm64" }, "sha512-lCxkVtb4wp1v+EoN+HjIG9cIIzPkX5OtM03pQYkG+U5O/wL53LC4QbIeazgiKqluGeVEeBlZahHalCaBvU1a2g=="], + + "@unrs/resolver-binding-darwin-arm64": ["@unrs/resolver-binding-darwin-arm64@1.11.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-gPVA1UjRu1Y/IsB/dQEsp2V1pm44Of6+LWvbLc9SDk1c2KhhDRDBUkQCYVWe6f26uJb3fOK8saWMgtX8IrMk3g=="], + + "@unrs/resolver-binding-darwin-x64": ["@unrs/resolver-binding-darwin-x64@1.11.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-cFzP7rWKd3lZaCsDze07QX1SC24lO8mPty9vdP+YVa3MGdVgPmFc59317b2ioXtgCMKGiCLxJ4HQs62oz6GfRQ=="], + + "@unrs/resolver-binding-freebsd-x64": ["@unrs/resolver-binding-freebsd-x64@1.11.1", "", { "os": "freebsd", "cpu": "x64" }, "sha512-fqtGgak3zX4DCB6PFpsH5+Kmt/8CIi4Bry4rb1ho6Av2QHTREM+47y282Uqiu3ZRF5IQioJQ5qWRV6jduA+iGw=="], + + "@unrs/resolver-binding-linux-arm-gnueabihf": ["@unrs/resolver-binding-linux-arm-gnueabihf@1.11.1", "", { "os": "linux", "cpu": "arm" }, "sha512-u92mvlcYtp9MRKmP+ZvMmtPN34+/3lMHlyMj7wXJDeXxuM0Vgzz0+PPJNsro1m3IZPYChIkn944wW8TYgGKFHw=="], + + "@unrs/resolver-binding-linux-arm-musleabihf": ["@unrs/resolver-binding-linux-arm-musleabihf@1.11.1", "", { "os": "linux", "cpu": "arm" }, "sha512-cINaoY2z7LVCrfHkIcmvj7osTOtm6VVT16b5oQdS4beibX2SYBwgYLmqhBjA1t51CarSaBuX5YNsWLjsqfW5Cw=="], + + "@unrs/resolver-binding-linux-arm64-gnu": ["@unrs/resolver-binding-linux-arm64-gnu@1.11.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-34gw7PjDGB9JgePJEmhEqBhWvCiiWCuXsL9hYphDF7crW7UgI05gyBAi6MF58uGcMOiOqSJ2ybEeCvHcq0BCmQ=="], + + "@unrs/resolver-binding-linux-arm64-musl": ["@unrs/resolver-binding-linux-arm64-musl@1.11.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-RyMIx6Uf53hhOtJDIamSbTskA99sPHS96wxVE/bJtePJJtpdKGXO1wY90oRdXuYOGOTuqjT8ACccMc4K6QmT3w=="], + + "@unrs/resolver-binding-linux-ppc64-gnu": ["@unrs/resolver-binding-linux-ppc64-gnu@1.11.1", "", { "os": "linux", "cpu": "ppc64" }, "sha512-D8Vae74A4/a+mZH0FbOkFJL9DSK2R6TFPC9M+jCWYia/q2einCubX10pecpDiTmkJVUH+y8K3BZClycD8nCShA=="], + + "@unrs/resolver-binding-linux-riscv64-gnu": ["@unrs/resolver-binding-linux-riscv64-gnu@1.11.1", "", { "os": "linux", "cpu": "none" }, "sha512-frxL4OrzOWVVsOc96+V3aqTIQl1O2TjgExV4EKgRY09AJ9leZpEg8Ak9phadbuX0BA4k8U5qtvMSQQGGmaJqcQ=="], + + "@unrs/resolver-binding-linux-riscv64-musl": ["@unrs/resolver-binding-linux-riscv64-musl@1.11.1", "", { "os": "linux", "cpu": "none" }, "sha512-mJ5vuDaIZ+l/acv01sHoXfpnyrNKOk/3aDoEdLO/Xtn9HuZlDD6jKxHlkN8ZhWyLJsRBxfv9GYM2utQ1SChKew=="], + + "@unrs/resolver-binding-linux-s390x-gnu": ["@unrs/resolver-binding-linux-s390x-gnu@1.11.1", "", { "os": "linux", "cpu": "s390x" }, "sha512-kELo8ebBVtb9sA7rMe1Cph4QHreByhaZ2QEADd9NzIQsYNQpt9UkM9iqr2lhGr5afh885d/cB5QeTXSbZHTYPg=="], + + "@unrs/resolver-binding-linux-x64-gnu": ["@unrs/resolver-binding-linux-x64-gnu@1.11.1", "", { "os": "linux", "cpu": "x64" }, "sha512-C3ZAHugKgovV5YvAMsxhq0gtXuwESUKc5MhEtjBpLoHPLYM+iuwSj3lflFwK3DPm68660rZ7G8BMcwSro7hD5w=="], + + "@unrs/resolver-binding-linux-x64-musl": ["@unrs/resolver-binding-linux-x64-musl@1.11.1", "", { "os": "linux", "cpu": "x64" }, "sha512-rV0YSoyhK2nZ4vEswT/QwqzqQXw5I6CjoaYMOX0TqBlWhojUf8P94mvI7nuJTeaCkkds3QE4+zS8Ko+GdXuZtA=="], + + "@unrs/resolver-binding-wasm32-wasi": ["@unrs/resolver-binding-wasm32-wasi@1.11.1", "", { "dependencies": { "@napi-rs/wasm-runtime": "^0.2.11" }, "cpu": "none" }, "sha512-5u4RkfxJm+Ng7IWgkzi3qrFOvLvQYnPBmjmZQ8+szTK/b31fQCnleNl1GgEt7nIsZRIf5PLhPwT0WM+q45x/UQ=="], + + "@unrs/resolver-binding-win32-arm64-msvc": ["@unrs/resolver-binding-win32-arm64-msvc@1.11.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-nRcz5Il4ln0kMhfL8S3hLkxI85BXs3o8EYoattsJNdsX4YUU89iOkVn7g0VHSRxFuVMdM4Q1jEpIId1Ihim/Uw=="], + + "@unrs/resolver-binding-win32-ia32-msvc": ["@unrs/resolver-binding-win32-ia32-msvc@1.11.1", "", { "os": "win32", "cpu": "ia32" }, "sha512-DCEI6t5i1NmAZp6pFonpD5m7i6aFrpofcp4LA2i8IIq60Jyo28hamKBxNrZcyOwVOZkgsRp9O2sXWBWP8MnvIQ=="], + + "@unrs/resolver-binding-win32-x64-msvc": ["@unrs/resolver-binding-win32-x64-msvc@1.11.1", "", { "os": "win32", "cpu": "x64" }, "sha512-lrW200hZdbfRtztbygyaq/6jP6AKE8qQN2KvPcJ+x7wiD038YtnYtZ82IMNJ69GJibV7bwL3y9FgK+5w/pYt6g=="], + + "@vercel/og": ["@vercel/og@0.8.5", "", { "dependencies": { "@resvg/resvg-wasm": "2.4.0", "satori": "0.16.0" } }, "sha512-fHqnxfBYcwkamlEgcIzaZqL8IHT09hR7FZL7UdMTdGJyoaBzM/dY6ulO5Swi4ig30FrBJI9I2C+GLV9sb9vexA=="], + + "abbrev": ["abbrev@1.1.1", "", {}, "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q=="], + + "acorn": ["acorn@8.15.0", "", { "bin": "bin/acorn" }, "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg=="], + + "acorn-jsx": ["acorn-jsx@5.3.2", "", { "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ=="], + + "acorn-walk": ["acorn-walk@8.3.4", "", { "dependencies": { "acorn": "^8.11.0" } }, "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g=="], + + "ajv": ["ajv@6.12.6", "", { "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } }, "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g=="], + + "ansi-regex": ["ansi-regex@2.1.1", "", {}, "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA=="], + + "ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], + + "any-promise": ["any-promise@1.3.0", "", {}, "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A=="], + + "anymatch": ["anymatch@3.1.3", "", { "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" } }, "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw=="], + + "arg": ["arg@5.0.2", "", {}, "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg=="], + + "argparse": ["argparse@1.0.10", "", { "dependencies": { "sprintf-js": "~1.0.2" } }, "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg=="], + + "aria-hidden": ["aria-hidden@1.2.6", "", { "dependencies": { "tslib": "^2.0.0" } }, "sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA=="], + + "aria-query": ["aria-query@5.3.2", "", {}, "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw=="], + + "array-buffer-byte-length": ["array-buffer-byte-length@1.0.2", "", { "dependencies": { "call-bound": "^1.0.3", "is-array-buffer": "^3.0.5" } }, "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw=="], + + "array-includes": ["array-includes@3.1.9", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.4", "define-properties": "^1.2.1", "es-abstract": "^1.24.0", "es-object-atoms": "^1.1.1", "get-intrinsic": "^1.3.0", "is-string": "^1.1.1", "math-intrinsics": "^1.1.0" } }, "sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ=="], + + "array.prototype.findlast": ["array.prototype.findlast@1.2.5", "", { "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", "es-abstract": "^1.23.2", "es-errors": "^1.3.0", "es-object-atoms": "^1.0.0", "es-shim-unscopables": "^1.0.2" } }, "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ=="], + + "array.prototype.findlastindex": ["array.prototype.findlastindex@1.2.6", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.4", "define-properties": "^1.2.1", "es-abstract": "^1.23.9", "es-errors": "^1.3.0", "es-object-atoms": "^1.1.1", "es-shim-unscopables": "^1.1.0" } }, "sha512-F/TKATkzseUExPlfvmwQKGITM3DGTK+vkAsCZoDc5daVygbJBnjEUCbgkAvVFsgfXfX4YIqZ/27G3k3tdXrTxQ=="], + + "array.prototype.flat": ["array.prototype.flat@1.3.3", "", { "dependencies": { "call-bind": "^1.0.8", "define-properties": "^1.2.1", "es-abstract": "^1.23.5", "es-shim-unscopables": "^1.0.2" } }, "sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg=="], + + "array.prototype.flatmap": ["array.prototype.flatmap@1.3.3", "", { "dependencies": { "call-bind": "^1.0.8", "define-properties": "^1.2.1", "es-abstract": "^1.23.5", "es-shim-unscopables": "^1.0.2" } }, "sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg=="], + + "array.prototype.tosorted": ["array.prototype.tosorted@1.1.4", "", { "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", "es-abstract": "^1.23.3", "es-errors": "^1.3.0", "es-shim-unscopables": "^1.0.2" } }, "sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA=="], + + "arraybuffer.prototype.slice": ["arraybuffer.prototype.slice@1.0.4", "", { "dependencies": { "array-buffer-byte-length": "^1.0.1", "call-bind": "^1.0.8", "define-properties": "^1.2.1", "es-abstract": "^1.23.5", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.6", "is-array-buffer": "^3.0.4" } }, "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ=="], + + "ast-types-flow": ["ast-types-flow@0.0.8", "", {}, "sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ=="], + + "astring": ["astring@1.8.6", "", { "bin": "bin/astring" }, "sha512-ISvCdHdlTDlH5IpxQJIex7BWBywFWgjJSVdwst+/iQCoEYnyOaQ95+X1JGshuBjGp6nxKUy1jMgE3zPqN7fQdg=="], + + "async-function": ["async-function@1.0.0", "", {}, "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA=="], + + "autoprefixer": ["autoprefixer@10.4.21", "", { "dependencies": { "browserslist": "^4.24.4", "caniuse-lite": "^1.0.30001702", "fraction.js": "^4.3.7", "normalize-range": "^0.1.2", "picocolors": "^1.1.1", "postcss-value-parser": "^4.2.0" }, "peerDependencies": { "postcss": "^8.1.0" }, "bin": "bin/autoprefixer" }, "sha512-O+A6LWV5LDHSJD3LjHYoNi4VLsj/Whi7k6zG12xTYaU4cQ8oxQGckXNX8cRHK5yOZ/ppVHe0ZBXGzSV9jXdVbQ=="], + + "available-typed-arrays": ["available-typed-arrays@1.0.7", "", { "dependencies": { "possible-typed-array-names": "^1.0.0" } }, "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ=="], + + "axe-core": ["axe-core@4.10.3", "", {}, "sha512-Xm7bpRXnDSX2YE2YFfBk2FnF0ep6tmG7xPh8iHee8MIcrgq762Nkce856dYtJYLkuIoYZvGfTs/PbZhideTcEg=="], + + "axobject-query": ["axobject-query@4.1.0", "", {}, "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ=="], + + "bail": ["bail@2.0.2", "", {}, "sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw=="], + + "balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], + + "base64-js": ["base64-js@0.0.8", "", {}, "sha512-3XSA2cR/h/73EzlXXdU6YNycmYI7+kicTxks4eJg2g39biHR84slg2+des+p7iHYhbRg/udIS4TD53WabcOUkw=="], + + "bhttp": ["bhttp@1.2.8", "", { "dependencies": { "bluebird": "^2.8.2", "concat-stream": "^1.4.7", "debug": "^2.1.1", "dev-null": "^0.1.1", "errors": "^0.2.0", "extend": "^2.0.0", "form-data2": "^1.0.0", "form-fix-array": "^1.0.0", "lodash.clonedeep": "^4.5.0", "lodash.merge": "^4.6.2", "stream-length": "^1.0.2", "through2-sink": "^1.0.0", "through2-spy": "^1.2.0", "tough-cookie": "^2.3.1" } }, "sha512-ZwEA5FKEUhc98EHRX+BkNmUOs48RTnglvfze2+p0HrMPwhQBtVw1aAYyylnCtRl6x6vltCkzGo2+twQ6LVfm6Q=="], + + "binary-extensions": ["binary-extensions@2.3.0", "", {}, "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw=="], + + "bluebird": ["bluebird@2.11.0", "", {}, "sha512-UfFSr22dmHPQqPP9XWHRhq+gWnHCYguQGkXQlbyPtW5qTnhFWA8/iXg765tH0cAjy7l/zPJ1aBTO0g5XgA7kvQ=="], + + "brace-expansion": ["brace-expansion@1.1.11", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA=="], + + "braces": ["braces@3.0.3", "", { "dependencies": { "fill-range": "^7.1.1" } }, "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA=="], + + "broken-link-checker": ["broken-link-checker@0.7.8", "", { "dependencies": { "bhttp": "^1.2.1", "calmcard": "~0.1.1", "chalk": "^1.1.3", "char-spinner": "^1.0.1", "condense-whitespace": "^1.0.0", "default-user-agent": "^1.0.0", "errno": "~0.1.4", "extend": "^3.0.0", "http-equiv-refresh": "^1.0.0", "humanize-duration": "^3.9.1", "is-stream": "^1.0.1", "is-string": "^1.0.4", "limited-request-queue": "^2.0.0", "link-types": "^1.1.0", "maybe-callback": "^2.1.0", "nopter": "~0.3.0", "parse5": "^3.0.2", "robot-directives": "~0.3.0", "robots-txt-guard": "~0.1.0", "robots-txt-parse": "~0.0.4", "urlcache": "~0.7.0", "urlobj": "0.0.11" }, "bin": { "blc": "bin/blc", "broken-link-checker": "bin/blc" } }, "sha512-/zH4/nLMNKDeDH5nVuf/R6WYd0Yjnar1NpcdAO2+VlwjGKzJa6y42C03UO+imBSHwe6BefSkVi82fImE2Rb7yg=="], + + "browserslist": ["browserslist@4.25.1", "", { "dependencies": { "caniuse-lite": "^1.0.30001726", "electron-to-chromium": "^1.5.173", "node-releases": "^2.0.19", "update-browserslist-db": "^1.1.3" }, "bin": "cli.js" }, "sha512-KGj0KoOMXLpSNkkEI6Z6mShmQy0bc1I+T7K9N81k4WWMrfz+6fQ6es80B/YLAeRoKvjYE1YSHHOW1qe9xIVzHw=="], + + "buffer-from": ["buffer-from@1.1.2", "", {}, "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="], + + "call-bind": ["call-bind@1.0.8", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.0", "es-define-property": "^1.0.0", "get-intrinsic": "^1.2.4", "set-function-length": "^1.2.2" } }, "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww=="], + + "call-bind-apply-helpers": ["call-bind-apply-helpers@1.0.2", "", { "dependencies": { "es-errors": "^1.3.0", "function-bind": "^1.1.2" } }, "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ=="], + + "call-bound": ["call-bound@1.0.4", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.2", "get-intrinsic": "^1.3.0" } }, "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg=="], + + "caller-path": ["caller-path@0.1.0", "", { "dependencies": { "callsites": "^0.2.0" } }, "sha512-UJiE1otjXPF5/x+T3zTnSFiTOEmJoGTD9HmBoxnCUwho61a2eSNn/VwtwuIBDAo2SEOv1AJ7ARI5gCmohFLu/g=="], + + "callsites": ["callsites@0.2.0", "", {}, "sha512-Zv4Dns9IbXXmPkgRRUjAaJQgfN4xX5p6+RQFhWUqscdvvK2xK/ZL8b3IXIJsj+4sD+f24NwnWy2BY8AJ82JB0A=="], + + "calmcard": ["calmcard@0.1.1", "", {}, "sha512-Ol6L8HQ0n1qFAOmuXcXcOXVpcQ+x5/N8ff+i6G76a4sDjRVtCWmpsG6RorloS1vVG9O0IGq9l7sqaxBnwG/LUA=="], + + "camelcase": ["camelcase@1.2.1", "", {}, "sha512-wzLkDa4K/mzI1OSITC+DUyjgIl/ETNHE9QvYgy6J6Jvqyyz4C0Xfd+lQhb19sX2jMpZV4IssUn0VDVmglV+s4g=="], + + "camelcase-css": ["camelcase-css@2.0.1", "", {}, "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA=="], + + "camelize": ["camelize@1.0.1", "", {}, "sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ=="], + + "caniuse-lite": ["caniuse-lite@1.0.30001731", "", {}, "sha512-lDdp2/wrOmTRWuoB5DpfNkC0rJDU8DqRa6nYL6HK6sytw70QMopt/NIc/9SM7ylItlBWfACXk0tEn37UWM/+mg=="], + + "ccount": ["ccount@2.0.1", "", {}, "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg=="], + + "chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], + + "char-spinner": ["char-spinner@1.0.1", "", {}, "sha512-acv43vqJ0+N0rD+Uw3pDHSxP30FHrywu2NO6/wBaHChJIizpDeBUd6NjqhNhy9LGaEAhZAXn46QzmlAvIWd16g=="], + + "character-entities": ["character-entities@2.0.2", "", {}, "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ=="], + + "character-entities-html4": ["character-entities-html4@2.1.0", "", {}, "sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA=="], + + "character-entities-legacy": ["character-entities-legacy@3.0.0", "", {}, "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ=="], + + "character-reference-invalid": ["character-reference-invalid@2.0.1", "", {}, "sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw=="], + + "chokidar": ["chokidar@3.6.0", "", { "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", "glob-parent": "~5.1.2", "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", "normalize-path": "~3.0.0", "readdirp": "~3.6.0" }, "optionalDependencies": { "fsevents": "~2.3.2" } }, "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw=="], + + "class-variance-authority": ["class-variance-authority@0.7.1", "", { "dependencies": { "clsx": "^2.1.1" } }, "sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg=="], + + "cli-table": ["cli-table@0.3.11", "", { "dependencies": { "colors": "1.0.3" } }, "sha512-IqLQi4lO0nIB4tcdTpN4LCB9FI3uqrJZK7RC515EnhZ6qBaglkIgICb1wjeAqpdoOabm1+SuQtkXIPdYC93jhQ=="], + + "client-only": ["client-only@0.0.1", "", {}, "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA=="], + + "clsx": ["clsx@2.1.1", "", {}, "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA=="], + + "cmdk": ["cmdk@1.1.1", "", { "dependencies": { "@radix-ui/react-compose-refs": "^1.1.1", "@radix-ui/react-dialog": "^1.1.6", "@radix-ui/react-id": "^1.1.0", "@radix-ui/react-primitive": "^2.0.2" }, "peerDependencies": { "react": "^18 || ^19 || ^19.0.0-rc", "react-dom": "^18 || ^19 || ^19.0.0-rc" } }, "sha512-Vsv7kFaXm+ptHDMZ7izaRsP70GgrW9NBNGswt9OZaVBLlE0SNpDq8eu/VGXyF9r7M0azK3Wy7OlYXsuyYLFzHg=="], + + "collapse-white-space": ["collapse-white-space@2.1.0", "", {}, "sha512-loKTxY1zCOuG4j9f6EPnuyyYkf58RnhhWTvRoZEokgB+WbdXehfjFviyOVYkqzEWz1Q5kRiZdBYS5SwxbQYwzw=="], + + "color": ["color@4.2.3", "", { "dependencies": { "color-convert": "^2.0.1", "color-string": "^1.9.0" } }, "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A=="], + + "color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="], + + "color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="], + + "color-string": ["color-string@1.9.1", "", { "dependencies": { "color-name": "^1.0.0", "simple-swizzle": "^0.2.2" } }, "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg=="], + + "colors": ["colors@1.0.3", "", {}, "sha512-pFGrxThWcWQ2MsAz6RtgeWe4NK2kUE1WfsrvvlctdII745EW9I0yflqhe7++M5LEc7bV2c/9/5zc8sFcpL0Drw=="], + + "combined-stream2": ["combined-stream2@1.1.2", "", { "dependencies": { "bluebird": "^2.8.1", "debug": "^2.1.1", "stream-length": "^1.0.1" } }, "sha512-sVqUHJmbdVm+HZWy4l34BPLczxI4fltN4Bm2vcvASsqBIXW4xFb4TRkwM8bw/UUXK9/OdHdAwi2cRYVEKrxzbg=="], + + "comma-separated-tokens": ["comma-separated-tokens@2.0.3", "", {}, "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg=="], + + "commander": ["commander@4.1.1", "", {}, "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA=="], + + "concat-map": ["concat-map@0.0.1", "", {}, "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="], + + "concat-stream": ["concat-stream@1.6.2", "", { "dependencies": { "buffer-from": "^1.0.0", "inherits": "^2.0.3", "readable-stream": "^2.2.2", "typedarray": "^0.0.6" } }, "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw=="], + + "condense-whitespace": ["condense-whitespace@1.0.0", "", {}, "sha512-1eu4eAfuH4oongidVWOX8EkYUxTmav9SpEW1YUeNVWzrdgJTEoXFnF7WuLL+sI9SSQdfnKWjObAn/g9SkseUiw=="], + + "core-util-is": ["core-util-is@1.0.3", "", {}, "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ=="], + + "create-require": ["create-require@1.1.1", "", {}, "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ=="], + + "cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="], + + "css-background-parser": ["css-background-parser@0.1.0", "", {}, "sha512-2EZLisiZQ+7m4wwur/qiYJRniHX4K5Tc9w93MT3AS0WS1u5kaZ4FKXlOTBhOjc+CgEgPiGY+fX1yWD8UwpEqUA=="], + + "css-box-shadow": ["css-box-shadow@1.0.0-3", "", {}, "sha512-9jaqR6e7Ohds+aWwmhe6wILJ99xYQbfmK9QQB9CcMjDbTxPZjwEmUQpU91OG05Xgm8BahT5fW+svbsQGjS/zPg=="], + + "css-color-keywords": ["css-color-keywords@1.0.0", "", {}, "sha512-FyyrDHZKEjXDpNJYvVsV960FiqQyXc/LlYmsxl2BcdMb2WPx0OGRVgTg55rPSyLSNMqP52R9r8geSp7apN3Ofg=="], + + "css-gradient-parser": ["css-gradient-parser@0.0.16", "", {}, "sha512-3O5QdqgFRUbXvK1x5INf1YkBz1UKSWqrd63vWsum8MNHDBYD5urm3QtxZbKU259OrEXNM26lP/MPY3d1IGkBgA=="], + + "css-to-react-native": ["css-to-react-native@3.2.0", "", { "dependencies": { "camelize": "^1.0.0", "css-color-keywords": "^1.0.0", "postcss-value-parser": "^4.0.2" } }, "sha512-e8RKaLXMOFii+02mOlqwjbD00KSEKqblnpO9e++1aXS1fPQOpS1YoqdVHBqPjHNoxeF2mimzVqawm2KCbEdtHQ=="], + + "cssesc": ["cssesc@3.0.0", "", { "bin": "bin/cssesc" }, "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg=="], + + "csstype": ["csstype@3.1.3", "", {}, "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="], + + "damerau-levenshtein": ["damerau-levenshtein@1.0.8", "", {}, "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA=="], + + "data-view-buffer": ["data-view-buffer@1.0.2", "", { "dependencies": { "call-bound": "^1.0.3", "es-errors": "^1.3.0", "is-data-view": "^1.0.2" } }, "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ=="], + + "data-view-byte-length": ["data-view-byte-length@1.0.2", "", { "dependencies": { "call-bound": "^1.0.3", "es-errors": "^1.3.0", "is-data-view": "^1.0.2" } }, "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ=="], + + "data-view-byte-offset": ["data-view-byte-offset@1.0.1", "", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "is-data-view": "^1.0.1" } }, "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ=="], + + "debug": ["debug@4.3.4", "", { "dependencies": { "ms": "2.1.2" } }, "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ=="], + + "decode-named-character-reference": ["decode-named-character-reference@1.0.2", "", { "dependencies": { "character-entities": "^2.0.0" } }, "sha512-O8x12RzrUF8xyVcY0KJowWsmaJxQbmy0/EtnNtHRpsOcT7dFk5W598coHqBVpmWo1oQQfsCqfCmkZN5DJrZVdg=="], + + "deep-is": ["deep-is@0.1.4", "", {}, "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ=="], + + "default-user-agent": ["default-user-agent@1.0.0", "", { "dependencies": { "os-name": "~1.0.3" } }, "sha512-bDF7bg6OSNcSwFWPu4zYKpVkJZQYVrAANMYB8bc9Szem1D0yKdm4sa/rOCs2aC9+2GMqQ7KnwtZRvDhmLF0dXw=="], + + "define-data-property": ["define-data-property@1.1.4", "", { "dependencies": { "es-define-property": "^1.0.0", "es-errors": "^1.3.0", "gopd": "^1.0.1" } }, "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A=="], + + "define-properties": ["define-properties@1.2.1", "", { "dependencies": { "define-data-property": "^1.0.1", "has-property-descriptors": "^1.0.0", "object-keys": "^1.1.1" } }, "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg=="], + + "dequal": ["dequal@2.0.3", "", {}, "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA=="], + + "detect-libc": ["detect-libc@2.0.4", "", {}, "sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA=="], + + "detect-node-es": ["detect-node-es@1.1.0", "", {}, "sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ=="], + + "dev-null": ["dev-null@0.1.1", "", {}, "sha512-nMNZG0zfMgmdv8S5O0TM5cpwNbGKRGPCxVsr0SmA3NZZy9CYBbuNLL0PD3Acx9e5LIUgwONXtM9kM6RlawPxEQ=="], + + "devlop": ["devlop@1.1.0", "", { "dependencies": { "dequal": "^2.0.0" } }, "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA=="], + + "didyoumean": ["didyoumean@1.2.2", "", {}, "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw=="], + + "diff": ["diff@4.0.2", "", {}, "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A=="], + + "dlv": ["dlv@1.1.3", "", {}, "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA=="], + + "doctrine": ["doctrine@2.1.0", "", { "dependencies": { "esutils": "^2.0.2" } }, "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw=="], + + "dunder-proto": ["dunder-proto@1.0.1", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.1", "es-errors": "^1.3.0", "gopd": "^1.2.0" } }, "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A=="], + + "duplexer": ["duplexer@0.1.2", "", {}, "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg=="], + + "eastasianwidth": ["eastasianwidth@0.2.0", "", {}, "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA=="], + + "electron-to-chromium": ["electron-to-chromium@1.5.199", "", {}, "sha512-3gl0S7zQd88kCAZRO/DnxtBKuhMO4h0EaQIN3YgZfV6+pW+5+bf2AdQeHNESCoaQqo/gjGVYEf2YM4O5HJQqpQ=="], + + "emoji-regex": ["emoji-regex@9.2.2", "", {}, "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="], + + "emoji-regex-xs": ["emoji-regex-xs@2.0.1", "", {}, "sha512-1QFuh8l7LqUcKe24LsPUNzjrzJQ7pgRwp1QMcZ5MX6mFplk2zQ08NVCM84++1cveaUUYtcCYHmeFEuNg16sU4g=="], + + "entities": ["entities@4.5.0", "", {}, "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="], + + "eol": ["eol@0.2.0", "", {}, "sha512-LCBxmDyUDh5pAXALohe9NCwyedyECwpFrcebZyW/XNTzn4WZFY3cX9MdkrJQu71ojEoHqcsciqFG7d3WQA+1Ew=="], + + "errno": ["errno@0.1.8", "", { "dependencies": { "prr": "~1.0.1" }, "bin": "cli.js" }, "sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A=="], + + "errors": ["errors@0.2.0", "", {}, "sha512-W0w4yTo+twP/wGTF25kBGAXroAHzvxZvEDHJsCixlWS8lf8li0aZDhT+hz0mHQwsSW5esD5jyTQkaqA0ZHF83A=="], + + "es-abstract": ["es-abstract@1.24.0", "", { "dependencies": { "array-buffer-byte-length": "^1.0.2", "arraybuffer.prototype.slice": "^1.0.4", "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.8", "call-bound": "^1.0.4", "data-view-buffer": "^1.0.2", "data-view-byte-length": "^1.0.2", "data-view-byte-offset": "^1.0.1", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.1.1", "es-set-tostringtag": "^2.1.0", "es-to-primitive": "^1.3.0", "function.prototype.name": "^1.1.8", "get-intrinsic": "^1.3.0", "get-proto": "^1.0.1", "get-symbol-description": "^1.1.0", "globalthis": "^1.0.4", "gopd": "^1.2.0", "has-property-descriptors": "^1.0.2", "has-proto": "^1.2.0", "has-symbols": "^1.1.0", "hasown": "^2.0.2", "internal-slot": "^1.1.0", "is-array-buffer": "^3.0.5", "is-callable": "^1.2.7", "is-data-view": "^1.0.2", "is-negative-zero": "^2.0.3", "is-regex": "^1.2.1", "is-set": "^2.0.3", "is-shared-array-buffer": "^1.0.4", "is-string": "^1.1.1", "is-typed-array": "^1.1.15", "is-weakref": "^1.1.1", "math-intrinsics": "^1.1.0", "object-inspect": "^1.13.4", "object-keys": "^1.1.1", "object.assign": "^4.1.7", "own-keys": "^1.0.1", "regexp.prototype.flags": "^1.5.4", "safe-array-concat": "^1.1.3", "safe-push-apply": "^1.0.0", "safe-regex-test": "^1.1.0", "set-proto": "^1.0.0", "stop-iteration-iterator": "^1.1.0", "string.prototype.trim": "^1.2.10", "string.prototype.trimend": "^1.0.9", "string.prototype.trimstart": "^1.0.8", "typed-array-buffer": "^1.0.3", "typed-array-byte-length": "^1.0.3", "typed-array-byte-offset": "^1.0.4", "typed-array-length": "^1.0.7", "unbox-primitive": "^1.1.0", "which-typed-array": "^1.1.19" } }, "sha512-WSzPgsdLtTcQwm4CROfS5ju2Wa1QQcVeT37jFjYzdFz1r9ahadC8B8/a4qxJxM+09F18iumCdRmlr96ZYkQvEg=="], + + "es-define-property": ["es-define-property@1.0.1", "", {}, "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g=="], + + "es-errors": ["es-errors@1.3.0", "", {}, "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw=="], + + "es-iterator-helpers": ["es-iterator-helpers@1.2.1", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.3", "define-properties": "^1.2.1", "es-abstract": "^1.23.6", "es-errors": "^1.3.0", "es-set-tostringtag": "^2.0.3", "function-bind": "^1.1.2", "get-intrinsic": "^1.2.6", "globalthis": "^1.0.4", "gopd": "^1.2.0", "has-property-descriptors": "^1.0.2", "has-proto": "^1.2.0", "has-symbols": "^1.1.0", "internal-slot": "^1.1.0", "iterator.prototype": "^1.1.4", "safe-array-concat": "^1.1.3" } }, "sha512-uDn+FE1yrDzyC0pCo961B2IHbdM8y/ACZsKD4dG6WqrjV53BADjwa7D+1aom2rsNVfLyDgU/eigvlJGJ08OQ4w=="], + + "es-object-atoms": ["es-object-atoms@1.1.1", "", { "dependencies": { "es-errors": "^1.3.0" } }, "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA=="], + + "es-set-tostringtag": ["es-set-tostringtag@2.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "get-intrinsic": "^1.2.6", "has-tostringtag": "^1.0.2", "hasown": "^2.0.2" } }, "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA=="], + + "es-shim-unscopables": ["es-shim-unscopables@1.1.0", "", { "dependencies": { "hasown": "^2.0.2" } }, "sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw=="], + + "es-to-primitive": ["es-to-primitive@1.3.0", "", { "dependencies": { "is-callable": "^1.2.7", "is-date-object": "^1.0.5", "is-symbol": "^1.0.4" } }, "sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g=="], + + "esbuild": ["esbuild@0.25.0", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.0", "@esbuild/android-arm": "0.25.0", "@esbuild/android-arm64": "0.25.0", "@esbuild/android-x64": "0.25.0", "@esbuild/darwin-arm64": "0.25.0", "@esbuild/darwin-x64": "0.25.0", "@esbuild/freebsd-arm64": "0.25.0", "@esbuild/freebsd-x64": "0.25.0", "@esbuild/linux-arm": "0.25.0", "@esbuild/linux-arm64": "0.25.0", "@esbuild/linux-ia32": "0.25.0", "@esbuild/linux-loong64": "0.25.0", "@esbuild/linux-mips64el": "0.25.0", "@esbuild/linux-ppc64": "0.25.0", "@esbuild/linux-riscv64": "0.25.0", "@esbuild/linux-s390x": "0.25.0", "@esbuild/linux-x64": "0.25.0", "@esbuild/netbsd-arm64": "0.25.0", "@esbuild/netbsd-x64": "0.25.0", "@esbuild/openbsd-arm64": "0.25.0", "@esbuild/openbsd-x64": "0.25.0", "@esbuild/sunos-x64": "0.25.0", "@esbuild/win32-arm64": "0.25.0", "@esbuild/win32-ia32": "0.25.0", "@esbuild/win32-x64": "0.25.0" }, "bin": "bin/esbuild" }, "sha512-BXq5mqc8ltbaN34cDqWuYKyNhX8D/Z0J1xdtdQ8UcIIIyJyz+ZMKUt58tF3SrZ85jcfN/PZYhjR5uDQAYNVbuw=="], + + "escalade": ["escalade@3.2.0", "", {}, "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA=="], + + "escape-html": ["escape-html@1.0.3", "", {}, "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow=="], + + "escape-string-regexp": ["escape-string-regexp@4.0.0", "", {}, "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA=="], + + "eslint": ["eslint@9.32.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.12.1", "@eslint/config-array": "^0.21.0", "@eslint/config-helpers": "^0.3.0", "@eslint/core": "^0.15.0", "@eslint/eslintrc": "^3.3.1", "@eslint/js": "9.32.0", "@eslint/plugin-kit": "^0.3.4", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", "@types/estree": "^1.0.6", "@types/json-schema": "^7.0.15", "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", "eslint-scope": "^8.4.0", "eslint-visitor-keys": "^4.2.1", "espree": "^10.4.0", "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^8.0.0", "find-up": "^5.0.0", "glob-parent": "^6.0.2", "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "json-stable-stringify-without-jsonify": "^1.0.1", "lodash.merge": "^4.6.2", "minimatch": "^3.1.2", "natural-compare": "^1.4.0", "optionator": "^0.9.3" }, "peerDependencies": { "jiti": "*" }, "bin": "bin/eslint.js" }, "sha512-LSehfdpgMeWcTZkWZVIJl+tkZ2nuSkyyB9C27MZqFWXuph7DvaowgcTvKqxvpLW1JZIk8PN7hFY3Rj9LQ7m7lg=="], + + "eslint-config-next": ["eslint-config-next@15.4.6", "", { "dependencies": { "@next/eslint-plugin-next": "15.4.6", "@rushstack/eslint-patch": "^1.10.3", "@typescript-eslint/eslint-plugin": "^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0", "@typescript-eslint/parser": "^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0", "eslint-import-resolver-node": "^0.3.6", "eslint-import-resolver-typescript": "^3.5.2", "eslint-plugin-import": "^2.31.0", "eslint-plugin-jsx-a11y": "^6.10.0", "eslint-plugin-react": "^7.37.0", "eslint-plugin-react-hooks": "^5.0.0" }, "peerDependencies": { "eslint": "^7.23.0 || ^8.0.0 || ^9.0.0", "typescript": ">=3.3.1" } }, "sha512-4uznvw5DlTTjrZgYZjMciSdDDMO2SWIuQgUNaFyC2O3Zw3Z91XeIejeVa439yRq2CnJb/KEvE4U2AeN/66FpUA=="], + + "eslint-import-resolver-node": ["eslint-import-resolver-node@0.3.9", "", { "dependencies": { "debug": "^3.2.7", "is-core-module": "^2.13.0", "resolve": "^1.22.4" } }, "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g=="], + + "eslint-import-resolver-typescript": ["eslint-import-resolver-typescript@3.10.1", "", { "dependencies": { "@nolyfill/is-core-module": "1.0.39", "debug": "^4.4.0", "get-tsconfig": "^4.10.0", "is-bun-module": "^2.0.0", "stable-hash": "^0.0.5", "tinyglobby": "^0.2.13", "unrs-resolver": "^1.6.2" }, "peerDependencies": { "eslint": "*", "eslint-plugin-import": "*", "eslint-plugin-import-x": "*" }, "optionalPeers": ["eslint-plugin-import-x"] }, "sha512-A1rHYb06zjMGAxdLSkN2fXPBwuSaQ0iO5M/hdyS0Ajj1VBaRp0sPD3dn1FhME3c/JluGFbwSxyCfqdSbtQLAHQ=="], + + "eslint-module-utils": ["eslint-module-utils@2.12.1", "", { "dependencies": { "debug": "^3.2.7" } }, "sha512-L8jSWTze7K2mTg0vos/RuLRS5soomksDPoJLXIslC7c8Wmut3bx7CPpJijDcBZtxQ5lrbUdM+s0OlNbz0DCDNw=="], + + "eslint-plugin-import": ["eslint-plugin-import@2.32.0", "", { "dependencies": { "@rtsao/scc": "^1.1.0", "array-includes": "^3.1.9", "array.prototype.findlastindex": "^1.2.6", "array.prototype.flat": "^1.3.3", "array.prototype.flatmap": "^1.3.3", "debug": "^3.2.7", "doctrine": "^2.1.0", "eslint-import-resolver-node": "^0.3.9", "eslint-module-utils": "^2.12.1", "hasown": "^2.0.2", "is-core-module": "^2.16.1", "is-glob": "^4.0.3", "minimatch": "^3.1.2", "object.fromentries": "^2.0.8", "object.groupby": "^1.0.3", "object.values": "^1.2.1", "semver": "^6.3.1", "string.prototype.trimend": "^1.0.9", "tsconfig-paths": "^3.15.0" }, "peerDependencies": { "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9" } }, "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA=="], + + "eslint-plugin-jsx-a11y": ["eslint-plugin-jsx-a11y@6.10.2", "", { "dependencies": { "aria-query": "^5.3.2", "array-includes": "^3.1.8", "array.prototype.flatmap": "^1.3.2", "ast-types-flow": "^0.0.8", "axe-core": "^4.10.0", "axobject-query": "^4.1.0", "damerau-levenshtein": "^1.0.8", "emoji-regex": "^9.2.2", "hasown": "^2.0.2", "jsx-ast-utils": "^3.3.5", "language-tags": "^1.0.9", "minimatch": "^3.1.2", "object.fromentries": "^2.0.8", "safe-regex-test": "^1.0.3", "string.prototype.includes": "^2.0.1" }, "peerDependencies": { "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9" } }, "sha512-scB3nz4WmG75pV8+3eRUQOHZlNSUhFNq37xnpgRkCCELU3XMvXAxLk1eqWWyE22Ki4Q01Fnsw9BA3cJHDPgn2Q=="], + + "eslint-plugin-react": ["eslint-plugin-react@7.37.5", "", { "dependencies": { "array-includes": "^3.1.8", "array.prototype.findlast": "^1.2.5", "array.prototype.flatmap": "^1.3.3", "array.prototype.tosorted": "^1.1.4", "doctrine": "^2.1.0", "es-iterator-helpers": "^1.2.1", "estraverse": "^5.3.0", "hasown": "^2.0.2", "jsx-ast-utils": "^2.4.1 || ^3.0.0", "minimatch": "^3.1.2", "object.entries": "^1.1.9", "object.fromentries": "^2.0.8", "object.values": "^1.2.1", "prop-types": "^15.8.1", "resolve": "^2.0.0-next.5", "semver": "^6.3.1", "string.prototype.matchall": "^4.0.12", "string.prototype.repeat": "^1.0.0" }, "peerDependencies": { "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7" } }, "sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA=="], + + "eslint-plugin-react-hooks": ["eslint-plugin-react-hooks@5.2.0", "", { "peerDependencies": { "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0" } }, "sha512-+f15FfK64YQwZdJNELETdn5ibXEUQmW1DZL6KXhNnc2heoy/sg9VJJeT7n8TlMWouzWqSWavFkIhHyIbIAEapg=="], + + "eslint-scope": ["eslint-scope@8.4.0", "", { "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" } }, "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg=="], + + "eslint-visitor-keys": ["eslint-visitor-keys@4.2.1", "", {}, "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ=="], + + "espree": ["espree@10.4.0", "", { "dependencies": { "acorn": "^8.15.0", "acorn-jsx": "^5.3.2", "eslint-visitor-keys": "^4.2.1" } }, "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ=="], + + "esprima": ["esprima@4.0.1", "", { "bin": { "esparse": "bin/esparse.js", "esvalidate": "bin/esvalidate.js" } }, "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A=="], + + "esquery": ["esquery@1.5.0", "", { "dependencies": { "estraverse": "^5.1.0" } }, "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg=="], + + "esrecurse": ["esrecurse@4.3.0", "", { "dependencies": { "estraverse": "^5.2.0" } }, "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag=="], + + "estraverse": ["estraverse@5.3.0", "", {}, "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA=="], + + "estree-util-attach-comments": ["estree-util-attach-comments@3.0.0", "", { "dependencies": { "@types/estree": "^1.0.0" } }, "sha512-cKUwm/HUcTDsYh/9FgnuFqpfquUbwIqwKM26BVCGDPVgvaCl/nDCCjUfiLlx6lsEZ3Z4RFxNbOQ60pkaEwFxGw=="], + + "estree-util-build-jsx": ["estree-util-build-jsx@3.0.1", "", { "dependencies": { "@types/estree-jsx": "^1.0.0", "devlop": "^1.0.0", "estree-util-is-identifier-name": "^3.0.0", "estree-walker": "^3.0.0" } }, "sha512-8U5eiL6BTrPxp/CHbs2yMgP8ftMhR5ww1eIKoWRMlqvltHF8fZn5LRDvTKuxD3DUn+shRbLGqXemcP51oFCsGQ=="], + + "estree-util-is-identifier-name": ["estree-util-is-identifier-name@3.0.0", "", {}, "sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg=="], + + "estree-util-to-js": ["estree-util-to-js@2.0.0", "", { "dependencies": { "@types/estree-jsx": "^1.0.0", "astring": "^1.8.0", "source-map": "^0.7.0" } }, "sha512-WDF+xj5rRWmD5tj6bIqRi6CkLIXbbNQUcxQHzGysQzvHmdYG2G7p/Tf0J0gpxGgkeMZNTIjT/AoSvC9Xehcgdg=="], + + "estree-util-visit": ["estree-util-visit@2.0.0", "", { "dependencies": { "@types/estree-jsx": "^1.0.0", "@types/unist": "^3.0.0" } }, "sha512-m5KgiH85xAhhW8Wta0vShLcUvOsh3LLPI2YVwcbio1l7E09NTLL1EyMZFM1OyWowoH0skScNbhOPl4kcBgzTww=="], + + "estree-walker": ["estree-walker@3.0.3", "", { "dependencies": { "@types/estree": "^1.0.0" } }, "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g=="], + + "esutils": ["esutils@2.0.3", "", {}, "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g=="], + + "extend": ["extend@3.0.2", "", {}, "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="], + + "extend-shallow": ["extend-shallow@2.0.1", "", { "dependencies": { "is-extendable": "^0.1.0" } }, "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug=="], + + "fast-deep-equal": ["fast-deep-equal@3.1.3", "", {}, "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="], + + "fast-glob": ["fast-glob@3.3.3", "", { "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", "micromatch": "^4.0.8" } }, "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg=="], + + "fast-json-stable-stringify": ["fast-json-stable-stringify@2.1.0", "", {}, "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="], + + "fast-levenshtein": ["fast-levenshtein@2.0.6", "", {}, "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw=="], + + "fastq": ["fastq@1.19.1", "", { "dependencies": { "reusify": "^1.0.4" } }, "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ=="], + + "fdir": ["fdir@6.4.6", "", { "peerDependencies": { "picomatch": "^3 || ^4" } }, "sha512-hiFoqpyZcfNm1yc4u8oWCf9A2c4D3QjCrks3zmoVKVxpQRzmPNar1hUJcBG2RQHvEVGDN+Jm81ZheVLAQMK6+w=="], + + "fflate": ["fflate@0.7.4", "", {}, "sha512-5u2V/CDW15QM1XbbgS+0DfPxVB+jUKhWEKuuFuHncbk3tEEqzmoXL+2KyOFuKGqOnmdIy0/davWF1CkuwtibCw=="], + + "file-entry-cache": ["file-entry-cache@8.0.0", "", { "dependencies": { "flat-cache": "^4.0.0" } }, "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ=="], + + "fill-range": ["fill-range@7.1.1", "", { "dependencies": { "to-regex-range": "^5.0.1" } }, "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg=="], + + "find-up": ["find-up@5.0.0", "", { "dependencies": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" } }, "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng=="], + + "flat-cache": ["flat-cache@4.0.1", "", { "dependencies": { "flatted": "^3.2.9", "keyv": "^4.5.4" } }, "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw=="], + + "flatted": ["flatted@3.3.3", "", {}, "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg=="], + + "for-each": ["for-each@0.3.5", "", { "dependencies": { "is-callable": "^1.2.7" } }, "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg=="], + + "foreground-child": ["foreground-child@3.3.1", "", { "dependencies": { "cross-spawn": "^7.0.6", "signal-exit": "^4.0.1" } }, "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw=="], + + "form-data2": ["form-data2@1.0.4", "", { "dependencies": { "bluebird": "^2.8.2", "combined-stream2": "^1.0.2", "debug": "^2.1.1", "mime": "^1.3.4", "uuid": "^2.0.1" } }, "sha512-buz4C3F6/7Vpdxt7dNU/tSfjQO/5z9Pyjfb43VhlVvSos5zVhCcMuW9sF1yJ2FdxZRCD2sWQ9WhqUiYLt+AUVQ=="], + + "form-fix-array": ["form-fix-array@1.0.0", "", {}, "sha512-f3qXI4CcvW7/6vqTKwCftcrFgfEBfWYPQTfvXrHYevHbJVfc107/SVvXvwUAYMaUAHdvu9ENQvLufJKphQI14w=="], + + "fraction.js": ["fraction.js@4.3.7", "", {}, "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew=="], + + "fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="], + + "function-bind": ["function-bind@1.1.2", "", {}, "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="], + + "function.prototype.name": ["function.prototype.name@1.1.8", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.3", "define-properties": "^1.2.1", "functions-have-names": "^1.2.3", "hasown": "^2.0.2", "is-callable": "^1.2.7" } }, "sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q=="], + + "functions-have-names": ["functions-have-names@1.2.3", "", {}, "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ=="], + + "get-intrinsic": ["get-intrinsic@1.3.0", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.2", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.1.1", "function-bind": "^1.1.2", "get-proto": "^1.0.1", "gopd": "^1.2.0", "has-symbols": "^1.1.0", "hasown": "^2.0.2", "math-intrinsics": "^1.1.0" } }, "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ=="], + + "get-nonce": ["get-nonce@1.0.1", "", {}, "sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q=="], + + "get-proto": ["get-proto@1.0.1", "", { "dependencies": { "dunder-proto": "^1.0.1", "es-object-atoms": "^1.0.0" } }, "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g=="], + + "get-symbol-description": ["get-symbol-description@1.1.0", "", { "dependencies": { "call-bound": "^1.0.3", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.6" } }, "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg=="], + + "get-tsconfig": ["get-tsconfig@4.10.0", "", { "dependencies": { "resolve-pkg-maps": "^1.0.0" } }, "sha512-kGzZ3LWWQcGIAmg6iWvXn0ei6WDtV26wzHRMwDSzmAbcXrTEXxHy6IehI6/4eT6VRKyMP1eF1VqwrVUmE/LR7A=="], + + "github-slugger": ["github-slugger@2.0.0", "", {}, "sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw=="], + + "glob": ["glob@10.4.5", "", { "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^3.1.2", "minimatch": "^9.0.4", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^1.11.1" }, "bin": "dist/esm/bin.mjs" }, "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg=="], + + "glob-parent": ["glob-parent@6.0.2", "", { "dependencies": { "is-glob": "^4.0.3" } }, "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A=="], + + "globals": ["globals@14.0.0", "", {}, "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ=="], + + "globalthis": ["globalthis@1.0.4", "", { "dependencies": { "define-properties": "^1.2.1", "gopd": "^1.0.1" } }, "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ=="], + + "gopd": ["gopd@1.2.0", "", {}, "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg=="], + + "graphemer": ["graphemer@1.4.0", "", {}, "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag=="], + + "gray-matter": ["gray-matter@4.0.3", "", { "dependencies": { "js-yaml": "^3.13.1", "kind-of": "^6.0.2", "section-matter": "^1.0.0", "strip-bom-string": "^1.0.0" } }, "sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q=="], + + "has-ansi": ["has-ansi@2.0.0", "", { "dependencies": { "ansi-regex": "^2.0.0" } }, "sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg=="], + + "has-bigints": ["has-bigints@1.0.2", "", {}, "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ=="], + + "has-flag": ["has-flag@4.0.0", "", {}, "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="], + + "has-property-descriptors": ["has-property-descriptors@1.0.2", "", { "dependencies": { "es-define-property": "^1.0.0" } }, "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg=="], + + "has-proto": ["has-proto@1.2.0", "", { "dependencies": { "dunder-proto": "^1.0.0" } }, "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ=="], + + "has-symbols": ["has-symbols@1.1.0", "", {}, "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ=="], + + "has-tostringtag": ["has-tostringtag@1.0.2", "", { "dependencies": { "has-symbols": "^1.0.3" } }, "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw=="], + + "hasown": ["hasown@2.0.2", "", { "dependencies": { "function-bind": "^1.1.2" } }, "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ=="], + + "hast": ["hast@1.0.0", "", {}, "sha512-vFUqlRV5C+xqP76Wwq2SrM0kipnmpxJm7OfvVXpB35Fp+Fn4MV+ozr+JZr5qFvyR1q/U+Foim2x+3P+x9S1PLA=="], + + "hast-util-from-html": ["hast-util-from-html@2.0.1", "", { "dependencies": { "@types/hast": "^3.0.0", "devlop": "^1.1.0", "hast-util-from-parse5": "^8.0.0", "parse5": "^7.0.0", "vfile": "^6.0.0", "vfile-message": "^4.0.0" } }, "sha512-RXQBLMl9kjKVNkJTIO6bZyb2n+cUH8LFaSSzo82jiLT6Tfc+Pt7VQCS+/h3YwG4jaNE2TA2sdJisGWR+aJrp0g=="], + + "hast-util-from-parse5": ["hast-util-from-parse5@8.0.1", "", { "dependencies": { "@types/hast": "^3.0.0", "@types/unist": "^3.0.0", "devlop": "^1.0.0", "hastscript": "^8.0.0", "property-information": "^6.0.0", "vfile": "^6.0.0", "vfile-location": "^5.0.0", "web-namespaces": "^2.0.0" } }, "sha512-Er/Iixbc7IEa7r/XLtuG52zoqn/b3Xng/w6aZQ0xGVxzhw5xUFxcRqdPzP6yFi/4HBYRaifaI5fQ1RH8n0ZeOQ=="], + + "hast-util-heading-rank": ["hast-util-heading-rank@3.0.0", "", { "dependencies": { "@types/hast": "^3.0.0" } }, "sha512-EJKb8oMUXVHcWZTDepnr+WNbfnXKFNf9duMesmr4S8SXTJBJ9M4Yok08pu9vxdJwdlGRhVumk9mEhkEvKGifwA=="], + + "hast-util-is-element": ["hast-util-is-element@3.0.0", "", { "dependencies": { "@types/hast": "^3.0.0" } }, "sha512-Val9mnv2IWpLbNPqc/pUem+a7Ipj2aHacCwgNfTiK0vJKl0LF+4Ba4+v1oPHFpf3bLYmreq0/l3Gud9S5OH42g=="], + + "hast-util-parse-selector": ["hast-util-parse-selector@3.1.1", "", { "dependencies": { "@types/hast": "^2.0.0" } }, "sha512-jdlwBjEexy1oGz0aJ2f4GKMaVKkA9jwjr4MjAAI22E5fM/TXVZHuS5OpONtdeIkRKqAaryQ2E9xNQxijoThSZA=="], + + "hast-util-to-estree": ["hast-util-to-estree@3.1.0", "", { "dependencies": { "@types/estree": "^1.0.0", "@types/estree-jsx": "^1.0.0", "@types/hast": "^3.0.0", "comma-separated-tokens": "^2.0.0", "devlop": "^1.0.0", "estree-util-attach-comments": "^3.0.0", "estree-util-is-identifier-name": "^3.0.0", "hast-util-whitespace": "^3.0.0", "mdast-util-mdx-expression": "^2.0.0", "mdast-util-mdx-jsx": "^3.0.0", "mdast-util-mdxjs-esm": "^2.0.0", "property-information": "^6.0.0", "space-separated-tokens": "^2.0.0", "style-to-object": "^0.4.0", "unist-util-position": "^5.0.0", "zwitch": "^2.0.0" } }, "sha512-lfX5g6hqVh9kjS/B9E2gSkvHH4SZNiQFiqWS0x9fENzEl+8W12RqdRxX6d/Cwxi30tPQs3bIO+aolQJNp1bIyw=="], + + "hast-util-to-jsx-runtime": ["hast-util-to-jsx-runtime@2.3.0", "", { "dependencies": { "@types/estree": "^1.0.0", "@types/hast": "^3.0.0", "@types/unist": "^3.0.0", "comma-separated-tokens": "^2.0.0", "devlop": "^1.0.0", "estree-util-is-identifier-name": "^3.0.0", "hast-util-whitespace": "^3.0.0", "mdast-util-mdx-expression": "^2.0.0", "mdast-util-mdx-jsx": "^3.0.0", "mdast-util-mdxjs-esm": "^2.0.0", "property-information": "^6.0.0", "space-separated-tokens": "^2.0.0", "style-to-object": "^1.0.0", "unist-util-position": "^5.0.0", "vfile-message": "^4.0.0" } }, "sha512-H/y0+IWPdsLLS738P8tDnrQ8Z+dj12zQQ6WC11TIM21C8WFVoIxcqWXf2H3hiTVZjF1AWqoimGwrTWecWrnmRQ=="], + + "hast-util-to-string": ["hast-util-to-string@3.0.0", "", { "dependencies": { "@types/hast": "^3.0.0" } }, "sha512-OGkAxX1Ua3cbcW6EJ5pT/tslVb90uViVkcJ4ZZIMW/R33DX/AkcJcRrPebPwJkHYwlDHXz4aIwvAAaAdtrACFA=="], + + "hast-util-whitespace": ["hast-util-whitespace@3.0.0", "", { "dependencies": { "@types/hast": "^3.0.0" } }, "sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw=="], + + "hastscript": ["hastscript@7.2.0", "", { "dependencies": { "@types/hast": "^2.0.0", "comma-separated-tokens": "^2.0.0", "hast-util-parse-selector": "^3.0.0", "property-information": "^6.0.0", "space-separated-tokens": "^2.0.0" } }, "sha512-TtYPq24IldU8iKoJQqvZOuhi5CyCQRAbvDOX0x1eW6rsHSxa/1i2CCiptNTotGHJ3VoHRGmqiv6/D3q113ikkw=="], + + "hex-rgb": ["hex-rgb@4.3.0", "", {}, "sha512-Ox1pJVrDCyGHMG9CFg1tmrRUMRPRsAWYc/PinY0XzJU4K7y7vjNoLKIQ7BR5UJMCxNN8EM1MNDmHWA/B3aZUuw=="], + + "highlight.js": ["highlight.js@11.11.1", "", {}, "sha512-Xwwo44whKBVCYoliBQwaPvtd/2tYFkRQtXDWj1nackaV2JPXx3L0+Jvd8/qCJ2p+ML0/XVkJ2q+Mr+UVdpJK5w=="], + + "http-equiv-refresh": ["http-equiv-refresh@1.0.0", "", {}, "sha512-TScO04soylRN9i/QdOdgZyhydXg9z6XdaGzEyOgDKycePeDeTT4KvigjBcI+tgfTlieLWauGORMq5F1eIDa+1w=="], + + "humanize-duration": ["humanize-duration@3.32.1", "", {}, "sha512-inh5wue5XdfObhu/IGEMiA1nUXigSGcaKNemcbLRKa7jXYGDZXr3LoT9pTIzq2hPEbld7w/qv9h+ikWGz8fL1g=="], + + "ignore": ["ignore@5.3.1", "", {}, "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw=="], + + "import-fresh": ["import-fresh@3.3.1", "", { "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" } }, "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ=="], + + "imurmurhash": ["imurmurhash@0.1.4", "", {}, "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA=="], + + "inherits": ["inherits@2.0.4", "", {}, "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="], + + "inline-style-parser": ["inline-style-parser@0.1.1", "", {}, "sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q=="], + + "internal-slot": ["internal-slot@1.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "hasown": "^2.0.2", "side-channel": "^1.1.0" } }, "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw=="], + + "is-alphabetical": ["is-alphabetical@2.0.1", "", {}, "sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ=="], + + "is-alphanumerical": ["is-alphanumerical@2.0.1", "", { "dependencies": { "is-alphabetical": "^2.0.0", "is-decimal": "^2.0.0" } }, "sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw=="], + + "is-array-buffer": ["is-array-buffer@3.0.5", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.3", "get-intrinsic": "^1.2.6" } }, "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A=="], + + "is-arrayish": ["is-arrayish@0.3.2", "", {}, "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ=="], + + "is-async-function": ["is-async-function@2.1.1", "", { "dependencies": { "async-function": "^1.0.0", "call-bound": "^1.0.3", "get-proto": "^1.0.1", "has-tostringtag": "^1.0.2", "safe-regex-test": "^1.1.0" } }, "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ=="], + + "is-bigint": ["is-bigint@1.1.0", "", { "dependencies": { "has-bigints": "^1.0.2" } }, "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ=="], + + "is-binary-path": ["is-binary-path@2.1.0", "", { "dependencies": { "binary-extensions": "^2.0.0" } }, "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw=="], + + "is-boolean-object": ["is-boolean-object@1.2.2", "", { "dependencies": { "call-bound": "^1.0.3", "has-tostringtag": "^1.0.2" } }, "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A=="], + + "is-browser": ["is-browser@2.1.0", "", {}, "sha512-F5rTJxDQ2sW81fcfOR1GnCXT6sVJC104fCyfj+mjpwNEwaPYSn5fte5jiHmBg3DHsIoL/l8Kvw5VN5SsTRcRFQ=="], + + "is-bun-module": ["is-bun-module@2.0.0", "", { "dependencies": { "semver": "^7.7.1" } }, "sha512-gNCGbnnnnFAUGKeZ9PdbyeGYJqewpmc2aKHUEMO5nQPWU9lOmv7jcmQIv+qHD8fXW6W7qfuCwX4rY9LNRjXrkQ=="], + + "is-callable": ["is-callable@1.2.7", "", {}, "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA=="], + + "is-core-module": ["is-core-module@2.16.1", "", { "dependencies": { "hasown": "^2.0.2" } }, "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w=="], + + "is-data-view": ["is-data-view@1.0.2", "", { "dependencies": { "call-bound": "^1.0.2", "get-intrinsic": "^1.2.6", "is-typed-array": "^1.1.13" } }, "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw=="], + + "is-date-object": ["is-date-object@1.1.0", "", { "dependencies": { "call-bound": "^1.0.2", "has-tostringtag": "^1.0.2" } }, "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg=="], + + "is-decimal": ["is-decimal@2.0.1", "", {}, "sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A=="], + + "is-extendable": ["is-extendable@0.1.1", "", {}, "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw=="], + + "is-extglob": ["is-extglob@2.1.1", "", {}, "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ=="], + + "is-finalizationregistry": ["is-finalizationregistry@1.1.1", "", { "dependencies": { "call-bound": "^1.0.3" } }, "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg=="], + + "is-fullwidth-code-point": ["is-fullwidth-code-point@3.0.0", "", {}, "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="], + + "is-generator-function": ["is-generator-function@1.1.0", "", { "dependencies": { "call-bound": "^1.0.3", "get-proto": "^1.0.0", "has-tostringtag": "^1.0.2", "safe-regex-test": "^1.1.0" } }, "sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ=="], + + "is-glob": ["is-glob@4.0.3", "", { "dependencies": { "is-extglob": "^2.1.1" } }, "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg=="], + + "is-hexadecimal": ["is-hexadecimal@2.0.1", "", {}, "sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg=="], + + "is-map": ["is-map@2.0.3", "", {}, "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw=="], + + "is-negative-zero": ["is-negative-zero@2.0.3", "", {}, "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw=="], + + "is-number": ["is-number@7.0.0", "", {}, "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="], + + "is-number-object": ["is-number-object@1.1.1", "", { "dependencies": { "call-bound": "^1.0.3", "has-tostringtag": "^1.0.2" } }, "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw=="], + + "is-object": ["is-object@1.0.2", "", {}, "sha512-2rRIahhZr2UWb45fIOuvZGpFtz0TyOZLf32KxBbSoUCeZR495zCKlWUKKUByk3geS2eAs7ZAABt0Y/Rx0GiQGA=="], + + "is-plain-obj": ["is-plain-obj@4.1.0", "", {}, "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg=="], + + "is-reference": ["is-reference@3.0.2", "", { "dependencies": { "@types/estree": "*" } }, "sha512-v3rht/LgVcsdZa3O2Nqs+NMowLOxeOm7Ay9+/ARQ2F+qEoANRcqrjAZKGN0v8ymUetZGgkp26LTnGT7H0Qo9Pg=="], + + "is-regex": ["is-regex@1.2.1", "", { "dependencies": { "call-bound": "^1.0.2", "gopd": "^1.2.0", "has-tostringtag": "^1.0.2", "hasown": "^2.0.2" } }, "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g=="], + + "is-set": ["is-set@2.0.3", "", {}, "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg=="], + + "is-shared-array-buffer": ["is-shared-array-buffer@1.0.4", "", { "dependencies": { "call-bound": "^1.0.3" } }, "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A=="], + + "is-stream": ["is-stream@1.1.0", "", {}, "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ=="], + + "is-string": ["is-string@1.1.1", "", { "dependencies": { "call-bound": "^1.0.3", "has-tostringtag": "^1.0.2" } }, "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA=="], + + "is-symbol": ["is-symbol@1.1.1", "", { "dependencies": { "call-bound": "^1.0.2", "has-symbols": "^1.1.0", "safe-regex-test": "^1.1.0" } }, "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w=="], + + "is-typed-array": ["is-typed-array@1.1.15", "", { "dependencies": { "which-typed-array": "^1.1.16" } }, "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ=="], + + "is-weakmap": ["is-weakmap@2.0.2", "", {}, "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w=="], + + "is-weakref": ["is-weakref@1.1.1", "", { "dependencies": { "call-bound": "^1.0.3" } }, "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew=="], + + "is-weakset": ["is-weakset@2.0.4", "", { "dependencies": { "call-bound": "^1.0.3", "get-intrinsic": "^1.2.6" } }, "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ=="], + + "isarray": ["isarray@2.0.5", "", {}, "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw=="], + + "isbot": ["isbot@2.5.7", "", {}, "sha512-8P+oGrRDvuCpDdovK9oD4skHmSXu56bsK17K2ovXrkW7Ic4H9Y4AqnUUqlXqZxcqQ2358kid9Rb+fbLH5yeeUw=="], + + "isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="], + + "iterator.prototype": ["iterator.prototype@1.1.5", "", { "dependencies": { "define-data-property": "^1.1.4", "es-object-atoms": "^1.0.0", "get-intrinsic": "^1.2.6", "get-proto": "^1.0.0", "has-symbols": "^1.1.0", "set-function-name": "^2.0.2" } }, "sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g=="], + + "jackspeak": ["jackspeak@3.4.3", "", { "dependencies": { "@isaacs/cliui": "^8.0.2" }, "optionalDependencies": { "@pkgjs/parseargs": "^0.11.0" } }, "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw=="], + + "jiti": ["jiti@1.21.7", "", { "bin": "bin/jiti.js" }, "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A=="], + + "js-tokens": ["js-tokens@4.0.0", "", {}, "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="], + + "js-yaml": ["js-yaml@3.14.1", "", { "dependencies": { "argparse": "^1.0.7", "esprima": "^4.0.0" }, "bin": "bin/js-yaml.js" }, "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g=="], + + "json-buffer": ["json-buffer@3.0.1", "", {}, "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ=="], + + "json-schema-traverse": ["json-schema-traverse@0.4.1", "", {}, "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="], + + "json-stable-stringify-without-jsonify": ["json-stable-stringify-without-jsonify@1.0.1", "", {}, "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw=="], + + "json5": ["json5@1.0.2", "", { "dependencies": { "minimist": "^1.2.0" }, "bin": "lib/cli.js" }, "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA=="], + + "jsx-ast-utils": ["jsx-ast-utils@3.3.5", "", { "dependencies": { "array-includes": "^3.1.6", "array.prototype.flat": "^1.3.1", "object.assign": "^4.1.4", "object.values": "^1.1.6" } }, "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ=="], + + "keyv": ["keyv@4.5.4", "", { "dependencies": { "json-buffer": "3.0.1" } }, "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw=="], + + "kind-of": ["kind-of@6.0.3", "", {}, "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw=="], + + "language-subtag-registry": ["language-subtag-registry@0.3.23", "", {}, "sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ=="], + + "language-tags": ["language-tags@1.0.9", "", { "dependencies": { "language-subtag-registry": "^0.3.20" } }, "sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA=="], + + "levn": ["levn@0.4.1", "", { "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" } }, "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ=="], + + "lilconfig": ["lilconfig@3.1.3", "", {}, "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw=="], + + "limited-request-queue": ["limited-request-queue@2.0.0", "", { "dependencies": { "is-browser": "^2.0.1", "parse-domain": "~0.2.0" } }, "sha512-dZC4pHSV4jdvtZDandTZiVj+FogwII50wbDVeROhLXxme46J7wNUAMPPIm3x66KAZSoVAHy31muBN+H6pco1Eg=="], + + "linebreak": ["linebreak@1.1.0", "", { "dependencies": { "base64-js": "0.0.8", "unicode-trie": "^2.0.0" } }, "sha512-MHp03UImeVhB7XZtjd0E4n6+3xr5Dq/9xI/5FptGk5FrbDR3zagPa2DS6U8ks/3HjbKWG9Q1M2ufOzxV2qLYSQ=="], + + "lines-and-columns": ["lines-and-columns@1.2.4", "", {}, "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg=="], + + "link-types": ["link-types@1.1.0", "", {}, "sha512-6R1evfF/YPACIF01Lb2Dm0v2GZbJo06+wX5v1TByKt2drvkI2A2LlOgAOG1T/rxTlGEO4rdOlSrQabxmy7tfNg=="], + + "locate-path": ["locate-path@6.0.0", "", { "dependencies": { "p-locate": "^5.0.0" } }, "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw=="], + + "lodash.castarray": ["lodash.castarray@4.4.0", "", {}, "sha512-aVx8ztPv7/2ULbArGJ2Y42bG1mEQ5mGjpdvrbJcJFU3TbYybe+QlLS4pst9zV52ymy2in1KpFPiZnAOATxD4+Q=="], + + "lodash.clonedeep": ["lodash.clonedeep@4.5.0", "", {}, "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ=="], + + "lodash.isplainobject": ["lodash.isplainobject@4.0.6", "", {}, "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA=="], + + "lodash.merge": ["lodash.merge@4.6.2", "", {}, "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ=="], + + "longest-streak": ["longest-streak@3.1.0", "", {}, "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g=="], + + "loose-envify": ["loose-envify@1.4.0", "", { "dependencies": { "js-tokens": "^3.0.0 || ^4.0.0" }, "bin": "cli.js" }, "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q=="], + + "lru-cache": ["lru-cache@4.1.5", "", { "dependencies": { "pseudomap": "^1.0.2", "yallist": "^2.1.2" } }, "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g=="], + + "lucide-react": ["lucide-react@0.537.0", "", { "peerDependencies": { "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-VxWsdxBGeFnlC+HwMg/l08HptN4YRU9o/lRog156jOmRxI1ERKqN+rJiNY/mPcKAdWdM0UbyO8ft1o0jq69SSQ=="], + + "lunr": ["lunr@2.3.9", "", {}, "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow=="], + + "make-error": ["make-error@1.3.6", "", {}, "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw=="], + + "markdown-extensions": ["markdown-extensions@2.0.0", "", {}, "sha512-o5vL7aDWatOTX8LzaS1WMoaoxIiLRQJuIKKe2wAw6IeULDHaqbiqiggmx+pKvZDb1Sj+pE46Sn1T7lCqfFtg1Q=="], + + "markdown-table": ["markdown-table@3.0.3", "", {}, "sha512-Z1NL3Tb1M9wH4XESsCDEksWoKTdlUafKc4pt0GRwjUyXaCFZ+dc3g2erqB6zm3szA2IUSi7VnPI+o/9jnxh9hw=="], + + "math-intrinsics": ["math-intrinsics@1.1.0", "", {}, "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g=="], + + "maybe-callback": ["maybe-callback@2.1.0", "", {}, "sha512-P8CekEs8v3zn0bM/tXgfL0UkBXO//BAQkoAmn8s+eFmH451+7wBWY2aKEmyItoZUcbpaI2OCcM6tcuIil/n5mA=="], + + "mdast-util-find-and-replace": ["mdast-util-find-and-replace@3.0.1", "", { "dependencies": { "@types/mdast": "^4.0.0", "escape-string-regexp": "^5.0.0", "unist-util-is": "^6.0.0", "unist-util-visit-parents": "^6.0.0" } }, "sha512-SG21kZHGC3XRTSUhtofZkBzZTJNM5ecCi0SK2IMKmSXR8vO3peL+kb1O0z7Zl83jKtutG4k5Wv/W7V3/YHvzPA=="], + + "mdast-util-from-markdown": ["mdast-util-from-markdown@2.0.1", "", { "dependencies": { "@types/mdast": "^4.0.0", "@types/unist": "^3.0.0", "decode-named-character-reference": "^1.0.0", "devlop": "^1.0.0", "mdast-util-to-string": "^4.0.0", "micromark": "^4.0.0", "micromark-util-decode-numeric-character-reference": "^2.0.0", "micromark-util-decode-string": "^2.0.0", "micromark-util-normalize-identifier": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0", "unist-util-stringify-position": "^4.0.0" } }, "sha512-aJEUyzZ6TzlsX2s5B4Of7lN7EQtAxvtradMMglCQDyaTFgse6CmtmdJ15ElnVRlCg1vpNyVtbem0PWzlNieZsA=="], + + "mdast-util-gfm": ["mdast-util-gfm@3.0.0", "", { "dependencies": { "mdast-util-from-markdown": "^2.0.0", "mdast-util-gfm-autolink-literal": "^2.0.0", "mdast-util-gfm-footnote": "^2.0.0", "mdast-util-gfm-strikethrough": "^2.0.0", "mdast-util-gfm-table": "^2.0.0", "mdast-util-gfm-task-list-item": "^2.0.0", "mdast-util-to-markdown": "^2.0.0" } }, "sha512-dgQEX5Amaq+DuUqf26jJqSK9qgixgd6rYDHAv4aTBuA92cTknZlKpPfa86Z/s8Dj8xsAQpFfBmPUHWJBWqS4Bw=="], + + "mdast-util-gfm-autolink-literal": ["mdast-util-gfm-autolink-literal@2.0.0", "", { "dependencies": { "@types/mdast": "^4.0.0", "ccount": "^2.0.0", "devlop": "^1.0.0", "mdast-util-find-and-replace": "^3.0.0", "micromark-util-character": "^2.0.0" } }, "sha512-FyzMsduZZHSc3i0Px3PQcBT4WJY/X/RCtEJKuybiC6sjPqLv7h1yqAkmILZtuxMSsUyaLUWNp71+vQH2zqp5cg=="], + + "mdast-util-gfm-footnote": ["mdast-util-gfm-footnote@2.0.0", "", { "dependencies": { "@types/mdast": "^4.0.0", "devlop": "^1.1.0", "mdast-util-from-markdown": "^2.0.0", "mdast-util-to-markdown": "^2.0.0", "micromark-util-normalize-identifier": "^2.0.0" } }, "sha512-5jOT2boTSVkMnQ7LTrd6n/18kqwjmuYqo7JUPe+tRCY6O7dAuTFMtTPauYYrMPpox9hlN0uOx/FL8XvEfG9/mQ=="], + + "mdast-util-gfm-strikethrough": ["mdast-util-gfm-strikethrough@2.0.0", "", { "dependencies": { "@types/mdast": "^4.0.0", "mdast-util-from-markdown": "^2.0.0", "mdast-util-to-markdown": "^2.0.0" } }, "sha512-mKKb915TF+OC5ptj5bJ7WFRPdYtuHv0yTRxK2tJvi+BDqbkiG7h7u/9SI89nRAYcmap2xHQL9D+QG/6wSrTtXg=="], + + "mdast-util-gfm-table": ["mdast-util-gfm-table@2.0.0", "", { "dependencies": { "@types/mdast": "^4.0.0", "devlop": "^1.0.0", "markdown-table": "^3.0.0", "mdast-util-from-markdown": "^2.0.0", "mdast-util-to-markdown": "^2.0.0" } }, "sha512-78UEvebzz/rJIxLvE7ZtDd/vIQ0RHv+3Mh5DR96p7cS7HsBhYIICDBCu8csTNWNO6tBWfqXPWekRuj2FNOGOZg=="], + + "mdast-util-gfm-task-list-item": ["mdast-util-gfm-task-list-item@2.0.0", "", { "dependencies": { "@types/mdast": "^4.0.0", "devlop": "^1.0.0", "mdast-util-from-markdown": "^2.0.0", "mdast-util-to-markdown": "^2.0.0" } }, "sha512-IrtvNvjxC1o06taBAVJznEnkiHxLFTzgonUdy8hzFVeDun0uTjxxrRGVaNFqkU1wJR3RBPEfsxmU6jDWPofrTQ=="], + + "mdast-util-mdx": ["mdast-util-mdx@3.0.0", "", { "dependencies": { "mdast-util-from-markdown": "^2.0.0", "mdast-util-mdx-expression": "^2.0.0", "mdast-util-mdx-jsx": "^3.0.0", "mdast-util-mdxjs-esm": "^2.0.0", "mdast-util-to-markdown": "^2.0.0" } }, "sha512-JfbYLAW7XnYTTbUsmpu0kdBUVe+yKVJZBItEjwyYJiDJuZ9w4eeaqks4HQO+R7objWgS2ymV60GYpI14Ug554w=="], + + "mdast-util-mdx-expression": ["mdast-util-mdx-expression@2.0.0", "", { "dependencies": { "@types/estree-jsx": "^1.0.0", "@types/hast": "^3.0.0", "@types/mdast": "^4.0.0", "devlop": "^1.0.0", "mdast-util-from-markdown": "^2.0.0", "mdast-util-to-markdown": "^2.0.0" } }, "sha512-fGCu8eWdKUKNu5mohVGkhBXCXGnOTLuFqOvGMvdikr+J1w7lDJgxThOKpwRWzzbyXAU2hhSwsmssOY4yTokluw=="], + + "mdast-util-mdx-jsx": ["mdast-util-mdx-jsx@3.1.2", "", { "dependencies": { "@types/estree-jsx": "^1.0.0", "@types/hast": "^3.0.0", "@types/mdast": "^4.0.0", "@types/unist": "^3.0.0", "ccount": "^2.0.0", "devlop": "^1.1.0", "mdast-util-from-markdown": "^2.0.0", "mdast-util-to-markdown": "^2.0.0", "parse-entities": "^4.0.0", "stringify-entities": "^4.0.0", "unist-util-remove-position": "^5.0.0", "unist-util-stringify-position": "^4.0.0", "vfile-message": "^4.0.0" } }, "sha512-eKMQDeywY2wlHc97k5eD8VC+9ASMjN8ItEZQNGwJ6E0XWKiW/Z0V5/H8pvoXUf+y+Mj0VIgeRRbujBmFn4FTyA=="], + + "mdast-util-mdxjs-esm": ["mdast-util-mdxjs-esm@2.0.1", "", { "dependencies": { "@types/estree-jsx": "^1.0.0", "@types/hast": "^3.0.0", "@types/mdast": "^4.0.0", "devlop": "^1.0.0", "mdast-util-from-markdown": "^2.0.0", "mdast-util-to-markdown": "^2.0.0" } }, "sha512-EcmOpxsZ96CvlP03NghtH1EsLtr0n9Tm4lPUJUBccV9RwUOneqSycg19n5HGzCf+10LozMRSObtVr3ee1WoHtg=="], + + "mdast-util-phrasing": ["mdast-util-phrasing@4.1.0", "", { "dependencies": { "@types/mdast": "^4.0.0", "unist-util-is": "^6.0.0" } }, "sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w=="], + + "mdast-util-to-hast": ["mdast-util-to-hast@13.2.0", "", { "dependencies": { "@types/hast": "^3.0.0", "@types/mdast": "^4.0.0", "@ungap/structured-clone": "^1.0.0", "devlop": "^1.0.0", "micromark-util-sanitize-uri": "^2.0.0", "trim-lines": "^3.0.0", "unist-util-position": "^5.0.0", "unist-util-visit": "^5.0.0", "vfile": "^6.0.0" } }, "sha512-QGYKEuUsYT9ykKBCMOEDLsU5JRObWQusAolFMeko/tYPufNkRffBAQjIE+99jbA87xv6FgmjLtwjh9wBWajwAA=="], + + "mdast-util-to-markdown": ["mdast-util-to-markdown@2.1.0", "", { "dependencies": { "@types/mdast": "^4.0.0", "@types/unist": "^3.0.0", "longest-streak": "^3.0.0", "mdast-util-phrasing": "^4.0.0", "mdast-util-to-string": "^4.0.0", "micromark-util-decode-string": "^2.0.0", "unist-util-visit": "^5.0.0", "zwitch": "^2.0.0" } }, "sha512-SR2VnIEdVNCJbP6y7kVTJgPLifdr8WEU440fQec7qHoHOUz/oJ2jmNRqdDQ3rbiStOXb2mCDGTuwsK5OPUgYlQ=="], + + "mdast-util-to-string": ["mdast-util-to-string@4.0.0", "", { "dependencies": { "@types/mdast": "^4.0.0" } }, "sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg=="], + + "merge2": ["merge2@1.4.1", "", {}, "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg=="], + + "micromark": ["micromark@4.0.0", "", { "dependencies": { "@types/debug": "^4.0.0", "debug": "^4.0.0", "decode-named-character-reference": "^1.0.0", "devlop": "^1.0.0", "micromark-core-commonmark": "^2.0.0", "micromark-factory-space": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-chunked": "^2.0.0", "micromark-util-combine-extensions": "^2.0.0", "micromark-util-decode-numeric-character-reference": "^2.0.0", "micromark-util-encode": "^2.0.0", "micromark-util-normalize-identifier": "^2.0.0", "micromark-util-resolve-all": "^2.0.0", "micromark-util-sanitize-uri": "^2.0.0", "micromark-util-subtokenize": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-o/sd0nMof8kYff+TqcDx3VSrgBTcZpSvYcAHIfHhv5VAuNmisCxjhx6YmxS8PFEpb9z5WKWKPdzf0jM23ro3RQ=="], + + "micromark-core-commonmark": ["micromark-core-commonmark@2.0.1", "", { "dependencies": { "decode-named-character-reference": "^1.0.0", "devlop": "^1.0.0", "micromark-factory-destination": "^2.0.0", "micromark-factory-label": "^2.0.0", "micromark-factory-space": "^2.0.0", "micromark-factory-title": "^2.0.0", "micromark-factory-whitespace": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-chunked": "^2.0.0", "micromark-util-classify-character": "^2.0.0", "micromark-util-html-tag-name": "^2.0.0", "micromark-util-normalize-identifier": "^2.0.0", "micromark-util-resolve-all": "^2.0.0", "micromark-util-subtokenize": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-CUQyKr1e///ZODyD1U3xit6zXwy1a8q2a1S1HKtIlmgvurrEpaw/Y9y6KSIbF8P59cn/NjzHyO+Q2fAyYLQrAA=="], + + "micromark-extension-gfm": ["micromark-extension-gfm@3.0.0", "", { "dependencies": { "micromark-extension-gfm-autolink-literal": "^2.0.0", "micromark-extension-gfm-footnote": "^2.0.0", "micromark-extension-gfm-strikethrough": "^2.0.0", "micromark-extension-gfm-table": "^2.0.0", "micromark-extension-gfm-tagfilter": "^2.0.0", "micromark-extension-gfm-task-list-item": "^2.0.0", "micromark-util-combine-extensions": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w=="], + + "micromark-extension-gfm-autolink-literal": ["micromark-extension-gfm-autolink-literal@2.0.0", "", { "dependencies": { "micromark-util-character": "^2.0.0", "micromark-util-sanitize-uri": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-rTHfnpt/Q7dEAK1Y5ii0W8bhfJlVJFnJMHIPisfPK3gpVNuOP0VnRl96+YJ3RYWV/P4gFeQoGKNlT3RhuvpqAg=="], + + "micromark-extension-gfm-footnote": ["micromark-extension-gfm-footnote@2.0.0", "", { "dependencies": { "devlop": "^1.0.0", "micromark-core-commonmark": "^2.0.0", "micromark-factory-space": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-normalize-identifier": "^2.0.0", "micromark-util-sanitize-uri": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-6Rzu0CYRKDv3BfLAUnZsSlzx3ak6HAoI85KTiijuKIz5UxZxbUI+pD6oHgw+6UtQuiRwnGRhzMmPRv4smcz0fg=="], + + "micromark-extension-gfm-strikethrough": ["micromark-extension-gfm-strikethrough@2.0.0", "", { "dependencies": { "devlop": "^1.0.0", "micromark-util-chunked": "^2.0.0", "micromark-util-classify-character": "^2.0.0", "micromark-util-resolve-all": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-c3BR1ClMp5fxxmwP6AoOY2fXO9U8uFMKs4ADD66ahLTNcwzSCyRVU4k7LPV5Nxo/VJiR4TdzxRQY2v3qIUceCw=="], + + "micromark-extension-gfm-table": ["micromark-extension-gfm-table@2.0.0", "", { "dependencies": { "devlop": "^1.0.0", "micromark-factory-space": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-PoHlhypg1ItIucOaHmKE8fbin3vTLpDOUg8KAr8gRCF1MOZI9Nquq2i/44wFvviM4WuxJzc3demT8Y3dkfvYrw=="], + + "micromark-extension-gfm-tagfilter": ["micromark-extension-gfm-tagfilter@2.0.0", "", { "dependencies": { "micromark-util-types": "^2.0.0" } }, "sha512-xHlTOmuCSotIA8TW1mDIM6X2O1SiX5P9IuDtqGonFhEK0qgRI4yeC6vMxEV2dgyr2TiD+2PQ10o+cOhdVAcwfg=="], + + "micromark-extension-gfm-task-list-item": ["micromark-extension-gfm-task-list-item@2.0.1", "", { "dependencies": { "devlop": "^1.0.0", "micromark-factory-space": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-cY5PzGcnULaN5O7T+cOzfMoHjBW7j+T9D2sucA5d/KbsBTPcYdebm9zUd9zzdgJGCwahV+/W78Z3nbulBYVbTw=="], + + "micromark-extension-mdx-expression": ["micromark-extension-mdx-expression@3.0.0", "", { "dependencies": { "@types/estree": "^1.0.0", "devlop": "^1.0.0", "micromark-factory-mdx-expression": "^2.0.0", "micromark-factory-space": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-events-to-acorn": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-sI0nwhUDz97xyzqJAbHQhp5TfaxEvZZZ2JDqUo+7NvyIYG6BZ5CPPqj2ogUoPJlmXHBnyZUzISg9+oUmU6tUjQ=="], + + "micromark-extension-mdx-jsx": ["micromark-extension-mdx-jsx@3.0.0", "", { "dependencies": { "@types/acorn": "^4.0.0", "@types/estree": "^1.0.0", "devlop": "^1.0.0", "estree-util-is-identifier-name": "^3.0.0", "micromark-factory-mdx-expression": "^2.0.0", "micromark-factory-space": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0", "vfile-message": "^4.0.0" } }, "sha512-uvhhss8OGuzR4/N17L1JwvmJIpPhAd8oByMawEKx6NVdBCbesjH4t+vjEp3ZXft9DwvlKSD07fCeI44/N0Vf2w=="], + + "micromark-extension-mdx-md": ["micromark-extension-mdx-md@2.0.0", "", { "dependencies": { "micromark-util-types": "^2.0.0" } }, "sha512-EpAiszsB3blw4Rpba7xTOUptcFeBFi+6PY8VnJ2hhimH+vCQDirWgsMpz7w1XcZE7LVrSAUGb9VJpG9ghlYvYQ=="], + + "micromark-extension-mdxjs": ["micromark-extension-mdxjs@3.0.0", "", { "dependencies": { "acorn": "^8.0.0", "acorn-jsx": "^5.0.0", "micromark-extension-mdx-expression": "^3.0.0", "micromark-extension-mdx-jsx": "^3.0.0", "micromark-extension-mdx-md": "^2.0.0", "micromark-extension-mdxjs-esm": "^3.0.0", "micromark-util-combine-extensions": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-A873fJfhnJ2siZyUrJ31l34Uqwy4xIFmvPY1oj+Ean5PHcPBYzEsvqvWGaWcfEIr11O5Dlw3p2y0tZWpKHDejQ=="], + + "micromark-extension-mdxjs-esm": ["micromark-extension-mdxjs-esm@3.0.0", "", { "dependencies": { "@types/estree": "^1.0.0", "devlop": "^1.0.0", "micromark-core-commonmark": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-events-to-acorn": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0", "unist-util-position-from-estree": "^2.0.0", "vfile-message": "^4.0.0" } }, "sha512-DJFl4ZqkErRpq/dAPyeWp15tGrcrrJho1hKK5uBS70BCtfrIFg81sqcTVu3Ta+KD1Tk5vAtBNElWxtAa+m8K9A=="], + + "micromark-factory-destination": ["micromark-factory-destination@2.0.0", "", { "dependencies": { "micromark-util-character": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-j9DGrQLm/Uhl2tCzcbLhy5kXsgkHUrjJHg4fFAeoMRwJmJerT9aw4FEhIbZStWN8A3qMwOp1uzHr4UL8AInxtA=="], + + "micromark-factory-label": ["micromark-factory-label@2.0.0", "", { "dependencies": { "devlop": "^1.0.0", "micromark-util-character": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-RR3i96ohZGde//4WSe/dJsxOX6vxIg9TimLAS3i4EhBAFx8Sm5SmqVfR8E87DPSR31nEAjZfbt91OMZWcNgdZw=="], + + "micromark-factory-mdx-expression": ["micromark-factory-mdx-expression@2.0.1", "", { "dependencies": { "@types/estree": "^1.0.0", "devlop": "^1.0.0", "micromark-util-character": "^2.0.0", "micromark-util-events-to-acorn": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0", "unist-util-position-from-estree": "^2.0.0", "vfile-message": "^4.0.0" } }, "sha512-F0ccWIUHRLRrYp5TC9ZYXmZo+p2AM13ggbsW4T0b5CRKP8KHVRB8t4pwtBgTxtjRmwrK0Irwm7vs2JOZabHZfg=="], + + "micromark-factory-space": ["micromark-factory-space@2.0.0", "", { "dependencies": { "micromark-util-character": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-TKr+LIDX2pkBJXFLzpyPyljzYK3MtmllMUMODTQJIUfDGncESaqB90db9IAUcz4AZAJFdd8U9zOp9ty1458rxg=="], + + "micromark-factory-title": ["micromark-factory-title@2.0.0", "", { "dependencies": { "micromark-factory-space": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-jY8CSxmpWLOxS+t8W+FG3Xigc0RDQA9bKMY/EwILvsesiRniiVMejYTE4wumNc2f4UbAa4WsHqe3J1QS1sli+A=="], + + "micromark-factory-whitespace": ["micromark-factory-whitespace@2.0.0", "", { "dependencies": { "micromark-factory-space": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-28kbwaBjc5yAI1XadbdPYHX/eDnqaUFVikLwrO7FDnKG7lpgxnvk/XGRhX/PN0mOZ+dBSZ+LgunHS+6tYQAzhA=="], + + "micromark-util-character": ["micromark-util-character@2.1.0", "", { "dependencies": { "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ=="], + + "micromark-util-chunked": ["micromark-util-chunked@2.0.0", "", { "dependencies": { "micromark-util-symbol": "^2.0.0" } }, "sha512-anK8SWmNphkXdaKgz5hJvGa7l00qmcaUQoMYsBwDlSKFKjc6gjGXPDw3FNL3Nbwq5L8gE+RCbGqTw49FK5Qyvg=="], + + "micromark-util-classify-character": ["micromark-util-classify-character@2.0.0", "", { "dependencies": { "micromark-util-character": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-S0ze2R9GH+fu41FA7pbSqNWObo/kzwf8rN/+IGlW/4tC6oACOs8B++bh+i9bVyNnwCcuksbFwsBme5OCKXCwIw=="], + + "micromark-util-combine-extensions": ["micromark-util-combine-extensions@2.0.0", "", { "dependencies": { "micromark-util-chunked": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-vZZio48k7ON0fVS3CUgFatWHoKbbLTK/rT7pzpJ4Bjp5JjkZeasRfrS9wsBdDJK2cJLHMckXZdzPSSr1B8a4oQ=="], + + "micromark-util-decode-numeric-character-reference": ["micromark-util-decode-numeric-character-reference@2.0.1", "", { "dependencies": { "micromark-util-symbol": "^2.0.0" } }, "sha512-bmkNc7z8Wn6kgjZmVHOX3SowGmVdhYS7yBpMnuMnPzDq/6xwVA604DuOXMZTO1lvq01g+Adfa0pE2UKGlxL1XQ=="], + + "micromark-util-decode-string": ["micromark-util-decode-string@2.0.0", "", { "dependencies": { "decode-named-character-reference": "^1.0.0", "micromark-util-character": "^2.0.0", "micromark-util-decode-numeric-character-reference": "^2.0.0", "micromark-util-symbol": "^2.0.0" } }, "sha512-r4Sc6leeUTn3P6gk20aFMj2ntPwn6qpDZqWvYmAG6NgvFTIlj4WtrAudLi65qYoaGdXYViXYw2pkmn7QnIFasA=="], + + "micromark-util-encode": ["micromark-util-encode@2.0.0", "", {}, "sha512-pS+ROfCXAGLWCOc8egcBvT0kf27GoWMqtdarNfDcjb6YLuV5cM3ioG45Ys2qOVqeqSbjaKg72vU+Wby3eddPsA=="], + + "micromark-util-events-to-acorn": ["micromark-util-events-to-acorn@2.0.2", "", { "dependencies": { "@types/acorn": "^4.0.0", "@types/estree": "^1.0.0", "@types/unist": "^3.0.0", "devlop": "^1.0.0", "estree-util-visit": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0", "vfile-message": "^4.0.0" } }, "sha512-Fk+xmBrOv9QZnEDguL9OI9/NQQp6Hz4FuQ4YmCb/5V7+9eAh1s6AYSvL20kHkD67YIg7EpE54TiSlcsf3vyZgA=="], + + "micromark-util-html-tag-name": ["micromark-util-html-tag-name@2.0.0", "", {}, "sha512-xNn4Pqkj2puRhKdKTm8t1YHC/BAjx6CEwRFXntTaRf/x16aqka6ouVoutm+QdkISTlT7e2zU7U4ZdlDLJd2Mcw=="], + + "micromark-util-normalize-identifier": ["micromark-util-normalize-identifier@2.0.0", "", { "dependencies": { "micromark-util-symbol": "^2.0.0" } }, "sha512-2xhYT0sfo85FMrUPtHcPo2rrp1lwbDEEzpx7jiH2xXJLqBuy4H0GgXk5ToU8IEwoROtXuL8ND0ttVa4rNqYK3w=="], + + "micromark-util-resolve-all": ["micromark-util-resolve-all@2.0.0", "", { "dependencies": { "micromark-util-types": "^2.0.0" } }, "sha512-6KU6qO7DZ7GJkaCgwBNtplXCvGkJToU86ybBAUdavvgsCiG8lSSvYxr9MhwmQ+udpzywHsl4RpGJsYWG1pDOcA=="], + + "micromark-util-sanitize-uri": ["micromark-util-sanitize-uri@2.0.0", "", { "dependencies": { "micromark-util-character": "^2.0.0", "micromark-util-encode": "^2.0.0", "micromark-util-symbol": "^2.0.0" } }, "sha512-WhYv5UEcZrbAtlsnPuChHUAsu/iBPOVaEVsntLBIdpibO0ddy8OzavZz3iL2xVvBZOpolujSliP65Kq0/7KIYw=="], + + "micromark-util-subtokenize": ["micromark-util-subtokenize@2.0.1", "", { "dependencies": { "devlop": "^1.0.0", "micromark-util-chunked": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-jZNtiFl/1aY73yS3UGQkutD0UbhTt68qnRpw2Pifmz5wV9h8gOVsN70v+Lq/f1rKaU/W8pxRe8y8Q9FX1AOe1Q=="], + + "micromark-util-symbol": ["micromark-util-symbol@2.0.0", "", {}, "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw=="], + + "micromark-util-types": ["micromark-util-types@2.0.0", "", {}, "sha512-oNh6S2WMHWRZrmutsRmDDfkzKtxF+bc2VxLC9dvtrDIRFln627VsFP6fLMgTryGDljgLPjkrzQSDcPrjPyDJ5w=="], + + "micromatch": ["micromatch@4.0.8", "", { "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" } }, "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA=="], + + "mime": ["mime@1.6.0", "", { "bin": "cli.js" }, "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg=="], + + "minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="], + + "minimist": ["minimist@1.2.8", "", {}, "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA=="], + + "minipass": ["minipass@7.1.2", "", {}, "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw=="], + + "ms": ["ms@2.1.2", "", {}, "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="], + + "mz": ["mz@2.7.0", "", { "dependencies": { "any-promise": "^1.0.0", "object-assign": "^4.0.1", "thenify-all": "^1.0.0" } }, "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q=="], + + "nanoid": ["nanoid@3.3.11", "", { "bin": "bin/nanoid.cjs" }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="], + + "napi-postinstall": ["napi-postinstall@0.3.2", "", { "bin": "lib/cli.js" }, "sha512-tWVJxJHmBWLy69PvO96TZMZDrzmw5KeiZBz3RHmiM2XZ9grBJ2WgMAFVVg25nqp3ZjTFUs2Ftw1JhscL3Teliw=="], + + "natural-compare": ["natural-compare@1.4.0", "", {}, "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw=="], + + "next": ["next@15.4.6", "", { "dependencies": { "@next/env": "15.4.6", "@swc/helpers": "0.5.15", "caniuse-lite": "^1.0.30001579", "postcss": "8.4.31", "styled-jsx": "5.1.6" }, "optionalDependencies": { "@next/swc-darwin-arm64": "15.4.6", "@next/swc-darwin-x64": "15.4.6", "@next/swc-linux-arm64-gnu": "15.4.6", "@next/swc-linux-arm64-musl": "15.4.6", "@next/swc-linux-x64-gnu": "15.4.6", "@next/swc-linux-x64-musl": "15.4.6", "@next/swc-win32-arm64-msvc": "15.4.6", "@next/swc-win32-x64-msvc": "15.4.6", "sharp": "^0.34.3" }, "peerDependencies": { "@opentelemetry/api": "^1.1.0", "@playwright/test": "^1.51.1", "babel-plugin-react-compiler": "*", "react": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", "react-dom": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", "sass": "^1.3.0" }, "optionalPeers": ["@opentelemetry/api", "@playwright/test", "babel-plugin-react-compiler", "sass"], "bin": "dist/bin/next" }, "sha512-us++E/Q80/8+UekzB3SAGs71AlLDsadpFMXVNM/uQ0BMwsh9m3mr0UNQIfjKed8vpWXsASe+Qifrnu1oLIcKEQ=="], + + "next-mdx-remote": ["next-mdx-remote@5.0.0", "", { "dependencies": { "@babel/code-frame": "^7.23.5", "@mdx-js/mdx": "^3.0.1", "@mdx-js/react": "^3.0.1", "unist-util-remove": "^3.1.0", "vfile": "^6.0.1", "vfile-matter": "^5.0.0" }, "peerDependencies": { "react": ">=16" } }, "sha512-RNNbqRpK9/dcIFZs/esQhuLA8jANqlH694yqoDBK8hkVdJUndzzGmnPHa2nyi90N4Z9VmzuSWNRpr5ItT3M7xQ=="], + + "next-themes": ["next-themes@0.4.6", "", { "peerDependencies": { "react": "^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc", "react-dom": "^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc" } }, "sha512-pZvgD5L0IEvX5/9GWyHMf3m8BKiVQwsCMHfoFosXtXBMnaS0ZnIJ9ST4b4NqLVKDEm8QBxoNNGNaBv2JNF6XNA=="], + + "node-releases": ["node-releases@2.0.19", "", {}, "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw=="], + + "nopt": ["nopt@3.0.6", "", { "dependencies": { "abbrev": "1" }, "bin": "bin/nopt.js" }, "sha512-4GUt3kSEYmk4ITxzB/b9vaIDfUVWN/Ml1Fwl11IlnIG2iaJ9O6WXZ9SrYM9NLI8OCBieN2Y8SWC2oJV0RQ7qYg=="], + + "nopter": ["nopter@0.3.0", "", { "dependencies": { "caller-path": "~0.1.0", "camelcase": "^1.0.2", "chalk": "~0.5.1", "cli-table": "~0.3.1", "eol": "~0.2.0", "nopt": "^3.0.1", "object-assign": "^2.0.0", "splitargs": "~0.0.3" } }, "sha512-gSYCd2Gxge0Ovnszf8fI9WkN7/PiuTTIpbeo2VhyQ3+NwJ7z3x6jiOFAMuU65JZz+BK/I1uzae2neQVGFHMClQ=="], + + "normalize-path": ["normalize-path@3.0.0", "", {}, "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA=="], + + "normalize-range": ["normalize-range@0.1.2", "", {}, "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA=="], + + "object-assign": ["object-assign@2.1.1", "", {}, "sha512-CdsOUYIh5wIiozhJ3rLQgmUTgcyzFwZZrqhkKhODMoGtPKM+wt0h0CNIoauJWMsS9822EdzPsF/6mb4nLvPN5g=="], + + "object-hash": ["object-hash@3.0.0", "", {}, "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw=="], + + "object-inspect": ["object-inspect@1.13.4", "", {}, "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew=="], + + "object-keys": ["object-keys@1.1.1", "", {}, "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA=="], + + "object.assign": ["object.assign@4.1.7", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.3", "define-properties": "^1.2.1", "es-object-atoms": "^1.0.0", "has-symbols": "^1.1.0", "object-keys": "^1.1.1" } }, "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw=="], + + "object.entries": ["object.entries@1.1.9", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.4", "define-properties": "^1.2.1", "es-object-atoms": "^1.1.1" } }, "sha512-8u/hfXFRBD1O0hPUjioLhoWFHRmt6tKA4/vZPyckBr18l1KE9uHrFaFaUi8MDRTpi4uak2goyPTSNJLXX2k2Hw=="], + + "object.fromentries": ["object.fromentries@2.0.8", "", { "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", "es-abstract": "^1.23.2", "es-object-atoms": "^1.0.0" } }, "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ=="], + + "object.groupby": ["object.groupby@1.0.3", "", { "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", "es-abstract": "^1.23.2" } }, "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ=="], + + "object.values": ["object.values@1.2.1", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.3", "define-properties": "^1.2.1", "es-object-atoms": "^1.0.0" } }, "sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA=="], + + "optionator": ["optionator@0.9.3", "", { "dependencies": { "@aashutoshrathi/word-wrap": "^1.2.3", "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", "levn": "^0.4.1", "prelude-ls": "^1.2.1", "type-check": "^0.4.0" } }, "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg=="], + + "os-name": ["os-name@1.0.3", "", { "dependencies": { "osx-release": "^1.0.0", "win-release": "^1.0.0" }, "bin": "cli.js" }, "sha512-f5estLO2KN8vgtTRaILIgEGBoBrMnZ3JQ7W9TMZCnOIGwHe8TRGSpcagnWDo+Dfhd/z08k9Xe75hvciJJ8Qaew=="], + + "os-tmpdir": ["os-tmpdir@1.0.2", "", {}, "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g=="], + + "osx-release": ["osx-release@1.1.0", "", { "dependencies": { "minimist": "^1.1.0" }, "bin": "cli.js" }, "sha512-ixCMMwnVxyHFQLQnINhmIpWqXIfS2YOXchwQrk+OFzmo6nDjQ0E4KXAyyUh0T0MZgV4bUhkRrAbVqlE4yLVq4A=="], + + "own-keys": ["own-keys@1.0.1", "", { "dependencies": { "get-intrinsic": "^1.2.6", "object-keys": "^1.1.1", "safe-push-apply": "^1.0.0" } }, "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg=="], + + "p-limit": ["p-limit@3.1.0", "", { "dependencies": { "yocto-queue": "^0.1.0" } }, "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ=="], + + "p-locate": ["p-locate@5.0.0", "", { "dependencies": { "p-limit": "^3.0.2" } }, "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw=="], + + "package-json-from-dist": ["package-json-from-dist@1.0.1", "", {}, "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw=="], + + "pako": ["pako@0.2.9", "", {}, "sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA=="], + + "parent-module": ["parent-module@1.0.1", "", { "dependencies": { "callsites": "^3.0.0" } }, "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g=="], + + "parse-css-color": ["parse-css-color@0.2.1", "", { "dependencies": { "color-name": "^1.1.4", "hex-rgb": "^4.1.0" } }, "sha512-bwS/GGIFV3b6KS4uwpzCFj4w297Yl3uqnSgIPsoQkx7GMLROXfMnWvxfNkL0oh8HVhZA4hvJoEoEIqonfJ3BWg=="], + + "parse-domain": ["parse-domain@0.2.2", "", {}, "sha512-AtlCTd18kw7oMd4MBTOqW+tQP6FklBdGZsA6xxYs86C/DvIeJv7dl9Sm6I5e33SWN7NEQ8en3CYGpkXS1O0qDg=="], + + "parse-entities": ["parse-entities@4.0.1", "", { "dependencies": { "@types/unist": "^2.0.0", "character-entities": "^2.0.0", "character-entities-legacy": "^3.0.0", "character-reference-invalid": "^2.0.0", "decode-named-character-reference": "^1.0.0", "is-alphanumerical": "^2.0.0", "is-decimal": "^2.0.0", "is-hexadecimal": "^2.0.0" } }, "sha512-SWzvYcSJh4d/SGLIOQfZ/CoNv6BTlI6YEQ7Nj82oDVnRpwe/Z/F1EMx42x3JAOwGBlCjeCH0BRJQbQ/opHL17w=="], + + "parse-numeric-range": ["parse-numeric-range@1.3.0", "", {}, "sha512-twN+njEipszzlMJd4ONUYgSfZPDxgHhT9Ahed5uTigpQn90FggW4SA/AIPq/6a149fTbE9qBEcSwE3FAEp6wQQ=="], + + "parse5": ["parse5@3.0.3", "", { "dependencies": { "@types/node": "*" } }, "sha512-rgO9Zg5LLLkfJF9E6CCmXlSE4UVceloys8JrFqCcHloC3usd/kJCyPDwH2SOlzix2j3xaP9sUX3e8+kvkuleAA=="], + + "path-exists": ["path-exists@4.0.0", "", {}, "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w=="], + + "path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="], + + "path-parse": ["path-parse@1.0.7", "", {}, "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="], + + "path-scurry": ["path-scurry@1.11.1", "", { "dependencies": { "lru-cache": "^10.2.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" } }, "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA=="], + + "periscopic": ["periscopic@3.1.0", "", { "dependencies": { "@types/estree": "^1.0.0", "estree-walker": "^3.0.0", "is-reference": "^3.0.0" } }, "sha512-vKiQ8RRtkl9P+r/+oefh25C3fhybptkHKCZSPlcXiJux2tJF55GnEj3BVn4A5gKfq9NWWXXrxkHBwVPUfH0opw=="], + + "picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="], + + "picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], + + "pify": ["pify@2.3.0", "", {}, "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog=="], + + "pirates": ["pirates@4.0.7", "", {}, "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA=="], + + "possible-typed-array-names": ["possible-typed-array-names@1.0.0", "", {}, "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q=="], + + "postcss": ["postcss@8.5.6", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg=="], + + "postcss-import": ["postcss-import@15.1.0", "", { "dependencies": { "postcss-value-parser": "^4.0.0", "read-cache": "^1.0.0", "resolve": "^1.1.7" }, "peerDependencies": { "postcss": "^8.0.0" } }, "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew=="], + + "postcss-js": ["postcss-js@4.0.1", "", { "dependencies": { "camelcase-css": "^2.0.1" }, "peerDependencies": { "postcss": "^8.4.21" } }, "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw=="], + + "postcss-load-config": ["postcss-load-config@4.0.2", "", { "dependencies": { "lilconfig": "^3.0.0", "yaml": "^2.3.4" }, "peerDependencies": { "postcss": ">=8.0.9", "ts-node": ">=9.0.0" } }, "sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ=="], + + "postcss-nested": ["postcss-nested@6.2.0", "", { "dependencies": { "postcss-selector-parser": "^6.1.1" }, "peerDependencies": { "postcss": "^8.2.14" } }, "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ=="], + + "postcss-selector-parser": ["postcss-selector-parser@6.0.10", "", { "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" } }, "sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w=="], + + "postcss-value-parser": ["postcss-value-parser@4.2.0", "", {}, "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ=="], + + "prelude-ls": ["prelude-ls@1.2.1", "", {}, "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g=="], + + "prettier": ["prettier@3.5.3", "", { "bin": "bin/prettier.cjs" }, "sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw=="], + + "process-nextick-args": ["process-nextick-args@2.0.1", "", {}, "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="], + + "prop-types": ["prop-types@15.8.1", "", { "dependencies": { "loose-envify": "^1.4.0", "object-assign": "^4.1.1", "react-is": "^16.13.1" } }, "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg=="], + + "property-information": ["property-information@6.5.0", "", {}, "sha512-PgTgs/BlvHxOu8QuEN7wi5A0OmXaBcHpmCSTehcs6Uuu9IkDIEo13Hy7n898RHfrQ49vKCoGeWZSaAK01nwVig=="], + + "prr": ["prr@1.0.1", "", {}, "sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw=="], + + "pseudomap": ["pseudomap@1.0.2", "", {}, "sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ=="], + + "psl": ["psl@1.15.0", "", { "dependencies": { "punycode": "^2.3.1" } }, "sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w=="], + + "punycode": ["punycode@2.3.1", "", {}, "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="], + + "queue-microtask": ["queue-microtask@1.2.3", "", {}, "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A=="], + + "react": ["react@19.1.1", "", {}, "sha512-w8nqGImo45dmMIfljjMwOGtbmC/mk4CMYhWIicdSflH91J9TyCyczcPFXJzrZ/ZXcgGRFeP6BU0BEJTw6tZdfQ=="], + + "react-dom": ["react-dom@19.1.1", "", { "dependencies": { "scheduler": "^0.26.0" }, "peerDependencies": { "react": "^19.1.1" } }, "sha512-Dlq/5LAZgF0Gaz6yiqZCf6VCcZs1ghAJyrsu84Q/GT0gV+mCxbfmKNoGRKBYMJ8IEdGPqu49YWXD02GCknEDkw=="], + + "react-highlight": ["react-highlight@0.15.0", "", { "dependencies": { "highlight.js": "^10.5.0" } }, "sha512-5uV/b/N4Z421GSVVe05fz+OfTsJtFzx/fJBdafZyw4LS70XjIZwgEx3Lrkfc01W/RzZ2Dtfb0DApoaJFAIKBtA=="], + + "react-hotkeys-hook": ["react-hotkeys-hook@5.1.0", "", { "peerDependencies": { "react": ">=16.8.0", "react-dom": ">=16.8.0" } }, "sha512-GCNGXjBzV9buOS3REoQFmSmE4WTvBhYQ0YrAeeMZI83bhXg3dRWsLHXDutcVDdEjwJqJCxk5iewWYX5LtFUd7g=="], + + "react-is": ["react-is@16.13.1", "", {}, "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="], + + "react-remove-scroll": ["react-remove-scroll@2.7.1", "", { "dependencies": { "react-remove-scroll-bar": "^2.3.7", "react-style-singleton": "^2.2.3", "tslib": "^2.1.0", "use-callback-ref": "^1.3.3", "use-sidecar": "^1.1.3" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" } }, "sha512-HpMh8+oahmIdOuS5aFKKY6Pyog+FNaZV/XyJOq7b4YFwsFHe5yYfdbIalI4k3vU2nSDql7YskmUseHsRrJqIPA=="], + + "react-remove-scroll-bar": ["react-remove-scroll-bar@2.3.8", "", { "dependencies": { "react-style-singleton": "^2.2.2", "tslib": "^2.0.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q=="], + + "react-style-singleton": ["react-style-singleton@2.2.3", "", { "dependencies": { "get-nonce": "^1.0.0", "tslib": "^2.0.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" } }, "sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ=="], + + "read-cache": ["read-cache@1.0.0", "", { "dependencies": { "pify": "^2.3.0" } }, "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA=="], + + "readable-stream": ["readable-stream@2.3.8", "", { "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", "isarray": "~1.0.0", "process-nextick-args": "~2.0.0", "safe-buffer": "~5.1.1", "string_decoder": "~1.1.1", "util-deprecate": "~1.0.1" } }, "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA=="], + + "readdirp": ["readdirp@3.6.0", "", { "dependencies": { "picomatch": "^2.2.1" } }, "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA=="], + + "reflect.getprototypeof": ["reflect.getprototypeof@1.0.10", "", { "dependencies": { "call-bind": "^1.0.8", "define-properties": "^1.2.1", "es-abstract": "^1.23.9", "es-errors": "^1.3.0", "es-object-atoms": "^1.0.0", "get-intrinsic": "^1.2.7", "get-proto": "^1.0.1", "which-builtin-type": "^1.2.1" } }, "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw=="], + + "refractor": ["refractor@4.8.1", "", { "dependencies": { "@types/hast": "^2.0.0", "@types/prismjs": "^1.0.0", "hastscript": "^7.0.0", "parse-entities": "^4.0.0" } }, "sha512-/fk5sI0iTgFYlmVGYVew90AoYnNMP6pooClx/XKqyeeCQXrL0Kvgn8V0VEht5ccdljbzzF1i3Q213gcntkRExg=="], + + "regexp.prototype.flags": ["regexp.prototype.flags@1.5.4", "", { "dependencies": { "call-bind": "^1.0.8", "define-properties": "^1.2.1", "es-errors": "^1.3.0", "get-proto": "^1.0.1", "gopd": "^1.2.0", "set-function-name": "^2.0.2" } }, "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA=="], + + "rehype-autolink-headings": ["rehype-autolink-headings@7.1.0", "", { "dependencies": { "@types/hast": "^3.0.0", "@ungap/structured-clone": "^1.0.0", "hast-util-heading-rank": "^3.0.0", "hast-util-is-element": "^3.0.0", "unified": "^11.0.0", "unist-util-visit": "^5.0.0" } }, "sha512-rItO/pSdvnvsP4QRB1pmPiNHUskikqtPojZKJPPPAVx9Hj8i8TwMBhofrrAYRhYOOBZH9tgmG5lPqDLuIWPWmw=="], + + "rehype-code-titles": ["rehype-code-titles@1.2.0", "", { "dependencies": { "hast": "~1.0.0", "unist-util-visit": "~4.1.2" } }, "sha512-bSr2YJ0GHbHFarUNDZ3VpcGi9HqjLNrA9Lj3nuyox2aGGLhN53dFP2WJtPRnnRqU/vpbCatIgOYxEvWP1YYKrw=="], + + "rehype-parse": ["rehype-parse@9.0.0", "", { "dependencies": { "@types/hast": "^3.0.0", "hast-util-from-html": "^2.0.0", "unified": "^11.0.0" } }, "sha512-WG7nfvmWWkCR++KEkZevZb/uw41E8TsH4DsY9UxsTbIXCVGbAs4S+r8FrQ+OtH5EEQAs+5UxKC42VinkmpA1Yw=="], + + "rehype-prism-plus": ["rehype-prism-plus@2.0.1", "", { "dependencies": { "hast-util-to-string": "^3.0.0", "parse-numeric-range": "^1.3.0", "refractor": "^4.8.0", "rehype-parse": "^9.0.0", "unist-util-filter": "^5.0.0", "unist-util-visit": "^5.0.0" } }, "sha512-Wglct0OW12tksTUseAPyWPo3srjBOY7xKlql/DPKi7HbsdZTyaLCAoO58QBKSczFQxElTsQlOY3JDOFzB/K++Q=="], + + "rehype-slug": ["rehype-slug@6.0.0", "", { "dependencies": { "@types/hast": "^3.0.0", "github-slugger": "^2.0.0", "hast-util-heading-rank": "^3.0.0", "hast-util-to-string": "^3.0.0", "unist-util-visit": "^5.0.0" } }, "sha512-lWyvf/jwu+oS5+hL5eClVd3hNdmwM1kAC0BUvEGD19pajQMIzcNUd/k9GsfQ+FfECvX+JE+e9/btsKH0EjJT6A=="], + + "remark": ["remark@15.0.1", "", { "dependencies": { "@types/mdast": "^4.0.0", "remark-parse": "^11.0.0", "remark-stringify": "^11.0.0", "unified": "^11.0.0" } }, "sha512-Eht5w30ruCXgFmxVUSlNWQ9iiimq07URKeFS3hNc8cUWy1llX4KDWfyEDZRycMc+znsN9Ux5/tJ/BFdgdOwA3A=="], + + "remark-gfm": ["remark-gfm@4.0.1", "", { "dependencies": { "@types/mdast": "^4.0.0", "mdast-util-gfm": "^3.0.0", "micromark-extension-gfm": "^3.0.0", "remark-parse": "^11.0.0", "remark-stringify": "^11.0.0", "unified": "^11.0.0" } }, "sha512-1quofZ2RQ9EWdeN34S79+KExV1764+wCUGop5CPL1WGdD0ocPpu91lzPGbwWMECpEpd42kJGQwzRfyov9j4yNg=="], + + "remark-mdx": ["remark-mdx@3.0.1", "", { "dependencies": { "mdast-util-mdx": "^3.0.0", "micromark-extension-mdxjs": "^3.0.0" } }, "sha512-3Pz3yPQ5Rht2pM5R+0J2MrGoBSrzf+tJG94N+t/ilfdh8YLyyKYtidAYwTveB20BoHAcwIopOUqhcmh2F7hGYA=="], + + "remark-parse": ["remark-parse@11.0.0", "", { "dependencies": { "@types/mdast": "^4.0.0", "mdast-util-from-markdown": "^2.0.0", "micromark-util-types": "^2.0.0", "unified": "^11.0.0" } }, "sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA=="], + + "remark-rehype": ["remark-rehype@11.1.0", "", { "dependencies": { "@types/hast": "^3.0.0", "@types/mdast": "^4.0.0", "mdast-util-to-hast": "^13.0.0", "unified": "^11.0.0", "vfile": "^6.0.0" } }, "sha512-z3tJrAs2kIs1AqIIy6pzHmAHlF1hWQ+OdY4/hv+Wxe35EhyLKcajL33iUEn3ScxtFox9nUvRufR/Zre8Q08H/g=="], + + "remark-stringify": ["remark-stringify@11.0.0", "", { "dependencies": { "@types/mdast": "^4.0.0", "mdast-util-to-markdown": "^2.0.0", "unified": "^11.0.0" } }, "sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw=="], + + "resolve": ["resolve@1.22.8", "", { "dependencies": { "is-core-module": "^2.13.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": "bin/resolve" }, "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw=="], + + "resolve-from": ["resolve-from@4.0.0", "", {}, "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g=="], + + "resolve-pkg-maps": ["resolve-pkg-maps@1.0.0", "", {}, "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw=="], + + "reusify": ["reusify@1.1.0", "", {}, "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw=="], + + "robot-directives": ["robot-directives@0.3.0", "", { "dependencies": { "isbot": "^2.0.0", "useragent": "^2.1.8" } }, "sha512-mROGTXczU5H5jpfwIpy4TUcmoZH033UXvkI2QZfbfH+qugWr7XzmXmMtKcqqrTn1d4wabmwfVG9xaVQQ66ti8Q=="], + + "robots-txt-guard": ["robots-txt-guard@0.1.1", "", {}, "sha512-6+nGkE6c2dI9/dmhmNcoMKVwJxlA6sgN/XNo0rm6LLdA0hnj4YkpgrZdhMPl58gJkAqeiHlf4+8tJcLM1tv1Ew=="], + + "robots-txt-parse": ["robots-txt-parse@0.0.4", "", { "dependencies": { "bluebird": "^2.3.5", "split": "^0.3.0", "stream-combiner": "^0.2.1", "through": "^2.3.4" } }, "sha512-B2VQEC5oe9MD/77oILGi98NNAqtY1BlqgrwlYjq/RR5sDfZqpkFj1sG5pCieiSApoTxatJgGW+yWCh0zFfOGMQ=="], + + "run-parallel": ["run-parallel@1.2.0", "", { "dependencies": { "queue-microtask": "^1.2.2" } }, "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA=="], + + "safe-array-concat": ["safe-array-concat@1.1.3", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.2", "get-intrinsic": "^1.2.6", "has-symbols": "^1.1.0", "isarray": "^2.0.5" } }, "sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q=="], + + "safe-buffer": ["safe-buffer@5.1.2", "", {}, "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="], + + "safe-push-apply": ["safe-push-apply@1.0.0", "", { "dependencies": { "es-errors": "^1.3.0", "isarray": "^2.0.5" } }, "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA=="], + + "safe-regex-test": ["safe-regex-test@1.1.0", "", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "is-regex": "^1.2.1" } }, "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw=="], + + "satori": ["satori@0.16.0", "", { "dependencies": { "@shuding/opentype.js": "1.4.0-beta.0", "css-background-parser": "^0.1.0", "css-box-shadow": "1.0.0-3", "css-gradient-parser": "^0.0.16", "css-to-react-native": "^3.0.0", "emoji-regex-xs": "^2.0.1", "escape-html": "^1.0.3", "linebreak": "^1.1.0", "parse-css-color": "^0.2.1", "postcss-value-parser": "^4.2.0", "yoga-layout": "^3.2.1" } }, "sha512-ZvHN3ygzZ8FuxjSNB+mKBiF/NIoqHzlBGbD0MJiT+MvSsFOvotnWOhdTjxKzhHRT2wPC1QbhLzx2q/Y83VhfYQ=="], + + "scheduler": ["scheduler@0.26.0", "", {}, "sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA=="], + + "section-matter": ["section-matter@1.0.0", "", { "dependencies": { "extend-shallow": "^2.0.1", "kind-of": "^6.0.0" } }, "sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA=="], + + "semver": ["semver@6.3.1", "", { "bin": "bin/semver.js" }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], + + "set-function-length": ["set-function-length@1.2.2", "", { "dependencies": { "define-data-property": "^1.1.4", "es-errors": "^1.3.0", "function-bind": "^1.1.2", "get-intrinsic": "^1.2.4", "gopd": "^1.0.1", "has-property-descriptors": "^1.0.2" } }, "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg=="], + + "set-function-name": ["set-function-name@2.0.2", "", { "dependencies": { "define-data-property": "^1.1.4", "es-errors": "^1.3.0", "functions-have-names": "^1.2.3", "has-property-descriptors": "^1.0.2" } }, "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ=="], + + "set-proto": ["set-proto@1.0.0", "", { "dependencies": { "dunder-proto": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.0.0" } }, "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw=="], + + "sharp": ["sharp@0.34.3", "", { "dependencies": { "color": "^4.2.3", "detect-libc": "^2.0.4", "semver": "^7.7.2" }, "optionalDependencies": { "@img/sharp-darwin-arm64": "0.34.3", "@img/sharp-darwin-x64": "0.34.3", "@img/sharp-libvips-darwin-arm64": "1.2.0", "@img/sharp-libvips-darwin-x64": "1.2.0", "@img/sharp-libvips-linux-arm": "1.2.0", "@img/sharp-libvips-linux-arm64": "1.2.0", "@img/sharp-libvips-linux-ppc64": "1.2.0", "@img/sharp-libvips-linux-s390x": "1.2.0", "@img/sharp-libvips-linux-x64": "1.2.0", "@img/sharp-libvips-linuxmusl-arm64": "1.2.0", "@img/sharp-libvips-linuxmusl-x64": "1.2.0", "@img/sharp-linux-arm": "0.34.3", "@img/sharp-linux-arm64": "0.34.3", "@img/sharp-linux-ppc64": "0.34.3", "@img/sharp-linux-s390x": "0.34.3", "@img/sharp-linux-x64": "0.34.3", "@img/sharp-linuxmusl-arm64": "0.34.3", "@img/sharp-linuxmusl-x64": "0.34.3", "@img/sharp-wasm32": "0.34.3", "@img/sharp-win32-arm64": "0.34.3", "@img/sharp-win32-ia32": "0.34.3", "@img/sharp-win32-x64": "0.34.3" } }, "sha512-eX2IQ6nFohW4DbvHIOLRB3MHFpYqaqvXd3Tp5e/T/dSH83fxaNJQRvDMhASmkNTsNTVF2/OOopzRCt7xokgPfg=="], + + "shebang-command": ["shebang-command@2.0.0", "", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="], + + "shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="], + + "side-channel": ["side-channel@1.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.3", "side-channel-list": "^1.0.0", "side-channel-map": "^1.0.1", "side-channel-weakmap": "^1.0.2" } }, "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw=="], + + "side-channel-list": ["side-channel-list@1.0.0", "", { "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.3" } }, "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA=="], + + "side-channel-map": ["side-channel-map@1.0.1", "", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.5", "object-inspect": "^1.13.3" } }, "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA=="], + + "side-channel-weakmap": ["side-channel-weakmap@1.0.2", "", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.5", "object-inspect": "^1.13.3", "side-channel-map": "^1.0.1" } }, "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A=="], + + "signal-exit": ["signal-exit@4.1.0", "", {}, "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw=="], + + "simple-swizzle": ["simple-swizzle@0.2.2", "", { "dependencies": { "is-arrayish": "^0.3.1" } }, "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg=="], + + "source-map": ["source-map@0.7.4", "", {}, "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA=="], + + "source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="], + + "space-separated-tokens": ["space-separated-tokens@2.0.2", "", {}, "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q=="], + + "split": ["split@0.3.3", "", { "dependencies": { "through": "2" } }, "sha512-wD2AeVmxXRBoX44wAycgjVpMhvbwdI2aZjCkvfNcH1YqHQvJVa1duWc73OyVGJUc05fhFaTZeQ/PYsrmyH0JVA=="], + + "splitargs": ["splitargs@0.0.7", "", {}, "sha512-UUFYD2oWbNwULH6WoVtLUOw8ch586B+HUqcsAjjjeoBQAM1bD4wZRXu01koaxyd8UeYpybWqW4h+lO1Okv40Tg=="], + + "sprintf-js": ["sprintf-js@1.0.3", "", {}, "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g=="], + + "stable-hash": ["stable-hash@0.0.5", "", {}, "sha512-+L3ccpzibovGXFK+Ap/f8LOS0ahMrHTf3xu7mMLSpEGU0EO9ucaysSylKo9eRDFNhWve/y275iPmIZ4z39a9iA=="], + + "stop-iteration-iterator": ["stop-iteration-iterator@1.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "internal-slot": "^1.1.0" } }, "sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ=="], + + "stream-combiner": ["stream-combiner@0.2.2", "", { "dependencies": { "duplexer": "~0.1.1", "through": "~2.3.4" } }, "sha512-6yHMqgLYDzQDcAkL+tjJDC5nSNuNIx0vZtRZeiPh7Saef7VHX9H5Ijn9l2VIol2zaNYlYEX6KyuT/237A58qEQ=="], + + "stream-length": ["stream-length@1.0.2", "", { "dependencies": { "bluebird": "^2.6.2" } }, "sha512-aI+qKFiwoDV4rsXiS7WRoCt+v2RX1nUj17+KJC5r2gfh5xoSJIfP6Y3Do/HtvesFcTSWthIuJ3l1cvKQY/+nZg=="], + + "string-width": ["string-width@5.1.2", "", { "dependencies": { "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", "strip-ansi": "^7.0.1" } }, "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA=="], + + "string-width-cjs": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], + + "string.prototype.codepointat": ["string.prototype.codepointat@0.2.1", "", {}, "sha512-2cBVCj6I4IOvEnjgO/hWqXjqBGsY+zwPmHl12Srk9IXSZ56Jwwmy+66XO5Iut/oQVR7t5ihYdLB0GMa4alEUcg=="], + + "string.prototype.includes": ["string.prototype.includes@2.0.1", "", { "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", "es-abstract": "^1.23.3" } }, "sha512-o7+c9bW6zpAdJHTtujeePODAhkuicdAryFsfVKwA+wGw89wJ4GTY484WTucM9hLtDEOpOvI+aHnzqnC5lHp4Rg=="], + + "string.prototype.matchall": ["string.prototype.matchall@4.0.12", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.3", "define-properties": "^1.2.1", "es-abstract": "^1.23.6", "es-errors": "^1.3.0", "es-object-atoms": "^1.0.0", "get-intrinsic": "^1.2.6", "gopd": "^1.2.0", "has-symbols": "^1.1.0", "internal-slot": "^1.1.0", "regexp.prototype.flags": "^1.5.3", "set-function-name": "^2.0.2", "side-channel": "^1.1.0" } }, "sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA=="], + + "string.prototype.repeat": ["string.prototype.repeat@1.0.0", "", { "dependencies": { "define-properties": "^1.1.3", "es-abstract": "^1.17.5" } }, "sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w=="], + + "string.prototype.trim": ["string.prototype.trim@1.2.10", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.2", "define-data-property": "^1.1.4", "define-properties": "^1.2.1", "es-abstract": "^1.23.5", "es-object-atoms": "^1.0.0", "has-property-descriptors": "^1.0.2" } }, "sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA=="], + + "string.prototype.trimend": ["string.prototype.trimend@1.0.9", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.2", "define-properties": "^1.2.1", "es-object-atoms": "^1.0.0" } }, "sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ=="], + + "string.prototype.trimstart": ["string.prototype.trimstart@1.0.8", "", { "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", "es-object-atoms": "^1.0.0" } }, "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg=="], + + "string_decoder": ["string_decoder@1.1.1", "", { "dependencies": { "safe-buffer": "~5.1.0" } }, "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg=="], + + "stringify-entities": ["stringify-entities@4.0.4", "", { "dependencies": { "character-entities-html4": "^2.0.0", "character-entities-legacy": "^3.0.0" } }, "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg=="], + + "strip-ansi": ["strip-ansi@3.0.1", "", { "dependencies": { "ansi-regex": "^2.0.0" } }, "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg=="], + + "strip-ansi-cjs": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], + + "strip-bom": ["strip-bom@3.0.0", "", {}, "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA=="], + + "strip-bom-string": ["strip-bom-string@1.0.0", "", {}, "sha512-uCC2VHvQRYu+lMh4My/sFNmF2klFymLX1wHJeXnbEJERpV/ZsVuonzerjfrGpIGF7LBVa1O7i9kjiWvJiFck8g=="], + + "strip-json-comments": ["strip-json-comments@3.1.1", "", {}, "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig=="], + + "strip-markdown": ["strip-markdown@6.0.0", "", { "dependencies": { "@types/mdast": "^4.0.0" } }, "sha512-mSa8FtUoX3ExJYDkjPUTC14xaBAn4Ik5GPQD45G5E2egAmeV3kHgVSTfIoSDggbF6Pk9stahVgqsLCNExv6jHw=="], + + "style-to-object": ["style-to-object@0.4.4", "", { "dependencies": { "inline-style-parser": "0.1.1" } }, "sha512-HYNoHZa2GorYNyqiCaBgsxvcJIn7OHq6inEga+E6Ke3m5JkoqpQbnFssk4jwe+K7AhGa2fcha4wSOf1Kn01dMg=="], + + "styled-jsx": ["styled-jsx@5.1.6", "", { "dependencies": { "client-only": "0.0.1" }, "peerDependencies": { "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0 || ^19.0.0-0" } }, "sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA=="], + + "sucrase": ["sucrase@3.35.0", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.2", "commander": "^4.0.0", "glob": "^10.3.10", "lines-and-columns": "^1.1.6", "mz": "^2.7.0", "pirates": "^4.0.1", "ts-interface-checker": "^0.1.9" }, "bin": { "sucrase": "bin/sucrase", "sucrase-node": "bin/sucrase-node" } }, "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA=="], + + "supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="], + + "supports-preserve-symlinks-flag": ["supports-preserve-symlinks-flag@1.0.0", "", {}, "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w=="], + + "tailwind-merge": ["tailwind-merge@3.3.1", "", {}, "sha512-gBXpgUm/3rp1lMZZrM/w7D8GKqshif0zAymAhbCyIt8KMe+0v9DQ7cdYLR4FHH/cKpdTXb+A/tKKU3eolfsI+g=="], + + "tailwindcss": ["tailwindcss@3.4.17", "", { "dependencies": { "@alloc/quick-lru": "^5.2.0", "arg": "^5.0.2", "chokidar": "^3.6.0", "didyoumean": "^1.2.2", "dlv": "^1.1.3", "fast-glob": "^3.3.2", "glob-parent": "^6.0.2", "is-glob": "^4.0.3", "jiti": "^1.21.6", "lilconfig": "^3.1.3", "micromatch": "^4.0.8", "normalize-path": "^3.0.0", "object-hash": "^3.0.0", "picocolors": "^1.1.1", "postcss": "^8.4.47", "postcss-import": "^15.1.0", "postcss-js": "^4.0.1", "postcss-load-config": "^4.0.2", "postcss-nested": "^6.2.0", "postcss-selector-parser": "^6.1.2", "resolve": "^1.22.8", "sucrase": "^3.35.0" }, "bin": { "tailwind": "lib/cli.js", "tailwindcss": "lib/cli.js" } }, "sha512-w33E2aCvSDP0tW9RZuNXadXlkHXqFzSkQew/aIa2i/Sj8fThxwovwlXHSPXTbAHwEIhBFXAedUhP2tueAKP8Og=="], + + "tailwindcss-animate": ["tailwindcss-animate@1.0.7", "", { "peerDependencies": { "tailwindcss": ">=3.0.0 || insiders" } }, "sha512-bl6mpH3T7I3UFxuvDEXLxy/VuFxBk5bbzplh7tXI68mwMokNYd1t9qPBHlnyTwfa4JGC4zP516I1hYYtQ/vspA=="], + + "thenify": ["thenify@3.3.1", "", { "dependencies": { "any-promise": "^1.0.0" } }, "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw=="], + + "thenify-all": ["thenify-all@1.6.0", "", { "dependencies": { "thenify": ">= 3.1.0 < 4" } }, "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA=="], + + "through": ["through@2.3.8", "", {}, "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg=="], + + "through2": ["through2@0.5.1", "", { "dependencies": { "readable-stream": "~1.0.17", "xtend": "~3.0.0" } }, "sha512-zexCrAOTbjkBCXGyozn7hhS3aEaqdrc59mAD2E3dKYzV1vFuEGQ1hEDJN2oQMQFwy4he2zyLqPZV+AlfS8ZWJA=="], + + "through2-sink": ["through2-sink@1.0.0", "", { "dependencies": { "through2": "~0.5.1", "xtend": "~3.0.0" } }, "sha512-9HvIHIEXZ5YgstQx3vsu4U/QQ/n7X5RHlXf8MsfSEnEzeUFbX9BHBWmlwdQ1b6CzDlUEDwjFnkSIxpJZ6qP+0Q=="], + + "through2-spy": ["through2-spy@1.2.0", "", { "dependencies": { "through2": "~0.5.1", "xtend": "~3.0.0" } }, "sha512-QJ/32YGXA8K/PlkT/7kJOfWZREdlwoCcdVOL/wZHhV0JQJlwUQeDi4QZrEUEAdIL6Kjb9BRdHHz65zg+rzFxuA=="], + + "tiny-inflate": ["tiny-inflate@1.0.3", "", {}, "sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw=="], + + "tinyglobby": ["tinyglobby@0.2.14", "", { "dependencies": { "fdir": "^6.4.4", "picomatch": "^4.0.2" } }, "sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ=="], + + "tmp": ["tmp@0.0.33", "", { "dependencies": { "os-tmpdir": "~1.0.2" } }, "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw=="], + + "to-regex-range": ["to-regex-range@5.0.1", "", { "dependencies": { "is-number": "^7.0.0" } }, "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ=="], + + "tough-cookie": ["tough-cookie@2.5.0", "", { "dependencies": { "psl": "^1.1.28", "punycode": "^2.1.1" } }, "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g=="], + + "trim-lines": ["trim-lines@3.0.1", "", {}, "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg=="], + + "trough": ["trough@2.2.0", "", {}, "sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw=="], + + "ts-api-utils": ["ts-api-utils@2.1.0", "", { "peerDependencies": { "typescript": ">=4.8.4" } }, "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ=="], + + "ts-interface-checker": ["ts-interface-checker@0.1.13", "", {}, "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA=="], + + "ts-node": ["ts-node@10.9.2", "", { "dependencies": { "@cspotcode/source-map-support": "^0.8.0", "@tsconfig/node10": "^1.0.7", "@tsconfig/node12": "^1.0.7", "@tsconfig/node14": "^1.0.0", "@tsconfig/node16": "^1.0.2", "acorn": "^8.4.1", "acorn-walk": "^8.1.1", "arg": "^4.1.0", "create-require": "^1.1.0", "diff": "^4.0.1", "make-error": "^1.1.1", "v8-compile-cache-lib": "^3.0.1", "yn": "3.1.1" }, "peerDependencies": { "@swc/core": ">=1.2.50", "@swc/wasm": ">=1.2.50", "@types/node": "*", "typescript": ">=2.7" }, "optionalPeers": ["@swc/core", "@swc/wasm"], "bin": { "ts-node": "dist/bin.js", "ts-node-cwd": "dist/bin-cwd.js", "ts-node-esm": "dist/bin-esm.js", "ts-node-script": "dist/bin-script.js", "ts-node-transpile-only": "dist/bin-transpile.js", "ts-script": "dist/bin-script-deprecated.js" } }, "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ=="], + + "tsconfig-paths": ["tsconfig-paths@3.15.0", "", { "dependencies": { "@types/json5": "^0.0.29", "json5": "^1.0.2", "minimist": "^1.2.6", "strip-bom": "^3.0.0" } }, "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg=="], + + "tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], + + "tsx": ["tsx@4.20.3", "", { "dependencies": { "esbuild": "~0.25.0", "get-tsconfig": "^4.7.5" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "bin": "dist/cli.mjs" }, "sha512-qjbnuR9Tr+FJOMBqJCW5ehvIo/buZq7vH7qD7JziU98h6l3qGy0a/yPFjwO+y0/T7GFpNgNAvEcPPVfyT8rrPQ=="], + + "type-check": ["type-check@0.4.0", "", { "dependencies": { "prelude-ls": "^1.2.1" } }, "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew=="], + + "typed-array-buffer": ["typed-array-buffer@1.0.3", "", { "dependencies": { "call-bound": "^1.0.3", "es-errors": "^1.3.0", "is-typed-array": "^1.1.14" } }, "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw=="], + + "typed-array-byte-length": ["typed-array-byte-length@1.0.3", "", { "dependencies": { "call-bind": "^1.0.8", "for-each": "^0.3.3", "gopd": "^1.2.0", "has-proto": "^1.2.0", "is-typed-array": "^1.1.14" } }, "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg=="], + + "typed-array-byte-offset": ["typed-array-byte-offset@1.0.4", "", { "dependencies": { "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.8", "for-each": "^0.3.3", "gopd": "^1.2.0", "has-proto": "^1.2.0", "is-typed-array": "^1.1.15", "reflect.getprototypeof": "^1.0.9" } }, "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ=="], + + "typed-array-length": ["typed-array-length@1.0.7", "", { "dependencies": { "call-bind": "^1.0.7", "for-each": "^0.3.3", "gopd": "^1.0.1", "is-typed-array": "^1.1.13", "possible-typed-array-names": "^1.0.0", "reflect.getprototypeof": "^1.0.6" } }, "sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg=="], + + "typedarray": ["typedarray@0.0.6", "", {}, "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA=="], + + "typescript": ["typescript@5.4.5", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ=="], + + "unbox-primitive": ["unbox-primitive@1.1.0", "", { "dependencies": { "call-bound": "^1.0.3", "has-bigints": "^1.0.2", "has-symbols": "^1.1.0", "which-boxed-primitive": "^1.1.1" } }, "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw=="], + + "undici-types": ["undici-types@7.10.0", "", {}, "sha512-t5Fy/nfn+14LuOc2KNYg75vZqClpAiqscVvMygNnlsHBFpSXdJaYtXMcdNLpl/Qvc3P2cB3s6lOV51nqsFq4ag=="], + + "unicode-trie": ["unicode-trie@2.0.0", "", { "dependencies": { "pako": "^0.2.5", "tiny-inflate": "^1.0.0" } }, "sha512-x7bc76x0bm4prf1VLg79uhAzKw8DVboClSN5VxJuQ+LKDOVEW9CdH+VY7SP+vX7xCYQqzzgQpFqz15zeLvAtZQ=="], + + "unified": ["unified@11.0.4", "", { "dependencies": { "@types/unist": "^3.0.0", "bail": "^2.0.0", "devlop": "^1.0.0", "extend": "^3.0.0", "is-plain-obj": "^4.0.0", "trough": "^2.0.0", "vfile": "^6.0.0" } }, "sha512-apMPnyLjAX+ty4OrNap7yumyVAMlKx5IWU2wlzzUdYJO9A8f1p9m/gywF/GM2ZDFcjQPrx59Mc90KwmxsoklxQ=="], + + "unist-util-filter": ["unist-util-filter@5.0.1", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-is": "^6.0.0", "unist-util-visit-parents": "^6.0.0" } }, "sha512-pHx7D4Zt6+TsfwylH9+lYhBhzyhEnCXs/lbq/Hstxno5z4gVdyc2WEW0asfjGKPyG4pEKrnBv5hdkO6+aRnQJw=="], + + "unist-util-is": ["unist-util-is@6.0.0", "", { "dependencies": { "@types/unist": "^3.0.0" } }, "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw=="], + + "unist-util-position": ["unist-util-position@5.0.0", "", { "dependencies": { "@types/unist": "^3.0.0" } }, "sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA=="], + + "unist-util-position-from-estree": ["unist-util-position-from-estree@2.0.0", "", { "dependencies": { "@types/unist": "^3.0.0" } }, "sha512-KaFVRjoqLyF6YXCbVLNad/eS4+OfPQQn2yOd7zF/h5T/CSL2v8NpN6a5TPvtbXthAGw5nG+PuTtq+DdIZr+cRQ=="], + + "unist-util-remove": ["unist-util-remove@3.1.1", "", { "dependencies": { "@types/unist": "^2.0.0", "unist-util-is": "^5.0.0", "unist-util-visit-parents": "^5.0.0" } }, "sha512-kfCqZK5YVY5yEa89tvpl7KnBBHu2c6CzMkqHUrlOqaRgGOMp0sMvwWOVrbAtj03KhovQB7i96Gda72v/EFE0vw=="], + + "unist-util-remove-position": ["unist-util-remove-position@5.0.0", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-visit": "^5.0.0" } }, "sha512-Hp5Kh3wLxv0PHj9m2yZhhLt58KzPtEYKQQ4yxfYFEO7EvHwzyDYnduhHnY1mDxoqr7VUwVuHXk9RXKIiYS1N8Q=="], + + "unist-util-stringify-position": ["unist-util-stringify-position@4.0.0", "", { "dependencies": { "@types/unist": "^3.0.0" } }, "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ=="], + + "unist-util-visit": ["unist-util-visit@5.0.0", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-is": "^6.0.0", "unist-util-visit-parents": "^6.0.0" } }, "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg=="], + + "unist-util-visit-parents": ["unist-util-visit-parents@6.0.1", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-is": "^6.0.0" } }, "sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw=="], + + "unrs-resolver": ["unrs-resolver@1.11.1", "", { "dependencies": { "napi-postinstall": "^0.3.0" }, "optionalDependencies": { "@unrs/resolver-binding-android-arm-eabi": "1.11.1", "@unrs/resolver-binding-android-arm64": "1.11.1", "@unrs/resolver-binding-darwin-arm64": "1.11.1", "@unrs/resolver-binding-darwin-x64": "1.11.1", "@unrs/resolver-binding-freebsd-x64": "1.11.1", "@unrs/resolver-binding-linux-arm-gnueabihf": "1.11.1", "@unrs/resolver-binding-linux-arm-musleabihf": "1.11.1", "@unrs/resolver-binding-linux-arm64-gnu": "1.11.1", "@unrs/resolver-binding-linux-arm64-musl": "1.11.1", "@unrs/resolver-binding-linux-ppc64-gnu": "1.11.1", "@unrs/resolver-binding-linux-riscv64-gnu": "1.11.1", "@unrs/resolver-binding-linux-riscv64-musl": "1.11.1", "@unrs/resolver-binding-linux-s390x-gnu": "1.11.1", "@unrs/resolver-binding-linux-x64-gnu": "1.11.1", "@unrs/resolver-binding-linux-x64-musl": "1.11.1", "@unrs/resolver-binding-wasm32-wasi": "1.11.1", "@unrs/resolver-binding-win32-arm64-msvc": "1.11.1", "@unrs/resolver-binding-win32-ia32-msvc": "1.11.1", "@unrs/resolver-binding-win32-x64-msvc": "1.11.1" } }, "sha512-bSjt9pjaEBnNiGgc9rUiHGKv5l4/TGzDmYw3RhnkJGtLhbnnA/5qJj7x3dNDCRx/PJxu774LlH8lCOlB4hEfKg=="], + + "update-browserslist-db": ["update-browserslist-db@1.1.3", "", { "dependencies": { "escalade": "^3.2.0", "picocolors": "^1.1.1" }, "peerDependencies": { "browserslist": ">= 4.21.0" }, "bin": "cli.js" }, "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw=="], + + "uri-js": ["uri-js@4.4.1", "", { "dependencies": { "punycode": "^2.1.0" } }, "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg=="], + + "urlcache": ["urlcache@0.7.0", "", { "dependencies": { "urlobj": "0.0.11" } }, "sha512-xOW4t6wJDT07+VunsHwePemyXXRidCSOZ/1RIILJi2XnB+81FA5H0MRvS63/7joTWjGLajcJJGvR5odpbkV6hw=="], + + "urlobj": ["urlobj@0.0.11", "", { "dependencies": { "is-object": "^1.0.1", "is-string": "^1.0.4", "object-assign": "^4.1.1" } }, "sha512-Ncck0WWtuFBbZhSYwKjK1AU2V51V98P/KHUPkaEc+mFy4xkpAHFNyVQT+S5SgtsJAr94e4wiKUucJSfasV2kBw=="], + + "use-callback-ref": ["use-callback-ref@1.3.3", "", { "dependencies": { "tslib": "^2.0.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" } }, "sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg=="], + + "use-sidecar": ["use-sidecar@1.1.3", "", { "dependencies": { "detect-node-es": "^1.1.0", "tslib": "^2.0.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" } }, "sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ=="], + + "useragent": ["useragent@2.3.0", "", { "dependencies": { "lru-cache": "4.1.x", "tmp": "0.0.x" } }, "sha512-4AoH4pxuSvHCjqLO04sU6U/uE65BYza8l/KKBS0b0hnUPWi+cQ2BpeTEwejCSx9SPV5/U03nniDTrWx5NrmKdw=="], + + "util-deprecate": ["util-deprecate@1.0.2", "", {}, "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="], + + "uuid": ["uuid@2.0.3", "", {}, "sha512-FULf7fayPdpASncVy4DLh3xydlXEJJpvIELjYjNeQWYUZ9pclcpvCZSr2gkmN2FrrGcI7G/cJsIEwk5/8vfXpg=="], + + "v8-compile-cache-lib": ["v8-compile-cache-lib@3.0.1", "", {}, "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg=="], + + "vfile": ["vfile@6.0.1", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-stringify-position": "^4.0.0", "vfile-message": "^4.0.0" } }, "sha512-1bYqc7pt6NIADBJ98UiG0Bn/CHIVOoZ/IyEkqIruLg0mE1BKzkOXY2D6CSqQIcKqgadppE5lrxgWXJmXd7zZJw=="], + + "vfile-location": ["vfile-location@5.0.2", "", { "dependencies": { "@types/unist": "^3.0.0", "vfile": "^6.0.0" } }, "sha512-NXPYyxyBSH7zB5U6+3uDdd6Nybz6o6/od9rk8bp9H8GR3L+cm/fC0uUTbqBmUTnMCUDslAGBOIKNfvvb+gGlDg=="], + + "vfile-matter": ["vfile-matter@5.0.0", "", { "dependencies": { "vfile": "^6.0.0", "yaml": "^2.0.0" } }, "sha512-jhPSqlj8hTSkTXOqyxbUeZAFFVq/iwu/jukcApEqc/7DOidaAth6rDc0Zgg0vWpzUnWkwFP7aK28l6nBmxMqdQ=="], + + "vfile-message": ["vfile-message@4.0.2", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-stringify-position": "^4.0.0" } }, "sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw=="], + + "web-namespaces": ["web-namespaces@2.0.1", "", {}, "sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ=="], + + "which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="], + + "which-boxed-primitive": ["which-boxed-primitive@1.1.1", "", { "dependencies": { "is-bigint": "^1.1.0", "is-boolean-object": "^1.2.1", "is-number-object": "^1.1.1", "is-string": "^1.1.1", "is-symbol": "^1.1.1" } }, "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA=="], + + "which-builtin-type": ["which-builtin-type@1.2.1", "", { "dependencies": { "call-bound": "^1.0.2", "function.prototype.name": "^1.1.6", "has-tostringtag": "^1.0.2", "is-async-function": "^2.0.0", "is-date-object": "^1.1.0", "is-finalizationregistry": "^1.1.0", "is-generator-function": "^1.0.10", "is-regex": "^1.2.1", "is-weakref": "^1.0.2", "isarray": "^2.0.5", "which-boxed-primitive": "^1.1.0", "which-collection": "^1.0.2", "which-typed-array": "^1.1.16" } }, "sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q=="], + + "which-collection": ["which-collection@1.0.2", "", { "dependencies": { "is-map": "^2.0.3", "is-set": "^2.0.3", "is-weakmap": "^2.0.2", "is-weakset": "^2.0.3" } }, "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw=="], + + "which-typed-array": ["which-typed-array@1.1.19", "", { "dependencies": { "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.8", "call-bound": "^1.0.4", "for-each": "^0.3.5", "get-proto": "^1.0.1", "gopd": "^1.2.0", "has-tostringtag": "^1.0.2" } }, "sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw=="], + + "win-release": ["win-release@1.1.1", "", { "dependencies": { "semver": "^5.0.1" } }, "sha512-iCRnKVvGxOQdsKhcQId2PXV1vV3J/sDPXKA4Oe9+Eti2nb2ESEsYHRYls/UjoUW3bIc5ZDO8dTH50A/5iVN+bw=="], + + "wrap-ansi": ["wrap-ansi@8.1.0", "", { "dependencies": { "ansi-styles": "^6.1.0", "string-width": "^5.0.1", "strip-ansi": "^7.0.1" } }, "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ=="], + + "wrap-ansi-cjs": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="], + + "xtend": ["xtend@3.0.0", "", {}, "sha512-sp/sT9OALMjRW1fKDlPeuSZlDQpkqReA0pyJukniWbTGoEKefHxhGJynE3PNhUMlcM8qWIjPwecwCw4LArS5Eg=="], + + "yallist": ["yallist@2.1.2", "", {}, "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A=="], + + "yaml": ["yaml@2.4.1", "", { "bin": "bin.mjs" }, "sha512-pIXzoImaqmfOrL7teGUBt/T7ZDnyeGBWyXQBvOVhLkWLN37GXv8NMLK406UY6dS51JfcQHsmcW5cJ441bHg6Lg=="], + + "yn": ["yn@3.1.1", "", {}, "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q=="], + + "yocto-queue": ["yocto-queue@0.1.0", "", {}, "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q=="], + + "yoga-layout": ["yoga-layout@3.2.1", "", {}, "sha512-0LPOt3AxKqMdFBZA3HBAt/t/8vIKq7VaQYbuA8WxCgung+p9TVyKRYdpvCb80HcdTN2NkbIKbhNwKUfm3tQywQ=="], + + "zwitch": ["zwitch@2.0.4", "", {}, "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A=="], + + "@babel/highlight/chalk": ["chalk@2.4.2", "", { "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", "supports-color": "^5.3.0" } }, "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ=="], + + "@eslint-community/eslint-utils/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="], + + "@eslint/eslintrc/js-yaml": ["js-yaml@4.1.0", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": "bin/js-yaml.js" }, "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA=="], + + "@humanfs/node/@humanwhocodes/retry": ["@humanwhocodes/retry@0.3.1", "", {}, "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA=="], + + "@isaacs/cliui/strip-ansi": ["strip-ansi@7.1.0", "", { "dependencies": { "ansi-regex": "^6.0.1" } }, "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ=="], + + "@jridgewell/gen-mapping/@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.29", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-uw6guiW/gcAGPDhLmd77/6lW8QLeiV5RUTsAX46Db6oLhGaVj4lhnPwb184s1bkc8kdVg/+h988dro8GRDpmYQ=="], + + "@next/eslint-plugin-next/fast-glob": ["fast-glob@3.3.1", "", { "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", "micromatch": "^4.0.4" } }, "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg=="], + + "@typescript-eslint/eslint-plugin/ignore": ["ignore@7.0.5", "", {}, "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg=="], + + "@typescript-eslint/typescript-estree/fast-glob": ["fast-glob@3.3.3", "", { "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", "micromatch": "^4.0.8" } }, "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg=="], + + "@typescript-eslint/typescript-estree/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="], + + "@typescript-eslint/typescript-estree/semver": ["semver@7.7.2", "", { "bin": "bin/semver.js" }, "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA=="], + + "@typescript-eslint/visitor-keys/eslint-visitor-keys": ["eslint-visitor-keys@4.2.1", "", {}, "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ=="], + + "bhttp/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="], + + "bhttp/extend": ["extend@2.0.2", "", {}, "sha512-AgFD4VU+lVLP6vjnlNfF7OeInLTyeyckCNPEsuxz1vi786UuK/nk6ynPuhn/h+Ju9++TQyr5EpLRI14fc1QtTQ=="], + + "broken-link-checker/chalk": ["chalk@1.1.3", "", { "dependencies": { "ansi-styles": "^2.2.1", "escape-string-regexp": "^1.0.2", "has-ansi": "^2.0.0", "strip-ansi": "^3.0.0", "supports-color": "^2.0.0" } }, "sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A=="], + + "chokidar/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="], + + "combined-stream2/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="], + + "eslint-import-resolver-node/debug": ["debug@3.2.7", "", { "dependencies": { "ms": "^2.1.1" } }, "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ=="], + + "eslint-import-resolver-typescript/debug": ["debug@4.4.1", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ=="], + + "eslint-module-utils/debug": ["debug@3.2.7", "", { "dependencies": { "ms": "^2.1.1" } }, "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ=="], + + "eslint-plugin-import/debug": ["debug@3.2.7", "", { "dependencies": { "ms": "^2.1.1" } }, "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ=="], + + "eslint-plugin-react/resolve": ["resolve@2.0.0-next.5", "", { "dependencies": { "is-core-module": "^2.13.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": "bin/resolve" }, "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA=="], + + "eslint-plugin-react/semver": ["semver@6.3.1", "", { "bin": "bin/semver.js" }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], + + "espree/eslint-visitor-keys": ["eslint-visitor-keys@4.2.1", "", {}, "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ=="], + + "fast-glob/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="], + + "fdir/picomatch": ["picomatch@4.0.3", "", {}, "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q=="], + + "form-data2/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="], + + "glob/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="], + + "hast-util-from-html/parse5": ["parse5@7.1.2", "", { "dependencies": { "entities": "^4.4.0" } }, "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw=="], + + "hast-util-from-parse5/hastscript": ["hastscript@8.0.0", "", { "dependencies": { "@types/hast": "^3.0.0", "comma-separated-tokens": "^2.0.0", "hast-util-parse-selector": "^4.0.0", "property-information": "^6.0.0", "space-separated-tokens": "^2.0.0" } }, "sha512-dMOtzCEd3ABUeSIISmrETiKuyydk1w0pa+gE/uormcTpSYuaNJPbX1NU3JLyscSLjwAQM8bWMhhIlnCqnRvDTw=="], + + "hast-util-parse-selector/@types/hast": ["@types/hast@2.3.10", "", { "dependencies": { "@types/unist": "^2" } }, "sha512-McWspRw8xx8J9HurkVBfYj0xKoE25tOFlHGdx4MJ5xORQrMGZNqJhVQWaIbm6Oyla5kYOXtDiopzKRJzEOkwJw=="], + + "hast-util-to-jsx-runtime/style-to-object": ["style-to-object@1.0.6", "", { "dependencies": { "inline-style-parser": "0.2.3" } }, "sha512-khxq+Qm3xEyZfKd/y9L3oIWQimxuc4STrQKtQn8aSDRHb8mFgpukgX1hdzfrMEW6JCjyJ8p89x+IUMVnCBI1PA=="], + + "hastscript/@types/hast": ["@types/hast@2.3.10", "", { "dependencies": { "@types/unist": "^2" } }, "sha512-McWspRw8xx8J9HurkVBfYj0xKoE25tOFlHGdx4MJ5xORQrMGZNqJhVQWaIbm6Oyla5kYOXtDiopzKRJzEOkwJw=="], + + "is-bun-module/semver": ["semver@7.7.2", "", { "bin": "bin/semver.js" }, "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA=="], + + "mdast-util-find-and-replace/escape-string-regexp": ["escape-string-regexp@5.0.0", "", {}, "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw=="], + + "mdast-util-find-and-replace/unist-util-is": ["unist-util-is@6.0.0", "", { "dependencies": { "@types/unist": "^3.0.0" } }, "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw=="], + + "mdast-util-find-and-replace/unist-util-visit-parents": ["unist-util-visit-parents@6.0.1", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-is": "^6.0.0" } }, "sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw=="], + + "mdast-util-phrasing/unist-util-is": ["unist-util-is@6.0.0", "", { "dependencies": { "@types/unist": "^3.0.0" } }, "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw=="], + + "mz/object-assign": ["object-assign@4.1.1", "", {}, "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="], + + "next/postcss": ["postcss@8.4.31", "", { "dependencies": { "nanoid": "^3.3.6", "picocolors": "^1.0.0", "source-map-js": "^1.0.2" } }, "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ=="], + + "nopter/chalk": ["chalk@0.5.1", "", { "dependencies": { "ansi-styles": "^1.1.0", "escape-string-regexp": "^1.0.0", "has-ansi": "^0.1.0", "strip-ansi": "^0.3.0", "supports-color": "^0.2.0" } }, "sha512-bIKA54hP8iZhyDT81TOsJiQvR1gW+ZYSXFaZUAvoD4wCHdbHY2actmpTE4x344ZlFqHbvoxKOaESULTZN2gstg=="], + + "parent-module/callsites": ["callsites@3.1.0", "", {}, "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ=="], + + "parse-entities/@types/unist": ["@types/unist@2.0.11", "", {}, "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA=="], + + "path-scurry/lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="], + + "postcss-nested/postcss-selector-parser": ["postcss-selector-parser@6.1.2", "", { "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" } }, "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg=="], + + "prop-types/object-assign": ["object-assign@4.1.1", "", {}, "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="], + + "react-highlight/highlight.js": ["highlight.js@10.7.3", "", {}, "sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A=="], + + "readable-stream/isarray": ["isarray@1.0.0", "", {}, "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ=="], + + "refractor/@types/hast": ["@types/hast@2.3.10", "", { "dependencies": { "@types/unist": "^2" } }, "sha512-McWspRw8xx8J9HurkVBfYj0xKoE25tOFlHGdx4MJ5xORQrMGZNqJhVQWaIbm6Oyla5kYOXtDiopzKRJzEOkwJw=="], + + "rehype-code-titles/unist-util-visit": ["unist-util-visit@4.1.2", "", { "dependencies": { "@types/unist": "^2.0.0", "unist-util-is": "^5.0.0", "unist-util-visit-parents": "^5.1.1" } }, "sha512-MSd8OUGISqHdVvfY9TPhyK2VdUrPgxkUtWSuMHF6XAAFuL4LokseigBnZtPnJMu+FbynTkFNnFlyjxpVKujMRg=="], + + "sharp/semver": ["semver@7.7.2", "", { "bin": "bin/semver.js" }, "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA=="], + + "string-width/strip-ansi": ["strip-ansi@7.1.0", "", { "dependencies": { "ansi-regex": "^6.0.1" } }, "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ=="], + + "string-width-cjs/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], + + "string-width-cjs/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], + + "strip-ansi/ansi-regex": ["ansi-regex@2.1.1", "", {}, "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA=="], + + "strip-ansi-cjs/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], + + "tailwindcss/postcss-selector-parser": ["postcss-selector-parser@6.1.2", "", { "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" } }, "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg=="], + + "through2/readable-stream": ["readable-stream@1.0.34", "", { "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.1", "isarray": "0.0.1", "string_decoder": "~0.10.x" } }, "sha512-ok1qVCJuRkNmvebYikljxJA/UEsKwLl2nI1OmaqAu4/UE+h0wKCHok4XkL/gvi39OacXvw59RJUOFUkDib2rHg=="], + + "tinyglobby/picomatch": ["picomatch@4.0.3", "", {}, "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q=="], + + "ts-node/arg": ["arg@4.1.3", "", {}, "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA=="], + + "unist-util-filter/unist-util-is": ["unist-util-is@6.0.0", "", { "dependencies": { "@types/unist": "^3.0.0" } }, "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw=="], + + "unist-util-filter/unist-util-visit-parents": ["unist-util-visit-parents@6.0.1", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-is": "^6.0.0" } }, "sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw=="], + + "unist-util-remove/@types/unist": ["@types/unist@2.0.11", "", {}, "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA=="], + + "unist-util-remove/unist-util-is": ["unist-util-is@5.2.1", "", { "dependencies": { "@types/unist": "^2.0.0" } }, "sha512-u9njyyfEh43npf1M+yGKDGVPbY/JWEemg5nH05ncKPfi+kBbKBJoTdsogMu33uhytuLlv9y0O7GH7fEdwLdLQw=="], + + "unist-util-remove/unist-util-visit-parents": ["unist-util-visit-parents@5.1.3", "", { "dependencies": { "@types/unist": "^2.0.0", "unist-util-is": "^5.0.0" } }, "sha512-x6+y8g7wWMyQhL1iZfhIPhDAs7Xwbn9nRosDXl7qoPTSCy0yNxnKc+hWokFifWQIDGi154rdUqKvbCa4+1kLhg=="], + + "urlobj/object-assign": ["object-assign@4.1.1", "", {}, "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="], + + "win-release/semver": ["semver@5.7.2", "", { "bin": "bin/semver" }, "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g=="], + + "wrap-ansi/ansi-styles": ["ansi-styles@6.2.1", "", {}, "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug=="], + + "wrap-ansi/strip-ansi": ["strip-ansi@7.1.0", "", { "dependencies": { "ansi-regex": "^6.0.1" } }, "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ=="], + + "wrap-ansi-cjs/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], + + "wrap-ansi-cjs/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], + + "@babel/highlight/chalk/ansi-styles": ["ansi-styles@3.2.1", "", { "dependencies": { "color-convert": "^1.9.0" } }, "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA=="], + + "@babel/highlight/chalk/escape-string-regexp": ["escape-string-regexp@1.0.5", "", {}, "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg=="], + + "@babel/highlight/chalk/supports-color": ["supports-color@5.5.0", "", { "dependencies": { "has-flag": "^3.0.0" } }, "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow=="], + + "@eslint/eslintrc/js-yaml/argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="], + + "@isaacs/cliui/strip-ansi/ansi-regex": ["ansi-regex@6.1.0", "", {}, "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA=="], + + "@next/eslint-plugin-next/fast-glob/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="], + + "@typescript-eslint/typescript-estree/fast-glob/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="], + + "@typescript-eslint/typescript-estree/minimatch/brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="], + + "bhttp/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="], + + "broken-link-checker/chalk/ansi-styles": ["ansi-styles@2.2.1", "", {}, "sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA=="], + + "broken-link-checker/chalk/escape-string-regexp": ["escape-string-regexp@1.0.5", "", {}, "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg=="], + + "broken-link-checker/chalk/supports-color": ["supports-color@2.0.0", "", {}, "sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g=="], + + "combined-stream2/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="], + + "eslint-import-resolver-typescript/debug/ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="], + + "form-data2/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="], + + "glob/minimatch/brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="], + + "hast-util-from-parse5/hastscript/hast-util-parse-selector": ["hast-util-parse-selector@4.0.0", "", { "dependencies": { "@types/hast": "^3.0.0" } }, "sha512-wkQCkSYoOGCRKERFWcxMVMOcYE2K1AaNLU8DXS9arxnLOUEWbOXKXiJUNzEpqZ3JOKpnha3jkFrumEjVliDe7A=="], + + "hast-util-parse-selector/@types/hast/@types/unist": ["@types/unist@2.0.11", "", {}, "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA=="], + + "hast-util-to-jsx-runtime/style-to-object/inline-style-parser": ["inline-style-parser@0.2.3", "", {}, "sha512-qlD8YNDqyTKTyuITrDOffsl6Tdhv+UC4hcdAVuQsK4IMQ99nSgd1MIA/Q+jQYoh9r3hVUXhYh7urSRmXPkW04g=="], + + "hastscript/@types/hast/@types/unist": ["@types/unist@2.0.11", "", {}, "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA=="], + + "nopter/chalk/ansi-styles": ["ansi-styles@1.1.0", "", {}, "sha512-f2PKUkN5QngiSemowa6Mrk9MPCdtFiOSmibjZ+j1qhLGHHYsqZwmBMRF3IRMVXo8sybDqx2fJl2d/8OphBoWkA=="], + + "nopter/chalk/escape-string-regexp": ["escape-string-regexp@1.0.5", "", {}, "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg=="], + + "nopter/chalk/has-ansi": ["has-ansi@0.1.0", "", { "dependencies": { "ansi-regex": "^0.2.0" }, "bin": "cli.js" }, "sha512-1YsTg1fk2/6JToQhtZkArMkurq8UoWU1Qe0aR3VUHjgij4nOylSWLWAtBXoZ4/dXOmugfLGm1c+QhuD0JyedFA=="], + + "nopter/chalk/strip-ansi": ["strip-ansi@0.3.0", "", { "dependencies": { "ansi-regex": "^0.2.1" }, "bin": "cli.js" }, "sha512-DerhZL7j6i6/nEnVG0qViKXI0OKouvvpsAiaj7c+LfqZZZxdwZtv8+UiA/w4VUJpT8UzX0pR1dcHOii1GbmruQ=="], + + "nopter/chalk/supports-color": ["supports-color@0.2.0", "", { "bin": "cli.js" }, "sha512-tdCZ28MnM7k7cJDJc7Eq80A9CsRFAAOZUy41npOZCs++qSjfIy7o5Rh46CBk+Dk5FbKJ33X3Tqg4YrV07N5RaA=="], + + "refractor/@types/hast/@types/unist": ["@types/unist@2.0.11", "", {}, "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA=="], + + "rehype-code-titles/unist-util-visit/@types/unist": ["@types/unist@2.0.11", "", {}, "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA=="], + + "rehype-code-titles/unist-util-visit/unist-util-is": ["unist-util-is@5.2.1", "", { "dependencies": { "@types/unist": "^2.0.0" } }, "sha512-u9njyyfEh43npf1M+yGKDGVPbY/JWEemg5nH05ncKPfi+kBbKBJoTdsogMu33uhytuLlv9y0O7GH7fEdwLdLQw=="], + + "rehype-code-titles/unist-util-visit/unist-util-visit-parents": ["unist-util-visit-parents@5.1.3", "", { "dependencies": { "@types/unist": "^2.0.0", "unist-util-is": "^5.0.0" } }, "sha512-x6+y8g7wWMyQhL1iZfhIPhDAs7Xwbn9nRosDXl7qoPTSCy0yNxnKc+hWokFifWQIDGi154rdUqKvbCa4+1kLhg=="], + + "string-width-cjs/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], + + "string-width/strip-ansi/ansi-regex": ["ansi-regex@6.1.0", "", {}, "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA=="], + + "through2/readable-stream/isarray": ["isarray@0.0.1", "", {}, "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ=="], + + "through2/readable-stream/string_decoder": ["string_decoder@0.10.31", "", {}, "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ=="], + + "unist-util-remove/unist-util-is/@types/unist": ["@types/unist@2.0.11", "", {}, "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA=="], + + "unist-util-remove/unist-util-visit-parents/@types/unist": ["@types/unist@2.0.11", "", {}, "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA=="], + + "wrap-ansi-cjs/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], + + "wrap-ansi-cjs/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], + + "wrap-ansi/strip-ansi/ansi-regex": ["ansi-regex@6.1.0", "", {}, "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA=="], + + "@babel/highlight/chalk/ansi-styles/color-convert": ["color-convert@1.9.3", "", { "dependencies": { "color-name": "1.1.3" } }, "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg=="], + + "@babel/highlight/chalk/supports-color/has-flag": ["has-flag@3.0.0", "", {}, "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw=="], + + "nopter/chalk/has-ansi/ansi-regex": ["ansi-regex@0.2.1", "", {}, "sha512-sGwIGMjhYdW26/IhwK2gkWWI8DRCVO6uj3hYgHT+zD+QL1pa37tM3ujhyfcJIYSbsxp7Gxhy7zrRW/1AHm4BmA=="], + + "nopter/chalk/strip-ansi/ansi-regex": ["ansi-regex@0.2.1", "", {}, "sha512-sGwIGMjhYdW26/IhwK2gkWWI8DRCVO6uj3hYgHT+zD+QL1pa37tM3ujhyfcJIYSbsxp7Gxhy7zrRW/1AHm4BmA=="], + + "rehype-code-titles/unist-util-visit/unist-util-is/@types/unist": ["@types/unist@2.0.11", "", {}, "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA=="], + + "rehype-code-titles/unist-util-visit/unist-util-visit-parents/@types/unist": ["@types/unist@2.0.11", "", {}, "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA=="], + + "@babel/highlight/chalk/ansi-styles/color-convert/color-name": ["color-name@1.1.3", "", {}, "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="], + } +} diff --git a/contents/docs/deployment.mdx b/contents/docs/deployment.mdx index 055abe75..08adb446 100644 --- a/contents/docs/deployment.mdx +++ b/contents/docs/deployment.mdx @@ -438,25 +438,23 @@ Explaining the arguments above -- - `ZERO_AUTH_SECRET` - The secret to create and verify JWTs. This is the same secret that was used when deploying zero-cache to fly. - `VITE_PUBLIC_SERVER` - The URL the frontend will call to talk to the zero-cache server. This is the URL of the fly app. -## Guide: Single-Node on Sevalla.com +## Guide: Single-Node on Sevalla [Sevalla.com](https://sevalla.com) is a modern Platform as a Service (PaaS) that can be used to deploy `zero-cache` in a single-node configuration, similar to Fly.io. This guide will walk you through deploying `zero-cache` to Sevalla using its web dashboard. -### Setup +### Setup Sevalla First, create an account on [Sevalla.com](https://sevalla.com). You will also need an upstream Postgres database. You can use any hosted Postgres provider like Supabase or Neon. Ensure you have the connection string handy. -### 1. Create a New Application +### Create a `zero-cache` Sevalla app 1. From the Sevalla dashboard, create a new Application. 2. Choose **Deploy from a public Docker image**. 3. For the **Image URL**, enter `rocicorp/zero`. You can append a specific version tag like `rocicorp/zero:0.22.2025080201`, or use `latest` to get the newest version. 4. Click **Continue**. -### 2. Configure Your Application - On the configuration screen, you will set up the necessary resources, networking, and environment variables. #### Resources @@ -489,7 +487,7 @@ Expose `zero-cache` to the internet so your frontend client can connect to it. #### Environment Variables -This is where you'll configure `zero-cache` to connect to your database. +This is where you'll configure `zero-cache` to connect to your database. 1. Under the **Environment variables** section, add the following variables, replacing them with their corresponding values. ``` @@ -500,7 +498,31 @@ ZERO_AUTH_JWKS_URL="..." # or `ZERO_AUTH_SECRET` alternatively ZERO_LOG_FORMAT="text" # required by Sevalla.com to properly display logs ``` -#### +#### Deploy + +Click **Deploy** to deploy your `zero-cache` app. + +### Deploy Permissions + +Now `zero-cache` is running on Sevalla, but there are no permissions. If you run the app against this `zero-cache`, you'll see that no data is returned from any query. To fix this, deploy your permissions: + +```bash +npx zero-deploy-permissions --schema-path='./src/schema.ts' --output-file='/tmp/permissions.sql' +(cat /tmp/permissions.sql; echo "\q") | fly pg connect -a $PG_APP_NAME -d zstart +``` + +You will need to redo this step every time you change your app's permissions, likely as part of your +CI/CD pipeline. + +### Use Remote `zero-cache` + +```bash +VITE_PUBLIC_SERVER="https://${CACHE_APP_NAME}.fly.dev/" npm run dev:ui +``` + +Now restart the frontend to pick up the env change, and refresh the app. You can stop your local database and `zero-cache` as we're not using them anymore. Open the web inspector to verify the app is talking to the remote `zero-cache`! + +You can deploy the frontend to any standard hosting service like Vercel or Netlify, or even to Sevalla.com! ## Guide: Multi-Node on Raw AWS From 0b573a832b0da2c5c90dfb291499bde020c092b0 Mon Sep 17 00:00:00 2001 From: miguelrk Date: Fri, 8 Aug 2025 16:54:39 +0200 Subject: [PATCH 27/28] chore: remove `bun.lock` file pushed by accident --- bun.lock | 1808 ------------------------------------------------------ 1 file changed, 1808 deletions(-) delete mode 100644 bun.lock diff --git a/bun.lock b/bun.lock deleted file mode 100644 index 99cc28dd..00000000 --- a/bun.lock +++ /dev/null @@ -1,1808 +0,0 @@ -{ - "lockfileVersion": 1, - "workspaces": { - "": { - "name": "aria-docs", - "dependencies": { - "@radix-ui/react-collapsible": "^1.1.11", - "@radix-ui/react-dialog": "^1.1.14", - "@radix-ui/react-dropdown-menu": "^2.1.15", - "@radix-ui/react-scroll-area": "^1.2.9", - "@radix-ui/react-slot": "^1.2.3", - "@radix-ui/react-tooltip": "^1.2.7", - "@vercel/og": "^0.8.5", - "broken-link-checker": "^0.7.8", - "class-variance-authority": "^0.7.1", - "clsx": "^2.1.1", - "cmdk": "^1.1.1", - "gray-matter": "^4.0.3", - "lucide-react": "^0.537.0", - "lunr": "^2.3.9", - "mdast-util-to-string": "^4.0.0", - "next": "^15.4.6", - "next-mdx-remote": "^5.0.0", - "next-themes": "^0.4.6", - "react": "^19.1.1", - "react-dom": "^19.1.1", - "react-hotkeys-hook": "^5.1.0", - "rehype-autolink-headings": "^7.1.0", - "rehype-code-titles": "^1.2.0", - "rehype-prism-plus": "^2.0.1", - "rehype-slug": "^6.0.0", - "remark": "^15.0.1", - "remark-gfm": "^4.0.1", - "remark-parse": "^11.0.0", - "remark-stringify": "^11.0.0", - "strip-markdown": "^6.0.0", - "tailwind-merge": "^3.3.1", - "tailwindcss-animate": "^1.0.7", - "unist-util-visit": "^5.0.0", - }, - "devDependencies": { - "@rocicorp/prettier-config": "^0.3.0", - "@tailwindcss/typography": "^0.5.16", - "@types/hast": "^3.0.4", - "@types/lunr": "^2.3.7", - "@types/node": "^24.2.0", - "@types/react": "^19", - "@types/react-dom": "^19", - "@types/unist": "^3.0.3", - "autoprefixer": "^10.4.21", - "eslint": "^9", - "eslint-config-next": "^15.4.6", - "highlight.js": "^11.11.1", - "postcss": "^8", - "react-highlight": "^0.15.0", - "tailwindcss": "^3.4.10", - "ts-node": "^10.9.2", - "tsx": "^4.20.3", - "typescript": "^5", - }, - }, - }, - "packages": { - "@aashutoshrathi/word-wrap": ["@aashutoshrathi/word-wrap@1.2.6", "", {}, "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA=="], - - "@alloc/quick-lru": ["@alloc/quick-lru@5.2.0", "", {}, "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw=="], - - "@babel/code-frame": ["@babel/code-frame@7.24.7", "", { "dependencies": { "@babel/highlight": "^7.24.7", "picocolors": "^1.0.0" } }, "sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA=="], - - "@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.24.7", "", {}, "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w=="], - - "@babel/highlight": ["@babel/highlight@7.24.7", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.24.7", "chalk": "^2.4.2", "js-tokens": "^4.0.0", "picocolors": "^1.0.0" } }, "sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw=="], - - "@cspotcode/source-map-support": ["@cspotcode/source-map-support@0.8.1", "", { "dependencies": { "@jridgewell/trace-mapping": "0.3.9" } }, "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw=="], - - "@emnapi/core": ["@emnapi/core@1.4.5", "", { "dependencies": { "@emnapi/wasi-threads": "1.0.4", "tslib": "^2.4.0" } }, "sha512-XsLw1dEOpkSX/WucdqUhPWP7hDxSvZiY+fsUC14h+FtQ2Ifni4znbBt8punRX+Uj2JG/uDb8nEHVKvrVlvdZ5Q=="], - - "@emnapi/runtime": ["@emnapi/runtime@1.4.5", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-++LApOtY0pEEz1zrd9vy1/zXVaVJJ/EbAF3u0fXIzPJEDtnITsBGbbK0EkM72amhl/R5b+5xx0Y/QhcVOpuulg=="], - - "@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.0.4", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-PJR+bOmMOPH8AtcTGAyYNiuJ3/Fcoj2XN/gBEWzDIKh254XO+mM9XoXHk5GNEhodxeMznbg7BlRojVbKN+gC6g=="], - - "@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.25.0", "", { "os": "aix", "cpu": "ppc64" }, "sha512-O7vun9Sf8DFjH2UtqK8Ku3LkquL9SZL8OLY1T5NZkA34+wG3OQF7cl4Ql8vdNzM6fzBbYfLaiRLIOZ+2FOCgBQ=="], - - "@esbuild/android-arm": ["@esbuild/android-arm@0.25.0", "", { "os": "android", "cpu": "arm" }, "sha512-PTyWCYYiU0+1eJKmw21lWtC+d08JDZPQ5g+kFyxP0V+es6VPPSUhM6zk8iImp2jbV6GwjX4pap0JFbUQN65X1g=="], - - "@esbuild/android-arm64": ["@esbuild/android-arm64@0.25.0", "", { "os": "android", "cpu": "arm64" }, "sha512-grvv8WncGjDSyUBjN9yHXNt+cq0snxXbDxy5pJtzMKGmmpPxeAmAhWxXI+01lU5rwZomDgD3kJwulEnhTRUd6g=="], - - "@esbuild/android-x64": ["@esbuild/android-x64@0.25.0", "", { "os": "android", "cpu": "x64" }, "sha512-m/ix7SfKG5buCnxasr52+LI78SQ+wgdENi9CqyCXwjVR2X4Jkz+BpC3le3AoBPYTC9NHklwngVXvbJ9/Akhrfg=="], - - "@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.25.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-mVwdUb5SRkPayVadIOI78K7aAnPamoeFR2bT5nszFUZ9P8UpK4ratOdYbZZXYSqPKMHfS1wdHCJk1P1EZpRdvw=="], - - "@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.25.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-DgDaYsPWFTS4S3nWpFcMn/33ZZwAAeAFKNHNa1QN0rI4pUjgqf0f7ONmXf6d22tqTY+H9FNdgeaAa+YIFUn2Rg=="], - - "@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.25.0", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-VN4ocxy6dxefN1MepBx/iD1dH5K8qNtNe227I0mnTRjry8tj5MRk4zprLEdG8WPyAPb93/e4pSgi1SoHdgOa4w=="], - - "@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.25.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-mrSgt7lCh07FY+hDD1TxiTyIHyttn6vnjesnPoVDNmDfOmggTLXRv8Id5fNZey1gl/V2dyVK1VXXqVsQIiAk+A=="], - - "@esbuild/linux-arm": ["@esbuild/linux-arm@0.25.0", "", { "os": "linux", "cpu": "arm" }, "sha512-vkB3IYj2IDo3g9xX7HqhPYxVkNQe8qTK55fraQyTzTX/fxaDtXiEnavv9geOsonh2Fd2RMB+i5cbhu2zMNWJwg=="], - - "@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.25.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-9QAQjTWNDM/Vk2bgBl17yWuZxZNQIF0OUUuPZRKoDtqF2k4EtYbpyiG5/Dk7nqeK6kIJWPYldkOcBqjXjrUlmg=="], - - "@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.25.0", "", { "os": "linux", "cpu": "ia32" }, "sha512-43ET5bHbphBegyeqLb7I1eYn2P/JYGNmzzdidq/w0T8E2SsYL1U6un2NFROFRg1JZLTzdCoRomg8Rvf9M6W6Gg=="], - - "@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.25.0", "", { "os": "linux", "cpu": "none" }, "sha512-fC95c/xyNFueMhClxJmeRIj2yrSMdDfmqJnyOY4ZqsALkDrrKJfIg5NTMSzVBr5YW1jf+l7/cndBfP3MSDpoHw=="], - - "@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.25.0", "", { "os": "linux", "cpu": "none" }, "sha512-nkAMFju7KDW73T1DdH7glcyIptm95a7Le8irTQNO/qtkoyypZAnjchQgooFUDQhNAy4iu08N79W4T4pMBwhPwQ=="], - - "@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.25.0", "", { "os": "linux", "cpu": "ppc64" }, "sha512-NhyOejdhRGS8Iwv+KKR2zTq2PpysF9XqY+Zk77vQHqNbo/PwZCzB5/h7VGuREZm1fixhs4Q/qWRSi5zmAiO4Fw=="], - - "@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.25.0", "", { "os": "linux", "cpu": "none" }, "sha512-5S/rbP5OY+GHLC5qXp1y/Mx//e92L1YDqkiBbO9TQOvuFXM+iDqUNG5XopAnXoRH3FjIUDkeGcY1cgNvnXp/kA=="], - - "@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.25.0", "", { "os": "linux", "cpu": "s390x" }, "sha512-XM2BFsEBz0Fw37V0zU4CXfcfuACMrppsMFKdYY2WuTS3yi8O1nFOhil/xhKTmE1nPmVyvQJjJivgDT+xh8pXJA=="], - - "@esbuild/linux-x64": ["@esbuild/linux-x64@0.25.0", "", { "os": "linux", "cpu": "x64" }, "sha512-9yl91rHw/cpwMCNytUDxwj2XjFpxML0y9HAOH9pNVQDpQrBxHy01Dx+vaMu0N1CKa/RzBD2hB4u//nfc+Sd3Cw=="], - - "@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.25.0", "", { "os": "none", "cpu": "arm64" }, "sha512-RuG4PSMPFfrkH6UwCAqBzauBWTygTvb1nxWasEJooGSJ/NwRw7b2HOwyRTQIU97Hq37l3npXoZGYMy3b3xYvPw=="], - - "@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.25.0", "", { "os": "none", "cpu": "x64" }, "sha512-jl+qisSB5jk01N5f7sPCsBENCOlPiS/xptD5yxOx2oqQfyourJwIKLRA2yqWdifj3owQZCL2sn6o08dBzZGQzA=="], - - "@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.25.0", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-21sUNbq2r84YE+SJDfaQRvdgznTD8Xc0oc3p3iW/a1EVWeNj/SdUCbm5U0itZPQYRuRTW20fPMWMpcrciH2EJw=="], - - "@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.25.0", "", { "os": "openbsd", "cpu": "x64" }, "sha512-2gwwriSMPcCFRlPlKx3zLQhfN/2WjJ2NSlg5TKLQOJdV0mSxIcYNTMhk3H3ulL/cak+Xj0lY1Ym9ysDV1igceg=="], - - "@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.25.0", "", { "os": "sunos", "cpu": "x64" }, "sha512-bxI7ThgLzPrPz484/S9jLlvUAHYMzy6I0XiU1ZMeAEOBcS0VePBFxh1JjTQt3Xiat5b6Oh4x7UC7IwKQKIJRIg=="], - - "@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.25.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-ZUAc2YK6JW89xTbXvftxdnYy3m4iHIkDtK3CLce8wg8M2L+YZhIvO1DKpxrd0Yr59AeNNkTiic9YLf6FTtXWMw=="], - - "@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.25.0", "", { "os": "win32", "cpu": "ia32" }, "sha512-eSNxISBu8XweVEWG31/JzjkIGbGIJN/TrRoiSVZwZ6pkC6VX4Im/WV2cz559/TXLcYbcrDN8JtKgd9DJVIo8GA=="], - - "@esbuild/win32-x64": ["@esbuild/win32-x64@0.25.0", "", { "os": "win32", "cpu": "x64" }, "sha512-ZENoHJBxA20C2zFzh6AI4fT6RraMzjYw4xKWemRTRmRVtN9c5DcH9r/f2ihEkMjOW5eGgrwCslG/+Y/3bL+DHQ=="], - - "@eslint-community/eslint-utils": ["@eslint-community/eslint-utils@4.7.0", "", { "dependencies": { "eslint-visitor-keys": "^3.4.3" }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, "sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw=="], - - "@eslint-community/regexpp": ["@eslint-community/regexpp@4.12.1", "", {}, "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ=="], - - "@eslint/config-array": ["@eslint/config-array@0.21.0", "", { "dependencies": { "@eslint/object-schema": "^2.1.6", "debug": "^4.3.1", "minimatch": "^3.1.2" } }, "sha512-ENIdc4iLu0d93HeYirvKmrzshzofPw6VkZRKQGe9Nv46ZnWUzcF1xV01dcvEg/1wXUR61OmmlSfyeyO7EvjLxQ=="], - - "@eslint/config-helpers": ["@eslint/config-helpers@0.3.0", "", {}, "sha512-ViuymvFmcJi04qdZeDc2whTHryouGcDlaxPqarTD0ZE10ISpxGUVZGZDx4w01upyIynL3iu6IXH2bS1NhclQMw=="], - - "@eslint/core": ["@eslint/core@0.15.1", "", { "dependencies": { "@types/json-schema": "^7.0.15" } }, "sha512-bkOp+iumZCCbt1K1CmWf0R9pM5yKpDv+ZXtvSyQpudrI9kuFLp+bM2WOPXImuD/ceQuaa8f5pj93Y7zyECIGNA=="], - - "@eslint/eslintrc": ["@eslint/eslintrc@3.3.1", "", { "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", "espree": "^10.0.1", "globals": "^14.0.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", "js-yaml": "^4.1.0", "minimatch": "^3.1.2", "strip-json-comments": "^3.1.1" } }, "sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ=="], - - "@eslint/js": ["@eslint/js@9.32.0", "", {}, "sha512-BBpRFZK3eX6uMLKz8WxFOBIFFcGFJ/g8XuwjTHCqHROSIsopI+ddn/d5Cfh36+7+e5edVS8dbSHnBNhrLEX0zg=="], - - "@eslint/object-schema": ["@eslint/object-schema@2.1.6", "", {}, "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA=="], - - "@eslint/plugin-kit": ["@eslint/plugin-kit@0.3.4", "", { "dependencies": { "@eslint/core": "^0.15.1", "levn": "^0.4.1" } }, "sha512-Ul5l+lHEcw3L5+k8POx6r74mxEYKG5kOb6Xpy2gCRW6zweT6TEhAf8vhxGgjhqrd/VO/Dirhsb+1hNpD1ue9hw=="], - - "@floating-ui/core": ["@floating-ui/core@1.7.3", "", { "dependencies": { "@floating-ui/utils": "^0.2.10" } }, "sha512-sGnvb5dmrJaKEZ+LDIpguvdX3bDlEllmv4/ClQ9awcmCZrlx5jQyyMWFM5kBI+EyNOCDDiKk8il0zeuX3Zlg/w=="], - - "@floating-ui/dom": ["@floating-ui/dom@1.7.3", "", { "dependencies": { "@floating-ui/core": "^1.7.3", "@floating-ui/utils": "^0.2.10" } }, "sha512-uZA413QEpNuhtb3/iIKoYMSK07keHPYeXF02Zhd6e213j+d1NamLix/mCLxBUDW/Gx52sPH2m+chlUsyaBs/Ag=="], - - "@floating-ui/react-dom": ["@floating-ui/react-dom@2.1.5", "", { "dependencies": { "@floating-ui/dom": "^1.7.3" }, "peerDependencies": { "react": ">=16.8.0", "react-dom": ">=16.8.0" } }, "sha512-HDO/1/1oH9fjj4eLgegrlH3dklZpHtUYYFiVwMUwfGvk9jWDRWqkklA2/NFScknrcNSspbV868WjXORvreDX+Q=="], - - "@floating-ui/utils": ["@floating-ui/utils@0.2.10", "", {}, "sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ=="], - - "@humanfs/core": ["@humanfs/core@0.19.1", "", {}, "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA=="], - - "@humanfs/node": ["@humanfs/node@0.16.6", "", { "dependencies": { "@humanfs/core": "^0.19.1", "@humanwhocodes/retry": "^0.3.0" } }, "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw=="], - - "@humanwhocodes/module-importer": ["@humanwhocodes/module-importer@1.0.1", "", {}, "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA=="], - - "@humanwhocodes/retry": ["@humanwhocodes/retry@0.4.3", "", {}, "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ=="], - - "@img/sharp-darwin-arm64": ["@img/sharp-darwin-arm64@0.34.3", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-arm64": "1.2.0" }, "os": "darwin", "cpu": "arm64" }, "sha512-ryFMfvxxpQRsgZJqBd4wsttYQbCxsJksrv9Lw/v798JcQ8+w84mBWuXwl+TT0WJ/WrYOLaYpwQXi3sA9nTIaIg=="], - - "@img/sharp-darwin-x64": ["@img/sharp-darwin-x64@0.34.3", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-x64": "1.2.0" }, "os": "darwin", "cpu": "x64" }, "sha512-yHpJYynROAj12TA6qil58hmPmAwxKKC7reUqtGLzsOHfP7/rniNGTL8tjWX6L3CTV4+5P4ypcS7Pp+7OB+8ihA=="], - - "@img/sharp-libvips-darwin-arm64": ["@img/sharp-libvips-darwin-arm64@1.2.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-sBZmpwmxqwlqG9ueWFXtockhsxefaV6O84BMOrhtg/YqbTaRdqDE7hxraVE3y6gVM4eExmfzW4a8el9ArLeEiQ=="], - - "@img/sharp-libvips-darwin-x64": ["@img/sharp-libvips-darwin-x64@1.2.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-M64XVuL94OgiNHa5/m2YvEQI5q2cl9d/wk0qFTDVXcYzi43lxuiFTftMR1tOnFQovVXNZJ5TURSDK2pNe9Yzqg=="], - - "@img/sharp-libvips-linux-arm": ["@img/sharp-libvips-linux-arm@1.2.0", "", { "os": "linux", "cpu": "arm" }, "sha512-mWd2uWvDtL/nvIzThLq3fr2nnGfyr/XMXlq8ZJ9WMR6PXijHlC3ksp0IpuhK6bougvQrchUAfzRLnbsen0Cqvw=="], - - "@img/sharp-libvips-linux-arm64": ["@img/sharp-libvips-linux-arm64@1.2.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-RXwd0CgG+uPRX5YYrkzKyalt2OJYRiJQ8ED/fi1tq9WQW2jsQIn0tqrlR5l5dr/rjqq6AHAxURhj2DVjyQWSOA=="], - - "@img/sharp-libvips-linux-ppc64": ["@img/sharp-libvips-linux-ppc64@1.2.0", "", { "os": "linux", "cpu": "ppc64" }, "sha512-Xod/7KaDDHkYu2phxxfeEPXfVXFKx70EAFZ0qyUdOjCcxbjqyJOEUpDe6RIyaunGxT34Anf9ue/wuWOqBW2WcQ=="], - - "@img/sharp-libvips-linux-s390x": ["@img/sharp-libvips-linux-s390x@1.2.0", "", { "os": "linux", "cpu": "s390x" }, "sha512-eMKfzDxLGT8mnmPJTNMcjfO33fLiTDsrMlUVcp6b96ETbnJmd4uvZxVJSKPQfS+odwfVaGifhsB07J1LynFehw=="], - - "@img/sharp-libvips-linux-x64": ["@img/sharp-libvips-linux-x64@1.2.0", "", { "os": "linux", "cpu": "x64" }, "sha512-ZW3FPWIc7K1sH9E3nxIGB3y3dZkpJlMnkk7z5tu1nSkBoCgw2nSRTFHI5pB/3CQaJM0pdzMF3paf9ckKMSE9Tg=="], - - "@img/sharp-libvips-linuxmusl-arm64": ["@img/sharp-libvips-linuxmusl-arm64@1.2.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-UG+LqQJbf5VJ8NWJ5Z3tdIe/HXjuIdo4JeVNADXBFuG7z9zjoegpzzGIyV5zQKi4zaJjnAd2+g2nna8TZvuW9Q=="], - - "@img/sharp-libvips-linuxmusl-x64": ["@img/sharp-libvips-linuxmusl-x64@1.2.0", "", { "os": "linux", "cpu": "x64" }, "sha512-SRYOLR7CXPgNze8akZwjoGBoN1ThNZoqpOgfnOxmWsklTGVfJiGJoC/Lod7aNMGA1jSsKWM1+HRX43OP6p9+6Q=="], - - "@img/sharp-linux-arm": ["@img/sharp-linux-arm@0.34.3", "", { "optionalDependencies": { "@img/sharp-libvips-linux-arm": "1.2.0" }, "os": "linux", "cpu": "arm" }, "sha512-oBK9l+h6KBN0i3dC8rYntLiVfW8D8wH+NPNT3O/WBHeW0OQWCjfWksLUaPidsrDKpJgXp3G3/hkmhptAW0I3+A=="], - - "@img/sharp-linux-arm64": ["@img/sharp-linux-arm64@0.34.3", "", { "optionalDependencies": { "@img/sharp-libvips-linux-arm64": "1.2.0" }, "os": "linux", "cpu": "arm64" }, "sha512-QdrKe3EvQrqwkDrtuTIjI0bu6YEJHTgEeqdzI3uWJOH6G1O8Nl1iEeVYRGdj1h5I21CqxSvQp1Yv7xeU3ZewbA=="], - - "@img/sharp-linux-ppc64": ["@img/sharp-linux-ppc64@0.34.3", "", { "optionalDependencies": { "@img/sharp-libvips-linux-ppc64": "1.2.0" }, "os": "linux", "cpu": "ppc64" }, "sha512-GLtbLQMCNC5nxuImPR2+RgrviwKwVql28FWZIW1zWruy6zLgA5/x2ZXk3mxj58X/tszVF69KK0Is83V8YgWhLA=="], - - "@img/sharp-linux-s390x": ["@img/sharp-linux-s390x@0.34.3", "", { "optionalDependencies": { "@img/sharp-libvips-linux-s390x": "1.2.0" }, "os": "linux", "cpu": "s390x" }, "sha512-3gahT+A6c4cdc2edhsLHmIOXMb17ltffJlxR0aC2VPZfwKoTGZec6u5GrFgdR7ciJSsHT27BD3TIuGcuRT0KmQ=="], - - "@img/sharp-linux-x64": ["@img/sharp-linux-x64@0.34.3", "", { "optionalDependencies": { "@img/sharp-libvips-linux-x64": "1.2.0" }, "os": "linux", "cpu": "x64" }, "sha512-8kYso8d806ypnSq3/Ly0QEw90V5ZoHh10yH0HnrzOCr6DKAPI6QVHvwleqMkVQ0m+fc7EH8ah0BB0QPuWY6zJQ=="], - - "@img/sharp-linuxmusl-arm64": ["@img/sharp-linuxmusl-arm64@0.34.3", "", { "optionalDependencies": { "@img/sharp-libvips-linuxmusl-arm64": "1.2.0" }, "os": "linux", "cpu": "arm64" }, "sha512-vAjbHDlr4izEiXM1OTggpCcPg9tn4YriK5vAjowJsHwdBIdx0fYRsURkxLG2RLm9gyBq66gwtWI8Gx0/ov+JKQ=="], - - "@img/sharp-linuxmusl-x64": ["@img/sharp-linuxmusl-x64@0.34.3", "", { "optionalDependencies": { "@img/sharp-libvips-linuxmusl-x64": "1.2.0" }, "os": "linux", "cpu": "x64" }, "sha512-gCWUn9547K5bwvOn9l5XGAEjVTTRji4aPTqLzGXHvIr6bIDZKNTA34seMPgM0WmSf+RYBH411VavCejp3PkOeQ=="], - - "@img/sharp-wasm32": ["@img/sharp-wasm32@0.34.3", "", { "dependencies": { "@emnapi/runtime": "^1.4.4" }, "cpu": "none" }, "sha512-+CyRcpagHMGteySaWos8IbnXcHgfDn7pO2fiC2slJxvNq9gDipYBN42/RagzctVRKgxATmfqOSulgZv5e1RdMg=="], - - "@img/sharp-win32-arm64": ["@img/sharp-win32-arm64@0.34.3", "", { "os": "win32", "cpu": "arm64" }, "sha512-MjnHPnbqMXNC2UgeLJtX4XqoVHHlZNd+nPt1kRPmj63wURegwBhZlApELdtxM2OIZDRv/DFtLcNhVbd1z8GYXQ=="], - - "@img/sharp-win32-ia32": ["@img/sharp-win32-ia32@0.34.3", "", { "os": "win32", "cpu": "ia32" }, "sha512-xuCdhH44WxuXgOM714hn4amodJMZl3OEvf0GVTm0BEyMeA2to+8HEdRPShH0SLYptJY1uBw+SCFP9WVQi1Q/cw=="], - - "@img/sharp-win32-x64": ["@img/sharp-win32-x64@0.34.3", "", { "os": "win32", "cpu": "x64" }, "sha512-OWwz05d++TxzLEv4VnsTz5CmZ6mI6S05sfQGEMrNrQcOEERbX46332IvE7pO/EUiw7jUrrS40z/M7kPyjfl04g=="], - - "@isaacs/cliui": ["@isaacs/cliui@8.0.2", "", { "dependencies": { "string-width": "^5.1.2", "string-width-cjs": "npm:string-width@^4.2.0", "strip-ansi": "^7.0.1", "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", "wrap-ansi": "^8.1.0", "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" } }, "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA=="], - - "@jridgewell/gen-mapping": ["@jridgewell/gen-mapping@0.3.12", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-OuLGC46TjB5BbN1dH8JULVVZY4WTdkF7tV9Ys6wLL1rubZnCMstOhNHueU5bLCrnRuDhKPDM4g6sw4Bel5Gzqg=="], - - "@jridgewell/resolve-uri": ["@jridgewell/resolve-uri@3.1.2", "", {}, "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw=="], - - "@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.4", "", {}, "sha512-VT2+G1VQs/9oz078bLrYbecdZKs912zQlkelYpuf+SXF+QvZDYJlbx/LSx+meSAwdDFnF8FVXW92AVjjkVmgFw=="], - - "@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.9", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.0.3", "@jridgewell/sourcemap-codec": "^1.4.10" } }, "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ=="], - - "@mdx-js/mdx": ["@mdx-js/mdx@3.0.1", "", { "dependencies": { "@types/estree": "^1.0.0", "@types/estree-jsx": "^1.0.0", "@types/hast": "^3.0.0", "@types/mdx": "^2.0.0", "collapse-white-space": "^2.0.0", "devlop": "^1.0.0", "estree-util-build-jsx": "^3.0.0", "estree-util-is-identifier-name": "^3.0.0", "estree-util-to-js": "^2.0.0", "estree-walker": "^3.0.0", "hast-util-to-estree": "^3.0.0", "hast-util-to-jsx-runtime": "^2.0.0", "markdown-extensions": "^2.0.0", "periscopic": "^3.0.0", "remark-mdx": "^3.0.0", "remark-parse": "^11.0.0", "remark-rehype": "^11.0.0", "source-map": "^0.7.0", "unified": "^11.0.0", "unist-util-position-from-estree": "^2.0.0", "unist-util-stringify-position": "^4.0.0", "unist-util-visit": "^5.0.0", "vfile": "^6.0.0" } }, "sha512-eIQ4QTrOWyL3LWEe/bu6Taqzq2HQvHcyTMaOrI95P2/LmJE7AsfPfgJGuFLPVqBUE1BC1rik3VIhU+s9u72arA=="], - - "@mdx-js/react": ["@mdx-js/react@3.0.1", "", { "dependencies": { "@types/mdx": "^2.0.0" }, "peerDependencies": { "@types/react": ">=16", "react": ">=16" } }, "sha512-9ZrPIU4MGf6et1m1ov3zKf+q9+deetI51zprKB1D/z3NOb+rUxxtEl3mCjW5wTGh6VhRdwPueh1oRzi6ezkA8A=="], - - "@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@0.2.12", "", { "dependencies": { "@emnapi/core": "^1.4.3", "@emnapi/runtime": "^1.4.3", "@tybys/wasm-util": "^0.10.0" } }, "sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ=="], - - "@next/env": ["@next/env@15.4.6", "", {}, "sha512-yHDKVTcHrZy/8TWhj0B23ylKv5ypocuCwey9ZqPyv4rPdUdRzpGCkSi03t04KBPyU96kxVtUqx6O3nE1kpxASQ=="], - - "@next/eslint-plugin-next": ["@next/eslint-plugin-next@15.4.6", "", { "dependencies": { "fast-glob": "3.3.1" } }, "sha512-2NOu3ln+BTcpnbIDuxx6MNq+pRrCyey4WSXGaJIyt0D2TYicHeO9QrUENNjcf673n3B1s7hsiV5xBYRCK1Q8kA=="], - - "@next/swc-darwin-arm64": ["@next/swc-darwin-arm64@15.4.6", "", { "os": "darwin", "cpu": "arm64" }, "sha512-667R0RTP4DwxzmrqTs4Lr5dcEda9OxuZsVFsjVtxVMVhzSpo6nLclXejJVfQo2/g7/Z9qF3ETDmN3h65mTjpTQ=="], - - "@next/swc-darwin-x64": ["@next/swc-darwin-x64@15.4.6", "", { "os": "darwin", "cpu": "x64" }, "sha512-KMSFoistFkaiQYVQQnaU9MPWtp/3m0kn2Xed1Ces5ll+ag1+rlac20sxG+MqhH2qYWX1O2GFOATQXEyxKiIscg=="], - - "@next/swc-linux-arm64-gnu": ["@next/swc-linux-arm64-gnu@15.4.6", "", { "os": "linux", "cpu": "arm64" }, "sha512-PnOx1YdO0W7m/HWFeYd2A6JtBO8O8Eb9h6nfJia2Dw1sRHoHpNf6lN1U4GKFRzRDBi9Nq2GrHk9PF3Vmwf7XVw=="], - - "@next/swc-linux-arm64-musl": ["@next/swc-linux-arm64-musl@15.4.6", "", { "os": "linux", "cpu": "arm64" }, "sha512-XBbuQddtY1p5FGPc2naMO0kqs4YYtLYK/8aPausI5lyOjr4J77KTG9mtlU4P3NwkLI1+OjsPzKVvSJdMs3cFaw=="], - - "@next/swc-linux-x64-gnu": ["@next/swc-linux-x64-gnu@15.4.6", "", { "os": "linux", "cpu": "x64" }, "sha512-+WTeK7Qdw82ez3U9JgD+igBAP75gqZ1vbK6R8PlEEuY0OIe5FuYXA4aTjL811kWPf7hNeslD4hHK2WoM9W0IgA=="], - - "@next/swc-linux-x64-musl": ["@next/swc-linux-x64-musl@15.4.6", "", { "os": "linux", "cpu": "x64" }, "sha512-XP824mCbgQsK20jlXKrUpZoh/iO3vUWhMpxCz8oYeagoiZ4V0TQiKy0ASji1KK6IAe3DYGfj5RfKP6+L2020OQ=="], - - "@next/swc-win32-arm64-msvc": ["@next/swc-win32-arm64-msvc@15.4.6", "", { "os": "win32", "cpu": "arm64" }, "sha512-FxrsenhUz0LbgRkNWx6FRRJIPe/MI1JRA4W4EPd5leXO00AZ6YU8v5vfx4MDXTvN77lM/EqsE3+6d2CIeF5NYg=="], - - "@next/swc-win32-x64-msvc": ["@next/swc-win32-x64-msvc@15.4.6", "", { "os": "win32", "cpu": "x64" }, "sha512-T4ufqnZ4u88ZheczkBTtOF+eKaM14V8kbjud/XrAakoM5DKQWjW09vD6B9fsdsWS2T7D5EY31hRHdta7QKWOng=="], - - "@nodelib/fs.scandir": ["@nodelib/fs.scandir@2.1.5", "", { "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" } }, "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g=="], - - "@nodelib/fs.stat": ["@nodelib/fs.stat@2.0.5", "", {}, "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A=="], - - "@nodelib/fs.walk": ["@nodelib/fs.walk@1.2.8", "", { "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" } }, "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg=="], - - "@nolyfill/is-core-module": ["@nolyfill/is-core-module@1.0.39", "", {}, "sha512-nn5ozdjYQpUCZlWGuxcJY/KpxkWQs4DcbMCmKojjyrYDEAGy4Ce19NN4v5MduafTwJlbKc99UA8YhSVqq9yPZA=="], - - "@pkgjs/parseargs": ["@pkgjs/parseargs@0.11.0", "", {}, "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg=="], - - "@radix-ui/number": ["@radix-ui/number@1.1.1", "", {}, "sha512-MkKCwxlXTgz6CFoJx3pCwn07GKp36+aZyu/u2Ln2VrA5DcdyCZkASEDBTd8x5whTQQL5CiYf4prXKLcgQdv29g=="], - - "@radix-ui/primitive": ["@radix-ui/primitive@1.1.2", "", {}, "sha512-XnbHrrprsNqZKQhStrSwgRUQzoCI1glLzdw79xiZPoofhGICeZRSQ3dIxAKH1gb3OHfNf4d6f+vAv3kil2eggA=="], - - "@radix-ui/react-arrow": ["@radix-ui/react-arrow@1.1.7", "", { "dependencies": { "@radix-ui/react-primitive": "2.1.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-F+M1tLhO+mlQaOWspE8Wstg+z6PwxwRd8oQ8IXceWz92kfAmalTRf0EjrouQeo7QssEPfCn05B4Ihs1K9WQ/7w=="], - - "@radix-ui/react-collapsible": ["@radix-ui/react-collapsible@1.1.11", "", { "dependencies": { "@radix-ui/primitive": "1.1.2", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-presence": "1.1.4", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-controllable-state": "1.2.2", "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-2qrRsVGSCYasSz1RFOorXwl0H7g7J1frQtgpQgYrt+MOidtPAINHn9CPovQXb83r8ahapdx3Tu0fa/pdFFSdPg=="], - - "@radix-ui/react-collection": ["@radix-ui/react-collection@1.1.7", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-Fh9rGN0MoI4ZFUNyfFVNU4y9LUz93u9/0K+yLgA2bwRojxM8JU1DyvvMBabnZPBgMWREAJvU2jjVzq+LrFUglw=="], - - "@radix-ui/react-compose-refs": ["@radix-ui/react-compose-refs@1.1.2", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg=="], - - "@radix-ui/react-context": ["@radix-ui/react-context@1.1.2", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA=="], - - "@radix-ui/react-dialog": ["@radix-ui/react-dialog@1.1.14", "", { "dependencies": { "@radix-ui/primitive": "1.1.2", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-dismissable-layer": "1.1.10", "@radix-ui/react-focus-guards": "1.1.2", "@radix-ui/react-focus-scope": "1.1.7", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-portal": "1.1.9", "@radix-ui/react-presence": "1.1.4", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-slot": "1.2.3", "@radix-ui/react-use-controllable-state": "1.2.2", "aria-hidden": "^1.2.4", "react-remove-scroll": "^2.6.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-+CpweKjqpzTmwRwcYECQcNYbI8V9VSQt0SNFKeEBLgfucbsLssU6Ppq7wUdNXEGb573bMjFhVjKVll8rmV6zMw=="], - - "@radix-ui/react-direction": ["@radix-ui/react-direction@1.1.1", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-1UEWRX6jnOA2y4H5WczZ44gOOjTEmlqv1uNW4GAJEO5+bauCBhv8snY65Iw5/VOS/ghKN9gr2KjnLKxrsvoMVw=="], - - "@radix-ui/react-dismissable-layer": ["@radix-ui/react-dismissable-layer@1.1.10", "", { "dependencies": { "@radix-ui/primitive": "1.1.2", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-callback-ref": "1.1.1", "@radix-ui/react-use-escape-keydown": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-IM1zzRV4W3HtVgftdQiiOmA0AdJlCtMLe00FXaHwgt3rAnNsIyDqshvkIW3hj/iu5hu8ERP7KIYki6NkqDxAwQ=="], - - "@radix-ui/react-dropdown-menu": ["@radix-ui/react-dropdown-menu@2.1.15", "", { "dependencies": { "@radix-ui/primitive": "1.1.2", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-menu": "2.1.15", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-controllable-state": "1.2.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-mIBnOjgwo9AH3FyKaSWoSu/dYj6VdhJ7frEPiGTeXCdUFHjl9h3mFh2wwhEtINOmYXWhdpf1rY2minFsmaNgVQ=="], - - "@radix-ui/react-focus-guards": ["@radix-ui/react-focus-guards@1.1.2", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-fyjAACV62oPV925xFCrH8DR5xWhg9KYtJT4s3u54jxp+L/hbpTY2kIeEFFbFe+a/HCE94zGQMZLIpVTPVZDhaA=="], - - "@radix-ui/react-focus-scope": ["@radix-ui/react-focus-scope@1.1.7", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-callback-ref": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-t2ODlkXBQyn7jkl6TNaw/MtVEVvIGelJDCG41Okq/KwUsJBwQ4XVZsHAVUkK4mBv3ewiAS3PGuUWuY2BoK4ZUw=="], - - "@radix-ui/react-id": ["@radix-ui/react-id@1.1.1", "", { "dependencies": { "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg=="], - - "@radix-ui/react-menu": ["@radix-ui/react-menu@2.1.15", "", { "dependencies": { "@radix-ui/primitive": "1.1.2", "@radix-ui/react-collection": "1.1.7", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-dismissable-layer": "1.1.10", "@radix-ui/react-focus-guards": "1.1.2", "@radix-ui/react-focus-scope": "1.1.7", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-popper": "1.2.7", "@radix-ui/react-portal": "1.1.9", "@radix-ui/react-presence": "1.1.4", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-roving-focus": "1.1.10", "@radix-ui/react-slot": "1.2.3", "@radix-ui/react-use-callback-ref": "1.1.1", "aria-hidden": "^1.2.4", "react-remove-scroll": "^2.6.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-tVlmA3Vb9n8SZSd+YSbuFR66l87Wiy4du+YE+0hzKQEANA+7cWKH1WgqcEX4pXqxUFQKrWQGHdvEfw00TjFiew=="], - - "@radix-ui/react-popper": ["@radix-ui/react-popper@1.2.7", "", { "dependencies": { "@floating-ui/react-dom": "^2.0.0", "@radix-ui/react-arrow": "1.1.7", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-callback-ref": "1.1.1", "@radix-ui/react-use-layout-effect": "1.1.1", "@radix-ui/react-use-rect": "1.1.1", "@radix-ui/react-use-size": "1.1.1", "@radix-ui/rect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-IUFAccz1JyKcf/RjB552PlWwxjeCJB8/4KxT7EhBHOJM+mN7LdW+B3kacJXILm32xawcMMjb2i0cIZpo+f9kiQ=="], - - "@radix-ui/react-portal": ["@radix-ui/react-portal@1.1.9", "", { "dependencies": { "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-bpIxvq03if6UNwXZ+HTK71JLh4APvnXntDc6XOX8UVq4XQOVl7lwok0AvIl+b8zgCw3fSaVTZMpAPPagXbKmHQ=="], - - "@radix-ui/react-presence": ["@radix-ui/react-presence@1.1.4", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-ueDqRbdc4/bkaQT3GIpLQssRlFgWaL/U2z/S31qRwwLWoxHLgry3SIfCwhxeQNbirEUXFa+lq3RL3oBYXtcmIA=="], - - "@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="], - - "@radix-ui/react-roving-focus": ["@radix-ui/react-roving-focus@1.1.10", "", { "dependencies": { "@radix-ui/primitive": "1.1.2", "@radix-ui/react-collection": "1.1.7", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-callback-ref": "1.1.1", "@radix-ui/react-use-controllable-state": "1.2.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-dT9aOXUen9JSsxnMPv/0VqySQf5eDQ6LCk5Sw28kamz8wSOW2bJdlX2Bg5VUIIcV+6XlHpWTIuTPCf/UNIyq8Q=="], - - "@radix-ui/react-scroll-area": ["@radix-ui/react-scroll-area@1.2.9", "", { "dependencies": { "@radix-ui/number": "1.1.1", "@radix-ui/primitive": "1.1.2", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-presence": "1.1.4", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-callback-ref": "1.1.1", "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-YSjEfBXnhUELsO2VzjdtYYD4CfQjvao+lhhrX5XsHD7/cyUNzljF1FHEbgTPN7LH2MClfwRMIsYlqTYpKTTe2A=="], - - "@radix-ui/react-slot": ["@radix-ui/react-slot@1.2.3", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A=="], - - "@radix-ui/react-tooltip": ["@radix-ui/react-tooltip@1.2.7", "", { "dependencies": { "@radix-ui/primitive": "1.1.2", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-dismissable-layer": "1.1.10", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-popper": "1.2.7", "@radix-ui/react-portal": "1.1.9", "@radix-ui/react-presence": "1.1.4", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-slot": "1.2.3", "@radix-ui/react-use-controllable-state": "1.2.2", "@radix-ui/react-visually-hidden": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-Ap+fNYwKTYJ9pzqW+Xe2HtMRbQ/EeWkj2qykZ6SuEV4iS/o1bZI5ssJbk4D2r8XuDuOBVz/tIx2JObtuqU+5Zw=="], - - "@radix-ui/react-use-callback-ref": ["@radix-ui/react-use-callback-ref@1.1.1", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg=="], - - "@radix-ui/react-use-controllable-state": ["@radix-ui/react-use-controllable-state@1.2.2", "", { "dependencies": { "@radix-ui/react-use-effect-event": "0.0.2", "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg=="], - - "@radix-ui/react-use-effect-event": ["@radix-ui/react-use-effect-event@0.0.2", "", { "dependencies": { "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-Qp8WbZOBe+blgpuUT+lw2xheLP8q0oatc9UpmiemEICxGvFLYmHm9QowVZGHtJlGbS6A6yJ3iViad/2cVjnOiA=="], - - "@radix-ui/react-use-escape-keydown": ["@radix-ui/react-use-escape-keydown@1.1.1", "", { "dependencies": { "@radix-ui/react-use-callback-ref": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-Il0+boE7w/XebUHyBjroE+DbByORGR9KKmITzbR7MyQ4akpORYP/ZmbhAr0DG7RmmBqoOnZdy2QlvajJ2QA59g=="], - - "@radix-ui/react-use-layout-effect": ["@radix-ui/react-use-layout-effect@1.1.1", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ=="], - - "@radix-ui/react-use-rect": ["@radix-ui/react-use-rect@1.1.1", "", { "dependencies": { "@radix-ui/rect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-QTYuDesS0VtuHNNvMh+CjlKJ4LJickCMUAqjlE3+j8w+RlRpwyX3apEQKGFzbZGdo7XNG1tXa+bQqIE7HIXT2w=="], - - "@radix-ui/react-use-size": ["@radix-ui/react-use-size@1.1.1", "", { "dependencies": { "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-ewrXRDTAqAXlkl6t/fkXWNAhFX9I+CkKlw6zjEwk86RSPKwZr3xpBRso655aqYafwtnbpHLj6toFzmd6xdVptQ=="], - - "@radix-ui/react-visually-hidden": ["@radix-ui/react-visually-hidden@1.2.3", "", { "dependencies": { "@radix-ui/react-primitive": "2.1.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-pzJq12tEaaIhqjbzpCuv/OypJY/BPavOofm+dbab+MHLajy277+1lLm6JFcGgF5eskJ6mquGirhXY2GD/8u8Ug=="], - - "@radix-ui/rect": ["@radix-ui/rect@1.1.1", "", {}, "sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw=="], - - "@resvg/resvg-wasm": ["@resvg/resvg-wasm@2.4.0", "", {}, "sha512-C7c51Nn4yTxXFKvgh2txJFNweaVcfUPQxwEUFw4aWsCmfiBDJsTSwviIF8EcwjQ6k8bPyMWCl1vw4BdxE569Cg=="], - - "@rocicorp/prettier-config": ["@rocicorp/prettier-config@0.3.0", "", { "dependencies": { "prettier": "^3.5.3" } }, "sha512-w5xyMZjy32Xb3kgcZs28u/T1Q8XWi4kwWstyvF9ROsa9hNsJxP8g7LeaxwGHFJ7tPx7OXV3bexp1J3XKtoBgPg=="], - - "@rtsao/scc": ["@rtsao/scc@1.1.0", "", {}, "sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g=="], - - "@rushstack/eslint-patch": ["@rushstack/eslint-patch@1.12.0", "", {}, "sha512-5EwMtOqvJMMa3HbmxLlF74e+3/HhwBTMcvt3nqVJgGCozO6hzIPOBlwm8mGVNR9SN2IJpxSnlxczyDjcn7qIyw=="], - - "@shuding/opentype.js": ["@shuding/opentype.js@1.4.0-beta.0", "", { "dependencies": { "fflate": "^0.7.3", "string.prototype.codepointat": "^0.2.1" }, "bin": { "ot": "bin/ot" } }, "sha512-3NgmNyH3l/Hv6EvsWJbsvpcpUba6R8IREQ83nH83cyakCw7uM1arZKNfHwv1Wz6jgqrF/j4x5ELvR6PnK9nTcA=="], - - "@swc/helpers": ["@swc/helpers@0.5.15", "", { "dependencies": { "tslib": "^2.8.0" } }, "sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g=="], - - "@tailwindcss/typography": ["@tailwindcss/typography@0.5.16", "", { "dependencies": { "lodash.castarray": "^4.4.0", "lodash.isplainobject": "^4.0.6", "lodash.merge": "^4.6.2", "postcss-selector-parser": "6.0.10" }, "peerDependencies": { "tailwindcss": ">=3.0.0 || insiders || >=4.0.0-alpha.20 || >=4.0.0-beta.1" } }, "sha512-0wDLwCVF5V3x3b1SGXPCDcdsbDHMBe+lkFzBRaHeLvNi+nrrnZ1lA18u+OTWO8iSWU2GxUOCvlXtDuqftc1oiA=="], - - "@tsconfig/node10": ["@tsconfig/node10@1.0.11", "", {}, "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw=="], - - "@tsconfig/node12": ["@tsconfig/node12@1.0.11", "", {}, "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag=="], - - "@tsconfig/node14": ["@tsconfig/node14@1.0.3", "", {}, "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow=="], - - "@tsconfig/node16": ["@tsconfig/node16@1.0.4", "", {}, "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA=="], - - "@tybys/wasm-util": ["@tybys/wasm-util@0.10.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-VyyPYFlOMNylG45GoAe0xDoLwWuowvf92F9kySqzYh8vmYm7D2u4iUJKa1tOUpS70Ku13ASrOkS4ScXFsTaCNQ=="], - - "@types/acorn": ["@types/acorn@4.0.6", "", { "dependencies": { "@types/estree": "*" } }, "sha512-veQTnWP+1D/xbxVrPC3zHnCZRjSrKfhbMUlEA43iMZLu7EsnTtkJklIuwrCPbOi8YkvDQAiW05VQQFvvz9oieQ=="], - - "@types/debug": ["@types/debug@4.1.12", "", { "dependencies": { "@types/ms": "*" } }, "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ=="], - - "@types/estree": ["@types/estree@1.0.8", "", {}, "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="], - - "@types/estree-jsx": ["@types/estree-jsx@1.0.5", "", { "dependencies": { "@types/estree": "*" } }, "sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg=="], - - "@types/hast": ["@types/hast@3.0.4", "", { "dependencies": { "@types/unist": "*" } }, "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ=="], - - "@types/json-schema": ["@types/json-schema@7.0.15", "", {}, "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA=="], - - "@types/json5": ["@types/json5@0.0.29", "", {}, "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ=="], - - "@types/lunr": ["@types/lunr@2.3.7", "", {}, "sha512-Tb/kUm38e8gmjahQzdCKhbdsvQ9/ppzHFfsJ0dMs3ckqQsRj+P5IkSAwFTBrBxdyr3E/LoMUUrZngjDYAjiE3A=="], - - "@types/mdast": ["@types/mdast@4.0.4", "", { "dependencies": { "@types/unist": "*" } }, "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA=="], - - "@types/mdx": ["@types/mdx@2.0.13", "", {}, "sha512-+OWZQfAYyio6YkJb3HLxDrvnx6SWWDbC0zVPfBRzUk0/nqoDyf6dNxQi3eArPe8rJ473nobTMQ/8Zk+LxJ+Yuw=="], - - "@types/ms": ["@types/ms@0.7.34", "", {}, "sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g=="], - - "@types/node": ["@types/node@24.2.0", "", { "dependencies": { "undici-types": "~7.10.0" } }, "sha512-3xyG3pMCq3oYCNg7/ZP+E1ooTaGB4cG8JWRsqqOYQdbWNY4zbaV0Ennrd7stjiJEFZCaybcIgpTjJWHRfBSIDw=="], - - "@types/prismjs": ["@types/prismjs@1.26.3", "", {}, "sha512-A0D0aTXvjlqJ5ZILMz3rNfDBOx9hHxLZYv2by47Sm/pqW35zzjusrZTryatjN/Rf8Us2gZrJD+KeHbUSTux1Cw=="], - - "@types/react": ["@types/react@19.1.9", "", { "dependencies": { "csstype": "^3.0.2" } }, "sha512-WmdoynAX8Stew/36uTSVMcLJJ1KRh6L3IZRx1PZ7qJtBqT3dYTgyDTx8H1qoRghErydW7xw9mSJ3wS//tCRpFA=="], - - "@types/react-dom": ["@types/react-dom@19.1.7", "", { "peerDependencies": { "@types/react": "^19.0.0" } }, "sha512-i5ZzwYpqjmrKenzkoLM2Ibzt6mAsM7pxB6BCIouEVVmgiqaMj1TjaK7hnA36hbW5aZv20kx7Lw6hWzPWg0Rurw=="], - - "@types/unist": ["@types/unist@3.0.3", "", {}, "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q=="], - - "@typescript-eslint/eslint-plugin": ["@typescript-eslint/eslint-plugin@8.39.0", "", { "dependencies": { "@eslint-community/regexpp": "^4.10.0", "@typescript-eslint/scope-manager": "8.39.0", "@typescript-eslint/type-utils": "8.39.0", "@typescript-eslint/utils": "8.39.0", "@typescript-eslint/visitor-keys": "8.39.0", "graphemer": "^1.4.0", "ignore": "^7.0.0", "natural-compare": "^1.4.0", "ts-api-utils": "^2.1.0" }, "peerDependencies": { "@typescript-eslint/parser": "^8.39.0", "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-bhEz6OZeUR+O/6yx9Jk6ohX6H9JSFTaiY0v9/PuKT3oGK0rn0jNplLmyFUGV+a9gfYnVNwGDwS/UkLIuXNb2Rw=="], - - "@typescript-eslint/parser": ["@typescript-eslint/parser@8.39.0", "", { "dependencies": { "@typescript-eslint/scope-manager": "8.39.0", "@typescript-eslint/types": "8.39.0", "@typescript-eslint/typescript-estree": "8.39.0", "@typescript-eslint/visitor-keys": "8.39.0", "debug": "^4.3.4" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-g3WpVQHngx0aLXn6kfIYCZxM6rRJlWzEkVpqEFLT3SgEDsp9cpCbxxgwnE504q4H+ruSDh/VGS6nqZIDynP+vg=="], - - "@typescript-eslint/project-service": ["@typescript-eslint/project-service@8.39.0", "", { "dependencies": { "@typescript-eslint/tsconfig-utils": "^8.39.0", "@typescript-eslint/types": "^8.39.0", "debug": "^4.3.4" }, "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-CTzJqaSq30V/Z2Og9jogzZt8lJRR5TKlAdXmWgdu4hgcC9Kww5flQ+xFvMxIBWVNdxJO7OifgdOK4PokMIWPew=="], - - "@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.39.0", "", { "dependencies": { "@typescript-eslint/types": "8.39.0", "@typescript-eslint/visitor-keys": "8.39.0" } }, "sha512-8QOzff9UKxOh6npZQ/4FQu4mjdOCGSdO3p44ww0hk8Vu+IGbg0tB/H1LcTARRDzGCC8pDGbh2rissBuuoPgH8A=="], - - "@typescript-eslint/tsconfig-utils": ["@typescript-eslint/tsconfig-utils@8.39.0", "", { "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-Fd3/QjmFV2sKmvv3Mrj8r6N8CryYiCS8Wdb/6/rgOXAWGcFuc+VkQuG28uk/4kVNVZBQuuDHEDUpo/pQ32zsIQ=="], - - "@typescript-eslint/type-utils": ["@typescript-eslint/type-utils@8.39.0", "", { "dependencies": { "@typescript-eslint/types": "8.39.0", "@typescript-eslint/typescript-estree": "8.39.0", "@typescript-eslint/utils": "8.39.0", "debug": "^4.3.4", "ts-api-utils": "^2.1.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-6B3z0c1DXVT2vYA9+z9axjtc09rqKUPRmijD5m9iv8iQpHBRYRMBcgxSiKTZKm6FwWw1/cI4v6em35OsKCiN5Q=="], - - "@typescript-eslint/types": ["@typescript-eslint/types@8.39.0", "", {}, "sha512-ArDdaOllnCj3yn/lzKn9s0pBQYmmyme/v1HbGIGB0GB/knFI3fWMHloC+oYTJW46tVbYnGKTMDK4ah1sC2v0Kg=="], - - "@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.39.0", "", { "dependencies": { "@typescript-eslint/project-service": "8.39.0", "@typescript-eslint/tsconfig-utils": "8.39.0", "@typescript-eslint/types": "8.39.0", "@typescript-eslint/visitor-keys": "8.39.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", "minimatch": "^9.0.4", "semver": "^7.6.0", "ts-api-utils": "^2.1.0" }, "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-ndWdiflRMvfIgQRpckQQLiB5qAKQ7w++V4LlCHwp62eym1HLB/kw7D9f2e8ytONls/jt89TEasgvb+VwnRprsw=="], - - "@typescript-eslint/utils": ["@typescript-eslint/utils@8.39.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.7.0", "@typescript-eslint/scope-manager": "8.39.0", "@typescript-eslint/types": "8.39.0", "@typescript-eslint/typescript-estree": "8.39.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-4GVSvNA0Vx1Ktwvf4sFE+exxJ3QGUorQG1/A5mRfRNZtkBT2xrA/BCO2H0eALx/PnvCS6/vmYwRdDA41EoffkQ=="], - - "@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.39.0", "", { "dependencies": { "@typescript-eslint/types": "8.39.0", "eslint-visitor-keys": "^4.2.1" } }, "sha512-ldgiJ+VAhQCfIjeOgu8Kj5nSxds0ktPOSO9p4+0VDH2R2pLvQraaM5Oen2d7NxzMCm+Sn/vJT+mv2H5u6b/3fA=="], - - "@ungap/structured-clone": ["@ungap/structured-clone@1.2.0", "", {}, "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ=="], - - "@unrs/resolver-binding-android-arm-eabi": ["@unrs/resolver-binding-android-arm-eabi@1.11.1", "", { "os": "android", "cpu": "arm" }, "sha512-ppLRUgHVaGRWUx0R0Ut06Mjo9gBaBkg3v/8AxusGLhsIotbBLuRk51rAzqLC8gq6NyyAojEXglNjzf6R948DNw=="], - - "@unrs/resolver-binding-android-arm64": ["@unrs/resolver-binding-android-arm64@1.11.1", "", { "os": "android", "cpu": "arm64" }, "sha512-lCxkVtb4wp1v+EoN+HjIG9cIIzPkX5OtM03pQYkG+U5O/wL53LC4QbIeazgiKqluGeVEeBlZahHalCaBvU1a2g=="], - - "@unrs/resolver-binding-darwin-arm64": ["@unrs/resolver-binding-darwin-arm64@1.11.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-gPVA1UjRu1Y/IsB/dQEsp2V1pm44Of6+LWvbLc9SDk1c2KhhDRDBUkQCYVWe6f26uJb3fOK8saWMgtX8IrMk3g=="], - - "@unrs/resolver-binding-darwin-x64": ["@unrs/resolver-binding-darwin-x64@1.11.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-cFzP7rWKd3lZaCsDze07QX1SC24lO8mPty9vdP+YVa3MGdVgPmFc59317b2ioXtgCMKGiCLxJ4HQs62oz6GfRQ=="], - - "@unrs/resolver-binding-freebsd-x64": ["@unrs/resolver-binding-freebsd-x64@1.11.1", "", { "os": "freebsd", "cpu": "x64" }, "sha512-fqtGgak3zX4DCB6PFpsH5+Kmt/8CIi4Bry4rb1ho6Av2QHTREM+47y282Uqiu3ZRF5IQioJQ5qWRV6jduA+iGw=="], - - "@unrs/resolver-binding-linux-arm-gnueabihf": ["@unrs/resolver-binding-linux-arm-gnueabihf@1.11.1", "", { "os": "linux", "cpu": "arm" }, "sha512-u92mvlcYtp9MRKmP+ZvMmtPN34+/3lMHlyMj7wXJDeXxuM0Vgzz0+PPJNsro1m3IZPYChIkn944wW8TYgGKFHw=="], - - "@unrs/resolver-binding-linux-arm-musleabihf": ["@unrs/resolver-binding-linux-arm-musleabihf@1.11.1", "", { "os": "linux", "cpu": "arm" }, "sha512-cINaoY2z7LVCrfHkIcmvj7osTOtm6VVT16b5oQdS4beibX2SYBwgYLmqhBjA1t51CarSaBuX5YNsWLjsqfW5Cw=="], - - "@unrs/resolver-binding-linux-arm64-gnu": ["@unrs/resolver-binding-linux-arm64-gnu@1.11.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-34gw7PjDGB9JgePJEmhEqBhWvCiiWCuXsL9hYphDF7crW7UgI05gyBAi6MF58uGcMOiOqSJ2ybEeCvHcq0BCmQ=="], - - "@unrs/resolver-binding-linux-arm64-musl": ["@unrs/resolver-binding-linux-arm64-musl@1.11.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-RyMIx6Uf53hhOtJDIamSbTskA99sPHS96wxVE/bJtePJJtpdKGXO1wY90oRdXuYOGOTuqjT8ACccMc4K6QmT3w=="], - - "@unrs/resolver-binding-linux-ppc64-gnu": ["@unrs/resolver-binding-linux-ppc64-gnu@1.11.1", "", { "os": "linux", "cpu": "ppc64" }, "sha512-D8Vae74A4/a+mZH0FbOkFJL9DSK2R6TFPC9M+jCWYia/q2einCubX10pecpDiTmkJVUH+y8K3BZClycD8nCShA=="], - - "@unrs/resolver-binding-linux-riscv64-gnu": ["@unrs/resolver-binding-linux-riscv64-gnu@1.11.1", "", { "os": "linux", "cpu": "none" }, "sha512-frxL4OrzOWVVsOc96+V3aqTIQl1O2TjgExV4EKgRY09AJ9leZpEg8Ak9phadbuX0BA4k8U5qtvMSQQGGmaJqcQ=="], - - "@unrs/resolver-binding-linux-riscv64-musl": ["@unrs/resolver-binding-linux-riscv64-musl@1.11.1", "", { "os": "linux", "cpu": "none" }, "sha512-mJ5vuDaIZ+l/acv01sHoXfpnyrNKOk/3aDoEdLO/Xtn9HuZlDD6jKxHlkN8ZhWyLJsRBxfv9GYM2utQ1SChKew=="], - - "@unrs/resolver-binding-linux-s390x-gnu": ["@unrs/resolver-binding-linux-s390x-gnu@1.11.1", "", { "os": "linux", "cpu": "s390x" }, "sha512-kELo8ebBVtb9sA7rMe1Cph4QHreByhaZ2QEADd9NzIQsYNQpt9UkM9iqr2lhGr5afh885d/cB5QeTXSbZHTYPg=="], - - "@unrs/resolver-binding-linux-x64-gnu": ["@unrs/resolver-binding-linux-x64-gnu@1.11.1", "", { "os": "linux", "cpu": "x64" }, "sha512-C3ZAHugKgovV5YvAMsxhq0gtXuwESUKc5MhEtjBpLoHPLYM+iuwSj3lflFwK3DPm68660rZ7G8BMcwSro7hD5w=="], - - "@unrs/resolver-binding-linux-x64-musl": ["@unrs/resolver-binding-linux-x64-musl@1.11.1", "", { "os": "linux", "cpu": "x64" }, "sha512-rV0YSoyhK2nZ4vEswT/QwqzqQXw5I6CjoaYMOX0TqBlWhojUf8P94mvI7nuJTeaCkkds3QE4+zS8Ko+GdXuZtA=="], - - "@unrs/resolver-binding-wasm32-wasi": ["@unrs/resolver-binding-wasm32-wasi@1.11.1", "", { "dependencies": { "@napi-rs/wasm-runtime": "^0.2.11" }, "cpu": "none" }, "sha512-5u4RkfxJm+Ng7IWgkzi3qrFOvLvQYnPBmjmZQ8+szTK/b31fQCnleNl1GgEt7nIsZRIf5PLhPwT0WM+q45x/UQ=="], - - "@unrs/resolver-binding-win32-arm64-msvc": ["@unrs/resolver-binding-win32-arm64-msvc@1.11.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-nRcz5Il4ln0kMhfL8S3hLkxI85BXs3o8EYoattsJNdsX4YUU89iOkVn7g0VHSRxFuVMdM4Q1jEpIId1Ihim/Uw=="], - - "@unrs/resolver-binding-win32-ia32-msvc": ["@unrs/resolver-binding-win32-ia32-msvc@1.11.1", "", { "os": "win32", "cpu": "ia32" }, "sha512-DCEI6t5i1NmAZp6pFonpD5m7i6aFrpofcp4LA2i8IIq60Jyo28hamKBxNrZcyOwVOZkgsRp9O2sXWBWP8MnvIQ=="], - - "@unrs/resolver-binding-win32-x64-msvc": ["@unrs/resolver-binding-win32-x64-msvc@1.11.1", "", { "os": "win32", "cpu": "x64" }, "sha512-lrW200hZdbfRtztbygyaq/6jP6AKE8qQN2KvPcJ+x7wiD038YtnYtZ82IMNJ69GJibV7bwL3y9FgK+5w/pYt6g=="], - - "@vercel/og": ["@vercel/og@0.8.5", "", { "dependencies": { "@resvg/resvg-wasm": "2.4.0", "satori": "0.16.0" } }, "sha512-fHqnxfBYcwkamlEgcIzaZqL8IHT09hR7FZL7UdMTdGJyoaBzM/dY6ulO5Swi4ig30FrBJI9I2C+GLV9sb9vexA=="], - - "abbrev": ["abbrev@1.1.1", "", {}, "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q=="], - - "acorn": ["acorn@8.15.0", "", { "bin": "bin/acorn" }, "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg=="], - - "acorn-jsx": ["acorn-jsx@5.3.2", "", { "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ=="], - - "acorn-walk": ["acorn-walk@8.3.4", "", { "dependencies": { "acorn": "^8.11.0" } }, "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g=="], - - "ajv": ["ajv@6.12.6", "", { "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } }, "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g=="], - - "ansi-regex": ["ansi-regex@2.1.1", "", {}, "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA=="], - - "ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], - - "any-promise": ["any-promise@1.3.0", "", {}, "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A=="], - - "anymatch": ["anymatch@3.1.3", "", { "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" } }, "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw=="], - - "arg": ["arg@5.0.2", "", {}, "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg=="], - - "argparse": ["argparse@1.0.10", "", { "dependencies": { "sprintf-js": "~1.0.2" } }, "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg=="], - - "aria-hidden": ["aria-hidden@1.2.6", "", { "dependencies": { "tslib": "^2.0.0" } }, "sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA=="], - - "aria-query": ["aria-query@5.3.2", "", {}, "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw=="], - - "array-buffer-byte-length": ["array-buffer-byte-length@1.0.2", "", { "dependencies": { "call-bound": "^1.0.3", "is-array-buffer": "^3.0.5" } }, "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw=="], - - "array-includes": ["array-includes@3.1.9", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.4", "define-properties": "^1.2.1", "es-abstract": "^1.24.0", "es-object-atoms": "^1.1.1", "get-intrinsic": "^1.3.0", "is-string": "^1.1.1", "math-intrinsics": "^1.1.0" } }, "sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ=="], - - "array.prototype.findlast": ["array.prototype.findlast@1.2.5", "", { "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", "es-abstract": "^1.23.2", "es-errors": "^1.3.0", "es-object-atoms": "^1.0.0", "es-shim-unscopables": "^1.0.2" } }, "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ=="], - - "array.prototype.findlastindex": ["array.prototype.findlastindex@1.2.6", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.4", "define-properties": "^1.2.1", "es-abstract": "^1.23.9", "es-errors": "^1.3.0", "es-object-atoms": "^1.1.1", "es-shim-unscopables": "^1.1.0" } }, "sha512-F/TKATkzseUExPlfvmwQKGITM3DGTK+vkAsCZoDc5daVygbJBnjEUCbgkAvVFsgfXfX4YIqZ/27G3k3tdXrTxQ=="], - - "array.prototype.flat": ["array.prototype.flat@1.3.3", "", { "dependencies": { "call-bind": "^1.0.8", "define-properties": "^1.2.1", "es-abstract": "^1.23.5", "es-shim-unscopables": "^1.0.2" } }, "sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg=="], - - "array.prototype.flatmap": ["array.prototype.flatmap@1.3.3", "", { "dependencies": { "call-bind": "^1.0.8", "define-properties": "^1.2.1", "es-abstract": "^1.23.5", "es-shim-unscopables": "^1.0.2" } }, "sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg=="], - - "array.prototype.tosorted": ["array.prototype.tosorted@1.1.4", "", { "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", "es-abstract": "^1.23.3", "es-errors": "^1.3.0", "es-shim-unscopables": "^1.0.2" } }, "sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA=="], - - "arraybuffer.prototype.slice": ["arraybuffer.prototype.slice@1.0.4", "", { "dependencies": { "array-buffer-byte-length": "^1.0.1", "call-bind": "^1.0.8", "define-properties": "^1.2.1", "es-abstract": "^1.23.5", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.6", "is-array-buffer": "^3.0.4" } }, "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ=="], - - "ast-types-flow": ["ast-types-flow@0.0.8", "", {}, "sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ=="], - - "astring": ["astring@1.8.6", "", { "bin": "bin/astring" }, "sha512-ISvCdHdlTDlH5IpxQJIex7BWBywFWgjJSVdwst+/iQCoEYnyOaQ95+X1JGshuBjGp6nxKUy1jMgE3zPqN7fQdg=="], - - "async-function": ["async-function@1.0.0", "", {}, "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA=="], - - "autoprefixer": ["autoprefixer@10.4.21", "", { "dependencies": { "browserslist": "^4.24.4", "caniuse-lite": "^1.0.30001702", "fraction.js": "^4.3.7", "normalize-range": "^0.1.2", "picocolors": "^1.1.1", "postcss-value-parser": "^4.2.0" }, "peerDependencies": { "postcss": "^8.1.0" }, "bin": "bin/autoprefixer" }, "sha512-O+A6LWV5LDHSJD3LjHYoNi4VLsj/Whi7k6zG12xTYaU4cQ8oxQGckXNX8cRHK5yOZ/ppVHe0ZBXGzSV9jXdVbQ=="], - - "available-typed-arrays": ["available-typed-arrays@1.0.7", "", { "dependencies": { "possible-typed-array-names": "^1.0.0" } }, "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ=="], - - "axe-core": ["axe-core@4.10.3", "", {}, "sha512-Xm7bpRXnDSX2YE2YFfBk2FnF0ep6tmG7xPh8iHee8MIcrgq762Nkce856dYtJYLkuIoYZvGfTs/PbZhideTcEg=="], - - "axobject-query": ["axobject-query@4.1.0", "", {}, "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ=="], - - "bail": ["bail@2.0.2", "", {}, "sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw=="], - - "balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], - - "base64-js": ["base64-js@0.0.8", "", {}, "sha512-3XSA2cR/h/73EzlXXdU6YNycmYI7+kicTxks4eJg2g39biHR84slg2+des+p7iHYhbRg/udIS4TD53WabcOUkw=="], - - "bhttp": ["bhttp@1.2.8", "", { "dependencies": { "bluebird": "^2.8.2", "concat-stream": "^1.4.7", "debug": "^2.1.1", "dev-null": "^0.1.1", "errors": "^0.2.0", "extend": "^2.0.0", "form-data2": "^1.0.0", "form-fix-array": "^1.0.0", "lodash.clonedeep": "^4.5.0", "lodash.merge": "^4.6.2", "stream-length": "^1.0.2", "through2-sink": "^1.0.0", "through2-spy": "^1.2.0", "tough-cookie": "^2.3.1" } }, "sha512-ZwEA5FKEUhc98EHRX+BkNmUOs48RTnglvfze2+p0HrMPwhQBtVw1aAYyylnCtRl6x6vltCkzGo2+twQ6LVfm6Q=="], - - "binary-extensions": ["binary-extensions@2.3.0", "", {}, "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw=="], - - "bluebird": ["bluebird@2.11.0", "", {}, "sha512-UfFSr22dmHPQqPP9XWHRhq+gWnHCYguQGkXQlbyPtW5qTnhFWA8/iXg765tH0cAjy7l/zPJ1aBTO0g5XgA7kvQ=="], - - "brace-expansion": ["brace-expansion@1.1.11", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA=="], - - "braces": ["braces@3.0.3", "", { "dependencies": { "fill-range": "^7.1.1" } }, "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA=="], - - "broken-link-checker": ["broken-link-checker@0.7.8", "", { "dependencies": { "bhttp": "^1.2.1", "calmcard": "~0.1.1", "chalk": "^1.1.3", "char-spinner": "^1.0.1", "condense-whitespace": "^1.0.0", "default-user-agent": "^1.0.0", "errno": "~0.1.4", "extend": "^3.0.0", "http-equiv-refresh": "^1.0.0", "humanize-duration": "^3.9.1", "is-stream": "^1.0.1", "is-string": "^1.0.4", "limited-request-queue": "^2.0.0", "link-types": "^1.1.0", "maybe-callback": "^2.1.0", "nopter": "~0.3.0", "parse5": "^3.0.2", "robot-directives": "~0.3.0", "robots-txt-guard": "~0.1.0", "robots-txt-parse": "~0.0.4", "urlcache": "~0.7.0", "urlobj": "0.0.11" }, "bin": { "blc": "bin/blc", "broken-link-checker": "bin/blc" } }, "sha512-/zH4/nLMNKDeDH5nVuf/R6WYd0Yjnar1NpcdAO2+VlwjGKzJa6y42C03UO+imBSHwe6BefSkVi82fImE2Rb7yg=="], - - "browserslist": ["browserslist@4.25.1", "", { "dependencies": { "caniuse-lite": "^1.0.30001726", "electron-to-chromium": "^1.5.173", "node-releases": "^2.0.19", "update-browserslist-db": "^1.1.3" }, "bin": "cli.js" }, "sha512-KGj0KoOMXLpSNkkEI6Z6mShmQy0bc1I+T7K9N81k4WWMrfz+6fQ6es80B/YLAeRoKvjYE1YSHHOW1qe9xIVzHw=="], - - "buffer-from": ["buffer-from@1.1.2", "", {}, "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="], - - "call-bind": ["call-bind@1.0.8", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.0", "es-define-property": "^1.0.0", "get-intrinsic": "^1.2.4", "set-function-length": "^1.2.2" } }, "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww=="], - - "call-bind-apply-helpers": ["call-bind-apply-helpers@1.0.2", "", { "dependencies": { "es-errors": "^1.3.0", "function-bind": "^1.1.2" } }, "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ=="], - - "call-bound": ["call-bound@1.0.4", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.2", "get-intrinsic": "^1.3.0" } }, "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg=="], - - "caller-path": ["caller-path@0.1.0", "", { "dependencies": { "callsites": "^0.2.0" } }, "sha512-UJiE1otjXPF5/x+T3zTnSFiTOEmJoGTD9HmBoxnCUwho61a2eSNn/VwtwuIBDAo2SEOv1AJ7ARI5gCmohFLu/g=="], - - "callsites": ["callsites@0.2.0", "", {}, "sha512-Zv4Dns9IbXXmPkgRRUjAaJQgfN4xX5p6+RQFhWUqscdvvK2xK/ZL8b3IXIJsj+4sD+f24NwnWy2BY8AJ82JB0A=="], - - "calmcard": ["calmcard@0.1.1", "", {}, "sha512-Ol6L8HQ0n1qFAOmuXcXcOXVpcQ+x5/N8ff+i6G76a4sDjRVtCWmpsG6RorloS1vVG9O0IGq9l7sqaxBnwG/LUA=="], - - "camelcase": ["camelcase@1.2.1", "", {}, "sha512-wzLkDa4K/mzI1OSITC+DUyjgIl/ETNHE9QvYgy6J6Jvqyyz4C0Xfd+lQhb19sX2jMpZV4IssUn0VDVmglV+s4g=="], - - "camelcase-css": ["camelcase-css@2.0.1", "", {}, "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA=="], - - "camelize": ["camelize@1.0.1", "", {}, "sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ=="], - - "caniuse-lite": ["caniuse-lite@1.0.30001731", "", {}, "sha512-lDdp2/wrOmTRWuoB5DpfNkC0rJDU8DqRa6nYL6HK6sytw70QMopt/NIc/9SM7ylItlBWfACXk0tEn37UWM/+mg=="], - - "ccount": ["ccount@2.0.1", "", {}, "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg=="], - - "chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], - - "char-spinner": ["char-spinner@1.0.1", "", {}, "sha512-acv43vqJ0+N0rD+Uw3pDHSxP30FHrywu2NO6/wBaHChJIizpDeBUd6NjqhNhy9LGaEAhZAXn46QzmlAvIWd16g=="], - - "character-entities": ["character-entities@2.0.2", "", {}, "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ=="], - - "character-entities-html4": ["character-entities-html4@2.1.0", "", {}, "sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA=="], - - "character-entities-legacy": ["character-entities-legacy@3.0.0", "", {}, "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ=="], - - "character-reference-invalid": ["character-reference-invalid@2.0.1", "", {}, "sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw=="], - - "chokidar": ["chokidar@3.6.0", "", { "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", "glob-parent": "~5.1.2", "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", "normalize-path": "~3.0.0", "readdirp": "~3.6.0" }, "optionalDependencies": { "fsevents": "~2.3.2" } }, "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw=="], - - "class-variance-authority": ["class-variance-authority@0.7.1", "", { "dependencies": { "clsx": "^2.1.1" } }, "sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg=="], - - "cli-table": ["cli-table@0.3.11", "", { "dependencies": { "colors": "1.0.3" } }, "sha512-IqLQi4lO0nIB4tcdTpN4LCB9FI3uqrJZK7RC515EnhZ6qBaglkIgICb1wjeAqpdoOabm1+SuQtkXIPdYC93jhQ=="], - - "client-only": ["client-only@0.0.1", "", {}, "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA=="], - - "clsx": ["clsx@2.1.1", "", {}, "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA=="], - - "cmdk": ["cmdk@1.1.1", "", { "dependencies": { "@radix-ui/react-compose-refs": "^1.1.1", "@radix-ui/react-dialog": "^1.1.6", "@radix-ui/react-id": "^1.1.0", "@radix-ui/react-primitive": "^2.0.2" }, "peerDependencies": { "react": "^18 || ^19 || ^19.0.0-rc", "react-dom": "^18 || ^19 || ^19.0.0-rc" } }, "sha512-Vsv7kFaXm+ptHDMZ7izaRsP70GgrW9NBNGswt9OZaVBLlE0SNpDq8eu/VGXyF9r7M0azK3Wy7OlYXsuyYLFzHg=="], - - "collapse-white-space": ["collapse-white-space@2.1.0", "", {}, "sha512-loKTxY1zCOuG4j9f6EPnuyyYkf58RnhhWTvRoZEokgB+WbdXehfjFviyOVYkqzEWz1Q5kRiZdBYS5SwxbQYwzw=="], - - "color": ["color@4.2.3", "", { "dependencies": { "color-convert": "^2.0.1", "color-string": "^1.9.0" } }, "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A=="], - - "color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="], - - "color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="], - - "color-string": ["color-string@1.9.1", "", { "dependencies": { "color-name": "^1.0.0", "simple-swizzle": "^0.2.2" } }, "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg=="], - - "colors": ["colors@1.0.3", "", {}, "sha512-pFGrxThWcWQ2MsAz6RtgeWe4NK2kUE1WfsrvvlctdII745EW9I0yflqhe7++M5LEc7bV2c/9/5zc8sFcpL0Drw=="], - - "combined-stream2": ["combined-stream2@1.1.2", "", { "dependencies": { "bluebird": "^2.8.1", "debug": "^2.1.1", "stream-length": "^1.0.1" } }, "sha512-sVqUHJmbdVm+HZWy4l34BPLczxI4fltN4Bm2vcvASsqBIXW4xFb4TRkwM8bw/UUXK9/OdHdAwi2cRYVEKrxzbg=="], - - "comma-separated-tokens": ["comma-separated-tokens@2.0.3", "", {}, "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg=="], - - "commander": ["commander@4.1.1", "", {}, "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA=="], - - "concat-map": ["concat-map@0.0.1", "", {}, "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="], - - "concat-stream": ["concat-stream@1.6.2", "", { "dependencies": { "buffer-from": "^1.0.0", "inherits": "^2.0.3", "readable-stream": "^2.2.2", "typedarray": "^0.0.6" } }, "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw=="], - - "condense-whitespace": ["condense-whitespace@1.0.0", "", {}, "sha512-1eu4eAfuH4oongidVWOX8EkYUxTmav9SpEW1YUeNVWzrdgJTEoXFnF7WuLL+sI9SSQdfnKWjObAn/g9SkseUiw=="], - - "core-util-is": ["core-util-is@1.0.3", "", {}, "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ=="], - - "create-require": ["create-require@1.1.1", "", {}, "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ=="], - - "cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="], - - "css-background-parser": ["css-background-parser@0.1.0", "", {}, "sha512-2EZLisiZQ+7m4wwur/qiYJRniHX4K5Tc9w93MT3AS0WS1u5kaZ4FKXlOTBhOjc+CgEgPiGY+fX1yWD8UwpEqUA=="], - - "css-box-shadow": ["css-box-shadow@1.0.0-3", "", {}, "sha512-9jaqR6e7Ohds+aWwmhe6wILJ99xYQbfmK9QQB9CcMjDbTxPZjwEmUQpU91OG05Xgm8BahT5fW+svbsQGjS/zPg=="], - - "css-color-keywords": ["css-color-keywords@1.0.0", "", {}, "sha512-FyyrDHZKEjXDpNJYvVsV960FiqQyXc/LlYmsxl2BcdMb2WPx0OGRVgTg55rPSyLSNMqP52R9r8geSp7apN3Ofg=="], - - "css-gradient-parser": ["css-gradient-parser@0.0.16", "", {}, "sha512-3O5QdqgFRUbXvK1x5INf1YkBz1UKSWqrd63vWsum8MNHDBYD5urm3QtxZbKU259OrEXNM26lP/MPY3d1IGkBgA=="], - - "css-to-react-native": ["css-to-react-native@3.2.0", "", { "dependencies": { "camelize": "^1.0.0", "css-color-keywords": "^1.0.0", "postcss-value-parser": "^4.0.2" } }, "sha512-e8RKaLXMOFii+02mOlqwjbD00KSEKqblnpO9e++1aXS1fPQOpS1YoqdVHBqPjHNoxeF2mimzVqawm2KCbEdtHQ=="], - - "cssesc": ["cssesc@3.0.0", "", { "bin": "bin/cssesc" }, "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg=="], - - "csstype": ["csstype@3.1.3", "", {}, "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="], - - "damerau-levenshtein": ["damerau-levenshtein@1.0.8", "", {}, "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA=="], - - "data-view-buffer": ["data-view-buffer@1.0.2", "", { "dependencies": { "call-bound": "^1.0.3", "es-errors": "^1.3.0", "is-data-view": "^1.0.2" } }, "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ=="], - - "data-view-byte-length": ["data-view-byte-length@1.0.2", "", { "dependencies": { "call-bound": "^1.0.3", "es-errors": "^1.3.0", "is-data-view": "^1.0.2" } }, "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ=="], - - "data-view-byte-offset": ["data-view-byte-offset@1.0.1", "", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "is-data-view": "^1.0.1" } }, "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ=="], - - "debug": ["debug@4.3.4", "", { "dependencies": { "ms": "2.1.2" } }, "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ=="], - - "decode-named-character-reference": ["decode-named-character-reference@1.0.2", "", { "dependencies": { "character-entities": "^2.0.0" } }, "sha512-O8x12RzrUF8xyVcY0KJowWsmaJxQbmy0/EtnNtHRpsOcT7dFk5W598coHqBVpmWo1oQQfsCqfCmkZN5DJrZVdg=="], - - "deep-is": ["deep-is@0.1.4", "", {}, "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ=="], - - "default-user-agent": ["default-user-agent@1.0.0", "", { "dependencies": { "os-name": "~1.0.3" } }, "sha512-bDF7bg6OSNcSwFWPu4zYKpVkJZQYVrAANMYB8bc9Szem1D0yKdm4sa/rOCs2aC9+2GMqQ7KnwtZRvDhmLF0dXw=="], - - "define-data-property": ["define-data-property@1.1.4", "", { "dependencies": { "es-define-property": "^1.0.0", "es-errors": "^1.3.0", "gopd": "^1.0.1" } }, "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A=="], - - "define-properties": ["define-properties@1.2.1", "", { "dependencies": { "define-data-property": "^1.0.1", "has-property-descriptors": "^1.0.0", "object-keys": "^1.1.1" } }, "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg=="], - - "dequal": ["dequal@2.0.3", "", {}, "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA=="], - - "detect-libc": ["detect-libc@2.0.4", "", {}, "sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA=="], - - "detect-node-es": ["detect-node-es@1.1.0", "", {}, "sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ=="], - - "dev-null": ["dev-null@0.1.1", "", {}, "sha512-nMNZG0zfMgmdv8S5O0TM5cpwNbGKRGPCxVsr0SmA3NZZy9CYBbuNLL0PD3Acx9e5LIUgwONXtM9kM6RlawPxEQ=="], - - "devlop": ["devlop@1.1.0", "", { "dependencies": { "dequal": "^2.0.0" } }, "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA=="], - - "didyoumean": ["didyoumean@1.2.2", "", {}, "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw=="], - - "diff": ["diff@4.0.2", "", {}, "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A=="], - - "dlv": ["dlv@1.1.3", "", {}, "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA=="], - - "doctrine": ["doctrine@2.1.0", "", { "dependencies": { "esutils": "^2.0.2" } }, "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw=="], - - "dunder-proto": ["dunder-proto@1.0.1", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.1", "es-errors": "^1.3.0", "gopd": "^1.2.0" } }, "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A=="], - - "duplexer": ["duplexer@0.1.2", "", {}, "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg=="], - - "eastasianwidth": ["eastasianwidth@0.2.0", "", {}, "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA=="], - - "electron-to-chromium": ["electron-to-chromium@1.5.199", "", {}, "sha512-3gl0S7zQd88kCAZRO/DnxtBKuhMO4h0EaQIN3YgZfV6+pW+5+bf2AdQeHNESCoaQqo/gjGVYEf2YM4O5HJQqpQ=="], - - "emoji-regex": ["emoji-regex@9.2.2", "", {}, "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="], - - "emoji-regex-xs": ["emoji-regex-xs@2.0.1", "", {}, "sha512-1QFuh8l7LqUcKe24LsPUNzjrzJQ7pgRwp1QMcZ5MX6mFplk2zQ08NVCM84++1cveaUUYtcCYHmeFEuNg16sU4g=="], - - "entities": ["entities@4.5.0", "", {}, "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="], - - "eol": ["eol@0.2.0", "", {}, "sha512-LCBxmDyUDh5pAXALohe9NCwyedyECwpFrcebZyW/XNTzn4WZFY3cX9MdkrJQu71ojEoHqcsciqFG7d3WQA+1Ew=="], - - "errno": ["errno@0.1.8", "", { "dependencies": { "prr": "~1.0.1" }, "bin": "cli.js" }, "sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A=="], - - "errors": ["errors@0.2.0", "", {}, "sha512-W0w4yTo+twP/wGTF25kBGAXroAHzvxZvEDHJsCixlWS8lf8li0aZDhT+hz0mHQwsSW5esD5jyTQkaqA0ZHF83A=="], - - "es-abstract": ["es-abstract@1.24.0", "", { "dependencies": { "array-buffer-byte-length": "^1.0.2", "arraybuffer.prototype.slice": "^1.0.4", "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.8", "call-bound": "^1.0.4", "data-view-buffer": "^1.0.2", "data-view-byte-length": "^1.0.2", "data-view-byte-offset": "^1.0.1", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.1.1", "es-set-tostringtag": "^2.1.0", "es-to-primitive": "^1.3.0", "function.prototype.name": "^1.1.8", "get-intrinsic": "^1.3.0", "get-proto": "^1.0.1", "get-symbol-description": "^1.1.0", "globalthis": "^1.0.4", "gopd": "^1.2.0", "has-property-descriptors": "^1.0.2", "has-proto": "^1.2.0", "has-symbols": "^1.1.0", "hasown": "^2.0.2", "internal-slot": "^1.1.0", "is-array-buffer": "^3.0.5", "is-callable": "^1.2.7", "is-data-view": "^1.0.2", "is-negative-zero": "^2.0.3", "is-regex": "^1.2.1", "is-set": "^2.0.3", "is-shared-array-buffer": "^1.0.4", "is-string": "^1.1.1", "is-typed-array": "^1.1.15", "is-weakref": "^1.1.1", "math-intrinsics": "^1.1.0", "object-inspect": "^1.13.4", "object-keys": "^1.1.1", "object.assign": "^4.1.7", "own-keys": "^1.0.1", "regexp.prototype.flags": "^1.5.4", "safe-array-concat": "^1.1.3", "safe-push-apply": "^1.0.0", "safe-regex-test": "^1.1.0", "set-proto": "^1.0.0", "stop-iteration-iterator": "^1.1.0", "string.prototype.trim": "^1.2.10", "string.prototype.trimend": "^1.0.9", "string.prototype.trimstart": "^1.0.8", "typed-array-buffer": "^1.0.3", "typed-array-byte-length": "^1.0.3", "typed-array-byte-offset": "^1.0.4", "typed-array-length": "^1.0.7", "unbox-primitive": "^1.1.0", "which-typed-array": "^1.1.19" } }, "sha512-WSzPgsdLtTcQwm4CROfS5ju2Wa1QQcVeT37jFjYzdFz1r9ahadC8B8/a4qxJxM+09F18iumCdRmlr96ZYkQvEg=="], - - "es-define-property": ["es-define-property@1.0.1", "", {}, "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g=="], - - "es-errors": ["es-errors@1.3.0", "", {}, "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw=="], - - "es-iterator-helpers": ["es-iterator-helpers@1.2.1", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.3", "define-properties": "^1.2.1", "es-abstract": "^1.23.6", "es-errors": "^1.3.0", "es-set-tostringtag": "^2.0.3", "function-bind": "^1.1.2", "get-intrinsic": "^1.2.6", "globalthis": "^1.0.4", "gopd": "^1.2.0", "has-property-descriptors": "^1.0.2", "has-proto": "^1.2.0", "has-symbols": "^1.1.0", "internal-slot": "^1.1.0", "iterator.prototype": "^1.1.4", "safe-array-concat": "^1.1.3" } }, "sha512-uDn+FE1yrDzyC0pCo961B2IHbdM8y/ACZsKD4dG6WqrjV53BADjwa7D+1aom2rsNVfLyDgU/eigvlJGJ08OQ4w=="], - - "es-object-atoms": ["es-object-atoms@1.1.1", "", { "dependencies": { "es-errors": "^1.3.0" } }, "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA=="], - - "es-set-tostringtag": ["es-set-tostringtag@2.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "get-intrinsic": "^1.2.6", "has-tostringtag": "^1.0.2", "hasown": "^2.0.2" } }, "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA=="], - - "es-shim-unscopables": ["es-shim-unscopables@1.1.0", "", { "dependencies": { "hasown": "^2.0.2" } }, "sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw=="], - - "es-to-primitive": ["es-to-primitive@1.3.0", "", { "dependencies": { "is-callable": "^1.2.7", "is-date-object": "^1.0.5", "is-symbol": "^1.0.4" } }, "sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g=="], - - "esbuild": ["esbuild@0.25.0", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.0", "@esbuild/android-arm": "0.25.0", "@esbuild/android-arm64": "0.25.0", "@esbuild/android-x64": "0.25.0", "@esbuild/darwin-arm64": "0.25.0", "@esbuild/darwin-x64": "0.25.0", "@esbuild/freebsd-arm64": "0.25.0", "@esbuild/freebsd-x64": "0.25.0", "@esbuild/linux-arm": "0.25.0", "@esbuild/linux-arm64": "0.25.0", "@esbuild/linux-ia32": "0.25.0", "@esbuild/linux-loong64": "0.25.0", "@esbuild/linux-mips64el": "0.25.0", "@esbuild/linux-ppc64": "0.25.0", "@esbuild/linux-riscv64": "0.25.0", "@esbuild/linux-s390x": "0.25.0", "@esbuild/linux-x64": "0.25.0", "@esbuild/netbsd-arm64": "0.25.0", "@esbuild/netbsd-x64": "0.25.0", "@esbuild/openbsd-arm64": "0.25.0", "@esbuild/openbsd-x64": "0.25.0", "@esbuild/sunos-x64": "0.25.0", "@esbuild/win32-arm64": "0.25.0", "@esbuild/win32-ia32": "0.25.0", "@esbuild/win32-x64": "0.25.0" }, "bin": "bin/esbuild" }, "sha512-BXq5mqc8ltbaN34cDqWuYKyNhX8D/Z0J1xdtdQ8UcIIIyJyz+ZMKUt58tF3SrZ85jcfN/PZYhjR5uDQAYNVbuw=="], - - "escalade": ["escalade@3.2.0", "", {}, "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA=="], - - "escape-html": ["escape-html@1.0.3", "", {}, "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow=="], - - "escape-string-regexp": ["escape-string-regexp@4.0.0", "", {}, "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA=="], - - "eslint": ["eslint@9.32.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.12.1", "@eslint/config-array": "^0.21.0", "@eslint/config-helpers": "^0.3.0", "@eslint/core": "^0.15.0", "@eslint/eslintrc": "^3.3.1", "@eslint/js": "9.32.0", "@eslint/plugin-kit": "^0.3.4", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", "@types/estree": "^1.0.6", "@types/json-schema": "^7.0.15", "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", "eslint-scope": "^8.4.0", "eslint-visitor-keys": "^4.2.1", "espree": "^10.4.0", "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^8.0.0", "find-up": "^5.0.0", "glob-parent": "^6.0.2", "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "json-stable-stringify-without-jsonify": "^1.0.1", "lodash.merge": "^4.6.2", "minimatch": "^3.1.2", "natural-compare": "^1.4.0", "optionator": "^0.9.3" }, "peerDependencies": { "jiti": "*" }, "bin": "bin/eslint.js" }, "sha512-LSehfdpgMeWcTZkWZVIJl+tkZ2nuSkyyB9C27MZqFWXuph7DvaowgcTvKqxvpLW1JZIk8PN7hFY3Rj9LQ7m7lg=="], - - "eslint-config-next": ["eslint-config-next@15.4.6", "", { "dependencies": { "@next/eslint-plugin-next": "15.4.6", "@rushstack/eslint-patch": "^1.10.3", "@typescript-eslint/eslint-plugin": "^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0", "@typescript-eslint/parser": "^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0", "eslint-import-resolver-node": "^0.3.6", "eslint-import-resolver-typescript": "^3.5.2", "eslint-plugin-import": "^2.31.0", "eslint-plugin-jsx-a11y": "^6.10.0", "eslint-plugin-react": "^7.37.0", "eslint-plugin-react-hooks": "^5.0.0" }, "peerDependencies": { "eslint": "^7.23.0 || ^8.0.0 || ^9.0.0", "typescript": ">=3.3.1" } }, "sha512-4uznvw5DlTTjrZgYZjMciSdDDMO2SWIuQgUNaFyC2O3Zw3Z91XeIejeVa439yRq2CnJb/KEvE4U2AeN/66FpUA=="], - - "eslint-import-resolver-node": ["eslint-import-resolver-node@0.3.9", "", { "dependencies": { "debug": "^3.2.7", "is-core-module": "^2.13.0", "resolve": "^1.22.4" } }, "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g=="], - - "eslint-import-resolver-typescript": ["eslint-import-resolver-typescript@3.10.1", "", { "dependencies": { "@nolyfill/is-core-module": "1.0.39", "debug": "^4.4.0", "get-tsconfig": "^4.10.0", "is-bun-module": "^2.0.0", "stable-hash": "^0.0.5", "tinyglobby": "^0.2.13", "unrs-resolver": "^1.6.2" }, "peerDependencies": { "eslint": "*", "eslint-plugin-import": "*", "eslint-plugin-import-x": "*" }, "optionalPeers": ["eslint-plugin-import-x"] }, "sha512-A1rHYb06zjMGAxdLSkN2fXPBwuSaQ0iO5M/hdyS0Ajj1VBaRp0sPD3dn1FhME3c/JluGFbwSxyCfqdSbtQLAHQ=="], - - "eslint-module-utils": ["eslint-module-utils@2.12.1", "", { "dependencies": { "debug": "^3.2.7" } }, "sha512-L8jSWTze7K2mTg0vos/RuLRS5soomksDPoJLXIslC7c8Wmut3bx7CPpJijDcBZtxQ5lrbUdM+s0OlNbz0DCDNw=="], - - "eslint-plugin-import": ["eslint-plugin-import@2.32.0", "", { "dependencies": { "@rtsao/scc": "^1.1.0", "array-includes": "^3.1.9", "array.prototype.findlastindex": "^1.2.6", "array.prototype.flat": "^1.3.3", "array.prototype.flatmap": "^1.3.3", "debug": "^3.2.7", "doctrine": "^2.1.0", "eslint-import-resolver-node": "^0.3.9", "eslint-module-utils": "^2.12.1", "hasown": "^2.0.2", "is-core-module": "^2.16.1", "is-glob": "^4.0.3", "minimatch": "^3.1.2", "object.fromentries": "^2.0.8", "object.groupby": "^1.0.3", "object.values": "^1.2.1", "semver": "^6.3.1", "string.prototype.trimend": "^1.0.9", "tsconfig-paths": "^3.15.0" }, "peerDependencies": { "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9" } }, "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA=="], - - "eslint-plugin-jsx-a11y": ["eslint-plugin-jsx-a11y@6.10.2", "", { "dependencies": { "aria-query": "^5.3.2", "array-includes": "^3.1.8", "array.prototype.flatmap": "^1.3.2", "ast-types-flow": "^0.0.8", "axe-core": "^4.10.0", "axobject-query": "^4.1.0", "damerau-levenshtein": "^1.0.8", "emoji-regex": "^9.2.2", "hasown": "^2.0.2", "jsx-ast-utils": "^3.3.5", "language-tags": "^1.0.9", "minimatch": "^3.1.2", "object.fromentries": "^2.0.8", "safe-regex-test": "^1.0.3", "string.prototype.includes": "^2.0.1" }, "peerDependencies": { "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9" } }, "sha512-scB3nz4WmG75pV8+3eRUQOHZlNSUhFNq37xnpgRkCCELU3XMvXAxLk1eqWWyE22Ki4Q01Fnsw9BA3cJHDPgn2Q=="], - - "eslint-plugin-react": ["eslint-plugin-react@7.37.5", "", { "dependencies": { "array-includes": "^3.1.8", "array.prototype.findlast": "^1.2.5", "array.prototype.flatmap": "^1.3.3", "array.prototype.tosorted": "^1.1.4", "doctrine": "^2.1.0", "es-iterator-helpers": "^1.2.1", "estraverse": "^5.3.0", "hasown": "^2.0.2", "jsx-ast-utils": "^2.4.1 || ^3.0.0", "minimatch": "^3.1.2", "object.entries": "^1.1.9", "object.fromentries": "^2.0.8", "object.values": "^1.2.1", "prop-types": "^15.8.1", "resolve": "^2.0.0-next.5", "semver": "^6.3.1", "string.prototype.matchall": "^4.0.12", "string.prototype.repeat": "^1.0.0" }, "peerDependencies": { "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7" } }, "sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA=="], - - "eslint-plugin-react-hooks": ["eslint-plugin-react-hooks@5.2.0", "", { "peerDependencies": { "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0" } }, "sha512-+f15FfK64YQwZdJNELETdn5ibXEUQmW1DZL6KXhNnc2heoy/sg9VJJeT7n8TlMWouzWqSWavFkIhHyIbIAEapg=="], - - "eslint-scope": ["eslint-scope@8.4.0", "", { "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" } }, "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg=="], - - "eslint-visitor-keys": ["eslint-visitor-keys@4.2.1", "", {}, "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ=="], - - "espree": ["espree@10.4.0", "", { "dependencies": { "acorn": "^8.15.0", "acorn-jsx": "^5.3.2", "eslint-visitor-keys": "^4.2.1" } }, "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ=="], - - "esprima": ["esprima@4.0.1", "", { "bin": { "esparse": "bin/esparse.js", "esvalidate": "bin/esvalidate.js" } }, "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A=="], - - "esquery": ["esquery@1.5.0", "", { "dependencies": { "estraverse": "^5.1.0" } }, "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg=="], - - "esrecurse": ["esrecurse@4.3.0", "", { "dependencies": { "estraverse": "^5.2.0" } }, "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag=="], - - "estraverse": ["estraverse@5.3.0", "", {}, "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA=="], - - "estree-util-attach-comments": ["estree-util-attach-comments@3.0.0", "", { "dependencies": { "@types/estree": "^1.0.0" } }, "sha512-cKUwm/HUcTDsYh/9FgnuFqpfquUbwIqwKM26BVCGDPVgvaCl/nDCCjUfiLlx6lsEZ3Z4RFxNbOQ60pkaEwFxGw=="], - - "estree-util-build-jsx": ["estree-util-build-jsx@3.0.1", "", { "dependencies": { "@types/estree-jsx": "^1.0.0", "devlop": "^1.0.0", "estree-util-is-identifier-name": "^3.0.0", "estree-walker": "^3.0.0" } }, "sha512-8U5eiL6BTrPxp/CHbs2yMgP8ftMhR5ww1eIKoWRMlqvltHF8fZn5LRDvTKuxD3DUn+shRbLGqXemcP51oFCsGQ=="], - - "estree-util-is-identifier-name": ["estree-util-is-identifier-name@3.0.0", "", {}, "sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg=="], - - "estree-util-to-js": ["estree-util-to-js@2.0.0", "", { "dependencies": { "@types/estree-jsx": "^1.0.0", "astring": "^1.8.0", "source-map": "^0.7.0" } }, "sha512-WDF+xj5rRWmD5tj6bIqRi6CkLIXbbNQUcxQHzGysQzvHmdYG2G7p/Tf0J0gpxGgkeMZNTIjT/AoSvC9Xehcgdg=="], - - "estree-util-visit": ["estree-util-visit@2.0.0", "", { "dependencies": { "@types/estree-jsx": "^1.0.0", "@types/unist": "^3.0.0" } }, "sha512-m5KgiH85xAhhW8Wta0vShLcUvOsh3LLPI2YVwcbio1l7E09NTLL1EyMZFM1OyWowoH0skScNbhOPl4kcBgzTww=="], - - "estree-walker": ["estree-walker@3.0.3", "", { "dependencies": { "@types/estree": "^1.0.0" } }, "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g=="], - - "esutils": ["esutils@2.0.3", "", {}, "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g=="], - - "extend": ["extend@3.0.2", "", {}, "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="], - - "extend-shallow": ["extend-shallow@2.0.1", "", { "dependencies": { "is-extendable": "^0.1.0" } }, "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug=="], - - "fast-deep-equal": ["fast-deep-equal@3.1.3", "", {}, "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="], - - "fast-glob": ["fast-glob@3.3.3", "", { "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", "micromatch": "^4.0.8" } }, "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg=="], - - "fast-json-stable-stringify": ["fast-json-stable-stringify@2.1.0", "", {}, "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="], - - "fast-levenshtein": ["fast-levenshtein@2.0.6", "", {}, "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw=="], - - "fastq": ["fastq@1.19.1", "", { "dependencies": { "reusify": "^1.0.4" } }, "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ=="], - - "fdir": ["fdir@6.4.6", "", { "peerDependencies": { "picomatch": "^3 || ^4" } }, "sha512-hiFoqpyZcfNm1yc4u8oWCf9A2c4D3QjCrks3zmoVKVxpQRzmPNar1hUJcBG2RQHvEVGDN+Jm81ZheVLAQMK6+w=="], - - "fflate": ["fflate@0.7.4", "", {}, "sha512-5u2V/CDW15QM1XbbgS+0DfPxVB+jUKhWEKuuFuHncbk3tEEqzmoXL+2KyOFuKGqOnmdIy0/davWF1CkuwtibCw=="], - - "file-entry-cache": ["file-entry-cache@8.0.0", "", { "dependencies": { "flat-cache": "^4.0.0" } }, "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ=="], - - "fill-range": ["fill-range@7.1.1", "", { "dependencies": { "to-regex-range": "^5.0.1" } }, "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg=="], - - "find-up": ["find-up@5.0.0", "", { "dependencies": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" } }, "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng=="], - - "flat-cache": ["flat-cache@4.0.1", "", { "dependencies": { "flatted": "^3.2.9", "keyv": "^4.5.4" } }, "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw=="], - - "flatted": ["flatted@3.3.3", "", {}, "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg=="], - - "for-each": ["for-each@0.3.5", "", { "dependencies": { "is-callable": "^1.2.7" } }, "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg=="], - - "foreground-child": ["foreground-child@3.3.1", "", { "dependencies": { "cross-spawn": "^7.0.6", "signal-exit": "^4.0.1" } }, "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw=="], - - "form-data2": ["form-data2@1.0.4", "", { "dependencies": { "bluebird": "^2.8.2", "combined-stream2": "^1.0.2", "debug": "^2.1.1", "mime": "^1.3.4", "uuid": "^2.0.1" } }, "sha512-buz4C3F6/7Vpdxt7dNU/tSfjQO/5z9Pyjfb43VhlVvSos5zVhCcMuW9sF1yJ2FdxZRCD2sWQ9WhqUiYLt+AUVQ=="], - - "form-fix-array": ["form-fix-array@1.0.0", "", {}, "sha512-f3qXI4CcvW7/6vqTKwCftcrFgfEBfWYPQTfvXrHYevHbJVfc107/SVvXvwUAYMaUAHdvu9ENQvLufJKphQI14w=="], - - "fraction.js": ["fraction.js@4.3.7", "", {}, "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew=="], - - "fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="], - - "function-bind": ["function-bind@1.1.2", "", {}, "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="], - - "function.prototype.name": ["function.prototype.name@1.1.8", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.3", "define-properties": "^1.2.1", "functions-have-names": "^1.2.3", "hasown": "^2.0.2", "is-callable": "^1.2.7" } }, "sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q=="], - - "functions-have-names": ["functions-have-names@1.2.3", "", {}, "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ=="], - - "get-intrinsic": ["get-intrinsic@1.3.0", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.2", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.1.1", "function-bind": "^1.1.2", "get-proto": "^1.0.1", "gopd": "^1.2.0", "has-symbols": "^1.1.0", "hasown": "^2.0.2", "math-intrinsics": "^1.1.0" } }, "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ=="], - - "get-nonce": ["get-nonce@1.0.1", "", {}, "sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q=="], - - "get-proto": ["get-proto@1.0.1", "", { "dependencies": { "dunder-proto": "^1.0.1", "es-object-atoms": "^1.0.0" } }, "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g=="], - - "get-symbol-description": ["get-symbol-description@1.1.0", "", { "dependencies": { "call-bound": "^1.0.3", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.6" } }, "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg=="], - - "get-tsconfig": ["get-tsconfig@4.10.0", "", { "dependencies": { "resolve-pkg-maps": "^1.0.0" } }, "sha512-kGzZ3LWWQcGIAmg6iWvXn0ei6WDtV26wzHRMwDSzmAbcXrTEXxHy6IehI6/4eT6VRKyMP1eF1VqwrVUmE/LR7A=="], - - "github-slugger": ["github-slugger@2.0.0", "", {}, "sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw=="], - - "glob": ["glob@10.4.5", "", { "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^3.1.2", "minimatch": "^9.0.4", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^1.11.1" }, "bin": "dist/esm/bin.mjs" }, "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg=="], - - "glob-parent": ["glob-parent@6.0.2", "", { "dependencies": { "is-glob": "^4.0.3" } }, "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A=="], - - "globals": ["globals@14.0.0", "", {}, "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ=="], - - "globalthis": ["globalthis@1.0.4", "", { "dependencies": { "define-properties": "^1.2.1", "gopd": "^1.0.1" } }, "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ=="], - - "gopd": ["gopd@1.2.0", "", {}, "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg=="], - - "graphemer": ["graphemer@1.4.0", "", {}, "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag=="], - - "gray-matter": ["gray-matter@4.0.3", "", { "dependencies": { "js-yaml": "^3.13.1", "kind-of": "^6.0.2", "section-matter": "^1.0.0", "strip-bom-string": "^1.0.0" } }, "sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q=="], - - "has-ansi": ["has-ansi@2.0.0", "", { "dependencies": { "ansi-regex": "^2.0.0" } }, "sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg=="], - - "has-bigints": ["has-bigints@1.0.2", "", {}, "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ=="], - - "has-flag": ["has-flag@4.0.0", "", {}, "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="], - - "has-property-descriptors": ["has-property-descriptors@1.0.2", "", { "dependencies": { "es-define-property": "^1.0.0" } }, "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg=="], - - "has-proto": ["has-proto@1.2.0", "", { "dependencies": { "dunder-proto": "^1.0.0" } }, "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ=="], - - "has-symbols": ["has-symbols@1.1.0", "", {}, "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ=="], - - "has-tostringtag": ["has-tostringtag@1.0.2", "", { "dependencies": { "has-symbols": "^1.0.3" } }, "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw=="], - - "hasown": ["hasown@2.0.2", "", { "dependencies": { "function-bind": "^1.1.2" } }, "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ=="], - - "hast": ["hast@1.0.0", "", {}, "sha512-vFUqlRV5C+xqP76Wwq2SrM0kipnmpxJm7OfvVXpB35Fp+Fn4MV+ozr+JZr5qFvyR1q/U+Foim2x+3P+x9S1PLA=="], - - "hast-util-from-html": ["hast-util-from-html@2.0.1", "", { "dependencies": { "@types/hast": "^3.0.0", "devlop": "^1.1.0", "hast-util-from-parse5": "^8.0.0", "parse5": "^7.0.0", "vfile": "^6.0.0", "vfile-message": "^4.0.0" } }, "sha512-RXQBLMl9kjKVNkJTIO6bZyb2n+cUH8LFaSSzo82jiLT6Tfc+Pt7VQCS+/h3YwG4jaNE2TA2sdJisGWR+aJrp0g=="], - - "hast-util-from-parse5": ["hast-util-from-parse5@8.0.1", "", { "dependencies": { "@types/hast": "^3.0.0", "@types/unist": "^3.0.0", "devlop": "^1.0.0", "hastscript": "^8.0.0", "property-information": "^6.0.0", "vfile": "^6.0.0", "vfile-location": "^5.0.0", "web-namespaces": "^2.0.0" } }, "sha512-Er/Iixbc7IEa7r/XLtuG52zoqn/b3Xng/w6aZQ0xGVxzhw5xUFxcRqdPzP6yFi/4HBYRaifaI5fQ1RH8n0ZeOQ=="], - - "hast-util-heading-rank": ["hast-util-heading-rank@3.0.0", "", { "dependencies": { "@types/hast": "^3.0.0" } }, "sha512-EJKb8oMUXVHcWZTDepnr+WNbfnXKFNf9duMesmr4S8SXTJBJ9M4Yok08pu9vxdJwdlGRhVumk9mEhkEvKGifwA=="], - - "hast-util-is-element": ["hast-util-is-element@3.0.0", "", { "dependencies": { "@types/hast": "^3.0.0" } }, "sha512-Val9mnv2IWpLbNPqc/pUem+a7Ipj2aHacCwgNfTiK0vJKl0LF+4Ba4+v1oPHFpf3bLYmreq0/l3Gud9S5OH42g=="], - - "hast-util-parse-selector": ["hast-util-parse-selector@3.1.1", "", { "dependencies": { "@types/hast": "^2.0.0" } }, "sha512-jdlwBjEexy1oGz0aJ2f4GKMaVKkA9jwjr4MjAAI22E5fM/TXVZHuS5OpONtdeIkRKqAaryQ2E9xNQxijoThSZA=="], - - "hast-util-to-estree": ["hast-util-to-estree@3.1.0", "", { "dependencies": { "@types/estree": "^1.0.0", "@types/estree-jsx": "^1.0.0", "@types/hast": "^3.0.0", "comma-separated-tokens": "^2.0.0", "devlop": "^1.0.0", "estree-util-attach-comments": "^3.0.0", "estree-util-is-identifier-name": "^3.0.0", "hast-util-whitespace": "^3.0.0", "mdast-util-mdx-expression": "^2.0.0", "mdast-util-mdx-jsx": "^3.0.0", "mdast-util-mdxjs-esm": "^2.0.0", "property-information": "^6.0.0", "space-separated-tokens": "^2.0.0", "style-to-object": "^0.4.0", "unist-util-position": "^5.0.0", "zwitch": "^2.0.0" } }, "sha512-lfX5g6hqVh9kjS/B9E2gSkvHH4SZNiQFiqWS0x9fENzEl+8W12RqdRxX6d/Cwxi30tPQs3bIO+aolQJNp1bIyw=="], - - "hast-util-to-jsx-runtime": ["hast-util-to-jsx-runtime@2.3.0", "", { "dependencies": { "@types/estree": "^1.0.0", "@types/hast": "^3.0.0", "@types/unist": "^3.0.0", "comma-separated-tokens": "^2.0.0", "devlop": "^1.0.0", "estree-util-is-identifier-name": "^3.0.0", "hast-util-whitespace": "^3.0.0", "mdast-util-mdx-expression": "^2.0.0", "mdast-util-mdx-jsx": "^3.0.0", "mdast-util-mdxjs-esm": "^2.0.0", "property-information": "^6.0.0", "space-separated-tokens": "^2.0.0", "style-to-object": "^1.0.0", "unist-util-position": "^5.0.0", "vfile-message": "^4.0.0" } }, "sha512-H/y0+IWPdsLLS738P8tDnrQ8Z+dj12zQQ6WC11TIM21C8WFVoIxcqWXf2H3hiTVZjF1AWqoimGwrTWecWrnmRQ=="], - - "hast-util-to-string": ["hast-util-to-string@3.0.0", "", { "dependencies": { "@types/hast": "^3.0.0" } }, "sha512-OGkAxX1Ua3cbcW6EJ5pT/tslVb90uViVkcJ4ZZIMW/R33DX/AkcJcRrPebPwJkHYwlDHXz4aIwvAAaAdtrACFA=="], - - "hast-util-whitespace": ["hast-util-whitespace@3.0.0", "", { "dependencies": { "@types/hast": "^3.0.0" } }, "sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw=="], - - "hastscript": ["hastscript@7.2.0", "", { "dependencies": { "@types/hast": "^2.0.0", "comma-separated-tokens": "^2.0.0", "hast-util-parse-selector": "^3.0.0", "property-information": "^6.0.0", "space-separated-tokens": "^2.0.0" } }, "sha512-TtYPq24IldU8iKoJQqvZOuhi5CyCQRAbvDOX0x1eW6rsHSxa/1i2CCiptNTotGHJ3VoHRGmqiv6/D3q113ikkw=="], - - "hex-rgb": ["hex-rgb@4.3.0", "", {}, "sha512-Ox1pJVrDCyGHMG9CFg1tmrRUMRPRsAWYc/PinY0XzJU4K7y7vjNoLKIQ7BR5UJMCxNN8EM1MNDmHWA/B3aZUuw=="], - - "highlight.js": ["highlight.js@11.11.1", "", {}, "sha512-Xwwo44whKBVCYoliBQwaPvtd/2tYFkRQtXDWj1nackaV2JPXx3L0+Jvd8/qCJ2p+ML0/XVkJ2q+Mr+UVdpJK5w=="], - - "http-equiv-refresh": ["http-equiv-refresh@1.0.0", "", {}, "sha512-TScO04soylRN9i/QdOdgZyhydXg9z6XdaGzEyOgDKycePeDeTT4KvigjBcI+tgfTlieLWauGORMq5F1eIDa+1w=="], - - "humanize-duration": ["humanize-duration@3.32.1", "", {}, "sha512-inh5wue5XdfObhu/IGEMiA1nUXigSGcaKNemcbLRKa7jXYGDZXr3LoT9pTIzq2hPEbld7w/qv9h+ikWGz8fL1g=="], - - "ignore": ["ignore@5.3.1", "", {}, "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw=="], - - "import-fresh": ["import-fresh@3.3.1", "", { "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" } }, "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ=="], - - "imurmurhash": ["imurmurhash@0.1.4", "", {}, "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA=="], - - "inherits": ["inherits@2.0.4", "", {}, "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="], - - "inline-style-parser": ["inline-style-parser@0.1.1", "", {}, "sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q=="], - - "internal-slot": ["internal-slot@1.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "hasown": "^2.0.2", "side-channel": "^1.1.0" } }, "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw=="], - - "is-alphabetical": ["is-alphabetical@2.0.1", "", {}, "sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ=="], - - "is-alphanumerical": ["is-alphanumerical@2.0.1", "", { "dependencies": { "is-alphabetical": "^2.0.0", "is-decimal": "^2.0.0" } }, "sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw=="], - - "is-array-buffer": ["is-array-buffer@3.0.5", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.3", "get-intrinsic": "^1.2.6" } }, "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A=="], - - "is-arrayish": ["is-arrayish@0.3.2", "", {}, "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ=="], - - "is-async-function": ["is-async-function@2.1.1", "", { "dependencies": { "async-function": "^1.0.0", "call-bound": "^1.0.3", "get-proto": "^1.0.1", "has-tostringtag": "^1.0.2", "safe-regex-test": "^1.1.0" } }, "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ=="], - - "is-bigint": ["is-bigint@1.1.0", "", { "dependencies": { "has-bigints": "^1.0.2" } }, "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ=="], - - "is-binary-path": ["is-binary-path@2.1.0", "", { "dependencies": { "binary-extensions": "^2.0.0" } }, "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw=="], - - "is-boolean-object": ["is-boolean-object@1.2.2", "", { "dependencies": { "call-bound": "^1.0.3", "has-tostringtag": "^1.0.2" } }, "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A=="], - - "is-browser": ["is-browser@2.1.0", "", {}, "sha512-F5rTJxDQ2sW81fcfOR1GnCXT6sVJC104fCyfj+mjpwNEwaPYSn5fte5jiHmBg3DHsIoL/l8Kvw5VN5SsTRcRFQ=="], - - "is-bun-module": ["is-bun-module@2.0.0", "", { "dependencies": { "semver": "^7.7.1" } }, "sha512-gNCGbnnnnFAUGKeZ9PdbyeGYJqewpmc2aKHUEMO5nQPWU9lOmv7jcmQIv+qHD8fXW6W7qfuCwX4rY9LNRjXrkQ=="], - - "is-callable": ["is-callable@1.2.7", "", {}, "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA=="], - - "is-core-module": ["is-core-module@2.16.1", "", { "dependencies": { "hasown": "^2.0.2" } }, "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w=="], - - "is-data-view": ["is-data-view@1.0.2", "", { "dependencies": { "call-bound": "^1.0.2", "get-intrinsic": "^1.2.6", "is-typed-array": "^1.1.13" } }, "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw=="], - - "is-date-object": ["is-date-object@1.1.0", "", { "dependencies": { "call-bound": "^1.0.2", "has-tostringtag": "^1.0.2" } }, "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg=="], - - "is-decimal": ["is-decimal@2.0.1", "", {}, "sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A=="], - - "is-extendable": ["is-extendable@0.1.1", "", {}, "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw=="], - - "is-extglob": ["is-extglob@2.1.1", "", {}, "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ=="], - - "is-finalizationregistry": ["is-finalizationregistry@1.1.1", "", { "dependencies": { "call-bound": "^1.0.3" } }, "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg=="], - - "is-fullwidth-code-point": ["is-fullwidth-code-point@3.0.0", "", {}, "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="], - - "is-generator-function": ["is-generator-function@1.1.0", "", { "dependencies": { "call-bound": "^1.0.3", "get-proto": "^1.0.0", "has-tostringtag": "^1.0.2", "safe-regex-test": "^1.1.0" } }, "sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ=="], - - "is-glob": ["is-glob@4.0.3", "", { "dependencies": { "is-extglob": "^2.1.1" } }, "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg=="], - - "is-hexadecimal": ["is-hexadecimal@2.0.1", "", {}, "sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg=="], - - "is-map": ["is-map@2.0.3", "", {}, "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw=="], - - "is-negative-zero": ["is-negative-zero@2.0.3", "", {}, "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw=="], - - "is-number": ["is-number@7.0.0", "", {}, "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="], - - "is-number-object": ["is-number-object@1.1.1", "", { "dependencies": { "call-bound": "^1.0.3", "has-tostringtag": "^1.0.2" } }, "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw=="], - - "is-object": ["is-object@1.0.2", "", {}, "sha512-2rRIahhZr2UWb45fIOuvZGpFtz0TyOZLf32KxBbSoUCeZR495zCKlWUKKUByk3geS2eAs7ZAABt0Y/Rx0GiQGA=="], - - "is-plain-obj": ["is-plain-obj@4.1.0", "", {}, "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg=="], - - "is-reference": ["is-reference@3.0.2", "", { "dependencies": { "@types/estree": "*" } }, "sha512-v3rht/LgVcsdZa3O2Nqs+NMowLOxeOm7Ay9+/ARQ2F+qEoANRcqrjAZKGN0v8ymUetZGgkp26LTnGT7H0Qo9Pg=="], - - "is-regex": ["is-regex@1.2.1", "", { "dependencies": { "call-bound": "^1.0.2", "gopd": "^1.2.0", "has-tostringtag": "^1.0.2", "hasown": "^2.0.2" } }, "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g=="], - - "is-set": ["is-set@2.0.3", "", {}, "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg=="], - - "is-shared-array-buffer": ["is-shared-array-buffer@1.0.4", "", { "dependencies": { "call-bound": "^1.0.3" } }, "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A=="], - - "is-stream": ["is-stream@1.1.0", "", {}, "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ=="], - - "is-string": ["is-string@1.1.1", "", { "dependencies": { "call-bound": "^1.0.3", "has-tostringtag": "^1.0.2" } }, "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA=="], - - "is-symbol": ["is-symbol@1.1.1", "", { "dependencies": { "call-bound": "^1.0.2", "has-symbols": "^1.1.0", "safe-regex-test": "^1.1.0" } }, "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w=="], - - "is-typed-array": ["is-typed-array@1.1.15", "", { "dependencies": { "which-typed-array": "^1.1.16" } }, "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ=="], - - "is-weakmap": ["is-weakmap@2.0.2", "", {}, "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w=="], - - "is-weakref": ["is-weakref@1.1.1", "", { "dependencies": { "call-bound": "^1.0.3" } }, "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew=="], - - "is-weakset": ["is-weakset@2.0.4", "", { "dependencies": { "call-bound": "^1.0.3", "get-intrinsic": "^1.2.6" } }, "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ=="], - - "isarray": ["isarray@2.0.5", "", {}, "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw=="], - - "isbot": ["isbot@2.5.7", "", {}, "sha512-8P+oGrRDvuCpDdovK9oD4skHmSXu56bsK17K2ovXrkW7Ic4H9Y4AqnUUqlXqZxcqQ2358kid9Rb+fbLH5yeeUw=="], - - "isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="], - - "iterator.prototype": ["iterator.prototype@1.1.5", "", { "dependencies": { "define-data-property": "^1.1.4", "es-object-atoms": "^1.0.0", "get-intrinsic": "^1.2.6", "get-proto": "^1.0.0", "has-symbols": "^1.1.0", "set-function-name": "^2.0.2" } }, "sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g=="], - - "jackspeak": ["jackspeak@3.4.3", "", { "dependencies": { "@isaacs/cliui": "^8.0.2" }, "optionalDependencies": { "@pkgjs/parseargs": "^0.11.0" } }, "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw=="], - - "jiti": ["jiti@1.21.7", "", { "bin": "bin/jiti.js" }, "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A=="], - - "js-tokens": ["js-tokens@4.0.0", "", {}, "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="], - - "js-yaml": ["js-yaml@3.14.1", "", { "dependencies": { "argparse": "^1.0.7", "esprima": "^4.0.0" }, "bin": "bin/js-yaml.js" }, "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g=="], - - "json-buffer": ["json-buffer@3.0.1", "", {}, "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ=="], - - "json-schema-traverse": ["json-schema-traverse@0.4.1", "", {}, "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="], - - "json-stable-stringify-without-jsonify": ["json-stable-stringify-without-jsonify@1.0.1", "", {}, "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw=="], - - "json5": ["json5@1.0.2", "", { "dependencies": { "minimist": "^1.2.0" }, "bin": "lib/cli.js" }, "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA=="], - - "jsx-ast-utils": ["jsx-ast-utils@3.3.5", "", { "dependencies": { "array-includes": "^3.1.6", "array.prototype.flat": "^1.3.1", "object.assign": "^4.1.4", "object.values": "^1.1.6" } }, "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ=="], - - "keyv": ["keyv@4.5.4", "", { "dependencies": { "json-buffer": "3.0.1" } }, "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw=="], - - "kind-of": ["kind-of@6.0.3", "", {}, "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw=="], - - "language-subtag-registry": ["language-subtag-registry@0.3.23", "", {}, "sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ=="], - - "language-tags": ["language-tags@1.0.9", "", { "dependencies": { "language-subtag-registry": "^0.3.20" } }, "sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA=="], - - "levn": ["levn@0.4.1", "", { "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" } }, "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ=="], - - "lilconfig": ["lilconfig@3.1.3", "", {}, "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw=="], - - "limited-request-queue": ["limited-request-queue@2.0.0", "", { "dependencies": { "is-browser": "^2.0.1", "parse-domain": "~0.2.0" } }, "sha512-dZC4pHSV4jdvtZDandTZiVj+FogwII50wbDVeROhLXxme46J7wNUAMPPIm3x66KAZSoVAHy31muBN+H6pco1Eg=="], - - "linebreak": ["linebreak@1.1.0", "", { "dependencies": { "base64-js": "0.0.8", "unicode-trie": "^2.0.0" } }, "sha512-MHp03UImeVhB7XZtjd0E4n6+3xr5Dq/9xI/5FptGk5FrbDR3zagPa2DS6U8ks/3HjbKWG9Q1M2ufOzxV2qLYSQ=="], - - "lines-and-columns": ["lines-and-columns@1.2.4", "", {}, "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg=="], - - "link-types": ["link-types@1.1.0", "", {}, "sha512-6R1evfF/YPACIF01Lb2Dm0v2GZbJo06+wX5v1TByKt2drvkI2A2LlOgAOG1T/rxTlGEO4rdOlSrQabxmy7tfNg=="], - - "locate-path": ["locate-path@6.0.0", "", { "dependencies": { "p-locate": "^5.0.0" } }, "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw=="], - - "lodash.castarray": ["lodash.castarray@4.4.0", "", {}, "sha512-aVx8ztPv7/2ULbArGJ2Y42bG1mEQ5mGjpdvrbJcJFU3TbYybe+QlLS4pst9zV52ymy2in1KpFPiZnAOATxD4+Q=="], - - "lodash.clonedeep": ["lodash.clonedeep@4.5.0", "", {}, "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ=="], - - "lodash.isplainobject": ["lodash.isplainobject@4.0.6", "", {}, "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA=="], - - "lodash.merge": ["lodash.merge@4.6.2", "", {}, "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ=="], - - "longest-streak": ["longest-streak@3.1.0", "", {}, "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g=="], - - "loose-envify": ["loose-envify@1.4.0", "", { "dependencies": { "js-tokens": "^3.0.0 || ^4.0.0" }, "bin": "cli.js" }, "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q=="], - - "lru-cache": ["lru-cache@4.1.5", "", { "dependencies": { "pseudomap": "^1.0.2", "yallist": "^2.1.2" } }, "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g=="], - - "lucide-react": ["lucide-react@0.537.0", "", { "peerDependencies": { "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-VxWsdxBGeFnlC+HwMg/l08HptN4YRU9o/lRog156jOmRxI1ERKqN+rJiNY/mPcKAdWdM0UbyO8ft1o0jq69SSQ=="], - - "lunr": ["lunr@2.3.9", "", {}, "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow=="], - - "make-error": ["make-error@1.3.6", "", {}, "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw=="], - - "markdown-extensions": ["markdown-extensions@2.0.0", "", {}, "sha512-o5vL7aDWatOTX8LzaS1WMoaoxIiLRQJuIKKe2wAw6IeULDHaqbiqiggmx+pKvZDb1Sj+pE46Sn1T7lCqfFtg1Q=="], - - "markdown-table": ["markdown-table@3.0.3", "", {}, "sha512-Z1NL3Tb1M9wH4XESsCDEksWoKTdlUafKc4pt0GRwjUyXaCFZ+dc3g2erqB6zm3szA2IUSi7VnPI+o/9jnxh9hw=="], - - "math-intrinsics": ["math-intrinsics@1.1.0", "", {}, "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g=="], - - "maybe-callback": ["maybe-callback@2.1.0", "", {}, "sha512-P8CekEs8v3zn0bM/tXgfL0UkBXO//BAQkoAmn8s+eFmH451+7wBWY2aKEmyItoZUcbpaI2OCcM6tcuIil/n5mA=="], - - "mdast-util-find-and-replace": ["mdast-util-find-and-replace@3.0.1", "", { "dependencies": { "@types/mdast": "^4.0.0", "escape-string-regexp": "^5.0.0", "unist-util-is": "^6.0.0", "unist-util-visit-parents": "^6.0.0" } }, "sha512-SG21kZHGC3XRTSUhtofZkBzZTJNM5ecCi0SK2IMKmSXR8vO3peL+kb1O0z7Zl83jKtutG4k5Wv/W7V3/YHvzPA=="], - - "mdast-util-from-markdown": ["mdast-util-from-markdown@2.0.1", "", { "dependencies": { "@types/mdast": "^4.0.0", "@types/unist": "^3.0.0", "decode-named-character-reference": "^1.0.0", "devlop": "^1.0.0", "mdast-util-to-string": "^4.0.0", "micromark": "^4.0.0", "micromark-util-decode-numeric-character-reference": "^2.0.0", "micromark-util-decode-string": "^2.0.0", "micromark-util-normalize-identifier": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0", "unist-util-stringify-position": "^4.0.0" } }, "sha512-aJEUyzZ6TzlsX2s5B4Of7lN7EQtAxvtradMMglCQDyaTFgse6CmtmdJ15ElnVRlCg1vpNyVtbem0PWzlNieZsA=="], - - "mdast-util-gfm": ["mdast-util-gfm@3.0.0", "", { "dependencies": { "mdast-util-from-markdown": "^2.0.0", "mdast-util-gfm-autolink-literal": "^2.0.0", "mdast-util-gfm-footnote": "^2.0.0", "mdast-util-gfm-strikethrough": "^2.0.0", "mdast-util-gfm-table": "^2.0.0", "mdast-util-gfm-task-list-item": "^2.0.0", "mdast-util-to-markdown": "^2.0.0" } }, "sha512-dgQEX5Amaq+DuUqf26jJqSK9qgixgd6rYDHAv4aTBuA92cTknZlKpPfa86Z/s8Dj8xsAQpFfBmPUHWJBWqS4Bw=="], - - "mdast-util-gfm-autolink-literal": ["mdast-util-gfm-autolink-literal@2.0.0", "", { "dependencies": { "@types/mdast": "^4.0.0", "ccount": "^2.0.0", "devlop": "^1.0.0", "mdast-util-find-and-replace": "^3.0.0", "micromark-util-character": "^2.0.0" } }, "sha512-FyzMsduZZHSc3i0Px3PQcBT4WJY/X/RCtEJKuybiC6sjPqLv7h1yqAkmILZtuxMSsUyaLUWNp71+vQH2zqp5cg=="], - - "mdast-util-gfm-footnote": ["mdast-util-gfm-footnote@2.0.0", "", { "dependencies": { "@types/mdast": "^4.0.0", "devlop": "^1.1.0", "mdast-util-from-markdown": "^2.0.0", "mdast-util-to-markdown": "^2.0.0", "micromark-util-normalize-identifier": "^2.0.0" } }, "sha512-5jOT2boTSVkMnQ7LTrd6n/18kqwjmuYqo7JUPe+tRCY6O7dAuTFMtTPauYYrMPpox9hlN0uOx/FL8XvEfG9/mQ=="], - - "mdast-util-gfm-strikethrough": ["mdast-util-gfm-strikethrough@2.0.0", "", { "dependencies": { "@types/mdast": "^4.0.0", "mdast-util-from-markdown": "^2.0.0", "mdast-util-to-markdown": "^2.0.0" } }, "sha512-mKKb915TF+OC5ptj5bJ7WFRPdYtuHv0yTRxK2tJvi+BDqbkiG7h7u/9SI89nRAYcmap2xHQL9D+QG/6wSrTtXg=="], - - "mdast-util-gfm-table": ["mdast-util-gfm-table@2.0.0", "", { "dependencies": { "@types/mdast": "^4.0.0", "devlop": "^1.0.0", "markdown-table": "^3.0.0", "mdast-util-from-markdown": "^2.0.0", "mdast-util-to-markdown": "^2.0.0" } }, "sha512-78UEvebzz/rJIxLvE7ZtDd/vIQ0RHv+3Mh5DR96p7cS7HsBhYIICDBCu8csTNWNO6tBWfqXPWekRuj2FNOGOZg=="], - - "mdast-util-gfm-task-list-item": ["mdast-util-gfm-task-list-item@2.0.0", "", { "dependencies": { "@types/mdast": "^4.0.0", "devlop": "^1.0.0", "mdast-util-from-markdown": "^2.0.0", "mdast-util-to-markdown": "^2.0.0" } }, "sha512-IrtvNvjxC1o06taBAVJznEnkiHxLFTzgonUdy8hzFVeDun0uTjxxrRGVaNFqkU1wJR3RBPEfsxmU6jDWPofrTQ=="], - - "mdast-util-mdx": ["mdast-util-mdx@3.0.0", "", { "dependencies": { "mdast-util-from-markdown": "^2.0.0", "mdast-util-mdx-expression": "^2.0.0", "mdast-util-mdx-jsx": "^3.0.0", "mdast-util-mdxjs-esm": "^2.0.0", "mdast-util-to-markdown": "^2.0.0" } }, "sha512-JfbYLAW7XnYTTbUsmpu0kdBUVe+yKVJZBItEjwyYJiDJuZ9w4eeaqks4HQO+R7objWgS2ymV60GYpI14Ug554w=="], - - "mdast-util-mdx-expression": ["mdast-util-mdx-expression@2.0.0", "", { "dependencies": { "@types/estree-jsx": "^1.0.0", "@types/hast": "^3.0.0", "@types/mdast": "^4.0.0", "devlop": "^1.0.0", "mdast-util-from-markdown": "^2.0.0", "mdast-util-to-markdown": "^2.0.0" } }, "sha512-fGCu8eWdKUKNu5mohVGkhBXCXGnOTLuFqOvGMvdikr+J1w7lDJgxThOKpwRWzzbyXAU2hhSwsmssOY4yTokluw=="], - - "mdast-util-mdx-jsx": ["mdast-util-mdx-jsx@3.1.2", "", { "dependencies": { "@types/estree-jsx": "^1.0.0", "@types/hast": "^3.0.0", "@types/mdast": "^4.0.0", "@types/unist": "^3.0.0", "ccount": "^2.0.0", "devlop": "^1.1.0", "mdast-util-from-markdown": "^2.0.0", "mdast-util-to-markdown": "^2.0.0", "parse-entities": "^4.0.0", "stringify-entities": "^4.0.0", "unist-util-remove-position": "^5.0.0", "unist-util-stringify-position": "^4.0.0", "vfile-message": "^4.0.0" } }, "sha512-eKMQDeywY2wlHc97k5eD8VC+9ASMjN8ItEZQNGwJ6E0XWKiW/Z0V5/H8pvoXUf+y+Mj0VIgeRRbujBmFn4FTyA=="], - - "mdast-util-mdxjs-esm": ["mdast-util-mdxjs-esm@2.0.1", "", { "dependencies": { "@types/estree-jsx": "^1.0.0", "@types/hast": "^3.0.0", "@types/mdast": "^4.0.0", "devlop": "^1.0.0", "mdast-util-from-markdown": "^2.0.0", "mdast-util-to-markdown": "^2.0.0" } }, "sha512-EcmOpxsZ96CvlP03NghtH1EsLtr0n9Tm4lPUJUBccV9RwUOneqSycg19n5HGzCf+10LozMRSObtVr3ee1WoHtg=="], - - "mdast-util-phrasing": ["mdast-util-phrasing@4.1.0", "", { "dependencies": { "@types/mdast": "^4.0.0", "unist-util-is": "^6.0.0" } }, "sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w=="], - - "mdast-util-to-hast": ["mdast-util-to-hast@13.2.0", "", { "dependencies": { "@types/hast": "^3.0.0", "@types/mdast": "^4.0.0", "@ungap/structured-clone": "^1.0.0", "devlop": "^1.0.0", "micromark-util-sanitize-uri": "^2.0.0", "trim-lines": "^3.0.0", "unist-util-position": "^5.0.0", "unist-util-visit": "^5.0.0", "vfile": "^6.0.0" } }, "sha512-QGYKEuUsYT9ykKBCMOEDLsU5JRObWQusAolFMeko/tYPufNkRffBAQjIE+99jbA87xv6FgmjLtwjh9wBWajwAA=="], - - "mdast-util-to-markdown": ["mdast-util-to-markdown@2.1.0", "", { "dependencies": { "@types/mdast": "^4.0.0", "@types/unist": "^3.0.0", "longest-streak": "^3.0.0", "mdast-util-phrasing": "^4.0.0", "mdast-util-to-string": "^4.0.0", "micromark-util-decode-string": "^2.0.0", "unist-util-visit": "^5.0.0", "zwitch": "^2.0.0" } }, "sha512-SR2VnIEdVNCJbP6y7kVTJgPLifdr8WEU440fQec7qHoHOUz/oJ2jmNRqdDQ3rbiStOXb2mCDGTuwsK5OPUgYlQ=="], - - "mdast-util-to-string": ["mdast-util-to-string@4.0.0", "", { "dependencies": { "@types/mdast": "^4.0.0" } }, "sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg=="], - - "merge2": ["merge2@1.4.1", "", {}, "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg=="], - - "micromark": ["micromark@4.0.0", "", { "dependencies": { "@types/debug": "^4.0.0", "debug": "^4.0.0", "decode-named-character-reference": "^1.0.0", "devlop": "^1.0.0", "micromark-core-commonmark": "^2.0.0", "micromark-factory-space": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-chunked": "^2.0.0", "micromark-util-combine-extensions": "^2.0.0", "micromark-util-decode-numeric-character-reference": "^2.0.0", "micromark-util-encode": "^2.0.0", "micromark-util-normalize-identifier": "^2.0.0", "micromark-util-resolve-all": "^2.0.0", "micromark-util-sanitize-uri": "^2.0.0", "micromark-util-subtokenize": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-o/sd0nMof8kYff+TqcDx3VSrgBTcZpSvYcAHIfHhv5VAuNmisCxjhx6YmxS8PFEpb9z5WKWKPdzf0jM23ro3RQ=="], - - "micromark-core-commonmark": ["micromark-core-commonmark@2.0.1", "", { "dependencies": { "decode-named-character-reference": "^1.0.0", "devlop": "^1.0.0", "micromark-factory-destination": "^2.0.0", "micromark-factory-label": "^2.0.0", "micromark-factory-space": "^2.0.0", "micromark-factory-title": "^2.0.0", "micromark-factory-whitespace": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-chunked": "^2.0.0", "micromark-util-classify-character": "^2.0.0", "micromark-util-html-tag-name": "^2.0.0", "micromark-util-normalize-identifier": "^2.0.0", "micromark-util-resolve-all": "^2.0.0", "micromark-util-subtokenize": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-CUQyKr1e///ZODyD1U3xit6zXwy1a8q2a1S1HKtIlmgvurrEpaw/Y9y6KSIbF8P59cn/NjzHyO+Q2fAyYLQrAA=="], - - "micromark-extension-gfm": ["micromark-extension-gfm@3.0.0", "", { "dependencies": { "micromark-extension-gfm-autolink-literal": "^2.0.0", "micromark-extension-gfm-footnote": "^2.0.0", "micromark-extension-gfm-strikethrough": "^2.0.0", "micromark-extension-gfm-table": "^2.0.0", "micromark-extension-gfm-tagfilter": "^2.0.0", "micromark-extension-gfm-task-list-item": "^2.0.0", "micromark-util-combine-extensions": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w=="], - - "micromark-extension-gfm-autolink-literal": ["micromark-extension-gfm-autolink-literal@2.0.0", "", { "dependencies": { "micromark-util-character": "^2.0.0", "micromark-util-sanitize-uri": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-rTHfnpt/Q7dEAK1Y5ii0W8bhfJlVJFnJMHIPisfPK3gpVNuOP0VnRl96+YJ3RYWV/P4gFeQoGKNlT3RhuvpqAg=="], - - "micromark-extension-gfm-footnote": ["micromark-extension-gfm-footnote@2.0.0", "", { "dependencies": { "devlop": "^1.0.0", "micromark-core-commonmark": "^2.0.0", "micromark-factory-space": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-normalize-identifier": "^2.0.0", "micromark-util-sanitize-uri": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-6Rzu0CYRKDv3BfLAUnZsSlzx3ak6HAoI85KTiijuKIz5UxZxbUI+pD6oHgw+6UtQuiRwnGRhzMmPRv4smcz0fg=="], - - "micromark-extension-gfm-strikethrough": ["micromark-extension-gfm-strikethrough@2.0.0", "", { "dependencies": { "devlop": "^1.0.0", "micromark-util-chunked": "^2.0.0", "micromark-util-classify-character": "^2.0.0", "micromark-util-resolve-all": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-c3BR1ClMp5fxxmwP6AoOY2fXO9U8uFMKs4ADD66ahLTNcwzSCyRVU4k7LPV5Nxo/VJiR4TdzxRQY2v3qIUceCw=="], - - "micromark-extension-gfm-table": ["micromark-extension-gfm-table@2.0.0", "", { "dependencies": { "devlop": "^1.0.0", "micromark-factory-space": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-PoHlhypg1ItIucOaHmKE8fbin3vTLpDOUg8KAr8gRCF1MOZI9Nquq2i/44wFvviM4WuxJzc3demT8Y3dkfvYrw=="], - - "micromark-extension-gfm-tagfilter": ["micromark-extension-gfm-tagfilter@2.0.0", "", { "dependencies": { "micromark-util-types": "^2.0.0" } }, "sha512-xHlTOmuCSotIA8TW1mDIM6X2O1SiX5P9IuDtqGonFhEK0qgRI4yeC6vMxEV2dgyr2TiD+2PQ10o+cOhdVAcwfg=="], - - "micromark-extension-gfm-task-list-item": ["micromark-extension-gfm-task-list-item@2.0.1", "", { "dependencies": { "devlop": "^1.0.0", "micromark-factory-space": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-cY5PzGcnULaN5O7T+cOzfMoHjBW7j+T9D2sucA5d/KbsBTPcYdebm9zUd9zzdgJGCwahV+/W78Z3nbulBYVbTw=="], - - "micromark-extension-mdx-expression": ["micromark-extension-mdx-expression@3.0.0", "", { "dependencies": { "@types/estree": "^1.0.0", "devlop": "^1.0.0", "micromark-factory-mdx-expression": "^2.0.0", "micromark-factory-space": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-events-to-acorn": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-sI0nwhUDz97xyzqJAbHQhp5TfaxEvZZZ2JDqUo+7NvyIYG6BZ5CPPqj2ogUoPJlmXHBnyZUzISg9+oUmU6tUjQ=="], - - "micromark-extension-mdx-jsx": ["micromark-extension-mdx-jsx@3.0.0", "", { "dependencies": { "@types/acorn": "^4.0.0", "@types/estree": "^1.0.0", "devlop": "^1.0.0", "estree-util-is-identifier-name": "^3.0.0", "micromark-factory-mdx-expression": "^2.0.0", "micromark-factory-space": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0", "vfile-message": "^4.0.0" } }, "sha512-uvhhss8OGuzR4/N17L1JwvmJIpPhAd8oByMawEKx6NVdBCbesjH4t+vjEp3ZXft9DwvlKSD07fCeI44/N0Vf2w=="], - - "micromark-extension-mdx-md": ["micromark-extension-mdx-md@2.0.0", "", { "dependencies": { "micromark-util-types": "^2.0.0" } }, "sha512-EpAiszsB3blw4Rpba7xTOUptcFeBFi+6PY8VnJ2hhimH+vCQDirWgsMpz7w1XcZE7LVrSAUGb9VJpG9ghlYvYQ=="], - - "micromark-extension-mdxjs": ["micromark-extension-mdxjs@3.0.0", "", { "dependencies": { "acorn": "^8.0.0", "acorn-jsx": "^5.0.0", "micromark-extension-mdx-expression": "^3.0.0", "micromark-extension-mdx-jsx": "^3.0.0", "micromark-extension-mdx-md": "^2.0.0", "micromark-extension-mdxjs-esm": "^3.0.0", "micromark-util-combine-extensions": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-A873fJfhnJ2siZyUrJ31l34Uqwy4xIFmvPY1oj+Ean5PHcPBYzEsvqvWGaWcfEIr11O5Dlw3p2y0tZWpKHDejQ=="], - - "micromark-extension-mdxjs-esm": ["micromark-extension-mdxjs-esm@3.0.0", "", { "dependencies": { "@types/estree": "^1.0.0", "devlop": "^1.0.0", "micromark-core-commonmark": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-events-to-acorn": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0", "unist-util-position-from-estree": "^2.0.0", "vfile-message": "^4.0.0" } }, "sha512-DJFl4ZqkErRpq/dAPyeWp15tGrcrrJho1hKK5uBS70BCtfrIFg81sqcTVu3Ta+KD1Tk5vAtBNElWxtAa+m8K9A=="], - - "micromark-factory-destination": ["micromark-factory-destination@2.0.0", "", { "dependencies": { "micromark-util-character": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-j9DGrQLm/Uhl2tCzcbLhy5kXsgkHUrjJHg4fFAeoMRwJmJerT9aw4FEhIbZStWN8A3qMwOp1uzHr4UL8AInxtA=="], - - "micromark-factory-label": ["micromark-factory-label@2.0.0", "", { "dependencies": { "devlop": "^1.0.0", "micromark-util-character": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-RR3i96ohZGde//4WSe/dJsxOX6vxIg9TimLAS3i4EhBAFx8Sm5SmqVfR8E87DPSR31nEAjZfbt91OMZWcNgdZw=="], - - "micromark-factory-mdx-expression": ["micromark-factory-mdx-expression@2.0.1", "", { "dependencies": { "@types/estree": "^1.0.0", "devlop": "^1.0.0", "micromark-util-character": "^2.0.0", "micromark-util-events-to-acorn": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0", "unist-util-position-from-estree": "^2.0.0", "vfile-message": "^4.0.0" } }, "sha512-F0ccWIUHRLRrYp5TC9ZYXmZo+p2AM13ggbsW4T0b5CRKP8KHVRB8t4pwtBgTxtjRmwrK0Irwm7vs2JOZabHZfg=="], - - "micromark-factory-space": ["micromark-factory-space@2.0.0", "", { "dependencies": { "micromark-util-character": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-TKr+LIDX2pkBJXFLzpyPyljzYK3MtmllMUMODTQJIUfDGncESaqB90db9IAUcz4AZAJFdd8U9zOp9ty1458rxg=="], - - "micromark-factory-title": ["micromark-factory-title@2.0.0", "", { "dependencies": { "micromark-factory-space": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-jY8CSxmpWLOxS+t8W+FG3Xigc0RDQA9bKMY/EwILvsesiRniiVMejYTE4wumNc2f4UbAa4WsHqe3J1QS1sli+A=="], - - "micromark-factory-whitespace": ["micromark-factory-whitespace@2.0.0", "", { "dependencies": { "micromark-factory-space": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-28kbwaBjc5yAI1XadbdPYHX/eDnqaUFVikLwrO7FDnKG7lpgxnvk/XGRhX/PN0mOZ+dBSZ+LgunHS+6tYQAzhA=="], - - "micromark-util-character": ["micromark-util-character@2.1.0", "", { "dependencies": { "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ=="], - - "micromark-util-chunked": ["micromark-util-chunked@2.0.0", "", { "dependencies": { "micromark-util-symbol": "^2.0.0" } }, "sha512-anK8SWmNphkXdaKgz5hJvGa7l00qmcaUQoMYsBwDlSKFKjc6gjGXPDw3FNL3Nbwq5L8gE+RCbGqTw49FK5Qyvg=="], - - "micromark-util-classify-character": ["micromark-util-classify-character@2.0.0", "", { "dependencies": { "micromark-util-character": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-S0ze2R9GH+fu41FA7pbSqNWObo/kzwf8rN/+IGlW/4tC6oACOs8B++bh+i9bVyNnwCcuksbFwsBme5OCKXCwIw=="], - - "micromark-util-combine-extensions": ["micromark-util-combine-extensions@2.0.0", "", { "dependencies": { "micromark-util-chunked": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-vZZio48k7ON0fVS3CUgFatWHoKbbLTK/rT7pzpJ4Bjp5JjkZeasRfrS9wsBdDJK2cJLHMckXZdzPSSr1B8a4oQ=="], - - "micromark-util-decode-numeric-character-reference": ["micromark-util-decode-numeric-character-reference@2.0.1", "", { "dependencies": { "micromark-util-symbol": "^2.0.0" } }, "sha512-bmkNc7z8Wn6kgjZmVHOX3SowGmVdhYS7yBpMnuMnPzDq/6xwVA604DuOXMZTO1lvq01g+Adfa0pE2UKGlxL1XQ=="], - - "micromark-util-decode-string": ["micromark-util-decode-string@2.0.0", "", { "dependencies": { "decode-named-character-reference": "^1.0.0", "micromark-util-character": "^2.0.0", "micromark-util-decode-numeric-character-reference": "^2.0.0", "micromark-util-symbol": "^2.0.0" } }, "sha512-r4Sc6leeUTn3P6gk20aFMj2ntPwn6qpDZqWvYmAG6NgvFTIlj4WtrAudLi65qYoaGdXYViXYw2pkmn7QnIFasA=="], - - "micromark-util-encode": ["micromark-util-encode@2.0.0", "", {}, "sha512-pS+ROfCXAGLWCOc8egcBvT0kf27GoWMqtdarNfDcjb6YLuV5cM3ioG45Ys2qOVqeqSbjaKg72vU+Wby3eddPsA=="], - - "micromark-util-events-to-acorn": ["micromark-util-events-to-acorn@2.0.2", "", { "dependencies": { "@types/acorn": "^4.0.0", "@types/estree": "^1.0.0", "@types/unist": "^3.0.0", "devlop": "^1.0.0", "estree-util-visit": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0", "vfile-message": "^4.0.0" } }, "sha512-Fk+xmBrOv9QZnEDguL9OI9/NQQp6Hz4FuQ4YmCb/5V7+9eAh1s6AYSvL20kHkD67YIg7EpE54TiSlcsf3vyZgA=="], - - "micromark-util-html-tag-name": ["micromark-util-html-tag-name@2.0.0", "", {}, "sha512-xNn4Pqkj2puRhKdKTm8t1YHC/BAjx6CEwRFXntTaRf/x16aqka6ouVoutm+QdkISTlT7e2zU7U4ZdlDLJd2Mcw=="], - - "micromark-util-normalize-identifier": ["micromark-util-normalize-identifier@2.0.0", "", { "dependencies": { "micromark-util-symbol": "^2.0.0" } }, "sha512-2xhYT0sfo85FMrUPtHcPo2rrp1lwbDEEzpx7jiH2xXJLqBuy4H0GgXk5ToU8IEwoROtXuL8ND0ttVa4rNqYK3w=="], - - "micromark-util-resolve-all": ["micromark-util-resolve-all@2.0.0", "", { "dependencies": { "micromark-util-types": "^2.0.0" } }, "sha512-6KU6qO7DZ7GJkaCgwBNtplXCvGkJToU86ybBAUdavvgsCiG8lSSvYxr9MhwmQ+udpzywHsl4RpGJsYWG1pDOcA=="], - - "micromark-util-sanitize-uri": ["micromark-util-sanitize-uri@2.0.0", "", { "dependencies": { "micromark-util-character": "^2.0.0", "micromark-util-encode": "^2.0.0", "micromark-util-symbol": "^2.0.0" } }, "sha512-WhYv5UEcZrbAtlsnPuChHUAsu/iBPOVaEVsntLBIdpibO0ddy8OzavZz3iL2xVvBZOpolujSliP65Kq0/7KIYw=="], - - "micromark-util-subtokenize": ["micromark-util-subtokenize@2.0.1", "", { "dependencies": { "devlop": "^1.0.0", "micromark-util-chunked": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-jZNtiFl/1aY73yS3UGQkutD0UbhTt68qnRpw2Pifmz5wV9h8gOVsN70v+Lq/f1rKaU/W8pxRe8y8Q9FX1AOe1Q=="], - - "micromark-util-symbol": ["micromark-util-symbol@2.0.0", "", {}, "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw=="], - - "micromark-util-types": ["micromark-util-types@2.0.0", "", {}, "sha512-oNh6S2WMHWRZrmutsRmDDfkzKtxF+bc2VxLC9dvtrDIRFln627VsFP6fLMgTryGDljgLPjkrzQSDcPrjPyDJ5w=="], - - "micromatch": ["micromatch@4.0.8", "", { "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" } }, "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA=="], - - "mime": ["mime@1.6.0", "", { "bin": "cli.js" }, "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg=="], - - "minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="], - - "minimist": ["minimist@1.2.8", "", {}, "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA=="], - - "minipass": ["minipass@7.1.2", "", {}, "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw=="], - - "ms": ["ms@2.1.2", "", {}, "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="], - - "mz": ["mz@2.7.0", "", { "dependencies": { "any-promise": "^1.0.0", "object-assign": "^4.0.1", "thenify-all": "^1.0.0" } }, "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q=="], - - "nanoid": ["nanoid@3.3.11", "", { "bin": "bin/nanoid.cjs" }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="], - - "napi-postinstall": ["napi-postinstall@0.3.2", "", { "bin": "lib/cli.js" }, "sha512-tWVJxJHmBWLy69PvO96TZMZDrzmw5KeiZBz3RHmiM2XZ9grBJ2WgMAFVVg25nqp3ZjTFUs2Ftw1JhscL3Teliw=="], - - "natural-compare": ["natural-compare@1.4.0", "", {}, "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw=="], - - "next": ["next@15.4.6", "", { "dependencies": { "@next/env": "15.4.6", "@swc/helpers": "0.5.15", "caniuse-lite": "^1.0.30001579", "postcss": "8.4.31", "styled-jsx": "5.1.6" }, "optionalDependencies": { "@next/swc-darwin-arm64": "15.4.6", "@next/swc-darwin-x64": "15.4.6", "@next/swc-linux-arm64-gnu": "15.4.6", "@next/swc-linux-arm64-musl": "15.4.6", "@next/swc-linux-x64-gnu": "15.4.6", "@next/swc-linux-x64-musl": "15.4.6", "@next/swc-win32-arm64-msvc": "15.4.6", "@next/swc-win32-x64-msvc": "15.4.6", "sharp": "^0.34.3" }, "peerDependencies": { "@opentelemetry/api": "^1.1.0", "@playwright/test": "^1.51.1", "babel-plugin-react-compiler": "*", "react": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", "react-dom": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", "sass": "^1.3.0" }, "optionalPeers": ["@opentelemetry/api", "@playwright/test", "babel-plugin-react-compiler", "sass"], "bin": "dist/bin/next" }, "sha512-us++E/Q80/8+UekzB3SAGs71AlLDsadpFMXVNM/uQ0BMwsh9m3mr0UNQIfjKed8vpWXsASe+Qifrnu1oLIcKEQ=="], - - "next-mdx-remote": ["next-mdx-remote@5.0.0", "", { "dependencies": { "@babel/code-frame": "^7.23.5", "@mdx-js/mdx": "^3.0.1", "@mdx-js/react": "^3.0.1", "unist-util-remove": "^3.1.0", "vfile": "^6.0.1", "vfile-matter": "^5.0.0" }, "peerDependencies": { "react": ">=16" } }, "sha512-RNNbqRpK9/dcIFZs/esQhuLA8jANqlH694yqoDBK8hkVdJUndzzGmnPHa2nyi90N4Z9VmzuSWNRpr5ItT3M7xQ=="], - - "next-themes": ["next-themes@0.4.6", "", { "peerDependencies": { "react": "^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc", "react-dom": "^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc" } }, "sha512-pZvgD5L0IEvX5/9GWyHMf3m8BKiVQwsCMHfoFosXtXBMnaS0ZnIJ9ST4b4NqLVKDEm8QBxoNNGNaBv2JNF6XNA=="], - - "node-releases": ["node-releases@2.0.19", "", {}, "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw=="], - - "nopt": ["nopt@3.0.6", "", { "dependencies": { "abbrev": "1" }, "bin": "bin/nopt.js" }, "sha512-4GUt3kSEYmk4ITxzB/b9vaIDfUVWN/Ml1Fwl11IlnIG2iaJ9O6WXZ9SrYM9NLI8OCBieN2Y8SWC2oJV0RQ7qYg=="], - - "nopter": ["nopter@0.3.0", "", { "dependencies": { "caller-path": "~0.1.0", "camelcase": "^1.0.2", "chalk": "~0.5.1", "cli-table": "~0.3.1", "eol": "~0.2.0", "nopt": "^3.0.1", "object-assign": "^2.0.0", "splitargs": "~0.0.3" } }, "sha512-gSYCd2Gxge0Ovnszf8fI9WkN7/PiuTTIpbeo2VhyQ3+NwJ7z3x6jiOFAMuU65JZz+BK/I1uzae2neQVGFHMClQ=="], - - "normalize-path": ["normalize-path@3.0.0", "", {}, "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA=="], - - "normalize-range": ["normalize-range@0.1.2", "", {}, "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA=="], - - "object-assign": ["object-assign@2.1.1", "", {}, "sha512-CdsOUYIh5wIiozhJ3rLQgmUTgcyzFwZZrqhkKhODMoGtPKM+wt0h0CNIoauJWMsS9822EdzPsF/6mb4nLvPN5g=="], - - "object-hash": ["object-hash@3.0.0", "", {}, "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw=="], - - "object-inspect": ["object-inspect@1.13.4", "", {}, "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew=="], - - "object-keys": ["object-keys@1.1.1", "", {}, "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA=="], - - "object.assign": ["object.assign@4.1.7", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.3", "define-properties": "^1.2.1", "es-object-atoms": "^1.0.0", "has-symbols": "^1.1.0", "object-keys": "^1.1.1" } }, "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw=="], - - "object.entries": ["object.entries@1.1.9", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.4", "define-properties": "^1.2.1", "es-object-atoms": "^1.1.1" } }, "sha512-8u/hfXFRBD1O0hPUjioLhoWFHRmt6tKA4/vZPyckBr18l1KE9uHrFaFaUi8MDRTpi4uak2goyPTSNJLXX2k2Hw=="], - - "object.fromentries": ["object.fromentries@2.0.8", "", { "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", "es-abstract": "^1.23.2", "es-object-atoms": "^1.0.0" } }, "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ=="], - - "object.groupby": ["object.groupby@1.0.3", "", { "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", "es-abstract": "^1.23.2" } }, "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ=="], - - "object.values": ["object.values@1.2.1", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.3", "define-properties": "^1.2.1", "es-object-atoms": "^1.0.0" } }, "sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA=="], - - "optionator": ["optionator@0.9.3", "", { "dependencies": { "@aashutoshrathi/word-wrap": "^1.2.3", "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", "levn": "^0.4.1", "prelude-ls": "^1.2.1", "type-check": "^0.4.0" } }, "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg=="], - - "os-name": ["os-name@1.0.3", "", { "dependencies": { "osx-release": "^1.0.0", "win-release": "^1.0.0" }, "bin": "cli.js" }, "sha512-f5estLO2KN8vgtTRaILIgEGBoBrMnZ3JQ7W9TMZCnOIGwHe8TRGSpcagnWDo+Dfhd/z08k9Xe75hvciJJ8Qaew=="], - - "os-tmpdir": ["os-tmpdir@1.0.2", "", {}, "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g=="], - - "osx-release": ["osx-release@1.1.0", "", { "dependencies": { "minimist": "^1.1.0" }, "bin": "cli.js" }, "sha512-ixCMMwnVxyHFQLQnINhmIpWqXIfS2YOXchwQrk+OFzmo6nDjQ0E4KXAyyUh0T0MZgV4bUhkRrAbVqlE4yLVq4A=="], - - "own-keys": ["own-keys@1.0.1", "", { "dependencies": { "get-intrinsic": "^1.2.6", "object-keys": "^1.1.1", "safe-push-apply": "^1.0.0" } }, "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg=="], - - "p-limit": ["p-limit@3.1.0", "", { "dependencies": { "yocto-queue": "^0.1.0" } }, "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ=="], - - "p-locate": ["p-locate@5.0.0", "", { "dependencies": { "p-limit": "^3.0.2" } }, "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw=="], - - "package-json-from-dist": ["package-json-from-dist@1.0.1", "", {}, "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw=="], - - "pako": ["pako@0.2.9", "", {}, "sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA=="], - - "parent-module": ["parent-module@1.0.1", "", { "dependencies": { "callsites": "^3.0.0" } }, "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g=="], - - "parse-css-color": ["parse-css-color@0.2.1", "", { "dependencies": { "color-name": "^1.1.4", "hex-rgb": "^4.1.0" } }, "sha512-bwS/GGIFV3b6KS4uwpzCFj4w297Yl3uqnSgIPsoQkx7GMLROXfMnWvxfNkL0oh8HVhZA4hvJoEoEIqonfJ3BWg=="], - - "parse-domain": ["parse-domain@0.2.2", "", {}, "sha512-AtlCTd18kw7oMd4MBTOqW+tQP6FklBdGZsA6xxYs86C/DvIeJv7dl9Sm6I5e33SWN7NEQ8en3CYGpkXS1O0qDg=="], - - "parse-entities": ["parse-entities@4.0.1", "", { "dependencies": { "@types/unist": "^2.0.0", "character-entities": "^2.0.0", "character-entities-legacy": "^3.0.0", "character-reference-invalid": "^2.0.0", "decode-named-character-reference": "^1.0.0", "is-alphanumerical": "^2.0.0", "is-decimal": "^2.0.0", "is-hexadecimal": "^2.0.0" } }, "sha512-SWzvYcSJh4d/SGLIOQfZ/CoNv6BTlI6YEQ7Nj82oDVnRpwe/Z/F1EMx42x3JAOwGBlCjeCH0BRJQbQ/opHL17w=="], - - "parse-numeric-range": ["parse-numeric-range@1.3.0", "", {}, "sha512-twN+njEipszzlMJd4ONUYgSfZPDxgHhT9Ahed5uTigpQn90FggW4SA/AIPq/6a149fTbE9qBEcSwE3FAEp6wQQ=="], - - "parse5": ["parse5@3.0.3", "", { "dependencies": { "@types/node": "*" } }, "sha512-rgO9Zg5LLLkfJF9E6CCmXlSE4UVceloys8JrFqCcHloC3usd/kJCyPDwH2SOlzix2j3xaP9sUX3e8+kvkuleAA=="], - - "path-exists": ["path-exists@4.0.0", "", {}, "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w=="], - - "path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="], - - "path-parse": ["path-parse@1.0.7", "", {}, "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="], - - "path-scurry": ["path-scurry@1.11.1", "", { "dependencies": { "lru-cache": "^10.2.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" } }, "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA=="], - - "periscopic": ["periscopic@3.1.0", "", { "dependencies": { "@types/estree": "^1.0.0", "estree-walker": "^3.0.0", "is-reference": "^3.0.0" } }, "sha512-vKiQ8RRtkl9P+r/+oefh25C3fhybptkHKCZSPlcXiJux2tJF55GnEj3BVn4A5gKfq9NWWXXrxkHBwVPUfH0opw=="], - - "picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="], - - "picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], - - "pify": ["pify@2.3.0", "", {}, "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog=="], - - "pirates": ["pirates@4.0.7", "", {}, "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA=="], - - "possible-typed-array-names": ["possible-typed-array-names@1.0.0", "", {}, "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q=="], - - "postcss": ["postcss@8.5.6", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg=="], - - "postcss-import": ["postcss-import@15.1.0", "", { "dependencies": { "postcss-value-parser": "^4.0.0", "read-cache": "^1.0.0", "resolve": "^1.1.7" }, "peerDependencies": { "postcss": "^8.0.0" } }, "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew=="], - - "postcss-js": ["postcss-js@4.0.1", "", { "dependencies": { "camelcase-css": "^2.0.1" }, "peerDependencies": { "postcss": "^8.4.21" } }, "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw=="], - - "postcss-load-config": ["postcss-load-config@4.0.2", "", { "dependencies": { "lilconfig": "^3.0.0", "yaml": "^2.3.4" }, "peerDependencies": { "postcss": ">=8.0.9", "ts-node": ">=9.0.0" } }, "sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ=="], - - "postcss-nested": ["postcss-nested@6.2.0", "", { "dependencies": { "postcss-selector-parser": "^6.1.1" }, "peerDependencies": { "postcss": "^8.2.14" } }, "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ=="], - - "postcss-selector-parser": ["postcss-selector-parser@6.0.10", "", { "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" } }, "sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w=="], - - "postcss-value-parser": ["postcss-value-parser@4.2.0", "", {}, "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ=="], - - "prelude-ls": ["prelude-ls@1.2.1", "", {}, "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g=="], - - "prettier": ["prettier@3.5.3", "", { "bin": "bin/prettier.cjs" }, "sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw=="], - - "process-nextick-args": ["process-nextick-args@2.0.1", "", {}, "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="], - - "prop-types": ["prop-types@15.8.1", "", { "dependencies": { "loose-envify": "^1.4.0", "object-assign": "^4.1.1", "react-is": "^16.13.1" } }, "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg=="], - - "property-information": ["property-information@6.5.0", "", {}, "sha512-PgTgs/BlvHxOu8QuEN7wi5A0OmXaBcHpmCSTehcs6Uuu9IkDIEo13Hy7n898RHfrQ49vKCoGeWZSaAK01nwVig=="], - - "prr": ["prr@1.0.1", "", {}, "sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw=="], - - "pseudomap": ["pseudomap@1.0.2", "", {}, "sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ=="], - - "psl": ["psl@1.15.0", "", { "dependencies": { "punycode": "^2.3.1" } }, "sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w=="], - - "punycode": ["punycode@2.3.1", "", {}, "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="], - - "queue-microtask": ["queue-microtask@1.2.3", "", {}, "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A=="], - - "react": ["react@19.1.1", "", {}, "sha512-w8nqGImo45dmMIfljjMwOGtbmC/mk4CMYhWIicdSflH91J9TyCyczcPFXJzrZ/ZXcgGRFeP6BU0BEJTw6tZdfQ=="], - - "react-dom": ["react-dom@19.1.1", "", { "dependencies": { "scheduler": "^0.26.0" }, "peerDependencies": { "react": "^19.1.1" } }, "sha512-Dlq/5LAZgF0Gaz6yiqZCf6VCcZs1ghAJyrsu84Q/GT0gV+mCxbfmKNoGRKBYMJ8IEdGPqu49YWXD02GCknEDkw=="], - - "react-highlight": ["react-highlight@0.15.0", "", { "dependencies": { "highlight.js": "^10.5.0" } }, "sha512-5uV/b/N4Z421GSVVe05fz+OfTsJtFzx/fJBdafZyw4LS70XjIZwgEx3Lrkfc01W/RzZ2Dtfb0DApoaJFAIKBtA=="], - - "react-hotkeys-hook": ["react-hotkeys-hook@5.1.0", "", { "peerDependencies": { "react": ">=16.8.0", "react-dom": ">=16.8.0" } }, "sha512-GCNGXjBzV9buOS3REoQFmSmE4WTvBhYQ0YrAeeMZI83bhXg3dRWsLHXDutcVDdEjwJqJCxk5iewWYX5LtFUd7g=="], - - "react-is": ["react-is@16.13.1", "", {}, "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="], - - "react-remove-scroll": ["react-remove-scroll@2.7.1", "", { "dependencies": { "react-remove-scroll-bar": "^2.3.7", "react-style-singleton": "^2.2.3", "tslib": "^2.1.0", "use-callback-ref": "^1.3.3", "use-sidecar": "^1.1.3" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" } }, "sha512-HpMh8+oahmIdOuS5aFKKY6Pyog+FNaZV/XyJOq7b4YFwsFHe5yYfdbIalI4k3vU2nSDql7YskmUseHsRrJqIPA=="], - - "react-remove-scroll-bar": ["react-remove-scroll-bar@2.3.8", "", { "dependencies": { "react-style-singleton": "^2.2.2", "tslib": "^2.0.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q=="], - - "react-style-singleton": ["react-style-singleton@2.2.3", "", { "dependencies": { "get-nonce": "^1.0.0", "tslib": "^2.0.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" } }, "sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ=="], - - "read-cache": ["read-cache@1.0.0", "", { "dependencies": { "pify": "^2.3.0" } }, "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA=="], - - "readable-stream": ["readable-stream@2.3.8", "", { "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", "isarray": "~1.0.0", "process-nextick-args": "~2.0.0", "safe-buffer": "~5.1.1", "string_decoder": "~1.1.1", "util-deprecate": "~1.0.1" } }, "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA=="], - - "readdirp": ["readdirp@3.6.0", "", { "dependencies": { "picomatch": "^2.2.1" } }, "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA=="], - - "reflect.getprototypeof": ["reflect.getprototypeof@1.0.10", "", { "dependencies": { "call-bind": "^1.0.8", "define-properties": "^1.2.1", "es-abstract": "^1.23.9", "es-errors": "^1.3.0", "es-object-atoms": "^1.0.0", "get-intrinsic": "^1.2.7", "get-proto": "^1.0.1", "which-builtin-type": "^1.2.1" } }, "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw=="], - - "refractor": ["refractor@4.8.1", "", { "dependencies": { "@types/hast": "^2.0.0", "@types/prismjs": "^1.0.0", "hastscript": "^7.0.0", "parse-entities": "^4.0.0" } }, "sha512-/fk5sI0iTgFYlmVGYVew90AoYnNMP6pooClx/XKqyeeCQXrL0Kvgn8V0VEht5ccdljbzzF1i3Q213gcntkRExg=="], - - "regexp.prototype.flags": ["regexp.prototype.flags@1.5.4", "", { "dependencies": { "call-bind": "^1.0.8", "define-properties": "^1.2.1", "es-errors": "^1.3.0", "get-proto": "^1.0.1", "gopd": "^1.2.0", "set-function-name": "^2.0.2" } }, "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA=="], - - "rehype-autolink-headings": ["rehype-autolink-headings@7.1.0", "", { "dependencies": { "@types/hast": "^3.0.0", "@ungap/structured-clone": "^1.0.0", "hast-util-heading-rank": "^3.0.0", "hast-util-is-element": "^3.0.0", "unified": "^11.0.0", "unist-util-visit": "^5.0.0" } }, "sha512-rItO/pSdvnvsP4QRB1pmPiNHUskikqtPojZKJPPPAVx9Hj8i8TwMBhofrrAYRhYOOBZH9tgmG5lPqDLuIWPWmw=="], - - "rehype-code-titles": ["rehype-code-titles@1.2.0", "", { "dependencies": { "hast": "~1.0.0", "unist-util-visit": "~4.1.2" } }, "sha512-bSr2YJ0GHbHFarUNDZ3VpcGi9HqjLNrA9Lj3nuyox2aGGLhN53dFP2WJtPRnnRqU/vpbCatIgOYxEvWP1YYKrw=="], - - "rehype-parse": ["rehype-parse@9.0.0", "", { "dependencies": { "@types/hast": "^3.0.0", "hast-util-from-html": "^2.0.0", "unified": "^11.0.0" } }, "sha512-WG7nfvmWWkCR++KEkZevZb/uw41E8TsH4DsY9UxsTbIXCVGbAs4S+r8FrQ+OtH5EEQAs+5UxKC42VinkmpA1Yw=="], - - "rehype-prism-plus": ["rehype-prism-plus@2.0.1", "", { "dependencies": { "hast-util-to-string": "^3.0.0", "parse-numeric-range": "^1.3.0", "refractor": "^4.8.0", "rehype-parse": "^9.0.0", "unist-util-filter": "^5.0.0", "unist-util-visit": "^5.0.0" } }, "sha512-Wglct0OW12tksTUseAPyWPo3srjBOY7xKlql/DPKi7HbsdZTyaLCAoO58QBKSczFQxElTsQlOY3JDOFzB/K++Q=="], - - "rehype-slug": ["rehype-slug@6.0.0", "", { "dependencies": { "@types/hast": "^3.0.0", "github-slugger": "^2.0.0", "hast-util-heading-rank": "^3.0.0", "hast-util-to-string": "^3.0.0", "unist-util-visit": "^5.0.0" } }, "sha512-lWyvf/jwu+oS5+hL5eClVd3hNdmwM1kAC0BUvEGD19pajQMIzcNUd/k9GsfQ+FfECvX+JE+e9/btsKH0EjJT6A=="], - - "remark": ["remark@15.0.1", "", { "dependencies": { "@types/mdast": "^4.0.0", "remark-parse": "^11.0.0", "remark-stringify": "^11.0.0", "unified": "^11.0.0" } }, "sha512-Eht5w30ruCXgFmxVUSlNWQ9iiimq07URKeFS3hNc8cUWy1llX4KDWfyEDZRycMc+znsN9Ux5/tJ/BFdgdOwA3A=="], - - "remark-gfm": ["remark-gfm@4.0.1", "", { "dependencies": { "@types/mdast": "^4.0.0", "mdast-util-gfm": "^3.0.0", "micromark-extension-gfm": "^3.0.0", "remark-parse": "^11.0.0", "remark-stringify": "^11.0.0", "unified": "^11.0.0" } }, "sha512-1quofZ2RQ9EWdeN34S79+KExV1764+wCUGop5CPL1WGdD0ocPpu91lzPGbwWMECpEpd42kJGQwzRfyov9j4yNg=="], - - "remark-mdx": ["remark-mdx@3.0.1", "", { "dependencies": { "mdast-util-mdx": "^3.0.0", "micromark-extension-mdxjs": "^3.0.0" } }, "sha512-3Pz3yPQ5Rht2pM5R+0J2MrGoBSrzf+tJG94N+t/ilfdh8YLyyKYtidAYwTveB20BoHAcwIopOUqhcmh2F7hGYA=="], - - "remark-parse": ["remark-parse@11.0.0", "", { "dependencies": { "@types/mdast": "^4.0.0", "mdast-util-from-markdown": "^2.0.0", "micromark-util-types": "^2.0.0", "unified": "^11.0.0" } }, "sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA=="], - - "remark-rehype": ["remark-rehype@11.1.0", "", { "dependencies": { "@types/hast": "^3.0.0", "@types/mdast": "^4.0.0", "mdast-util-to-hast": "^13.0.0", "unified": "^11.0.0", "vfile": "^6.0.0" } }, "sha512-z3tJrAs2kIs1AqIIy6pzHmAHlF1hWQ+OdY4/hv+Wxe35EhyLKcajL33iUEn3ScxtFox9nUvRufR/Zre8Q08H/g=="], - - "remark-stringify": ["remark-stringify@11.0.0", "", { "dependencies": { "@types/mdast": "^4.0.0", "mdast-util-to-markdown": "^2.0.0", "unified": "^11.0.0" } }, "sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw=="], - - "resolve": ["resolve@1.22.8", "", { "dependencies": { "is-core-module": "^2.13.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": "bin/resolve" }, "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw=="], - - "resolve-from": ["resolve-from@4.0.0", "", {}, "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g=="], - - "resolve-pkg-maps": ["resolve-pkg-maps@1.0.0", "", {}, "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw=="], - - "reusify": ["reusify@1.1.0", "", {}, "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw=="], - - "robot-directives": ["robot-directives@0.3.0", "", { "dependencies": { "isbot": "^2.0.0", "useragent": "^2.1.8" } }, "sha512-mROGTXczU5H5jpfwIpy4TUcmoZH033UXvkI2QZfbfH+qugWr7XzmXmMtKcqqrTn1d4wabmwfVG9xaVQQ66ti8Q=="], - - "robots-txt-guard": ["robots-txt-guard@0.1.1", "", {}, "sha512-6+nGkE6c2dI9/dmhmNcoMKVwJxlA6sgN/XNo0rm6LLdA0hnj4YkpgrZdhMPl58gJkAqeiHlf4+8tJcLM1tv1Ew=="], - - "robots-txt-parse": ["robots-txt-parse@0.0.4", "", { "dependencies": { "bluebird": "^2.3.5", "split": "^0.3.0", "stream-combiner": "^0.2.1", "through": "^2.3.4" } }, "sha512-B2VQEC5oe9MD/77oILGi98NNAqtY1BlqgrwlYjq/RR5sDfZqpkFj1sG5pCieiSApoTxatJgGW+yWCh0zFfOGMQ=="], - - "run-parallel": ["run-parallel@1.2.0", "", { "dependencies": { "queue-microtask": "^1.2.2" } }, "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA=="], - - "safe-array-concat": ["safe-array-concat@1.1.3", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.2", "get-intrinsic": "^1.2.6", "has-symbols": "^1.1.0", "isarray": "^2.0.5" } }, "sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q=="], - - "safe-buffer": ["safe-buffer@5.1.2", "", {}, "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="], - - "safe-push-apply": ["safe-push-apply@1.0.0", "", { "dependencies": { "es-errors": "^1.3.0", "isarray": "^2.0.5" } }, "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA=="], - - "safe-regex-test": ["safe-regex-test@1.1.0", "", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "is-regex": "^1.2.1" } }, "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw=="], - - "satori": ["satori@0.16.0", "", { "dependencies": { "@shuding/opentype.js": "1.4.0-beta.0", "css-background-parser": "^0.1.0", "css-box-shadow": "1.0.0-3", "css-gradient-parser": "^0.0.16", "css-to-react-native": "^3.0.0", "emoji-regex-xs": "^2.0.1", "escape-html": "^1.0.3", "linebreak": "^1.1.0", "parse-css-color": "^0.2.1", "postcss-value-parser": "^4.2.0", "yoga-layout": "^3.2.1" } }, "sha512-ZvHN3ygzZ8FuxjSNB+mKBiF/NIoqHzlBGbD0MJiT+MvSsFOvotnWOhdTjxKzhHRT2wPC1QbhLzx2q/Y83VhfYQ=="], - - "scheduler": ["scheduler@0.26.0", "", {}, "sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA=="], - - "section-matter": ["section-matter@1.0.0", "", { "dependencies": { "extend-shallow": "^2.0.1", "kind-of": "^6.0.0" } }, "sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA=="], - - "semver": ["semver@6.3.1", "", { "bin": "bin/semver.js" }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], - - "set-function-length": ["set-function-length@1.2.2", "", { "dependencies": { "define-data-property": "^1.1.4", "es-errors": "^1.3.0", "function-bind": "^1.1.2", "get-intrinsic": "^1.2.4", "gopd": "^1.0.1", "has-property-descriptors": "^1.0.2" } }, "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg=="], - - "set-function-name": ["set-function-name@2.0.2", "", { "dependencies": { "define-data-property": "^1.1.4", "es-errors": "^1.3.0", "functions-have-names": "^1.2.3", "has-property-descriptors": "^1.0.2" } }, "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ=="], - - "set-proto": ["set-proto@1.0.0", "", { "dependencies": { "dunder-proto": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.0.0" } }, "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw=="], - - "sharp": ["sharp@0.34.3", "", { "dependencies": { "color": "^4.2.3", "detect-libc": "^2.0.4", "semver": "^7.7.2" }, "optionalDependencies": { "@img/sharp-darwin-arm64": "0.34.3", "@img/sharp-darwin-x64": "0.34.3", "@img/sharp-libvips-darwin-arm64": "1.2.0", "@img/sharp-libvips-darwin-x64": "1.2.0", "@img/sharp-libvips-linux-arm": "1.2.0", "@img/sharp-libvips-linux-arm64": "1.2.0", "@img/sharp-libvips-linux-ppc64": "1.2.0", "@img/sharp-libvips-linux-s390x": "1.2.0", "@img/sharp-libvips-linux-x64": "1.2.0", "@img/sharp-libvips-linuxmusl-arm64": "1.2.0", "@img/sharp-libvips-linuxmusl-x64": "1.2.0", "@img/sharp-linux-arm": "0.34.3", "@img/sharp-linux-arm64": "0.34.3", "@img/sharp-linux-ppc64": "0.34.3", "@img/sharp-linux-s390x": "0.34.3", "@img/sharp-linux-x64": "0.34.3", "@img/sharp-linuxmusl-arm64": "0.34.3", "@img/sharp-linuxmusl-x64": "0.34.3", "@img/sharp-wasm32": "0.34.3", "@img/sharp-win32-arm64": "0.34.3", "@img/sharp-win32-ia32": "0.34.3", "@img/sharp-win32-x64": "0.34.3" } }, "sha512-eX2IQ6nFohW4DbvHIOLRB3MHFpYqaqvXd3Tp5e/T/dSH83fxaNJQRvDMhASmkNTsNTVF2/OOopzRCt7xokgPfg=="], - - "shebang-command": ["shebang-command@2.0.0", "", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="], - - "shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="], - - "side-channel": ["side-channel@1.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.3", "side-channel-list": "^1.0.0", "side-channel-map": "^1.0.1", "side-channel-weakmap": "^1.0.2" } }, "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw=="], - - "side-channel-list": ["side-channel-list@1.0.0", "", { "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.3" } }, "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA=="], - - "side-channel-map": ["side-channel-map@1.0.1", "", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.5", "object-inspect": "^1.13.3" } }, "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA=="], - - "side-channel-weakmap": ["side-channel-weakmap@1.0.2", "", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.5", "object-inspect": "^1.13.3", "side-channel-map": "^1.0.1" } }, "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A=="], - - "signal-exit": ["signal-exit@4.1.0", "", {}, "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw=="], - - "simple-swizzle": ["simple-swizzle@0.2.2", "", { "dependencies": { "is-arrayish": "^0.3.1" } }, "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg=="], - - "source-map": ["source-map@0.7.4", "", {}, "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA=="], - - "source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="], - - "space-separated-tokens": ["space-separated-tokens@2.0.2", "", {}, "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q=="], - - "split": ["split@0.3.3", "", { "dependencies": { "through": "2" } }, "sha512-wD2AeVmxXRBoX44wAycgjVpMhvbwdI2aZjCkvfNcH1YqHQvJVa1duWc73OyVGJUc05fhFaTZeQ/PYsrmyH0JVA=="], - - "splitargs": ["splitargs@0.0.7", "", {}, "sha512-UUFYD2oWbNwULH6WoVtLUOw8ch586B+HUqcsAjjjeoBQAM1bD4wZRXu01koaxyd8UeYpybWqW4h+lO1Okv40Tg=="], - - "sprintf-js": ["sprintf-js@1.0.3", "", {}, "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g=="], - - "stable-hash": ["stable-hash@0.0.5", "", {}, "sha512-+L3ccpzibovGXFK+Ap/f8LOS0ahMrHTf3xu7mMLSpEGU0EO9ucaysSylKo9eRDFNhWve/y275iPmIZ4z39a9iA=="], - - "stop-iteration-iterator": ["stop-iteration-iterator@1.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "internal-slot": "^1.1.0" } }, "sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ=="], - - "stream-combiner": ["stream-combiner@0.2.2", "", { "dependencies": { "duplexer": "~0.1.1", "through": "~2.3.4" } }, "sha512-6yHMqgLYDzQDcAkL+tjJDC5nSNuNIx0vZtRZeiPh7Saef7VHX9H5Ijn9l2VIol2zaNYlYEX6KyuT/237A58qEQ=="], - - "stream-length": ["stream-length@1.0.2", "", { "dependencies": { "bluebird": "^2.6.2" } }, "sha512-aI+qKFiwoDV4rsXiS7WRoCt+v2RX1nUj17+KJC5r2gfh5xoSJIfP6Y3Do/HtvesFcTSWthIuJ3l1cvKQY/+nZg=="], - - "string-width": ["string-width@5.1.2", "", { "dependencies": { "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", "strip-ansi": "^7.0.1" } }, "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA=="], - - "string-width-cjs": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], - - "string.prototype.codepointat": ["string.prototype.codepointat@0.2.1", "", {}, "sha512-2cBVCj6I4IOvEnjgO/hWqXjqBGsY+zwPmHl12Srk9IXSZ56Jwwmy+66XO5Iut/oQVR7t5ihYdLB0GMa4alEUcg=="], - - "string.prototype.includes": ["string.prototype.includes@2.0.1", "", { "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", "es-abstract": "^1.23.3" } }, "sha512-o7+c9bW6zpAdJHTtujeePODAhkuicdAryFsfVKwA+wGw89wJ4GTY484WTucM9hLtDEOpOvI+aHnzqnC5lHp4Rg=="], - - "string.prototype.matchall": ["string.prototype.matchall@4.0.12", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.3", "define-properties": "^1.2.1", "es-abstract": "^1.23.6", "es-errors": "^1.3.0", "es-object-atoms": "^1.0.0", "get-intrinsic": "^1.2.6", "gopd": "^1.2.0", "has-symbols": "^1.1.0", "internal-slot": "^1.1.0", "regexp.prototype.flags": "^1.5.3", "set-function-name": "^2.0.2", "side-channel": "^1.1.0" } }, "sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA=="], - - "string.prototype.repeat": ["string.prototype.repeat@1.0.0", "", { "dependencies": { "define-properties": "^1.1.3", "es-abstract": "^1.17.5" } }, "sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w=="], - - "string.prototype.trim": ["string.prototype.trim@1.2.10", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.2", "define-data-property": "^1.1.4", "define-properties": "^1.2.1", "es-abstract": "^1.23.5", "es-object-atoms": "^1.0.0", "has-property-descriptors": "^1.0.2" } }, "sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA=="], - - "string.prototype.trimend": ["string.prototype.trimend@1.0.9", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.2", "define-properties": "^1.2.1", "es-object-atoms": "^1.0.0" } }, "sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ=="], - - "string.prototype.trimstart": ["string.prototype.trimstart@1.0.8", "", { "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", "es-object-atoms": "^1.0.0" } }, "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg=="], - - "string_decoder": ["string_decoder@1.1.1", "", { "dependencies": { "safe-buffer": "~5.1.0" } }, "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg=="], - - "stringify-entities": ["stringify-entities@4.0.4", "", { "dependencies": { "character-entities-html4": "^2.0.0", "character-entities-legacy": "^3.0.0" } }, "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg=="], - - "strip-ansi": ["strip-ansi@3.0.1", "", { "dependencies": { "ansi-regex": "^2.0.0" } }, "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg=="], - - "strip-ansi-cjs": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], - - "strip-bom": ["strip-bom@3.0.0", "", {}, "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA=="], - - "strip-bom-string": ["strip-bom-string@1.0.0", "", {}, "sha512-uCC2VHvQRYu+lMh4My/sFNmF2klFymLX1wHJeXnbEJERpV/ZsVuonzerjfrGpIGF7LBVa1O7i9kjiWvJiFck8g=="], - - "strip-json-comments": ["strip-json-comments@3.1.1", "", {}, "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig=="], - - "strip-markdown": ["strip-markdown@6.0.0", "", { "dependencies": { "@types/mdast": "^4.0.0" } }, "sha512-mSa8FtUoX3ExJYDkjPUTC14xaBAn4Ik5GPQD45G5E2egAmeV3kHgVSTfIoSDggbF6Pk9stahVgqsLCNExv6jHw=="], - - "style-to-object": ["style-to-object@0.4.4", "", { "dependencies": { "inline-style-parser": "0.1.1" } }, "sha512-HYNoHZa2GorYNyqiCaBgsxvcJIn7OHq6inEga+E6Ke3m5JkoqpQbnFssk4jwe+K7AhGa2fcha4wSOf1Kn01dMg=="], - - "styled-jsx": ["styled-jsx@5.1.6", "", { "dependencies": { "client-only": "0.0.1" }, "peerDependencies": { "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0 || ^19.0.0-0" } }, "sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA=="], - - "sucrase": ["sucrase@3.35.0", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.2", "commander": "^4.0.0", "glob": "^10.3.10", "lines-and-columns": "^1.1.6", "mz": "^2.7.0", "pirates": "^4.0.1", "ts-interface-checker": "^0.1.9" }, "bin": { "sucrase": "bin/sucrase", "sucrase-node": "bin/sucrase-node" } }, "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA=="], - - "supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="], - - "supports-preserve-symlinks-flag": ["supports-preserve-symlinks-flag@1.0.0", "", {}, "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w=="], - - "tailwind-merge": ["tailwind-merge@3.3.1", "", {}, "sha512-gBXpgUm/3rp1lMZZrM/w7D8GKqshif0zAymAhbCyIt8KMe+0v9DQ7cdYLR4FHH/cKpdTXb+A/tKKU3eolfsI+g=="], - - "tailwindcss": ["tailwindcss@3.4.17", "", { "dependencies": { "@alloc/quick-lru": "^5.2.0", "arg": "^5.0.2", "chokidar": "^3.6.0", "didyoumean": "^1.2.2", "dlv": "^1.1.3", "fast-glob": "^3.3.2", "glob-parent": "^6.0.2", "is-glob": "^4.0.3", "jiti": "^1.21.6", "lilconfig": "^3.1.3", "micromatch": "^4.0.8", "normalize-path": "^3.0.0", "object-hash": "^3.0.0", "picocolors": "^1.1.1", "postcss": "^8.4.47", "postcss-import": "^15.1.0", "postcss-js": "^4.0.1", "postcss-load-config": "^4.0.2", "postcss-nested": "^6.2.0", "postcss-selector-parser": "^6.1.2", "resolve": "^1.22.8", "sucrase": "^3.35.0" }, "bin": { "tailwind": "lib/cli.js", "tailwindcss": "lib/cli.js" } }, "sha512-w33E2aCvSDP0tW9RZuNXadXlkHXqFzSkQew/aIa2i/Sj8fThxwovwlXHSPXTbAHwEIhBFXAedUhP2tueAKP8Og=="], - - "tailwindcss-animate": ["tailwindcss-animate@1.0.7", "", { "peerDependencies": { "tailwindcss": ">=3.0.0 || insiders" } }, "sha512-bl6mpH3T7I3UFxuvDEXLxy/VuFxBk5bbzplh7tXI68mwMokNYd1t9qPBHlnyTwfa4JGC4zP516I1hYYtQ/vspA=="], - - "thenify": ["thenify@3.3.1", "", { "dependencies": { "any-promise": "^1.0.0" } }, "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw=="], - - "thenify-all": ["thenify-all@1.6.0", "", { "dependencies": { "thenify": ">= 3.1.0 < 4" } }, "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA=="], - - "through": ["through@2.3.8", "", {}, "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg=="], - - "through2": ["through2@0.5.1", "", { "dependencies": { "readable-stream": "~1.0.17", "xtend": "~3.0.0" } }, "sha512-zexCrAOTbjkBCXGyozn7hhS3aEaqdrc59mAD2E3dKYzV1vFuEGQ1hEDJN2oQMQFwy4he2zyLqPZV+AlfS8ZWJA=="], - - "through2-sink": ["through2-sink@1.0.0", "", { "dependencies": { "through2": "~0.5.1", "xtend": "~3.0.0" } }, "sha512-9HvIHIEXZ5YgstQx3vsu4U/QQ/n7X5RHlXf8MsfSEnEzeUFbX9BHBWmlwdQ1b6CzDlUEDwjFnkSIxpJZ6qP+0Q=="], - - "through2-spy": ["through2-spy@1.2.0", "", { "dependencies": { "through2": "~0.5.1", "xtend": "~3.0.0" } }, "sha512-QJ/32YGXA8K/PlkT/7kJOfWZREdlwoCcdVOL/wZHhV0JQJlwUQeDi4QZrEUEAdIL6Kjb9BRdHHz65zg+rzFxuA=="], - - "tiny-inflate": ["tiny-inflate@1.0.3", "", {}, "sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw=="], - - "tinyglobby": ["tinyglobby@0.2.14", "", { "dependencies": { "fdir": "^6.4.4", "picomatch": "^4.0.2" } }, "sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ=="], - - "tmp": ["tmp@0.0.33", "", { "dependencies": { "os-tmpdir": "~1.0.2" } }, "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw=="], - - "to-regex-range": ["to-regex-range@5.0.1", "", { "dependencies": { "is-number": "^7.0.0" } }, "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ=="], - - "tough-cookie": ["tough-cookie@2.5.0", "", { "dependencies": { "psl": "^1.1.28", "punycode": "^2.1.1" } }, "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g=="], - - "trim-lines": ["trim-lines@3.0.1", "", {}, "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg=="], - - "trough": ["trough@2.2.0", "", {}, "sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw=="], - - "ts-api-utils": ["ts-api-utils@2.1.0", "", { "peerDependencies": { "typescript": ">=4.8.4" } }, "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ=="], - - "ts-interface-checker": ["ts-interface-checker@0.1.13", "", {}, "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA=="], - - "ts-node": ["ts-node@10.9.2", "", { "dependencies": { "@cspotcode/source-map-support": "^0.8.0", "@tsconfig/node10": "^1.0.7", "@tsconfig/node12": "^1.0.7", "@tsconfig/node14": "^1.0.0", "@tsconfig/node16": "^1.0.2", "acorn": "^8.4.1", "acorn-walk": "^8.1.1", "arg": "^4.1.0", "create-require": "^1.1.0", "diff": "^4.0.1", "make-error": "^1.1.1", "v8-compile-cache-lib": "^3.0.1", "yn": "3.1.1" }, "peerDependencies": { "@swc/core": ">=1.2.50", "@swc/wasm": ">=1.2.50", "@types/node": "*", "typescript": ">=2.7" }, "optionalPeers": ["@swc/core", "@swc/wasm"], "bin": { "ts-node": "dist/bin.js", "ts-node-cwd": "dist/bin-cwd.js", "ts-node-esm": "dist/bin-esm.js", "ts-node-script": "dist/bin-script.js", "ts-node-transpile-only": "dist/bin-transpile.js", "ts-script": "dist/bin-script-deprecated.js" } }, "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ=="], - - "tsconfig-paths": ["tsconfig-paths@3.15.0", "", { "dependencies": { "@types/json5": "^0.0.29", "json5": "^1.0.2", "minimist": "^1.2.6", "strip-bom": "^3.0.0" } }, "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg=="], - - "tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], - - "tsx": ["tsx@4.20.3", "", { "dependencies": { "esbuild": "~0.25.0", "get-tsconfig": "^4.7.5" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "bin": "dist/cli.mjs" }, "sha512-qjbnuR9Tr+FJOMBqJCW5ehvIo/buZq7vH7qD7JziU98h6l3qGy0a/yPFjwO+y0/T7GFpNgNAvEcPPVfyT8rrPQ=="], - - "type-check": ["type-check@0.4.0", "", { "dependencies": { "prelude-ls": "^1.2.1" } }, "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew=="], - - "typed-array-buffer": ["typed-array-buffer@1.0.3", "", { "dependencies": { "call-bound": "^1.0.3", "es-errors": "^1.3.0", "is-typed-array": "^1.1.14" } }, "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw=="], - - "typed-array-byte-length": ["typed-array-byte-length@1.0.3", "", { "dependencies": { "call-bind": "^1.0.8", "for-each": "^0.3.3", "gopd": "^1.2.0", "has-proto": "^1.2.0", "is-typed-array": "^1.1.14" } }, "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg=="], - - "typed-array-byte-offset": ["typed-array-byte-offset@1.0.4", "", { "dependencies": { "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.8", "for-each": "^0.3.3", "gopd": "^1.2.0", "has-proto": "^1.2.0", "is-typed-array": "^1.1.15", "reflect.getprototypeof": "^1.0.9" } }, "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ=="], - - "typed-array-length": ["typed-array-length@1.0.7", "", { "dependencies": { "call-bind": "^1.0.7", "for-each": "^0.3.3", "gopd": "^1.0.1", "is-typed-array": "^1.1.13", "possible-typed-array-names": "^1.0.0", "reflect.getprototypeof": "^1.0.6" } }, "sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg=="], - - "typedarray": ["typedarray@0.0.6", "", {}, "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA=="], - - "typescript": ["typescript@5.4.5", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ=="], - - "unbox-primitive": ["unbox-primitive@1.1.0", "", { "dependencies": { "call-bound": "^1.0.3", "has-bigints": "^1.0.2", "has-symbols": "^1.1.0", "which-boxed-primitive": "^1.1.1" } }, "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw=="], - - "undici-types": ["undici-types@7.10.0", "", {}, "sha512-t5Fy/nfn+14LuOc2KNYg75vZqClpAiqscVvMygNnlsHBFpSXdJaYtXMcdNLpl/Qvc3P2cB3s6lOV51nqsFq4ag=="], - - "unicode-trie": ["unicode-trie@2.0.0", "", { "dependencies": { "pako": "^0.2.5", "tiny-inflate": "^1.0.0" } }, "sha512-x7bc76x0bm4prf1VLg79uhAzKw8DVboClSN5VxJuQ+LKDOVEW9CdH+VY7SP+vX7xCYQqzzgQpFqz15zeLvAtZQ=="], - - "unified": ["unified@11.0.4", "", { "dependencies": { "@types/unist": "^3.0.0", "bail": "^2.0.0", "devlop": "^1.0.0", "extend": "^3.0.0", "is-plain-obj": "^4.0.0", "trough": "^2.0.0", "vfile": "^6.0.0" } }, "sha512-apMPnyLjAX+ty4OrNap7yumyVAMlKx5IWU2wlzzUdYJO9A8f1p9m/gywF/GM2ZDFcjQPrx59Mc90KwmxsoklxQ=="], - - "unist-util-filter": ["unist-util-filter@5.0.1", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-is": "^6.0.0", "unist-util-visit-parents": "^6.0.0" } }, "sha512-pHx7D4Zt6+TsfwylH9+lYhBhzyhEnCXs/lbq/Hstxno5z4gVdyc2WEW0asfjGKPyG4pEKrnBv5hdkO6+aRnQJw=="], - - "unist-util-is": ["unist-util-is@6.0.0", "", { "dependencies": { "@types/unist": "^3.0.0" } }, "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw=="], - - "unist-util-position": ["unist-util-position@5.0.0", "", { "dependencies": { "@types/unist": "^3.0.0" } }, "sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA=="], - - "unist-util-position-from-estree": ["unist-util-position-from-estree@2.0.0", "", { "dependencies": { "@types/unist": "^3.0.0" } }, "sha512-KaFVRjoqLyF6YXCbVLNad/eS4+OfPQQn2yOd7zF/h5T/CSL2v8NpN6a5TPvtbXthAGw5nG+PuTtq+DdIZr+cRQ=="], - - "unist-util-remove": ["unist-util-remove@3.1.1", "", { "dependencies": { "@types/unist": "^2.0.0", "unist-util-is": "^5.0.0", "unist-util-visit-parents": "^5.0.0" } }, "sha512-kfCqZK5YVY5yEa89tvpl7KnBBHu2c6CzMkqHUrlOqaRgGOMp0sMvwWOVrbAtj03KhovQB7i96Gda72v/EFE0vw=="], - - "unist-util-remove-position": ["unist-util-remove-position@5.0.0", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-visit": "^5.0.0" } }, "sha512-Hp5Kh3wLxv0PHj9m2yZhhLt58KzPtEYKQQ4yxfYFEO7EvHwzyDYnduhHnY1mDxoqr7VUwVuHXk9RXKIiYS1N8Q=="], - - "unist-util-stringify-position": ["unist-util-stringify-position@4.0.0", "", { "dependencies": { "@types/unist": "^3.0.0" } }, "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ=="], - - "unist-util-visit": ["unist-util-visit@5.0.0", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-is": "^6.0.0", "unist-util-visit-parents": "^6.0.0" } }, "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg=="], - - "unist-util-visit-parents": ["unist-util-visit-parents@6.0.1", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-is": "^6.0.0" } }, "sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw=="], - - "unrs-resolver": ["unrs-resolver@1.11.1", "", { "dependencies": { "napi-postinstall": "^0.3.0" }, "optionalDependencies": { "@unrs/resolver-binding-android-arm-eabi": "1.11.1", "@unrs/resolver-binding-android-arm64": "1.11.1", "@unrs/resolver-binding-darwin-arm64": "1.11.1", "@unrs/resolver-binding-darwin-x64": "1.11.1", "@unrs/resolver-binding-freebsd-x64": "1.11.1", "@unrs/resolver-binding-linux-arm-gnueabihf": "1.11.1", "@unrs/resolver-binding-linux-arm-musleabihf": "1.11.1", "@unrs/resolver-binding-linux-arm64-gnu": "1.11.1", "@unrs/resolver-binding-linux-arm64-musl": "1.11.1", "@unrs/resolver-binding-linux-ppc64-gnu": "1.11.1", "@unrs/resolver-binding-linux-riscv64-gnu": "1.11.1", "@unrs/resolver-binding-linux-riscv64-musl": "1.11.1", "@unrs/resolver-binding-linux-s390x-gnu": "1.11.1", "@unrs/resolver-binding-linux-x64-gnu": "1.11.1", "@unrs/resolver-binding-linux-x64-musl": "1.11.1", "@unrs/resolver-binding-wasm32-wasi": "1.11.1", "@unrs/resolver-binding-win32-arm64-msvc": "1.11.1", "@unrs/resolver-binding-win32-ia32-msvc": "1.11.1", "@unrs/resolver-binding-win32-x64-msvc": "1.11.1" } }, "sha512-bSjt9pjaEBnNiGgc9rUiHGKv5l4/TGzDmYw3RhnkJGtLhbnnA/5qJj7x3dNDCRx/PJxu774LlH8lCOlB4hEfKg=="], - - "update-browserslist-db": ["update-browserslist-db@1.1.3", "", { "dependencies": { "escalade": "^3.2.0", "picocolors": "^1.1.1" }, "peerDependencies": { "browserslist": ">= 4.21.0" }, "bin": "cli.js" }, "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw=="], - - "uri-js": ["uri-js@4.4.1", "", { "dependencies": { "punycode": "^2.1.0" } }, "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg=="], - - "urlcache": ["urlcache@0.7.0", "", { "dependencies": { "urlobj": "0.0.11" } }, "sha512-xOW4t6wJDT07+VunsHwePemyXXRidCSOZ/1RIILJi2XnB+81FA5H0MRvS63/7joTWjGLajcJJGvR5odpbkV6hw=="], - - "urlobj": ["urlobj@0.0.11", "", { "dependencies": { "is-object": "^1.0.1", "is-string": "^1.0.4", "object-assign": "^4.1.1" } }, "sha512-Ncck0WWtuFBbZhSYwKjK1AU2V51V98P/KHUPkaEc+mFy4xkpAHFNyVQT+S5SgtsJAr94e4wiKUucJSfasV2kBw=="], - - "use-callback-ref": ["use-callback-ref@1.3.3", "", { "dependencies": { "tslib": "^2.0.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" } }, "sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg=="], - - "use-sidecar": ["use-sidecar@1.1.3", "", { "dependencies": { "detect-node-es": "^1.1.0", "tslib": "^2.0.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" } }, "sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ=="], - - "useragent": ["useragent@2.3.0", "", { "dependencies": { "lru-cache": "4.1.x", "tmp": "0.0.x" } }, "sha512-4AoH4pxuSvHCjqLO04sU6U/uE65BYza8l/KKBS0b0hnUPWi+cQ2BpeTEwejCSx9SPV5/U03nniDTrWx5NrmKdw=="], - - "util-deprecate": ["util-deprecate@1.0.2", "", {}, "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="], - - "uuid": ["uuid@2.0.3", "", {}, "sha512-FULf7fayPdpASncVy4DLh3xydlXEJJpvIELjYjNeQWYUZ9pclcpvCZSr2gkmN2FrrGcI7G/cJsIEwk5/8vfXpg=="], - - "v8-compile-cache-lib": ["v8-compile-cache-lib@3.0.1", "", {}, "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg=="], - - "vfile": ["vfile@6.0.1", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-stringify-position": "^4.0.0", "vfile-message": "^4.0.0" } }, "sha512-1bYqc7pt6NIADBJ98UiG0Bn/CHIVOoZ/IyEkqIruLg0mE1BKzkOXY2D6CSqQIcKqgadppE5lrxgWXJmXd7zZJw=="], - - "vfile-location": ["vfile-location@5.0.2", "", { "dependencies": { "@types/unist": "^3.0.0", "vfile": "^6.0.0" } }, "sha512-NXPYyxyBSH7zB5U6+3uDdd6Nybz6o6/od9rk8bp9H8GR3L+cm/fC0uUTbqBmUTnMCUDslAGBOIKNfvvb+gGlDg=="], - - "vfile-matter": ["vfile-matter@5.0.0", "", { "dependencies": { "vfile": "^6.0.0", "yaml": "^2.0.0" } }, "sha512-jhPSqlj8hTSkTXOqyxbUeZAFFVq/iwu/jukcApEqc/7DOidaAth6rDc0Zgg0vWpzUnWkwFP7aK28l6nBmxMqdQ=="], - - "vfile-message": ["vfile-message@4.0.2", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-stringify-position": "^4.0.0" } }, "sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw=="], - - "web-namespaces": ["web-namespaces@2.0.1", "", {}, "sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ=="], - - "which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="], - - "which-boxed-primitive": ["which-boxed-primitive@1.1.1", "", { "dependencies": { "is-bigint": "^1.1.0", "is-boolean-object": "^1.2.1", "is-number-object": "^1.1.1", "is-string": "^1.1.1", "is-symbol": "^1.1.1" } }, "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA=="], - - "which-builtin-type": ["which-builtin-type@1.2.1", "", { "dependencies": { "call-bound": "^1.0.2", "function.prototype.name": "^1.1.6", "has-tostringtag": "^1.0.2", "is-async-function": "^2.0.0", "is-date-object": "^1.1.0", "is-finalizationregistry": "^1.1.0", "is-generator-function": "^1.0.10", "is-regex": "^1.2.1", "is-weakref": "^1.0.2", "isarray": "^2.0.5", "which-boxed-primitive": "^1.1.0", "which-collection": "^1.0.2", "which-typed-array": "^1.1.16" } }, "sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q=="], - - "which-collection": ["which-collection@1.0.2", "", { "dependencies": { "is-map": "^2.0.3", "is-set": "^2.0.3", "is-weakmap": "^2.0.2", "is-weakset": "^2.0.3" } }, "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw=="], - - "which-typed-array": ["which-typed-array@1.1.19", "", { "dependencies": { "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.8", "call-bound": "^1.0.4", "for-each": "^0.3.5", "get-proto": "^1.0.1", "gopd": "^1.2.0", "has-tostringtag": "^1.0.2" } }, "sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw=="], - - "win-release": ["win-release@1.1.1", "", { "dependencies": { "semver": "^5.0.1" } }, "sha512-iCRnKVvGxOQdsKhcQId2PXV1vV3J/sDPXKA4Oe9+Eti2nb2ESEsYHRYls/UjoUW3bIc5ZDO8dTH50A/5iVN+bw=="], - - "wrap-ansi": ["wrap-ansi@8.1.0", "", { "dependencies": { "ansi-styles": "^6.1.0", "string-width": "^5.0.1", "strip-ansi": "^7.0.1" } }, "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ=="], - - "wrap-ansi-cjs": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="], - - "xtend": ["xtend@3.0.0", "", {}, "sha512-sp/sT9OALMjRW1fKDlPeuSZlDQpkqReA0pyJukniWbTGoEKefHxhGJynE3PNhUMlcM8qWIjPwecwCw4LArS5Eg=="], - - "yallist": ["yallist@2.1.2", "", {}, "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A=="], - - "yaml": ["yaml@2.4.1", "", { "bin": "bin.mjs" }, "sha512-pIXzoImaqmfOrL7teGUBt/T7ZDnyeGBWyXQBvOVhLkWLN37GXv8NMLK406UY6dS51JfcQHsmcW5cJ441bHg6Lg=="], - - "yn": ["yn@3.1.1", "", {}, "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q=="], - - "yocto-queue": ["yocto-queue@0.1.0", "", {}, "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q=="], - - "yoga-layout": ["yoga-layout@3.2.1", "", {}, "sha512-0LPOt3AxKqMdFBZA3HBAt/t/8vIKq7VaQYbuA8WxCgung+p9TVyKRYdpvCb80HcdTN2NkbIKbhNwKUfm3tQywQ=="], - - "zwitch": ["zwitch@2.0.4", "", {}, "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A=="], - - "@babel/highlight/chalk": ["chalk@2.4.2", "", { "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", "supports-color": "^5.3.0" } }, "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ=="], - - "@eslint-community/eslint-utils/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="], - - "@eslint/eslintrc/js-yaml": ["js-yaml@4.1.0", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": "bin/js-yaml.js" }, "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA=="], - - "@humanfs/node/@humanwhocodes/retry": ["@humanwhocodes/retry@0.3.1", "", {}, "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA=="], - - "@isaacs/cliui/strip-ansi": ["strip-ansi@7.1.0", "", { "dependencies": { "ansi-regex": "^6.0.1" } }, "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ=="], - - "@jridgewell/gen-mapping/@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.29", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-uw6guiW/gcAGPDhLmd77/6lW8QLeiV5RUTsAX46Db6oLhGaVj4lhnPwb184s1bkc8kdVg/+h988dro8GRDpmYQ=="], - - "@next/eslint-plugin-next/fast-glob": ["fast-glob@3.3.1", "", { "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", "micromatch": "^4.0.4" } }, "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg=="], - - "@typescript-eslint/eslint-plugin/ignore": ["ignore@7.0.5", "", {}, "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg=="], - - "@typescript-eslint/typescript-estree/fast-glob": ["fast-glob@3.3.3", "", { "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", "micromatch": "^4.0.8" } }, "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg=="], - - "@typescript-eslint/typescript-estree/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="], - - "@typescript-eslint/typescript-estree/semver": ["semver@7.7.2", "", { "bin": "bin/semver.js" }, "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA=="], - - "@typescript-eslint/visitor-keys/eslint-visitor-keys": ["eslint-visitor-keys@4.2.1", "", {}, "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ=="], - - "bhttp/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="], - - "bhttp/extend": ["extend@2.0.2", "", {}, "sha512-AgFD4VU+lVLP6vjnlNfF7OeInLTyeyckCNPEsuxz1vi786UuK/nk6ynPuhn/h+Ju9++TQyr5EpLRI14fc1QtTQ=="], - - "broken-link-checker/chalk": ["chalk@1.1.3", "", { "dependencies": { "ansi-styles": "^2.2.1", "escape-string-regexp": "^1.0.2", "has-ansi": "^2.0.0", "strip-ansi": "^3.0.0", "supports-color": "^2.0.0" } }, "sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A=="], - - "chokidar/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="], - - "combined-stream2/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="], - - "eslint-import-resolver-node/debug": ["debug@3.2.7", "", { "dependencies": { "ms": "^2.1.1" } }, "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ=="], - - "eslint-import-resolver-typescript/debug": ["debug@4.4.1", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ=="], - - "eslint-module-utils/debug": ["debug@3.2.7", "", { "dependencies": { "ms": "^2.1.1" } }, "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ=="], - - "eslint-plugin-import/debug": ["debug@3.2.7", "", { "dependencies": { "ms": "^2.1.1" } }, "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ=="], - - "eslint-plugin-react/resolve": ["resolve@2.0.0-next.5", "", { "dependencies": { "is-core-module": "^2.13.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": "bin/resolve" }, "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA=="], - - "eslint-plugin-react/semver": ["semver@6.3.1", "", { "bin": "bin/semver.js" }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], - - "espree/eslint-visitor-keys": ["eslint-visitor-keys@4.2.1", "", {}, "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ=="], - - "fast-glob/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="], - - "fdir/picomatch": ["picomatch@4.0.3", "", {}, "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q=="], - - "form-data2/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="], - - "glob/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="], - - "hast-util-from-html/parse5": ["parse5@7.1.2", "", { "dependencies": { "entities": "^4.4.0" } }, "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw=="], - - "hast-util-from-parse5/hastscript": ["hastscript@8.0.0", "", { "dependencies": { "@types/hast": "^3.0.0", "comma-separated-tokens": "^2.0.0", "hast-util-parse-selector": "^4.0.0", "property-information": "^6.0.0", "space-separated-tokens": "^2.0.0" } }, "sha512-dMOtzCEd3ABUeSIISmrETiKuyydk1w0pa+gE/uormcTpSYuaNJPbX1NU3JLyscSLjwAQM8bWMhhIlnCqnRvDTw=="], - - "hast-util-parse-selector/@types/hast": ["@types/hast@2.3.10", "", { "dependencies": { "@types/unist": "^2" } }, "sha512-McWspRw8xx8J9HurkVBfYj0xKoE25tOFlHGdx4MJ5xORQrMGZNqJhVQWaIbm6Oyla5kYOXtDiopzKRJzEOkwJw=="], - - "hast-util-to-jsx-runtime/style-to-object": ["style-to-object@1.0.6", "", { "dependencies": { "inline-style-parser": "0.2.3" } }, "sha512-khxq+Qm3xEyZfKd/y9L3oIWQimxuc4STrQKtQn8aSDRHb8mFgpukgX1hdzfrMEW6JCjyJ8p89x+IUMVnCBI1PA=="], - - "hastscript/@types/hast": ["@types/hast@2.3.10", "", { "dependencies": { "@types/unist": "^2" } }, "sha512-McWspRw8xx8J9HurkVBfYj0xKoE25tOFlHGdx4MJ5xORQrMGZNqJhVQWaIbm6Oyla5kYOXtDiopzKRJzEOkwJw=="], - - "is-bun-module/semver": ["semver@7.7.2", "", { "bin": "bin/semver.js" }, "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA=="], - - "mdast-util-find-and-replace/escape-string-regexp": ["escape-string-regexp@5.0.0", "", {}, "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw=="], - - "mdast-util-find-and-replace/unist-util-is": ["unist-util-is@6.0.0", "", { "dependencies": { "@types/unist": "^3.0.0" } }, "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw=="], - - "mdast-util-find-and-replace/unist-util-visit-parents": ["unist-util-visit-parents@6.0.1", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-is": "^6.0.0" } }, "sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw=="], - - "mdast-util-phrasing/unist-util-is": ["unist-util-is@6.0.0", "", { "dependencies": { "@types/unist": "^3.0.0" } }, "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw=="], - - "mz/object-assign": ["object-assign@4.1.1", "", {}, "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="], - - "next/postcss": ["postcss@8.4.31", "", { "dependencies": { "nanoid": "^3.3.6", "picocolors": "^1.0.0", "source-map-js": "^1.0.2" } }, "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ=="], - - "nopter/chalk": ["chalk@0.5.1", "", { "dependencies": { "ansi-styles": "^1.1.0", "escape-string-regexp": "^1.0.0", "has-ansi": "^0.1.0", "strip-ansi": "^0.3.0", "supports-color": "^0.2.0" } }, "sha512-bIKA54hP8iZhyDT81TOsJiQvR1gW+ZYSXFaZUAvoD4wCHdbHY2actmpTE4x344ZlFqHbvoxKOaESULTZN2gstg=="], - - "parent-module/callsites": ["callsites@3.1.0", "", {}, "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ=="], - - "parse-entities/@types/unist": ["@types/unist@2.0.11", "", {}, "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA=="], - - "path-scurry/lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="], - - "postcss-nested/postcss-selector-parser": ["postcss-selector-parser@6.1.2", "", { "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" } }, "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg=="], - - "prop-types/object-assign": ["object-assign@4.1.1", "", {}, "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="], - - "react-highlight/highlight.js": ["highlight.js@10.7.3", "", {}, "sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A=="], - - "readable-stream/isarray": ["isarray@1.0.0", "", {}, "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ=="], - - "refractor/@types/hast": ["@types/hast@2.3.10", "", { "dependencies": { "@types/unist": "^2" } }, "sha512-McWspRw8xx8J9HurkVBfYj0xKoE25tOFlHGdx4MJ5xORQrMGZNqJhVQWaIbm6Oyla5kYOXtDiopzKRJzEOkwJw=="], - - "rehype-code-titles/unist-util-visit": ["unist-util-visit@4.1.2", "", { "dependencies": { "@types/unist": "^2.0.0", "unist-util-is": "^5.0.0", "unist-util-visit-parents": "^5.1.1" } }, "sha512-MSd8OUGISqHdVvfY9TPhyK2VdUrPgxkUtWSuMHF6XAAFuL4LokseigBnZtPnJMu+FbynTkFNnFlyjxpVKujMRg=="], - - "sharp/semver": ["semver@7.7.2", "", { "bin": "bin/semver.js" }, "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA=="], - - "string-width/strip-ansi": ["strip-ansi@7.1.0", "", { "dependencies": { "ansi-regex": "^6.0.1" } }, "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ=="], - - "string-width-cjs/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], - - "string-width-cjs/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], - - "strip-ansi/ansi-regex": ["ansi-regex@2.1.1", "", {}, "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA=="], - - "strip-ansi-cjs/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], - - "tailwindcss/postcss-selector-parser": ["postcss-selector-parser@6.1.2", "", { "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" } }, "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg=="], - - "through2/readable-stream": ["readable-stream@1.0.34", "", { "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.1", "isarray": "0.0.1", "string_decoder": "~0.10.x" } }, "sha512-ok1qVCJuRkNmvebYikljxJA/UEsKwLl2nI1OmaqAu4/UE+h0wKCHok4XkL/gvi39OacXvw59RJUOFUkDib2rHg=="], - - "tinyglobby/picomatch": ["picomatch@4.0.3", "", {}, "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q=="], - - "ts-node/arg": ["arg@4.1.3", "", {}, "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA=="], - - "unist-util-filter/unist-util-is": ["unist-util-is@6.0.0", "", { "dependencies": { "@types/unist": "^3.0.0" } }, "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw=="], - - "unist-util-filter/unist-util-visit-parents": ["unist-util-visit-parents@6.0.1", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-is": "^6.0.0" } }, "sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw=="], - - "unist-util-remove/@types/unist": ["@types/unist@2.0.11", "", {}, "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA=="], - - "unist-util-remove/unist-util-is": ["unist-util-is@5.2.1", "", { "dependencies": { "@types/unist": "^2.0.0" } }, "sha512-u9njyyfEh43npf1M+yGKDGVPbY/JWEemg5nH05ncKPfi+kBbKBJoTdsogMu33uhytuLlv9y0O7GH7fEdwLdLQw=="], - - "unist-util-remove/unist-util-visit-parents": ["unist-util-visit-parents@5.1.3", "", { "dependencies": { "@types/unist": "^2.0.0", "unist-util-is": "^5.0.0" } }, "sha512-x6+y8g7wWMyQhL1iZfhIPhDAs7Xwbn9nRosDXl7qoPTSCy0yNxnKc+hWokFifWQIDGi154rdUqKvbCa4+1kLhg=="], - - "urlobj/object-assign": ["object-assign@4.1.1", "", {}, "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="], - - "win-release/semver": ["semver@5.7.2", "", { "bin": "bin/semver" }, "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g=="], - - "wrap-ansi/ansi-styles": ["ansi-styles@6.2.1", "", {}, "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug=="], - - "wrap-ansi/strip-ansi": ["strip-ansi@7.1.0", "", { "dependencies": { "ansi-regex": "^6.0.1" } }, "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ=="], - - "wrap-ansi-cjs/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], - - "wrap-ansi-cjs/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], - - "@babel/highlight/chalk/ansi-styles": ["ansi-styles@3.2.1", "", { "dependencies": { "color-convert": "^1.9.0" } }, "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA=="], - - "@babel/highlight/chalk/escape-string-regexp": ["escape-string-regexp@1.0.5", "", {}, "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg=="], - - "@babel/highlight/chalk/supports-color": ["supports-color@5.5.0", "", { "dependencies": { "has-flag": "^3.0.0" } }, "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow=="], - - "@eslint/eslintrc/js-yaml/argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="], - - "@isaacs/cliui/strip-ansi/ansi-regex": ["ansi-regex@6.1.0", "", {}, "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA=="], - - "@next/eslint-plugin-next/fast-glob/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="], - - "@typescript-eslint/typescript-estree/fast-glob/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="], - - "@typescript-eslint/typescript-estree/minimatch/brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="], - - "bhttp/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="], - - "broken-link-checker/chalk/ansi-styles": ["ansi-styles@2.2.1", "", {}, "sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA=="], - - "broken-link-checker/chalk/escape-string-regexp": ["escape-string-regexp@1.0.5", "", {}, "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg=="], - - "broken-link-checker/chalk/supports-color": ["supports-color@2.0.0", "", {}, "sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g=="], - - "combined-stream2/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="], - - "eslint-import-resolver-typescript/debug/ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="], - - "form-data2/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="], - - "glob/minimatch/brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="], - - "hast-util-from-parse5/hastscript/hast-util-parse-selector": ["hast-util-parse-selector@4.0.0", "", { "dependencies": { "@types/hast": "^3.0.0" } }, "sha512-wkQCkSYoOGCRKERFWcxMVMOcYE2K1AaNLU8DXS9arxnLOUEWbOXKXiJUNzEpqZ3JOKpnha3jkFrumEjVliDe7A=="], - - "hast-util-parse-selector/@types/hast/@types/unist": ["@types/unist@2.0.11", "", {}, "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA=="], - - "hast-util-to-jsx-runtime/style-to-object/inline-style-parser": ["inline-style-parser@0.2.3", "", {}, "sha512-qlD8YNDqyTKTyuITrDOffsl6Tdhv+UC4hcdAVuQsK4IMQ99nSgd1MIA/Q+jQYoh9r3hVUXhYh7urSRmXPkW04g=="], - - "hastscript/@types/hast/@types/unist": ["@types/unist@2.0.11", "", {}, "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA=="], - - "nopter/chalk/ansi-styles": ["ansi-styles@1.1.0", "", {}, "sha512-f2PKUkN5QngiSemowa6Mrk9MPCdtFiOSmibjZ+j1qhLGHHYsqZwmBMRF3IRMVXo8sybDqx2fJl2d/8OphBoWkA=="], - - "nopter/chalk/escape-string-regexp": ["escape-string-regexp@1.0.5", "", {}, "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg=="], - - "nopter/chalk/has-ansi": ["has-ansi@0.1.0", "", { "dependencies": { "ansi-regex": "^0.2.0" }, "bin": "cli.js" }, "sha512-1YsTg1fk2/6JToQhtZkArMkurq8UoWU1Qe0aR3VUHjgij4nOylSWLWAtBXoZ4/dXOmugfLGm1c+QhuD0JyedFA=="], - - "nopter/chalk/strip-ansi": ["strip-ansi@0.3.0", "", { "dependencies": { "ansi-regex": "^0.2.1" }, "bin": "cli.js" }, "sha512-DerhZL7j6i6/nEnVG0qViKXI0OKouvvpsAiaj7c+LfqZZZxdwZtv8+UiA/w4VUJpT8UzX0pR1dcHOii1GbmruQ=="], - - "nopter/chalk/supports-color": ["supports-color@0.2.0", "", { "bin": "cli.js" }, "sha512-tdCZ28MnM7k7cJDJc7Eq80A9CsRFAAOZUy41npOZCs++qSjfIy7o5Rh46CBk+Dk5FbKJ33X3Tqg4YrV07N5RaA=="], - - "refractor/@types/hast/@types/unist": ["@types/unist@2.0.11", "", {}, "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA=="], - - "rehype-code-titles/unist-util-visit/@types/unist": ["@types/unist@2.0.11", "", {}, "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA=="], - - "rehype-code-titles/unist-util-visit/unist-util-is": ["unist-util-is@5.2.1", "", { "dependencies": { "@types/unist": "^2.0.0" } }, "sha512-u9njyyfEh43npf1M+yGKDGVPbY/JWEemg5nH05ncKPfi+kBbKBJoTdsogMu33uhytuLlv9y0O7GH7fEdwLdLQw=="], - - "rehype-code-titles/unist-util-visit/unist-util-visit-parents": ["unist-util-visit-parents@5.1.3", "", { "dependencies": { "@types/unist": "^2.0.0", "unist-util-is": "^5.0.0" } }, "sha512-x6+y8g7wWMyQhL1iZfhIPhDAs7Xwbn9nRosDXl7qoPTSCy0yNxnKc+hWokFifWQIDGi154rdUqKvbCa4+1kLhg=="], - - "string-width-cjs/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], - - "string-width/strip-ansi/ansi-regex": ["ansi-regex@6.1.0", "", {}, "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA=="], - - "through2/readable-stream/isarray": ["isarray@0.0.1", "", {}, "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ=="], - - "through2/readable-stream/string_decoder": ["string_decoder@0.10.31", "", {}, "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ=="], - - "unist-util-remove/unist-util-is/@types/unist": ["@types/unist@2.0.11", "", {}, "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA=="], - - "unist-util-remove/unist-util-visit-parents/@types/unist": ["@types/unist@2.0.11", "", {}, "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA=="], - - "wrap-ansi-cjs/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], - - "wrap-ansi-cjs/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], - - "wrap-ansi/strip-ansi/ansi-regex": ["ansi-regex@6.1.0", "", {}, "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA=="], - - "@babel/highlight/chalk/ansi-styles/color-convert": ["color-convert@1.9.3", "", { "dependencies": { "color-name": "1.1.3" } }, "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg=="], - - "@babel/highlight/chalk/supports-color/has-flag": ["has-flag@3.0.0", "", {}, "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw=="], - - "nopter/chalk/has-ansi/ansi-regex": ["ansi-regex@0.2.1", "", {}, "sha512-sGwIGMjhYdW26/IhwK2gkWWI8DRCVO6uj3hYgHT+zD+QL1pa37tM3ujhyfcJIYSbsxp7Gxhy7zrRW/1AHm4BmA=="], - - "nopter/chalk/strip-ansi/ansi-regex": ["ansi-regex@0.2.1", "", {}, "sha512-sGwIGMjhYdW26/IhwK2gkWWI8DRCVO6uj3hYgHT+zD+QL1pa37tM3ujhyfcJIYSbsxp7Gxhy7zrRW/1AHm4BmA=="], - - "rehype-code-titles/unist-util-visit/unist-util-is/@types/unist": ["@types/unist@2.0.11", "", {}, "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA=="], - - "rehype-code-titles/unist-util-visit/unist-util-visit-parents/@types/unist": ["@types/unist@2.0.11", "", {}, "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA=="], - - "@babel/highlight/chalk/ansi-styles/color-convert/color-name": ["color-name@1.1.3", "", {}, "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="], - } -} From 21261cd5a453b20ca0556fb19456e6869eb4eb6e Mon Sep 17 00:00:00 2001 From: miguelrk Date: Sun, 10 Aug 2025 13:52:11 +0200 Subject: [PATCH 28/28] Update contents/docs/deployment.mdx MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Kristóf Dombi --- contents/docs/deployment.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contents/docs/deployment.mdx b/contents/docs/deployment.mdx index 08adb446..85777cf8 100644 --- a/contents/docs/deployment.mdx +++ b/contents/docs/deployment.mdx @@ -462,7 +462,7 @@ On the configuration screen, you will set up the necessary resources, networking Under the **Resources** section, it is critical to allocate enough memory. `zero-cache` can be memory-intensive during startup. - **RAM**: Set to at least **2 GB**. -- **vCPU**: Set to at least **1 vCPU**. +- **vCPU**: Set to at least **0.5 vCPU**. **Note:** Running with less than 2GB of RAM may cause the deployment to fail with an Out-Of-Memory (OOM) error (exit code 137). The process may fail silently and enter a restart loop, making it difficult to debug.

- Zero is currently in public alpha. It's got a few rough edges, and you - have to deploy it yourself, but it's already remarkably fun. We're - using it ourselves for Zero's{' '} + Zero is currently in public alpha. It's got a few rough edges, and + you have to deploy it yourself, but it's already remarkably fun. + We're using it ourselves for Zero's{' '} official bug tracker {' '} @@ -170,7 +170,7 @@ export default function Home() {