diff --git a/.changeset/gentle-hoops-repeat.md b/.changeset/gentle-hoops-repeat.md new file mode 100644 index 0000000..a300477 --- /dev/null +++ b/.changeset/gentle-hoops-repeat.md @@ -0,0 +1,7 @@ +--- +"@btravstack/entity": patch +--- + +Point the package README at the new documentation site, +, instead of the Markdown files in the +repository. No code change. diff --git a/.github/actions/setup/action.yml b/.github/actions/setup/action.yml new file mode 100644 index 0000000..6620fee --- /dev/null +++ b/.github/actions/setup/action.yml @@ -0,0 +1,30 @@ +name: "Setup Node.js and pnpm" +description: "Setup Node.js and pnpm, install dependencies" + +# CI and Release call btravstack/config's reusable workflows, which do their own +# setup. This composite exists for Deploy Documentation, which runs its own +# steps in this repo and needs the same toolchain. + +runs: + using: "composite" + steps: + - name: Setup pnpm + uses: pnpm/action-setup@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version-file: .node-version + cache: pnpm + + - name: Setup Turbo Cache + uses: actions/cache@v4 + with: + path: .turbo + key: ${{ runner.os }}-turbo-${{ github.sha }} + restore-keys: | + ${{ runner.os }}-turbo- + + - name: Install dependencies + shell: bash + run: pnpm install --frozen-lockfile diff --git a/.github/workflows/deploy-docs.yml b/.github/workflows/deploy-docs.yml new file mode 100644 index 0000000..f5bf59c --- /dev/null +++ b/.github/workflows/deploy-docs.yml @@ -0,0 +1,62 @@ +name: Deploy Documentation + +# Publish the VitePress site once CI is green on main. Chaining off CI rather +# than pushing directly means the site is never built from a commit that does +# not compile, and the `github-pages` environment's branch policy sees `main` +# (a `workflow_run` event runs against the default branch). +on: + workflow_run: + workflows: ["CI"] + types: + - completed + branches: + - main + workflow_dispatch: + +permissions: + contents: read + pages: write + id-token: write + +concurrency: + # A Pages deploy replaces the whole site, so only one may be in flight. + group: pages + cancel-in-progress: false + +env: + FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true + +jobs: + build: + # A `workflow_run` fires on ANY CI conclusion (failure, cancelled); deploy + # only after a successful one. `workflow_dispatch` is unconditional. + if: ${{ github.event_name != 'workflow_run' || github.event.workflow_run.conclusion == 'success' }} + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v7 + + - name: Setup + uses: ./.github/actions/setup + + # The docs build runs TypeDoc (straight from packages/entity/src into + # docs/api/entity) and then VitePress — see docs/package.json. + - name: Build documentation + run: pnpm --filter ./docs exec turbo build + + - name: Upload artifact + uses: actions/upload-pages-artifact@v5 + with: + path: docs/.vitepress/dist + + deploy: + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + needs: build + runs-on: ubuntu-latest + name: Deploy + steps: + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v5 diff --git a/.gitignore b/.gitignore index aca1408..b166f8f 100644 --- a/.gitignore +++ b/.gitignore @@ -12,6 +12,13 @@ coverage/ # Turbo .turbo/ +# VitePress +docs/.vitepress/cache/ +docs/.vitepress/dist/ +# The package's API reference, generated by TypeDoc at build time +# (the hand-written docs/api/index.md overview is kept) +docs/api/entity/ + # Logs *.log diff --git a/CLAUDE.md b/CLAUDE.md index 66bf30a..fe24c06 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -10,18 +10,43 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co fallible operation returns an `unthrown` `Result` instead of throwing. -pnpm + turbo monorepo with a single package, `packages/entity`. Root scripts -delegate to turbo; package scripts are where the real commands live. +pnpm + turbo monorepo with two workspaces: the package, `packages/entity`, and +the documentation site, `docs`. Root scripts delegate to turbo; workspace +scripts are where the real commands live. ## Commands -Scripts are in `package.json`; the root ones delegate to turbo. Two things +Scripts are in `package.json`; the root ones delegate to turbo. Three things that are not derivable from there: - **The gate CI runs, in order**: `format --check`, `lint`, `typecheck`, `test`, `knip`, `build`. `typecheck` is three passes — the main `tsc`, the `.test-d.ts` pass, and the consumer declaration-emit pass. - **A single test file runs from inside `packages/entity`**, not the root. +- **The docs site runs from inside `docs`**: `pnpm --filter ./docs dev`. + `pnpm build` at the root builds it too, since it is a workspace. + +## The documentation site + +`docs/` is a VitePress site deployed to +by `.github/workflows/deploy-docs.yml` once CI is green on `main`. It is +organised by the four [Diátaxis](https://diataxis.fr/) modes — `tutorial/`, +`how-to/`, `reference/`, `explanation/` — with one shared sidebar across all +four so any page reaches any other. `docs/.vitepress/theme/custom.css` sets a +single `--accent` token; the shared `@btravstack/theme` derives every other +shade from it. + +Its build is `typedoc && vitepress build`. TypeDoc reads +`packages/entity/src/index.ts` straight through and writes `docs/api/entity/`, +which is git-ignored and regenerated every build — `docs/api/index.md` is the +one hand-written page under `api/`. + +TypeDoc runs from **`docs/`** rather than from `packages/entity/` (where the +other btravstack repos put it), with its own TypeScript from the named +`typedoc` catalog. That is forced, not stylistic: the default catalog's +`typescript: 7.0.2` is the native port and ships no JS compiler API, so TypeDoc +cannot run against it. Measured — the reason is inline in +`pnpm-workspace.yaml`. ## Architecture diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 421059d..3bf7376 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -29,11 +29,35 @@ pnpm lint # oxlint pnpm typecheck # tsc (incl. type-level tests) pnpm test # vitest pnpm knip # dead code / unused deps -pnpm build # tsdown dual CJS/ESM + d.ts +pnpm build # tsdown dual CJS/ESM + d.ts, and the docs site ``` Run `pnpm format` (no `--check`) to auto-fix formatting. +### The documentation site + +`docs/` is a workspace of its own — a [VitePress](https://vitepress.dev) site +organised by the four [Diátaxis](https://diataxis.fr/) modes (Tutorial, How-to, +Reference, Explanation), deployed to + by `.github/workflows/deploy-docs.yml` +once CI is green on `main`. + +```sh +pnpm --filter ./docs dev # local preview with hot reload +pnpm --filter ./docs build # what CI and the deploy build +``` + +The build is `typedoc && vitepress build`. TypeDoc reads +`packages/entity/src/index.ts` and writes `docs/api/entity/` (git-ignored, +regenerated every build); `docs/api/index.md` is the one hand-written page +there. + +TypeDoc runs from **`docs/`**, not from `packages/entity/` as it does in the +other btravstack repos, and with its own TypeScript. That is forced, not +stylistic: the catalog's `typescript: 7.0.2` is the native port, which ships no +JS compiler API for TypeDoc to drive. The named `typedoc` catalog in +`pnpm-workspace.yaml` pins 6.0.3 for that one job, with the reason inline. + ### Type-level tests Behaviour that only shows up at the type level — the construction seal, the @@ -69,8 +93,8 @@ types, while the plain `tsc` pass is `noEmit` from the shared base. ## Design rules (binding) -`docs/reference.md` documents the public behaviour and `docs/explanation.md` -the rationale behind it; many of those rules were measured against a specific +`docs/reference/` documents the public behaviour and `docs/explanation/` the +rationale behind it; many of those rules were measured against a specific compiler/library version, not assumed. Where a source comment records a measurement (a TS diagnostic code, a specific library's output), treat it as a regression guard, not decoration — verify diff --git a/README.md b/README.md index 662b698..ac65e2e 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ [![TypeScript](https://img.shields.io/badge/TypeScript-7.0-blue?logo=typescript)](https://www.typescriptlang.org/) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) -[**Reference**](./docs/reference.md) · [**Explanation**](./docs/explanation.md) · [**How-to guides**](./docs/how-to) +[**Documentation**](https://btravstack.github.io/entity/) · [**Getting started**](https://btravstack.github.io/entity/tutorial/getting-started) · [**Reference**](https://btravstack.github.io/entity/reference/declaration) · [**Why entity?**](https://btravstack.github.io/entity/explanation/why-entity) @@ -67,7 +67,8 @@ pnpm add @btravstack/entity zod unthrown @unthrown/standard-schema ``` `zod`, `unthrown` and `@unthrown/standard-schema` are **peer dependencies** — -install all four. ([Why](./docs/explanation.md#peer-dependencies).) +install all four. +([Why](https://btravstack.github.io/entity/explanation/peer-dependencies).) ## A worked example @@ -146,13 +147,14 @@ existing one. ## Documentation -- **[Reference](./docs/reference.md)** — every member, option and type, with signatures. -- **[Explanation](./docs/explanation.md)** — why it is built this way: sealed construction, deep immutability, no I/O, why entities are not subclassable. -- **How-to guides** - - [Expose an HTTP contract](./docs/how-to/http-contract.md) - - [Persist and rehydrate](./docs/how-to/persist-and-rehydrate.md) - - [Model an aggregate](./docs/how-to/model-an-aggregate.md) - - [Test domain logic](./docs/how-to/test-domain-logic.md) +**[btravstack.github.io/entity](https://btravstack.github.io/entity/)** — built +with VitePress from [`docs/`](./docs), and organised by the four +[Diátaxis](https://diataxis.fr/) modes: + +- **[Tutorial](https://btravstack.github.io/entity/tutorial/getting-started)** — from nothing to a working entity, one step at a time. +- **How-to guides** — [expose an HTTP contract](https://btravstack.github.io/entity/how-to/http-contract) · [persist and rehydrate](https://btravstack.github.io/entity/how-to/persist-and-rehydrate) · [model an aggregate](https://btravstack.github.io/entity/how-to/model-an-aggregate) · [test domain logic](https://btravstack.github.io/entity/how-to/test-domain-logic) +- **[Reference](https://btravstack.github.io/entity/reference/declaration)** — every member, option and type, with signatures. Plus the [generated API reference](https://btravstack.github.io/entity/api/). +- **[Explanation](https://btravstack.github.io/entity/explanation/why-entity)** — why it is built this way: sealed construction, deep immutability, no I/O, why entities are not subclassable. ## Development diff --git a/docs/.vitepress/config.ts b/docs/.vitepress/config.ts new file mode 100644 index 0000000..39467cd --- /dev/null +++ b/docs/.vitepress/config.ts @@ -0,0 +1,282 @@ +import { defineConfig } from "vitepress"; + +const SITE_DESCRIPTION = + "A domain-entity builder on zod v4: branded fields, immutable data, sealed construction, and Result instead of throws."; + +const BASE = "/entity/"; +const SITE_URL = `https://btravstack.github.io${BASE}`; + +// The guide is structured by the four Diátaxis modes (https://diataxis.fr/): a +// learning-oriented Tutorial, task-oriented How-to guides, information-oriented +// Reference, and understanding-oriented Explanation. One shared sidebar carries +// all four so any page can reach any other. +const GUIDE_SIDEBAR = [ + { + text: "Tutorial", + items: [{ text: "Getting started", link: "/tutorial/getting-started" }], + }, + { + text: "How-to guides", + items: [ + { text: "Expose an HTTP contract", link: "/how-to/http-contract" }, + { text: "Persist and rehydrate", link: "/how-to/persist-and-rehydrate" }, + { text: "Model an aggregate", link: "/how-to/model-an-aggregate" }, + { text: "Test domain logic", link: "/how-to/test-domain-logic" }, + ], + }, + { + text: "Reference", + items: [ + { text: "Declaring an entity", link: "/reference/declaration" }, + { text: "Schema members", link: "/reference/schemas" }, + { text: "Entry points", link: "/reference/entry-points" }, + { text: "Errors", link: "/reference/errors" }, + { text: "Helper types", link: "/reference/types" }, + { text: "API reference", link: "/api/" }, + ], + }, + { + text: "Explanation", + items: [ + { text: "Why entity?", link: "/explanation/why-entity" }, + { text: "No I/O, by design", link: "/explanation/no-io" }, + { text: "Sealed construction", link: "/explanation/sealed-construction" }, + { text: "Immutability", link: "/explanation/immutability" }, + { text: "Why computed re-derives", link: "/explanation/computed-fields" }, + { text: "Tags and identity", link: "/explanation/tags-and-identity" }, + { text: "Errors are values", link: "/explanation/errors-are-values" }, + { text: "Peer dependencies", link: "/explanation/peer-dependencies" }, + ], + }, +]; + +// https://vitepress.dev/reference/site-config +export default defineConfig({ + title: "entity", + description: SITE_DESCRIPTION, + base: BASE, + lang: "en-US", + cleanUrls: true, + + // `docs/superpowers/` is local design scratch — git-ignored, and not part of + // the published site. Without this VitePress renders whatever happens to be + // sitting there into a page and a sitemap entry. + srcExclude: ["superpowers/**"], + + // The API reference under /api/entity/ is generated by TypeDoc and copied in at + // build time; its cross-references use relative links TypeDoc resolves itself. + ignoreDeadLinks: [/^\/api\//, /^\.\/index$/, /^\.\/[a-z-]+$/, /^\.\.\//], + + sitemap: { + hostname: SITE_URL, + }, + + // Per-page canonical URL + Open Graph / Twitter title & description, so every + // page shares a correct preview and avoids duplicate-content ambiguity. + transformPageData(pageData) { + if (!pageData.relativePath.endsWith(".md")) { + return; + } + + const normalizedPath = pageData.relativePath.replace(/^\/+/, ""); + // cleanUrls is true, so the public URL has no `.html` extension: strip + // `index.md` to the directory and any other `.md` to the bare route. + const canonicalUrl = `${SITE_URL}${normalizedPath}` + .replace(/index\.md$/, "") + .replace(/\.md$/, ""); + + pageData.frontmatter ??= {}; + pageData.frontmatter.head ??= []; + + // The /api/ pages (except the hand-written overview) are TypeDoc output copied + // in at build time — they have no source file in the repo, so "Edit this page" + // would 404. docs/api/index.md is the one committed file there. + if (pageData.relativePath.startsWith("api/") && pageData.relativePath !== "api/index.md") { + pageData.frontmatter.editLink = false; + } + + pageData.frontmatter.head.push(["link", { rel: "canonical", href: canonicalUrl }]); + + const pageTitle = pageData.title || pageData.frontmatter.title || "entity"; + const pageDescription = + pageData.description || pageData.frontmatter.description || SITE_DESCRIPTION; + + pageData.frontmatter.head.push( + ["meta", { property: "og:url", content: canonicalUrl }], + ["meta", { property: "og:title", content: pageTitle }], + ["meta", { property: "og:description", content: pageDescription }], + ["meta", { name: "twitter:title", content: pageTitle }], + ["meta", { name: "twitter:description", content: pageDescription }], + ); + }, + + themeConfig: { + logo: { light: "/logo-light.svg", dark: "/logo-dark.svg" }, + + nav: [ + // The guide is organised by the four Diátaxis modes; the dropdown links + // the entry page of each. See the sidebar for the full contents. + { + text: "Guide", + items: [ + { text: "Tutorial", link: "/tutorial/getting-started" }, + { text: "How-to guides", link: "/how-to/http-contract" }, + { text: "Reference", link: "/reference/declaration" }, + { text: "Explanation", link: "/explanation/why-entity" }, + ], + }, + { text: "API", link: "/api/" }, + { + text: "Changelog", + link: "https://github.com/btravstack/entity/releases", + }, + // Back to the btravstack hub (links the docs up to the landing page). + { text: "btravstack", link: "https://btravstack.github.io/" }, + ], + + sidebar: { + // One shared sidebar across all four Diátaxis sections, so a reader can + // move between Tutorial / How-to / Reference / Explanation from any page. + ...Object.fromEntries( + ["/tutorial/", "/how-to/", "/reference/", "/explanation/"].map((prefix) => [ + prefix, + GUIDE_SIDEBAR, + ]), + ), + "/api/": [ + { + text: "API Reference", + items: [ + { text: "Overview", link: "/api/" }, + { text: "@btravstack/entity", link: "/api/entity/" }, + ], + }, + ], + }, + + socialLinks: [ + { icon: "github", link: "https://github.com/btravstack/entity" }, + { icon: "npm", link: "https://www.npmjs.com/package/@btravstack/entity" }, + ], + + footer: { + message: "Released under the MIT License.", + copyright: `Copyright © ${new Date().getFullYear()} Benoit TRAVERS`, + }, + + search: { + provider: "local", + }, + + // The reference pages are dense with `###`-level members; surfacing them in + // the right-rail outline is what makes them navigable. + outline: { level: [2, 3] }, + + editLink: { + pattern: "https://github.com/btravstack/entity/edit/main/docs/:path", + text: "Edit this page on GitHub", + }, + }, + + vite: { + // @btravstack/theme's entry imports `vitepress/theme` (which pulls in `.css`) + // and its own `style.css`. VitePress externalizes node_modules deps in the SSR + // build, so Node's ESM loader would hit those `.css` files and throw + // ERR_UNKNOWN_FILE_EXTENSION. Bundling the theme through Vite handles the CSS. + ssr: { noExternal: ["@btravstack/theme"] }, + }, + + head: [ + ["link", { rel: "icon", type: "image/svg+xml", href: `${BASE}logo.svg` }], + ["meta", { name: "author", content: "Benoit TRAVERS" }], + ["meta", { name: "robots", content: "index, follow" }], + ["meta", { name: "application-name", content: "entity" }], + [ + "meta", + { + name: "keywords", + content: + "typescript, zod, entity, domain-driven design, ddd, value object, immutable, branded types, json schema, errors as values, result, unthrown", + }, + ], + // Open Graph — og:title/description/url are added per page in transformPageData + ["meta", { property: "og:type", content: "website" }], + ["meta", { property: "og:site_name", content: "entity" }], + ["meta", { property: "og:locale", content: "en_US" }], + ["meta", { property: "og:image", content: `${SITE_URL}logo-light.svg` }], + ["meta", { property: "og:image:type", content: "image/svg+xml" }], + [ + "meta", + { + property: "og:image:alt", + content: "entity — a domain-entity builder for TypeScript, on zod v4", + }, + ], + // Twitter Card + ["meta", { name: "twitter:card", content: "summary" }], + ["meta", { name: "twitter:image", content: `${SITE_URL}logo-light.svg` }], + [ + "meta", + { + name: "twitter:image:alt", + content: "entity — a domain-entity builder for TypeScript, on zod v4", + }, + ], + // JSON-LD structured data for better SEO + [ + "script", + { type: "application/ld+json" }, + JSON.stringify({ + "@context": "https://schema.org", + "@type": "SoftwareApplication", + name: "@btravstack/entity", + description: SITE_DESCRIPTION, + applicationCategory: "DeveloperApplication", + operatingSystem: "Cross-platform", + offers: { + "@type": "Offer", + price: "0", + priceCurrency: "USD", + }, + url: SITE_URL, + author: { + "@type": "Person", + name: "Benoit TRAVERS", + }, + programmingLanguage: { + "@type": "ComputerLanguage", + name: "TypeScript", + url: "https://www.typescriptlang.org/", + }, + keywords: "TypeScript, zod, domain-driven design, entity, immutability, Result", + }), + ], + // WebSite JSON-LD for proper site name display in Google search + [ + "script", + { type: "application/ld+json" }, + JSON.stringify({ + "@context": "https://schema.org", + "@type": "WebSite", + name: "entity", + url: SITE_URL, + }), + ], + // Organization JSON-LD for logo display in Google search + [ + "script", + { type: "application/ld+json" }, + JSON.stringify({ + "@context": "https://schema.org", + "@type": "Organization", + name: "entity", + url: SITE_URL, + logo: { + "@type": "ImageObject", + url: `${SITE_URL}logo.svg`, + }, + sameAs: ["https://github.com/btravstack/entity"], + }), + ], + ], +}); diff --git a/docs/.vitepress/theme/custom.css b/docs/.vitepress/theme/custom.css new file mode 100644 index 0000000..6b96f33 --- /dev/null +++ b/docs/.vitepress/theme/custom.css @@ -0,0 +1,59 @@ +/* entity accent — the mascotte's blush pink. The shared @btravstack/theme + * derives every accent shade (deep/hover/soft/washes/hero glow/feature icons/AA + * text) from this single token, including the darkened --text-accent that keeps + * accent-coloured text readable on the light canvas. */ +:root { + --accent: #ee9cc4; +} + +/* Hero name in the package accent — the BtravStack multi-accent rule: the + * canvas stays neutral, the product glows in its own color (AA via + * --text-accent, which darkens on light). */ +:root:root { + --vp-home-hero-name-color: var(--text-accent); +} + +/* Home-hero background glyph — the project's motif behind the hero: a record + * card with its fields, stamped validated. Painted in --accent through a mask, + * so it always tracks the accent token; the SVG is base64-encoded so no CSS + * minifier can mangle it. */ +.VPHome { + position: relative; + isolation: isolate; + /* content-column width, and the gutter from the viewport edge in to it — + defined once so the glow and glyph stay anchored to the same column. */ + --btv-col: 1152px; + --btv-gutter: max(0px, calc((100% - var(--btv-col)) / 2)); +} +.VPHome::after { + content: ""; + position: absolute; + top: 8px; + left: var(--btv-gutter); + right: var(--btv-gutter); + aspect-ratio: 500 / 300; + background-color: var(--accent); + -webkit-mask: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA1MDAgMzAwIiBmaWxsPSJub25lIj48cmVjdCB4PSIxNDAiIHk9IjUyIiB3aWR0aD0iMjIwIiBoZWlnaHQ9IjE0NiIgcng9IjE2IiBzdHJva2U9IiNmZmYiIHN0cm9rZS13aWR0aD0iMiIvPjxnIHN0cm9rZT0iI2ZmZiIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiPjxwYXRoIGQ9Ik0xNzIsOTYgSDI2MiIvPjxwYXRoIGQ9Ik0xNzIsMTI0IEgzMDIiLz48cGF0aCBkPSJNMTcyLDE1MiBIMjMyIi8+PC9nPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKDM0OCwxODYpIHJvdGF0ZSgtMTQpIiBzdHJva2U9IiNmZmYiIGZpbGw9Im5vbmUiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCI+PGNpcmNsZSByPSIzMCIgc3Ryb2tlLXdpZHRoPSIyLjQiIHN0cm9rZS1kYXNoYXJyYXk9IjQwIDcgNTIgNyA1OCA3Ii8+PGNpcmNsZSByPSIyMC41IiBzdHJva2Utd2lkdGg9IjEuNSIvPjxwYXRoIGQ9Ik0tOCwwLjYgTC0yLjcsNi4yIEw4LjksLTYuNiIgc3Ryb2tlLXdpZHRoPSIyLjQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiLz48L2c+PHRleHQgeD0iMTQwIiB5PSIyNDgiIGZvbnQtZmFtaWx5PSJtb25vc3BhY2UiIGZvbnQtc2l6ZT0iMTUiIGZpbGw9IiNmZmYiPkVudGl0eSgiT3JnYW5pemF0aW9uIik8L3RleHQ+PC9zdmc+") + no-repeat top center / contain; + mask: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA1MDAgMzAwIiBmaWxsPSJub25lIj48cmVjdCB4PSIxNDAiIHk9IjUyIiB3aWR0aD0iMjIwIiBoZWlnaHQ9IjE0NiIgcng9IjE2IiBzdHJva2U9IiNmZmYiIHN0cm9rZS13aWR0aD0iMiIvPjxnIHN0cm9rZT0iI2ZmZiIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiPjxwYXRoIGQ9Ik0xNzIsOTYgSDI2MiIvPjxwYXRoIGQ9Ik0xNzIsMTI0IEgzMDIiLz48cGF0aCBkPSJNMTcyLDE1MiBIMjMyIi8+PC9nPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKDM0OCwxODYpIHJvdGF0ZSgtMTQpIiBzdHJva2U9IiNmZmYiIGZpbGw9Im5vbmUiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCI+PGNpcmNsZSByPSIzMCIgc3Ryb2tlLXdpZHRoPSIyLjQiIHN0cm9rZS1kYXNoYXJyYXk9IjQwIDcgNTIgNyA1OCA3Ii8+PGNpcmNsZSByPSIyMC41IiBzdHJva2Utd2lkdGg9IjEuNSIvPjxwYXRoIGQ9Ik0tOCwwLjYgTC0yLjcsNi4yIEw4LjksLTYuNiIgc3Ryb2tlLXdpZHRoPSIyLjQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiLz48L2c+PHRleHQgeD0iMTQwIiB5PSIyNDgiIGZvbnQtZmFtaWx5PSJtb25vc3BhY2UiIGZvbnQtc2l6ZT0iMTUiIGZpbGw9IiNmZmYiPkVudGl0eSgiT3JnYW5pemF0aW9uIik8L3RleHQ+PC9zdmc+") + no-repeat top center / contain; + opacity: 0.14; + pointer-events: none; + z-index: -1; +} +@media (max-width: 768px) { + .VPHome::after { + display: none; + } +} + +/* The shared theme only enlarges the hero mark at >=960px; below that the + * mark's small intrinsic size leaves it tiny, so size it up for tablet/mobile + * too. */ +@media (max-width: 959px) { + .VPHero .image-src { + width: min(208px, 62vw); + height: min(208px, 62vw); + object-fit: contain; + } +} diff --git a/docs/.vitepress/theme/index.ts b/docs/.vitepress/theme/index.ts new file mode 100644 index 0000000..d0c50ff --- /dev/null +++ b/docs/.vitepress/theme/index.ts @@ -0,0 +1,5 @@ +import Theme from "@btravstack/theme"; + +import "./custom.css"; + +export default Theme; diff --git a/docs/api/index.md b/docs/api/index.md new file mode 100644 index 0000000..509aaba --- /dev/null +++ b/docs/api/index.md @@ -0,0 +1,30 @@ +# API reference + +Generated from the source with [TypeDoc](https://typedoc.org/) — every exported +symbol, with its signature and TSDoc. + +- **[`@btravstack/entity`](/api/entity/)** — `Entity`, the merged `Entity` + namespace, and the three seal names (`BaseInstance`, `ConstructionKey`, + `Sealed`) the published declarations force out. + +::: tip Looking for prose? +The generated pages document _signatures_. For what each member is **for**, with +worked examples, read the hand-written [Reference](/reference/declaration); for +_why_ the surface is shaped this way, read the +[Explanation](/explanation/why-entity). +::: + +## The shape of the surface + +`index.ts` exports exactly one name you write against: + +```ts +import { Entity } from "@btravstack/entity"; +``` + +`Entity.computed`, `Entity.invariant`, `Entity.union` and `Entity.InvalidEntity` +hang off it as values, and every public type lives in a merged +`declare namespace Entity`. A bare `computed` or `union` would be too generic to +take from a consumer's import scope, so nothing else is exported — with one +measured exception, [`BaseInstance` / `ConstructionKey` / +`Sealed`](/reference/types#the-seal-names). diff --git a/docs/explanation.md b/docs/explanation.md deleted file mode 100644 index 6360503..0000000 --- a/docs/explanation.md +++ /dev/null @@ -1,217 +0,0 @@ -# Explanation - -Why the package is built the way it is. Several of these record behaviour that -was **measured**, not assumed — the diagnostic codes are quoted so a future -change can re-check rather than re-litigate. - -> Snippets below assume these imports: -> -> ```ts -> import { z } from "zod"; -> import { match, P } from "unthrown"; -> import { Entity } from "@btravstack/entity"; -> ``` - -## What an entity is, and why this exists - -An entity is simultaneously four things: a **type** your domain code programs -against, a **validator** for data crossing a trust boundary, a **value with -behaviour** (methods, invariants), and something that **nests inside other -entities**. Most tools give you two or three at once — a validation library -gives a type and a validator; a plain class gives a type and behaviour — and -stitching the rest together by hand is exactly the repetitive, error-prone work -a library should absorb. - -[Effect's `Schema.Class`](https://www.effect.website/docs/v3/schema/classes) -gets all four right at once and is the closest prior art. This package targets -the same shape on top of **zod v4** and -**[Standard Schema](https://standardschema.dev)**, with entry points named for -the use case they serve rather than one generic `parse`. - -## The rule the design turns on - -**Contracts compose the four `ZodObject`s; domain code composes the class.** - -It comes from a real constraint in zod's schema-to-JSON-Schema conversion: a -schema carrying a `.transform()` — which is what turns parsed data into a class -instance — has no output representation. The class does exactly that, so -`z.toJSONSchema(Organization, { io: "output" })` throws by design, while the -four plain `ZodObject`s convert in both directions with no hand-written omit -lists. - -## No I/O, by design - -The package reads no clock and generates no id. A factory's generators, not an -internal `crypto.randomUUID()`/`Date.now()`, are how a domain-generated value -reaches an entity. - -The _rule_ — which fields the domain owns, and that a caller may never supply -them — lives in the declaration. The _sources_ are bound once at your -composition root. That keeps the entity pure, and lets a test bind fixed -generators instead of stubbing globals. - -Generators are functions, called once per create, so a factory built at startup -still yields a fresh id per entity. - -## Sealed construction - -`new SomeEntity(...)` does not compile. The constructor takes a `Sealed`, -and no outside code can produce a value assignable to it — so every instance -comes through `make`, `update` or a factory, which means the invariants have -run and the stored data is exactly what `output` describes. - -The seal is a type, not a runtime check, because a runtime guard would mean -throwing — which this package exists to avoid. - -Two alternatives were measured and rejected: - -- **`private constructor`** → `TS2675: Cannot extend a class 'Base'`. The - declaration form `class X extends Entity("X")(…)` stops compiling outright. -- **`protected constructor`** → seals correctly (`TS2674`) but breaks the - statics with `TS2684` — a protected constructor type is not assignable to a - public one — so `make` could only return the base class. - -The key is an **exported but unconstructable** `ConstructionKey` rather than a -module-private `unique symbol`. That matters for consumers: a `unique symbol` -in computed-key position cannot be named across a module boundary even when -exported, so any downstream library compiling with `declaration: true` failed -with `TS4020: 'extends' clause of exported class has or is using private name`. -A fixture in CI compiles a consumer with declaration emit against the built -types, so that cannot regress. - -## Immutability - -Data is immutable in both halves. Each field is installed non-writable, and its -value is **deep-frozen** — a shallow guard would leave `org.tags.push(…)` legal, -which could push an entity into a state its own invariants had already -rejected. The instance type is `DeepReadonly<…>`, not a shallow `Readonly<…>`, -so mutation is a compile error first and a `TypeError` only if a consumer casts -around the type system: - -```ts -org.slug = otherSlug; // ✗ compile error — read-only property -(org as never as Record).slug = "hacked"; // TypeError - -// on a `Team` declared with `tags: z.array(Tag)` and `address: Address` -team.tags.push(tag); // ✗ compile error — tags is `readonly Tag[]` -(team.tags as never as string[]).push("hacked"); // TypeError — the array is frozen -team.address.city = "Paris"; // ✗ compile error — nested objects are readonly too -``` - -Locking the binding alone would not be enough: `writable: false` stops -`team.tags = [...]` but not `team.tags.push(...)`, and a shallow `Readonly` -types an array field as a mutable `Tag[]`, because `z.infer` of `z.array(Tag)` -is `Tag[]`. Both halves matter — the second is what lets `invariants` mean -anything after construction. - -What the freeze covers is deliberately narrow: arrays and plain objects are -frozen and recursed into; `Date` is frozen as a leaf; `Map`, `Set` and typed -arrays are left alone, because freezing those is either theatre (a frozen `Map` -still accepts `.set`) or destructive. A field whose schema yields a live mutable -object is outside the guarantee. - -A `z.custom(...)`/`z.instanceof(...)` field is skipped **by its schema**, not by -what the value turns out to look like at runtime. That distinction is the whole -point: `z.custom` hands back the caller's own reference, and a plain-object one -is indistinguishable at runtime from decoded data. Deciding by runtime shape -froze objects the caller still owned, so their next write threw. Only the -declaration knows which values were passed through, so that is where the -decision is made. - -`Object.freeze(this)` is **not** used and cannot be: a class body's field -initialisers run after `super()` returns, so the instance itself must stay -extensible. - -## Why `computed` re-derives - -A computed field reads the declared fields and is re-derived on `make` and -`update` alike, rather than computed once and stored. - -The alternative was tried and is quietly wrong. Deriving `fullName` from -`first` + `last` once, then renaming the person, leaves `fullName` frozen at the -old value — and since a derived field is not patchable, unrepairable. Every -plausible use (`totalCents`, `tier`, `wordCount`, `durationDays`) has that shape. - -Re-deriving also makes `make` self-healing: a row written before a derivation -changed, or before the field existed at all, is corrected on read rather than -trusted. That is why `make` validates against `input` and not `output` — -validating stored computed values would reject exactly the rows it is meant to -repair. - -**Why not a getter?** Because a getter carries no schema. It cannot appear in -`output`, cannot generate JSON Schema, and is skipped by `toJSON()` — it lives -on the prototype, not in the data. The rule: - -| | use | -| -------------------------------------------------- | ---------- | -| derived, needed in the response body / JSON Schema | `computed` | -| derived, domain-only behaviour | a getter | - -## Entities are not subclassable - -`class Sub extends Organization {}` fails at construction with a `Defect`. - -A bare subclass is an alias you cannot tell apart from what it aliases: same -tag, same schemas, indistinguishable under `equals`. `extend` exists for the -legitimate case and produces a genuine entity with its own identity. - -The prohibition is runtime-only. TypeScript has no `final`, and the constructor -accessibility modifiers that would express it break the declaration form or the -statics (see [Sealed construction](#sealed-construction)). So the declaration -compiles and reports on first construction. - -Redeclaring a data field in a subclass is caught earlier — TypeScript reports -`TS4114` under `noImplicitOverride`, and the field is non-configurable, so -construction fails with `TypeError: Cannot redefine property`. - -## `_tag` is runtime-only - -Every instance carries a non-enumerable `_tag`, for pattern matching with -`unthrown`'s `P.tag(...)`: - -```ts -match(member) - .with(P.tag("User"), (u) => u.email) - .with(P.tag("ServiceAccount"), (s) => s.label) - .exhaustive(); -``` - -It never reaches the wire — absent from every schema, from `toJSON()`, -`JSON.stringify`, `Object.keys` and spread. That has a direct consequence: a -union that must survive a JSON round trip **cannot** discriminate on `_tag`, -because it is not there after serialisation. Declare the discriminant as an -ordinary domain field; `Entity.union` takes that field. - -The two are not redundant. A brand is per-field and type-only; the tag is -per-entity and runtime-present, which is what makes it matchable. `entityName` -is the same string read from the class rather than an instance — the only path -for code holding the class and no instance. - -## Errors are values, and defects are separate - -Every fallible entry point returns `Result`. Bad input is -modelled; a bug in domain code is not. - -The line: a field failing its schema or a broken invariant is `InvalidEntity` — -expected, caller-caused. A `computed` function throwing or producing data its -own schema rejects is a **defect**: `computed` is pure, total and typed, so a -violation is a bug rather than bad input. An async generator rejecting is a -defect for the same reason — infrastructure failing is not bad domain input. - -A defect is never folded into a validation issue, even when the entity is -nested inside another schema. An unmodelled bug stays distinguishable from bad -caller input all the way to the edge. - -Issues are carried **structured**, exactly as the validator produced them, so -keying a field-level error response is a `path` lookup rather than a string -parse. - -## Peer dependencies - -`zod`, `unthrown` and `@unthrown/standard-schema` are peer dependencies, not -bundled ones. The package hands back real `ZodObject`s and real `Result`s built -from _your_ copies. If it pinned its own, a consumer would end up with two -copies of zod in the tree, and identity checks — `result instanceof Result`, -`schema instanceof z.ZodType`, or composing an entity into your own -`z.object({...})` — can silently misbehave across the boundary between two -copies of the same package. diff --git a/docs/explanation/computed-fields.md b/docs/explanation/computed-fields.md new file mode 100644 index 0000000..4ed8dde --- /dev/null +++ b/docs/explanation/computed-fields.md @@ -0,0 +1,34 @@ +--- +title: Why computed re-derives +description: Why a derived field is recomputed on every construction instead of stored, why make validates against input, and when to use a getter instead. +--- + +# Why `computed` re-derives + +A computed field reads the declared fields and is re-derived on `make` and +`update` alike, rather than computed once and stored. + +The alternative was tried and is quietly wrong. Deriving `fullName` from +`first` + `last` once, then renaming the person, leaves `fullName` frozen at the +old value — and since a derived field is not patchable, unrepairable. Every +plausible use (`totalCents`, `tier`, `wordCount`, `durationDays`) has that shape. + +Re-deriving also makes `make` self-healing: a row written before a derivation +changed, or before the field existed at all, is corrected on read rather than +trusted. That is why `make` validates against `input` and not `output` — +validating stored computed values would reject exactly the rows it is meant to +repair. + +## Why not a getter? + +Because a getter carries no schema. It cannot appear in `output`, cannot +generate JSON Schema, and is skipped by `toJSON()` — it lives on the prototype, +not in the data. The rule: + +| | use | +| -------------------------------------------------- | ---------- | +| derived, needed in the response body / JSON Schema | `computed` | +| derived, domain-only behaviour | a getter | + +[Persist and rehydrate](/how-to/persist-and-rehydrate#computed-columns-heal-themselves) +shows the self-healing read against a real table. diff --git a/docs/explanation/errors-are-values.md b/docs/explanation/errors-are-values.md new file mode 100644 index 0000000..9a116d2 --- /dev/null +++ b/docs/explanation/errors-are-values.md @@ -0,0 +1,27 @@ +--- +title: Errors are values, and defects are separate +description: Where the line falls between bad caller input and a bug in domain code, and why the two never merge. +--- + +# Errors are values, and defects are separate + +Every fallible entry point returns `Result`. Bad input is +modelled; a bug in domain code is not. + +The line: a field failing its schema or a broken invariant is `InvalidEntity` — +expected, caller-caused. A `computed` function throwing or producing data its +own schema rejects is a **defect**: `computed` is pure, total and typed, so a +violation is a bug rather than bad input. An async generator rejecting is a +defect for the same reason — infrastructure failing is not bad domain input. + +A defect is never folded into a validation issue, even when the entity is +nested inside another schema. An unmodelled bug stays distinguishable from bad +caller input all the way to the edge. + +Issues are carried **structured**, exactly as the validator produced them, so +keying a field-level error response is a `path` lookup rather than a string +parse. + +[Errors](/reference/errors) tabulates which failure takes which channel; the +[unthrown docs](https://btravstack.github.io/unthrown/explanation/the-defect-channel) +explain the defect channel itself. diff --git a/docs/explanation/immutability.md b/docs/explanation/immutability.md new file mode 100644 index 0000000..0331b50 --- /dev/null +++ b/docs/explanation/immutability.md @@ -0,0 +1,49 @@ +--- +title: Immutability +description: Why both halves matter — non-writable bindings and a deep freeze — and exactly what the freeze does and does not cover. +--- + +# Immutability + +Data is immutable in both halves. Each field is installed non-writable, and its +value is **deep-frozen** — a shallow guard would leave `org.tags.push(…)` legal, +which could push an entity into a state its own invariants had already +rejected. The instance type is `DeepReadonly<…>`, not a shallow `Readonly<…>`, +so mutation is a compile error first and a `TypeError` only if a consumer casts +around the type system: + +```ts +org.slug = otherSlug; // ✗ compile error — read-only property +(org as never as Record).slug = "hacked"; // TypeError + +// on a `Team` declared with `tags: z.array(Tag)` and `address: Address` +team.tags.push(tag); // ✗ compile error — tags is `readonly Tag[]` +(team.tags as never as string[]).push("hacked"); // TypeError — the array is frozen +team.address.city = "Paris"; // ✗ compile error — nested objects are readonly too +``` + +Locking the binding alone would not be enough: `writable: false` stops +`team.tags = [...]` but not `team.tags.push(...)`, and a shallow `Readonly` +types an array field as a mutable `Tag[]`, because `z.infer` of `z.array(Tag)` +is `Tag[]`. Both halves matter — the second is what lets `invariants` mean +anything after construction. + +## What the freeze covers + +What the freeze covers is deliberately narrow: arrays and plain objects are +frozen and recursed into; `Date` is frozen as a leaf; `Map`, `Set` and typed +arrays are left alone, because freezing those is either theatre (a frozen `Map` +still accepts `.set`) or destructive. A field whose schema yields a live mutable +object is outside the guarantee. + +A `z.custom(...)`/`z.instanceof(...)` field is skipped **by its schema**, not by +what the value turns out to look like at runtime. That distinction is the whole +point: `z.custom` hands back the caller's own reference, and a plain-object one +is indistinguishable at runtime from decoded data. Deciding by runtime shape +froze objects the caller still owned, so their next write threw. Only the +declaration knows which values were passed through, so that is where the +decision is made. + +`Object.freeze(this)` is **not** used and cannot be: a class body's field +initialisers run after `super()` returns, so the instance itself must stay +extensible. diff --git a/docs/explanation/no-io.md b/docs/explanation/no-io.md new file mode 100644 index 0000000..fcc8b17 --- /dev/null +++ b/docs/explanation/no-io.md @@ -0,0 +1,36 @@ +--- +title: No I/O, by design +description: Why the package reads no clock and generates no id, and why generators are functions bound at the composition root. +--- + +# No I/O, by design + +The package reads no clock and generates no id. A factory's generators, not an +internal `crypto.randomUUID()`/`Date.now()`, are how a domain-generated value +reaches an entity. + +The _rule_ — which fields the domain owns, and that a caller may never supply +them — lives in the declaration. The _sources_ are bound once at your +composition root. That keeps the entity pure, and lets a test bind fixed +generators instead of stubbing globals. + +Generators are functions, called once per create, so a factory built at startup +still yields a fresh id per entity. + +```ts +// composition root +const createOrganization = Organization.factory({ + id: () => ids.next(), + createdAt: () => clock.now(), +}); + +// a test — no global stubbing, no fake timers +const createFixed = Organization.factory({ + id: () => FIXED_ID, + createdAt: () => FIXED_INSTANT, +}); +``` + +See [`factory` / `factoryAsync`](/reference/entry-points) for the signatures, and +[Test domain logic](/how-to/test-domain-logic#bind-fixed-generators-instead-of-stubbing-globals) +for the testing pattern this enables. diff --git a/docs/explanation/peer-dependencies.md b/docs/explanation/peer-dependencies.md new file mode 100644 index 0000000..e6e1c08 --- /dev/null +++ b/docs/explanation/peer-dependencies.md @@ -0,0 +1,20 @@ +--- +title: Peer dependencies +description: Why zod, unthrown and @unthrown/standard-schema are peers rather than bundled dependencies. +--- + +# Peer dependencies + +`zod`, `unthrown` and `@unthrown/standard-schema` are peer dependencies, not +bundled ones. The package hands back real `ZodObject`s and real `Result`s built +from _your_ copies. If it pinned its own, a consumer would end up with two +copies of zod in the tree, and identity checks — `result instanceof Result`, +`schema instanceof z.ZodType`, or composing an entity into your own +`z.object({...})` — can silently misbehave across the boundary between two +copies of the same package. + +So all four are installed together: + +```sh +pnpm add @btravstack/entity zod unthrown @unthrown/standard-schema +``` diff --git a/docs/explanation/sealed-construction.md b/docs/explanation/sealed-construction.md new file mode 100644 index 0000000..cbce82e --- /dev/null +++ b/docs/explanation/sealed-construction.md @@ -0,0 +1,48 @@ +--- +title: Sealed construction +description: Why new SomeEntity(…) does not compile, the two alternatives that were measured and rejected, and why entities are not subclassable. +--- + +# Sealed construction + +`new SomeEntity(...)` does not compile. The constructor takes a `Sealed`, +and no outside code can produce a value assignable to it — so every instance +comes through `make`, `update` or a factory, which means the invariants have +run and the stored data is exactly what `output` describes. + +The seal is a type, not a runtime check, because a runtime guard would mean +throwing — which this package exists to avoid. + +Two alternatives were measured and rejected: + +- **`private constructor`** → `TS2675: Cannot extend a class 'Base'`. The + declaration form `class X extends Entity("X")(…)` stops compiling outright. +- **`protected constructor`** → seals correctly (`TS2674`) but breaks the + statics with `TS2684` — a protected constructor type is not assignable to a + public one — so `make` could only return the base class. + +The key is an **exported but unconstructable** `ConstructionKey` rather than a +module-private `unique symbol`. That matters for consumers: a `unique symbol` +in computed-key position cannot be named across a module boundary even when +exported, so any downstream library compiling with `declaration: true` failed +with `TS4020: 'extends' clause of exported class has or is using private name`. +A fixture in CI compiles a consumer with declaration emit against the built +types, so that cannot regress. + +## Entities are not subclassable + +`class Sub extends Organization {}` fails at construction with a `Defect`. + +A bare subclass is an alias you cannot tell apart from what it aliases: same +tag, same schemas, indistinguishable under `equals`. +[`extend`](/reference/declaration#someentity-extend-tag-fields-options) exists +for the legitimate case and produces a genuine entity with its own identity. + +The prohibition is runtime-only. TypeScript has no `final`, and the constructor +accessibility modifiers that would express it break the declaration form or the +statics (see above). So the declaration compiles and reports on first +construction. + +Redeclaring a data field in a subclass is caught earlier — TypeScript reports +`TS4114` under `noImplicitOverride`, and the field is non-configurable, so +construction fails with `TypeError: Cannot redefine property`. diff --git a/docs/explanation/tags-and-identity.md b/docs/explanation/tags-and-identity.md new file mode 100644 index 0000000..c8a340a --- /dev/null +++ b/docs/explanation/tags-and-identity.md @@ -0,0 +1,31 @@ +--- +title: Tags and identity +description: Why every instance carries a runtime _tag that never reaches the wire, and why a serialisable union must discriminate on a domain field instead. +--- + +# Tags and identity + +Every instance carries a non-enumerable `_tag`, for pattern matching with +`unthrown`'s `P.tag(...)`: + +```ts +match(member) + .with(P.tag("User"), (u) => u.email) + .with(P.tag("ServiceAccount"), (s) => s.label) + .exhaustive(); +``` + +It never reaches the wire — absent from every schema, from `toJSON()`, +`JSON.stringify`, `Object.keys` and spread. That has a direct consequence: a +union that must survive a JSON round trip **cannot** discriminate on `_tag`, +because it is not there after serialisation. Declare the discriminant as an +ordinary domain field; [`Entity.union`](/reference/declaration#entity-union-discriminant-members) +takes that field. + +The two are not redundant. A brand is per-field and type-only; the tag is +per-entity and runtime-present, which is what makes it matchable. `entityName` +is the same string read from the class rather than an instance — the only path +for code holding the class and no instance. + +[Model an aggregate](/how-to/model-an-aggregate#model-a-union-of-entities) +declares such a union against a real payload. diff --git a/docs/explanation/why-entity.md b/docs/explanation/why-entity.md new file mode 100644 index 0000000..c69872f --- /dev/null +++ b/docs/explanation/why-entity.md @@ -0,0 +1,48 @@ +--- +title: Why entity? +description: What an entity actually is, why the four jobs belong in one declaration, and the rule the whole design turns on. +--- + +# Why entity? + +Why the package is built the way it is. Several pages in this section record +behaviour that was **measured**, not assumed — the diagnostic codes are quoted +so a future change can re-check rather than re-litigate. + +> Snippets in this section assume these imports: +> +> ```ts +> import { z } from "zod"; +> import { match, P } from "unthrown"; +> import { Entity } from "@btravstack/entity"; +> ``` + +## What an entity is, and why this exists + +An entity is simultaneously four things: a **type** your domain code programs +against, a **validator** for data crossing a trust boundary, a **value with +behaviour** (methods, invariants), and something that **nests inside other +entities**. Most tools give you two or three at once — a validation library +gives a type and a validator; a plain class gives a type and behaviour — and +stitching the rest together by hand is exactly the repetitive, error-prone work +a library should absorb. + +[Effect's `Schema.Class`](https://www.effect.website/docs/v3/schema/classes) +gets all four right at once and is the closest prior art. This package targets +the same shape on top of **zod v4** and +**[Standard Schema](https://standardschema.dev)**, with entry points named for +the use case they serve rather than one generic `parse`. + +## The rule the design turns on + +**Contracts compose the four `ZodObject`s; domain code composes the class.** + +It comes from a real constraint in zod's schema-to-JSON-Schema conversion: a +schema carrying a `.transform()` — which is what turns parsed data into a class +instance — has no output representation. The class does exactly that, so +`z.toJSONSchema(Organization, { io: "output" })` throws by design, while the +four plain `ZodObject`s convert in both directions with no hand-written omit +lists. + +[Expose an HTTP contract](/how-to/http-contract) is that rule applied end to +end; [Schema members](/reference/schemas) is what each of the four is for. diff --git a/docs/how-to/http-contract.md b/docs/how-to/http-contract.md index f85e7ab..a02af69 100644 --- a/docs/how-to/http-contract.md +++ b/docs/how-to/http-contract.md @@ -1,3 +1,8 @@ +--- +title: Expose an HTTP contract +description: Turn an entity into request and response schemas for a route, converted to JSON Schema in both directions, with no hand-written omit lists. +--- + # Expose an HTTP contract **Problem:** you have an entity and need request and response schemas for a diff --git a/docs/how-to/model-an-aggregate.md b/docs/how-to/model-an-aggregate.md index f2f76b9..b0bfc8a 100644 --- a/docs/how-to/model-an-aggregate.md +++ b/docs/how-to/model-an-aggregate.md @@ -1,3 +1,8 @@ +--- +title: Model an aggregate +description: Nest entities inside entities, span invariants across the boundary, and model a union of entities that survives a JSON round trip. +--- + # Model an aggregate **Problem:** one entity contains others — an order with a customer and line @@ -145,4 +150,4 @@ class PersonWithAge extends Person.extend("PersonWithAge")({ age: Age }) {} That produces a new entity with its own tag and identity — not a variant of `Person`, and not a subclass, which is -[refused](../explanation.md#entities-are-not-subclassable). +[refused](/explanation/sealed-construction#entities-are-not-subclassable). diff --git a/docs/how-to/persist-and-rehydrate.md b/docs/how-to/persist-and-rehydrate.md index 3a30482..e4a8852 100644 --- a/docs/how-to/persist-and-rehydrate.md +++ b/docs/how-to/persist-and-rehydrate.md @@ -1,3 +1,8 @@ +--- +title: Persist and rehydrate +description: Write an entity to a database with toJSON() and read it back with make(), without the storage layer knowing about entity internals. +--- + # Persist and rehydrate **Problem:** you need to write an entity to a database and read it back, diff --git a/docs/how-to/test-domain-logic.md b/docs/how-to/test-domain-logic.md index e74b365..ae0b55d 100644 --- a/docs/how-to/test-domain-logic.md +++ b/docs/how-to/test-domain-logic.md @@ -1,3 +1,8 @@ +--- +title: Test domain logic +description: Deterministic entity tests without stubbing Date.now or crypto.randomUUID, asserting on failures without try/catch. +--- + # Test domain logic **Problem:** entities involve ids and timestamps, and you want deterministic diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 0000000..cec8042 --- /dev/null +++ b/docs/index.md @@ -0,0 +1,102 @@ +--- +layout: home +title: entity — a domain-entity builder for TypeScript, on zod v4 +description: One declaration gives you a type, four request/response schemas, behaviour, and a class that is itself a zod schema. Nothing throws. + +hero: + name: "entity" + text: "Domain entities, declared once" + tagline: One declaration yields a type, four request/response schemas, behaviour, and a class that is itself a zod schema — with branded fields, immutable data, sealed construction, and Result instead of throws. + image: + light: /logo-light.svg + dark: /logo-dark.svg + alt: entity + actions: + - theme: brand + text: Get Started + link: /tutorial/getting-started + - theme: alt + text: Why entity? + link: /explanation/why-entity + - theme: alt + text: GitHub + link: https://github.com/btravstack/entity + +features: + - icon: { src: /icons/schemas.svg } + title: One declaration, four schemas + details: "input, output, createInput and updateInput are derived from one field map plus generated / immutable / computed. Plain ZodObjects, so they convert to JSON Schema in both directions — no hand-written omit lists." + - icon: { src: /icons/seal.svg } + title: Sealed and immutable + details: "new SomeEntity(…) does not compile. Every instance comes through make, update or a factory, so the invariants have run — and its data is deep-frozen, mutation a compile error first." + - icon: { src: /icons/nest.svg } + title: Entities nest in entities + details: "The class is itself a zod schema, so it drops into z.object({ owner: Organization }) as a field and still parses to a real instance, with its own behaviour and identity." + - icon: { src: /icons/result.svg } + title: Nothing throws + details: "Every fallible operation returns an unthrown Result carrying structured issues. A bug in your own domain code stays a separate defect, never folded into caller error." +--- + +## At a glance + +```ts +import { z } from "zod"; +import { Entity } from "@btravstack/entity"; + +const OrgId = z.uuid().brand("OrgId"); +const Slug = z.string().min(1).brand("Slug"); +const DisplayName = z.string().min(1).brand("DisplayName"); +const Instant = z.iso.datetime().brand("Instant"); +const Upper = z.string().min(1).brand("Upper"); + +class Organization extends Entity("Organization")( + { id: OrgId, slug: Slug, name: DisplayName, createdAt: Instant }, + { + generated: ["id", "createdAt"], + immutable: ["id", "createdAt", "slug"], + computed: { + shout: Entity.computed( + Upper, + (d) => d.name.toUpperCase() as z.infer, + ), + }, + invariants: [ + Entity.invariant( + (d) => d.name.length <= 80, + "name must be at most 80 characters", + ), + ], + }, +) { + get greeting(): string { + return `Welcome, ${this.name}`; + } +} + +// The package reads no clock and generates no id: bind the sources once, +// where your ports already live. +const createOrganization = Organization.factory({ + id: () => ids.next(), + createdAt: () => clock.now(), +}); + +const org = createOrganization({ slug, name }).getOrThrow(); +await db.insert(org.toJSON()); // exactly the stored shape — never `_tag` +const loaded = Organization.make(row).getOrThrow(); // rows, imports, event folds +const renamed = loaded.update({ name: next }).getOrThrow(); // a NEW entity +``` + +Failures are values, not exceptions: + +```ts +import { P } from "unthrown"; + +Organization.make({ ...row, name: "" }).match({ + ok: (o) => o, + errCases: (m) => m.with(P.tag("InvalidEntity"), (e) => e.issues), // [{ path: ["name"], … }] + defect: (cause) => report(cause), // a bug in domain code, kept separate +}); +``` + +The design rule the whole package turns on: **contracts compose the four plain +`ZodObject`s; domain code composes the class itself.** [Why](/explanation/why-entity). diff --git a/docs/package.json b/docs/package.json new file mode 100644 index 0000000..20bca3c --- /dev/null +++ b/docs/package.json @@ -0,0 +1,22 @@ +{ + "name": "@btravstack/entity-docs", + "private": true, + "description": "Documentation website for @btravstack/entity", + "license": "MIT", + "author": "Benoit TRAVERS ", + "type": "module", + "scripts": { + "build": "typedoc && vitepress build .", + "dev": "typedoc && vitepress dev .", + "preview": "vitepress preview ." + }, + "devDependencies": { + "@btravstack/theme": "catalog:", + "@btravstack/typedoc": "catalog:", + "@types/node": "catalog:", + "typedoc": "catalog:", + "typedoc-plugin-markdown": "catalog:", + "typescript": "catalog:typedoc", + "vitepress": "catalog:" + } +} diff --git a/docs/public/icons/nest.svg b/docs/public/icons/nest.svg new file mode 100644 index 0000000..3cf4dad --- /dev/null +++ b/docs/public/icons/nest.svg @@ -0,0 +1 @@ + diff --git a/docs/public/icons/result.svg b/docs/public/icons/result.svg new file mode 100644 index 0000000..2542241 --- /dev/null +++ b/docs/public/icons/result.svg @@ -0,0 +1 @@ + diff --git a/docs/public/icons/schemas.svg b/docs/public/icons/schemas.svg new file mode 100644 index 0000000..ec1db89 --- /dev/null +++ b/docs/public/icons/schemas.svg @@ -0,0 +1 @@ + diff --git a/docs/public/icons/seal.svg b/docs/public/icons/seal.svg new file mode 100644 index 0000000..6e062ef --- /dev/null +++ b/docs/public/icons/seal.svg @@ -0,0 +1 @@ + diff --git a/docs/public/logo.svg b/docs/public/logo.svg new file mode 100644 index 0000000..4aa0e63 --- /dev/null +++ b/docs/public/logo.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/docs/reference.md b/docs/reference.md deleted file mode 100644 index 273dddd..0000000 --- a/docs/reference.md +++ /dev/null @@ -1,274 +0,0 @@ -# Reference - -Every member of the public surface. For _why_ it is shaped this way, see -[Explanation](./explanation.md); for task recipes, see the -[how-to guides](./how-to/). - -> Snippets below assume these imports: -> -> ```ts -> import { z } from "zod"; -> import { match, P } from "unthrown"; -> import { Entity } from "@btravstack/entity"; -> ``` - -## `Entity(tag)(fields, options?)` - -Declares an entity. Curried on the tag so it reads next to the class name. - -```ts -class Organization extends Entity("Organization")(fields, options) {} -``` - -### `fields` - -A map of field name to schema. Every field must be **nominal** — a branded -schema, a narrow literal union, a boolean, or another entity class. A bare -`z.string()` is a compile error naming `DomainFieldMustBeBrandedOrAnEntity`. - -Four names are reserved, because an entity installs them on every instance: -`_tag`, `equals`, `toJSON`, `update`. Using one is a compile error naming -`FieldNameIsReservedByEntity`. - -### `options` - -| Option | Type | Effect | -| ------------ | ---------------------------------- | -------------------------------------------------------------------------------- | -| `generated` | `readonly (keyof fields)[]` | omitted from `createInput`; supplied by a factory's generators | -| `immutable` | `readonly (keyof output)[]` | omitted from `updateInput`; `update()` drops them even if smuggled in at runtime | -| `computed` | `{ [name]: Entity.ComputedField }` | derived fields; added to `output`, re-derived on every construction | -| `invariants` | `readonly Entity.Invariant[]` | rules spanning two or more declared fields; any failing rule rejects | - -`generated` and `immutable` are keyed off the field names, so a typo is a -compile error rather than a silently-inert entry. - -`Entity.ComputedField` and `Entity.Invariant` are both generic; the -parameters are elided above because you never write them. `Entity.computed` and -`Entity.invariant` infer them from the surrounding declaration, which is what -makes `d` contextually typed with no annotation. - -## Schema members - -```ts -Organization.input; // ZodObject — everything make() accepts -Organization.output; // ZodObject — stored state and response body -Organization.createInput; // ZodObject — input minus generated -Organization.updateInput; // ZodObject — output minus immutable, partial -Organization.entityName; // the tag, as a literal type -Organization; // …is itself a zod schema, parsing to an instance -``` - -`output` is `input` plus the computed fields. All four `ZodObject`s generate -JSON Schema in **both** `"input"` and `"output"` directions. - -The class carries zod's internal slots (`_zod`, `~standard`) but **not** its -methods, so it composes anywhere zod takes a schema while `.parse()` — which -throws — does not exist on it: - -```ts -z.object({ owner: Organization }); // ✓ -z.array(Organization); // ✓ -z.optional(Organization); // ✓ the function form -Organization.optional(); // ✗ does not exist -Organization.parse(raw); // ✗ does not exist — use make() -z.toJSONSchema(Organization, { io: "output" }); // ✗ throws — the class carries a transform -``` - -## Entry points - -### `SomeEntity.factory(generators)` → `(input) => Result` - -Binds the `generated` fields' sources. Generators are **functions**, called -once per create. - -```ts -const createOrg = Organization.factory({ - id: () => ids.next(), - createdAt: () => clock.now(), -}); -createOrg({ slug, name }); // Result -``` - -Pass an arrow, not a bare method reference — `{ id: ids.next }` loses `this`. - -### `SomeEntity.factoryAsync(generators)` → `(input) => AsyncResult` - -The same for promise-returning generators — an id from a database sequence, -say. A generator that **rejects** surfaces as a `Defect`, not an -`InvalidEntity`: infrastructure failing is not the same as bad domain input. - -```ts -const createOrgAsync = Organization.factoryAsync({ - id: () => ids.nextFromSequence(), - createdAt: () => clock.now(), -}); -(await createOrgAsync({ slug, name })).getOrThrow(); -``` - -### `SomeEntity.make(data)` → `Result` - -The only way in. Validates against `input`, re-derives the computed fields, -checks the invariants, constructs. Extra keys are ignored, so a stored row -carrying computed columns round-trips. - -### `entity.update(patch)` → `Result` - -Returns a **new** entity. Re-runs the invariants and re-derives the computed -fields. `immutable` and `computed` fields are absent from the patch type and -dropped at runtime. - -### `entity.toJSON()` → the stored shape - -Projects exactly `output`'s keys. Excludes `_tag` and any class-body fields. -Called implicitly by `JSON.stringify`. - -### `entity.equals(other)` → `boolean` - -True when both are the same entity and their stored data is deep-equal. -Compares the stored data **structurally**, so entities holding equal arrays -compare equal. `Set`, `Map` and typed-array fields compare by contents, `Date` -by timestamp, `bigint` like any other primitive, and a nested object or record -is compared key-by-key rather than by key order. Arrays stay order-sensitive. -Two separate `Entity(...)` calls never compare equal, even with identical -fields. - -## `Entity.computed(schema, from)` - -One derived field: its schema, and the function producing it. - -```ts -computed: { - fullName: Entity.computed(FullName, (d) => `${d.first} ${d.last}` as z.infer), - initials: Entity.computed(Initials, (d) => `${d.first[0]}${d.last[0]}` as z.infer), -} -``` - -`d` is the declared shape, contextually typed. Each return value is checked -against **that field's** schema. A computed field cannot read another computed -field — every derivation is a function of declared data only. - -Output that fails its own schema is a `Defect`, named for the field -(`Person.computed.initials: …`). - -## `Entity.invariant(ensure, message)` - -One rule spanning the whole entity: the predicate, and what to say when it -fails. - -```ts -invariants: [ - Entity.invariant( - (d) => d.name.length <= 80, - "name must be at most 80 characters", - ), - Entity.invariant( - (d) => d.endsAt > d.startsAt, - (d) => `endsAt must be after ${d.startsAt}`, - ), -]; -``` - -`ensure` returning **true** means valid — a rule reads as the assertion it -makes. `d` is contextually typed and needs no annotation. `message` takes the -data when the text depends on it. - -Every failing rule in the list reports, not just the first, and none of them -carries a `path`: an invariant spans the entity, which is what separates it from -a field complaint. - -`d` is the **declared** fields, not the output — a rule cannot read a computed -field. Every computed value is a function of declared data, so any rule about -one is expressible over its sources, and a computed value failing its own schema -is already a Defect rather than something to re-check here. - -A predicate that throws is a Defect, not an `InvalidEntity`, on the same -reasoning as `computed`. - -## `SomeEntity.extend(tag)(fields, options?)` - -A **new** entity carrying the parent's fields plus more, under its own tag — -its own schemas, its own `equals` identity. - -```ts -class PersonWithAge extends Person.extend("PersonWithAge")({ age: Age }) { - get isAdult(): boolean { - return this.age >= 18; - } -} -``` - -Options merge per key, child winning — **except `invariants`**, which -concatenates parent-then-child. An extension can add rules; it cannot shed them, -so it is never quietly laxer than what it extends. Declaring `invariants: []` on -a child does not clear the parent's. - -`extend` rebuilds from the **declaration**, so class-body members do not carry -over — re-declare them. - -## `Entity.union(discriminant, members)` - -A union of entities that is itself entity-like. - -```ts -const Member = Entity.union("kind", [User, ServiceAccount]); - -Member.make(row); // Result -Member.input; // discriminated union, one branch per member -Member.output; // ditto — JSON Schema both directions -Member.members; // the tuple, for registries and exhaustiveness -Member.discriminant; // "kind" -``` - -`discriminant` names a declared domain field, not `_tag`. The union dispatches -on it rather than trying each branch, so a failing member reports its own -issues. The union is a schema too, so it nests as a field. - -## `Entity.InvalidEntity` - -```ts -class InvalidEntity extends TaggedError("InvalidEntity")<{ - readonly entity: string; - readonly issues: SchemaIssues; // readonly StandardSchemaV1.Issue[] -}> {} -``` - -Reachable as both a value and a type — `e instanceof Entity.InvalidEntity` and -`const e: Entity.InvalidEntity`. The signatures above write it unqualified, the -way `SomeEntity` is also a stand-in; `Entity.InvalidEntity` is how you spell it. -Matching by tag needs no import at all: `P.tag("InvalidEntity")`. - -Schema failures carry the failing field's `path`; an `invariants` violation has -none — that absence distinguishes a whole-entity rule from a field complaint. - -| Failure | Channel | -| ---------------------------------------- | ------------------------------------ | -| a field fails its own schema | `InvalidEntity`, issue has a `path` | -| a broken `invariants` rule | `InvalidEntity`, issue has no `path` | -| `computed` output failing its own schema | **defect** | -| a `computed` function throwing | **defect** | -| an async generator rejecting | **defect** | -| subclassing an entity | **defect** | - -## Helper types - -```ts -import { Entity } from "@btravstack/entity"; - -type OrgWire = Entity.Input; // what make() accepts -type OrgState = Entity.Output; // what toJSON() returns -type OrgCreate = Entity.CreateInput; // what a factory accepts -type OrgPatch = Entity.Patch; // what update() accepts -``` - -Also `Entity.ComputedField` and `Entity.Union`, the shapes `Entity.computed` and -`Entity.union` return. - -`BaseInstance`, `ConstructionKey` and `Sealed` are the one exception to the -single-import rule: they are exported at the top level **as well as** under -`Entity`, because a downstream library compiling with `declaration: true` emits -the underlying name rather than the namespace path that aliases it, and would -otherwise fail with `TS4020`. They are not part of the API you write against. - -```ts -import type { BaseInstance, ConstructionKey, Sealed } from "@btravstack/entity"; -``` diff --git a/docs/reference/declaration.md b/docs/reference/declaration.md new file mode 100644 index 0000000..06a6458 --- /dev/null +++ b/docs/reference/declaration.md @@ -0,0 +1,156 @@ +--- +title: Declaring an entity +description: Entity(tag)(fields, options), the field rules, the four options, and the Entity.computed / Entity.invariant / extend / union declaration helpers. +--- + +# Declaring an entity + +The builder itself, the rules a field map must satisfy, the four options, and the +helpers that go inside them. For _why_ it is shaped this way, see +[Explanation](/explanation/why-entity); for task recipes, see the +[how-to guides](/how-to/http-contract). + +> Snippets on this page assume these imports: +> +> ```ts +> import { z } from "zod"; +> import { match, P } from "unthrown"; +> import { Entity } from "@btravstack/entity"; +> ``` + +## `Entity(tag)(fields, options?)` + +Declares an entity. Curried on the tag so it reads next to the class name. + +```ts +class Organization extends Entity("Organization")(fields, options) {} +``` + +### `fields` + +A map of field name to schema. Every field must be **nominal** — a branded +schema, a narrow literal union, a boolean, or another entity class. A bare +`z.string()` is a compile error naming `DomainFieldMustBeBrandedOrAnEntity`. + +Four names are reserved, because an entity installs them on every instance: +`_tag`, `equals`, `toJSON`, `update`. Using one is a compile error naming +`FieldNameIsReservedByEntity`. + +### `options` + +| Option | Type | Effect | +| ------------ | ---------------------------------- | -------------------------------------------------------------------------------- | +| `generated` | `readonly (keyof fields)[]` | omitted from `createInput`; supplied by a factory's generators | +| `immutable` | `readonly (keyof output)[]` | omitted from `updateInput`; `update()` drops them even if smuggled in at runtime | +| `computed` | `{ [name]: Entity.ComputedField }` | derived fields; added to `output`, re-derived on every construction | +| `invariants` | `readonly Entity.Invariant[]` | rules spanning two or more declared fields; any failing rule rejects | + +`generated` and `immutable` are keyed off the field names, so a typo is a +compile error rather than a silently-inert entry. + +`Entity.ComputedField` and `Entity.Invariant` are both generic; the +parameters are elided above because you never write them. `Entity.computed` and +`Entity.invariant` infer them from the surrounding declaration, which is what +makes `d` contextually typed with no annotation. + +## `Entity.computed(schema, from)` + +One derived field: its schema, and the function producing it. + +```ts +computed: { + fullName: Entity.computed(FullName, (d) => `${d.first} ${d.last}` as z.infer), + initials: Entity.computed(Initials, (d) => `${d.first[0]}${d.last[0]}` as z.infer), +} +``` + +`d` is the declared shape, contextually typed. Each return value is checked +against **that field's** schema. A computed field cannot read another computed +field — every derivation is a function of declared data only. + +Output that fails its own schema is a `Defect`, named for the field +(`Person.computed.initials: …`). + +Computed fields are re-derived on every construction path rather than stored — +see [Why `computed` re-derives](/explanation/computed-fields), which also covers +when to reach for a plain getter instead. + +## `Entity.invariant(ensure, message)` + +One rule spanning the whole entity: the predicate, and what to say when it +fails. + +```ts +invariants: [ + Entity.invariant( + (d) => d.name.length <= 80, + "name must be at most 80 characters", + ), + Entity.invariant( + (d) => d.endsAt > d.startsAt, + (d) => `endsAt must be after ${d.startsAt}`, + ), +]; +``` + +`ensure` returning **true** means valid — a rule reads as the assertion it +makes. `d` is contextually typed and needs no annotation. `message` takes the +data when the text depends on it. + +Every failing rule in the list reports, not just the first, and none of them +carries a `path`: an invariant spans the entity, which is what separates it from +a field complaint. + +`d` is the **declared** fields, not the output — a rule cannot read a computed +field. Every computed value is a function of declared data, so any rule about +one is expressible over its sources, and a computed value failing its own schema +is already a Defect rather than something to re-check here. + +A predicate that throws is a Defect, not an `InvalidEntity`, on the same +reasoning as `computed`. + +## `SomeEntity.extend(tag)(fields, options?)` + +A **new** entity carrying the parent's fields plus more, under its own tag — +its own schemas, its own `equals` identity. + +```ts +class PersonWithAge extends Person.extend("PersonWithAge")({ age: Age }) { + get isAdult(): boolean { + return this.age >= 18; + } +} +``` + +Options merge per key, child winning — **except `invariants`**, which +concatenates parent-then-child. An extension can add rules; it cannot shed them, +so it is never quietly laxer than what it extends. Declaring `invariants: []` on +a child does not clear the parent's. + +`extend` rebuilds from the **declaration**, so class-body members do not carry +over — re-declare them. + +This is the only supported way to build on an existing entity: a bare +`class Sub extends Organization {}` is +[rejected at construction](/explanation/sealed-construction#entities-are-not-subclassable). + +## `Entity.union(discriminant, members)` + +A union of entities that is itself entity-like. + +```ts +const Member = Entity.union("kind", [User, ServiceAccount]); + +Member.make(row); // Result +Member.input; // discriminated union, one branch per member +Member.output; // ditto — JSON Schema both directions +Member.members; // the tuple, for registries and exhaustiveness +Member.discriminant; // "kind" +``` + +`discriminant` names a declared domain field, not `_tag`. The union dispatches +on it rather than trying each branch, so a failing member reports its own +issues. The union is a schema too, so it nests as a field. + +`_tag` cannot serve as the discriminant here, and that is not an oversight — +[it never reaches the wire](/explanation/tags-and-identity). diff --git a/docs/reference/entry-points.md b/docs/reference/entry-points.md new file mode 100644 index 0000000..e5efcca --- /dev/null +++ b/docs/reference/entry-points.md @@ -0,0 +1,73 @@ +--- +title: Entry points +description: factory, factoryAsync, make, update, toJSON and equals — every way in and out of an entity. +--- + +# Entry points + +Every way an entity comes into existence, and the two projections out of one. +There is no other: `new SomeEntity(…)` +[does not compile](/explanation/sealed-construction). + +> Snippets on this page assume these imports: +> +> ```ts +> import { z } from "zod"; +> import { Entity } from "@btravstack/entity"; +> ``` + +## `SomeEntity.factory(generators)` → `(input) => Result` + +Binds the `generated` fields' sources. Generators are **functions**, called +once per create. + +```ts +const createOrg = Organization.factory({ + id: () => ids.next(), + createdAt: () => clock.now(), +}); +createOrg({ slug, name }); // Result +``` + +Pass an arrow, not a bare method reference — `{ id: ids.next }` loses `this`. + +## `SomeEntity.factoryAsync(generators)` → `(input) => AsyncResult` + +The same for promise-returning generators — an id from a database sequence, +say. A generator that **rejects** surfaces as a `Defect`, not an +`InvalidEntity`: infrastructure failing is not the same as bad domain input. + +```ts +const createOrgAsync = Organization.factoryAsync({ + id: () => ids.nextFromSequence(), + createdAt: () => clock.now(), +}); +(await createOrgAsync({ slug, name })).getOrThrow(); +``` + +## `SomeEntity.make(data)` → `Result` + +The only way in. Validates against `input`, re-derives the computed fields, +checks the invariants, constructs. Extra keys are ignored, so a stored row +carrying computed columns round-trips. + +## `entity.update(patch)` → `Result` + +Returns a **new** entity. Re-runs the invariants and re-derives the computed +fields. `immutable` and `computed` fields are absent from the patch type and +dropped at runtime. + +## `entity.toJSON()` → the stored shape + +Projects exactly `output`'s keys. Excludes `_tag` and any class-body fields. +Called implicitly by `JSON.stringify`. + +## `entity.equals(other)` → `boolean` + +True when both are the same entity and their stored data is deep-equal. +Compares the stored data **structurally**, so entities holding equal arrays +compare equal. `Set`, `Map` and typed-array fields compare by contents, `Date` +by timestamp, `bigint` like any other primitive, and a nested object or record +is compared key-by-key rather than by key order. Arrays stay order-sensitive. +Two separate `Entity(...)` calls never compare equal, even with identical +fields. diff --git a/docs/reference/errors.md b/docs/reference/errors.md new file mode 100644 index 0000000..6fc1af1 --- /dev/null +++ b/docs/reference/errors.md @@ -0,0 +1,67 @@ +--- +title: Errors +description: Entity.InvalidEntity, its structured issues, and the table of which failure goes down which channel. +--- + +# Errors + +Every fallible entry point returns `Result`. Bad input is +modelled as a value; a bug in domain code goes down the separate defect channel. + +> Snippets on this page assume these imports: +> +> ```ts +> import { match, P } from "unthrown"; +> import { Entity } from "@btravstack/entity"; +> ``` + +## `Entity.InvalidEntity` + +```ts +class InvalidEntity extends TaggedError("InvalidEntity")<{ + readonly entity: string; + readonly issues: SchemaIssues; // readonly StandardSchemaV1.Issue[] +}> {} +``` + +Reachable as both a value and a type — `e instanceof Entity.InvalidEntity` and +`const e: Entity.InvalidEntity`. The signatures throughout this reference write +it unqualified, the way `SomeEntity` is also a stand-in; `Entity.InvalidEntity` +is how you spell it. Matching by tag needs no import at all: +`P.tag("InvalidEntity")`. + +Schema failures carry the failing field's `path`; an `invariants` violation has +none — that absence distinguishes a whole-entity rule from a field complaint. + +## Which channel a failure takes + +| Failure | Channel | +| ---------------------------------------- | ------------------------------------ | +| a field fails its own schema | `InvalidEntity`, issue has a `path` | +| a broken `invariants` rule | `InvalidEntity`, issue has no `path` | +| `computed` output failing its own schema | **defect** | +| a `computed` function throwing | **defect** | +| an async generator rejecting | **defect** | +| subclassing an entity | **defect** | + +The line between the two columns is argued in +[Errors are values, and defects are separate](/explanation/errors-are-values). + +## Handling both at the edge + +```ts +Organization.make(row).match({ + ok: (org) => respond(200, org.toJSON()), + errCases: (m) => + m.with(P.tag("InvalidEntity"), (e) => respond(422, e.issues)), + defect: (cause) => { + report(cause); + return respond(500); + }, +}); +``` + +Issues are carried **structured**, exactly as the validator produced them, so +keying a field-level error response is a `path` lookup rather than a string +parse. [Expose an HTTP contract](/how-to/http-contract#handle-failures-at-the-edge) +works this through end to end. diff --git a/docs/reference/schemas.md b/docs/reference/schemas.md new file mode 100644 index 0000000..a6c9e88 --- /dev/null +++ b/docs/reference/schemas.md @@ -0,0 +1,46 @@ +--- +title: Schema members +description: input, output, createInput, updateInput, entityName — and the class itself as a zod schema. +--- + +# Schema members + +Every entity carries four plain `ZodObject`s as statics, plus the class itself. + +> Snippets on this page assume these imports: +> +> ```ts +> import { z } from "zod"; +> import { Entity } from "@btravstack/entity"; +> ``` + +```ts +Organization.input; // ZodObject — everything make() accepts +Organization.output; // ZodObject — stored state and response body +Organization.createInput; // ZodObject — input minus generated +Organization.updateInput; // ZodObject — output minus immutable, partial +Organization.entityName; // the tag, as a literal type +Organization; // …is itself a zod schema, parsing to an instance +``` + +`output` is `input` plus the computed fields. All four `ZodObject`s generate +JSON Schema in **both** `"input"` and `"output"` directions. + +The class carries zod's internal slots (`_zod`, `~standard`) but **not** its +methods, so it composes anywhere zod takes a schema while `.parse()` — which +throws — does not exist on it: + +```ts +z.object({ owner: Organization }); // ✓ +z.array(Organization); // ✓ +z.optional(Organization); // ✓ the function form +Organization.optional(); // ✗ does not exist +Organization.parse(raw); // ✗ does not exist — use make() +z.toJSONSchema(Organization, { io: "output" }); // ✗ throws — the class carries a transform +``` + +That last line is the design rule made concrete: **contracts compose the four +plain `ZodObject`s; domain code composes the class itself.** See +[Why entity?](/explanation/why-entity#the-rule-the-design-turns-on) for the +constraint it comes from, and +[Expose an HTTP contract](/how-to/http-contract) for the recipe. diff --git a/docs/reference/types.md b/docs/reference/types.md new file mode 100644 index 0000000..2bff596 --- /dev/null +++ b/docs/reference/types.md @@ -0,0 +1,38 @@ +--- +title: Helper types +description: Entity.Input, Entity.Output, Entity.CreateInput, Entity.Patch — and the three seal names exported at the top level. +--- + +# Helper types + +Every public type hangs off the merged `Entity` namespace, so one import covers +the whole surface. + +```ts +import { Entity } from "@btravstack/entity"; + +type OrgWire = Entity.Input; // what make() accepts +type OrgState = Entity.Output; // what toJSON() returns +type OrgCreate = Entity.CreateInput; // what a factory accepts +type OrgPatch = Entity.Patch; // what update() accepts +``` + +Also `Entity.ComputedField` and `Entity.Union`, the shapes `Entity.computed` and +`Entity.union` return. + +## The seal names + +`BaseInstance`, `ConstructionKey` and `Sealed` are the one exception to the +single-import rule: they are exported at the top level **as well as** under +`Entity`, because a downstream library compiling with `declaration: true` emits +the underlying name rather than the namespace path that aliases it, and would +otherwise fail with `TS4020`. They are not part of the API you write against. + +```ts +import type { BaseInstance, ConstructionKey, Sealed } from "@btravstack/entity"; +``` + +That is measured, not assumed: a fixture in CI compiles a consumer with +declaration emit against the built types, so it cannot regress. See +[Sealed construction](/explanation/sealed-construction) for what the seal buys +and what the two rejected alternatives cost. diff --git a/docs/tutorial/getting-started.md b/docs/tutorial/getting-started.md new file mode 100644 index 0000000..34e9efe --- /dev/null +++ b/docs/tutorial/getting-started.md @@ -0,0 +1,293 @@ +--- +title: Getting started +description: Build a working entity from nothing — declare it, create one, watch a bad value fail as a value, update it, and send it over the wire. +--- + +# Getting started + +By the end of this page you will have declared an entity, created one through a +factory, seen a bad value come back as a `Result` instead of an exception, +updated it into a new instance, and projected it to the shape you would store or +respond with. + +The snippets build on one another, so follow along in a `.ts` file. Each step +shows only what changed; the two lines marked `// ✗` are meant not to compile, +and that is the point of them. + +## Install + +```sh +pnpm add @btravstack/entity zod unthrown @unthrown/standard-schema +``` + +All four, because `zod`, `unthrown` and `@unthrown/standard-schema` are **peer** +dependencies — the package hands you back _your_ copies of them rather than its +own. ([Why](/explanation/peer-dependencies).) + +## 1. Brand your fields + +Every field of an entity must be **nominal** — a schema that carries a brand, a +narrow literal union, a boolean, or another entity. A bare `z.string()` is a +compile error. + +```ts +import { z } from "zod"; + +const OrgId = z.uuid().brand("OrgId"); +const Slug = z.string().min(1).brand("Slug"); +const DisplayName = z.string().min(1).brand("DisplayName"); +const Instant = z.iso.datetime().brand("Instant"); +``` + +The reason is the one every domain modeller already knows: with plain strings, +`findOrg(slug, name)` type-checks with the arguments swapped. Branded, it does +not. + +## 2. Declare the entity + +```ts +import { Entity } from "@btravstack/entity"; + +class Organization extends Entity("Organization")({ + id: OrgId, + slug: Slug, + name: DisplayName, + createdAt: Instant, +}) {} +``` + +That single declaration already gives you four validators and a class that is +itself a zod schema: + +```ts +Organization.input; // ZodObject — everything make() accepts +Organization.output; // ZodObject — the stored shape / response body +Organization.createInput; // ZodObject — the create request +Organization.updateInput; // ZodObject — the update request, partial +``` + +Right now `createInput` equals `input` and `updateInput` is just `output` made +partial. The next step is what makes them differ. + +## 3. Say which fields the domain owns + +`id` and `createdAt` are not the caller's to supply, and never change once set. +Declare that: + +```ts +class Organization extends Entity("Organization")( + { id: OrgId, slug: Slug, name: DisplayName, createdAt: Instant }, + { + generated: ["id", "createdAt"], + immutable: ["id", "createdAt", "slug"], + }, +) {} +``` + +- `generated` drops those fields from `createInput` — a create request cannot + carry them. +- `immutable` drops them from `updateInput` — and `update()` discards them at + runtime even if something smuggles them past the type. + +Both are keyed off the field names, so a typo is a compile error rather than a +silently-inert entry. + +## 4. Create one + +The package reads no clock and generates no id. Instead you bind the **sources** +once — at your composition root, next to the ports you already have: + +```ts +const createOrganization = Organization.factory({ + id: () => crypto.randomUUID() as z.infer, + createdAt: () => new Date().toISOString() as z.infer, +}); +``` + +Now a create use case supplies only the caller's fields: + +```ts +const created = createOrganization({ + slug: "acme" as z.infer, + name: "Acme" as z.infer, +}); + +const org = created.getOrThrow(); +org.name; // "Acme" +org.id; // a fresh uuid +``` + +Generators are **functions**, called once per create — so a factory built at +startup still yields a fresh id per entity. And a test can bind fixed generators +instead of stubbing globals. ([Why no I/O](/explanation/no-io).) + +::: tip `getOrThrow()` is for a tutorial +It is the shortest way to get at a value while you are exploring. Real code +handles the `Result` — [step 6](#_6-handle-failure-as-a-value) does. +::: + +## 5. Try to break it + +The entity is immutable in both halves — the binding is non-writable and the +value is deep-frozen: + +```ts +org.name = "Other" as z.infer; // ✗ compile error — read-only property +``` + +And you cannot sidestep the entry points: + +```ts +new Organization(org.toJSON()); // ✗ does not compile — the constructor is sealed +``` + +The constructor takes a value no outside code can produce. That is what +guarantees every instance in your program went through validation and the +invariants. ([Sealed construction](/explanation/sealed-construction).) + +## 6. Handle failure as a value + +Nothing throws. `make` is the general entry point — a database row, a folded +event stream, an untrusted import all come in the same way — and it returns a +`Result`: + +```ts +import { P } from "unthrown"; + +const outcome = Organization.make({ + id: "not-a-uuid", + slug: "acme", + name: "Acme", + createdAt: "2026-01-01T00:00:00.000Z", +}).match({ + ok: (o) => `created ${o.slug}`, + errCases: (m) => m.with(P.tag("InvalidEntity"), (e) => e.issues), + defect: (cause) => { + console.error(cause); + return "bug"; + }, +}); +``` + +`outcome` is the issue list: `[{ path: ["id"], message: "Invalid UUID" }]`. +Structured, exactly as the validator produced it — keying a field-level error +response is a `path` lookup, not a string parse. + +The third branch is not decoration. `defect` is a separate channel for a bug in +your own domain code, and it is never folded into `errCases`. ([Errors are +values, and defects are separate](/explanation/errors-are-values).) + +## 7. Add a rule that spans fields + +A single field's schema cannot express "these two fields must agree". +`invariants` can: + +```ts +class Organization extends Entity("Organization")( + { id: OrgId, slug: Slug, name: DisplayName, createdAt: Instant }, + { + generated: ["id", "createdAt"], + immutable: ["id", "createdAt", "slug"], + invariants: [ + Entity.invariant( + (d) => d.name.length <= 80, + "name must be at most 80 characters", + ), + ], + }, +) {} +``` + +`ensure` returning **true** means valid, so a rule reads as the assertion it +makes. `d` is contextually typed — no annotation needed. Every failing rule +reports, not just the first, and an invariant's issue carries no `path`: it is a +complaint about the entity, not about one field. + +Invariants re-run on every construction path, including `update`. + +## 8. Derive a field, and add behaviour + +Two different things live in a class, and they go in two different places: + +```ts +const Upper = z.string().min(1).brand("Upper"); + +class Organization extends Entity("Organization")( + { id: OrgId, slug: Slug, name: DisplayName, createdAt: Instant }, + { + generated: ["id", "createdAt"], + immutable: ["id", "createdAt", "slug"], + computed: { + shout: Entity.computed( + Upper, + (d) => d.name.toUpperCase() as z.infer, + ), + }, + }, +) { + get greeting(): string { + return `Welcome, ${this.name}`; + } +} + +org.shout; // "ACME" — data: in `output`, in toJSON(), in the JSON Schema +org.greeting; // "Welcome, Acme" — behaviour: on the prototype, never serialised +``` + +A `computed` field is **data**. A getter is **behaviour**. If it belongs in the +response body, it is `computed`. ([Why `computed` +re-derives](/explanation/computed-fields).) + +## 9. Update + +`update` returns a **new** entity — the original is untouched: + +```ts +const renamed = org + .update({ name: "Acme Corp" as z.infer }) + .getOrThrow(); + +renamed.name; // "Acme Corp" +renamed.shout; // "ACME CORP" — re-derived, never stale +org.name; // "Acme" — the original is unchanged +renamed.equals(org); // false +``` + +`org.update({ slug })` does not compile: `slug` is `immutable`. + +## 10. Send it over the wire + +`toJSON()` projects exactly `output`'s keys — never `_tag`, never `greeting`, +never anything your class body added: + +```ts +console.log(renamed.toJSON()); +// { id, slug, name, createdAt, shout } — that object is what you store or respond with +``` + +And the four schema members are plain `ZodObject`s, so a contract layer converts +them to JSON Schema in **both** directions: + +```ts +z.toJSONSchema(Organization.createInput, { io: "input" }); // ✓ +z.toJSONSchema(Organization.output, { io: "output" }); // ✓ +z.toJSONSchema(Organization, { io: "output" }); // ✗ throws — by design +``` + +That last line is the rule the whole package turns on: **contracts compose the +four plain `ZodObject`s; domain code composes the class itself.** The class +carries a `.transform()` (that is what produces an instance), and a transform has +no output representation. + +## Where to go next + +- [Expose an HTTP contract](/how-to/http-contract) — the contract layer, worked + end to end. +- [Persist and rehydrate](/how-to/persist-and-rehydrate) — repositories, and why + computed columns heal themselves. +- [Model an aggregate](/how-to/model-an-aggregate) — entities nested in entities, + and `Entity.union`. +- [Test domain logic](/how-to/test-domain-logic) — deterministic tests with no + global stubbing. +- [Reference](/reference/declaration) — every member, option and type. +- [Why entity?](/explanation/why-entity) — the design, and what was measured. diff --git a/docs/typedoc.json b/docs/typedoc.json new file mode 100644 index 0000000..0954900 --- /dev/null +++ b/docs/typedoc.json @@ -0,0 +1,29 @@ +{ + "extends": "@btravstack/typedoc/base.json", + "entryPoints": ["../packages/entity/src/index.ts"], + "tsconfig": "../packages/entity/tsconfig.json", + "out": "api/entity", + "categoryOrder": ["Facade", "Declaration", "Entry points", "Types", "Errors", "*"], + "intentionallyNotExported": [ + "BaseInstanceSrc", + "ComputedField", + "ComputedFieldSrc", + "ComputedOf", + "ConstructionKeySrc", + "DomainFieldMustBeBrandedOrAnEntity", + "EntityStatic", + "EntityUnion", + "EntityUnionSrc", + "Fields", + "InputOf", + "InvalidEntity", + "Invariant", + "InvariantSrc", + "IsNominalField", + "OnlyNominal", + "OutputOf", + "PatchOf", + "SealedSrc", + "UnionMember" + ] +} diff --git a/knip.json b/knip.json index 4ccdf17..12eac17 100644 --- a/knip.json +++ b/knip.json @@ -5,7 +5,15 @@ "workspaces": { "packages/*": { "project": ["src/**/*.ts"] + }, + "docs": { + "project": [".vitepress/**/*.ts"] } }, - "ignoreDependencies": ["@btravstack/oxlint", "@btravstack/lefthook"] + "ignoreDependencies": [ + "@btravstack/oxlint", + "@btravstack/lefthook", + "@btravstack/typedoc", + "typedoc-plugin-markdown" + ] } diff --git a/packages/entity/README.md b/packages/entity/README.md index a7567cb..aab4c25 100644 --- a/packages/entity/README.md +++ b/packages/entity/README.md @@ -67,11 +67,12 @@ Also `Entity.union(...)` for a union that is itself entity-like, and ## Documentation -Full docs live in the repository: +**[btravstack.github.io/entity](https://btravstack.github.io/entity/)** -- [Reference](https://github.com/btravstack/entity/blob/main/docs/reference.md) — every member, option and type -- [Explanation](https://github.com/btravstack/entity/blob/main/docs/explanation.md) — why it is built this way -- How-to: [HTTP contract](https://github.com/btravstack/entity/blob/main/docs/how-to/http-contract.md) · [persist and rehydrate](https://github.com/btravstack/entity/blob/main/docs/how-to/persist-and-rehydrate.md) · [model an aggregate](https://github.com/btravstack/entity/blob/main/docs/how-to/model-an-aggregate.md) · [test domain logic](https://github.com/btravstack/entity/blob/main/docs/how-to/test-domain-logic.md) +- [Getting started](https://btravstack.github.io/entity/tutorial/getting-started) — from nothing to a working entity +- [Reference](https://btravstack.github.io/entity/reference/declaration) — every member, option and type +- [Explanation](https://btravstack.github.io/entity/explanation/why-entity) — why it is built this way +- How-to: [HTTP contract](https://btravstack.github.io/entity/how-to/http-contract) · [persist and rehydrate](https://btravstack.github.io/entity/how-to/persist-and-rehydrate) · [model an aggregate](https://btravstack.github.io/entity/how-to/model-an-aggregate) · [test domain logic](https://btravstack.github.io/entity/how-to/test-domain-logic) ## License diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 724e941..b9c0812 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -15,9 +15,15 @@ catalogs: '@btravstack/oxlint': specifier: 0.2.1 version: 0.2.1 + '@btravstack/theme': + specifier: 1.7.0 + version: 1.7.0 '@btravstack/tsconfig': specifier: 0.2.0 version: 0.2.0 + '@btravstack/typedoc': + specifier: 0.1.0 + version: 0.1.0 '@changesets/cli': specifier: 2.31.1 version: 2.31.1 @@ -60,18 +66,34 @@ catalogs: turbo: specifier: 2.10.8 version: 2.10.8 + typedoc: + specifier: 0.28.20 + version: 0.28.20 + typedoc-plugin-markdown: + specifier: 4.12.0 + version: 4.12.0 typescript: specifier: 7.0.2 version: 7.0.2 unthrown: specifier: 5.1.0 version: 5.1.0 + vitepress: + specifier: 1.6.4 + version: 1.6.4 vitest: specifier: 4.1.10 version: 4.1.10 zod: specifier: 4.4.3 version: 4.4.3 + typedoc: + typescript: + specifier: 6.0.3 + version: 6.0.3 + +overrides: + vite@<6.4.3: 6.4.3 importers: @@ -111,6 +133,30 @@ importers: specifier: 'catalog:' version: 2.10.8 + docs: + devDependencies: + '@btravstack/theme': + specifier: 'catalog:' + version: 1.7.0(vitepress@1.6.4(@algolia/client-search@5.56.0)(@types/node@26.1.2)(jiti@2.7.0)(postcss@8.5.25)(typescript@6.0.3)(yaml@2.9.0))(vue@3.5.41(typescript@6.0.3)) + '@btravstack/typedoc': + specifier: 'catalog:' + version: 0.1.0(typedoc-plugin-markdown@4.12.0(typedoc@0.28.20(typescript@6.0.3)))(typedoc@0.28.20(typescript@6.0.3)) + '@types/node': + specifier: 'catalog:' + version: 26.1.2 + typedoc: + specifier: 'catalog:' + version: 0.28.20(typescript@6.0.3) + typedoc-plugin-markdown: + specifier: 'catalog:' + version: 4.12.0(typedoc@0.28.20(typescript@6.0.3)) + typescript: + specifier: catalog:typedoc + version: 6.0.3 + vitepress: + specifier: 'catalog:' + version: 1.6.4(@algolia/client-search@5.56.0)(@types/node@26.1.2)(jiti@2.7.0)(postcss@8.5.25)(typescript@6.0.3)(yaml@2.9.0) + packages/entity: devDependencies: '@btravstack/tsconfig': @@ -149,6 +195,82 @@ importers: packages: + '@algolia/abtesting@1.22.0': + resolution: {integrity: sha512-BFR6zNowNKcY7Ou7TaJc9QWexES4YKPbmf/OTFofpdsdhz4x6q0lbxp3duO0EHnyrN7rE4ba/TSXuY+BDGu4+g==} + engines: {node: '>= 14.0.0'} + + '@algolia/autocomplete-core@1.17.7': + resolution: {integrity: sha512-BjiPOW6ks90UKl7TwMv7oNQMnzU+t/wk9mgIDi6b1tXpUek7MW0lbNOUHpvam9pe3lVCf4xPFT+lK7s+e+fs7Q==} + + '@algolia/autocomplete-plugin-algolia-insights@1.17.7': + resolution: {integrity: sha512-Jca5Ude6yUOuyzjnz57og7Et3aXjbwCSDf/8onLHSQgw1qW3ALl9mrMWaXb5FmPVkV3EtkD2F/+NkT6VHyPu9A==} + peerDependencies: + search-insights: '>= 1 < 3' + + '@algolia/autocomplete-preset-algolia@1.17.7': + resolution: {integrity: sha512-ggOQ950+nwbWROq2MOCIL71RE0DdQZsceqrg32UqnhDz8FlO9rL8ONHNsI2R1MH0tkgVIDKI/D0sMiUchsFdWA==} + peerDependencies: + '@algolia/client-search': '>= 4.9.1 < 6' + algoliasearch: '>= 4.9.1 < 6' + + '@algolia/autocomplete-shared@1.17.7': + resolution: {integrity: sha512-o/1Vurr42U/qskRSuhBH+VKxMvkkUVTLU6WZQr+L5lGZZLYWyhdzWjW0iGXY7EkwRTjBqvN2EsR81yCTGV/kmg==} + peerDependencies: + '@algolia/client-search': '>= 4.9.1 < 6' + algoliasearch: '>= 4.9.1 < 6' + + '@algolia/client-abtesting@5.56.0': + resolution: {integrity: sha512-7r4Z3NC7yU1oAQVWJNA2HX7tX481F3pJvCGyLIXiTdBcthz4Q/o21jwcMYDFkuI92UWTNBQQmHYgwHo1zS5dzg==} + engines: {node: '>= 14.0.0'} + + '@algolia/client-analytics@5.56.0': + resolution: {integrity: sha512-avmjXQSq+jadFO8Xl2em05/uQdQnEmHsJyOAdVbZkmVgpMfxL12aJwVVfGNwYr9nulcpuJN1X0lTaQ5wxuNGcA==} + engines: {node: '>= 14.0.0'} + + '@algolia/client-common@5.56.0': + resolution: {integrity: sha512-v2TPStUhY//ripPjIVclZ8AWc7DEGooXULZGFlFu37zNatgHjw34oZZ+OSbbc/YHO+xZwPl62I1k8xH1m4S2eg==} + engines: {node: '>= 14.0.0'} + + '@algolia/client-insights@5.56.0': + resolution: {integrity: sha512-P0ehROpM4Sem3Sqo5x2cKPgj67D3G3jy0rh1Amwkcvsfr6tkvIcdCmerieanqTF7NxUMPNFLkpIFeMO8Rpa50w==} + engines: {node: '>= 14.0.0'} + + '@algolia/client-personalization@5.56.0': + resolution: {integrity: sha512-SXK3Vn3WVxyzbm31oePZBJkp1wpOyuWdd4B/Pv7n0aXDxmeSWhC1R1FC1517mMrFAIaPH4Rt0x6RUe7ZNjz8FA==} + engines: {node: '>= 14.0.0'} + + '@algolia/client-query-suggestions@5.56.0': + resolution: {integrity: sha512-5+ZdX8garFnmycnZgKhtXHePEaLj5zqDxI/0lkhhluzCcvTn0/PvvTirTg8hHYetQHvn7GDyeAiqTAieMvMW4A==} + engines: {node: '>= 14.0.0'} + + '@algolia/client-search@5.56.0': + resolution: {integrity: sha512-+mKUdYvqOi0BcvpAEyCEw49vSBptufIcfibtHz2bdr1pI789M46Yt0uQEk/sxtK3teh71OQvVFHaTDzShUWewQ==} + engines: {node: '>= 14.0.0'} + + '@algolia/ingestion@1.56.0': + resolution: {integrity: sha512-9g/zj+AZx5moFcdFIrYQoVrueXivjUcc3MQHtCYT8WhIuk1lUh1AyEhvJCS0XBZld09cLvd1AZ3BvDBpVpX2UA==} + engines: {node: '>= 14.0.0'} + + '@algolia/monitoring@1.56.0': + resolution: {integrity: sha512-Qf3Sr6f9A9uxCZUf3MXS0d2b877uYzEB5yxqpVGXAhcJnBCQjrRRon0KvefpGkxy+BshrIJs96OUoMtGqXTFDA==} + engines: {node: '>= 14.0.0'} + + '@algolia/recommend@5.56.0': + resolution: {integrity: sha512-GXWG1rWc5wu8hY4N33Y3b6ernY6sAdAvmKWN/zHAiACOx40WnpG0TVX5YazCAr/9gOYGInSiM2A0y2jy2xbiDA==} + engines: {node: '>= 14.0.0'} + + '@algolia/requester-browser-xhr@5.56.0': + resolution: {integrity: sha512-7t24cBxaInS3mZb7ddEaZT/tp6q+/aR4YttsQVyP1/i+LmwPR34atO35KjaLFCcRVrlP7sYOAqkCfg6lIRB+ew==} + engines: {node: '>= 14.0.0'} + + '@algolia/requester-fetch@5.56.0': + resolution: {integrity: sha512-R7ePHgVYmDFjZpvrsVAfbDz/d4RxKAYZ5/vgLfIsCVRZRryjWl/3INOxpOICzitehQ5FjNtNjcLQTrmHPTcHBQ==} + engines: {node: '>= 14.0.0'} + + '@algolia/requester-node-http@5.56.0': + resolution: {integrity: sha512-PIOUXlSnrqM0S+WOgDRb4RzotydJH7ZoT6tOyL7tAO7qJOfvX5wsEW8Pe+PMKMwvuI4/gIyK9cg2H7lJXqnc4Q==} + engines: {node: '>= 14.0.0'} + '@babel/code-frame@7.29.7': resolution: {integrity: sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==} engines: {node: '>=6.9.0'} @@ -196,10 +318,26 @@ packages: peerDependencies: oxlint: '>=1' + '@btravstack/theme@1.7.0': + resolution: {integrity: sha512-EcBvQruZdsiL/zuNsu7Y1r2FeMDv0J5LZJx7ikO6cFvNRzKCc63A7582gVmfJNQlGJIg0cUCjQXB4Tm1YHtyug==} + peerDependencies: + vitepress: ^1.6.0 + vue: ^3.3.0 + peerDependenciesMeta: + vue: + optional: true + '@btravstack/tsconfig@0.2.0': resolution: {integrity: sha512-0VZt4DNJlY+XgAeCS4HybgsG0kdWDGjRwBiDdQZ6pYPUo1ayjM4AIH1oPatL5+YQvICTqrSaXTHSa8DnP+GXbg==} engines: {node: '>=20'} + '@btravstack/typedoc@0.1.0': + resolution: {integrity: sha512-cAhj15iqJwPQ+Z+I/Kc1Bafu9HqfS2D/uaU7czPecaCgZpH5F8LUfNRmTZppkvnTMpDX0La+UrdIUyNHHLqtIg==} + engines: {node: '>=20'} + peerDependencies: + typedoc: '>=0.28' + typedoc-plugin-markdown: '>=4' + '@changesets/apply-release-plan@7.1.1': resolution: {integrity: sha512-9qPCm/rLx/xoOFXIHGB229+4GOL76S4MC+7tyOuTsR6+1jYlfFDQORdvwR5hDA6y4FL2BPt3qpbcQIS+dW85LA==} @@ -340,6 +478,29 @@ packages: resolution: {integrity: sha512-TzlTVpKPjaqW6qOYjQcYUDuGsLCNsvFHVBXkYGTAnf5V37jCWrE5haKNXzz0WZUtVHjrpV76L1buANjwXMfT8w==} engines: {node: '>=22'} + '@docsearch/css@3.8.2': + resolution: {integrity: sha512-y05ayQFyUmCXze79+56v/4HpycYF3uFqB78pLPrSV5ZKAlDuIAAJNhaRi8tTdRNXh05yxX/TyNnzD6LwSM89vQ==} + + '@docsearch/js@3.8.2': + resolution: {integrity: sha512-Q5wY66qHn0SwA7Taa0aDbHiJvaFJLOJyHmooQ7y8hlwwQLQ/5WwCcoX0g7ii04Qi2DJlHsd0XXzJ8Ypw9+9YmQ==} + + '@docsearch/react@3.8.2': + resolution: {integrity: sha512-xCRrJQlTt8N9GU0DG4ptwHRkfnSnD/YpdeaXe02iKfqs97TkZJv60yE+1eq/tjPcVnTW8dP5qLP7itifFVV5eg==} + peerDependencies: + '@types/react': '>= 16.8.0 < 19.0.0' + react: '>= 16.8.0 < 19.0.0' + react-dom: '>= 16.8.0 < 19.0.0' + search-insights: '>= 1 < 3' + peerDependenciesMeta: + '@types/react': + optional: true + react: + optional: true + react-dom: + optional: true + search-insights: + optional: true + '@emnapi/core@1.11.2': resolution: {integrity: sha512-TC8MkTuZUtcTSiFeuC0ksCh9QIJ5+F21MvZ4Wn4ORfYaFJ/0dsiudv5tVkejgwZlwQ39jL9WWDe2lz8x0WglOA==} @@ -349,6 +510,171 @@ packages: '@emnapi/wasi-threads@1.2.2': resolution: {integrity: sha512-c95qOXkHdydNKhscBTebqEC1CVAZpyqOfVfBzQ1qgzyl3gfeldUjIggDbIZgDKsHLgnsM+igH7TJ/eAasaVuMA==} + '@esbuild/aix-ppc64@0.25.12': + resolution: {integrity: sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [aix] + + '@esbuild/android-arm64@0.25.12': + resolution: {integrity: sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [android] + + '@esbuild/android-arm@0.25.12': + resolution: {integrity: sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==} + engines: {node: '>=18'} + cpu: [arm] + os: [android] + + '@esbuild/android-x64@0.25.12': + resolution: {integrity: sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==} + engines: {node: '>=18'} + cpu: [x64] + os: [android] + + '@esbuild/darwin-arm64@0.25.12': + resolution: {integrity: sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [darwin] + + '@esbuild/darwin-x64@0.25.12': + resolution: {integrity: sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==} + engines: {node: '>=18'} + cpu: [x64] + os: [darwin] + + '@esbuild/freebsd-arm64@0.25.12': + resolution: {integrity: sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [freebsd] + + '@esbuild/freebsd-x64@0.25.12': + resolution: {integrity: sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [freebsd] + + '@esbuild/linux-arm64@0.25.12': + resolution: {integrity: sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==} + engines: {node: '>=18'} + cpu: [arm64] + os: [linux] + + '@esbuild/linux-arm@0.25.12': + resolution: {integrity: sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==} + engines: {node: '>=18'} + cpu: [arm] + os: [linux] + + '@esbuild/linux-ia32@0.25.12': + resolution: {integrity: sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==} + engines: {node: '>=18'} + cpu: [ia32] + os: [linux] + + '@esbuild/linux-loong64@0.25.12': + resolution: {integrity: sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==} + engines: {node: '>=18'} + cpu: [loong64] + os: [linux] + + '@esbuild/linux-mips64el@0.25.12': + resolution: {integrity: sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==} + engines: {node: '>=18'} + cpu: [mips64el] + os: [linux] + + '@esbuild/linux-ppc64@0.25.12': + resolution: {integrity: sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [linux] + + '@esbuild/linux-riscv64@0.25.12': + resolution: {integrity: sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==} + engines: {node: '>=18'} + cpu: [riscv64] + os: [linux] + + '@esbuild/linux-s390x@0.25.12': + resolution: {integrity: sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==} + engines: {node: '>=18'} + cpu: [s390x] + os: [linux] + + '@esbuild/linux-x64@0.25.12': + resolution: {integrity: sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==} + engines: {node: '>=18'} + cpu: [x64] + os: [linux] + + '@esbuild/netbsd-arm64@0.25.12': + resolution: {integrity: sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [netbsd] + + '@esbuild/netbsd-x64@0.25.12': + resolution: {integrity: sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [netbsd] + + '@esbuild/openbsd-arm64@0.25.12': + resolution: {integrity: sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openbsd] + + '@esbuild/openbsd-x64@0.25.12': + resolution: {integrity: sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==} + engines: {node: '>=18'} + cpu: [x64] + os: [openbsd] + + '@esbuild/openharmony-arm64@0.25.12': + resolution: {integrity: sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openharmony] + + '@esbuild/sunos-x64@0.25.12': + resolution: {integrity: sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==} + engines: {node: '>=18'} + cpu: [x64] + os: [sunos] + + '@esbuild/win32-arm64@0.25.12': + resolution: {integrity: sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [win32] + + '@esbuild/win32-ia32@0.25.12': + resolution: {integrity: sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==} + engines: {node: '>=18'} + cpu: [ia32] + os: [win32] + + '@esbuild/win32-x64@0.25.12': + resolution: {integrity: sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==} + engines: {node: '>=18'} + cpu: [x64] + os: [win32] + + '@gerrit0/mini-shiki@3.23.0': + resolution: {integrity: sha512-bEMORlG0cqdjVyCEuU0cDQbORWX+kYCeo0kV1lbxF5bt4r7SID2l9bqsxJEM0zndaxpOUT7riCyIVEuqq/Ynxg==} + + '@iconify-json/simple-icons@1.2.93': + resolution: {integrity: sha512-/XhANjfGYOuqvSR3TmUnkQkINvQ4GVjVuukvymRbxtVFBvIq/yiXJqCDycKcQPT401OYT9H2vIY6ihAlz1QIAw==} + + '@iconify/types@2.0.0': + resolution: {integrity: sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==} + '@inquirer/external-editor@1.0.3': resolution: {integrity: sha512-RWbSrDiYmO4LbejWY7ttpxczuwQyZLBUyygsA9Nsv95hpzUWwnNTVQmAq3xuh7vNwCp07UTmE5i11XAEExx4RA==} engines: {node: '>=18'} @@ -374,6 +700,13 @@ packages: '@manypkg/get-packages@1.1.3': resolution: {integrity: sha512-fo+QhuU3qE/2TQMQmbVMqaQ6EWbMhi4ABWP+O4AM1NqPBuy0OrApV5LO6BrrgnhtAHS2NH6RrVk9OL181tTi8A==} + '@napi-rs/lzma-linux-x64-gnu@1.5.1': + resolution: {integrity: sha512-oTXEIha4SsuXdTA4Iyskj0kpdx2yVXdhd75c2v3xGrHFfVMsbhTPZU/nMPL4sWKo4pBHm3aucLaqGlF696dTyQ==} + engines: {node: ^22.20 || ^24.12 || >=25} + cpu: [x64] + os: [linux] + libc: [glibc] + '@napi-rs/wasm-runtime@1.2.2': resolution: {integrity: sha512-JfB4kuJQjaoHuCTseIINHtHWeJnvgEcxjwA5t/Y00ZgaOO1Crz3fjT/p8kT28zA/Caz7oiUMn3d6H2yOVCVwuw==} engines: {node: ^20.19.0 || ^22.13.0 || >=23.5.0} @@ -1006,91 +1339,286 @@ packages: '@rolldown/pluginutils@1.0.1': resolution: {integrity: sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==} - '@simple-libs/child-process-utils@2.0.0': - resolution: {integrity: sha512-dvNoRKLijXnD0XoJAz94pbNuB5GQgDr55UhpSPhffDkTT0Cmcqh9jSCOtwfT2d4H6MI9E7c4SgtMuJXZ6F3c6A==} - engines: {node: '>=22'} - - '@simple-libs/stream-utils@2.0.0': - resolution: {integrity: sha512-fCTuZK4QBa+39Oz9l4OGfJfz+GpwCp3AqO7Zch3to99xHPgstVsRFpeQ8LNd2o1Gv8raL2mCFwiaHh7bFSp5DQ==} - engines: {node: '>=22'} - - '@standard-schema/spec@1.1.0': - resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==} - - '@standardserver/aws-lambda@0.7.1': - resolution: {integrity: sha512-fuwAx2M2O5Bnjk2JdFrtEQALmBwVtnn4jKApzFVmlIivWA7EGMj5kOzCNaJizxCQXlhPmC+doDHqf/H7FKMaNA==} - - '@standardserver/core@0.7.1': - resolution: {integrity: sha512-ZMoFDR92p9HnaI6vXK1iNFKXyLK8/6r3D4EJUM+SqeyReUH3OEJO4CZKU8BfXyzAV1A6Nsa7y2dGqDOYqH5LlQ==} - - '@standardserver/fastify@0.7.1': - resolution: {integrity: sha512-Oa+ttR0CyNkFjNczs2dO/WFFeZ4sAszVBKIOhKb1FFcDtD9VdqDgMBhbQ4sFR885fwpYckoYjFU6xXWWTueBlw==} - peerDependencies: - fastify: '>=5.6.1' - peerDependenciesMeta: - fastify: - optional: true - - '@standardserver/fetch@0.7.1': - resolution: {integrity: sha512-BeiAWESedv0woYpoBHCnq2Y3xLZZ3voFahdzpFd+HqLyenXIL4XX3z7/WgWNQnf+WsSQrK6HzBkDWCicCXVoKQ==} - - '@standardserver/node@0.7.1': - resolution: {integrity: sha512-Ikc07cGBTJ8tJgPd1OanNKVNpijcbixB1iKk0GdL/b1vkYbriGgNW3oHvbApM7+XqeCeNHj5XawHk6q90mwEEA==} + '@rollup/rollup-android-arm-eabi@4.62.4': + resolution: {integrity: sha512-RrPokAb7dmbxFoeO3TloqHyOjgye8RkBhSqmp4aJMIex4c9r46ZstPnleDQOq1t46VOVjwIuwNogIqbodV1Vvg==} + cpu: [arm] + os: [android] - '@standardserver/peer@0.7.1': - resolution: {integrity: sha512-ggqPbwz4X4GIziQgoyCTDHFw9nM9YuEvlSpO21pfoXLYF80ijtpN/iq4P0zKpb4kcXnBoSVDRUSnBJSZi0SJDg==} + '@rollup/rollup-android-arm64@4.62.4': + resolution: {integrity: sha512-JKuJc+pnpks2pjy7L/N3v/cAkZxYlnmuZoD840ldbMI5KDbC4iO9NKwPKYdjYFCMAIIlBzYSFHxIJVYzRo2/8A==} + cpu: [arm64] + os: [android] - '@standardserver/shared@0.7.1': - resolution: {integrity: sha512-tBDheI3Me1gQEKPU+XhcCZ6/njmkKgJhA5rhi1/m6GauGhHq87UuVslDNc8qB+T/xsxVch/qETFhssEWO9c6BA==} + '@rollup/rollup-darwin-arm64@4.62.4': + resolution: {integrity: sha512-krw5uS2STmvJ02x0uTXHbqQNuz+9eZ1iw+qXk9dmW2gvV4jV7O2hEoOnuhFrpOPiel1mBFtqbxYZZtC46hXLOw==} + cpu: [arm64] + os: [darwin] - '@turbo/darwin-64@2.10.8': - resolution: {integrity: sha512-po+7rfJfUnFXjWlcoN2RwhErgzCdRtBc1T26vYPcywHlggmCQiQe1uWaE4j+BibI2uY9/2pDoFzMN0rmSaPFOw==} + '@rollup/rollup-darwin-x64@4.62.4': + resolution: {integrity: sha512-wsTxtgApb4PrOsNJIm0FZ1h3WvCC+k9uxLJ4ad75hgoS4NiRes2SoJFlDAyMwiUY8IssDqGcHbXuN0sx1tfF1A==} cpu: [x64] os: [darwin] - '@turbo/darwin-arm64@2.10.8': - resolution: {integrity: sha512-+zB2btDJ00lnPRuqOvpVvgl4x34k/djZQGZTTCfjn7JgNCl8QFY5Njo5+dqkY1g/+9gbbsnAvWm9CmJg9ebcXA==} + '@rollup/rollup-freebsd-arm64@4.62.4': + resolution: {integrity: sha512-GUOnQlyZe3yAXhWOtOMsn5Qkrv5E5mZXa0thbARWi5Ei2szlVXJFQhddZ4HbAzh8q92w5twp+CQvs/eFanz9YQ==} cpu: [arm64] - os: [darwin] + os: [freebsd] - '@turbo/linux-64@2.10.8': - resolution: {integrity: sha512-K1dxqiVisyN7cViVsfQLs6xscQbYuI8aO2nbUhFURDACgEDfZRdP/b4CCxeosBJpcMfhYyiibWqJorCnvz9kKg==} + '@rollup/rollup-freebsd-x64@4.62.4': + resolution: {integrity: sha512-/Y7f3QuxjzPKsjA/rfEDa3+0vXqyjmJ50Ln8dPpCmWkKTrUoWHG1cWhTqaAMLob2m2nESWuC7yGrREz019Ztqg==} cpu: [x64] - os: [android, linux] + os: [freebsd] - '@turbo/linux-arm64@2.10.8': - resolution: {integrity: sha512-Gi77ibVnrE1fEmvr+/wBD/yvRqhwp/RQuCp2+//lv1U1wNFFyVg0V7Wj8FG9FXPFAw5QHReo8rxc9+wBSDZjzA==} - cpu: [arm64] - os: [android, linux] + '@rollup/rollup-linux-arm-gnueabihf@4.62.4': + resolution: {integrity: sha512-81wiiX3v7aqy+T+bT61TJ78yJjRquqFFTTbAPt08imfQQzkPIW8t6aJbkTagtCCrXMNc9D66+geqlK7ydLPNqA==} + cpu: [arm] + os: [linux] + libc: [glibc] - '@turbo/windows-64@2.10.8': - resolution: {integrity: sha512-znnLO1haJPYTHoKMKwlAvlkjRiYbbhBzME6wIGaMd+fwir23U6jVd1ecaTWWi1fbnRVqxMfgDBKseQ/hLKb83g==} - cpu: [x64] - os: [win32] + '@rollup/rollup-linux-arm-musleabihf@4.62.4': + resolution: {integrity: sha512-9kmDIvNZqdoHOBZgNtpTBeLWYO/LVipM3H/j62P8848/l/VPEQL6N3uxU9pvP1oZAsXyC2MEnFP3ovRjo7WYNQ==} + cpu: [arm] + os: [linux] + libc: [musl] - '@turbo/windows-arm64@2.10.8': - resolution: {integrity: sha512-VN30vh3b3Czh2WzYHNTfF1FE0YMZ5aHsLO8dBMGHJewA6792wX6iJR8ZxlzFW6WdOu0gEAKIvlYhfyT81Wkm4Q==} + '@rollup/rollup-linux-arm64-gnu@4.62.4': + resolution: {integrity: sha512-CcnXHWnXg69g+DX5VWL3FHts3qMRN2uVEHX+BZvGLdd07/gXkn3ePjYtO1LDJvxkGKVHMclKBRa1QUTH+6toYQ==} cpu: [arm64] - os: [win32] - - '@tybys/wasm-util@0.10.3': - resolution: {integrity: sha512-F3fo1MYrRJYL3zER0OUOmkutjr1Vp23m7OsSgp7nq4SP6OqX6C/56XFIPAl5bt3zaBRjmW7SGz3u/6LwFpYcOg==} + os: [linux] + libc: [glibc] - '@types/chai@5.2.3': - resolution: {integrity: sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==} + '@rollup/rollup-linux-arm64-musl@4.62.4': + resolution: {integrity: sha512-iFOibiHnTRuhrWLlRsOQFdZJJIa7S8OwkneJr4ocALP16u5yk6lWLINFwhHaEqBFMsKDUZofLkGos7+CPzGB3g==} + cpu: [arm64] + os: [linux] + libc: [musl] - '@types/deep-eql@4.0.2': - resolution: {integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==} + '@rollup/rollup-linux-loong64-gnu@4.62.4': + resolution: {integrity: sha512-XnWYMI7euHlb5a871xPja+Gm7DRCFU+FGRrtS2sMq9N8FvqtpagUy6gD4YOemC5MRk9xbh8+jYMEJbigFQwsgA==} + cpu: [loong64] + os: [linux] + libc: [glibc] - '@types/estree@1.0.9': - resolution: {integrity: sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==} + '@rollup/rollup-linux-loong64-musl@4.62.4': + resolution: {integrity: sha512-qGDAlO0U8xedCcsdRm9oaoQY8DAx/QT7uIxJWhCdx0ceIWX783UC9QSYkdpzAe29wNiVfp24+bZdQmn49o45SQ==} + cpu: [loong64] + os: [linux] + libc: [musl] - '@types/node@12.20.55': - resolution: {integrity: sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==} + '@rollup/rollup-linux-ppc64-gnu@4.62.4': + resolution: {integrity: sha512-ru4H6ezD7ysA5EiEK6qkkaEb4modH8CTej6kUy/gQi20u3kB3G7Zn8snXXkeJSCOFKG/rbPPtM/+9Wgas1961w==} + cpu: [ppc64] + os: [linux] + libc: [glibc] - '@types/node@26.1.2': + '@rollup/rollup-linux-ppc64-musl@4.62.4': + resolution: {integrity: sha512-2W4MO5WQVJnbJaZdvDb9rhBDuFU1nKIepPFpJUBsTh2k1YY2g+ODViaWuyOAjQ5cOP7NvrvLzt3wvHOoiAvc7w==} + cpu: [ppc64] + os: [linux] + libc: [musl] + + '@rollup/rollup-linux-riscv64-gnu@4.62.4': + resolution: {integrity: sha512-+fxjfuoAmVMCYV5QyjoIpu0cp5DOiOTeqYFk1AVaxGr+/ravWLX89XfQmptsoWcaVy/TGf2hexzbUOrCQIL1CQ==} + cpu: [riscv64] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-riscv64-musl@4.62.4': + resolution: {integrity: sha512-jTn8JfHGL4djjFxPuM06LmNUJDsst2jeVlsd9OmIH6zc5sC9K6rIuO4YajXatLUpBmBKl6b35ro1QZocLi+tcA==} + cpu: [riscv64] + os: [linux] + libc: [musl] + + '@rollup/rollup-linux-s390x-gnu@4.62.4': + resolution: {integrity: sha512-oCJCJL4pXsoDcP2QZ+JVlPTIRc6266zsIaeJJsWImmF7HO0W8nb6HuSgZlMWxJwaPf8ehbSw8yo0EUw925hKsA==} + cpu: [s390x] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-x64-gnu@4.62.4': + resolution: {integrity: sha512-W69hukhZ3KKNRCaMIEzKvcFye42hh0FE1+YoYaf5+Ikacuftoco6yO/xouz0hc5d5W/s3yBro5jRiuEE/Q5vUw==} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-x64-musl@4.62.4': + resolution: {integrity: sha512-qiXbGG2jkjXhzXpsFZSR2Xpb8DN/UaxYsbb/STbuR/6fpaDgRmmaq1B/LmtF2wQFOFOSsK2jdE0RZ3a0zHn4QA==} + cpu: [x64] + os: [linux] + libc: [musl] + + '@rollup/rollup-openbsd-x64@4.62.4': + resolution: {integrity: sha512-nWeM//hxv8mIo6jD7Hu4o48DVmV9pbV6gsKaWU+4NFyqHoPKwrkRiZGLKUhOBk8qNmDmpwFtPKg80Bo/Tn4xiQ==} + cpu: [x64] + os: [openbsd] + + '@rollup/rollup-openharmony-arm64@4.62.4': + resolution: {integrity: sha512-s62SQ/vgsRSvMwDkOEfTqfgASF0f26ZNaQuTA6Aok5lrikf89yI2W0gFHvZb2Jpgc6N8JnOKZgCK2iciO3CsxQ==} + cpu: [arm64] + os: [openharmony] + + '@rollup/rollup-win32-arm64-msvc@4.62.4': + resolution: {integrity: sha512-J6wGf8TVGbXJq+HH+ttTvrcfNKPbuZecV6KT1B8I18BC5IURUh5kl4Yl5OEP5eFIUoI5BWxCsyYMhFsDx8kekw==} + cpu: [arm64] + os: [win32] + + '@rollup/rollup-win32-ia32-msvc@4.62.4': + resolution: {integrity: sha512-zmfrQd/0wu6oJs8Vq8KwY/YtsKSsLtKe/HwAP4Wqy8LhWjeT55fHRAkOhYQ12wI3ayS4Tt12d5CDRD7N96SAYQ==} + cpu: [ia32] + os: [win32] + + '@rollup/rollup-win32-x64-gnu@4.62.4': + resolution: {integrity: sha512-qPzHqdj9rfUD+w79dtE07zi/kFwKyCJqplp5K5ygeLTp7jLpAoc16OAH39HSmRC9UpozaecsleI8uAdEj6v2yw==} + cpu: [x64] + os: [win32] + + '@rollup/rollup-win32-x64-msvc@4.62.4': + resolution: {integrity: sha512-zD6NdeWEByGE9QF9vCrlJ5YQB4oq9q91kPZS37Jwj5hOkvR1lTBSpsKhKDw4IJtbQ35LsTS1HD9DZYGKIshU1Q==} + cpu: [x64] + os: [win32] + + '@shikijs/core@2.5.0': + resolution: {integrity: sha512-uu/8RExTKtavlpH7XqnVYBrfBkUc20ngXiX9NSrBhOVZYv/7XQRKUyhtkeflY5QsxC0GbJThCerruZfsUaSldg==} + + '@shikijs/engine-javascript@2.5.0': + resolution: {integrity: sha512-VjnOpnQf8WuCEZtNUdjjwGUbtAVKuZkVQ/5cHy/tojVVRIRtlWMYVjyWhxOmIq05AlSOv72z7hRNRGVBgQOl0w==} + + '@shikijs/engine-oniguruma@2.5.0': + resolution: {integrity: sha512-pGd1wRATzbo/uatrCIILlAdFVKdxImWJGQ5rFiB5VZi2ve5xj3Ax9jny8QvkaV93btQEwR/rSz5ERFpC5mKNIw==} + + '@shikijs/engine-oniguruma@3.23.0': + resolution: {integrity: sha512-1nWINwKXxKKLqPibT5f4pAFLej9oZzQTsby8942OTlsJzOBZ0MWKiwzMsd+jhzu8YPCHAswGnnN1YtQfirL35g==} + + '@shikijs/langs@2.5.0': + resolution: {integrity: sha512-Qfrrt5OsNH5R+5tJ/3uYBBZv3SuGmnRPejV9IlIbFH3HTGLDlkqgHymAlzklVmKBjAaVmkPkyikAV/sQ1wSL+w==} + + '@shikijs/langs@3.23.0': + resolution: {integrity: sha512-2Ep4W3Re5aB1/62RSYQInK9mM3HsLeB91cHqznAJMuylqjzNVAVCMnNWRHFtcNHXsoNRayP9z1qj4Sq3nMqYXg==} + + '@shikijs/themes@2.5.0': + resolution: {integrity: sha512-wGrk+R8tJnO0VMzmUExHR+QdSaPUl/NKs+a4cQQRWyoc3YFbUzuLEi/KWK1hj+8BfHRKm2jNhhJck1dfstJpiw==} + + '@shikijs/themes@3.23.0': + resolution: {integrity: sha512-5qySYa1ZgAT18HR/ypENL9cUSGOeI2x+4IvYJu4JgVJdizn6kG4ia5Q1jDEOi7gTbN4RbuYtmHh0W3eccOrjMA==} + + '@shikijs/transformers@2.5.0': + resolution: {integrity: sha512-SI494W5X60CaUwgi8u4q4m4s3YAFSxln3tzNjOSYqq54wlVgz0/NbbXEb3mdLbqMBztcmS7bVTaEd2w0qMmfeg==} + + '@shikijs/types@2.5.0': + resolution: {integrity: sha512-ygl5yhxki9ZLNuNpPitBWvcy9fsSKKaRuO4BAlMyagszQidxcpLAr0qiW/q43DtSIDxO6hEbtYLiFZNXO/hdGw==} + + '@shikijs/types@3.23.0': + resolution: {integrity: sha512-3JZ5HXOZfYjsYSk0yPwBrkupyYSLpAE26Qc0HLghhZNGTZg/SKxXIIgoxOpmmeQP0RRSDJTk1/vPfw9tbw+jSQ==} + + '@shikijs/vscode-textmate@10.0.2': + resolution: {integrity: sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==} + + '@simple-libs/child-process-utils@2.0.0': + resolution: {integrity: sha512-dvNoRKLijXnD0XoJAz94pbNuB5GQgDr55UhpSPhffDkTT0Cmcqh9jSCOtwfT2d4H6MI9E7c4SgtMuJXZ6F3c6A==} + engines: {node: '>=22'} + + '@simple-libs/stream-utils@2.0.0': + resolution: {integrity: sha512-fCTuZK4QBa+39Oz9l4OGfJfz+GpwCp3AqO7Zch3to99xHPgstVsRFpeQ8LNd2o1Gv8raL2mCFwiaHh7bFSp5DQ==} + engines: {node: '>=22'} + + '@standard-schema/spec@1.1.0': + resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==} + + '@standardserver/aws-lambda@0.7.1': + resolution: {integrity: sha512-fuwAx2M2O5Bnjk2JdFrtEQALmBwVtnn4jKApzFVmlIivWA7EGMj5kOzCNaJizxCQXlhPmC+doDHqf/H7FKMaNA==} + + '@standardserver/core@0.7.1': + resolution: {integrity: sha512-ZMoFDR92p9HnaI6vXK1iNFKXyLK8/6r3D4EJUM+SqeyReUH3OEJO4CZKU8BfXyzAV1A6Nsa7y2dGqDOYqH5LlQ==} + + '@standardserver/fastify@0.7.1': + resolution: {integrity: sha512-Oa+ttR0CyNkFjNczs2dO/WFFeZ4sAszVBKIOhKb1FFcDtD9VdqDgMBhbQ4sFR885fwpYckoYjFU6xXWWTueBlw==} + peerDependencies: + fastify: '>=5.6.1' + peerDependenciesMeta: + fastify: + optional: true + + '@standardserver/fetch@0.7.1': + resolution: {integrity: sha512-BeiAWESedv0woYpoBHCnq2Y3xLZZ3voFahdzpFd+HqLyenXIL4XX3z7/WgWNQnf+WsSQrK6HzBkDWCicCXVoKQ==} + + '@standardserver/node@0.7.1': + resolution: {integrity: sha512-Ikc07cGBTJ8tJgPd1OanNKVNpijcbixB1iKk0GdL/b1vkYbriGgNW3oHvbApM7+XqeCeNHj5XawHk6q90mwEEA==} + + '@standardserver/peer@0.7.1': + resolution: {integrity: sha512-ggqPbwz4X4GIziQgoyCTDHFw9nM9YuEvlSpO21pfoXLYF80ijtpN/iq4P0zKpb4kcXnBoSVDRUSnBJSZi0SJDg==} + + '@standardserver/shared@0.7.1': + resolution: {integrity: sha512-tBDheI3Me1gQEKPU+XhcCZ6/njmkKgJhA5rhi1/m6GauGhHq87UuVslDNc8qB+T/xsxVch/qETFhssEWO9c6BA==} + + '@turbo/darwin-64@2.10.8': + resolution: {integrity: sha512-po+7rfJfUnFXjWlcoN2RwhErgzCdRtBc1T26vYPcywHlggmCQiQe1uWaE4j+BibI2uY9/2pDoFzMN0rmSaPFOw==} + cpu: [x64] + os: [darwin] + + '@turbo/darwin-arm64@2.10.8': + resolution: {integrity: sha512-+zB2btDJ00lnPRuqOvpVvgl4x34k/djZQGZTTCfjn7JgNCl8QFY5Njo5+dqkY1g/+9gbbsnAvWm9CmJg9ebcXA==} + cpu: [arm64] + os: [darwin] + + '@turbo/linux-64@2.10.8': + resolution: {integrity: sha512-K1dxqiVisyN7cViVsfQLs6xscQbYuI8aO2nbUhFURDACgEDfZRdP/b4CCxeosBJpcMfhYyiibWqJorCnvz9kKg==} + cpu: [x64] + os: [android, linux] + + '@turbo/linux-arm64@2.10.8': + resolution: {integrity: sha512-Gi77ibVnrE1fEmvr+/wBD/yvRqhwp/RQuCp2+//lv1U1wNFFyVg0V7Wj8FG9FXPFAw5QHReo8rxc9+wBSDZjzA==} + cpu: [arm64] + os: [android, linux] + + '@turbo/windows-64@2.10.8': + resolution: {integrity: sha512-znnLO1haJPYTHoKMKwlAvlkjRiYbbhBzME6wIGaMd+fwir23U6jVd1ecaTWWi1fbnRVqxMfgDBKseQ/hLKb83g==} + cpu: [x64] + os: [win32] + + '@turbo/windows-arm64@2.10.8': + resolution: {integrity: sha512-VN30vh3b3Czh2WzYHNTfF1FE0YMZ5aHsLO8dBMGHJewA6792wX6iJR8ZxlzFW6WdOu0gEAKIvlYhfyT81Wkm4Q==} + cpu: [arm64] + os: [win32] + + '@tybys/wasm-util@0.10.3': + resolution: {integrity: sha512-F3fo1MYrRJYL3zER0OUOmkutjr1Vp23m7OsSgp7nq4SP6OqX6C/56XFIPAl5bt3zaBRjmW7SGz3u/6LwFpYcOg==} + + '@types/chai@5.2.3': + resolution: {integrity: sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==} + + '@types/deep-eql@4.0.2': + resolution: {integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==} + + '@types/estree@1.0.9': + resolution: {integrity: sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==} + + '@types/hast@3.0.5': + resolution: {integrity: sha512-rp/ezSWaD1m44dPKICGhiskI13nVr7qTloFwDa/IYkhhf5nzwP+zIQcIJh3WIFSBOy/H1PzB40jPjMDksN4F+g==} + + '@types/linkify-it@5.0.0': + resolution: {integrity: sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q==} + + '@types/markdown-it@14.1.2': + resolution: {integrity: sha512-promo4eFwuiW+TfGxhi+0x3czqTYJkG8qB17ZUJiVF10Xm7NLVRSLUsfRTU/6h1e24VvRnXCx+hG7li58lkzog==} + + '@types/mdast@4.0.4': + resolution: {integrity: sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==} + + '@types/mdurl@2.0.0': + resolution: {integrity: sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg==} + + '@types/node@12.20.55': + resolution: {integrity: sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==} + + '@types/node@26.1.2': resolution: {integrity: sha512-Vu4a5UFA9rIIFJ7rB/Vaafh9lrCQszopTCx6KjFboXTGQbPNasehVR5TEiithSDGyd1DEiUByggTZsg8jukeIg==} + '@types/unist@3.0.3': + resolution: {integrity: sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==} + + '@types/web-bluetooth@0.0.21': + resolution: {integrity: sha512-oIQLCGWtcFZy2JW77j9k8nHzAOpqMHLQejDA48XXMWH6tjCQHz5RCFz1bzsmROyL6PUm+LLnUiI4BCn221inxA==} + '@typescript/typescript-aix-ppc64@7.0.2': resolution: {integrity: sha512-MTKKkWB7p/0E9xi1d1tHtZ5PiLkGEMIq88pK2CubZjOsLtYTLqhgIgi6zepFa+9GHZ6h05NMCkQxGKiPXMxXtQ==} engines: {node: '>=16.20.0'} @@ -1211,6 +1739,9 @@ packages: cpu: [x64] os: [win32] + '@ungap/structured-clone@1.3.3': + resolution: {integrity: sha512-60YRaenCQcVjYEKOcG824+DRGGIQ3VKErcBoAEDJZz5bKIs2ZG+X/H9Nk+Q6EVkwJk5QNApxbrc5QtBSwtrXAg==} + '@unthrown/oxlint@5.1.0': resolution: {integrity: sha512-xTbO9Qoz5W0J7Ur+vFiKAw8buxd6gCaOt16dYkVuNHIyiROl/fL5S9hCQkxduLYReiVATMOis4cgh0KnQy4HIQ==} engines: {node: '>=20'} @@ -1228,6 +1759,13 @@ packages: unthrown: ^5.1.0 vitest: ^4 + '@vitejs/plugin-vue@5.2.4': + resolution: {integrity: sha512-7Yx/SXSOcQq5HiiV3orevHUFn+pmMB4cgbEkDYgnkUWb0WfeQ/wa2yFv6D5ICiCQOVpjA7vYDXrC7AGO8yjDHA==} + engines: {node: ^18.0.0 || >=20.0.0} + peerDependencies: + vite: 6.4.3 + vue: ^3.2.25 + '@vitest/coverage-v8@4.1.10': resolution: {integrity: sha512-IM49HmthevbgAO4anp1hwtoT9wYe59w0LR00gr+eagHE+ZJ5lK4sLPeO0ubgoJcwLk6dehU3R24N+FbEEKDc8g==} peerDependencies: @@ -1244,7 +1782,7 @@ packages: resolution: {integrity: sha512-v0xaezt+DKEmKfaxg133ldzADrwLGd7Ze1MfQQTYfvs8OqZIwbxyxaYURivwV7sWy5fqn3rH5uOrSp07bp44Ow==} peerDependencies: msw: ^2.4.9 - vite: ^6.0.0 || ^7.0.0 || ^8.0.0 + vite: 6.4.3 peerDependenciesMeta: msw: optional: true @@ -1266,6 +1804,92 @@ packages: '@vitest/utils@4.1.10': resolution: {integrity: sha512-fy9am/HWxbaGt/Sawrp90vt6Y6jQwf1RX77cz3uwoJwJVMli/e1IEwRPnMNJ7vKfPTwo0diXifkpPvwH9v7nGA==} + '@vue/compiler-core@3.5.41': + resolution: {integrity: sha512-q0Xtv/F9w2YO/7htQhtiL+Ev2WCJbe5N2hc+XfgyKkEKqWpSxknmT8QOuGdEKNdjPq0c3F7rNpFkTo3Kfrm7pg==} + + '@vue/compiler-dom@3.5.41': + resolution: {integrity: sha512-oKacVfNglLvGjnS6BXOlGL7EyG2h8X03pqXCjzotRZUaXGjbrTJUnVAQjrCqUnS+lyu31nwQjZY/d817GmCnfw==} + + '@vue/compiler-sfc@3.5.41': + resolution: {integrity: sha512-XJhip7R2wy6vX3knCxdZN4KracFaZUef58s1KYewqluedHIJaPIVfXoYT7MF1F8nCvv6k8bWWxDC8opMkg1VTQ==} + + '@vue/compiler-ssr@3.5.41': + resolution: {integrity: sha512-U3v5OejKEGqOI0Wy0+Sz7hGuIFZHA4LSXzrNM3IMIeDyJEBBfTpX26n3SDgToRpP2bLc9FfI2j/kSgcJ8Emq5A==} + + '@vue/devtools-api@7.7.10': + resolution: {integrity: sha512-KxtEpUOOpFz/qOGRrAwA36QF7DqIA+FXgCYit9mk9wjbaZt0sXOFz81ElOZtKA4HbWHUdwNjZHBFsFFyp5BZiA==} + + '@vue/devtools-kit@7.7.10': + resolution: {integrity: sha512-3WNi2Kq4tbpVbmhml7RiphmAt0279oh3fKNeWMQIrltfX8Q91b4i5PL8DtyNKdwmcsGrV4fg+erwWOmD05CLIw==} + + '@vue/devtools-shared@7.7.10': + resolution: {integrity: sha512-wOPslzB8vTvpxwdaOcR2qAbwmuSP0L+rhpoC6Cf56V3Jip+HWb7PQQXOUPgBNQARpXsbQX/+mvi8kKucmBGRwQ==} + + '@vue/reactivity@3.5.41': + resolution: {integrity: sha512-rznsqKM0np0x18EjzF8x88MpEhdNsffbvFbckLL5+oUKz1BxAImEmO7J1ArRYSyo6aQaVoBDp7jEkT91OOxydA==} + + '@vue/runtime-core@3.5.41': + resolution: {integrity: sha512-Vcry58hiAKwGen9Z1jUZE0feFsNArPCMOImYI8el48A9Idf6DuQYD0U05zZIF2Iad1hGhPSvcbBbAOhNr55fhg==} + + '@vue/runtime-dom@3.5.41': + resolution: {integrity: sha512-3vVBahVBS9+U6cmXBLyb8nE6/yYo4J/CGI9eVFs3KiMc0YHuudwKyShTD65jtJy/L9PUUxNAFu4cj4LiJ0UFbw==} + + '@vue/server-renderer@3.5.41': + resolution: {integrity: sha512-n6hx/pNFfbD6SuyeuMVkvqox8bwf/ET9JlA/kAz/imw8sw++wkqKe2mHX5KutjPpbKE4Z56yTHszoOjGMI9igQ==} + + '@vue/shared@3.5.41': + resolution: {integrity: sha512-IOnwSCma8j+9xJT6b8H0dEYidC80NsYmNMlZxRsukYcSoGaDBohog5hDxzeUXdFeGWFA++vWvxqOmrr96VlqMA==} + + '@vueuse/core@12.8.2': + resolution: {integrity: sha512-HbvCmZdzAu3VGi/pWYm5Ut+Kd9mn1ZHnn4L5G8kOQTPs/IwIAmJoBrmYk2ckLArgMXZj0AW3n5CAejLUO+PhdQ==} + + '@vueuse/integrations@12.8.2': + resolution: {integrity: sha512-fbGYivgK5uBTRt7p5F3zy6VrETlV9RtZjBqd1/HxGdjdckBgBM4ugP8LHpjolqTj14TXTxSK1ZfgPbHYyGuH7g==} + peerDependencies: + async-validator: ^4 + axios: ^1 + change-case: ^5 + drauu: ^0.4 + focus-trap: ^7 + fuse.js: ^7 + idb-keyval: ^6 + jwt-decode: ^4 + nprogress: ^0.2 + qrcode: ^1.5 + sortablejs: ^1 + universal-cookie: ^7 + peerDependenciesMeta: + async-validator: + optional: true + axios: + optional: true + change-case: + optional: true + drauu: + optional: true + focus-trap: + optional: true + fuse.js: + optional: true + idb-keyval: + optional: true + jwt-decode: + optional: true + nprogress: + optional: true + qrcode: + optional: true + sortablejs: + optional: true + universal-cookie: + optional: true + + '@vueuse/metadata@12.8.2': + resolution: {integrity: sha512-rAyLGEuoBJ/Il5AmFHiziCPdQzRt88VxR+Y/A/QhJ1EWtWqPBBAxTAFaSkviwEuOEZNtW8pvkPgoCZQ+HxqW1A==} + + '@vueuse/shared@12.8.2': + resolution: {integrity: sha512-dznP38YzxZoNloI0qpEfpkms8knDtaoQ6Y/sfS0L7Yki4zh40LFHEhur0odJC6xTHG5dxWVPiUWBXn+wCG2s5w==} + '@yuku-codegen/binding-android-arm64@0.8.3': resolution: {integrity: sha512-/EKnnqwvN7xYoVDhQEIEJTdPDwGW1wkFz/2Eku3ES/IJd4lcQh/OaIDFBmoJKvpe12enrb1TIoYh1fxasGXolA==} cpu: [arm64] @@ -1404,6 +2028,10 @@ packages: ajv@8.20.0: resolution: {integrity: sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==} + algoliasearch@5.56.0: + resolution: {integrity: sha512-PrqppUmhT4ENdas2pH9caE7efUcxy6EcSFhWzosiVuQBzu2tQ5yLTI6jwomT/1cuBnivzGfxiJCqDNN9FRRh+Q==} + engines: {node: '>= 14.0.0'} + ansi-colors@4.1.3: resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==} engines: {node: '>=6'} @@ -1445,10 +2073,21 @@ packages: ast-v8-to-istanbul@1.0.5: resolution: {integrity: sha512-UPAgKJFSEGMWSDr3LX4tqnAb4f7KGT8O40Tyx8wbYmmZ/yn58lNCm8h3svs3eXgiGd5AXxz8NDOvXWvicq+rJA==} + balanced-match@4.0.4: + resolution: {integrity: sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==} + engines: {node: 18 || 20 || >=22} + better-path-resolve@1.0.0: resolution: {integrity: sha512-pbnl5XzGBdrFU/wT4jqmJVPn2B6UHPBOhzMQkY/SPUPB6QtUXtmBHBIwCbXJol93mOpGMnQyP/+BB19q04xj7g==} engines: {node: '>=4'} + birpc@2.9.0: + resolution: {integrity: sha512-KrayHS5pBi69Xi9JmvoqrIgYGDkD6mcSe/i6YKi3w5kekCLzrX4+nawcXqrj2tIp50Kw/mT/s3p+GVK0A0sKxw==} + + brace-expansion@5.0.9: + resolution: {integrity: sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg==} + engines: {node: 20 || >=22} + braces@3.0.3: resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} engines: {node: '>=8'} @@ -1461,10 +2100,19 @@ packages: resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} engines: {node: '>=6'} + ccount@2.0.1: + resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==} + chai@6.2.2: resolution: {integrity: sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==} engines: {node: '>=18'} + character-entities-html4@2.1.0: + resolution: {integrity: sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==} + + character-entities-legacy@3.0.0: + resolution: {integrity: sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==} + chardet@2.2.0: resolution: {integrity: sha512-rddelWYNPRrXq6PtNEN2S3f6t9ILzvqaN5pVgi4kqt9jHQaXIial9PznB5iSPVlQSLNaaH22ItWz3EJtQ10+OA==} @@ -1472,6 +2120,9 @@ packages: resolution: {integrity: sha512-k7ndgKhwoQveBL+/1tqGJYNz097I7WOvwbmmU2AR5+magtbjPWQTS1C5vzGkBC8Ym8UWRzfKUzUUqFLypY4Q+w==} engines: {node: '>=20'} + comma-separated-tokens@2.0.3: + resolution: {integrity: sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==} + conventional-changelog-angular@9.2.1: resolution: {integrity: sha512-oWSL6ZhnXbYraOFTK3PgRAQJ8fADDAEv5K6AdeyQPLvjFmhG8+ejL0jZZp/R7vTmGJaBvZEE+sE7dB4bCv7sAw==} engines: {node: '>=22'} @@ -1492,6 +2143,10 @@ packages: resolution: {integrity: sha512-yuToqVvRrj6pfDXREyQAAv8SkAEk/8GS3jQRTiUMm66TVtBYmqQeoEjL2Lmq8Rpo6271vH76InTChTitEAm65w==} engines: {node: '>=22'} + copy-anything@4.0.5: + resolution: {integrity: sha512-7Vv6asjS4gMOuILabD3l739tsaxFQmC+a7pLZm02zyvs8p977bL3zEgq3yDk5rn9B0PbYgIv++jmHcuUab4RhA==} + engines: {node: '>=18'} + cosmiconfig-typescript-loader@6.3.0: resolution: {integrity: sha512-Akr82WH1Wfqatyiqpj8HDkO2o2KmJRu1FhKfSNJP3K4IdXwHfEyL7MOb62i1AGQVLtIQM+iCE9CGOtrfhR+mmA==} engines: {node: '>=v18'} @@ -1513,16 +2168,22 @@ packages: resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} engines: {node: '>= 8'} + csstype@3.2.3: + resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==} + defu@6.1.7: resolution: {integrity: sha512-7z22QmUWiQ/2d0KkdYmANbRUVABpZ9SNYyH5vx6PZ+nE5bcC0l7uFvEfHlyld/HcGBFTL536ClDt3DEcSlEJAQ==} + dequal@2.0.3: + resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} + engines: {node: '>=6'} + detect-indent@6.1.0: resolution: {integrity: sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==} engines: {node: '>=8'} - detect-libc@2.1.2: - resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==} - engines: {node: '>=8'} + devlop@1.1.0: + resolution: {integrity: sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==} dir-glob@3.0.1: resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} @@ -1537,6 +2198,9 @@ packages: oxc-resolver: optional: true + emoji-regex-xs@1.0.0: + resolution: {integrity: sha512-LRlerrMYoIDrT6jgpeZ2YYl/L8EulRTt5hQcYjy5AInh7HWXKimpqx68aknBFpGL2+/IcogTcaydJEgaTmOpDg==} + emoji-regex@10.6.0: resolution: {integrity: sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==} @@ -1548,6 +2212,14 @@ packages: resolution: {integrity: sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==} engines: {node: '>=8.6'} + entities@4.5.0: + resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} + engines: {node: '>=0.12'} + + entities@7.0.1: + resolution: {integrity: sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==} + engines: {node: '>=0.12'} + env-paths@2.2.1: resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==} engines: {node: '>=6'} @@ -1561,6 +2233,11 @@ packages: es-toolkit@1.50.0: resolution: {integrity: sha512-OyZKhUVvEep9ITEiwHn8GKnMRQIVqoSIX7WnRbkWgJkllCujilqP2rD0u979tkl8wqyc8ICwlc1UBVv/Sl1G6w==} + esbuild@0.25.12: + resolution: {integrity: sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==} + engines: {node: '>=18'} + hasBin: true + escalade@3.2.0: resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} engines: {node: '>=6'} @@ -1570,6 +2247,9 @@ packages: engines: {node: '>=4'} hasBin: true + estree-walker@2.0.2: + resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} + estree-walker@3.0.3: resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} @@ -1613,6 +2293,9 @@ packages: resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} engines: {node: '>=8'} + focus-trap@7.8.0: + resolution: {integrity: sha512-/yNdlIkpWbM0ptxno3ONTuf+2g318kh2ez3KSeZN5dZ8YC6AAmgeWz+GasYYiBJPFaYcSAPeu4GfhUaChzIJXA==} + formatly@0.3.0: resolution: {integrity: sha512-9XNj/o4wrRFyhSMJOvsuyMwy8aUfBaZ1VrqHVfohyXf0Sw0e+yfKG+xZaY3arGCOMdwFsqObtzVOc1gU9KiT9w==} engines: {node: '>=18.3.0'} @@ -1665,12 +2348,24 @@ packages: resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} engines: {node: '>=8'} + hast-util-to-html@9.0.5: + resolution: {integrity: sha512-OguPdidb+fbHQSU4Q4ZiLKnzWo8Wwsf5bZfbvu7//a9oTYoqD/fWpe96NuHkoS9h0ccGOTe0C4NGXdtS0iObOw==} + + hast-util-whitespace@3.0.0: + resolution: {integrity: sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==} + + hookable@5.5.3: + resolution: {integrity: sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==} + hookable@6.1.1: resolution: {integrity: sha512-U9LYDy1CwhMCnprUfeAZWZGByVbhd54hwepegYTK7Pi5NvqEj63ifz5z+xukznehT7i6NIZRu89Ay1AZmRsLEQ==} html-escaper@2.0.2: resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} + html-void-elements@3.0.0: + resolution: {integrity: sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==} + human-id@4.2.0: resolution: {integrity: sha512-K3GbkIWqyvvlpfhBPlbEvD97TtqBpAYA4kt+cn2lD2x2HuohzZCibcA2nOlnJT6exqvJLggoB5nv2dNf192nEA==} hasBin: true @@ -1718,6 +2413,10 @@ packages: resolution: {integrity: sha512-2AT6j+gXe/1ueqbW6fLZJiIw3F8iXGJtt0yDrZaBhAZEG1raiTxKWU+IPqMCzQAXOUCKdA4UDMgacKH25XG2Cw==} engines: {node: '>=4'} + is-what@5.5.0: + resolution: {integrity: sha512-oG7cgbmg5kLYae2N5IVd3jm2s+vldjxJzK1pcu9LfpGuQ93MQSzo0okvRna+7y5ifrD+20FE8FvjusyGaz14fw==} + engines: {node: '>=18'} + is-windows@1.0.2: resolution: {integrity: sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==} engines: {node: '>=0.10.0'} @@ -1830,83 +2529,12 @@ packages: resolution: {integrity: sha512-K7mM4WoqMwqfXYK11EHy+lSH1uW8XHni3Yn/bSqyerPkUPygGdf3xn18JoV5HyA06xuQL3ofGAOjG01QX9oJ4w==} hasBin: true - lightningcss-android-arm64@1.33.0: - resolution: {integrity: sha512-gEpRTalKdosp4Bb8qWtc2iOgE5SeIHlpS1up9bFq2wAyYhl1UdTObYiHe98zEM9SQvSoqQZ1IQD0JNpg3Ml5pg==} - engines: {node: '>= 12.0.0'} - cpu: [arm64] - os: [android] - - lightningcss-darwin-arm64@1.33.0: - resolution: {integrity: sha512-Sciaz8eenNTKn9b3t7+xr0ipTp9YxKQY4npwQ3mrRuL0BAVHBLyZxofhaKBAVtzmtRZ/zTyo0/to4B1uWG/Djg==} - engines: {node: '>= 12.0.0'} - cpu: [arm64] - os: [darwin] - - lightningcss-darwin-x64@1.33.0: - resolution: {integrity: sha512-Z5UPAxzrjlWNNyGy6i65cJzzvgJ5D3T6wMvs+gWpY9d7qRhANrxqAp6LhxIgZhWEw18RfJTGcRxjuLIBr+m8XQ==} - engines: {node: '>= 12.0.0'} - cpu: [x64] - os: [darwin] - - lightningcss-freebsd-x64@1.33.0: - resolution: {integrity: sha512-QQM/Ti/hQajJwCY+RiWuCZ9sdtI/XQk7nDK5vC8kkdwixezOlDgvDx7+RT+QjK6FcFT4MpsuoBnHIo/O3StRRg==} - engines: {node: '>= 12.0.0'} - cpu: [x64] - os: [freebsd] - - lightningcss-linux-arm-gnueabihf@1.33.0: - resolution: {integrity: sha512-N7FVBe6iS24MlM6R/4RBTxGhQheZGs7tiQ9U32UtF75NzP5Q7xWPRqLBCKxlRQRk3rY1jCIPLzx7WzOhuUIRLQ==} - engines: {node: '>= 12.0.0'} - cpu: [arm] - os: [linux] - - lightningcss-linux-arm64-gnu@1.33.0: - resolution: {integrity: sha512-j2v/itmy4HlNxlc6voKXYgBqNi0Ng2LShg4z7GufpEgs05P+2suBVyi9I6YHq5uoVFx9ETin3eCEhLVyXGQnKg==} - engines: {node: '>= 12.0.0'} - cpu: [arm64] - os: [linux] - libc: [glibc] - - lightningcss-linux-arm64-musl@1.33.0: - resolution: {integrity: sha512-yiO5ROMuYQgXbC60yjZU5CYSFZGKXL0HFATXt9mHJn1+zW55oCtMI9NfcVhYLMFDL7gV7oBPon/EmMMGg2OvtQ==} - engines: {node: '>= 12.0.0'} - cpu: [arm64] - os: [linux] - libc: [musl] - - lightningcss-linux-x64-gnu@1.33.0: - resolution: {integrity: sha512-ar+Ju7LmcN0Jo4FpL4hpFybwNG9/3A/Br5KW2n2jyODg3MEZXaDYADdemoNS+BDNfMgKvylJLj4S5tyRActuAg==} - engines: {node: '>= 12.0.0'} - cpu: [x64] - os: [linux] - libc: [glibc] - - lightningcss-linux-x64-musl@1.33.0: - resolution: {integrity: sha512-RYiYbkokw0trfKqqzfF55lginwEPrD3OJDfTuJzFs1MK6iFnDenaz1fqLLtX4ITG3OktJQXOeTaw1awrBAlZPw==} - engines: {node: '>= 12.0.0'} - cpu: [x64] - os: [linux] - libc: [musl] - - lightningcss-win32-arm64-msvc@1.33.0: - resolution: {integrity: sha512-1K+MPfLSFVpphzpdbfkhlWk6wBrTObBzS2T6db10PNOZgR9GoVsAWzwNyuhUYYbTp23j+4RrncfujZ4uAzXvwA==} - engines: {node: '>= 12.0.0'} - cpu: [arm64] - os: [win32] - - lightningcss-win32-x64-msvc@1.33.0: - resolution: {integrity: sha512-OlEICDx/Xl0FqSp4bry8zFnCvGpig3Gl4gCquvYwHuqJKEC1+n9NgDniFvqHGmMv1ZkqDJrDqKKSykTDX+ehuA==} - engines: {node: '>= 12.0.0'} - cpu: [x64] - os: [win32] - - lightningcss@1.33.0: - resolution: {integrity: sha512-WkUDrojuJs0xkgGf2udWxa3yGBRxPtxUkB79i6aCZLRgc7PM8fZe9TosfPDcvEpQZbuFASnHYmRLBLUbmLOIIA==} - engines: {node: '>= 12.0.0'} - lines-and-columns@1.2.4: resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} + linkify-it@5.0.2: + resolution: {integrity: sha512-ONTm2jCMAVZjgQa/Fy1kScXsuOoF5NPTsoFBdE1KVIZ2vAh/r9+Bqo+0jINCBYnavTPQZz38QzFTme79ENoN3Q==} + locate-path@5.0.0: resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} engines: {node: '>=8'} @@ -1914,6 +2542,9 @@ packages: lodash.startcase@4.4.0: resolution: {integrity: sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg==} + lunr@2.3.9: + resolution: {integrity: sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==} + magic-string@0.30.21: resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} @@ -1924,14 +2555,52 @@ packages: resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==} engines: {node: '>=10'} + mark.js@8.11.1: + resolution: {integrity: sha512-1I+1qpDt4idfgLQG+BNWmrqku+7/2bi5nLf4YwF8y8zXvmfiTBY3PV3ZibfrjBueCByROpuBjLLFCajqkgYoLQ==} + + markdown-it@14.3.0: + resolution: {integrity: sha512-RCEsPjR+sr0x+AuYp601tKTkgFG4YEPLCzHST3cQ/fhlJkqAkz1L2/Qbp1j9qw5SBwQHFBoW8+hoN5xssOF0Tw==} + hasBin: true + + mdast-util-to-hast@13.2.1: + resolution: {integrity: sha512-cctsq2wp5vTsLIcaymblUriiTcZd0CwWtCbLvrOzYCDZoWyMNV8sZ7krj09FSnsiJi3WVsHLM4k6Dq/yaPyCXA==} + + mdurl@2.1.0: + resolution: {integrity: sha512-1+HBaOx0zi/dQWht8rNv9MYf9qqpqL/kxI0hXImU6Y547zM6Sni8BQibt7ifgMcYtQg41ao3Ivd6cnSM86inpg==} + merge2@1.4.1: resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} engines: {node: '>= 8'} + micromark-util-character@2.1.1: + resolution: {integrity: sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==} + + micromark-util-encode@2.0.1: + resolution: {integrity: sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==} + + micromark-util-sanitize-uri@2.0.1: + resolution: {integrity: sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==} + + micromark-util-symbol@2.0.1: + resolution: {integrity: sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==} + + micromark-util-types@2.0.2: + resolution: {integrity: sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA==} + micromatch@4.0.8: resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} engines: {node: '>=8.6'} + minimatch@10.2.6: + resolution: {integrity: sha512-vpLQEs+VLCr1nU0BXS07maYoFwlDAH0gngQuuttxIwutDFEMHq2blX+8vpgxDdK3J1PwjCJiep77OitTZ4Ll1A==} + engines: {node: 18 || 20 || >=22} + + minisearch@7.2.0: + resolution: {integrity: sha512-dqT2XBYUOZOiC5t2HRnwADjhNS2cecp9u+TJRiJ1Qp/f5qjkeT5APcGPjHw+bz89Ms8Jp+cG4AlE+QZ/QnDglg==} + + mitt@3.0.1: + resolution: {integrity: sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==} + mri@1.2.0: resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==} engines: {node: '>=4'} @@ -1945,6 +2614,9 @@ packages: resolution: {integrity: sha512-4a+OsYv9UktOJKE+l1A4OufDgdRF9PifWj+tJnHURo/P+WOxpG4GzUFL9qCalmWauao6ogiG+QvnCovwPoyAWA==} engines: {node: '>=12.20.0'} + oniguruma-to-es@3.1.1: + resolution: {integrity: sha512-bUH8SDvPkH3ho3dvwJwfonjlQ4R80vjyvrU8YpxuROddv55vAEJrTuCuCVUhhsHbtlD9tGGbaNApGQckXhS8iQ==} + outdent@0.5.0: resolution: {integrity: sha512-/jHxFIzoMXdqPzTaCpFzAAWhpkSjZPF4Vsn6jAfNpmbH/ymsmd7Qc6VE9BGn0L6YMj6uwpQLxCECpus4ukKS9Q==} @@ -2027,6 +2699,9 @@ packages: pathe@2.0.3: resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} + perfect-debounce@1.0.0: + resolution: {integrity: sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==} + picocolors@1.1.1: resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} @@ -2046,11 +2721,26 @@ packages: resolution: {integrity: sha512-DTPx3RWSSnWyzLxQnlH0rJP+EW5ekl16ZU4/psbIhA0e53kJfdgaN5vKM+xP7yJtXVu+nfdVFmlgFDEKAe4Pyw==} engines: {node: ^10 || ^12 || >=14} + preact@10.29.8: + resolution: {integrity: sha512-ej2aVZ+vZ8WO7tvlQWRM9N63A0KzF9q4mWJfDUHgYaIofWY9hu74QdnQrjoPMmZi2/nZ5gN0bJCQF49xQqx09Q==} + peerDependencies: + preact-render-to-string: '>=5' + peerDependenciesMeta: + preact-render-to-string: + optional: true + prettier@2.8.8: resolution: {integrity: sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==} engines: {node: '>=10.13.0'} hasBin: true + property-information@7.2.0: + resolution: {integrity: sha512-IAtzIB6sUiWaJYrX9smp3V46pBGbBeLFRGdh25kg1334VcBlD8HzhPeNIWQH9zhGmo2itIe25EHt9dQP7G5hmg==} + + punycode.js@2.3.1: + resolution: {integrity: sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==} + engines: {node: '>=6'} + quansync@0.2.11: resolution: {integrity: sha512-AifT7QEbW9Nri4tAwR5M/uzpBuqfZf+zwaEM/QkzEjj7NBuFD2rBuy0K3dE+8wltbezDV7JMA0WfnCPYRSYbXA==} @@ -2068,6 +2758,15 @@ packages: resolution: {integrity: sha512-VIMnQi/Z4HT2Fxuwg5KrY174U1VdUIASQVWXXyqtNRtxSr9IYkn1rsI6Tb6HsrHCmB7gVpNwX6JxPTHcH6IoTA==} engines: {node: '>=6'} + regex-recursion@6.0.2: + resolution: {integrity: sha512-0YCaSCq2VRIebiaUviZNs0cBz1kg5kVS2UKUfNIx8YVs1cN3AV7NTctO5FOKBA+UT2BPJIWZauYHPqJODG50cg==} + + regex-utilities@2.3.0: + resolution: {integrity: sha512-8VhliFJAWRaUiVvREIiW2NXXTmHs4vMNnSzuJVhscgmGav3g9VDxLrQndI3dZZVVdp0ZO/5v0xmX516/7M9cng==} + + regex@6.1.0: + resolution: {integrity: sha512-6VwtthbV4o/7+OaAF9I5L5V3llLEsoPyq9P1JVXkedTP33c7MfCG0/5NOPcSJn0TzXcG9YUrR0gQSWioew3LDg==} + require-from-string@2.0.2: resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} engines: {node: '>=0.10.0'} @@ -2087,6 +2786,9 @@ packages: resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==} engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + rfdc@1.4.1: + resolution: {integrity: sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==} + rolldown-plugin-dts@0.27.14: resolution: {integrity: sha512-ZvuDDwoIpRK9RPxDXratCpklFO9QZZWndf/sd0VBFb4LEj0jj07UcHK9OCh7V4XiFz2Z89ziyBC2K6tJiDjrbw==} engines: {node: ^22.18.0 || >=24.11.0} @@ -2111,6 +2813,11 @@ packages: engines: {node: ^20.19.0 || >=22.12.0} hasBin: true + rollup@4.62.4: + resolution: {integrity: sha512-RXOqwaPsBGjMNMa4sQjDjHieHEZDFoj/Rdr46l2MU5DfEs16wHJPC2RPTPHWhNl+M3aI472LLqFkFKut4SblOg==} + engines: {node: '>=18.0.0', npm: '>=8.0.0'} + hasBin: true + run-parallel@1.2.0: resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} @@ -2130,6 +2837,9 @@ packages: resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} engines: {node: '>=8'} + shiki@2.5.0: + resolution: {integrity: sha512-mI//trrsaiCIPsja5CNfsyNOqgAZUb6VpJA+340toL42UpzQlXpwRV9nch69X6gaUxrr9kaOOa6e3y3uAkGFxQ==} + siginfo@2.0.0: resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} @@ -2149,9 +2859,16 @@ packages: resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} engines: {node: '>=0.10.0'} + space-separated-tokens@2.0.2: + resolution: {integrity: sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==} + spawndamnit@3.0.1: resolution: {integrity: sha512-MmnduQUuHCoFckZoWnXsTg7JaiLBJrKFj9UI2MbRPGaJeVpsLcVBu6P/IGZovziM/YBsellCmsprgNA+w0CzVg==} + speakingurl@14.0.1: + resolution: {integrity: sha512-1POYv7uv2gXoyGFpBCmpDVSNV74IfsWlDW216UPjbWufNf+bSU6GdbDsxdcxtfwb4xlI3yxzOTKClUosxARYrQ==} + engines: {node: '>=0.10.0'} + sprintf-js@1.0.3: resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} @@ -2169,6 +2886,9 @@ packages: resolution: {integrity: sha512-GaPUh5gfdrYzqeVNZvUfT23vYYxXzKYidUcnMtJg/3rxRV63EFZy3k6xfKlmfeJD0176lnUV/Usr3XcwSvFzpg==} engines: {node: '>=20'} + stringify-entities@4.0.4: + resolution: {integrity: sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==} + strip-ansi@6.0.1: resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} engines: {node: '>=8'} @@ -2185,10 +2905,17 @@ packages: resolution: {integrity: sha512-1tB5mhVo7U+ETBKNf92xT4hrQa3pm0MZ0PQvuDnWgAAGHDsfp4lPSpiS6psrSiet87wyGPh9ft6wmhOMQ0hDiw==} engines: {node: '>=14.16'} + superjson@2.2.6: + resolution: {integrity: sha512-H+ue8Zo4vJmV2nRjpx86P35lzwDT3nItnIsocgumgr0hHMQ+ZGq5vrERg9kJBo5AWGmxZDhzDo+WVIJqkB0cGA==} + engines: {node: '>=16'} + supports-color@7.2.0: resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} engines: {node: '>=8'} + tabbable@6.5.0: + resolution: {integrity: sha512-wieBHXygIm7OyQOu5hQlkk62/WyCFYGlWg7L6/ZCUZwx0o398Zkn4pVmMyfYhfMG8kGrj/Krt8eIk6UKC6VzwA==} + tagged-tag@1.0.0: resolution: {integrity: sha512-yEFYrVhod+hdNyx7g5Bnkkb0G6si8HJurOoOEgC8B/O0uXLHlaey/65KRv6cuWBNhBgHKAROVpc7QyYqE5gFng==} engines: {node: '>=20'} @@ -2224,6 +2951,9 @@ packages: resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==} hasBin: true + trim-lines@3.0.1: + resolution: {integrity: sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==} + tsdown@0.22.14: resolution: {integrity: sha512-ule7Y+fsAN2iZbLDoo7C4KYljFJNJJ+fLshyn+9gozeTspVersWHxwdGB+Dm2hzA38s6muFnUTl0jK3vJm9ifQ==} engines: {node: ^22.18.0 || >=24.11.0} @@ -2269,11 +2999,32 @@ packages: resolution: {integrity: sha512-YGYEVz3Fm5iy/AybuA0oyNFq7H4CgQNfRp/qfe8nurE1kuCeNm3/vfm9X4Mtl+qLyaKJUh5xrFZwogr41SMjYA==} engines: {node: '>=20'} + typedoc-plugin-markdown@4.12.0: + resolution: {integrity: sha512-eJDEMAfxCmede22c/Jw7d0FA13ggAQv+KkwQYKYCdqI02cin6Rc9QRwbG/7XvvHWinuFejySnZVUWDtvGk3Vbg==} + engines: {node: '>= 18'} + peerDependencies: + typedoc: 0.28.x + + typedoc@0.28.20: + resolution: {integrity: sha512-uSKqkh8Cr48vllnEy+jdaAgOeR6Y+QCBW7usgUsKj7gJEfR7stw9U/fE49LBnj2tPRKPY0c0EBJSWe9Appmplg==} + engines: {node: '>= 18', pnpm: '>= 10'} + hasBin: true + peerDependencies: + typescript: 5.0.x || 5.1.x || 5.2.x || 5.3.x || 5.4.x || 5.5.x || 5.6.x || 5.7.x || 5.8.x || 5.9.x || 6.0.x + + typescript@6.0.3: + resolution: {integrity: sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw==} + engines: {node: '>=14.17'} + hasBin: true + typescript@7.0.2: resolution: {integrity: sha512-8FYau96o3NKOhbjKi/qNvG/W5jhzxkbdm5sj9AbZ/5T5sWqn3hJgLfGx27sRKZWTvyzCP8dLRBTf5tBTSRVUNA==} engines: {node: '>=16.20.0'} hasBin: true + uc.micro@2.1.0: + resolution: {integrity: sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==} + unbash@4.0.6: resolution: {integrity: sha512-YGBMSVG/WrA2vgaZbXVvxrGgoMcWZecyyS4foGt8clbtY7s1nIKNmt7Z9LR74XE6FkYTSqDmKk2lIOhOjIvmrw==} engines: {node: '>=14'} @@ -2284,6 +3035,21 @@ packages: undici-types@8.3.0: resolution: {integrity: sha512-j375ScV60dom+YkPFIfTLcOiPxkN/buHz5GobjLhixFuANaNs3C9l4GmrWqejgXWJ7BbJcFYpTEUkS1Ge8bpZQ==} + unist-util-is@6.0.1: + resolution: {integrity: sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==} + + unist-util-position@5.0.0: + resolution: {integrity: sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==} + + unist-util-stringify-position@4.0.0: + resolution: {integrity: sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==} + + unist-util-visit-parents@6.0.2: + resolution: {integrity: sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ==} + + unist-util-visit@5.1.0: + resolution: {integrity: sha512-m+vIdyeCOpdr/QeQCu2EzxX/ohgS8KbnPDgFni4dQsfSCtpz8UqDyY5GjRru8PDKuYn7Fq19j1CQ+nJSsGKOzg==} + universalify@0.1.2: resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==} engines: {node: '>= 4.0.0'} @@ -2296,34 +3062,37 @@ packages: resolution: {integrity: sha512-zj/ob3UsvJGN0whEAKFp53REA5X66hvffVqoCtVQAakJKnKlH+/PcOfMoFwIG/o4rElqLv/ycAFlx8ZlXUorCg==} engines: {node: '>=18.12.0'} - vite@8.2.0: - resolution: {integrity: sha512-pn+CFpM0lwDeKwmOq1ZaBK/9sjorZcgqxki6MbY/jPEVd9vichIlmlD4HmQ5wdP5EgqQCFRaACBxMC7uEGc6lQ==} - engines: {node: ^20.19.0 || >=22.12.0} + vfile-message@4.0.3: + resolution: {integrity: sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==} + + vfile@6.0.3: + resolution: {integrity: sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==} + + vite@6.4.3: + resolution: {integrity: sha512-NTKlcQjlAK7MlQoyb6LgaqHc8sso/pVyUJYWMws3jg21uTJw/LddqIFPcPqP6PzpgbIcZyKI85sFE4HBrQDA8A==} + engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} hasBin: true peerDependencies: - '@types/node': ^20.19.0 || >=22.12.0 - '@vitejs/devtools': ^0.4.0 - esbuild: ^0.27.0 || ^0.28.0 + '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0 jiti: '>=1.21.0' - less: ^4.0.0 - sass: ^1.70.0 - sass-embedded: ^1.70.0 - stylus: '>=0.54.8' - sugarss: ^5.0.0 + less: '*' + lightningcss: ^1.21.0 + sass: '*' + sass-embedded: '*' + stylus: '*' + sugarss: '*' terser: ^5.16.0 tsx: ^4.8.1 yaml: ^2.4.2 peerDependenciesMeta: '@types/node': optional: true - '@vitejs/devtools': - optional: true - esbuild: - optional: true jiti: optional: true less: optional: true + lightningcss: + optional: true sass: optional: true sass-embedded: @@ -2339,6 +3108,18 @@ packages: yaml: optional: true + vitepress@1.6.4: + resolution: {integrity: sha512-+2ym1/+0VVrbhNyRoFFesVvBvHAVMZMK0rw60E3X/5349M1GuVdKeazuksqopEdvkKwKGs21Q729jX81/bkBJg==} + hasBin: true + peerDependencies: + markdown-it-mathjax3: ^4 + postcss: ^8 + peerDependenciesMeta: + markdown-it-mathjax3: + optional: true + postcss: + optional: true + vitest@4.1.10: resolution: {integrity: sha512-R9jUTe5S4Qb0HCd4TNqpC7oGcrMssMRGXLW80ubjWsW9VH5GF8y1Y0SFLY9AbqSk6nt0PnOx4H4WNJYZ13GUPw==} engines: {node: ^20.0.0 || ^22.0.0 || >=24.0.0} @@ -2379,6 +3160,14 @@ packages: jsdom: optional: true + vue@3.5.41: + resolution: {integrity: sha512-2laE0p+aK+/AOPG/XL/WepOs/GlK755LJ1XECi9kDUrz1FKNw8rb2Xzlw9JS1rqEV55nb0ttsKxVlTCcd+R5cg==} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + walk-up-path@4.0.0: resolution: {integrity: sha512-3hu+tD8YzSLGuFYtPRb48vdhKMi0KQV5sn+uWr8+7dMEq/2G/dtLrdDinkLjqq5TIbIBjYJ4Ax/n3YiaW7QM8A==} engines: {node: 20 || >=22} @@ -2426,8 +3215,122 @@ packages: zod@4.4.3: resolution: {integrity: sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ==} + zwitch@2.0.4: + resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==} + snapshots: + '@algolia/abtesting@1.22.0': + dependencies: + '@algolia/client-common': 5.56.0 + '@algolia/requester-browser-xhr': 5.56.0 + '@algolia/requester-fetch': 5.56.0 + '@algolia/requester-node-http': 5.56.0 + + '@algolia/autocomplete-core@1.17.7(@algolia/client-search@5.56.0)(algoliasearch@5.56.0)': + dependencies: + '@algolia/autocomplete-plugin-algolia-insights': 1.17.7(@algolia/client-search@5.56.0)(algoliasearch@5.56.0) + '@algolia/autocomplete-shared': 1.17.7(@algolia/client-search@5.56.0)(algoliasearch@5.56.0) + transitivePeerDependencies: + - '@algolia/client-search' + - algoliasearch + - search-insights + + '@algolia/autocomplete-plugin-algolia-insights@1.17.7(@algolia/client-search@5.56.0)(algoliasearch@5.56.0)': + dependencies: + '@algolia/autocomplete-shared': 1.17.7(@algolia/client-search@5.56.0)(algoliasearch@5.56.0) + transitivePeerDependencies: + - '@algolia/client-search' + - algoliasearch + + '@algolia/autocomplete-preset-algolia@1.17.7(@algolia/client-search@5.56.0)(algoliasearch@5.56.0)': + dependencies: + '@algolia/autocomplete-shared': 1.17.7(@algolia/client-search@5.56.0)(algoliasearch@5.56.0) + '@algolia/client-search': 5.56.0 + algoliasearch: 5.56.0 + + '@algolia/autocomplete-shared@1.17.7(@algolia/client-search@5.56.0)(algoliasearch@5.56.0)': + dependencies: + '@algolia/client-search': 5.56.0 + algoliasearch: 5.56.0 + + '@algolia/client-abtesting@5.56.0': + dependencies: + '@algolia/client-common': 5.56.0 + '@algolia/requester-browser-xhr': 5.56.0 + '@algolia/requester-fetch': 5.56.0 + '@algolia/requester-node-http': 5.56.0 + + '@algolia/client-analytics@5.56.0': + dependencies: + '@algolia/client-common': 5.56.0 + '@algolia/requester-browser-xhr': 5.56.0 + '@algolia/requester-fetch': 5.56.0 + '@algolia/requester-node-http': 5.56.0 + + '@algolia/client-common@5.56.0': {} + + '@algolia/client-insights@5.56.0': + dependencies: + '@algolia/client-common': 5.56.0 + '@algolia/requester-browser-xhr': 5.56.0 + '@algolia/requester-fetch': 5.56.0 + '@algolia/requester-node-http': 5.56.0 + + '@algolia/client-personalization@5.56.0': + dependencies: + '@algolia/client-common': 5.56.0 + '@algolia/requester-browser-xhr': 5.56.0 + '@algolia/requester-fetch': 5.56.0 + '@algolia/requester-node-http': 5.56.0 + + '@algolia/client-query-suggestions@5.56.0': + dependencies: + '@algolia/client-common': 5.56.0 + '@algolia/requester-browser-xhr': 5.56.0 + '@algolia/requester-fetch': 5.56.0 + '@algolia/requester-node-http': 5.56.0 + + '@algolia/client-search@5.56.0': + dependencies: + '@algolia/client-common': 5.56.0 + '@algolia/requester-browser-xhr': 5.56.0 + '@algolia/requester-fetch': 5.56.0 + '@algolia/requester-node-http': 5.56.0 + + '@algolia/ingestion@1.56.0': + dependencies: + '@algolia/client-common': 5.56.0 + '@algolia/requester-browser-xhr': 5.56.0 + '@algolia/requester-fetch': 5.56.0 + '@algolia/requester-node-http': 5.56.0 + + '@algolia/monitoring@1.56.0': + dependencies: + '@algolia/client-common': 5.56.0 + '@algolia/requester-browser-xhr': 5.56.0 + '@algolia/requester-fetch': 5.56.0 + '@algolia/requester-node-http': 5.56.0 + + '@algolia/recommend@5.56.0': + dependencies: + '@algolia/client-common': 5.56.0 + '@algolia/requester-browser-xhr': 5.56.0 + '@algolia/requester-fetch': 5.56.0 + '@algolia/requester-node-http': 5.56.0 + + '@algolia/requester-browser-xhr@5.56.0': + dependencies: + '@algolia/client-common': 5.56.0 + + '@algolia/requester-fetch@5.56.0': + dependencies: + '@algolia/client-common': 5.56.0 + + '@algolia/requester-node-http@5.56.0': + dependencies: + '@algolia/client-common': 5.56.0 + '@babel/code-frame@7.29.7': dependencies: '@babel/helper-validator-identifier': 7.29.7 @@ -2464,8 +3367,19 @@ snapshots: dependencies: oxlint: 1.77.0 + '@btravstack/theme@1.7.0(vitepress@1.6.4(@algolia/client-search@5.56.0)(@types/node@26.1.2)(jiti@2.7.0)(postcss@8.5.25)(typescript@6.0.3)(yaml@2.9.0))(vue@3.5.41(typescript@6.0.3))': + dependencies: + vitepress: 1.6.4(@algolia/client-search@5.56.0)(@types/node@26.1.2)(jiti@2.7.0)(postcss@8.5.25)(typescript@6.0.3)(yaml@2.9.0) + optionalDependencies: + vue: 3.5.41(typescript@6.0.3) + '@btravstack/tsconfig@0.2.0': {} + '@btravstack/typedoc@0.1.0(typedoc-plugin-markdown@4.12.0(typedoc@0.28.20(typescript@6.0.3)))(typedoc@0.28.20(typescript@6.0.3))': + dependencies: + typedoc: 0.28.20(typescript@6.0.3) + typedoc-plugin-markdown: 4.12.0(typedoc@0.28.20(typescript@6.0.3)) + '@changesets/apply-release-plan@7.1.1': dependencies: '@changesets/config': 3.1.4 @@ -2728,6 +3642,29 @@ snapshots: '@conventional-changelog/template@1.2.1': {} + '@docsearch/css@3.8.2': {} + + '@docsearch/js@3.8.2(@algolia/client-search@5.56.0)': + dependencies: + '@docsearch/react': 3.8.2(@algolia/client-search@5.56.0) + preact: 10.29.8 + transitivePeerDependencies: + - '@algolia/client-search' + - '@types/react' + - preact-render-to-string + - react + - react-dom + - search-insights + + '@docsearch/react@3.8.2(@algolia/client-search@5.56.0)': + dependencies: + '@algolia/autocomplete-core': 1.17.7(@algolia/client-search@5.56.0)(algoliasearch@5.56.0) + '@algolia/autocomplete-preset-algolia': 1.17.7(@algolia/client-search@5.56.0)(algoliasearch@5.56.0) + '@docsearch/css': 3.8.2 + algoliasearch: 5.56.0 + transitivePeerDependencies: + - '@algolia/client-search' + '@emnapi/core@1.11.2': dependencies: '@emnapi/wasi-threads': 1.2.2 @@ -2744,6 +3681,98 @@ snapshots: tslib: 2.8.1 optional: true + '@esbuild/aix-ppc64@0.25.12': + optional: true + + '@esbuild/android-arm64@0.25.12': + optional: true + + '@esbuild/android-arm@0.25.12': + optional: true + + '@esbuild/android-x64@0.25.12': + optional: true + + '@esbuild/darwin-arm64@0.25.12': + optional: true + + '@esbuild/darwin-x64@0.25.12': + optional: true + + '@esbuild/freebsd-arm64@0.25.12': + optional: true + + '@esbuild/freebsd-x64@0.25.12': + optional: true + + '@esbuild/linux-arm64@0.25.12': + optional: true + + '@esbuild/linux-arm@0.25.12': + optional: true + + '@esbuild/linux-ia32@0.25.12': + optional: true + + '@esbuild/linux-loong64@0.25.12': + optional: true + + '@esbuild/linux-mips64el@0.25.12': + optional: true + + '@esbuild/linux-ppc64@0.25.12': + optional: true + + '@esbuild/linux-riscv64@0.25.12': + optional: true + + '@esbuild/linux-s390x@0.25.12': + optional: true + + '@esbuild/linux-x64@0.25.12': + optional: true + + '@esbuild/netbsd-arm64@0.25.12': + optional: true + + '@esbuild/netbsd-x64@0.25.12': + optional: true + + '@esbuild/openbsd-arm64@0.25.12': + optional: true + + '@esbuild/openbsd-x64@0.25.12': + optional: true + + '@esbuild/openharmony-arm64@0.25.12': + optional: true + + '@esbuild/sunos-x64@0.25.12': + optional: true + + '@esbuild/win32-arm64@0.25.12': + optional: true + + '@esbuild/win32-ia32@0.25.12': + optional: true + + '@esbuild/win32-x64@0.25.12': + optional: true + + '@gerrit0/mini-shiki@3.23.0': + dependencies: + '@shikijs/engine-oniguruma': 3.23.0 + '@shikijs/langs': 3.23.0 + '@shikijs/themes': 3.23.0 + '@shikijs/types': 3.23.0 + '@shikijs/vscode-textmate': 10.0.2 + + '@iconify-json/simple-icons@1.2.93': + dependencies: + '@iconify/types': 2.0.0 + + '@iconify/types@2.0.0': {} + '@inquirer/external-editor@1.0.3(@types/node@26.1.2)': dependencies: chardet: 2.2.0 @@ -2776,6 +3805,9 @@ snapshots: globby: 11.1.0 read-yaml-file: 1.1.0 + '@napi-rs/lzma-linux-x64-gnu@1.5.1': + optional: true + '@napi-rs/wasm-runtime@1.2.2(@emnapi/core@1.11.2)(@emnapi/runtime@1.11.2)': dependencies: '@emnapi/core': 1.11.2 @@ -3045,109 +4077,242 @@ snapshots: '@oxlint/binding-android-arm-eabi@1.77.0': optional: true - '@oxlint/binding-android-arm64@1.77.0': + '@oxlint/binding-android-arm64@1.77.0': + optional: true + + '@oxlint/binding-darwin-arm64@1.77.0': + optional: true + + '@oxlint/binding-darwin-x64@1.77.0': + optional: true + + '@oxlint/binding-freebsd-x64@1.77.0': + optional: true + + '@oxlint/binding-linux-arm-gnueabihf@1.77.0': + optional: true + + '@oxlint/binding-linux-arm-musleabihf@1.77.0': + optional: true + + '@oxlint/binding-linux-arm64-gnu@1.77.0': + optional: true + + '@oxlint/binding-linux-arm64-musl@1.77.0': + optional: true + + '@oxlint/binding-linux-ppc64-gnu@1.77.0': + optional: true + + '@oxlint/binding-linux-riscv64-gnu@1.77.0': + optional: true + + '@oxlint/binding-linux-riscv64-musl@1.77.0': + optional: true + + '@oxlint/binding-linux-s390x-gnu@1.77.0': + optional: true + + '@oxlint/binding-linux-x64-gnu@1.77.0': + optional: true + + '@oxlint/binding-linux-x64-musl@1.77.0': + optional: true + + '@oxlint/binding-openharmony-arm64@1.77.0': + optional: true + + '@oxlint/binding-win32-arm64-msvc@1.77.0': + optional: true + + '@oxlint/binding-win32-ia32-msvc@1.77.0': + optional: true + + '@oxlint/binding-win32-x64-msvc@1.77.0': + optional: true + + '@oxlint/plugins@1.77.0': {} + + '@quansync/fs@1.0.0': + dependencies: + quansync: 1.0.0 + + '@rolldown/binding-android-arm64@1.2.3': + optional: true + + '@rolldown/binding-darwin-arm64@1.2.3': + optional: true + + '@rolldown/binding-darwin-x64@1.2.3': + optional: true + + '@rolldown/binding-freebsd-x64@1.2.3': + optional: true + + '@rolldown/binding-linux-arm-gnueabihf@1.2.3': + optional: true + + '@rolldown/binding-linux-arm64-gnu@1.2.3': + optional: true + + '@rolldown/binding-linux-arm64-musl@1.2.3': + optional: true + + '@rolldown/binding-linux-ppc64-gnu@1.2.3': + optional: true + + '@rolldown/binding-linux-s390x-gnu@1.2.3': + optional: true + + '@rolldown/binding-linux-x64-gnu@1.2.3': + optional: true + + '@rolldown/binding-linux-x64-musl@1.2.3': + optional: true + + '@rolldown/binding-openharmony-arm64@1.2.3': + optional: true + + '@rolldown/binding-win32-arm64-msvc@1.2.3': + optional: true + + '@rolldown/binding-win32-x64-msvc@1.2.3': + optional: true + + '@rolldown/pluginutils@1.0.1': {} + + '@rollup/rollup-android-arm-eabi@4.62.4': optional: true - '@oxlint/binding-darwin-arm64@1.77.0': + '@rollup/rollup-android-arm64@4.62.4': optional: true - '@oxlint/binding-darwin-x64@1.77.0': + '@rollup/rollup-darwin-arm64@4.62.4': optional: true - '@oxlint/binding-freebsd-x64@1.77.0': + '@rollup/rollup-darwin-x64@4.62.4': optional: true - '@oxlint/binding-linux-arm-gnueabihf@1.77.0': + '@rollup/rollup-freebsd-arm64@4.62.4': optional: true - '@oxlint/binding-linux-arm-musleabihf@1.77.0': + '@rollup/rollup-freebsd-x64@4.62.4': optional: true - '@oxlint/binding-linux-arm64-gnu@1.77.0': + '@rollup/rollup-linux-arm-gnueabihf@4.62.4': optional: true - '@oxlint/binding-linux-arm64-musl@1.77.0': + '@rollup/rollup-linux-arm-musleabihf@4.62.4': optional: true - '@oxlint/binding-linux-ppc64-gnu@1.77.0': + '@rollup/rollup-linux-arm64-gnu@4.62.4': optional: true - '@oxlint/binding-linux-riscv64-gnu@1.77.0': + '@rollup/rollup-linux-arm64-musl@4.62.4': optional: true - '@oxlint/binding-linux-riscv64-musl@1.77.0': + '@rollup/rollup-linux-loong64-gnu@4.62.4': optional: true - '@oxlint/binding-linux-s390x-gnu@1.77.0': + '@rollup/rollup-linux-loong64-musl@4.62.4': optional: true - '@oxlint/binding-linux-x64-gnu@1.77.0': + '@rollup/rollup-linux-ppc64-gnu@4.62.4': optional: true - '@oxlint/binding-linux-x64-musl@1.77.0': + '@rollup/rollup-linux-ppc64-musl@4.62.4': optional: true - '@oxlint/binding-openharmony-arm64@1.77.0': + '@rollup/rollup-linux-riscv64-gnu@4.62.4': optional: true - '@oxlint/binding-win32-arm64-msvc@1.77.0': + '@rollup/rollup-linux-riscv64-musl@4.62.4': optional: true - '@oxlint/binding-win32-ia32-msvc@1.77.0': + '@rollup/rollup-linux-s390x-gnu@4.62.4': optional: true - '@oxlint/binding-win32-x64-msvc@1.77.0': + '@rollup/rollup-linux-x64-gnu@4.62.4': optional: true - '@oxlint/plugins@1.77.0': {} - - '@quansync/fs@1.0.0': - dependencies: - quansync: 1.0.0 - - '@rolldown/binding-android-arm64@1.2.3': + '@rollup/rollup-linux-x64-musl@4.62.4': optional: true - '@rolldown/binding-darwin-arm64@1.2.3': + '@rollup/rollup-openbsd-x64@4.62.4': optional: true - '@rolldown/binding-darwin-x64@1.2.3': + '@rollup/rollup-openharmony-arm64@4.62.4': optional: true - '@rolldown/binding-freebsd-x64@1.2.3': + '@rollup/rollup-win32-arm64-msvc@4.62.4': optional: true - '@rolldown/binding-linux-arm-gnueabihf@1.2.3': + '@rollup/rollup-win32-ia32-msvc@4.62.4': optional: true - '@rolldown/binding-linux-arm64-gnu@1.2.3': + '@rollup/rollup-win32-x64-gnu@4.62.4': optional: true - '@rolldown/binding-linux-arm64-musl@1.2.3': + '@rollup/rollup-win32-x64-msvc@4.62.4': optional: true - '@rolldown/binding-linux-ppc64-gnu@1.2.3': - optional: true + '@shikijs/core@2.5.0': + dependencies: + '@shikijs/engine-javascript': 2.5.0 + '@shikijs/engine-oniguruma': 2.5.0 + '@shikijs/types': 2.5.0 + '@shikijs/vscode-textmate': 10.0.2 + '@types/hast': 3.0.5 + hast-util-to-html: 9.0.5 - '@rolldown/binding-linux-s390x-gnu@1.2.3': - optional: true + '@shikijs/engine-javascript@2.5.0': + dependencies: + '@shikijs/types': 2.5.0 + '@shikijs/vscode-textmate': 10.0.2 + oniguruma-to-es: 3.1.1 - '@rolldown/binding-linux-x64-gnu@1.2.3': - optional: true + '@shikijs/engine-oniguruma@2.5.0': + dependencies: + '@shikijs/types': 2.5.0 + '@shikijs/vscode-textmate': 10.0.2 - '@rolldown/binding-linux-x64-musl@1.2.3': - optional: true + '@shikijs/engine-oniguruma@3.23.0': + dependencies: + '@shikijs/types': 3.23.0 + '@shikijs/vscode-textmate': 10.0.2 - '@rolldown/binding-openharmony-arm64@1.2.3': - optional: true + '@shikijs/langs@2.5.0': + dependencies: + '@shikijs/types': 2.5.0 - '@rolldown/binding-win32-arm64-msvc@1.2.3': - optional: true + '@shikijs/langs@3.23.0': + dependencies: + '@shikijs/types': 3.23.0 - '@rolldown/binding-win32-x64-msvc@1.2.3': - optional: true + '@shikijs/themes@2.5.0': + dependencies: + '@shikijs/types': 2.5.0 - '@rolldown/pluginutils@1.0.1': {} + '@shikijs/themes@3.23.0': + dependencies: + '@shikijs/types': 3.23.0 + + '@shikijs/transformers@2.5.0': + dependencies: + '@shikijs/core': 2.5.0 + '@shikijs/types': 2.5.0 + + '@shikijs/types@2.5.0': + dependencies: + '@shikijs/vscode-textmate': 10.0.2 + '@types/hast': 3.0.5 + + '@shikijs/types@3.23.0': + dependencies: + '@shikijs/vscode-textmate': 10.0.2 + '@types/hast': 3.0.5 + + '@shikijs/vscode-textmate@10.0.2': {} '@simple-libs/child-process-utils@2.0.0': dependencies: @@ -3223,12 +4388,33 @@ snapshots: '@types/estree@1.0.9': {} + '@types/hast@3.0.5': + dependencies: + '@types/unist': 3.0.3 + + '@types/linkify-it@5.0.0': {} + + '@types/markdown-it@14.1.2': + dependencies: + '@types/linkify-it': 5.0.0 + '@types/mdurl': 2.0.0 + + '@types/mdast@4.0.4': + dependencies: + '@types/unist': 3.0.3 + + '@types/mdurl@2.0.0': {} + '@types/node@12.20.55': {} '@types/node@26.1.2': dependencies: undici-types: 8.3.0 + '@types/unist@3.0.3': {} + + '@types/web-bluetooth@0.0.21': {} + '@typescript/typescript-aix-ppc64@7.0.2': optional: true @@ -3289,6 +4475,8 @@ snapshots: '@typescript/typescript-win32-x64@7.0.2': optional: true + '@ungap/structured-clone@1.3.3': {} + '@unthrown/oxlint@5.1.0(oxlint@1.77.0)': dependencies: '@oxlint/plugins': 1.77.0 @@ -3304,6 +4492,11 @@ snapshots: unthrown: 5.1.0 vitest: 4.1.10(@types/node@26.1.2)(@vitest/coverage-v8@4.1.10)(jiti@2.7.0)(yaml@2.9.0) + '@vitejs/plugin-vue@5.2.4(vite@6.4.3(@types/node@26.1.2)(jiti@2.7.0)(yaml@2.9.0))(vue@3.5.41(typescript@6.0.3))': + dependencies: + vite: 6.4.3(@types/node@26.1.2)(jiti@2.7.0)(yaml@2.9.0) + vue: 3.5.41(typescript@6.0.3) + '@vitest/coverage-v8@4.1.10(vitest@4.1.10)': dependencies: '@bcoe/v8-coverage': 1.0.2 @@ -3327,13 +4520,13 @@ snapshots: chai: 6.2.2 tinyrainbow: 3.1.1 - '@vitest/mocker@4.1.10(vite@8.2.0(@types/node@26.1.2)(jiti@2.7.0)(yaml@2.9.0))': + '@vitest/mocker@4.1.10(vite@6.4.3(@types/node@26.1.2)(jiti@2.7.0)(yaml@2.9.0))': dependencies: '@vitest/spy': 4.1.10 estree-walker: 3.0.3 magic-string: 0.30.21 optionalDependencies: - vite: 8.2.0(@types/node@26.1.2)(jiti@2.7.0)(yaml@2.9.0) + vite: 6.4.3(@types/node@26.1.2)(jiti@2.7.0)(yaml@2.9.0) '@vitest/pretty-format@4.1.10': dependencies: @@ -3359,6 +4552,105 @@ snapshots: convert-source-map: 2.0.0 tinyrainbow: 3.1.1 + '@vue/compiler-core@3.5.41': + dependencies: + '@babel/parser': 7.29.8 + '@vue/shared': 3.5.41 + entities: 7.0.1 + estree-walker: 2.0.2 + source-map-js: 1.2.1 + + '@vue/compiler-dom@3.5.41': + dependencies: + '@vue/compiler-core': 3.5.41 + '@vue/shared': 3.5.41 + + '@vue/compiler-sfc@3.5.41': + dependencies: + '@babel/parser': 7.29.8 + '@vue/compiler-core': 3.5.41 + '@vue/compiler-dom': 3.5.41 + '@vue/compiler-ssr': 3.5.41 + '@vue/shared': 3.5.41 + estree-walker: 2.0.2 + magic-string: 0.30.21 + postcss: 8.5.25 + source-map-js: 1.2.1 + + '@vue/compiler-ssr@3.5.41': + dependencies: + '@vue/compiler-dom': 3.5.41 + '@vue/shared': 3.5.41 + + '@vue/devtools-api@7.7.10': + dependencies: + '@vue/devtools-kit': 7.7.10 + + '@vue/devtools-kit@7.7.10': + dependencies: + '@vue/devtools-shared': 7.7.10 + birpc: 2.9.0 + hookable: 5.5.3 + mitt: 3.0.1 + perfect-debounce: 1.0.0 + speakingurl: 14.0.1 + superjson: 2.2.6 + + '@vue/devtools-shared@7.7.10': + dependencies: + rfdc: 1.4.1 + + '@vue/reactivity@3.5.41': + dependencies: + '@vue/shared': 3.5.41 + + '@vue/runtime-core@3.5.41': + dependencies: + '@vue/reactivity': 3.5.41 + '@vue/shared': 3.5.41 + + '@vue/runtime-dom@3.5.41': + dependencies: + '@vue/reactivity': 3.5.41 + '@vue/runtime-core': 3.5.41 + '@vue/shared': 3.5.41 + csstype: 3.2.3 + + '@vue/server-renderer@3.5.41': + dependencies: + '@vue/compiler-ssr': 3.5.41 + '@vue/runtime-dom': 3.5.41 + '@vue/shared': 3.5.41 + + '@vue/shared@3.5.41': {} + + '@vueuse/core@12.8.2(typescript@6.0.3)': + dependencies: + '@types/web-bluetooth': 0.0.21 + '@vueuse/metadata': 12.8.2 + '@vueuse/shared': 12.8.2(typescript@6.0.3) + vue: 3.5.41(typescript@6.0.3) + transitivePeerDependencies: + - typescript + + '@vueuse/integrations@12.8.2(focus-trap@7.8.0)(typescript@6.0.3)': + dependencies: + '@vueuse/core': 12.8.2(typescript@6.0.3) + '@vueuse/shared': 12.8.2(typescript@6.0.3) + vue: 3.5.41(typescript@6.0.3) + optionalDependencies: + focus-trap: 7.8.0 + transitivePeerDependencies: + - typescript + + '@vueuse/metadata@12.8.2': {} + + '@vueuse/shared@12.8.2(typescript@6.0.3)': + dependencies: + vue: 3.5.41(typescript@6.0.3) + transitivePeerDependencies: + - typescript + '@yuku-codegen/binding-android-arm64@0.8.3': optional: true @@ -3440,6 +4732,23 @@ snapshots: json-schema-traverse: 1.0.0 require-from-string: 2.0.2 + algoliasearch@5.56.0: + dependencies: + '@algolia/abtesting': 1.22.0 + '@algolia/client-abtesting': 5.56.0 + '@algolia/client-analytics': 5.56.0 + '@algolia/client-common': 5.56.0 + '@algolia/client-insights': 5.56.0 + '@algolia/client-personalization': 5.56.0 + '@algolia/client-query-suggestions': 5.56.0 + '@algolia/client-search': 5.56.0 + '@algolia/ingestion': 1.56.0 + '@algolia/monitoring': 1.56.0 + '@algolia/recommend': 5.56.0 + '@algolia/requester-browser-xhr': 5.56.0 + '@algolia/requester-fetch': 5.56.0 + '@algolia/requester-node-http': 5.56.0 + ansi-colors@4.1.3: {} ansi-regex@5.0.1: {} @@ -3468,10 +4777,18 @@ snapshots: estree-walker: 3.0.3 js-tokens: 10.0.0 + balanced-match@4.0.4: {} + better-path-resolve@1.0.0: dependencies: is-windows: 1.0.2 + birpc@2.9.0: {} + + brace-expansion@5.0.9: + dependencies: + balanced-match: 4.0.4 + braces@3.0.3: dependencies: fill-range: 7.1.1 @@ -3480,8 +4797,14 @@ snapshots: callsites@3.1.0: {} + ccount@2.0.1: {} + chai@6.2.2: {} + character-entities-html4@2.1.0: {} + + character-entities-legacy@3.0.0: {} + chardet@2.2.0: {} cliui@9.0.1: @@ -3490,6 +4813,8 @@ snapshots: strip-ansi: 7.2.0 wrap-ansi: 9.0.2 + comma-separated-tokens@2.0.3: {} + conventional-changelog-angular@9.2.1: dependencies: '@conventional-changelog/template': 1.2.1 @@ -3507,6 +4832,10 @@ snapshots: cookie@2.0.1: {} + copy-anything@4.0.5: + dependencies: + is-what: 5.5.0 + cosmiconfig-typescript-loader@6.3.0(@types/node@26.1.2)(cosmiconfig@9.0.2(typescript@7.0.2))(typescript@7.0.2): dependencies: '@types/node': 26.1.2 @@ -3529,11 +4858,17 @@ snapshots: shebang-command: 2.0.0 which: 2.0.2 + csstype@3.2.3: {} + defu@6.1.7: {} + dequal@2.0.3: {} + detect-indent@6.1.0: {} - detect-libc@2.1.2: {} + devlop@1.1.0: + dependencies: + dequal: 2.0.3 dir-glob@3.0.1: dependencies: @@ -3543,6 +4878,8 @@ snapshots: optionalDependencies: oxc-resolver: 11.24.2 + emoji-regex-xs@1.0.0: {} + emoji-regex@10.6.0: {} empathic@2.0.1: {} @@ -3552,6 +4889,10 @@ snapshots: ansi-colors: 4.1.3 strip-ansi: 6.0.1 + entities@4.5.0: {} + + entities@7.0.1: {} + env-paths@2.2.1: {} error-ex@1.3.4: @@ -3562,10 +4903,41 @@ snapshots: es-toolkit@1.50.0: {} + esbuild@0.25.12: + optionalDependencies: + '@esbuild/aix-ppc64': 0.25.12 + '@esbuild/android-arm': 0.25.12 + '@esbuild/android-arm64': 0.25.12 + '@esbuild/android-x64': 0.25.12 + '@esbuild/darwin-arm64': 0.25.12 + '@esbuild/darwin-x64': 0.25.12 + '@esbuild/freebsd-arm64': 0.25.12 + '@esbuild/freebsd-x64': 0.25.12 + '@esbuild/linux-arm': 0.25.12 + '@esbuild/linux-arm64': 0.25.12 + '@esbuild/linux-ia32': 0.25.12 + '@esbuild/linux-loong64': 0.25.12 + '@esbuild/linux-mips64el': 0.25.12 + '@esbuild/linux-ppc64': 0.25.12 + '@esbuild/linux-riscv64': 0.25.12 + '@esbuild/linux-s390x': 0.25.12 + '@esbuild/linux-x64': 0.25.12 + '@esbuild/netbsd-arm64': 0.25.12 + '@esbuild/netbsd-x64': 0.25.12 + '@esbuild/openbsd-arm64': 0.25.12 + '@esbuild/openbsd-x64': 0.25.12 + '@esbuild/openharmony-arm64': 0.25.12 + '@esbuild/sunos-x64': 0.25.12 + '@esbuild/win32-arm64': 0.25.12 + '@esbuild/win32-ia32': 0.25.12 + '@esbuild/win32-x64': 0.25.12 + escalade@3.2.0: {} esprima@4.0.1: {} + estree-walker@2.0.2: {} + estree-walker@3.0.3: dependencies: '@types/estree': 1.0.9 @@ -3607,6 +4979,10 @@ snapshots: locate-path: 5.0.0 path-exists: 4.0.0 + focus-trap@7.8.0: + dependencies: + tabbable: 6.5.0 + formatly@0.3.0: dependencies: fd-package-json: 2.0.0 @@ -3659,10 +5035,32 @@ snapshots: has-flag@4.0.0: {} + hast-util-to-html@9.0.5: + dependencies: + '@types/hast': 3.0.5 + '@types/unist': 3.0.3 + ccount: 2.0.1 + comma-separated-tokens: 2.0.3 + hast-util-whitespace: 3.0.0 + html-void-elements: 3.0.0 + mdast-util-to-hast: 13.2.1 + property-information: 7.2.0 + space-separated-tokens: 2.0.2 + stringify-entities: 4.0.4 + zwitch: 2.0.4 + + hast-util-whitespace@3.0.0: + dependencies: + '@types/hast': 3.0.5 + + hookable@5.5.3: {} + hookable@6.1.1: {} html-escaper@2.0.2: {} + html-void-elements@3.0.0: {} + human-id@4.2.0: {} iconv-lite@0.7.3: @@ -3696,6 +5094,8 @@ snapshots: dependencies: better-path-resolve: 1.0.0 + is-what@5.5.0: {} + is-windows@1.0.2: {} isexe@2.0.0: {} @@ -3799,56 +5199,11 @@ snapshots: lefthook-windows-arm64: 2.1.10 lefthook-windows-x64: 2.1.10 - lightningcss-android-arm64@1.33.0: - optional: true - - lightningcss-darwin-arm64@1.33.0: - optional: true - - lightningcss-darwin-x64@1.33.0: - optional: true - - lightningcss-freebsd-x64@1.33.0: - optional: true - - lightningcss-linux-arm-gnueabihf@1.33.0: - optional: true - - lightningcss-linux-arm64-gnu@1.33.0: - optional: true - - lightningcss-linux-arm64-musl@1.33.0: - optional: true - - lightningcss-linux-x64-gnu@1.33.0: - optional: true - - lightningcss-linux-x64-musl@1.33.0: - optional: true - - lightningcss-win32-arm64-msvc@1.33.0: - optional: true - - lightningcss-win32-x64-msvc@1.33.0: - optional: true + lines-and-columns@1.2.4: {} - lightningcss@1.33.0: + linkify-it@5.0.2: dependencies: - detect-libc: 2.1.2 - optionalDependencies: - lightningcss-android-arm64: 1.33.0 - lightningcss-darwin-arm64: 1.33.0 - lightningcss-darwin-x64: 1.33.0 - lightningcss-freebsd-x64: 1.33.0 - lightningcss-linux-arm-gnueabihf: 1.33.0 - lightningcss-linux-arm64-gnu: 1.33.0 - lightningcss-linux-arm64-musl: 1.33.0 - lightningcss-linux-x64-gnu: 1.33.0 - lightningcss-linux-x64-musl: 1.33.0 - lightningcss-win32-arm64-msvc: 1.33.0 - lightningcss-win32-x64-msvc: 1.33.0 - - lines-and-columns@1.2.4: {} + uc.micro: 2.1.0 locate-path@5.0.0: dependencies: @@ -3856,6 +5211,8 @@ snapshots: lodash.startcase@4.4.0: {} + lunr@2.3.9: {} + magic-string@0.30.21: dependencies: '@jridgewell/sourcemap-codec': 1.5.5 @@ -3870,19 +5227,75 @@ snapshots: dependencies: semver: 7.8.5 + mark.js@8.11.1: {} + + markdown-it@14.3.0: + dependencies: + argparse: 2.0.1 + entities: 4.5.0 + linkify-it: 5.0.2 + mdurl: 2.1.0 + punycode.js: 2.3.1 + uc.micro: 2.1.0 + + mdast-util-to-hast@13.2.1: + dependencies: + '@types/hast': 3.0.5 + '@types/mdast': 4.0.4 + '@ungap/structured-clone': 1.3.3 + devlop: 1.1.0 + micromark-util-sanitize-uri: 2.0.1 + trim-lines: 3.0.1 + unist-util-position: 5.0.0 + unist-util-visit: 5.1.0 + vfile: 6.0.3 + + mdurl@2.1.0: {} + merge2@1.4.1: {} + micromark-util-character@2.1.1: + dependencies: + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + + micromark-util-encode@2.0.1: {} + + micromark-util-sanitize-uri@2.0.1: + dependencies: + micromark-util-character: 2.1.1 + micromark-util-encode: 2.0.1 + micromark-util-symbol: 2.0.1 + + micromark-util-symbol@2.0.1: {} + + micromark-util-types@2.0.2: {} + micromatch@4.0.8: dependencies: braces: 3.0.3 picomatch: 2.3.2 + minimatch@10.2.6: + dependencies: + brace-expansion: 5.0.9 + + minisearch@7.2.0: {} + + mitt@3.0.1: {} + mri@1.2.0: {} nanoid@3.3.17: {} obug@2.1.4: {} + oniguruma-to-es@3.1.1: + dependencies: + emoji-regex-xs: 1.0.0 + regex: 6.1.0 + regex-recursion: 6.0.2 + outdent@0.5.0: {} oxc-parser@0.142.0: @@ -4017,6 +5430,8 @@ snapshots: pathe@2.0.3: {} + perfect-debounce@1.0.0: {} + picocolors@1.1.1: {} picomatch@2.3.2: {} @@ -4031,8 +5446,14 @@ snapshots: picocolors: 1.1.1 source-map-js: 1.2.1 + preact@10.29.8: {} + prettier@2.8.8: {} + property-information@7.2.0: {} + + punycode.js@2.3.1: {} + quansync@0.2.11: {} quansync@1.0.0: {} @@ -4048,6 +5469,16 @@ snapshots: pify: 4.0.1 strip-bom: 3.0.0 + regex-recursion@6.0.2: + dependencies: + regex-utilities: 2.3.0 + + regex-utilities@2.3.0: {} + + regex@6.1.0: + dependencies: + regex-utilities: 2.3.0 + require-from-string@2.0.2: {} resolve-from@4.0.0: {} @@ -4058,6 +5489,8 @@ snapshots: reusify@1.1.0: {} + rfdc@1.4.1: {} + rolldown-plugin-dts@0.27.14(oxc-resolver@11.24.2)(rolldown@1.2.3)(typescript@7.0.2): dependencies: dts-resolver: 3.0.0(oxc-resolver@11.24.2) @@ -4092,6 +5525,38 @@ snapshots: '@rolldown/binding-win32-arm64-msvc': 1.2.3 '@rolldown/binding-win32-x64-msvc': 1.2.3 + rollup@4.62.4: + dependencies: + '@types/estree': 1.0.9 + optionalDependencies: + '@napi-rs/lzma-linux-x64-gnu': 1.5.1 + '@rollup/rollup-android-arm-eabi': 4.62.4 + '@rollup/rollup-android-arm64': 4.62.4 + '@rollup/rollup-darwin-arm64': 4.62.4 + '@rollup/rollup-darwin-x64': 4.62.4 + '@rollup/rollup-freebsd-arm64': 4.62.4 + '@rollup/rollup-freebsd-x64': 4.62.4 + '@rollup/rollup-linux-arm-gnueabihf': 4.62.4 + '@rollup/rollup-linux-arm-musleabihf': 4.62.4 + '@rollup/rollup-linux-arm64-gnu': 4.62.4 + '@rollup/rollup-linux-arm64-musl': 4.62.4 + '@rollup/rollup-linux-loong64-gnu': 4.62.4 + '@rollup/rollup-linux-loong64-musl': 4.62.4 + '@rollup/rollup-linux-ppc64-gnu': 4.62.4 + '@rollup/rollup-linux-ppc64-musl': 4.62.4 + '@rollup/rollup-linux-riscv64-gnu': 4.62.4 + '@rollup/rollup-linux-riscv64-musl': 4.62.4 + '@rollup/rollup-linux-s390x-gnu': 4.62.4 + '@rollup/rollup-linux-x64-gnu': 4.62.4 + '@rollup/rollup-linux-x64-musl': 4.62.4 + '@rollup/rollup-openbsd-x64': 4.62.4 + '@rollup/rollup-openharmony-arm64': 4.62.4 + '@rollup/rollup-win32-arm64-msvc': 4.62.4 + '@rollup/rollup-win32-ia32-msvc': 4.62.4 + '@rollup/rollup-win32-x64-gnu': 4.62.4 + '@rollup/rollup-win32-x64-msvc': 4.62.4 + fsevents: 2.3.3 + run-parallel@1.2.0: dependencies: queue-microtask: 1.2.3 @@ -4106,6 +5571,17 @@ snapshots: shebang-regex@3.0.0: {} + shiki@2.5.0: + dependencies: + '@shikijs/core': 2.5.0 + '@shikijs/engine-javascript': 2.5.0 + '@shikijs/engine-oniguruma': 2.5.0 + '@shikijs/langs': 2.5.0 + '@shikijs/themes': 2.5.0 + '@shikijs/types': 2.5.0 + '@shikijs/vscode-textmate': 10.0.2 + '@types/hast': 3.0.5 + siginfo@2.0.0: {} signal-exit@4.1.0: {} @@ -4116,11 +5592,15 @@ snapshots: source-map-js@1.2.1: {} + space-separated-tokens@2.0.2: {} + spawndamnit@3.0.1: dependencies: cross-spawn: 7.0.6 signal-exit: 4.1.0 + speakingurl@14.0.1: {} + sprintf-js@1.0.3: {} stackback@0.0.2: {} @@ -4138,6 +5618,11 @@ snapshots: get-east-asian-width: 1.6.0 strip-ansi: 7.2.0 + stringify-entities@4.0.4: + dependencies: + character-entities-html4: 2.1.0 + character-entities-legacy: 3.0.0 + strip-ansi@6.0.1: dependencies: ansi-regex: 5.0.1 @@ -4150,10 +5635,16 @@ snapshots: strip-json-comments@5.0.3: {} + superjson@2.2.6: + dependencies: + copy-anything: 4.0.5 + supports-color@7.2.0: dependencies: has-flag: 4.0.0 + tabbable@6.5.0: {} + tagged-tag@1.0.0: {} term-size@2.2.1: {} @@ -4177,6 +5668,8 @@ snapshots: tree-kill@1.2.2: {} + trim-lines@3.0.1: {} + tsdown@0.22.14(oxc-resolver@11.24.2)(typescript@7.0.2): dependencies: ansis: 4.3.1 @@ -4218,6 +5711,21 @@ snapshots: dependencies: tagged-tag: 1.0.0 + typedoc-plugin-markdown@4.12.0(typedoc@0.28.20(typescript@6.0.3)): + dependencies: + typedoc: 0.28.20(typescript@6.0.3) + + typedoc@0.28.20(typescript@6.0.3): + dependencies: + '@gerrit0/mini-shiki': 3.23.0 + lunr: 2.3.9 + markdown-it: 14.3.0 + minimatch: 10.2.6 + typescript: 6.0.3 + yaml: 2.9.0 + + typescript@6.0.3: {} + typescript@7.0.2: optionalDependencies: '@typescript/typescript-aix-ppc64': 7.0.2 @@ -4241,6 +5749,8 @@ snapshots: '@typescript/typescript-win32-arm64': 7.0.2 '@typescript/typescript-win32-x64': 7.0.2 + uc.micro@2.1.0: {} + unbash@4.0.6: {} unconfig-core@7.5.0: @@ -4250,18 +5760,52 @@ snapshots: undici-types@8.3.0: {} + unist-util-is@6.0.1: + dependencies: + '@types/unist': 3.0.3 + + unist-util-position@5.0.0: + dependencies: + '@types/unist': 3.0.3 + + unist-util-stringify-position@4.0.0: + dependencies: + '@types/unist': 3.0.3 + + unist-util-visit-parents@6.0.2: + dependencies: + '@types/unist': 3.0.3 + unist-util-is: 6.0.1 + + unist-util-visit@5.1.0: + dependencies: + '@types/unist': 3.0.3 + unist-util-is: 6.0.1 + unist-util-visit-parents: 6.0.2 + universalify@0.1.2: {} unthrown@5.1.0: {} verkit@0.3.2: {} - vite@8.2.0(@types/node@26.1.2)(jiti@2.7.0)(yaml@2.9.0): + vfile-message@4.0.3: + dependencies: + '@types/unist': 3.0.3 + unist-util-stringify-position: 4.0.0 + + vfile@6.0.3: + dependencies: + '@types/unist': 3.0.3 + vfile-message: 4.0.3 + + vite@6.4.3(@types/node@26.1.2)(jiti@2.7.0)(yaml@2.9.0): dependencies: - lightningcss: 1.33.0 + esbuild: 0.25.12 + fdir: 6.5.0(picomatch@4.0.5) picomatch: 4.0.5 postcss: 8.5.25 - rolldown: 1.2.3 + rollup: 4.62.4 tinyglobby: 0.2.17 optionalDependencies: '@types/node': 26.1.2 @@ -4269,10 +5813,63 @@ snapshots: jiti: 2.7.0 yaml: 2.9.0 + vitepress@1.6.4(@algolia/client-search@5.56.0)(@types/node@26.1.2)(jiti@2.7.0)(postcss@8.5.25)(typescript@6.0.3)(yaml@2.9.0): + dependencies: + '@docsearch/css': 3.8.2 + '@docsearch/js': 3.8.2(@algolia/client-search@5.56.0) + '@iconify-json/simple-icons': 1.2.93 + '@shikijs/core': 2.5.0 + '@shikijs/transformers': 2.5.0 + '@shikijs/types': 2.5.0 + '@types/markdown-it': 14.1.2 + '@vitejs/plugin-vue': 5.2.4(vite@6.4.3(@types/node@26.1.2)(jiti@2.7.0)(yaml@2.9.0))(vue@3.5.41(typescript@6.0.3)) + '@vue/devtools-api': 7.7.10 + '@vue/shared': 3.5.41 + '@vueuse/core': 12.8.2(typescript@6.0.3) + '@vueuse/integrations': 12.8.2(focus-trap@7.8.0)(typescript@6.0.3) + focus-trap: 7.8.0 + mark.js: 8.11.1 + minisearch: 7.2.0 + shiki: 2.5.0 + vite: 6.4.3(@types/node@26.1.2)(jiti@2.7.0)(yaml@2.9.0) + vue: 3.5.41(typescript@6.0.3) + optionalDependencies: + postcss: 8.5.25 + transitivePeerDependencies: + - '@algolia/client-search' + - '@types/node' + - '@types/react' + - async-validator + - axios + - change-case + - drauu + - fuse.js + - idb-keyval + - jiti + - jwt-decode + - less + - lightningcss + - nprogress + - preact-render-to-string + - qrcode + - react + - react-dom + - sass + - sass-embedded + - search-insights + - sortablejs + - stylus + - sugarss + - terser + - tsx + - typescript + - universal-cookie + - yaml + vitest@4.1.10(@types/node@26.1.2)(@vitest/coverage-v8@4.1.10)(jiti@2.7.0)(yaml@2.9.0): dependencies: '@vitest/expect': 4.1.10 - '@vitest/mocker': 4.1.10(vite@8.2.0(@types/node@26.1.2)(jiti@2.7.0)(yaml@2.9.0)) + '@vitest/mocker': 4.1.10(vite@6.4.3(@types/node@26.1.2)(jiti@2.7.0)(yaml@2.9.0)) '@vitest/pretty-format': 4.1.10 '@vitest/runner': 4.1.10 '@vitest/snapshot': 4.1.10 @@ -4289,16 +5886,15 @@ snapshots: tinyexec: 1.3.0 tinyglobby: 0.2.17 tinyrainbow: 3.1.1 - vite: 8.2.0(@types/node@26.1.2)(jiti@2.7.0)(yaml@2.9.0) + vite: 6.4.3(@types/node@26.1.2)(jiti@2.7.0)(yaml@2.9.0) why-is-node-running: 2.3.0 optionalDependencies: '@types/node': 26.1.2 '@vitest/coverage-v8': 4.1.10(vitest@4.1.10) transitivePeerDependencies: - - '@vitejs/devtools' - - esbuild - jiti - less + - lightningcss - msw - sass - sass-embedded @@ -4308,6 +5904,16 @@ snapshots: - tsx - yaml + vue@3.5.41(typescript@6.0.3): + dependencies: + '@vue/compiler-dom': 3.5.41 + '@vue/compiler-sfc': 3.5.41 + '@vue/runtime-dom': 3.5.41 + '@vue/server-renderer': 3.5.41 + '@vue/shared': 3.5.41 + optionalDependencies: + typescript: 6.0.3 + walk-up-path@4.0.0: {} which@2.0.2: @@ -4380,3 +5986,5 @@ snapshots: '@yuku-parser/binding-win32-x64': 0.8.3 zod@4.4.3: {} + + zwitch@2.0.4: {} diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index e21faeb..50cfe30 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -6,12 +6,15 @@ strictPeerDependencies: true packages: - packages/* + - docs catalog: "@btravstack/commitlint": 0.1.0 "@btravstack/lefthook": 0.1.1 "@btravstack/oxlint": 0.2.1 + "@btravstack/theme": 1.7.0 "@btravstack/tsconfig": 0.2.0 + "@btravstack/typedoc": 0.1.0 "@changesets/cli": 2.31.1 "@commitlint/cli": 21.2.1 # Pinned to the exact prerelease the package's design doc measured @@ -30,6 +33,8 @@ catalog: oxlint: 1.77.0 tsdown: 0.22.14 turbo: 2.10.8 + typedoc: 0.28.20 + typedoc-plugin-markdown: 4.12.0 # 7.0.2 is the exact release the package's design doc measured the # construction-seal declaration-emit behaviour against (zero TS4020, `declare # const CtorKey: unique symbol` carried module-local into the emitted @@ -37,11 +42,57 @@ catalog: typescript: 7.0.2 unthrown: 5.1.0 "@vitest/coverage-v8": 4.1.10 + vitepress: 1.6.4 vitest: 4.1.10 zod: 4.4.3 +catalogs: + # TypeDoc's own toolchain, deliberately NOT the default catalog's TypeScript. + # `typescript: 7.0.2` above is the native port: it ships `lib/tsc.js` (a thin + # launcher) and no `typescript.js`, so the compiler API TypeDoc is written + # against does not exist there — measured, and the reason `typedoc` runs from + # the `docs` workspace rather than from `packages/entity` as it does in the + # other btravstack repos. 6.0.3 is the last release carrying the JS API, and + # is what `typedoc@0.28`'s peer range allows. + typedoc: + typescript: 6.0.3 + +# Force patched versions of vulnerable transitive dependencies. Every advisory +# below reaches us only through dev/build tooling (never the published package's +# runtime deps, which are the three peers). Each selector is version-scoped so +# only the affected line moves and unrelated lines are untouched. +overrides: + # GHSA-fx2h-pf6j-xcff (High, `server.fs.deny` bypass on Windows alternate data + # streams) plus three moderates on the same line: GHSA path traversal in + # optimized deps, launch-editor NTLMv2 disclosure, and the esbuild dev-server + # advisory reached through vite's own dependency. All four are dev-server-only; + # the docs ship as static HTML. They reach us via docs > vitepress > vite: + # vitepress 1.6.x pins `vite ^5.4.14`, and the 5.x line has no patched release, + # so lift any pre-6.4.3 vite to 6.4.3 (the first fixed version). That also + # drags esbuild up to a patched 0.25.x. `vitepress build` and `vitepress dev` + # are both verified against it. + # + # Side effect, measured and accepted: vitest's own vite was resolving to 8.2.0, + # and pnpm dedupes it onto this 6.4.3 rather than keeping a second copy — + # vitest 4.1.10 declares `vite: "^6.0.0 || ^7.0.0 || ^8.0.0"`, so 6.4.3 is + # inside its supported range and the suite passes on it. Path-scoped selectors + # (`vitepress>vite`) were tried and produce the byte-identical tree, because + # the dedupe is resolution, not the selector — so the simpler form is kept. + # Pinning vitest's vite apart would mean an inline `vite` devDependency on the + # library package for a purely transitive concern; not worth it. + "vite@<6.4.3": "6.4.3" + +peerDependencyRules: + ignoreMissing: + # Optional analytics peer of VitePress's bundled Algolia DocSearch. + - search-insights + minimumReleaseAgeExclude: - knip@6.32.0 + # First-party shared config (@btravstack scope): adopt immediately, skip any + # registry-maturity delay — these are published from btravstack repos. + - "@btravstack/theme" + - "@btravstack/typedoc" allowBuilds: esbuild: true diff --git a/turbo.json b/turbo.json index d62d1c7..3a641c3 100644 --- a/turbo.json +++ b/turbo.json @@ -24,6 +24,10 @@ "build": { "dependsOn": ["^build"], "outputs": ["dist/**"] + }, + "@btravstack/entity-docs#build": { + "inputs": ["$TURBO_DEFAULT$", "../packages/entity/src/**"], + "outputs": [".vitepress/dist/**", "api/entity/**"] } } }