From 11be63560fbbb9c132e2ae635923b080b244a95a Mon Sep 17 00:00:00 2001 From: Braulio Date: Sat, 17 Oct 2026 21:08:11 +0200 Subject: [PATCH 1/4] spec(1): infraestructura base del monorepo PRD y brief funcional de Memora incluidos. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01FoSJwPZyTcTEfarL8vJrcX --- .claude/state/tasks/1/spec/design.md | 256 +++++++++++++++++++++ .claude/state/tasks/1/spec/requirements.md | 250 ++++++++++++++++++++ .claude/state/tasks/1/spec/tasks.md | 117 ++++++++++ docs/prds/infra-monorepo-2026-10-17.md | 223 ++++++++++++++++++ docs/product/memora-brief.md | 47 ++++ 5 files changed, 893 insertions(+) create mode 100644 .claude/state/tasks/1/spec/design.md create mode 100644 .claude/state/tasks/1/spec/requirements.md create mode 100644 .claude/state/tasks/1/spec/tasks.md create mode 100644 docs/prds/infra-monorepo-2026-10-17.md create mode 100644 docs/product/memora-brief.md diff --git a/.claude/state/tasks/1/spec/design.md b/.claude/state/tasks/1/spec/design.md new file mode 100644 index 0000000..f873fdc --- /dev/null +++ b/.claude/state/tasks/1/spec/design.md @@ -0,0 +1,256 @@ +# Design — Infraestructura y estructura base del monorepo + +> Source PRD: docs/prds/infra-monorepo-2026-10-17.md +> Task: #1 — branch `harness/1-infra-monorepo` + +## Approach + +Greenfield: the repository holds only the Lemony harness, an empty `README.md` and +`docs/`, so everything here is new code and nothing has to be migrated or preserved — +except the harness itself, which must keep working (its launcher resolves +`/node_modules/.bin/lemony`). We turn the root into a pnpm + Turborepo workspace +whose `package.json` is the single entry point, add `apps/web` (TanStack Start + +Tailwind + shadcn) as a «Hola Mundo» that proves the styling chain, a root +`docker-compose.yml` with `mongo:8` for the local database, `packages/db` as the only +module that knows how to reach Mongo, and `console-runner` (at the root, by explicit +request) as an `@inquirer/prompts` menu for maintenance. Quality is carried by +`tsc --noEmit` and Prettier — there is no linter by explicit decision, so `typecheck` +is the load-bearing mechanical gate — and a GitHub Actions workflow runs the four gates +on every PR so the harness merge gate has a real green to read. The database layer +exposes only what this delivery needs (resolve URI, client, ping, drop); the domain +model and real seed data are explicitly out of scope, and the seed menu entry prints a +`TODO` rather than faking work. + +## Spec gate decisions + +- **D1 — The front end does not consume `@memora/db` in this delivery.** [deviates] + The PRD says `packages/db` is consumed "tanto por las server functions del front + como por el runner". With a «Hola Mundo» front and no domain model, the front has + nothing to read: wiring the dependency now would either leave an unused dependency + (the PRD's own first risk: scaffolding noise nobody cleans) or require a server + function that hits Mongo, which would break the hermetic front smoke test (R19, R56) + and add product surface the PRD puts out of scope. Alternatives: (a) declare the + dependency unused, (b) add a DB-backed server function, (c) runner-only consumer now. + Taken (c): `packages/db` is created with its full seam and the runner is its only + consumer; the front gains the dependency in the first task that actually reads data + (one line in `apps/web/package.json`). Consequence the human signs: this delivery + does **not** prove the front→Mongo path end to end; only runner→Mongo is proven. +- **D2 — Prettier's scope is the project's own files; `.claude/` and generated paths + are excluded.** [deviates] + The PRD says "Prettier para formato" without a scope. Formatting the vendored harness + (`.claude/skills/**`, agents, hooks) would reformat files we do not own and make + `format:check` go red on the next `lemony update` — a gate failing for reasons + unrelated to the change. Alternatives: format everything, or exclude vendor and + generated paths. Taken the exclusion, via `.prettierignore` (`node_modules`, + `.claude/`, `pnpm-lock.yaml`, build outputs, caches). Consequence: harness files are + never auto-formatted, and the format gate only judges our own code and docs. +- **D3 — The front smoke test runs on Vitest + jsdom + `@testing-library/react`.** + [preference] + The PRD fixes Vitest for the runner and `packages/db` but leaves the front's single + smoke test open (it only says "un único smoke test"). Taken: the same runner (one + test tool in the repo) with jsdom and Testing Library, which asserts rendered output + rather than implementation. Consequence: three small devDependencies in `apps/web` + and a `vitest` environment config; no Playwright / browser-mode anywhere yet. +- **D4 — Workspace packages are scoped `@memora/*`, and `packages/db` is consumed as + TypeScript source with no build step.** [preference] + The PRD names the folder, not the package. Taken `@memora/db` with `exports`/`types` + pointing at `src/index.ts` (the Turborepo "internal package" pattern), consistent + with the PRD's no-build stance for the runner. Consequence: consumers must be able to + compile TS from `node_modules` (true for `tsx`, Vite and `tsc`), and `packages/db` + never emits a `dist/`. +- **D5 — Code and filenames in English; user-facing runner strings, the page greeting + and the spec/docs prose in Spanish.** [preference] + The PRD, the product brief and the issue are Spanish; identifiers in the stack are + English by convention. Consequence: mixed-language repository by design — the human + reads Spanish, the compiler reads English. +- **D6 — The existing npm install is migrated to pnpm: `package-lock.json` is deleted + and `@lemoncode/lemony` stays a root devDependency, installed by pnpm.** [open] + The PRD says pnpm is the package manager and the root `package.json` the single + entry point, but never mentions the npm lockfile already in the repo. Alternatives: + keep npm for the harness and pnpm for the product (two lockfiles, two installs), or + migrate wholesale. Taken the migration; pnpm creates `node_modules/.bin/lemony` for + root dependencies, so the harness launcher keeps resolving (R5 makes that an explicit + check). Consequence: `pnpm install` is the only install command from now on, and + anyone running `npm install` here regenerates a lockfile we no longer want. +- **D7 — Versions are pinned to exactly what this machine runs: `.nvmrc` `24.16.0`, + `engines.node` `>=24.16.0 <25`, `packageManager` `pnpm@10.19.0`.** [open] + The PRD says "fijada" without the values. Taken the measured versions (Node v24.16.0, + pnpm 10.19.0). Consequence: CI pins the same pair, and a Node 25 upgrade is a + deliberate edit rather than a silent drift. +- **D8 — `pnpm db:reset` removes the named volume; `db:down` does not.** [open] + The PRD wants data to survive `db:down` and wants `db:reset` to "empezar de cero" — + so the only thing reset can add is dropping the volume. Taken + `docker compose down -v` followed by `up -d --wait`. Alternative considered: making + `db:reset` call the runner's `dropDatabase`, rejected because that leaves the + container and volume state untouched and duplicates the runner's job. Consequence: + `db:reset` is destructive by definition and has no confirmation prompt (it is an + explicitly typed command, unlike the runner's one-keystroke menu entry). +- **D9 — The Mongo service gets a healthcheck and `db:up` waits for it.** [open] + Not in the PRD. Without it, `pnpm db:up` returns while Mongo is still starting and + the very next step of the manual verification (runner → check connection) can fail + for a reason that is not a defect. Taken: a `mongosh --eval 'db.adminCommand("ping")'` + healthcheck in the service plus `--wait` on `db:up`. Consequence: `db:up` takes a few + seconds longer and fails loudly if the container never becomes healthy. +- **D10 — `docker-compose.yml` carries a header comment marking it local-only.** [open] + The PRD flags the credential-less database as a risk but prescribes no mitigation. + Taken the cheapest one that travels with the file: a comment stating no credentials / + local development only / never for an externally reachable environment. +- **D11 — `.env` is loaded at the entry point, from the repository root, and the root + `runner` script runs `tsx console-runner/src/main.ts` from the root.** [open] + The PRD specifies `MONGODB_URI` by environment variable with `.env` ignored and + `.env.example` versioned, but not who loads the file nor where it lives. Taken: a + single `.env` at the repository root; `packages/db` stays pure (it reads the env + record it is handed, never a file), and the runner loads the file on start — + preferring Node's native `--env-file-if-exists=.env` passed through `tsx`, falling + back to `dotenv` in the entry module if `tsx` does not forward the flag. Running the + runner from the root (rather than `pnpm --filter`) makes the cwd deterministic. + Consequence: a `.env` inside a workspace package is not read, and the front will need + its own env wiring when it first touches the database (Vite does not populate + `process.env` from `.env`). +- **D12 — A single root `tsconfig.base.json`, extended by each workspace.** [open] + Alternative: a `packages/tsconfig` workspace package (common in Turborepo), rejected + because the PRD's structure lists exactly three workspaces and a fourth package that + holds only JSON adds a moving part for no gain at this size. +- **D13 — The menu has an explicit «Salir» entry and loops until it is chosen.** [open] + The PRD describes a menu of operations without saying what happens after one runs. + Taken: run → report → back to the menu; `Salir` closes the Mongo client and exits 0. + Alternative (one operation per invocation) rejected as worse for a maintenance tool + the human is exploring. +- **D14 — The clean-database confirmation defaults to «no».** [open] + The PRD requires an explicit confirmation; the default is unstated. Taken: default + no, so Enter cancels. Consequence: accepting costs a deliberate keystroke, which is + the point of having the prompt next to a one-key menu entry. +- **D15 — `README.md` gains a quickstart section.** [open] + The PRD's success criterion is that someone who clones the repo can bring everything + up, but it never mentions documentation and the README is empty. Taken: the minimum + that makes the criterion true — install, `db:*`, `dev`, `runner`, gates. +- **D16 — CI runs on `pull_request` targeting `main` (not on every push).** [open] + The PRD says "en cada PR". Taken exactly that, plus `workflow_dispatch` omitted, so + the check the harness merge gate reads is the PR check. Consequence: a direct push to + `main` runs no CI — acceptable because the flow always merges through a PR. + +## Files + +Root: + +- `package.json` — modified — private workspace root: `packageManager`, `engines`, the + ten scripts of R6, and the devDependencies shared by the gates (`turbo`, `prettier`, + `typescript`, `tsx`, `vitest`, `@lemoncode/lemony`). +- `pnpm-workspace.yaml` — created — `apps/*`, `packages/*`, `console-runner`. +- `pnpm-lock.yaml` — created — committed; `package-lock.json` deleted. +- `turbo.json` — created — tasks `dev` (persistent, no cache), `build`, `test`, + `typecheck`. +- `tsconfig.base.json` — created — strict TS options every workspace extends. +- `.nvmrc` — created — `24.16.0`. +- `.prettierrc` / `.prettierignore` — created — format config and the exclusions of D2. +- `.gitignore` — modified — `.env`, `.turbo/`, build outputs (`dist/`, `.output/`, + whatever the TanStack Start version emits), test caches. The existing + `# BEGIN lemony` block stays untouched. +- `.env.example` — created — `MONGODB_URI=mongodb://localhost:27017/memora`. +- `docker-compose.yml` — created — `mongo:8`, `27017:27017`, named volume + `memora-mongo-data:/data/db`, healthcheck, local-only header comment. +- `README.md` — modified — quickstart (R57). +- `harness.config.yml` — modified — uncomment/declare `gates:` with the four names + (R55); nothing else. +- `.github/workflows/ci.yml` — created — the PR workflow (R52–R54). + +`packages/db` (`@memora/db`): + +- `package.json` — created — `exports`/`types` → `src/index.ts`, dependency `mongodb`, + scripts `typecheck`, `test`. +- `tsconfig.json` — created — extends the root base. +- `src/config.ts` — created — `resolveMongoUri`. +- `src/client.ts` — created — `createMongoClient`, `pingDatabase`, `dropDatabase`. +- `src/index.ts` — created — the package's public surface (re-exports + types). +- `src/config.spec.ts`, `src/client.spec.ts` — created — Vitest units. + +`console-runner`: + +- `package.json` — created — name `console-runner`, dependencies `@inquirer/prompts` + and `@memora/db` (workspace), scripts `typecheck`, `test`. +- `tsconfig.json` — created. +- `src/main.ts` — created — entry: load `.env`, build the menu loop, dispatch, handle + `ExitPromptError`, close the client, exit codes. +- `src/actions/check-connection.ts` — created — prompt-free operation. +- `src/actions/clean-database.ts` — created — prompt-free operation (receives the + already-granted confirmation as an argument). +- `src/actions/seed-data.ts` — created — returns the pending marker, prints the `TODO`. +- `src/actions/*.spec.ts` — created — Vitest units against a Mongo double. + +`apps/web`: + +- `package.json`, `tsconfig.json`, `vite.config.ts`, `vitest.config.ts` (or the + `test` block inside the Vite config) — created. +- Tailwind + shadcn configuration and the generated `Button` / `Card` components under + the path shadcn's init chooses (`src/components/ui/`). +- the root route rendering the «Hola Mundo» page inside a `Card` with a `Button`. +- one `*.spec.tsx` smoke test for that page. + +## Functions / interfaces + +- `resolveMongoUri(env: NodeJS.ProcessEnv | Record): string` + — returns the trimmed `MONGODB_URI`; throws `Error` naming the variable and + `.env.example` when absent, empty or whitespace-only. Pure: no file reads, no + `process.env` access of its own (R30, R31). +- `createMongoClient(uri: string): MongoClient` — the official driver, configured with + `serverSelectionTimeoutMS` ≤ 5000 so failures are fast (R32). +- `pingDatabase(client: MongoClient): Promise<{ host: string; database: string }>` — + runs `db().command({ ping: 1 })` on the database encoded in the URI and returns what + it reached, for the runner's success line (R33, R40). +- `dropDatabase(client: MongoClient): Promise<{ database: string }>` — drops the + URI-encoded database; no hard-coded name (R33, R49). +- `checkConnection(deps): Promise` — runner operation; `{ ok: true, host, + database }` or `{ ok: false, error }`; never throws (R40, R41). +- `cleanDatabase(deps, confirmed: boolean): Promise` — `{ status: + 'cancelled' }` when `confirmed` is false **without touching the client**, else + `{ status: 'dropped', database }`, or `{ status: 'failed', error }` (R47–R51). +- `loadSeedData(): SeedResult` — synchronous, returns `{ status: 'pending' }` and takes + no client at all, so "no database access" is structural, not a promise (R43). +- The menu layer (`src/main.ts`) owns every `@inquirer/prompts` call — `select` for the + menu, `confirm` (default `false`) for the destructive operation — and no operation + module imports `@inquirer/prompts` (R45). + +## Edge cases + +- `MONGODB_URI` set to `" "` → treated as absent, explicit error (R31). +- `.env` missing but the variable exported in the shell → works; the file is optional + (R35). +- `.env` missing and the variable unset → explicit configuration error, printed, menu + stays usable (R42). +- Docker stopped during `db:up` → Docker's own error, non-zero exit (R27). +- Port 27017 already bound by a local Mongo → Docker's bind error; the documented way + out is changing the published port and `MONGODB_URI` (PRD assumption), not silent + fallback (R27). +- Mongo container up but still starting → `db:up` waits for healthy (R24); the runner's + check would otherwise fail misleadingly. +- Mongo unreachable when «check connection» runs → fails within the 5 s timeout with + the driver's message plus the `pnpm db:up` hint, returns to the menu (R41). +- `dropDatabase` against an already-empty database → succeeds, reported as dropped + (Mongo is idempotent here). +- Ctrl+C at any prompt → `@inquirer/prompts` throws `ExitPromptError`; caught at the + entry point, client closed, quiet exit (R44). +- shadcn / Tailwind version incompatibility → pin the working combination and record it + (R21). +- A scaffolding CLI leaving demo routes, logos or dependencies → pruned before done + (R18); `git status` must be clean after a build/test/dev cycle (R12). + +## Testing approach + +- **Unit (Vitest), `packages/db`**: `resolveMongoUri` present / absent / empty / + whitespace — the error path asserts the message names `MONGODB_URI`. `pingDatabase` + and `dropDatabase` against a client double (no driver socket). +- **Unit (Vitest), `console-runner`**: one spec per operation, against a Mongo double — + `checkConnection` ok and failure (double rejects); `cleanDatabase` confirmed ⇒ + `dropDatabase` called once, declined ⇒ **no** method called on the double and + `status: 'cancelled'`; `loadSeedData` ⇒ `status: 'pending'`. +- **Smoke (Vitest + jsdom + Testing Library), `apps/web`**: render the root route + component, assert the greeting text and the `Button`. No routing integration, no + styling or layout assertions. +- **Not tested, by decision**: the prompt layer itself (`select` / `confirm` wiring) — + it is a thin adapter and testing it would mean driving a TTY; the operations it calls + are fully covered. Docker, the real Mongo, `turbo` and CI are not exercised by the + suite either: the suite stays hermetic (R56). +- **Manual, part of done (R58)**: `pnpm db:up` → `pnpm runner` → «check connection» + green → `pnpm dev` → the page loads in a browser → `pnpm db:down`. This is the only + thing that proves the infrastructure actually runs, and it is recorded in + `progress.md`. diff --git a/.claude/state/tasks/1/spec/requirements.md b/.claude/state/tasks/1/spec/requirements.md new file mode 100644 index 0000000..2cdb0f8 --- /dev/null +++ b/.claude/state/tasks/1/spec/requirements.md @@ -0,0 +1,250 @@ +# Requirements — Infraestructura y estructura base del monorepo + +> Source PRD: docs/prds/infra-monorepo-2026-10-17.md +> Task: #1 — branch `harness/1-infra-monorepo` + +Scope note: this delivery is **infrastructure only**. No product surface, no domain +model, no auth. The success criterion is operational: a fresh clone can bring up the +database, start the front and run the maintenance runner from root `package.json` +scripts, and the PR passes the mechanical gates. + +## A. Monorepo root — one install, one entry point (US1) + +- **R1** (ubiquitous): The repository root shall be a private pnpm workspace whose + `pnpm-workspace.yaml` declares `apps/*`, `packages/*` and `console-runner` as + workspace packages. +- **R2** (ubiquitous): The root `package.json` shall pin the package manager with + `packageManager: "pnpm@10.19.0"` and declare the supported Node version in `engines` + (`node: ">=24.16.0 <25"`), matched by a committed `.nvmrc` holding `24.16.0`. +- **R3** (event): When `pnpm install` is run at the repository root, the system shall + install and link every workspace package's dependencies in a single command, with no + further manual configuration. +- **R4** (ubiquitous): After the migration the repository shall contain exactly one + lockfile — `pnpm-lock.yaml` — and no `package-lock.json`. +- **R5** (ubiquitous): The harness CLI shall stay resolvable at + `/node_modules/.bin/lemony` after a pnpm install, because + `.claude/hooks/lib/lemony.sh` resolves that exact path. +- **R6** (ubiquitous): The root `package.json` shall be the only entry point and expose + exactly these scripts: `dev`, `build`, `test`, `typecheck`, `format`, `format:check`, + `db:up`, `db:down`, `db:reset`, `runner`. +- **R7** (event): When one of the workspace-spanning root scripts (`dev`, `build`, + `test`, `typecheck`) is run, the system shall delegate the work to Turborepo through + `turbo.json`, not to a hand-written loop over directories. +- **R8** (ubiquitous): Every workspace package shall compile under TypeScript strict + mode (`strict: true`) from a shared root `tsconfig.base.json`. +- **R9** (event): When `pnpm typecheck` is run, the system shall run `tsc --noEmit` for + every workspace and exit non-zero if any workspace reports a type error. +- **R10** (event): When `pnpm format:check` is run, the system shall verify Prettier + formatting across the project's own tracked files and exit non-zero if any file is + unformatted. +- **R11** (ubiquitous): The Prettier scope shall exclude vendor and generated paths — + `node_modules`, `.claude/`, `pnpm-lock.yaml`, build outputs and caches — so a harness + vendor update can never fail the format gate. +- **R12** (event): When `pnpm build`, `pnpm test` or `pnpm dev` has been run, + `git status --porcelain` shall report no new untracked and no modified tracked files + (every build output and cache is gitignored). + +### Acceptance criteria + +- [ ] A fresh clone + `pnpm install` + `pnpm typecheck` + `pnpm test` + `pnpm build` + succeeds with no step outside the root `package.json`. +- [ ] `pnpm-lock.yaml` is committed; `package-lock.json` is gone from the worktree and + from the index. +- [ ] `.claude/hooks/lib/lemony.sh emit …` still works after the install (the launcher + finds the local bin). +- [ ] `git status --porcelain` is empty after a full `build` + `test` + a `dev` session. + +## B. Front end — «Hola Mundo» proving the TanStack Start → Tailwind → shadcn chain (US4) + +- **R13** (ubiquitous): `apps/web` shall be a TanStack Start application in TypeScript + strict mode, with Tailwind configured and shadcn initialised with style `new-york` + and base colour `neutral`. +- **R14** (event): When `pnpm dev` is run, the system shall serve `apps/web` on a local + port and its root route shall render the «Hola Mundo» page. +- **R15** (ubiquitous): The «Hola Mundo» route shall render its content inside a shadcn + `Card` and shall include a shadcn `Button`, so the styling chain is demonstrably + applied end to end. +- **R16** (ubiquitous): The page shall use the shadcn/Tailwind default tokens only — no + theme switcher, no dark-mode toggle, no custom palette (deferred by the PRD). +- **R17** (event): When `pnpm build` is run, the system shall produce a production build + of `apps/web` and exit zero. +- **R18** (ubiquitous): The repository shall contain no file, route, asset, script or + dependency left behind by a scaffolding CLI that is not used by the «Hola Mundo» + page, the tests, the gates or the build. +- **R19** (event): When the front smoke test runs, it shall render the «Hola Mundo» + route component and assert both the greeting text and the presence of the shadcn + `Button`, without Docker, a live Mongo or network access. +- **R20** (ubiquitous): The front end shall perform no database access in this delivery, + and `apps/web` shall declare no dependency on `@memora/db`. +- **R21** (unwanted): If the current shadcn release is incompatible with the Tailwind + version TanStack Start installs, then the implementation shall pin the exact + combination that works and state the pinned versions in `progress.md` and the PR + description, instead of leaving a broken or half-working styling chain. + +### Acceptance criteria + +- [ ] `pnpm dev` serves a page showing the greeting inside a `Card` with a styled + `Button` (Tailwind classes visibly applied). +- [ ] `pnpm test` runs the smoke test green with Docker stopped and no network. +- [ ] `apps/web/package.json` lists no unused dependency and no `@memora/db`. + +## C. MongoDB in Docker — reproducible local database (US2, US3) + +- **R22** (ubiquitous): `docker-compose.yml` at the repository root shall define a + single service built from image `mongo:8`, publishing port `27017`, with no + credentials, a **named volume** mounted at `/data/db`, and a healthcheck that reports + the server as ready. +- **R23** (ubiquitous): `docker-compose.yml` shall carry a header comment stating it is + for local development only — no credentials, never for an externally reachable + environment. +- **R24** (event): When `pnpm db:up` is run, the system shall start the Mongo container + detached and return only once the container reports healthy. +- **R25** (event): When `pnpm db:down` is run, the system shall stop and remove the + container while **preserving** the named volume, so the data survives. +- **R26** (event): When `pnpm db:reset` is run, the system shall remove the container + **and its named volume** and then start a fresh healthy container, so the database + comes back empty. +- **R27** (unwanted): If the Docker daemon is not running, or port 27017 is already + bound, then the `db:*` script shall surface Docker's own error message unchanged and + exit non-zero — no masking, no retry loop, no silent success. +- **R28** (ubiquitous): The database name shall be `memora` and the canonical local URI + `mongodb://localhost:27017/memora`. + +### Acceptance criteria + +- [ ] `pnpm db:up` → `docker compose ps` shows the service healthy. +- [ ] Data written between `db:up` and `db:down` is still there after `db:up` again. +- [ ] After `pnpm db:reset` the `memora` database is empty. +- [ ] With Docker stopped, `pnpm db:up` exits non-zero and prints Docker's error. + +## D. `packages/db` — the only place that knows how to reach Mongo (technical decision) + +- **R29** (ubiquitous): `packages/db`, published in the workspace as `@memora/db`, shall + be the only location in the repository that resolves `MONGODB_URI` or constructs a + Mongo client; no other workspace shall import the `mongodb` driver directly. +- **R30** (ubiquitous): `@memora/db` shall expose a pure resolver + (`resolveMongoUri(env)`) that returns the configured URI for a given environment + record, without reading global state itself. +- **R31** (unwanted): If `MONGODB_URI` is absent, empty or whitespace-only in the given + environment, then the resolver shall throw an explicit error naming the variable and + pointing at `.env.example`, and shall **not** fall back to any default URI. +- **R32** (ubiquitous): `@memora/db` shall expose a client factory + (`createMongoClient(uri)`) that applies a server-selection timeout of at most + 5000 ms, so an unreachable server fails fast instead of hanging on the driver's + default. +- **R33** (ubiquitous): `@memora/db` shall expose the two maintenance primitives the + runner needs — a connectivity check (`ping`) and a database drop — operating on the + database encoded in the URI, with no hard-coded database name. +- **R34** (ubiquitous): `.env.example` shall be versioned at the repository root with + `MONGODB_URI=mongodb://localhost:27017/memora`, and `.env` shall be gitignored. +- **R35** (event): When an entry point starts, the system shall load the + repository-root `.env` into the process environment if the file exists, and shall not + fail when it is absent — the missing-variable failure of R31 is the only + configuration failure path. +- **R36** (ubiquitous): `@memora/db` shall be consumed as TypeScript source (no build + step, no emitted `dist/`) and shall typecheck on its own via `pnpm typecheck`. +- **R37** (ubiquitous): The driver shall be the official `mongodb` package with generic + collection typing; no ODM (no Mongoose, no Prisma) shall be added. + +### Acceptance criteria + +- [ ] A unit test proves `resolveMongoUri` returns the value when present. +- [ ] A unit test proves the absent/empty variable throws, and the message names + `MONGODB_URI`. +- [ ] `grep` for `from 'mongodb'` outside `packages/db` returns nothing. + +## E. Console runner — discoverable maintenance menu (US5, US7) + +- **R38** (event): When `pnpm runner` is run, the system shall display an interactive + arrow-key menu offering exactly: check Mongo connection, clean database, load seed + data, exit — requiring no command-line flags. +- **R39** (event): When an operation finishes, the system shall return to the menu, and + when `exit` is chosen it shall close any open Mongo client and exit with code 0, + leaving no hanging process. +- **R40** (event): When «check connection» is chosen, the system shall connect with the + resolved URI, issue a `ping`, and report success naming the host and database it + reached. +- **R41** (unwanted): If the connection or `ping` fails (server down, timeout), then the + system shall report the failure with the driver's message plus a hint to run + `pnpm db:up`, return to the menu, and not crash with an unhandled-exception stack + trace. +- **R42** (unwanted): If `MONGODB_URI` cannot be resolved when an operation needs it, + then the runner shall print that explicit configuration error (R31) and return to the + menu without attempting a connection. +- **R43** (event): When «load seed data» is chosen, the system shall print a message + marking the operation as pending (`TODO`), perform **no** database access, and return + a pending result marker — it shall never report work it did not do. +- **R44** (unwanted): If the user interrupts a prompt (Ctrl+C), then the runner shall + terminate quietly — no unhandled-exception stack trace — closing any open client. +- **R45** (ubiquitous): Each runner operation shall be a function independent of the + prompt layer, receiving its Mongo client/db as a parameter, so it can be tested + against a double. +- **R46** (ubiquitous): The runner shall be executed with `tsx` directly over + TypeScript, with no build step. + +### Acceptance criteria + +- [ ] `pnpm runner` shows the four-entry menu and navigates with arrow keys. +- [ ] With Mongo down, «check connection» reports the failure and the menu is still + usable. +- [ ] «Load seed data» prints a `TODO` and the test proves no client method was called. +- [ ] Unit tests cover every operation function against a Mongo double. + +## F. Clean database — the destructive operation (US6) + +- **R47** (event): When «clean database» is chosen, the system shall first ask for an + explicit confirmation that names the target database, before touching anything. +- **R48** (ubiquitous): The confirmation prompt shall default to **no**, so proceeding + requires a deliberate keystroke. +- **R49** (state+event): While the confirmation has been accepted, the system shall call + `dropDatabase` on the database resolved from the URI and report the outcome. +- **R50** (unwanted): If the confirmation is declined, then the system shall perform no + write of any kind — `dropDatabase` shall not be called — and shall return a cancelled + marker. +- **R51** (unwanted): If `dropDatabase` fails, then the system shall report the error + and return to the menu, leaving the runner usable. + +### Acceptance criteria + +- [ ] A unit test proves accepted confirmation ⇒ `dropDatabase` called exactly once. +- [ ] A unit test proves declined confirmation ⇒ no method called on the double, result + marked cancelled. +- [ ] Manual check: cleaning the real local database actually empties it. + +## G. CI and declared gates (US8) + +- **R52** (event): When a pull request targeting `main` is opened or updated, GitHub + Actions shall run a workflow that installs with pnpm (`--frozen-lockfile`, with the + pnpm store cached) and then runs `typecheck`, `format:check`, `test` and `build`. +- **R53** (unwanted): If any of those four commands exits non-zero, then the workflow + shall fail — no `continue-on-error`, no step allowed to swallow a red gate. +- **R54** (ubiquitous): The workflow shall take the Node version from `.nvmrc` and the + pnpm version from the root `packageManager` field, so CI and local use the same + versions. +- **R55** (ubiquitous): `harness.config.yml` shall declare `gates:` as exactly + `typecheck`, `format:check`, `test`, `build`, and shall leave `merge.allow_no_checks` + at its default `false`. +- **R56** (ubiquitous): The whole test suite shall be hermetic — no test shall require + Docker, a live Mongo instance or network access. +- **R57** (ubiquitous): `README.md` shall document the quickstart for a fresh clone: + install, `db:up` / `db:down` / `db:reset`, `dev`, `runner`, and the gate commands. + +### Acceptance criteria + +- [ ] The PR for this task shows a green GitHub Actions check with the four gate steps. +- [ ] A deliberately broken type (locally) turns the `typecheck` step red. +- [ ] `harness.config.yml` lists the four gates under `gates:`. + +## H. Definition of done — manual real-run verification + +- **R58** (event): When the implementation is signalled done, `progress.md` shall record + the outcome of the manual real-run sequence, executed in this order: `pnpm db:up` → + `pnpm runner` → «check connection» reports success → `pnpm dev` → the «Hola Mundo» + page loads in a browser → `pnpm db:down`. +- **R59** (ubiquitous): This manual sequence shall be treated as part of done; the + hermetic suite does not cover it, and a green suite alone shall not be read as + evidence that the infrastructure runs. + +### Acceptance criteria + +- [ ] `progress.md` contains the six-step verification with its result. diff --git a/.claude/state/tasks/1/spec/tasks.md b/.claude/state/tasks/1/spec/tasks.md new file mode 100644 index 0000000..ea9a867 --- /dev/null +++ b/.claude/state/tasks/1/spec/tasks.md @@ -0,0 +1,117 @@ +# Tasks — Infraestructura y estructura base del monorepo + +> Source PRD: docs/prds/infra-monorepo-2026-10-17.md +> Requirements: `.claude/state/tasks/1/spec/requirements.md` +> Design: `.claude/state/tasks/1/spec/design.md` + +Order matters: the root workspace is the tracer bullet — nothing else can be installed, +typechecked or run until it exists. Each group leaves something the human can run at the +checkpoint. + +## Group 1 — Workspace root _(isolates the package-manager migration: it replaces the live npm install the harness depends on and is the hardest step to reverse)_ + +- [ ] T1 — Turn the root into a private pnpm workspace: `pnpm-workspace.yaml` + (`apps/*`, `packages/*`, `console-runner`), root `package.json` with + `packageManager: pnpm@10.19.0` and `engines.node >=24.16.0 <25`, `.nvmrc` with + `24.16.0`, `@lemoncode/lemony` kept as a root devDependency; delete + `package-lock.json`, run `pnpm install`, commit `pnpm-lock.yaml`, and prove the + harness launcher still resolves (`.claude/hooks/lib/lemony.sh --version` or an + `emit`, which needs `node_modules/.bin/lemony`) (R1, R2, R3, R4, R5) +- [ ] T2 — Add `turbo.json` (tasks `dev` persistent + uncached, `build`, `test`, + `typecheck`) and the ten root scripts of the single entry point, with the + workspace-spanning four delegating to Turborepo (R6, R7) +- [ ] T3 — Add `tsconfig.base.json` with strict mode and wire `pnpm typecheck` so it + runs `tsc --noEmit` per workspace and fails on any type error (R8, R9) +- [ ] T4 — Add Prettier (`.prettierrc`), `.prettierignore` excluding `node_modules`, + `.claude/`, `pnpm-lock.yaml` and build outputs, the `format` / `format:check` + scripts, and extend `.gitignore` with `.env`, `.turbo/` and the build outputs so + a build/test/dev cycle leaves `git status` clean (R10, R11, R12) + +## Group 2 — Front end «Hola Mundo» _(isolates the stack integration the PRD calls the most fragile part of this delivery: TanStack Start + Tailwind + shadcn)_ + +- [ ] T5 — Scaffold `apps/web` as a TanStack Start app in strict TypeScript, reachable + through the root `dev`, `build` and `typecheck` scripts, declaring no dependency + on `@memora/db` and touching no database (R14, R17, R20) +- [ ] T6 — Configure Tailwind and initialise shadcn (`new-york`, `neutral`), install + `Button` and `Card`, and render the «Hola Mundo» page inside a `Card` with a + `Button`, using default tokens only — no theme switcher; if shadcn and the + installed Tailwind disagree, pin the working combination and record the versions + in `progress.md` (R13, R15, R16, R21) +- [ ] T7 — Add the single front smoke test (Vitest + jsdom + Testing Library) that + renders the page and asserts the greeting text and the `Button`, green with + Docker stopped and no network (R19) +- [ ] T8 — Prune the scaffolding noise: remove every demo route, asset, script and + dependency the CLI left that the page, the tests, the gates or the build do not + use (R18) + +## Group 3 — Local MongoDB in Docker _(isolates the data surface: `db:reset` deletes the named volume, so the mistake here destroys local data)_ [risk: data-loss] + +- [ ] T9 — Add the root `docker-compose.yml`: single `mongo:8` service, `27017:27017`, + no credentials, named volume at `/data/db`, a `ping` healthcheck, and the header + comment marking it local-development-only; database `memora` at + `mongodb://localhost:27017/memora` (R22, R23, R28) +- [ ] T10 — Add `db:up` (detached, waiting for healthy) and `db:down` (container + removed, volume preserved), each surfacing Docker's own error and exiting + non-zero when the daemon is down or the port is bound (R24, R25, R27) +- [ ] T11 — Add `db:reset`: remove the container **and** its volume, then bring up a + fresh healthy container so the database comes back empty (R26) + +## Group 4 — `packages/db`, the only door to Mongo _(isolates a new seam every future consumer will depend on: configuration resolution and the client factory)_ + +- [ ] T12 — Create `packages/db` as `@memora/db`: `exports`/`types` pointing at + `src/index.ts` (no build step, no `dist/`), the official `mongodb` driver and no + ODM, typechecking on its own, and the only place in the repository that imports + the driver (R29, R36, R37) +- [ ] T13 — TDD `resolveMongoUri(env)`: returns the configured URI; throws an explicit + error naming `MONGODB_URI` and `.env.example` when absent, empty or + whitespace-only, with no default fallback (R30, R31) +- [ ] T14 — TDD the client primitives against a double: `createMongoClient` with + `serverSelectionTimeoutMS` ≤ 5000, `pingDatabase` returning the host and database + reached, and `dropDatabase` operating on the URI-encoded database with no + hard-coded name (R32, R33) +- [ ] T15 — Add the versioned `.env.example` with + `MONGODB_URI=mongodb://localhost:27017/memora` and confirm `.env` is ignored by + git (R34) + +## Group 5 — Console runner menu _(isolates the interactive entry point and its non-destructive operations; the destructive one is deliberately left to the next group)_ + +- [ ] T16 — Create the `console-runner` workspace at the repository root and the root + `runner` script running `tsx console-runner/src/main.ts` from the root, loading + the root `.env` when it exists and not failing when it does not (R35, R46) +- [ ] T17 — Build the `@inquirer/prompts` `select` menu with its four entries and the + loop that returns to it after each operation; «Salir» closes the client and exits + 0, and a Ctrl+C (`ExitPromptError`) exits quietly with no stack trace + (R38, R39, R44) +- [ ] T18 — TDD the prompt-free `checkConnection` operation against a Mongo double — + success reports host and database, failure reports the driver message plus the + `pnpm db:up` hint and returns to the menu without crashing — and wire it to the + menu (R40, R41, R45) +- [ ] T19 — TDD `loadSeedData` returning the pending marker and printing a `TODO` with + no database access at all, and the unresolved-`MONGODB_URI` path printing the + configuration error and returning to the menu without connecting (R42, R43) + +## Group 6 — Clean database _(isolates the only operation in the delivery that destroys data, one keystroke away from the connection check)_ [risk: data-loss] + +- [ ] T20 — TDD the prompt-free `cleanDatabase(deps, confirmed)` operation: confirmed ⇒ + `dropDatabase` called exactly once and the outcome reported; declined ⇒ no method + called on the client double and a cancelled marker returned; a driver failure ⇒ + reported, runner still usable (R47, R49, R50, R51) +- [ ] T21 — Wire the operation to the menu behind an `@inquirer/prompts` `confirm` that + names the target database and defaults to no, so Enter cancels (R48) + +## Group 7 — CI, declared gates and the real-run verification _(closes the delivery: the gates the harness reads, the documentation a fresh clone needs, and the only proof the infrastructure actually runs)_ + +- [ ] T22 — Add `.github/workflows/ci.yml` running on pull requests to `main`: pnpm + install `--frozen-lockfile` with the store cached, Node from `.nvmrc` and pnpm + from `packageManager`, then `typecheck`, `format:check`, `test` and `build`, with + no step allowed to swallow a red gate (R52, R53, R54) +- [ ] T23 — Declare `gates:` in `harness.config.yml` as exactly `typecheck`, + `format:check`, `test`, `build`, leaving `merge.allow_no_checks` at its default + `false`, and confirm the whole suite is hermetic (green with Docker stopped and + no network) (R55, R56) +- [ ] T24 — Write the `README.md` quickstart: `pnpm install`, `db:up` / `db:down` / + `db:reset`, `dev`, `runner` and the four gate commands (R57) +- [ ] T25 — Run the manual real-run verification and record its outcome in + `progress.md`: `pnpm db:up` → `pnpm runner` → «check connection» green → + `pnpm dev` → the «Hola Mundo» page loads in a browser → `pnpm db:down`; a green + suite alone is not evidence the infrastructure runs (R58, R59) diff --git a/docs/prds/infra-monorepo-2026-10-17.md b/docs/prds/infra-monorepo-2026-10-17.md new file mode 100644 index 0000000..6b0c6e1 --- /dev/null +++ b/docs/prds/infra-monorepo-2026-10-17.md @@ -0,0 +1,223 @@ +# PRD: Infraestructura y estructura base del monorepo + +**Date**: 2026-10-17 +**Mode**: validation +**Status**: completed + +## Problem Statement + +Memora (ver `docs/product/memora-brief.md`) no tiene todavía ni una línea de código de +producto: el repositorio contiene únicamente el harness Lemony y un `README.md` vacío. +Antes de poder construir cualquier funcionalidad del MVP (registro, círculos, álbumes, +fotos) hace falta un terreno de trabajo: un monorepo con el proyecto front, una base de +datos local reproducible y una herramienta de mantenimiento desde consola. + +Esta tarea entrega ese terreno y **nada de producto**. El criterio de éxito es +operativo, no funcional: alguien que clona el repositorio puede levantar la base de +datos, arrancar el front y ejecutar el runner de mantenimiento con comandos del +`package.json` raíz, y el PR pasa los gates mecánicos. + +Hallazgos del reconocimiento del entorno: + +- Repo `Lemoncode/demo-memora`, limpio, sin código previo ni `CLAUDE.md` / `CONTEXT.md`. +- Node v24.16.0, npm 12.0.2, **pnpm 10.19 ya disponible**. +- Docker 27.3.1 + Compose v2.29 operativos. +- `gh` autenticado; las etiquetas del harness existen en el repo. +- No hay CI: con `merge.allow_no_checks: false` en `harness.config.yml`, el gate de + merge preguntaría a un humano en cada PR mientras no haya checks. + +## User Stories + +1. Como desarrollador que acaba de clonar el repositorio, quiero instalar dependencias + con un solo comando y tener todos los paquetes del monorepo enlazados, para empezar + a trabajar sin configuración manual. +2. Como desarrollador, quiero levantar MongoDB en local con un comando del + `package.json` (`pnpm db:up`), para no tener que instalar Mongo en mi máquina ni + recordar flags de Docker. +3. Como desarrollador, quiero poder tirar la base de datos y volver a empezar de cero + (`pnpm db:reset`), para probar desde un estado limpio. +4. Como desarrollador, quiero arrancar el front con `pnpm dev` y ver una página «Hola + Mundo» que use un componente de shadcn, para confirmar que la cadena TanStack Start + → Tailwind → shadcn funciona de punta a punta. +5. Como desarrollador, quiero lanzar la herramienta de consola con `pnpm runner` y ver + un menú de operaciones de mantenimiento, para tener un sitio donde ir añadiendo + tareas de administración a medida que crezca el proyecto. +6. Como desarrollador, quiero que el runner compruebe la conexión a Mongo y pueda + limpiar la base de datos, para verificar que la infra está viva y para reiniciar mi + entorno de pruebas. +7. Como desarrollador, quiero ver en el runner la opción de cargar datos de prueba + marcada explícitamente como pendiente, para saber que el hueco existe y está + reservado, sin que finja hacer algo. +8. Como desarrollador, quiero que cada PR ejecute typecheck, formato, tests y build en + CI, para que no entre a `main` nada que no compile. + +## Product / UX Decisions + +- **Superficie de producto en esta entrega**: ninguna. El front es un «Hola Mundo» — + porque el objetivo es validar la cadena de herramientas, no diseñar pantallas. +- **Tema claro / oscuro**: fuera de esta entrega, aunque esté en el MVP — porque + implica decisiones de diseño (paleta, ubicación del selector) que merecen su propia + tarea con su fase de diseño, en vez de colarse en el scaffolding. +- **UX del runner**: menú interactivo con flechas (no flags de línea de comandos) — + porque es una herramienta de mantenimiento humano y se quiere descubrible: entras y + ves qué operaciones hay sin leer documentación. +- **Operación destructiva**: «Limpiar base de datos» pide confirmación explícita antes + de ejecutar el `dropDatabase` — porque es irreversible y estará a una tecla de la + opción de comprobar la conexión. +- **La opción de datos de prueba no se oculta**: aparece en el menú e imprime un `TODO` + — porque un hueco señalizado comunica la intención; una opción ausente parece olvido. + +## Technical Decisions + +- **Monorepo**: Turborepo con pnpm workspaces — porque es la combinación estándar con + este stack, y los filtros `--filter` y el enlazado estricto de pnpm evitan + dependencias fantasma que compilan en local y revientan en CI. +- **Gestor de paquetes**: pnpm (ya instalado, 10.19), fijado con el campo + `packageManager` en el `package.json` raíz. +- **Estructura**: + + ``` + demo-memora/ + ├─ apps/web/ TanStack Start + TypeScript + Tailwind + shadcn + ├─ console-runner/ CLI de mantenimiento (en la raíz, por petición explícita) + ├─ packages/db/ cliente Mongo + resolución de configuración (compartido) + ├─ docker-compose.yml + ├─ turbo.json + └─ pnpm-workspace.yaml + ``` + + `console-runner` vive en la raíz y no en `apps/` por petición explícita; es un + workspace de pnpm como cualquier otro. + +- **Acceso a datos**: driver oficial `mongodb` con tipado genérico de colecciones, sin + ODM — porque no añade capa intermedia, no pelea con TypeScript estricto y no oculta + lo que se envía a Mongo. La validación de forma se hará con zod en la frontera + (server functions), que es donde de verdad hace falta. +- **`packages/db` es el único sitio que sabe conectar a Mongo**: expone el cliente y la + resolución de `MONGODB_URI`, y lo consumen tanto las server functions del front como + el runner — porque cuando lleguen los modelos de dominio ya tienen casa y no hay que + refactorizar dos consumidores. +- **API**: sin proyecto de API separado; la lógica de servidor irá en **server + functions de TanStack Start** — por petición explícita. +- **Mongo local**: imagen `mongo:8` vía Docker Compose, puerto 27017, **sin + credenciales**, con volumen nombrado para que los datos sobrevivan a `db:down`. Base + de datos `memora`, URI `mongodb://localhost:27017/memora` — porque la fricción cero + para arrancar pesa más que parecerse a producción en un entorno local. +- **Configuración**: `MONGODB_URI` por variable de entorno, con `.env` ignorado por git + y `.env.example` versionado; `packages/db` falla de forma explícita si falta. +- **Ejecución del runner**: `tsx` directamente sobre TypeScript, sin paso de build — + porque es una herramienta de desarrollo y un build intermedio sólo añade latencia. +- **Prompts del runner**: `@inquirer/prompts` — porque es el estándar maduro para menús + interactivos en Node y su API por funciones se testea bien. +- **Calidad de código**: Prettier para formato, **sin linter**; TypeScript en modo + estricto hace de red. **Consecuencia asumida y explícita**: `typecheck` pasa a ser el + gate mecánico que carga el peso, y los errores que detectaría un linter (hooks mal + usados, promesas sin `await`) quedan para la revisión humana. +- **CI**: workflow de GitHub Actions en cada PR — install con pnpm (cacheado), + `typecheck`, `format:check`, `test` y `build` — porque el gate de merge del harness + necesita un verde real que comprobar, y sin él pregunta a mano en cada PR. +- **Gates declarados**: `typecheck`, `format:check`, `test`, `build` en la clave + `gates:` de `harness.config.yml`, para que el Reviewer los exija en su ledger. +- **Node**: versión fijada con `.nvmrc` y `engines` en el `package.json` raíz. +- **Scripts del `package.json` raíz** (única puerta de entrada): `dev`, `build`, + `test`, `typecheck`, `format`, `format:check`, `db:up`, `db:down`, `db:reset`, + `runner`. +- **shadcn**: estilo `new-york`, color base `neutral`, con `Button` y `Card` instalados + y usados en la página «Hola Mundo» para demostrar que la cadena de estilos aplica. + +## Testing Decisions + +- **Runner (lógica)**: Vitest. Las acciones se escriben desacopladas de los prompts + (una función por operación) y se testean contra un doble del cliente de Mongo: la + acción de limpiar invoca `dropDatabase`; la acción de datos de prueba devuelve su + marca de pendiente; la confirmación denegada **no** borra nada. +- **`packages/db` (configuración)**: Vitest. Resolución de `MONGODB_URI` — valor + presente, variable ausente (error explícito, no caída silenciosa). +- **Front**: un único smoke test de que la página «Hola Mundo» renderiza. No se testea + estilo ni layout. +- **Suite hermética**: los tests **no** requieren Docker ni un Mongo vivo — porque una + suite que depende de servicios externos se vuelve frágil y lenta justo cuando más se + usa. +- **Verificación de la infra real**: manual y explícita en la definición de terminado — + `pnpm db:up`, `pnpm runner` → comprobar conexión en verde, `pnpm dev` → la página + carga. Es lo único que esta entrega hace de verdad y la suite no lo cubre. + +## Out of Scope + +- Modelo de dominio del MVP (usuarios, círculos, álbumes, fotos, personas/etiquetas) y + cualquier esquema de colección. +- Generación de datos semilla reales, incluido el usuario `admin@email.com` con su + contraseña y los usuarios fake: la opción del menú existe pero imprime un `TODO`. +- Autenticación, sesiones, registro e inicio de sesión. +- Almacenamiento de binarios de las fotos (disco local / MinIO / Cloudinary) y subida + de ficheros. +- Tema claro / oscuro / sistema y cualquier decisión de diseño visual. +- PWA e instalabilidad en la pantalla de inicio. +- Despliegue, entornos remotos, Mongo gestionado, credenciales de producción. +- Proyecto de API separado. +- Linter. + +## Discarded Alternatives + +- **npm workspaces**: descartado porque el hoisting plano invita a dependencias + fantasma y la ergonomía de filtrado es peor; pnpm ya estaba instalado. +- **Mongoose**: descartado porque añade una capa de abstracción con su propio tipado + que pelea con TypeScript estricto, y sus modelos globales molestan con el hot-reload. +- **Prisma con MongoDB**: descartado porque su conector exige replica set (complica el + contenedor), no cubre todo Mongo y añade un paso de generación al build. +- **Sembrar el dominio completo ahora**: descartado porque el modelo nacería sin UI que + lo valide — acertar a medias y refactorizar cuesta más que esperar. +- **Decidir ya el almacenamiento de fotos**: descartado porque es una decisión de + arquitectura con peso propio y no cabe dentro de una tarea de scaffolding. +- **Runner enteramente simulado (todo `TODO`)**: descartado porque dejaría la infra sin + verificar; limpiar la base de datos no necesita modelo de dominio y sí demuestra que + la cadena funciona. +- **Mongo con credenciales / con mongo-express**: descartados para reducir fricción de + arranque y contenedores en marcha; se puede añadir cuando haya datos que inspeccionar. +- **ESLint + Prettier** y **Biome**: descartados por decisión explícita del usuario a + favor de sólo Prettier (ver la consecuencia asumida en Decisiones Técnicas). +- **Sin CI** y **sin CI con `allow_no_checks: true`**: descartados porque dejan entrar a + `main` código que no compila, o desactivan una salvaguarda de forma permanente. +- **Tema oscuro en el esqueleto**: descartado para esta entrega porque convierte el + scaffolding en una tarea de diseño. + +## Assumptions + +- La versión actual de shadcn soporta la versión de Tailwind que instale TanStack + Start; si no, se fija la combinación que sí funciona (y se anota en el PR). +- Puerto 27017 libre en la máquina de desarrollo; si hay un Mongo local en marcha, se + resuelve cambiando el puerto publicado en `docker-compose.yml` y la `MONGODB_URI`. +- Docker Desktop está arrancado cuando se usan los scripts `db:*`. +- La lógica de servidor con server functions será suficiente para el MVP; no se + necesitará un servicio de API separado. + +## Risks + +- **Scaffolding generado que nadie revisa de verdad**: los CLI de creación de proyectos + dejan ficheros de ejemplo y dependencias que no se usan; si no se limpian, el repo + arranca con ruido que se arrastra durante meses. +- **Versiones del stack en movimiento**: TanStack Start, Tailwind y shadcn evolucionan + rápido y su integración mutua es la parte más frágil de esta entrega. +- **Sin linter**: errores que un linter detecta en frío llegarán a la revisión humana o + a producción; el riesgo crece cuando entre más gente al repo. +- **El hueco del seed se queda hueco**: una opción que imprime `TODO` puede vivir ahí + mucho tiempo; conviene que la tarea del modelo de dominio la retome pronto. +- **La base de datos sin credenciales** es cómoda en local y peligrosa si el mismo + compose se copia hacia un entorno accesible desde fuera. + +## Open Points + +- [ ] Modelo de dominio del MVP y datos semilla reales (usuario `admin@email.com` / + `test` + usuarios fake + círculos, álbumes y fotos de prueba). +- [ ] Almacenamiento de los binarios de las fotos: disco local, MinIO o un servicio + gestionado. +- [ ] Estrategia de autenticación y sesiones. +- [ ] Tema claro / oscuro / sistema y dirección visual del producto. +- [ ] PWA e instalabilidad. +- [ ] Despliegue y entorno remoto (incluido el Mongo gestionado). + +## Next Steps + +- [ ] Hand off to the Spec Author (`prd-to-spec`) to turn this PRD into a spec. +- [ ] Declarar los gates en `harness.config.yml` como parte de la implementación. +- [ ] Abrir la tarea del modelo de dominio + datos semilla cuando esta cierre. diff --git a/docs/product/memora-brief.md b/docs/product/memora-brief.md new file mode 100644 index 0000000..7785b70 --- /dev/null +++ b/docs/product/memora-brief.md @@ -0,0 +1,47 @@ +--- +title: Memora — brief funcional +status: reference +date: 2026-10-17 +--- + +# Memora — brief funcional + +> Documento de contexto (no es un PRD ni una spec). Describe el producto al que +> sirven todas las tareas del repo. Lo consumen el grill, el Spec Author y el +> Architect para no perder el norte de producto. + +## Qué es Memora + +Las fotos de un viaje, una boda o un cumpleaños acaban repartidas entre los móviles +de cada persona, chats, nubes y discos. **Memora** es un archivo **privado y +colaborativo** de recuerdos fotográficos: un grupo de personas de confianza (un +**círculo**) reúne sus fotos en álbumes compartidos, etiqueta quién aparece en cada +una y descarga lo que quiera. + +**No es una red social**: no hay perfiles públicos, seguidores, likes ni contenido +público. + +**Propuesta de valor:** «Todos vuestros recuerdos, por fin, en el mismo lugar». + +## Qué se va a construir + +Una **aplicación web real** (no una maqueta) que funciona con la misma calidad en +**móvil** y en **escritorio**, instalable en la pantalla de inicio del móvil, con +tema claro y oscuro, **API propia** y datos persistentes. + +## Alcance del MVP + +- Registro e inicio de sesión. +- Círculos privados con invitación por enlace (con vista previa al compartirlo en un + chat) o por email. +- Álbumes colaborativos y subida de fotos desde la galería o la cámara del móvil, y + con arrastrar y soltar en escritorio. +- Galería, vista de foto con autor, fecha, lugar y descripción. +- Etiquetado de personas y filtro «Fotos de esta persona». +- Descarga de fotos y de álbumes completos. +- Perfil, tema claro / oscuro / sistema y permisos por círculo. + +## No objetivos (explícitos) + +- Perfiles públicos, seguidores, likes, feed público. +- Descubrimiento de contenido entre desconocidos. From 7341eb425548622e2ff2084c653484dd354d7331 Mon Sep 17 00:00:00 2001 From: Braulio Date: Sun, 18 Oct 2026 00:05:35 +0200 Subject: [PATCH 2/4] task(1): implementation Lemony-Checkpoint: .claude/hooks/lib/lemony.sh checkpoint ok --task-id=1 --auto-commit=off --- .env.example | 6 + .github/workflows/ci.yml | 51 + .gitignore | 15 + .nvmrc | 1 + .prettierignore | 27 + .prettierrc | 7 + README.md | 79 + apps/web/components.json | 21 + apps/web/package.json | 36 + apps/web/src/components/home-page.spec.tsx | 22 + apps/web/src/components/home-page.tsx | 28 + apps/web/src/components/ui/button.tsx | 61 + apps/web/src/components/ui/card.tsx | 85 + apps/web/src/routeTree.gen.ts | 68 + apps/web/src/router.tsx | 17 + apps/web/src/routes/__root.tsx | 30 + apps/web/src/routes/index.tsx | 5 + apps/web/src/styles.css | 124 + apps/web/tsconfig.json | 15 + apps/web/tsr.config.json | 3 + apps/web/vite.config.ts | 10 + apps/web/vitest.config.ts | 14 + apps/web/vitest.setup.ts | 7 + console-runner/package.json | 19 + .../src/actions/check-connection.spec.ts | 38 + .../src/actions/check-connection.ts | 26 + .../src/actions/clean-database.spec.ts | 49 + console-runner/src/actions/clean-database.ts | 34 + console-runner/src/actions/seed-data.spec.ts | 20 + console-runner/src/actions/seed-data.ts | 20 + console-runner/src/main.ts | 146 + console-runner/tsconfig.json | 7 + docker-compose.yml | 33 + harness.config.yml | 11 +- package-lock.json | 159 - package.json | 24 +- packages/db/package.json | 25 + packages/db/src/client.spec.ts | 75 + packages/db/src/client.ts | 83 + packages/db/src/config.spec.ts | 44 + packages/db/src/config.ts | 26 + packages/db/src/index.ts | 20 + packages/db/tsconfig.json | 7 + pnpm-lock.yaml | 5235 +++++++++++++++++ pnpm-workspace.yaml | 10 + tsconfig.base.json | 22 + turbo.json | 19 + 47 files changed, 6720 insertions(+), 164 deletions(-) create mode 100644 .env.example create mode 100644 .github/workflows/ci.yml create mode 100644 .nvmrc create mode 100644 .prettierignore create mode 100644 .prettierrc create mode 100644 apps/web/components.json create mode 100644 apps/web/package.json create mode 100644 apps/web/src/components/home-page.spec.tsx create mode 100644 apps/web/src/components/home-page.tsx create mode 100644 apps/web/src/components/ui/button.tsx create mode 100644 apps/web/src/components/ui/card.tsx create mode 100644 apps/web/src/routeTree.gen.ts create mode 100644 apps/web/src/router.tsx create mode 100644 apps/web/src/routes/__root.tsx create mode 100644 apps/web/src/routes/index.tsx create mode 100644 apps/web/src/styles.css create mode 100644 apps/web/tsconfig.json create mode 100644 apps/web/tsr.config.json create mode 100644 apps/web/vite.config.ts create mode 100644 apps/web/vitest.config.ts create mode 100644 apps/web/vitest.setup.ts create mode 100644 console-runner/package.json create mode 100644 console-runner/src/actions/check-connection.spec.ts create mode 100644 console-runner/src/actions/check-connection.ts create mode 100644 console-runner/src/actions/clean-database.spec.ts create mode 100644 console-runner/src/actions/clean-database.ts create mode 100644 console-runner/src/actions/seed-data.spec.ts create mode 100644 console-runner/src/actions/seed-data.ts create mode 100644 console-runner/src/main.ts create mode 100644 console-runner/tsconfig.json create mode 100644 docker-compose.yml delete mode 100644 package-lock.json create mode 100644 packages/db/package.json create mode 100644 packages/db/src/client.spec.ts create mode 100644 packages/db/src/client.ts create mode 100644 packages/db/src/config.spec.ts create mode 100644 packages/db/src/config.ts create mode 100644 packages/db/src/index.ts create mode 100644 packages/db/tsconfig.json create mode 100644 pnpm-lock.yaml create mode 100644 pnpm-workspace.yaml create mode 100644 tsconfig.base.json create mode 100644 turbo.json diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..405fa9f --- /dev/null +++ b/.env.example @@ -0,0 +1,6 @@ +# Copy this file to `.env` at the repository root and adjust if you need to. +# `.env` is git-ignored; this example is versioned. +# +# Only `packages/db` (@memora/db) reads this value — it is the single door to Mongo. +# It must point at the database the local Docker container publishes (`pnpm db:up`). +MONGODB_URI=mongodb://localhost:27017/memora diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..dd897c2 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,51 @@ +name: CI + +# Runs on pull requests targeting `main` (D16): the harness merge gate reads the +# check status of the PR, and the flow always merges through a PR. +on: + pull_request: + branches: [main] + +# A new push to the same PR makes the previous run obsolete. +concurrency: + group: ci-${{ github.ref }} + cancel-in-progress: true + +jobs: + gates: + name: Declared gates + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v7 + + # No `version:` input on purpose — the action reads the pnpm version from the + # root `packageManager` field, so CI and local can never drift (R54). + - name: Set up pnpm + uses: pnpm/action-setup@v6 + + # Node comes from the committed .nvmrc, for the same reason (R54). + # `cache: pnpm` caches the pnpm store, and needs pnpm on PATH already. + - name: Set up Node + uses: actions/setup-node@v7 + with: + node-version-file: .nvmrc + cache: pnpm + + - name: Install + run: pnpm install --frozen-lockfile + + # The four declared gates (harness.config.yml `gates:`), each its own step so + # a red one is obvious. No `continue-on-error` anywhere: any non-zero exit + # fails the workflow (R53). + - name: Typecheck + run: pnpm typecheck + + - name: Format check + run: pnpm format:check + + - name: Test + run: pnpm test + + - name: Build + run: pnpm build diff --git a/.gitignore b/.gitignore index 8848719..b29c2d9 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,18 @@ node_modules .claude/state/tmp/ .claude/.harness/snapshots/ # END lemony + +# Local environment (see .env.example) +.env + +# Build outputs +dist/ +.output/ +.tanstack/ +.nitro/ + +# Caches +.turbo/ +.vite/ +coverage/ +*.tsbuildinfo diff --git a/.nvmrc b/.nvmrc new file mode 100644 index 0000000..b832e40 --- /dev/null +++ b/.nvmrc @@ -0,0 +1 @@ +24.16.0 diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..b0968e4 --- /dev/null +++ b/.prettierignore @@ -0,0 +1,27 @@ +# Vendor and generated paths are out of the format gate's scope (design decision D2): +# formatting files we do not own would make `format:check` go red on an unrelated +# `lemony update`. + +# Dependencies +node_modules/ + +# Harness (vendored — not ours to format) +.claude/ +# ...and the harness files the installer drops outside .claude/: `lemony repair` +# regenerates them, so formatting them would fail the gate on a vendor update. +harness.config.schema.json +docs/playbooks/README.md + +# Lockfile (pnpm owns its layout) +pnpm-lock.yaml + +# Build outputs and caches +dist/ +.output/ +.turbo/ +.tanstack/ +.vite/ +coverage/ + +# Generated sources +**/routeTree.gen.ts diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..1cbe3b2 --- /dev/null +++ b/.prettierrc @@ -0,0 +1,7 @@ +{ + "semi": true, + "singleQuote": true, + "trailingComma": "all", + "printWidth": 90, + "tabWidth": 2 +} diff --git a/README.md b/README.md index e69de29..cfb73ff 100644 --- a/README.md +++ b/README.md @@ -0,0 +1,79 @@ +# Memora + +Monorepo de Memora. Esta entrega es **sólo infraestructura**: no hay superficie de +producto todavía (ver `docs/product/memora-brief.md` para el producto y +`docs/prds/` para los PRD). + +## Qué hay dentro + +| Ruta | Qué es | +| ---------------- | ----------------------------------------------------------- | +| `apps/web` | Front en TanStack Start + Tailwind + shadcn («Hola Mundo») | +| `packages/db` | `@memora/db` — el único sitio que sabe conectar con Mongo | +| `console-runner` | Herramienta de mantenimiento por consola (menú interactivo) | + +## Requisitos + +- **Node 24.16.0** — la versión está fijada en `.nvmrc` (`nvm use` / `fnm use`). +- **pnpm 10.19.0** — fijado en `packageManager`; con Corepack habilitado se usa solo. +- **Docker Desktop** arrancado, para los comandos `db:*`. + +## Arranque rápido + +```bash +pnpm install # instala y enlaza todos los workspaces +cp .env.example .env # MONGODB_URI=mongodb://localhost:27017/memora +pnpm db:up # levanta MongoDB y espera a que esté healthy +pnpm dev # front en http://localhost:3000 +``` + +El `package.json` de la raíz es la **única puerta de entrada**: no hace falta entrar +en ningún subdirectorio. + +## Base de datos + +MongoDB 8 en Docker, sin credenciales, en `localhost:27017`, base de datos `memora`. + +| Comando | Qué hace | +| --------------- | -------------------------------------------------------------------------- | +| `pnpm db:up` | Arranca el contenedor en background y **espera** a que reporte healthy. | +| `pnpm db:down` | Para y elimina el contenedor. **Los datos sobreviven** (volumen nombrado). | +| `pnpm db:reset` | Elimina el contenedor **y su volumen**, y levanta uno nuevo: base vacía. | + +> `docker-compose.yml` es **sólo para desarrollo local**: la base no tiene +> credenciales. No lo copies a ningún entorno accesible desde fuera de tu máquina. + +## Herramienta de consola + +```bash +pnpm runner +``` + +Menú interactivo (se navega con las flechas) con cuatro opciones: comprobar la +conexión con Mongo, limpiar la base de datos, cargar datos de prueba y salir. + +- **Limpiar base de datos** pide confirmación nombrando la base y por defecto + responde **no**: pulsar Enter cancela. +- **Cargar datos de prueba** está reservada: imprime un `TODO` y no toca la base. + Llegará con el modelo de dominio. + +Lee `MONGODB_URI` del `.env` de la raíz si existe; si falta la variable, falla con un +mensaje explícito en vez de inventarse una URI por defecto. + +## Gates + +Los cuatro comandos que ejecuta CI en cada PR contra `main` +(`.github/workflows/ci.yml`), y los declarados en `harness.config.yml`: + +```bash +pnpm typecheck # tsc --noEmit en todos los workspaces +pnpm format:check # Prettier +pnpm test # Vitest +pnpm build # build de producción +``` + +No hay linter por decisión explícita: TypeScript en modo estricto hace de red, así +que `typecheck` es el gate que carga el peso. + +`pnpm format` arregla el formato. La suite es **hermética**: no necesita Docker, ni +un Mongo vivo, ni red. diff --git a/apps/web/components.json b/apps/web/components.json new file mode 100644 index 0000000..cc95a53 --- /dev/null +++ b/apps/web/components.json @@ -0,0 +1,21 @@ +{ + "$schema": "https://ui.shadcn.com/schema.json", + "style": "new-york", + "rsc": false, + "tsx": true, + "tailwind": { + "config": "", + "css": "src/styles.css", + "baseColor": "neutral", + "cssVariables": true, + "prefix": "" + }, + "aliases": { + "components": "#/components", + "utils": "#/lib/utils", + "ui": "#/components/ui", + "lib": "#/lib", + "hooks": "#/hooks" + }, + "iconLibrary": "lucide" +} diff --git a/apps/web/package.json b/apps/web/package.json new file mode 100644 index 0000000..17dd975 --- /dev/null +++ b/apps/web/package.json @@ -0,0 +1,36 @@ +{ + "name": "@memora/web", + "private": true, + "type": "module", + "imports": { + "#/*": "./src/*" + }, + "scripts": { + "dev": "vite dev --port 3000", + "build": "vite build", + "test": "vitest run", + "typecheck": "tsc --noEmit" + }, + "dependencies": { + "@tanstack/react-router": "1.170.45", + "@tanstack/react-start": "1.169.3", + "class-variance-authority": "0.7.1", + "cn": "^0.5.0", + "nitro": "3.0.260903-beta", + "radix-ui": "^1.8.1", + "react": "19.3.1", + "react-dom": "19.3.1" + }, + "devDependencies": { + "@tailwindcss/vite": "4.3.3", + "@testing-library/react": "16.3.3", + "@types/react": "19.3.0", + "@types/react-dom": "19.3.0", + "@vitejs/plugin-react": "6.1.2", + "jsdom": "30.1.3", + "tailwindcss": "4.3.3", + "typescript": "7.0.2", + "vite": "8.3.4", + "vitest": "5.0.5" + } +} diff --git a/apps/web/src/components/home-page.spec.tsx b/apps/web/src/components/home-page.spec.tsx new file mode 100644 index 0000000..52f0d0b --- /dev/null +++ b/apps/web/src/components/home-page.spec.tsx @@ -0,0 +1,22 @@ +import { render, screen } from '@testing-library/react'; +import { describe, expect, it } from 'vitest'; + +import { HomePage } from './home-page'; + +describe('HomePage', () => { + it('muestra el saludo «Hola Mundo»', () => { + render(); + + expect(screen.getByRole('heading', { name: 'Hola Mundo' })).toBeDefined(); + }); + + it('renderiza el botón de shadcn', () => { + render(); + + const button = screen.getByRole('button', { name: 'Empezar' }); + + // `data-slot` is the marker shadcn's own components emit, so this asserts the + // shadcn Button is in the tree rather than a bare + + + + ); +} diff --git a/apps/web/src/components/ui/button.tsx b/apps/web/src/components/ui/button.tsx new file mode 100644 index 0000000..3487b56 --- /dev/null +++ b/apps/web/src/components/ui/button.tsx @@ -0,0 +1,61 @@ +import * as React from 'react'; +import { cva, type VariantProps } from 'class-variance-authority'; +import { cn } from 'cn'; +import { Slot } from 'radix-ui'; + +const buttonVariants = cva( + "inline-flex shrink-0 items-center justify-center gap-2 rounded-md text-sm font-medium whitespace-nowrap transition-all outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", + { + variants: { + variant: { + default: 'bg-primary text-primary-foreground hover:bg-primary/90', + destructive: + 'bg-destructive text-white hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:bg-destructive/60 dark:focus-visible:ring-destructive/40', + outline: + 'border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:border-input dark:bg-input/30 dark:hover:bg-input/50', + secondary: 'bg-secondary text-secondary-foreground hover:bg-secondary/80', + ghost: 'hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50', + link: 'text-primary underline-offset-4 hover:underline', + }, + size: { + default: 'h-9 px-4 py-2 has-[>svg]:px-3', + xs: "h-6 gap-1 rounded-md px-2 text-xs has-[>svg]:px-1.5 [&_svg:not([class*='size-'])]:size-3", + sm: 'h-8 gap-1.5 rounded-md px-3 has-[>svg]:px-2.5', + lg: 'h-10 rounded-md px-6 has-[>svg]:px-4', + icon: 'size-9', + 'icon-xs': "size-6 rounded-md [&_svg:not([class*='size-'])]:size-3", + 'icon-sm': 'size-8', + 'icon-lg': 'size-10', + }, + }, + defaultVariants: { + variant: 'default', + size: 'default', + }, + }, +); + +function Button({ + className, + variant = 'default', + size = 'default', + asChild = false, + ...props +}: React.ComponentProps<'button'> & + VariantProps & { + asChild?: boolean; + }) { + const Comp = asChild ? Slot.Root : 'button'; + + return ( + + ); +} + +export { Button, buttonVariants }; diff --git a/apps/web/src/components/ui/card.tsx b/apps/web/src/components/ui/card.tsx new file mode 100644 index 0000000..75c0d69 --- /dev/null +++ b/apps/web/src/components/ui/card.tsx @@ -0,0 +1,85 @@ +import * as React from 'react'; +import { cn } from 'cn'; + +function Card({ className, ...props }: React.ComponentProps<'div'>) { + return ( +
+ ); +} + +function CardHeader({ className, ...props }: React.ComponentProps<'div'>) { + return ( +
+ ); +} + +function CardTitle({ className, ...props }: React.ComponentProps<'div'>) { + return ( +
+ ); +} + +function CardDescription({ className, ...props }: React.ComponentProps<'div'>) { + return ( +
+ ); +} + +function CardAction({ className, ...props }: React.ComponentProps<'div'>) { + return ( +
+ ); +} + +function CardContent({ className, ...props }: React.ComponentProps<'div'>) { + return
; +} + +function CardFooter({ className, ...props }: React.ComponentProps<'div'>) { + return ( +
+ ); +} + +export { + Card, + CardHeader, + CardFooter, + CardTitle, + CardAction, + CardDescription, + CardContent, +}; diff --git a/apps/web/src/routeTree.gen.ts b/apps/web/src/routeTree.gen.ts new file mode 100644 index 0000000..dceedff --- /dev/null +++ b/apps/web/src/routeTree.gen.ts @@ -0,0 +1,68 @@ +/* eslint-disable */ + +// @ts-nocheck + +// noinspection JSUnusedGlobalSymbols + +// This file was automatically generated by TanStack Router. +// You should NOT make any changes in this file as it will be overwritten. +// Additionally, you should also exclude this file from your linter and/or formatter to prevent it from being checked or modified. + +import { Route as rootRouteImport } from './routes/__root' +import { Route as IndexRouteImport } from './routes/index' + +const IndexRoute = IndexRouteImport.update({ + id: '/', + path: '/', + getParentRoute: () => rootRouteImport, +} as any) + +export interface FileRoutesByFullPath { + '/': typeof IndexRoute +} +export interface FileRoutesByTo { + '/': typeof IndexRoute +} +export interface FileRoutesById { + __root__: typeof rootRouteImport + '/': typeof IndexRoute +} +export interface FileRouteTypes { + fileRoutesByFullPath: FileRoutesByFullPath + fullPaths: '/' + fileRoutesByTo: FileRoutesByTo + to: '/' + id: '__root__' | '/' + fileRoutesById: FileRoutesById +} +export interface RootRouteChildren { + IndexRoute: typeof IndexRoute +} + +declare module '@tanstack/react-router' { + interface FileRoutesByPath { + '/': { + id: '/' + path: '/' + fullPath: '/' + preLoaderRoute: typeof IndexRouteImport + parentRoute: typeof rootRouteImport + } + } +} + +const rootRouteChildren: RootRouteChildren = { + IndexRoute: IndexRoute, +} +export const routeTree = rootRouteImport + ._addFileChildren(rootRouteChildren) + ._addFileTypes() + +import type { getRouter } from './router.tsx' +import type { createStart } from '@tanstack/react-start' +declare module '@tanstack/react-start' { + interface Register { + ssr: true + router: Awaited> + } +} diff --git a/apps/web/src/router.tsx b/apps/web/src/router.tsx new file mode 100644 index 0000000..db0db5f --- /dev/null +++ b/apps/web/src/router.tsx @@ -0,0 +1,17 @@ +import { createRouter as createTanStackRouter } from '@tanstack/react-router'; + +import { routeTree } from './routeTree.gen'; + +export function getRouter() { + return createTanStackRouter({ + routeTree, + scrollRestoration: true, + defaultPreload: 'intent', + }); +} + +declare module '@tanstack/react-router' { + interface Register { + router: ReturnType; + } +} diff --git a/apps/web/src/routes/__root.tsx b/apps/web/src/routes/__root.tsx new file mode 100644 index 0000000..fda5605 --- /dev/null +++ b/apps/web/src/routes/__root.tsx @@ -0,0 +1,30 @@ +import { HeadContent, Scripts, createRootRoute } from '@tanstack/react-router'; +import type { ReactNode } from 'react'; + +import appCss from '../styles.css?url'; + +export const Route = createRootRoute({ + head: () => ({ + meta: [ + { charSet: 'utf-8' }, + { name: 'viewport', content: 'width=device-width, initial-scale=1' }, + { title: 'Memora' }, + ], + links: [{ rel: 'stylesheet', href: appCss }], + }), + shellComponent: RootDocument, +}); + +function RootDocument({ children }: { children: ReactNode }) { + return ( + + + + + + {children} + + + + ); +} diff --git a/apps/web/src/routes/index.tsx b/apps/web/src/routes/index.tsx new file mode 100644 index 0000000..f7acbca --- /dev/null +++ b/apps/web/src/routes/index.tsx @@ -0,0 +1,5 @@ +import { createFileRoute } from '@tanstack/react-router'; + +import { HomePage } from '#/components/home-page'; + +export const Route = createFileRoute('/')({ component: HomePage }); diff --git a/apps/web/src/styles.css b/apps/web/src/styles.css new file mode 100644 index 0000000..ab09833 --- /dev/null +++ b/apps/web/src/styles.css @@ -0,0 +1,124 @@ +@import 'tailwindcss'; + +/* shadcn/ui default tokens — style `new-york`, base colour `neutral`, taken + verbatim from the shadcn registry. No custom palette and no theme switcher in + this delivery (R16): the `.dark` values are shadcn's defaults and nothing in the + app toggles them. */ + +@custom-variant dark (&:is(.dark *)); + +:root { + --background: oklch(1 0 0); + --foreground: oklch(0.145 0 0); + --card: oklch(1 0 0); + --card-foreground: oklch(0.145 0 0); + --popover: oklch(1 0 0); + --popover-foreground: oklch(0.145 0 0); + --primary: oklch(0.205 0 0); + --primary-foreground: oklch(0.985 0 0); + --secondary: oklch(0.97 0 0); + --secondary-foreground: oklch(0.205 0 0); + --muted: oklch(0.97 0 0); + --muted-foreground: oklch(0.556 0 0); + --accent: oklch(0.97 0 0); + --accent-foreground: oklch(0.205 0 0); + --destructive: oklch(0.577 0.245 27.325); + --border: oklch(0.922 0 0); + --input: oklch(0.922 0 0); + --ring: oklch(0.708 0 0); + --chart-1: oklch(0.87 0 0); + --chart-2: oklch(0.556 0 0); + --chart-3: oklch(0.439 0 0); + --chart-4: oklch(0.371 0 0); + --chart-5: oklch(0.269 0 0); + --radius: 0.625rem; + --sidebar: oklch(0.985 0 0); + --sidebar-foreground: oklch(0.145 0 0); + --sidebar-primary: oklch(0.205 0 0); + --sidebar-primary-foreground: oklch(0.985 0 0); + --sidebar-accent: oklch(0.97 0 0); + --sidebar-accent-foreground: oklch(0.205 0 0); + --sidebar-border: oklch(0.922 0 0); + --sidebar-ring: oklch(0.708 0 0); +} + +.dark { + --background: oklch(0.145 0 0); + --foreground: oklch(0.985 0 0); + --card: oklch(0.205 0 0); + --card-foreground: oklch(0.985 0 0); + --popover: oklch(0.205 0 0); + --popover-foreground: oklch(0.985 0 0); + --primary: oklch(0.922 0 0); + --primary-foreground: oklch(0.205 0 0); + --secondary: oklch(0.269 0 0); + --secondary-foreground: oklch(0.985 0 0); + --muted: oklch(0.269 0 0); + --muted-foreground: oklch(0.708 0 0); + --accent: oklch(0.269 0 0); + --accent-foreground: oklch(0.985 0 0); + --destructive: oklch(0.704 0.191 22.216); + --border: oklch(1 0 0 / 10%); + --input: oklch(1 0 0 / 15%); + --ring: oklch(0.556 0 0); + --chart-1: oklch(0.87 0 0); + --chart-2: oklch(0.556 0 0); + --chart-3: oklch(0.439 0 0); + --chart-4: oklch(0.371 0 0); + --chart-5: oklch(0.269 0 0); + --sidebar: oklch(0.205 0 0); + --sidebar-foreground: oklch(0.985 0 0); + --sidebar-primary: oklch(0.488 0.243 264.376); + --sidebar-primary-foreground: oklch(0.985 0 0); + --sidebar-accent: oklch(0.269 0 0); + --sidebar-accent-foreground: oklch(0.985 0 0); + --sidebar-border: oklch(1 0 0 / 10%); + --sidebar-ring: oklch(0.556 0 0); +} + +@theme inline { + --color-background: var(--background); + --color-foreground: var(--foreground); + --color-card: var(--card); + --color-card-foreground: var(--card-foreground); + --color-popover: var(--popover); + --color-popover-foreground: var(--popover-foreground); + --color-primary: var(--primary); + --color-primary-foreground: var(--primary-foreground); + --color-secondary: var(--secondary); + --color-secondary-foreground: var(--secondary-foreground); + --color-muted: var(--muted); + --color-muted-foreground: var(--muted-foreground); + --color-accent: var(--accent); + --color-accent-foreground: var(--accent-foreground); + --color-destructive: var(--destructive); + --color-border: var(--border); + --color-input: var(--input); + --color-ring: var(--ring); + --color-chart-1: var(--chart-1); + --color-chart-2: var(--chart-2); + --color-chart-3: var(--chart-3); + --color-chart-4: var(--chart-4); + --color-chart-5: var(--chart-5); + --color-sidebar: var(--sidebar); + --color-sidebar-foreground: var(--sidebar-foreground); + --color-sidebar-primary: var(--sidebar-primary); + --color-sidebar-primary-foreground: var(--sidebar-primary-foreground); + --color-sidebar-accent: var(--sidebar-accent); + --color-sidebar-accent-foreground: var(--sidebar-accent-foreground); + --color-sidebar-border: var(--sidebar-border); + --color-sidebar-ring: var(--sidebar-ring); + --radius-sm: calc(var(--radius) - 4px); + --radius-md: calc(var(--radius) - 2px); + --radius-lg: var(--radius); + --radius-xl: calc(var(--radius) + 4px); +} + +@layer base { + * { + @apply border-border outline-ring/50; + } + body { + @apply bg-background text-foreground; + } +} diff --git a/apps/web/tsconfig.json b/apps/web/tsconfig.json new file mode 100644 index 0000000..9f61037 --- /dev/null +++ b/apps/web/tsconfig.json @@ -0,0 +1,15 @@ +{ + "extends": "../../tsconfig.base.json", + "include": ["**/*.ts", "**/*.tsx"], + "exclude": ["dist", ".output", ".nitro", ".tanstack"], + "compilerOptions": { + "jsx": "react-jsx", + "lib": ["ES2023", "DOM", "DOM.Iterable"], + "types": ["vite/client"], + "allowImportingTsExtensions": true, + "noUncheckedSideEffectImports": true, + "paths": { + "#/*": ["./src/*"] + } + } +} diff --git a/apps/web/tsr.config.json b/apps/web/tsr.config.json new file mode 100644 index 0000000..8b6b6ed --- /dev/null +++ b/apps/web/tsr.config.json @@ -0,0 +1,3 @@ +{ + "target": "react" +} diff --git a/apps/web/vite.config.ts b/apps/web/vite.config.ts new file mode 100644 index 0000000..45c6436 --- /dev/null +++ b/apps/web/vite.config.ts @@ -0,0 +1,10 @@ +import { tanstackStart } from '@tanstack/react-start/plugin/vite'; +import tailwindcss from '@tailwindcss/vite'; +import viteReact from '@vitejs/plugin-react'; +import { nitro } from 'nitro/vite'; +import { defineConfig } from 'vite'; + +export default defineConfig({ + resolve: { tsconfigPaths: true }, + plugins: [nitro(), tailwindcss(), tanstackStart(), viteReact()], +}); diff --git a/apps/web/vitest.config.ts b/apps/web/vitest.config.ts new file mode 100644 index 0000000..f39fe0e --- /dev/null +++ b/apps/web/vitest.config.ts @@ -0,0 +1,14 @@ +import viteReact from '@vitejs/plugin-react'; +import { defineConfig } from 'vitest/config'; + +// The smoke test renders the page component directly, so it needs only the React +// transform — not the Start/Nitro plugins. That keeps the suite hermetic (R56): +// no SSR pipeline, no route generation, no network. +export default defineConfig({ + plugins: [viteReact()], + test: { + environment: 'jsdom', + include: ['src/**/*.spec.{ts,tsx}'], + setupFiles: ['./vitest.setup.ts'], + }, +}); diff --git a/apps/web/vitest.setup.ts b/apps/web/vitest.setup.ts new file mode 100644 index 0000000..71cafd8 --- /dev/null +++ b/apps/web/vitest.setup.ts @@ -0,0 +1,7 @@ +import { cleanup } from '@testing-library/react'; +import { afterEach } from 'vitest'; + +// Testing Library's automatic cleanup only registers itself when Vitest runs with +// globals enabled. We keep globals off (explicit imports in every spec), so the +// unmount is wired here instead — otherwise renders leak between tests. +afterEach(cleanup); diff --git a/console-runner/package.json b/console-runner/package.json new file mode 100644 index 0000000..d563907 --- /dev/null +++ b/console-runner/package.json @@ -0,0 +1,19 @@ +{ + "name": "console-runner", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "test": "vitest run", + "typecheck": "tsc --noEmit" + }, + "dependencies": { + "@inquirer/prompts": "8.7.3", + "@memora/db": "workspace:*" + }, + "devDependencies": { + "@types/node": "24.19.2", + "typescript": "7.0.2", + "vitest": "5.0.5" + } +} diff --git a/console-runner/src/actions/check-connection.spec.ts b/console-runner/src/actions/check-connection.spec.ts new file mode 100644 index 0000000..9721c9d --- /dev/null +++ b/console-runner/src/actions/check-connection.spec.ts @@ -0,0 +1,38 @@ +import { describe, expect, it, vi } from 'vitest'; + +import { checkConnection } from './check-connection'; + +describe('checkConnection', () => { + it('informa del host y la base de datos alcanzados cuando el ping responde', async () => { + const client = { + options: { hosts: ['localhost:27017'] }, + db: () => ({ + databaseName: 'memora', + command: vi.fn().mockResolvedValue({ ok: 1 }), + }), + }; + + const result = await checkConnection(client); + + expect(result).toEqual({ ok: true, host: 'localhost:27017', database: 'memora' }); + }); + + it('no lanza cuando el servidor no responde: devuelve el mensaje del driver y la pista de pnpm db:up', async () => { + const client = { + options: { hosts: ['localhost:27017'] }, + db: () => ({ + databaseName: 'memora', + command: vi + .fn() + .mockRejectedValue(new Error('connect ECONNREFUSED 127.0.0.1:27017')), + }), + }; + + const result = await checkConnection(client); + + expect(result.ok).toBe(false); + if (result.ok) throw new Error('se esperaba un fallo'); + expect(result.error).toContain('connect ECONNREFUSED 127.0.0.1:27017'); + expect(result.error).toContain('pnpm db:up'); + }); +}); diff --git a/console-runner/src/actions/check-connection.ts b/console-runner/src/actions/check-connection.ts new file mode 100644 index 0000000..fe69764 --- /dev/null +++ b/console-runner/src/actions/check-connection.ts @@ -0,0 +1,26 @@ +import { pingDatabase, type PingableClient } from '@memora/db'; + +/** Outcome of a connectivity check. Never an exception — the menu must survive. */ +export type CheckResult = + { ok: true; host: string; database: string } | { ok: false; error: string }; + +/** + * Pings Mongo and reports what it reached (R40). Prompt-free and client-injected + * (R45), so it is tested against a double rather than a live server. + */ +export async function checkConnection(client: PingableClient): Promise { + try { + const { host, database } = await pingDatabase(client); + + return { ok: true, host, database }; + } catch (error) { + // The driver's own message is kept verbatim — it says what actually went wrong + // — and the hint names the one command that fixes the common case (R41). + const message = error instanceof Error ? error.message : String(error); + + return { + ok: false, + error: `${message}\n¿Está Mongo levantado? Prueba con \`pnpm db:up\`.`, + }; + } +} diff --git a/console-runner/src/actions/clean-database.spec.ts b/console-runner/src/actions/clean-database.spec.ts new file mode 100644 index 0000000..910acb9 --- /dev/null +++ b/console-runner/src/actions/clean-database.spec.ts @@ -0,0 +1,49 @@ +import { describe, expect, it, vi } from 'vitest'; + +import { cleanDatabase } from './clean-database'; + +/** + * A double that records every call, including `db()` itself — the declined case has + * to prove that *nothing* on the client was touched, not merely that the drop was + * skipped. + */ +function createClientDouble(dropImpl = vi.fn().mockResolvedValue(true)) { + const db = vi.fn(() => ({ databaseName: 'memora', dropDatabase: dropImpl })); + + return { client: { db }, db, dropDatabase: dropImpl }; +} + +describe('cleanDatabase', () => { + it('con la confirmación aceptada, borra la base exactamente una vez y lo informa', async () => { + const { client, dropDatabase } = createClientDouble(); + + const result = await cleanDatabase(client, true); + + expect(dropDatabase).toHaveBeenCalledTimes(1); + expect(result).toEqual({ status: 'dropped', database: 'memora' }); + }); + + it('con la confirmación denegada, no toca el cliente y devuelve cancelado', async () => { + const { client, db, dropDatabase } = createClientDouble(); + + const result = await cleanDatabase(client, false); + + expect(result).toEqual({ status: 'cancelled' }); + expect(dropDatabase).not.toHaveBeenCalled(); + // Not even `db()`: declining must perform no write "of any kind" (R50). + expect(db).not.toHaveBeenCalled(); + }); + + it('si el borrado falla, lo informa en vez de lanzar, para que el menú siga usable', async () => { + const { client } = createClientDouble( + vi.fn().mockRejectedValue(new Error('not authorized to execute dropDatabase')), + ); + + const result = await cleanDatabase(client, true); + + expect(result).toEqual({ + status: 'failed', + error: 'not authorized to execute dropDatabase', + }); + }); +}); diff --git a/console-runner/src/actions/clean-database.ts b/console-runner/src/actions/clean-database.ts new file mode 100644 index 0000000..0e8c7c7 --- /dev/null +++ b/console-runner/src/actions/clean-database.ts @@ -0,0 +1,34 @@ +import { dropDatabase, type DroppableClient } from '@memora/db'; + +/** Outcome of the destructive operation. */ +export type CleanResult = + | { status: 'dropped'; database: string } + | { status: 'cancelled' } + | { status: 'failed'; error: string }; + +/** + * Drops the database — the one destructive operation in this delivery. + * + * `confirmed` is passed in rather than asked for here: the prompt lives in the menu + * layer (R45), which keeps this function testable and makes the guard explicit at + * the call site. + */ +export async function cleanDatabase( + client: DroppableClient, + confirmed: boolean, +): Promise { + // Guard first, before anything touches the client (R50). + if (!confirmed) return { status: 'cancelled' }; + + try { + const { database } = await dropDatabase(client); + + return { status: 'dropped', database }; + } catch (error) { + // Reported, not thrown: a failed drop must leave the menu usable (R51). + return { + status: 'failed', + error: error instanceof Error ? error.message : String(error), + }; + } +} diff --git a/console-runner/src/actions/seed-data.spec.ts b/console-runner/src/actions/seed-data.spec.ts new file mode 100644 index 0000000..1338795 --- /dev/null +++ b/console-runner/src/actions/seed-data.spec.ts @@ -0,0 +1,20 @@ +import { describe, expect, it } from 'vitest'; + +import { loadSeedData } from './seed-data'; + +describe('loadSeedData', () => { + it('devuelve la marca de pendiente con un mensaje que dice TODO', () => { + const result = loadSeedData(); + + expect(result.status).toBe('pending'); + expect(result.message).toContain('TODO'); + }); + + // R43 demands "no database access at all". The structural proof is that the + // operation takes no client: there is nothing it could call. This pins that + // signature, so adding a client parameter (and with it the chance of real I/O) + // breaks the suite instead of passing silently. + it('no recibe cliente alguno, así que no puede tocar la base de datos', () => { + expect(loadSeedData).toHaveLength(0); + }); +}); diff --git a/console-runner/src/actions/seed-data.ts b/console-runner/src/actions/seed-data.ts new file mode 100644 index 0000000..16b8c1f --- /dev/null +++ b/console-runner/src/actions/seed-data.ts @@ -0,0 +1,20 @@ +/** Outcome of the seed operation. Only ever pending in this delivery (R43). */ +export interface SeedResult { + status: 'pending'; + message: string; +} + +/** + * The reserved slot for real seed data. It takes **no client on purpose**: the + * domain model does not exist yet, so there is nothing honest to write, and an + * operation that cannot reach Mongo cannot pretend it did (R43). The menu entry is + * deliberately visible — a signposted gap communicates intent, where a missing + * entry would look like an oversight. + */ +export function loadSeedData(): SeedResult { + return { + status: 'pending', + message: + 'TODO: los datos de prueba llegarán con el modelo de dominio. No se ha escrito nada en la base de datos.', + }; +} diff --git a/console-runner/src/main.ts b/console-runner/src/main.ts new file mode 100644 index 0000000..42bbb2c --- /dev/null +++ b/console-runner/src/main.ts @@ -0,0 +1,146 @@ +import { confirm, select } from '@inquirer/prompts'; +import { createMongoClient, resolveMongoUri } from '@memora/db'; + +import { checkConnection } from './actions/check-connection'; +import { cleanDatabase } from './actions/clean-database'; +import { loadSeedData } from './actions/seed-data'; + +/** + * The runner's entry point and the **only** module that talks to + * `@inquirer/prompts` (R45). Every operation lives in `src/actions/` as a plain + * function that receives its client, so the operations are testable against a + * double and the prompt layer stays a thin adapter. + */ + +type RunnerClient = ReturnType; + +const CHECK_CONNECTION = 'check-connection'; +const CLEAN_DATABASE = 'clean-database'; +const LOAD_SEED_DATA = 'load-seed-data'; +const EXIT = 'exit'; + +/** + * `@inquirer/prompts` rejects with an `ExitPromptError` when the user presses + * Ctrl+C. The package does not export the class, so it is matched by name — the + * documented approach, and cheaper than depending on `@inquirer/core` just for a + * type (R44). + */ +function isExitPromptError(error: unknown): boolean { + return error instanceof Error && error.name === 'ExitPromptError'; +} + +async function closeClient(client: RunnerClient | undefined): Promise { + if (client === undefined) return; + + try { + await client.close(); + } catch { + // Closing is best-effort during shutdown: a failure here must not mask the + // reason we are shutting down, and there is nothing left to recover. + } +} + +async function run(): Promise { + let client: RunnerClient | undefined; + + /** + * Connects lazily and reuses the client. `resolveMongoUri` throws when + * `MONGODB_URI` is missing; callers catch it so the menu survives (R42). + */ + const connect = (): RunnerClient => { + client ??= createMongoClient(resolveMongoUri(process.env)); + return client; + }; + + /** + * Resolves the client for an operation, or reports why it cannot and hands back + * `undefined` so the caller returns to the menu. This is the configuration-error + * path (R42): the explicit `MONGODB_URI` message is printed and **no connection + * is attempted**. + */ + const connectOrReport = (): RunnerClient | undefined => { + try { + return connect(); + } catch (error) { + console.error(`✖ ${error instanceof Error ? error.message : String(error)}\n`); + return undefined; + } + }; + + try { + for (;;) { + const choice = await select({ + message: '¿Qué quieres hacer?', + choices: [ + { name: 'Comprobar conexión con Mongo', value: CHECK_CONNECTION }, + { name: 'Limpiar base de datos', value: CLEAN_DATABASE }, + { name: 'Cargar datos de prueba', value: LOAD_SEED_DATA }, + { name: 'Salir', value: EXIT }, + ], + }); + + if (choice === EXIT) break; + + if (choice === LOAD_SEED_DATA) { + console.log(`${loadSeedData().message}\n`); + continue; + } + + if (choice === CHECK_CONNECTION) { + const target = connectOrReport(); + if (target === undefined) continue; + + const result = await checkConnection(target); + + if (result.ok) { + console.log( + `✔ Conexión correcta con ${result.host}, base de datos «${result.database}».\n`, + ); + } else { + console.error(`✖ No se pudo conectar.\n${result.error}\n`); + } + + continue; + } + + if (choice === CLEAN_DATABASE) { + const target = connectOrReport(); + if (target === undefined) continue; + + // Naming the database in the prompt is the point of the confirmation + // (R47); reading its name is local and touches no server. + const database = target.db().databaseName; + + const confirmed = await confirm({ + message: `Vas a BORRAR todos los datos de la base «${database}». ¿Seguro?`, + default: false, // Enter cancels (R48). + }); + + const result = await cleanDatabase(target, confirmed); + + if (result.status === 'dropped') { + console.log(`✔ Base de datos «${result.database}» borrada.\n`); + } else if (result.status === 'cancelled') { + console.log('Operación cancelada: no se ha borrado nada.\n'); + } else { + console.error(`✖ No se pudo borrar la base de datos.\n${result.error}\n`); + } + + continue; + } + } + } catch (error) { + if (isExitPromptError(error)) { + // Ctrl+C: leave quietly. No stack trace, and the client is still closed. + await closeClient(client); + return; + } + + await closeClient(client); + throw error; + } + + await closeClient(client); +} + +await run(); diff --git a/console-runner/tsconfig.json b/console-runner/tsconfig.json new file mode 100644 index 0000000..436bdc0 --- /dev/null +++ b/console-runner/tsconfig.json @@ -0,0 +1,7 @@ +{ + "extends": "../tsconfig.base.json", + "include": ["src/**/*.ts"], + "compilerOptions": { + "types": ["node"] + } +} diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..8cde745 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,33 @@ +# LOCAL DEVELOPMENT ONLY — no credentials. +# +# This MongoDB listens on localhost:27017 with authentication disabled, on purpose: +# the point is that a fresh clone can run `pnpm db:up` with zero friction. Anyone who +# can reach this port has full read/write access to every database in it. +# +# Never deploy this file, and never copy it to any environment that is reachable from +# outside this machine. A remote environment needs its own compose/manifest with +# credentials, TLS and a non-published port. +# +# The application database is `memora`; the canonical local URI is +# mongodb://localhost:27017/memora (see .env.example). Mongo creates the database on +# first write, so nothing here has to declare it. + +services: + mongo: + image: mongo:8 + container_name: memora-mongo + ports: + - '27017:27017' + volumes: + # Named volume, so the data survives `pnpm db:down` (only `pnpm db:reset` + # removes it). + - memora-mongo-data:/data/db + healthcheck: + test: ['CMD', 'mongosh', '--quiet', '--eval', "db.adminCommand('ping')"] + interval: 5s + timeout: 5s + retries: 12 + start_period: 10s + +volumes: + memora-mongo-data: diff --git a/harness.config.yml b/harness.config.yml index 080acd2..a220b5d 100644 --- a/harness.config.yml +++ b/harness.config.yml @@ -78,10 +78,13 @@ rollback: # reviews against a floor of the real run only (honest, but thin). The agent may # propose this list from your manifest at the approval gate — confirmed by a human # and added by hand (this block is the shape); no tool writes it for you. -# gates: -# - lint -# - test -# - build +# This project has no linter by explicit decision (Prettier only), so `typecheck` +# carries the weight a linter would. All four are enforced by .github/workflows/ci.yml. +gates: + - typecheck + - 'format:check' + - test + - build # Design tokens (the `design-tokens` verbs, and the token lines of `doctor` / `status`). # `scan_extensions`: the anti-hardcode scan inspects a built-in set of UI/style diff --git a/package-lock.json b/package-lock.json deleted file mode 100644 index 2c8ed06..0000000 --- a/package-lock.json +++ /dev/null @@ -1,159 +0,0 @@ -{ - "name": "demo-memora", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "devDependencies": { - "@lemoncode/lemony": "^0.10.0" - } - }, - "node_modules/@lemoncode/lemony": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/@lemoncode/lemony/-/lemony-0.10.0.tgz", - "integrity": "sha512-y00lRAyTH6Fe9uyH1/eFJ7Livtyl3udmSriCGWbYGERIGCoZHd7jLqKIWN/k97byoDyJ+O/RP6M0OKJ64Qy8uQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "markdown-it": "15.0.2", - "yaml": "2.9.1", - "zod": "4.6.5" - }, - "bin": { - "lemony": "dist/cli.mjs" - }, - "engines": { - "node": ">=24", - "pnpm": ">=11.5.1" - } - }, - "node_modules/argparse": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-3.0.3.tgz", - "integrity": "sha512-Sn98ftV3KfsO8xfLPHG6oT8y+b0yvbrLgZjgPDXsharNY15tTAjqIsIju4S32nl6/iEUNNE4v+yL2Zhm8ooP3w==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/puzrin" - }, - { - "type": "github", - "url": "https://github.com/sponsors/nodeca" - } - ], - "license": "PSF-2.0" - }, - "node_modules/entities": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-8.1.0.tgz", - "integrity": "sha512-kxL7msIffSuh9aaFAMD7rxAIuTRMAHMeBtgHW2yUdWw732ZNh4MehkF2gdjvtdmikkaIP9bFDDJOPlsvm7avrA==", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=20.19.0" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "node_modules/linkify-it": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-6.1.0.tgz", - "integrity": "sha512-wJ/TwpSDTLepCrQoYWYIExIKg5Zchex2Nn5yk2mFnB+6PtdkHtyLx742md9csRjjOnGkKIS/RrbY7l8D6gT9Vw==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/puzrin" - }, - { - "type": "github", - "url": "https://github.com/sponsors/markdown-it" - } - ], - "license": "MIT", - "dependencies": { - "uc.micro": "^3.0.0" - } - }, - "node_modules/markdown-it": { - "version": "15.0.2", - "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-15.0.2.tgz", - "integrity": "sha512-q4IGxMv56jCqT4OCRCADBoDP3LO4MhmTXjFbphHPXs4g3j9Xg5RDnxqN8IF/3vIWEU+VCnUq+7JUg/cfy2E6Qw==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/puzrin" - }, - { - "type": "github", - "url": "https://github.com/sponsors/markdown-it" - } - ], - "license": "MIT", - "dependencies": { - "argparse": "^3.0.0", - "entities": "^8.0.0", - "linkify-it": "^6.0.0", - "mdurl": "^2.1.0", - "punycode.js": "^2.3.1", - "uc.micro": "^3.0.0" - }, - "bin": { - "markdown-it": "bin/markdown-it.mjs" - } - }, - "node_modules/mdurl": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.1.0.tgz", - "integrity": "sha512-1+HBaOx0zi/dQWht8rNv9MYf9qqpqL/kxI0hXImU6Y547zM6Sni8BQibt7ifgMcYtQg41ao3Ivd6cnSM86inpg==", - "dev": true, - "license": "MIT" - }, - "node_modules/punycode.js": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz", - "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/uc.micro": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-3.0.0.tgz", - "integrity": "sha512-U3PppEkleoTnIfi8BozMx3yju3qc/L6SwqWo2Sw+54PX+PX0q9I+r1Um5HCmqD7n9VDX5/v3vQH/AjA6deDdtw==", - "dev": true, - "license": "MIT" - }, - "node_modules/yaml": { - "version": "2.9.1", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.9.1.tgz", - "integrity": "sha512-3NxN8+78OdzbT7C/WjGsyfPAtJaN3FNDsWxv7Y7mcDsT/oOmgW8BpyQQFFBnvZE3j9Y2Sdz1ULFLezL7Eb2yFw==", - "dev": true, - "license": "ISC", - "bin": { - "yaml": "bin.mjs" - }, - "engines": { - "node": ">= 14.6" - }, - "funding": { - "url": "https://github.com/sponsors/eemeli" - } - }, - "node_modules/zod": { - "version": "4.6.5", - "resolved": "https://registry.npmjs.org/zod/-/zod-4.6.5.tgz", - "integrity": "sha512-v5l/aFXZQeai4awLbOpSoHecE9UiMrnfx75tEXLjNonXVARxQ5mOeipTjROUchszUNCqnE+hqAMujRsRHsut2Q==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/colinhacks" - } - } - } -} diff --git a/package.json b/package.json index 8cf0b61..c8dc792 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,27 @@ { + "name": "memora", + "private": true, + "packageManager": "pnpm@10.19.0", + "engines": { + "node": ">=24.16.0 <25" + }, + "scripts": { + "dev": "turbo run dev", + "build": "turbo run build", + "test": "turbo run test", + "typecheck": "turbo run typecheck", + "format": "prettier --write .", + "format:check": "prettier --check .", + "db:up": "docker compose up -d --wait", + "db:down": "docker compose down", + "db:reset": "docker compose down -v && docker compose up -d --wait", + "runner": "tsx --env-file-if-exists=.env console-runner/src/main.ts" + }, "devDependencies": { - "@lemoncode/lemony": "^0.10.0" + "@lemoncode/lemony": "^0.10.0", + "prettier": "3.9.10", + "tsx": "4.23.15", + "turbo": "2.11.9", + "typescript": "7.0.2" } } diff --git a/packages/db/package.json b/packages/db/package.json new file mode 100644 index 0000000..a0833e1 --- /dev/null +++ b/packages/db/package.json @@ -0,0 +1,25 @@ +{ + "name": "@memora/db", + "version": "0.0.0", + "private": true, + "type": "module", + "types": "./src/index.ts", + "exports": { + ".": { + "types": "./src/index.ts", + "default": "./src/index.ts" + } + }, + "scripts": { + "test": "vitest run", + "typecheck": "tsc --noEmit" + }, + "dependencies": { + "mongodb": "7.7.0" + }, + "devDependencies": { + "@types/node": "24.19.2", + "typescript": "7.0.2", + "vitest": "5.0.5" + } +} diff --git a/packages/db/src/client.spec.ts b/packages/db/src/client.spec.ts new file mode 100644 index 0000000..cfee120 --- /dev/null +++ b/packages/db/src/client.spec.ts @@ -0,0 +1,75 @@ +import { describe, expect, it, vi } from 'vitest'; + +import { + createMongoClient, + dropDatabase, + pingDatabase, + type MongoClientLike, +} from './client'; + +describe('createMongoClient', () => { + it('falla rápido: timeout de selección de servidor de 5 s como máximo', () => { + const client = createMongoClient('mongodb://localhost:27017/memora'); + + expect(client.options.serverSelectionTimeoutMS).toBeLessThanOrEqual(5000); + }); + + // The runner hands a real driver client to the primitives below, so this pins both + // halves of that contract: it compiles only if MongoClient satisfies + // MongoClientLike, and it shows db() resolving the database from the URI (R33). + // Constructing a client opens no socket, so this stays hermetic. + it('un MongoClient real cumple el contrato estructural y toma la base de la URI', () => { + const client: MongoClientLike = createMongoClient('mongodb://localhost:27017/memora'); + + expect(client.db().databaseName).toBe('memora'); + }); +}); + +describe('pingDatabase', () => { + it('hace ping sobre la base de datos codificada en la URI y devuelve host y base', async () => { + const command = vi.fn().mockResolvedValue({ ok: 1 }); + const client = { + options: { hosts: ['localhost:27017'] }, + db: () => ({ databaseName: 'memora', command }), + }; + + const result = await pingDatabase(client); + + expect(command).toHaveBeenCalledWith({ ping: 1 }); + expect(result).toEqual({ host: 'localhost:27017', database: 'memora' }); + }); + + it('no codifica ningún nombre de base de datos: usa el que diga el cliente', async () => { + const client = { + options: { hosts: ['db.internal:27018'] }, + db: () => ({ + databaseName: 'otra-base', + command: vi.fn().mockResolvedValue({ ok: 1 }), + }), + }; + + await expect(pingDatabase(client)).resolves.toEqual({ + host: 'db.internal:27018', + database: 'otra-base', + }); + }); +}); + +describe('dropDatabase', () => { + it('borra la base de datos codificada en la URI y devuelve su nombre', async () => { + const drop = vi.fn().mockResolvedValue(true); + const client = { + options: { hosts: ['localhost:27017'] }, + db: () => ({ + databaseName: 'memora', + command: vi.fn(), + dropDatabase: drop, + }), + }; + + const result = await dropDatabase(client); + + expect(drop).toHaveBeenCalledTimes(1); + expect(result).toEqual({ database: 'memora' }); + }); +}); diff --git a/packages/db/src/client.ts b/packages/db/src/client.ts new file mode 100644 index 0000000..1628ec7 --- /dev/null +++ b/packages/db/src/client.ts @@ -0,0 +1,83 @@ +import { MongoClient } from 'mongodb'; + +/** + * How long the driver may spend looking for a reachable server before giving up. + * The driver's own default is 30 s, which makes a maintenance tool look hung when + * Mongo simply is not running; 5 s is short enough to read as "it's down" (R32). + */ +export const SERVER_SELECTION_TIMEOUT_MS = 5_000; + +/** + * Builds a Mongo client for `uri`. The constructor does not connect — the first + * operation does — so this is safe to call before knowing the server is up. + */ +export function createMongoClient(uri: string): MongoClient { + return new MongoClient(uri, { + serverSelectionTimeoutMS: SERVER_SELECTION_TIMEOUT_MS, + }); +} + +/** + * The slices of a Mongo client the maintenance primitives actually need, split per + * capability so each primitive asks for the least it can. + * + * A real `MongoClient` satisfies them structurally, and so does a hand-written + * double — which is what keeps the suite hermetic (R56): no socket, no container. + * `db()` is always called with no argument, so the database is whichever one the + * connection string encodes (R33: no hard-coded database name). + */ +interface HostsCarrier { + readonly options: { readonly hosts: readonly { toString(): string }[] }; +} + +export interface PingableClient extends HostsCarrier { + db(): { + readonly databaseName: string; + command(document: Record): Promise; + }; +} + +export interface DroppableClient { + db(): { + readonly databaseName: string; + dropDatabase(): Promise; + }; +} + +/** Everything the primitives need together — what the runner holds. */ +export type MongoClientLike = PingableClient & DroppableClient; + +/** What the runner reports after a successful connectivity check (R40). */ +export interface PingResult { + host: string; + database: string; +} + +/** What the runner reports after dropping the database (R49). */ +export interface DropResult { + database: string; +} + +/** Issues a `ping` against the URI's database and reports what it reached. */ +export async function pingDatabase(client: PingableClient): Promise { + const db = client.db(); + + await db.command({ ping: 1 }); + + return { + host: client.options.hosts.map((host) => host.toString()).join(','), + database: db.databaseName, + }; +} + +/** + * Drops the database the connection string points at. Destructive and + * unconditional: the confirmation that guards it lives in the runner (R47, R49). + */ +export async function dropDatabase(client: DroppableClient): Promise { + const db = client.db(); + + await db.dropDatabase(); + + return { database: db.databaseName }; +} diff --git a/packages/db/src/config.spec.ts b/packages/db/src/config.spec.ts new file mode 100644 index 0000000..8d52323 --- /dev/null +++ b/packages/db/src/config.spec.ts @@ -0,0 +1,44 @@ +import { describe, expect, it } from 'vitest'; + +import { MONGODB_URI_VAR, resolveMongoUri } from './config'; + +describe('resolveMongoUri', () => { + it('devuelve la URI configurada', () => { + const uri = resolveMongoUri({ MONGODB_URI: 'mongodb://localhost:27017/memora' }); + + expect(uri).toBe('mongodb://localhost:27017/memora'); + }); + + it('falla explícitamente cuando la variable no está definida, nombrándola y apuntando a .env.example', () => { + expect(() => resolveMongoUri({})).toThrowError(/MONGODB_URI(.|\n)*\.env\.example/); + }); + + it('trata la cadena vacía como ausente', () => { + expect(() => resolveMongoUri({ MONGODB_URI: '' })).toThrowError(/MONGODB_URI/); + }); + + it('trata una variable con sólo espacios como ausente', () => { + expect(() => resolveMongoUri({ MONGODB_URI: ' ' })).toThrowError(/MONGODB_URI/); + }); + + it('recorta los espacios alrededor de la URI', () => { + const uri = resolveMongoUri({ MONGODB_URI: ' mongodb://localhost:27017/memora ' }); + + expect(uri).toBe('mongodb://localhost:27017/memora'); + }); + + // Regression guard for R30 (the resolver must not read global state) and for the + // "no default fallback" half of R31: it must fail even when the real process + // environment would have answered. + it('no lee process.env por su cuenta ni cae a una URI por defecto', () => { + const previous = process.env[MONGODB_URI_VAR]; + process.env[MONGODB_URI_VAR] = 'mongodb://localhost:27017/desde-process-env'; + + try { + expect(() => resolveMongoUri({})).toThrowError(/MONGODB_URI/); + } finally { + if (previous === undefined) delete process.env[MONGODB_URI_VAR]; + else process.env[MONGODB_URI_VAR] = previous; + } + }); +}); diff --git a/packages/db/src/config.ts b/packages/db/src/config.ts new file mode 100644 index 0000000..52b8bf9 --- /dev/null +++ b/packages/db/src/config.ts @@ -0,0 +1,26 @@ +/** The environment record `resolveMongoUri` reads from. */ +export type EnvRecord = Record; + +export const MONGODB_URI_VAR = 'MONGODB_URI'; + +/** The canonical local URI, quoted in the error so the fix is obvious (R28, R31). */ +const EXAMPLE_URI = 'mongodb://localhost:27017/memora'; + +/** + * Resolves the MongoDB connection string from the given environment record. + * + * Pure by design (R30): it never touches `process.env` itself and never reads a + * file, so callers decide what environment an operation runs against. + */ +export function resolveMongoUri(env: EnvRecord): string { + const value = env[MONGODB_URI_VAR]?.trim(); + + if (value === undefined || value === '') { + throw new Error( + `${MONGODB_URI_VAR} no está definida. Copia .env.example a .env en la raíz del ` + + `repositorio y ajusta el valor (por ejemplo ${EXAMPLE_URI}).`, + ); + } + + return value; +} diff --git a/packages/db/src/index.ts b/packages/db/src/index.ts new file mode 100644 index 0000000..36bad01 --- /dev/null +++ b/packages/db/src/index.ts @@ -0,0 +1,20 @@ +// @memora/db — the only place in the repository that resolves MONGODB_URI or +// constructs a Mongo client (R29). Consumed as TypeScript source: no build step and +// no emitted dist/ (R36). + +export { MONGODB_URI_VAR, resolveMongoUri } from './config'; +export type { EnvRecord } from './config'; + +export { + SERVER_SELECTION_TIMEOUT_MS, + createMongoClient, + dropDatabase, + pingDatabase, +} from './client'; +export type { + DropResult, + DroppableClient, + MongoClientLike, + PingableClient, + PingResult, +} from './client'; diff --git a/packages/db/tsconfig.json b/packages/db/tsconfig.json new file mode 100644 index 0000000..f4f2150 --- /dev/null +++ b/packages/db/tsconfig.json @@ -0,0 +1,7 @@ +{ + "extends": "../../tsconfig.base.json", + "include": ["src/**/*.ts"], + "compilerOptions": { + "types": ["node"] + } +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml new file mode 100644 index 0000000..0b464ad --- /dev/null +++ b/pnpm-lock.yaml @@ -0,0 +1,5235 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: + devDependencies: + '@lemoncode/lemony': + specifier: ^0.10.0 + version: 0.10.0 + prettier: + specifier: 3.9.10 + version: 3.9.10 + tsx: + specifier: 4.23.15 + version: 4.23.15 + turbo: + specifier: 2.11.9 + version: 2.11.9 + typescript: + specifier: 7.0.2 + version: 7.0.2 + + apps/web: + dependencies: + '@tanstack/react-router': + specifier: 1.170.45 + version: 1.170.45(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@tanstack/react-start': + specifier: 1.169.3 + version: 1.169.3(esbuild@0.28.2)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(rolldown@1.2.14)(vite@8.3.4(@types/node@24.19.2)(esbuild@0.28.2)(jiti@2.7.0)(tsx@4.23.15)(yaml@2.9.1)) + class-variance-authority: + specifier: 0.7.1 + version: 0.7.1 + cn: + specifier: ^0.5.0 + version: 0.5.0 + nitro: + specifier: 3.0.260903-beta + version: 3.0.260903-beta + radix-ui: + specifier: ^1.8.1 + version: 1.8.1(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + react: + specifier: 19.3.1 + version: 19.3.1 + react-dom: + specifier: 19.3.1 + version: 19.3.1(react@19.3.1) + devDependencies: + '@tailwindcss/vite': + specifier: 4.3.3 + version: 4.3.3(vite@8.3.4(@types/node@24.19.2)(esbuild@0.28.2)(jiti@2.7.0)(tsx@4.23.15)(yaml@2.9.1)) + '@testing-library/react': + specifier: 16.3.3 + version: 16.3.3(@testing-library/dom@10.4.2)(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@types/react': + specifier: 19.3.0 + version: 19.3.0 + '@types/react-dom': + specifier: 19.3.0 + version: 19.3.0(@types/react@19.3.0) + '@vitejs/plugin-react': + specifier: 6.1.2 + version: 6.1.2(vite@8.3.4(@types/node@24.19.2)(esbuild@0.28.2)(jiti@2.7.0)(tsx@4.23.15)(yaml@2.9.1)) + jsdom: + specifier: 30.1.3 + version: 30.1.3 + tailwindcss: + specifier: 4.3.3 + version: 4.3.3 + typescript: + specifier: 7.0.2 + version: 7.0.2 + vite: + specifier: 8.3.4 + version: 8.3.4(@types/node@24.19.2)(esbuild@0.28.2)(jiti@2.7.0)(tsx@4.23.15)(yaml@2.9.1) + vitest: + specifier: 5.0.5 + version: 5.0.5(@types/node@24.19.2)(jsdom@30.1.3)(vite@8.3.4(@types/node@24.19.2)(esbuild@0.28.2)(jiti@2.7.0)(tsx@4.23.15)(yaml@2.9.1)) + + console-runner: + dependencies: + '@inquirer/prompts': + specifier: 8.7.3 + version: 8.7.3(@types/node@24.19.2) + '@memora/db': + specifier: workspace:* + version: link:../packages/db + devDependencies: + '@types/node': + specifier: 24.19.2 + version: 24.19.2 + typescript: + specifier: 7.0.2 + version: 7.0.2 + vitest: + specifier: 5.0.5 + version: 5.0.5(@types/node@24.19.2)(jsdom@30.1.3)(vite@8.3.4(@types/node@24.19.2)(esbuild@0.28.2)(jiti@2.7.0)(tsx@4.23.15)(yaml@2.9.1)) + + packages/db: + dependencies: + mongodb: + specifier: 7.7.0 + version: 7.7.0 + devDependencies: + '@types/node': + specifier: 24.19.2 + version: 24.19.2 + typescript: + specifier: 7.0.2 + version: 7.0.2 + vitest: + specifier: 5.0.5 + version: 5.0.5(@types/node@24.19.2)(jsdom@30.1.3)(vite@8.3.4(@types/node@24.19.2)(esbuild@0.28.2)(jiti@2.7.0)(tsx@4.23.15)(yaml@2.9.1)) + +packages: + + '@asamuzakjp/css-color@7.1.7': + resolution: {integrity: sha512-Q7ioeear07HwixdIitIn9KS1LZi97CEDFCSjPNm9v+y8KNbsu9q4Lrd4zUQW4faED+E7qxvfeVnbNRW46wFKuw==} + engines: {node: ^22.22.2 || ^24.15.0 || >=26.0.0} + + '@asamuzakjp/dom-selector@10.0.4': + resolution: {integrity: sha512-A6f1nKy99I6tyoK82U6kBHvQQZmdHmTmPzJYPY/0eaOW0r8/qPmEOwjGHs+hL/vCgOwQTupu4LT1XtXNUuDruA==} + engines: {node: ^22.22.2 || ^24.15.0 || >=26.0.0} + + '@babel/code-frame@7.29.7': + resolution: {integrity: sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==} + engines: {node: '>=6.9.0'} + + '@babel/compat-data@7.29.7': + resolution: {integrity: sha512-locTkQyKvwIEgBzVrn8693ebc97F2U8ZHjbXwDXJ5Fn2TCpNwTlKcaKLkdHop5c/icOFE7qt7Q9JC5hnKNa6Gg==} + engines: {node: '>=6.9.0'} + + '@babel/core@7.29.7': + resolution: {integrity: sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==} + engines: {node: '>=6.9.0'} + + '@babel/generator@7.29.8': + resolution: {integrity: sha512-gZbepsdh3WDtgZKWL+vTPh71LSBrm/Y4/QDZBVCcYfmeTEEuoOYwlSy+G1StfJg+/Zy550u/3TATbm7qDbbMtg==} + engines: {node: '>=6.9.0'} + + '@babel/helper-compilation-targets@7.29.7': + resolution: {integrity: sha512-wem6WaBj4NaVYVdNhLPPVacES6ZJ+KBBfSkTMD3YZxbP3rm3Di85tJU5ljaUNhaOynt+Aj0xruhYuzQBt8n71g==} + engines: {node: '>=6.9.0'} + + '@babel/helper-globals@7.29.7': + resolution: {integrity: sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA==} + engines: {node: '>=6.9.0'} + + '@babel/helper-module-imports@7.29.7': + resolution: {integrity: sha512-ejHwrQQYcm9xnTivShn2IDOlIzInN34AXskvq9QicvCtEzq1Vzclu/tKF8Jq1Cg8JG2GL6/EmjgsCT7lXepE3g==} + engines: {node: '>=6.9.0'} + + '@babel/helper-module-transforms@7.29.7': + resolution: {integrity: sha512-UPUVSyXbOh627KiCIGQSgwWzGeBKLkaJ9PJEdrngIwMSzxLR4jS4+f1f1jb7VzBbg8nFLaYotvVPFCTqdrmTAg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-string-parser@7.29.7': + resolution: {integrity: sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-identifier@7.29.7': + resolution: {integrity: sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-option@7.29.7': + resolution: {integrity: sha512-N9ZErrD+yW5geCDtBqnOoxmR8+tNKiGuxKlDpuJxfsqpa2dFcexaziGAE/qoHLiDDreVNMupxGmSoNlyvsA3gw==} + engines: {node: '>=6.9.0'} + + '@babel/helpers@7.29.10': + resolution: {integrity: sha512-EMCx3AGZ3WfAl6ht7AyQoPm2Lh+BGYEMdc4Q6Hf7uSCDOZFuLq44qNwL+iaim8VlyYhRAo4X43+weadK8ZB4Yg==} + engines: {node: '>=6.9.0'} + + '@babel/parser@7.29.9': + resolution: {integrity: sha512-CjXrNHTnvqBVqHgdBysY3vk2T8tpJHb5/RMeHJBTyVa9xgugCB0CJTx/3oO8RV2QRQP391RWpB7D6hLjm8V9uA==} + engines: {node: '>=6.0.0'} + hasBin: true + + '@babel/runtime@7.29.10': + resolution: {integrity: sha512-NpugTzbKgGrNe45Ui32cN8vCFFMxVtP/9rtfwv0nP5FRDAjvYBxJcLVpYA9mr1jxP6cnIT7x9LUzuDTbWYYNRA==} + engines: {node: '>=6.9.0'} + + '@babel/template@7.29.7': + resolution: {integrity: sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg==} + engines: {node: '>=6.9.0'} + + '@babel/traverse@7.29.10': + resolution: {integrity: sha512-B3lYAs2nkKskbgQ1nfy8Ma9ao9Q1rntTAQHrzzyDuj+TSO+X3le6PfWwqDvodsb+OumE10eMFfuMCTQSQ5iuIQ==} + engines: {node: '>=6.9.0'} + + '@babel/types@7.29.8': + resolution: {integrity: sha512-Vj1jF3cPfxg7OAfoI7QnVKLoILlm2JF9pnVHrX8qx7AHMiYWT+NDAA7jChlNgRS4WTLc/fD1lXLmPixluj+3Gg==} + engines: {node: '>=6.9.0'} + + '@bramus/specificity@2.4.3': + resolution: {integrity: sha512-0GEz8qJWokkUVYQYRukmkSHIFNoBH8QTreeHrAFbvz1XFYc3Y+puhMs8PQ5x8GNugiC2l5jvDBXKLbBIByeSBw==} + hasBin: true + + '@csstools/color-helpers@6.1.2': + resolution: {integrity: sha512-grhRy3OKmniaAEKXMjua5z/EODX0MSqBGjunw8+j/3HQjOnahs2AGhvEOIYVUWcU6ScApbhLhVrQTX8XqrMrow==} + engines: {node: '>=20.19.0'} + + '@csstools/css-calc@3.4.3': + resolution: {integrity: sha512-iex20d8CHVkyvg6B7UKV7uHnI2Bqo9g+EFfT9E0y+GvTvhZ/DwONJ+9aKb1dlqm0ZiGsL5RXjp0fCoJYnkeDjA==} + engines: {node: '>=20.19.0'} + peerDependencies: + '@csstools/css-parser-algorithms': ^4.0.2 + '@csstools/css-tokenizer': ^4.0.2 + + '@csstools/css-color-parser@4.2.6': + resolution: {integrity: sha512-iiPQ3iRWwnJkeEn6RIu6SJPr7hYrLz6XZ9s/QZl+2/LI5KQVjpl2fdmDSZKuD4xP6GMmMPgHFFXg6k1Wkz0Trg==} + engines: {node: '>=20.19.0'} + peerDependencies: + '@csstools/css-parser-algorithms': ^4.0.2 + '@csstools/css-tokenizer': ^4.0.2 + + '@csstools/css-parser-algorithms@4.0.2': + resolution: {integrity: sha512-40cSKyMvK+tq4qz6Awrlye2WGuOKt3FwPgtGg6KTfbHOWNw+Rk1rzbAtZnZ6IBhsY491HLRnDXwoyBAijmmILA==} + engines: {node: '>=20.19.0'} + peerDependencies: + '@csstools/css-tokenizer': ^4.0.2 + + '@csstools/css-syntax-patches-for-csstree@1.1.15': + resolution: {integrity: sha512-J0u7HkVl2nzSlhsiTOp4AmwcUQ3D+mGEEKfBy/7To5/y7F2OHwyLrXfrhR0SMgr4p5Lo+eaMVSeai24zUcBIxA==} + peerDependencies: + css-tree: ^3.2.1 + peerDependenciesMeta: + css-tree: + optional: true + + '@csstools/css-tokenizer@4.0.2': + resolution: {integrity: sha512-OoKoR0f76dCY666JlcbhmVTs2drYj1GUXZTYTcbUgJjh9Nv41aFfZ21bPQTERm5+L5cBDo466NltB2lplS5GBw==} + engines: {node: '>=20.19.0'} + + '@esbuild/aix-ppc64@0.28.2': + resolution: {integrity: sha512-XExcO+dvLKvVtNTibSTBej1NCAbaGhWn9Ww1ZPx80qsahhPFe/8jgWP0IchNe0F3HwkU7n8ejhH8bjonqht8mQ==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [aix] + + '@esbuild/android-arm64@0.28.2': + resolution: {integrity: sha512-5YfKeeI8qWfBZIX+u2xZC3Zlb3Os/gLS2sbEKM+I4ZOcsWmHS2WLysCcQZDAFRslDUU5Oiq44gf6PYN1vGwG5A==} + engines: {node: '>=18'} + cpu: [arm64] + os: [android] + + '@esbuild/android-arm@0.28.2': + resolution: {integrity: sha512-kXXoiPVVGQcnIYGOeaovwOURpniDBpSq4A03qkQ+BMQqtGG6HYap3xne9C1O1yo4TR3qxlCX5IqqmX6fFo2Lqg==} + engines: {node: '>=18'} + cpu: [arm] + os: [android] + + '@esbuild/android-x64@0.28.2': + resolution: {integrity: sha512-O387ite7SzUyCcy3JQX4P4bLtEA7bLLkx+esve5JHnyYfNTxcVpXZo9jhdB0lTKN44gztELTdU7nS8Nr16Fs1Q==} + engines: {node: '>=18'} + cpu: [x64] + os: [android] + + '@esbuild/darwin-arm64@0.28.2': + resolution: {integrity: sha512-n4KqkOQrraxHJcgjM1RvwbigfQKIKJVpM7xp+KsxiyUSrRdIXnt73VhrPAx0fV44hgfmIVKjxMN9J1t5jySVkw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [darwin] + + '@esbuild/darwin-x64@0.28.2': + resolution: {integrity: sha512-uq6suIWYP37qzGddBKPw5QEQPi6HiLGsO7UmkpfyaYNQ3D+rN6w6WfwH+nuqcGXWvawGwxOEroO4YGnFh95azw==} + engines: {node: '>=18'} + cpu: [x64] + os: [darwin] + + '@esbuild/freebsd-arm64@0.28.2': + resolution: {integrity: sha512-n+I0BTSRIoy+d6RPKnEVwql5UwBJolytvY4mAOIEJorKlqgPII8ix6slVVrfZ5Tnj7glIZvloylbB/EJPMWEXw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [freebsd] + + '@esbuild/freebsd-x64@0.28.2': + resolution: {integrity: sha512-78XJTJkvPs0kz2w61301PJjXl4g7q3JqiYMZ/M/yVI73EHBrCRTgkhu9oqG7vPqq+a/yadEW8aD+agKlk5xrmg==} + engines: {node: '>=18'} + cpu: [x64] + os: [freebsd] + + '@esbuild/linux-arm64@0.28.2': + resolution: {integrity: sha512-pW4AC0P3it8c7do9MVM4p51FzHzdM/TZrerurgRcHJ2WTa1VQ1CIq18xncfpBJw4ojkiZZrKW2yIBWBP92j6Ug==} + engines: {node: '>=18'} + cpu: [arm64] + os: [linux] + + '@esbuild/linux-arm@0.28.2': + resolution: {integrity: sha512-XlDnu2q5yoqems+xay6wSAcg9DDD7K9RLKZEBOMZm3ckNpJBvOX20tSfby8KfrrhINDyv9V2YVZKY/SpoGJI8w==} + engines: {node: '>=18'} + cpu: [arm] + os: [linux] + + '@esbuild/linux-ia32@0.28.2': + resolution: {integrity: sha512-CYbnj78HsIeA+DhgUKgFCfvNsTHFhMMrinUrMZpDXJXKN8T3XViTZ/+wtHeVxEWY8ewSzTFN+nRmSwO2tZaLUQ==} + engines: {node: '>=18'} + cpu: [ia32] + os: [linux] + + '@esbuild/linux-loong64@0.28.2': + resolution: {integrity: sha512-buwkd8nsph4R+ajRvw0qM5Hja/TXQow3ptzWO2EbG/cqcIkHloRrdlBtQlshyYGTNFvfkfJ5tpPLVkY4DtsPfQ==} + engines: {node: '>=18'} + cpu: [loong64] + os: [linux] + + '@esbuild/linux-mips64el@0.28.2': + resolution: {integrity: sha512-ZVykbDyk7519VwiNb9Lcj9m8XM6v5V9uKPvrEMkkEedVewf+0itkhahp4HDpgERXhwLRpWFypsGbG/J8s0QjJA==} + engines: {node: '>=18'} + cpu: [mips64el] + os: [linux] + + '@esbuild/linux-ppc64@0.28.2': + resolution: {integrity: sha512-CAXl+Dtd9UUuJd8pKKdwh6MLm3MUMiqMPmhZ3tTSXPqfyQ3vDl6R5hZdZ/kYojK4ofXtdfSv1tFq8XzWx3heNQ==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [linux] + + '@esbuild/linux-riscv64@0.28.2': + resolution: {integrity: sha512-GeXCej4IQtU1B+QlDV8W/RRvbzI3O/Stss+/bCXv4lZls5WGRtu2a+3JkA3i4qIUlMXpcHebWpF8AkJhATowuA==} + engines: {node: '>=18'} + cpu: [riscv64] + os: [linux] + + '@esbuild/linux-s390x@0.28.2': + resolution: {integrity: sha512-3H1weTYZPxt/WOhByszQZybS9w5lKzUn1FDMsgEChbHWQwHYQQRfBxgCcZvPhjHfKyJjIievvMmEUawJrdY9Dg==} + engines: {node: '>=18'} + cpu: [s390x] + os: [linux] + + '@esbuild/linux-x64@0.28.2': + resolution: {integrity: sha512-4xTZr1FUmSoQW4XIWmit3tzQrUTZM+N3P0XV8xROKYF50XfI7xeO90+1bZvNwxIufQ9hDQVRJH5YhgPVF8A/HQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [linux] + + '@esbuild/netbsd-arm64@0.28.2': + resolution: {integrity: sha512-sSATRjPeDBg3pdgHoQfoYBob11Kk1FGa9lui5RIHZCoCkJa9QKlvl3/vKz2usCmYYjs7ymJR/2Nnsqe+Hjt5nw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [netbsd] + + '@esbuild/netbsd-x64@0.28.2': + resolution: {integrity: sha512-lqnzCV+mM0gIADaKihiCg6ifgfU2L3h5E33rNQBN1Y4MaVGnzryzmvvf7UHxprpQdE8hpqLolJ9Rl+SkIRDpyw==} + engines: {node: '>=18'} + cpu: [x64] + os: [netbsd] + + '@esbuild/openbsd-arm64@0.28.2': + resolution: {integrity: sha512-AL2qJILH7lNjrDmCQDvdxMfAUIv8KMNZOvrwAQ8i8//ntL9FflhOyMJ8OZSMBb8/AWXe3/5v5S20y3zCoZWKoQ==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openbsd] + + '@esbuild/openbsd-x64@0.28.2': + resolution: {integrity: sha512-QtiuPytchRyC4rwUKhexJdQKvDuZ6hWloi3igqPQNUJCS1/v9EiO3UTOXR6A3FoMo4fnAKbWJdqaIwhOzh8qEw==} + engines: {node: '>=18'} + cpu: [x64] + os: [openbsd] + + '@esbuild/openharmony-arm64@0.28.2': + resolution: {integrity: sha512-WkhYDmpTjLvGlScA1rwjRUmhl4k8oXR3cIbtqWmELgU/dFeHHlEllxDvdWcNJV9rbzCexB5vz8gtNewWLgCT7Q==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openharmony] + + '@esbuild/sunos-x64@0.28.2': + resolution: {integrity: sha512-GPMSkTOtMnv2U2F8gxe4Io6qmVs+YKyp832Etqqxr0hFngmXQ3rzwytelm3GIn7T4VviRUlf3sOgBOiTdvaf7g==} + engines: {node: '>=18'} + cpu: [x64] + os: [sunos] + + '@esbuild/win32-arm64@0.28.2': + resolution: {integrity: sha512-PIhhEkE9uPBleRBrQEJpUn7MBnibZzbGzYWPmY3x+YoVg/95zbjB4CxPPOQ8l5tYYM4mMaCthF8/1DIfBQQyWQ==} + engines: {node: '>=18'} + cpu: [arm64] + os: [win32] + + '@esbuild/win32-ia32@0.28.2': + resolution: {integrity: sha512-YmJbfTlvU7Sdn9BB+4PRES4oB6pxgS37MAONj+hBr/cpXS1aBPKXxNnDbu+QCWPj0o9dgyxeq79g6c5P8KeuYA==} + engines: {node: '>=18'} + cpu: [ia32] + os: [win32] + + '@esbuild/win32-x64@0.28.2': + resolution: {integrity: sha512-5ebpxr3nWMzrL/rnUI755Jkuee0bHL/Gq0WTF9lvcpv73wAp5eu8MfBUgWK9bhWvZjj7yX8etf/8tI8Ney695g==} + engines: {node: '>=18'} + cpu: [x64] + os: [win32] + + '@exodus/bytes@1.16.0': + resolution: {integrity: sha512-IcpW84uEn3N7ETtNZMlxKhfl6Pec8rUNGOTBtWbK1FKhJxIFAptZyVrvVRVBimAJxJCgc3PxepxkdWWG4DVzfA==} + engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} + peerDependencies: + '@noble/hashes': ^1.8.0 || ^2.0.0 + peerDependenciesMeta: + '@noble/hashes': + optional: true + + '@floating-ui/core@1.8.0': + resolution: {integrity: sha512-0CIZ5itps/8x7BG8dEIhs53BvCUH2PCoogtakwRTut+Arm58sJooJ0AuZhLw2HJYIR5cMLNPBSS728sPho2khQ==} + + '@floating-ui/dom@1.8.0': + resolution: {integrity: sha512-yXSrzeHZBTZadLOlfyhCkJHNeLJnHRnRInwdZ40L7ZiaAtrBwoYlsDrX3v5zB1Utk7CLfzcOVnVVWoXEky7Ceg==} + + '@floating-ui/react-dom@2.1.9': + resolution: {integrity: sha512-JDjEFGCpImxDCA7JJKviA0M9+RtmJdj0m/NVU5IMgBK+AmZouAQQ7/+2GLH0GXXY0YMw9oXPB8hKdbPYg5QLYg==} + peerDependencies: + react: '>=16.8.0' + react-dom: '>=16.8.0' + + '@floating-ui/utils@0.2.12': + resolution: {integrity: sha512-HpCo8tmWzLVad5s2d19EhAz5zqrrQ6s69qd6moPMQvkOuSwDT1YgRfWSVuc4ennqrgv3OHppiOGMQ7oC13yIww==} + + '@inquirer/ansi@2.0.9': + resolution: {integrity: sha512-0Ywt3S8tqM6TWUcsRlBFQ1x+X3/o8kktX0ZiKAnByYb9GFDknnOhse1PVtfiD2BXPI8ar+BWx9PV9R0lQIcygw==} + engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} + + '@inquirer/checkbox@5.2.6': + resolution: {integrity: sha512-XkOardciF3tow2NUlY6/Qjk1QqYa+6WpmVLTpxXl97Uv4erczDEZ+xg1j6LqBf0ekcRSUiICQA4nQXHHkVKQ9w==} + engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + + '@inquirer/confirm@6.3.3': + resolution: {integrity: sha512-ImOBgpl/sJTFp8naeSkNu4S0Sf8F8pxv3/CUx+LoBAdQvCVqFz6rSB2A/oZYsJge3+yphbEDxEkfaRNYq1OU0A==} + engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + + '@inquirer/core@12.0.4': + resolution: {integrity: sha512-M5fB67y7jPObI45vhD82RskWwCSm0scOvenV/I6K8tIi2gfr9DXqQqJ+iw+Wi6SgapikdOiJibYzz1gW47fsDg==} + engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + + '@inquirer/editor@5.3.4': + resolution: {integrity: sha512-imzxQDfw26NpcJAubMj/dE5RjU9Mp80IcT+FzsD6YoxXmL8L1QYnAFdCNv7ccGWh//73+0YP+1kfhwnExdl2VQ==} + engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + + '@inquirer/expand@5.1.6': + resolution: {integrity: sha512-JfiLKi7qGuHmcQO/DqR10UFEp054Y1FXZaszP5ZEfHhgHeuFoT5nNFQIXFhed/5/p07SbsV2tIJFwG/dg5+NmQ==} + engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + + '@inquirer/external-editor@3.0.6': + resolution: {integrity: sha512-rWmw6WG8JZ7LMn/srXEylYGhL6EXXJeROE7/4x4GREh6NgzqJBDbIgpNGsYoLPfobeb4VZtEYzPGnT5EFNYhiQ==} + engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + + '@inquirer/figures@2.0.9': + resolution: {integrity: sha512-EAWgUTGQ/Umgga51dE3B2PUHbufuXarDfg86uVgoSgNHNNQnyFKcOrQLWVqYMghuSyHh8+2HUH0Js9cTC1WAdg==} + engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} + + '@inquirer/input@5.1.7': + resolution: {integrity: sha512-Icrs9tuMBCxGI+lFYNO71VFOnqGO8IIrLIGqnTGh07X8jZ2la9QLAYxXcikHZQjjVhIZUtU2xyH89DVN/pPhVg==} + engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + + '@inquirer/number@4.2.4': + resolution: {integrity: sha512-C6g80U4U2+w2Vxa1CB0MN3a2WnQIfzLSUG0lduO3Au9GsirJsKATZkOwZPK+vZ1BlAlz+/Z5ParfQCS9E0svmg==} + engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + + '@inquirer/password@5.2.3': + resolution: {integrity: sha512-1Uo2qfI2K3wXbfunMpvwAzoZPIUf5iEETwDGqRVbswoorXGqYQJ/bfIJFeLj+pxjq+e2UFPNOmx+fsIl4Urigw==} + engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + + '@inquirer/prompts@8.7.3': + resolution: {integrity: sha512-DHK20kO+H5k/XcJQpHQUpVQbMYHHhZchlGWhZVMUV4WIuRuBW5744hipOtriE1vMqPLgnIyXFMHWKkIbTepa4Q==} + engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + + '@inquirer/rawlist@5.3.6': + resolution: {integrity: sha512-2exExhQ5xTBqfN/rRlZkvM1Gm3b0eiLcWe2NqxWxe7qYmnU4M3j/n9TwzfPUb+Q7dAAz9TmBtDWWdF3jbp4ZLA==} + engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + + '@inquirer/search@4.3.4': + resolution: {integrity: sha512-xsk0UeFP04jsbEeFMzghjUaH2aHXyt+WykSajQzq/8qyBNHsgGYHea/sFwv5T08kW7Sp+KDX8aF124zPUIs1Ww==} + engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + + '@inquirer/select@5.2.6': + resolution: {integrity: sha512-jFu7CFghlr0vpi/326a4wz6BGkJH9X3H/iIu+ahyV2Ja52ktqQE3fC9BYP47JKeSPQYGUv5xquE2Vp9PbepZ3g==} + engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + + '@inquirer/type@4.2.0': + resolution: {integrity: sha512-2rnHX8RPo4glJYqnFc/v3nQeIhDcjyRRyaT7MGcfL/8xv/8K03SXYoA2tX06WVSKywWOE/ncbG3dtuzLjR5TCQ==} + engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + + '@jridgewell/gen-mapping@0.3.13': + resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==} + + '@jridgewell/remapping@2.3.5': + resolution: {integrity: sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==} + + '@jridgewell/resolve-uri@3.1.2': + resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} + engines: {node: '>=6.0.0'} + + '@jridgewell/sourcemap-codec@1.6.0': + resolution: {integrity: sha512-T7jf+5zgsZHwNJ4lvQ7/aezbyk0nNX+zJVWpmHA7VYsEx7a7qr5Rg5IbtJFqkgze5Y2sruq1RUY8Q837Od7iFw==} + + '@jridgewell/trace-mapping@0.3.31': + resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} + + '@lemoncode/lemony@0.10.0': + resolution: {integrity: sha512-y00lRAyTH6Fe9uyH1/eFJ7Livtyl3udmSriCGWbYGERIGCoZHd7jLqKIWN/k97byoDyJ+O/RP6M0OKJ64Qy8uQ==} + engines: {node: '>=24', pnpm: '>=11.5.1'} + hasBin: true + + '@mongodb-js/saslprep@1.6.1': + resolution: {integrity: sha512-D4CQtk9IwjCLAvCf1xvHEod3960q8XMUzfmdRU9qjUNlHnesGuTOvJcOTaPm9koZ1caUKA2aTbszZiAkcmSgmg==} + + '@oozcitak/dom@2.0.2': + resolution: {integrity: sha512-GjpKhkSYC3Mj4+lfwEyI1dqnsKTgwGy48ytZEhm4A/xnH/8z9M3ZVXKr/YGQi3uCLs1AEBS+x5T2JPiueEDW8w==} + engines: {node: '>=20.0'} + + '@oozcitak/infra@2.0.2': + resolution: {integrity: sha512-2g+E7hoE2dgCz/APPOEK5s3rMhJvNxSMBrP+U+j1OWsIbtSpWxxlUjq1lU8RIsFJNYv7NMlnVsCuHcUzJW+8vA==} + engines: {node: '>=20.0'} + + '@oozcitak/url@3.0.0': + resolution: {integrity: sha512-ZKfET8Ak1wsLAiLWNfFkZc/BraDccuTJKR6svTYc7sVjbR+Iu0vtXdiDMY4o6jaFl5TW2TlS7jbLl4VovtAJWQ==} + engines: {node: '>=20.0'} + + '@oozcitak/util@10.0.0': + resolution: {integrity: sha512-hAX0pT/73190NLqBPPWSdBVGtbY6VOhWYK3qqHqtXQ1gK7kS2yz4+ivsN07hpJ6I3aeMtKP6J6npsEKOAzuTLA==} + engines: {node: '>=20.0'} + + '@oxc-project/types@0.154.0': + resolution: {integrity: sha512-KYOUGQFlLWR+s4QMV2Q9ko38TZm7EdO87Qm7rvZLqk/webse/cDjtyxKhg/47l0byCbs/k46LT8qc4PKjAikzA==} + + '@radix-ui/number@1.1.3': + resolution: {integrity: sha512-Road2bidD0uu/1BGDOWNdPI06g0lIRy6IF9GZcIrDK2KGItfor8IQwQa+yM2ERgHM1MmHxaxpTzk0/Jp42lNfA==} + + '@radix-ui/primitive@1.2.0': + resolution: {integrity: sha512-KABY+VMIRPJL+Vyzv/335FEhXXD/xDv8BMb1kl48/aXJZMH0LtHCTx5ga5RnxaEP3nZHtmTLf1P9vanmFX46bw==} + + '@radix-ui/react-accessible-icon@1.2.0': + resolution: {integrity: sha512-BB4+HHkFl3HipEAhm/mLhrpXV+2kRX7MvY4AaImUcQVeWQt5KhV1JEByNs8NGfJOcr95RcQGijt9+OrCo68xGA==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-accordion@1.3.1': + resolution: {integrity: sha512-lCZ6sbGS/7WO0j84yx4srIgOf0MRJ/sZ13RonADXxvKBym8xrxNCq5f6DibGcr38sIlwPk8/52uYdXeOPsbEDw==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-alert-dialog@1.2.1': + resolution: {integrity: sha512-MWC4N7RY+qsbNrFNo7yQ9ZbdoZEW+B5DtpWxJfUnVCqcQxxqqg3qis3RMPTDbCNaTIdHJSn5XDkl9ZdVWXknLg==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-arrow@1.1.17': + resolution: {integrity: sha512-67jjcVvxjXCCStnTW3Z+M7jmaFMuMR7M2JgpDzH4w7JSRrikmzhjfYgP/09ECb8n7whnsgh1ifJ+Ie96qEj+pQ==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-aspect-ratio@1.2.0': + resolution: {integrity: sha512-gHEU+Lx8DlT/FYIjZQvvBJrFSwUngXTjh7FeL9QvJaNALDLez6pgDj2axCUihBjtPBy82LN0gNb25+sTcSXNmA==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-avatar@1.3.1': + resolution: {integrity: sha512-ssZOkfQNkFpYVmCPQlr978xSaU7moSrGXdwg4j2Xs2WlGl/1KsSZtfpK+WnLnx0Rwll1BAh6oUrAy/uR31SBvQ==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-checkbox@1.4.1': + resolution: {integrity: sha512-KWtwhh+98ML3seZ9vO9yRY2OwaQG90dCiDAxjpSNY2AaZ3Hik3B0dsk6m0ILywo/no3A9/SozadyPMNweVT8yw==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-collapsible@1.2.1': + resolution: {integrity: sha512-fSzLb/qy1wuZSxQBcxpW0hNXYHDMWiIXDGyJGdA4+FSLknOWZsNRrTCUavxb4PI8b8lvHo/CysO6NVi5zLpo5g==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-collection@1.2.0': + resolution: {integrity: sha512-+yiQzqcc7Sy7/5s0jrMCjpPRFB3538VNrXPWdTLZhE/SCfgEws4aI6lHWN/vvcnyhHndROWBzqmqB4QBrITZ9Q==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-compose-refs@1.1.5': + resolution: {integrity: sha512-+48PbAAbq3didjJxa+OaWY2ZwgAKsNiRGyeHKszblZMQ+kcpd9pAaT11cMkGEie0vsOi3QdeTE6d5Fe3Gn61kA==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-context-menu@2.4.1': + resolution: {integrity: sha512-Pddn3Z8lio3/ChxyXaEP3jHTTo1LTHCWwF8+mG1chQlWijP+ttVHBKwezrQTiV6Mj670ojvumqvuGh+mdv33iQ==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-context@1.3.0': + resolution: {integrity: sha512-v5AYEocMISkbJ+1fTXzZpiFv7NRr3D2WiYbLIKf+FkmJ8VkP6d503eV2n34MFussHXY1pcoq3yfJiQH77dc4Mg==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-dialog@1.3.1': + resolution: {integrity: sha512-+0E4qvVTwjAWra9sEhJ+9BTsvHE00zkUuNw1VGh7S+Gc13dfYk+S1PVQdchWDj+XYHhAai7Z7IpzXVDCGsDplg==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-direction@1.2.0': + resolution: {integrity: sha512-FtRA52a/r+LKStFT+neLUm+8vSe7wbzkbQGGeU8ixFiwC8NU14Evoq9ATECqL3eGbcUzJR4fyfA4KkK/q6dfqg==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-dismissable-layer@1.2.1': + resolution: {integrity: sha512-KIfDcAsx+oVylFZ4xryVKusJUrLLhTQmfnJW4kwk4Km5myvhHCrj04hnWWUC166+xD4DHdH8tQGylwYX1h6+Pg==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-dropdown-menu@2.2.1': + resolution: {integrity: sha512-XsHcmYG2AcqnvTqrOXXWcMrhquEIlqucizuDH1MV/qMRW+DndpBCMvNeTRXOxqmG1H5j89M/+I0/34Zdd+zDcQ==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-focus-guards@1.2.0': + resolution: {integrity: sha512-MPm5R0iRGUDrDnPNxmLBkv+X7pN4XKzt+MbWJEuJQsH3NFH4omrbpXpucyYCCKTSt+na/ZxGhEWQrWTZ0285cA==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-focus-scope@1.3.1': + resolution: {integrity: sha512-ugeMhbXt4y5S2T1GnIqbWDKEN962PDwnX1fN0eKOOgf5f63Dh2mn8F1FUySlgW0iF6GiVsRF32DzuDIWTUyQJg==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-form@0.3.0': + resolution: {integrity: sha512-KnmrCM27m7Jo1R8S6cFDPrEeq20Jfn5dqde0SZrJr2lVXlj6/QZSUCyFoYh1d8ti0uUrMNK5Lx6dUDuINT+f4Q==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-hover-card@1.2.1': + resolution: {integrity: sha512-4QooHxgmpCKRjj1Pft+hETKidYcrbPKcVwMGtk2Oa5DcWY2IH1fHuQt9LG6q5hUQBBV2MhQxSvtx6B/C1xfiTw==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-id@1.1.4': + resolution: {integrity: sha512-TMQp2llA+RYn7JcjnrMnz7wN4pcVttPZnRZo52PLQsoLVKzNlVwUeHmfePgTgRluXFvlD3GD5g5MOVVTJCO0qA==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-label@2.1.17': + resolution: {integrity: sha512-xmj7MN/drx1oUAXkfiFIvyDmGNUIN/omGobvA5oAoNqu9zO2MkISYGZOkBcqSzs/UZXXwV+/3ACRE7q7mGcmkA==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-menu@2.2.1': + resolution: {integrity: sha512-G34BsU90SBj5foYpz8pQqq/Q0Dlfyyl6KitWEfRwXC0QvfwhWNAwS49DWP2+rRJ0iwv20Z2Qx7Sk+T03bGo5JA==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-menubar@1.2.1': + resolution: {integrity: sha512-bRTYtS9JITV2dUYqYZb7+N5SooQBkZrNRejfmyrSKe3Y57aXhKgx//kBUP0kY7pEpsWR/U1AHsAJRzjwCrK3PA==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-navigation-menu@1.4.1': + resolution: {integrity: sha512-XPPZjkeyCSMNNvt0FyDv/PUauG7Ow4GwHQ/XZSwW36F/TS7rR4HFTsXH8ewLnXTOLn3x96/pmTPNQIVoTX/86g==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-one-time-password-field@0.2.1': + resolution: {integrity: sha512-KtHdcgnaAK6rohQ/MMJoGYcbgSRJsIuGBdHrFeTB1/9SaKlDs14oSOniW6BL6M43HqvgCO3u4WuVdFLkuc6sqw==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-password-toggle-field@0.2.1': + resolution: {integrity: sha512-vu4+ZoJAaFjdI7l1lDSZRs+4dEv83Jmu7lyzajPrAeQzX74y84n0rUNWbWSgN9XB5NE8IY86Z02kGH6oRrzR+w==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-popover@1.3.1': + resolution: {integrity: sha512-ZNxvXRx5W2Wos4fXCXb5lpdqN0Z5chf+mStOUOTr4ik7d+62MRvoe9rzCA/eGNg36lxXqSrKEKmwuZEcUrIstw==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-popper@1.4.0': + resolution: {integrity: sha512-yCWRvLeGv9Pz3+efwHqGPp70mZ56r3kfIgQVF56Oj2aAa4uP/Tb+IE59wNcc+758rctqbCKx4LbK8II/r7Bn0Q==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-portal@1.2.0': + resolution: {integrity: sha512-StX7xXnaRU41VvFtMm9zlhVGz8XF6GmWWTXftkQaY+tqVkbs/R9UmAp5mLzHHapk5hM9RMZQvO/3usyIP/g42g==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-presence@1.1.11': + resolution: {integrity: sha512-Z7/atlkab36Z8hm+V8zYc79r0W+tiOB1o0tun1By94JyadkekLQmtEAnBSP9XKXBNQsStoStS4+gX10JpS5akA==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-primitive@2.2.0': + resolution: {integrity: sha512-HCTSPMNqv55Qk0IX4geJbpyXazmqulcimwuyjxTkKi29v+QZbG2Zho9BnbBq4YS2PF+KlNb2CXoLz66uUmblkg==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-progress@1.2.1': + resolution: {integrity: sha512-yQBiM6J3YM8Ums1orkEFpbznK47geKxa0igikzcaS1xHgdba3DdAQBsGbCTt5BVfR8zhEvgxQ0poGcINaD3lvw==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-radio-group@1.5.1': + resolution: {integrity: sha512-QbyVT1ddnjqB9H+CUYKkNWdU9fIK3QHCYtjf7mS6ekSqiuXkWtWn5UZW9mhA8qtl3vrVyIsmR9gePstAtKrqkw==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-roving-focus@1.2.1': + resolution: {integrity: sha512-UwraORzVUeEPMclhO1p0vz0qI+TbdDLO9i+FiOqhJyHKwdpCRCck9yVEscUnAMIzCiuNoQa8D4A9bIpOPXGt6Q==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-scroll-area@1.4.0': + resolution: {integrity: sha512-CFrLqHNejWq5FhKAcj9V/WPGRsol76HBQto81NdOBVFEOqIEkJkKIJt0Z824A/9hHLCtoiR/Kw3euRgzXP2pxg==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-select@2.4.1': + resolution: {integrity: sha512-888ZwW0Md6GyptuqYABRX9nLKgoYfcooCyBBvVaX5Jp3e+8Jp2i4Zo/Uy50Hm+Ysn2JfloQXstW4U36w8teVtg==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-separator@1.2.0': + resolution: {integrity: sha512-1jUAap0wZEqVP05Ou7kJgRxe/W+Qftng+rUNWGa0qkKbv9r5pWTG3E7a3ELKo2eJoHKMECnzuYrZpSyO1YgcYQ==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-slider@1.6.1': + resolution: {integrity: sha512-IRNRR90moPqxfwCJ0XbMJIxo70W0/1ZExT/sNCxEHMaPx0SF9HoQrcPEC75+H28cFKa0b+KH63anfLYJmwKacw==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-slot@1.5.0': + resolution: {integrity: sha512-tyYd9ddPXAysAbdbD9eYxgwpCSv6f3PncqVSNKQFSR5lcJVLz3cb/pANDoYrLiHBpXv7skortyUgGUWsYuPPFQ==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-switch@1.4.1': + resolution: {integrity: sha512-NpBGwc40rY02ZmSvuyeKk0Bvc8ZsNeTMi4qHvJ+ZH4EiYCv0zIXEgdCW4bVdzgIUeP9xxbLJSxKOUfqITYNmkA==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-tabs@1.2.1': + resolution: {integrity: sha512-hRoJlode+hg5ZNlR+3tkfkUliIybdTpD5lkAvHQ9yaXseGf7XVO9Ib2GPEIOuaJJbo7YWYbNpDDRfo8Dhf6/xA==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-toast@1.3.1': + resolution: {integrity: sha512-iQvL0J7XK4HtJNGkkWMyYrboNseI7vtotFeUkIno8YNxVA9oM7B6//fh0Mc6TSKI96+zioLWi98lQLso88yJmQ==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-toggle-group@1.2.1': + resolution: {integrity: sha512-O8Ldx5ao4p4KoW+DO8/PmkOe5mdKNi3F2SseqjVj88wvDGDHe60cUmO0Zm/uHsKrvNgQGV8Efpuh95Tht/h4vw==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-toggle@1.2.1': + resolution: {integrity: sha512-+3MUq+WyiBplXYqQ0EIYlq8R4sLQ0T5NbOK7DMdDLCKO93pe2uE0DUJTWWfTBprpJJXxfoF3eMW0xpakVZrYsg==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-toolbar@1.2.1': + resolution: {integrity: sha512-Cm8m7JTEeUdbfA6T9xgyu8HfOpyvSx8pB/wj0DlEuWaJe9FilIs4Az9wci/lU9RbthV/UkltszMw5WnnD+m/Ug==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-tooltip@1.4.1': + resolution: {integrity: sha512-NxLFGSFtZ78zVfcoOhTwR1xwqo5qx1Jh8Pw6FMZ9McCaqfRzz7/gIRahs2Oy5XlPgQ+8QkUcKbN5B0U44J/kCg==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-use-callback-ref@1.1.5': + resolution: {integrity: sha512-Y5GBf4NKeADoXI1geiMlMuMoURT3k9MizzzKhGb/m55H94aGigZ01PIpkvsO6lML13BA6XYAXSJ6gza7vTn5nw==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-use-controllable-state@1.3.0': + resolution: {integrity: sha512-TAcBI7bw2ljYCbv4+zuTSd6zICu8pRt6SDN2vJ/Z06K2MXh6I9WYFe/A9ovlFDtR5HVHGm5iDxDoABm/++dbKg==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-use-effect-event@0.0.5': + resolution: {integrity: sha512-7cshFL8HGS/7HEiHH+9kL9HBwp2sa9yX18Knwek6KYWmXwM7pegMgta2AXMQKI+rq3JnfSj9x8wYqFMTdG1Jgg==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-use-escape-keydown@1.1.6': + resolution: {integrity: sha512-9cRullnQRv+kqnRmFlmh0WC3kAPuGmHiQ9VwsXdrYk//sBhgCKEttcpPEPgIQbyx6TGUmooVEHYTyohwz/lSJg==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-use-is-hydrated@0.1.3': + resolution: {integrity: sha512-umO/aJ+82CpOnhDZUTbILCQf7kU/g0iv+oGs/Q8jw7IkhWBzaEP4sA268PhFAJTFetbwp3ICc6ktpI4TqtxcIw==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-use-layout-effect@1.1.4': + resolution: {integrity: sha512-K20DkRkUwDnxEYMBPcg3Y6voLkEy5p5QQmszZgLngKKiC7dzBR/aEuK3w1qlx2JWDUNH6FluahYdgR3BP+QbYw==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-use-previous@1.1.4': + resolution: {integrity: sha512-XoSLhbRbqxFtgJoi2fNHA3C6pDlY34x508vUpUGoFZfvePfHXHbE1lC4FYFMnJWgiCRroSTw6fOsXQoVS9RwZg==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-use-rect@1.1.4': + resolution: {integrity: sha512-cSOCh6JlkmfjLyNcLiu2nB4v+nm+dkZ+Q5KHWk/soo4U7ZLiEQFKHK9/YmtBHjfCEaU43IBKQOc4/uJmCaiCTQ==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-use-size@1.1.5': + resolution: {integrity: sha512-V1McDQkMGzgivwqdu7u96APs7oi0Jvj9LTzgq3WWrDZqxWdAqU9yZnZQqk5OizGFR8badUQwZsrlao7MOlWYOA==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-visually-hidden@1.2.13': + resolution: {integrity: sha512-feijiN1oPk4rck4u9Dm9tsU4mT6Wp9oeEEhaz1WUEs1VuqLf8xzsFG+Qk+uWq6TnMH9O+WRECRg0NftyP9E4Fw==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/rect@1.1.3': + resolution: {integrity: sha512-JtyZR+mqgBibTo8xea3B6ZRmzZiM/YeVBtUkas6zMuXjAlfIFIW2FgqeM9eLyvEaYX66vr6DJMK+4U6LV0KhNw==} + + '@rolldown/binding-android-arm-eabi@1.2.14': + resolution: {integrity: sha512-aWR+XKH9+rW7m5fWq/5360J3mHycrx/o6xZM2DQFdJnTMdyP7/WzxPjhtLbVWdKo2y612/4U1bWqb3HQhiF7vg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [android] + + '@rolldown/binding-android-arm64@1.2.14': + resolution: {integrity: sha512-QiVxHofl6A8lQU7WAtOUY4QMVZXohxwz7WJJoeh8NBEUyKfIkMRKhYyq8az/1RypNiIXzNTtiS6KwHz0erxYRQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [android] + + '@rolldown/binding-darwin-arm64@1.2.14': + resolution: {integrity: sha512-lTQOzHuBIooh3jIr5XINQkjPGEuGy+Dsy0meXDr6Sjty0b99kYgGh4uBC/8mJX1T0kC8d6S0aPP1Y+bHkh6aBw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [darwin] + + '@rolldown/binding-darwin-x64@1.2.14': + resolution: {integrity: sha512-hyMKEGatjmBYCs/Q4sbIcL/GqpFEqsX3wc+HYVQ/85A4rxc1o7rPm4DUI4GV4k/h0ITddwFSGpqQunI14GXjTA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [darwin] + + '@rolldown/binding-freebsd-x64@1.2.14': + resolution: {integrity: sha512-u371GbXoVXrEgP20PwzoGNOdAOqAMhzo19JzzY+V4YmmnC+DTOoqdbMu+O+54emM59Mik/UdrtWgcuEDKWRPKA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [freebsd] + + '@rolldown/binding-linux-arm-gnueabihf@1.2.14': + resolution: {integrity: sha512-BqwKsdZQf6EqVWr8fv2MrDYzAvOZ7+NYFSJESRGs87fkseEhs0TU9TXgRJTkZoRRkxTizyEg1LKUXfU3/78uqg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [linux] + + '@rolldown/binding-linux-arm64-gnu@1.2.14': + resolution: {integrity: sha512-SD9kY8M009x/7s57Z1dgUVlP5+uYBgKQK0Tkr1WIWngrtUJmRCW1RJFMY7QDla2khXhmg2i5Io7MUjcmZNZ/KQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + + '@rolldown/binding-linux-arm64-musl@1.2.14': + resolution: {integrity: sha512-BJ2CL19M6uuWesMgnqJzgxoI+N+eV7b0A9O9vLV42y+gitC41fNa8KElau1tHVzuLWX5GzEuxMPhAO0tQXQMkg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + + '@rolldown/binding-linux-ppc64-gnu@1.2.14': + resolution: {integrity: sha512-4+Kl8daPV8NDHaD7mfCcc1pRM+Qg7ab8DyMm5FG5WoZgv4h2i3KFN1CybYBNbQqmuYm7ftJLvmMI1eHYJ22S/Q==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [ppc64] + os: [linux] + + '@rolldown/binding-linux-s390x-gnu@1.2.14': + resolution: {integrity: sha512-V/h8ePq1fKDrmtFMz6xcCN3DKvuvMRrwwD1q0PkBeeo4DpK64biaKvqWGVxqCeYKqeRk7gE7/iKPxLCn08O97A==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [s390x] + os: [linux] + + '@rolldown/binding-linux-x64-gnu@1.2.14': + resolution: {integrity: sha512-WxalXzgrLVpKC93xfpaJ3gCXUWzeCr+FRCbDVD2mUAy4L6Vo3lNVz0epUEUpxPWJkLNYUwM4OSIikv36OJ9mLg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + + '@rolldown/binding-linux-x64-musl@1.2.14': + resolution: {integrity: sha512-3G3tnAmTpdk9jO3GQtyHXqeFD2SlecfTws/Y3M2mmj9nMBwwuLT4kur8sZKeu7ENUHSpVO3cIsm5A52LEWWwlg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + + '@rolldown/binding-openharmony-arm64@1.2.14': + resolution: {integrity: sha512-qyr5XiNGxm2ytx17vvtcJ9nXn6v1gENETi503bJx3OGwZ1tSonj7BosxbMa/xeAfSl5iS9X6KjEWYXLu6v1L7Q==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [openharmony] + + '@rolldown/binding-win32-arm64-msvc@1.2.14': + resolution: {integrity: sha512-oA4o5o0S2yB199YyYXDzKUv1Z56Rc+mgOjwm7Z/vJ9Z8igiDPYvoOuDyo6g7AK/ZaF09nPhDKVnGBcYHO11GXA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [win32] + + '@rolldown/binding-win32-x64-msvc@1.2.14': + resolution: {integrity: sha512-9mE94bf2GZUaR/fUSXCMpBoWkctu421Mi0ORpm4zqfbkjKep7RxzPFa5etcGs5h+2KApoWBOA/hAJa/7saGgEQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [win32] + + '@rolldown/pluginutils@1.0.1': + resolution: {integrity: sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==} + + '@tailwindcss/node@4.3.3': + resolution: {integrity: sha512-/T8IKEsf9VTU6tLjgC7+sv2mOPtQxzE2jMw7u4Tt40Tx+QSZxpzh95/H6cMKoja9XuW7iMdLJYBB0o9G1CaAgg==} + + '@tailwindcss/oxide-android-arm64@4.3.3': + resolution: {integrity: sha512-Y85A2gmPSkl5Ve5qR86GL4HT509cFqQh1aes9p3sSkyTPwt0Pppf3GkwGe4JPACcRYjgJIEhQgM6dBClnr0NYw==} + engines: {node: '>= 20'} + cpu: [arm64] + os: [android] + + '@tailwindcss/oxide-darwin-arm64@4.3.3': + resolution: {integrity: sha512-BiaWatpBcERQFDlOjRDpIVXuFK5PJez5SA4JMg6VYZdBYU+qKfV/vqjcIs+IYmtitf1xYQZTwXvU/8y4lfZUGw==} + engines: {node: '>= 20'} + cpu: [arm64] + os: [darwin] + + '@tailwindcss/oxide-darwin-x64@4.3.3': + resolution: {integrity: sha512-fAeUqfV5ndhxRwai8cXGzdLvul9utWOmeTkv69unv4ZXixjn61Z+p9lCWdwOwA3TYboG3BwdVuN/RDjhBRl0mw==} + engines: {node: '>= 20'} + cpu: [x64] + os: [darwin] + + '@tailwindcss/oxide-freebsd-x64@4.3.3': + resolution: {integrity: sha512-iyf5bV6+wnAlflVeEy7R25dupxTNECZN5QMI0qNT6eT+EgaGdZcKhGkr5SdoaWiLJ3spLqIY9VCeSGrwmtg4kw==} + engines: {node: '>= 20'} + cpu: [x64] + os: [freebsd] + + '@tailwindcss/oxide-linux-arm-gnueabihf@4.3.3': + resolution: {integrity: sha512-aAYUprJAJQWWbRrPvtjdroZ56Md+JM8pMiopS6xGEwDfLhqj+2ver2p4nU4Mb3CRqcMmNBjo8KkUgcxhkzVQGQ==} + engines: {node: '>= 20'} + cpu: [arm] + os: [linux] + + '@tailwindcss/oxide-linux-arm64-gnu@4.3.3': + resolution: {integrity: sha512-nDxldcEENOxZRzC2uu9jrutZdAAQtb+8WWDCSnWL1zvBk1+FN+x6MtDViPB5AJMfttVCUhehGWus3XBPgatM/w==} + engines: {node: '>= 20'} + cpu: [arm64] + os: [linux] + + '@tailwindcss/oxide-linux-arm64-musl@4.3.3': + resolution: {integrity: sha512-Md44bD6veX/PC5iyF8cDVnw4HBIANZepRZZ7a8DQOvkfo5WUBwcp6iAuCUz23u+4SUkhJlD3eL7hNdW8ezd/kA==} + engines: {node: '>= 20'} + cpu: [arm64] + os: [linux] + + '@tailwindcss/oxide-linux-x64-gnu@4.3.3': + resolution: {integrity: sha512-tx7us1muwOKAKWao2v/GaafFeQboE6aj88vC6ziN2NCGcRm8gWUhwjzg+YdVB1e4boAtdtma4L43onunI6NS4w==} + engines: {node: '>= 20'} + cpu: [x64] + os: [linux] + + '@tailwindcss/oxide-linux-x64-musl@4.3.3': + resolution: {integrity: sha512-SJxX60smvHgasZoBy11dX6YRjXJFovwWBoedhbQPOBzgFWBHGB+TVPWB9BxzR7TTxU8FQZAI2AyiNCMzFm8Img==} + engines: {node: '>= 20'} + cpu: [x64] + os: [linux] + + '@tailwindcss/oxide-wasm32-wasi@4.3.3': + resolution: {integrity: sha512-jx1+rPhY/5Ympkktd656HBWEBLxP7dH06losBLjjf5vgCODXvi9KhtftWcMIwTFIDqBr7cRnQkdLnAG+IOlGvQ==} + engines: {node: '>=14.0.0'} + cpu: [wasm32] + bundledDependencies: + - '@napi-rs/wasm-runtime' + - '@emnapi/core' + - '@emnapi/runtime' + - '@tybys/wasm-util' + - '@emnapi/wasi-threads' + - tslib + + '@tailwindcss/oxide-win32-arm64-msvc@4.3.3': + resolution: {integrity: sha512-3rc292Ca2ceK6Ulcc/bAVnTs/3nDtoPhyEKlgPv+yQJQi/JS/AMJlqzxvlDacL1nekbrcf6bTqp/jV4qgnPxNQ==} + engines: {node: '>= 20'} + cpu: [arm64] + os: [win32] + + '@tailwindcss/oxide-win32-x64-msvc@4.3.3': + resolution: {integrity: sha512-yJ0pwIVc/nYeGoV02WtsN8KYyLQv7kyI2wDnkezyJlGGjkd4QLwDGAwl47YpPJeuI0M0ObaXGSPjvWDPeTPggw==} + engines: {node: '>= 20'} + cpu: [x64] + os: [win32] + + '@tailwindcss/oxide@4.3.3': + resolution: {integrity: sha512-krXjAikiaFSPaK/FkAQT5UTx3VormQaiZ5hBFlJZ9UFQGB/rwg1MZIhHAG9smMQRTdyJxP6Qt5MwMtdyU5FWrA==} + engines: {node: '>= 20'} + + '@tailwindcss/vite@4.3.3': + resolution: {integrity: sha512-yYU8cogLeSh/ms2jh8Fj7jaba/EWa7Ja6GoUqYZaraEuCI5YS6ms6ObZgjjedm+jm6XZjdNRWBpPP6Z86oOxcw==} + peerDependencies: + vite: ^5.2.0 || ^6 || ^7 || ^8 + + '@tanstack/history@1.162.5': + resolution: {integrity: sha512-w1+YvwmTkwt5n8yUqEH3IWZ9DsmorCZW/EQ3KYHnqEgIkOZpH54NvW6/Epq3Dzb8H0ifIeYX8PExvrNLIH5FIA==} + engines: {node: '>=20.19'} + + '@tanstack/react-router@1.170.45': + resolution: {integrity: sha512-6tuiIAFb82zsk/YxveJRyGjbsm6kIfgUuoH7qCp2R2aSHveW6W0t/6j+Sn4m1iIlA2lLU4cvooqks08/YMOThw==} + engines: {node: '>=20.19'} + peerDependencies: + react: '>=18.0.0 || >=19.0.0' + react-dom: '>=18.0.0 || >=19.0.0' + + '@tanstack/react-start-client@1.168.43': + resolution: {integrity: sha512-XolxHGl5d0uLxVZ4A03iG+dL/xyAFwqbZYXque9iKftN/o/bbQ4ejjgc6yo3+FXb7LBcdjlWLyzy92r1vHFBog==} + engines: {node: '>=22.12.0'} + peerDependencies: + react: '>=18.0.0 || >=19.0.0' + react-dom: '>=18.0.0 || >=19.0.0' + + '@tanstack/react-start-rsc@0.1.64': + resolution: {integrity: sha512-pxiz1O9c1HAo2BwzBuMUjkutKeDYlDlJHOzYrNaj6w4mwokOdN1b9B0myzDxNhnS9Ign0zU12vP9JVr20DUDSQ==} + engines: {node: '>=22.12.0'} + peerDependencies: + '@rspack/core': '>=2.0.0-0' + '@vitejs/plugin-rsc': '>=0.5.30' + react: '>=18.0.0 || >=19.0.0' + react-dom: '>=18.0.0 || >=19.0.0' + react-server-dom-rspack: '>=0.0.2' + peerDependenciesMeta: + '@rspack/core': + optional: true + '@vitejs/plugin-rsc': + optional: true + react-server-dom-rspack: + optional: true + + '@tanstack/react-start-server@1.167.51': + resolution: {integrity: sha512-vITebNqXC3ievzYQr3b4z2jZWpEo95oYPfXP1kBi5OudSbcp2pN2A2/pzDsoJ/ei3oZ2rjEEbnOVrbDSHiO+HA==} + engines: {node: '>=22.12.0'} + peerDependencies: + react: '>=18.0.0 || >=19.0.0' + react-dom: '>=18.0.0 || >=19.0.0' + + '@tanstack/react-start@1.169.3': + resolution: {integrity: sha512-tujqzu41T6c74zMj9c8rUpNOA5MExSHyLxCoE/m7QpfDLzTrloD5TUhk/9Z97c8AM91oFGdsQYN4JC5iUxl6Ow==} + engines: {node: '>=22.12.0'} + peerDependencies: + '@rsbuild/core': ^2.0.0 + '@vitejs/plugin-rsc': '*' + react: '>=18.0.0 || >=19.0.0' + react-dom: '>=18.0.0 || >=19.0.0' + vite: '>=8.0.0' + peerDependenciesMeta: + '@rsbuild/core': + optional: true + '@vitejs/plugin-rsc': + optional: true + vite: + optional: true + + '@tanstack/react-store@0.11.2': + resolution: {integrity: sha512-oj5O5DmiMWE+ih+SioX2ayC1kbK7d3fpLx0B75fPJr9nY3zU+hoW010yr64qXsY/9fyiLVE2bn5mGNV3owm8RQ==} + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + + '@tanstack/router-core@1.171.38': + resolution: {integrity: sha512-XRZVxiO6BIexICmEo3XfPmpoyyLhbjgaMJsONz4gIf5oYys0UiaG1BJGRyj9x8QZPDZcBhvAMuTYN70wSxV0gA==} + engines: {node: '>=20.19'} + + '@tanstack/router-generator@1.167.45': + resolution: {integrity: sha512-oCtNqtsMNcBJkPIOu1O7a68jnxt4TkVJj3jHrW3VgiZdBeaj/lBJQh50yvzmNRswRcyIkRg0g30g25bbLRrAGw==} + engines: {node: '>=20.19'} + + '@tanstack/router-plugin@1.168.47': + resolution: {integrity: sha512-1qvMto2Id0Uulux4qd+WttCbOFloIEQ5x82m68T4knt6NmUDQC66P/u/5yzN0FWGSO0u2U2nbDSIQoR6g7HNmQ==} + engines: {node: '>=20.19'} + peerDependencies: + '@rsbuild/core': '>=1.0.2 || ^2.0.0' + '@tanstack/react-router': ^1.170.45 + vite: '>=5.0.0 || >=6.0.0 || >=7.0.0 || >=8.0.0' + vite-plugin-solid: ^2.11.10 || ^3.0.0-0 + webpack: '>=5.92.0' + peerDependenciesMeta: + '@rsbuild/core': + optional: true + '@tanstack/react-router': + optional: true + vite: + optional: true + vite-plugin-solid: + optional: true + webpack: + optional: true + + '@tanstack/router-utils@1.162.4': + resolution: {integrity: sha512-3TSH3rwAQTqQOtTBF8IXMFXmGNJWnjwIm+l87uguyC/of0pSRKcU9GJrozaf0fY9it8dLQvUZJA2MOlfqbW1sA==} + engines: {node: '>=20.19'} + + '@tanstack/start-client-core@1.170.38': + resolution: {integrity: sha512-XK+HVhXz9Fs7bJAYmsdLccq3lc/85Z83oPt7He7b3BMX6Ejw2/N9JzUeqwcxXtd29SPBRFb5VRMtZf3uu4Tlag==} + engines: {node: '>=22.12.0'} + + '@tanstack/start-fn-stubs@1.162.0': + resolution: {integrity: sha512-QWfUZ3Yo923tdQn38LyKMU8rcTw69zc+T4dAvgTWV4O56SqFRsGfS0lSWIMhJRwXIx/bvdi7nTUBDdZtTHtpTQ==} + engines: {node: '>=22.12.0'} + + '@tanstack/start-plugin-core@1.171.54': + resolution: {integrity: sha512-EQJDF1HC1tIdz0pNey+GI0VWci4GU4zGKM4jTzwbNMQmoqlilFhkNwgrPgUP4TBRtkBbgpuuGlrafChzj66A3w==} + engines: {node: '>=22.12.0'} + peerDependencies: + '@rsbuild/core': ^2.0.0 + vite: '>=8.0.0' + peerDependenciesMeta: + '@rsbuild/core': + optional: true + vite: + optional: true + + '@tanstack/start-server-core@1.169.44': + resolution: {integrity: sha512-xgZfItp1af0zBbR326R54ageMeQwnrZgRrapAc3sO9uMgANdy1rpxwvSPqT5+0T6HQbFQavRPwxydWSxT7Rr6g==} + engines: {node: '>=22.12.0'} + + '@tanstack/start-storage-context@1.167.40': + resolution: {integrity: sha512-xolDIZPyOiAk3XE5m4UICArqwkRNB6z3nr6aAKJphvCM8nzHKlu/laJ+3WtfWFb2iPB9B3K6R/X+fKSoz4OpVA==} + engines: {node: '>=22.12.0'} + + '@tanstack/store@0.11.2': + resolution: {integrity: sha512-sJ4mjol8uQsHV0gOJzzjwXfh2Fwm+Sz0+8deqiTm4jGbMdjzNSW+xZCFm0kUa870uhd8yi+DpKnZb5Kc4apa0Q==} + + '@tanstack/virtual-file-routes@1.162.0': + resolution: {integrity: sha512-uhOeFyxLcU41HzvrxsGpiWdcMbScY1EDgbZ5K7DVRMYInbLYWAC0EA/kx9wXAoSM8q82bUG2hRl8+EAjE6XAbA==} + engines: {node: '>=20.19'} + + '@testing-library/dom@10.4.2': + resolution: {integrity: sha512-yzr2S9HyAIdhz2/6qHgbs665Q7PKVcDF05vsOlHPxG1mo36gKVesdYVeDLnXgfjJ03CrKRk08knc6+E/9m8v2Q==} + engines: {node: '>=18'} + + '@testing-library/react@16.3.3': + resolution: {integrity: sha512-Uo193NgQbPMz6lrrhtRQQFcMC6Re/ELLFbbuVL30WDlZxlpZf9/lMHTAVxPRLw1q1iu9OJmR1c2BLiENRstdBg==} + engines: {node: '>=18'} + peerDependencies: + '@testing-library/dom': ^10.0.0 + '@types/react': ^18.0.0 || ^19.0.0 + '@types/react-dom': ^18.0.0 || ^19.0.0 + react: ^18.0.0 || ^19.0.0 + react-dom: ^18.0.0 || ^19.0.0 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@turbo/darwin-64@2.11.9': + resolution: {integrity: sha512-OkW+EESJjo248CThWe9DfuUqzGcRwHe1DXKWRw9DSZ0lMkocKbbwNMjWVCiO+WNBcARDM0ibu0c9SbuIe4mw6w==} + cpu: [x64] + os: [darwin] + + '@turbo/darwin-arm64@2.11.9': + resolution: {integrity: sha512-NIbFEogMaIyOi2egLH7XtuW0DXmPOpydnanyB3rw/WXCPYl1OAFRPHPGixIaakGnfNLey8LMmKemgNtqtFKdcg==} + cpu: [arm64] + os: [darwin] + + '@turbo/linux-64@2.11.9': + resolution: {integrity: sha512-RkD/Atqqek2WNnYJlmPogZpXjAW+cSsPXDn7E0mufSNN86ClXCSKme/BBYMeIvPoFZ4egPJLF+JpYkuuNkMYhg==} + cpu: [x64] + os: [android, linux] + + '@turbo/linux-arm64@2.11.9': + resolution: {integrity: sha512-iW/0YGS9D9YlgD4ad2IEEolD9PuNJGdkEI650AELLln8YaGsloiH8QyTUnajjxPufMuY/eWRWxO+PMBYsGvVlA==} + cpu: [arm64] + os: [android, linux] + + '@turbo/windows-64@2.11.9': + resolution: {integrity: sha512-rg/kuQmSm9m/z8W5HYHLMSnTbLDXBs/9liVZh9YnfkGYm0DlFj2SV9/0fQy/EpJTq81O36kMb7p8Fmt9f67ocA==} + cpu: [x64] + os: [win32] + + '@turbo/windows-arm64@2.11.9': + resolution: {integrity: sha512-PgjBpLPW/WDsKzeBmNuw2QHtPxT/PtcloN3rHFTqVyMsqkLlyHVJbSusuhYoYFdi08lZ9Stryw66UOuPg/yW0w==} + cpu: [arm64] + os: [win32] + + '@types/aria-query@5.0.4': + resolution: {integrity: sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==} + + '@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/node@24.19.2': + resolution: {integrity: sha512-93d49wCWJkCyN87MxLpNN6KXPCwFw7bVUg79mGUV1OS40JGWwVCr8n61DXCSqz7CV6/VfPkb7xec7uP2M+QHWQ==} + + '@types/react-dom@19.3.0': + resolution: {integrity: sha512-ZI7bU42mZXXKHn/qNLEw2IrbiINU7X5+vfgdixBHkCNpYWXjKgfQ/P+uyGb5CjOLB9UcnTeg3rylQtV2hym44Q==} + peerDependencies: + '@types/react': ^19.3.0 + + '@types/react@19.3.0': + resolution: {integrity: sha512-N0rFCuH9YoxG9/m61l9MfpJKfmLOVU0em7ipIz6TRgSSkvReLB9vL85GB+yr8Bs5leqpvg96JSwF4ZS1s4viQg==} + + '@types/webidl-conversions@7.0.3': + resolution: {integrity: sha512-CiJJvcRtIgzadHCYXw7dqEnMNRjhGZlYK05Mj9OyktqV8uVT8fD2BFOB7S1uwBE3Kj2Z+4UyPmFw/Ixgw/LAlA==} + + '@types/whatwg-url@13.0.0': + resolution: {integrity: sha512-N8WXpbE6Wgri7KUSvrmQcqrMllKZ9uxkYWMt+mCSGwNc0Hsw9VQTW7ApqI4XNrx6/SaM2QQJCzMPDEXE058s+Q==} + + '@typescript/typescript-aix-ppc64@7.0.2': + resolution: {integrity: sha512-MTKKkWB7p/0E9xi1d1tHtZ5PiLkGEMIq88pK2CubZjOsLtYTLqhgIgi6zepFa+9GHZ6h05NMCkQxGKiPXMxXtQ==} + engines: {node: '>=16.20.0'} + cpu: [ppc64] + os: [aix] + + '@typescript/typescript-darwin-arm64@7.0.2': + resolution: {integrity: sha512-gowzar9MwS/aRWp6f3a4KUqzRjAZjOsmGNCM6LcTgXum+dBfgsBVMN+AgvOCCbguXyick6LJhpBszxMebJ8syA==} + engines: {node: '>=16.20.0'} + cpu: [arm64] + os: [darwin] + + '@typescript/typescript-darwin-x64@7.0.2': + resolution: {integrity: sha512-SZ9xZInqApNlNGc9s0W1VSsktYSOe9cFqNOIqmN1Gs8SmkjKZYFt017G4VwPxASInODuAdbTW7sXiFUf893RgA==} + engines: {node: '>=16.20.0'} + cpu: [x64] + os: [darwin] + + '@typescript/typescript-freebsd-arm64@7.0.2': + resolution: {integrity: sha512-W5NH4y/J0plIIS5b2xvTEkU7JFxyqdMAOgf+Ilhl0vHQXKO5dZoxd+C/jEtq56c4F3wk71RB4BMRQ2XdI+bwYQ==} + engines: {node: '>=16.20.0'} + cpu: [arm64] + os: [freebsd] + + '@typescript/typescript-freebsd-x64@7.0.2': + resolution: {integrity: sha512-UMGDx5sTpzNw3WiPebH7l90IWfJggEd+egHt/q6p7/Cm3zqoV7VxkGXt+3DxPIw8CcmvAB0j3sVVfbhX+M4Tpw==} + engines: {node: '>=16.20.0'} + cpu: [x64] + os: [freebsd] + + '@typescript/typescript-linux-arm64@7.0.2': + resolution: {integrity: sha512-Qh4eU4/y3yDjnfjjyPYihMj5/ODIlmt+Bzu17OI+fiSRDW57QmU5SiN63exPRNJPKUzcc1INa1NXdrJ+MqHjUQ==} + engines: {node: '>=16.20.0'} + cpu: [arm64] + os: [linux] + + '@typescript/typescript-linux-arm@7.0.2': + resolution: {integrity: sha512-gffT3xPz9sR7j/YJExkyPntrI0P2EP9XbOyWzth2/Gs0RstK+90RBcO0ncXoXy/beYll1SXw846Nf2zdnEz0QQ==} + engines: {node: '>=16.20.0'} + cpu: [arm] + os: [linux] + + '@typescript/typescript-linux-loong64@7.0.2': + resolution: {integrity: sha512-uEHck9i8hoAzXPiYRib1O7miOnz23SxIeVl6F4LXox+qov1K35jHcEW6VHKvZI+pyvl7fZEP4MCU5LYvIq1GuQ==} + engines: {node: '>=16.20.0'} + cpu: [loong64] + os: [linux] + + '@typescript/typescript-linux-mips64el@7.0.2': + resolution: {integrity: sha512-R4KvAMnE43W5Qeqb0Ly56O3mWMWIAgsMyz36DCaycd5nbg/9kzm0liw3JocfRqyJY0KPmzFjbswozXyW0DnIYA==} + engines: {node: '>=16.20.0'} + cpu: [mips64el] + os: [linux] + + '@typescript/typescript-linux-ppc64@7.0.2': + resolution: {integrity: sha512-DORx5b3sd/4S7eayxm4FQv+A7CrkUIGRaHiwI8oiHTAI1fAPWhF4J0vAlkC8biAlHSVVwxMQ3tjZ2/DVbnQiiA==} + engines: {node: '>=16.20.0'} + cpu: [ppc64] + os: [linux] + + '@typescript/typescript-linux-riscv64@7.0.2': + resolution: {integrity: sha512-wf0jqEDOjrPRnKwYRyyJDRo11KMbvMFrU+q4zqKyChODBzvlkbhNQfKvLxQCcwTpdDaXSHZTVuh0JoCrKCUMHQ==} + engines: {node: '>=16.20.0'} + cpu: [riscv64] + os: [linux] + + '@typescript/typescript-linux-s390x@7.0.2': + resolution: {integrity: sha512-IkwJc3L7yhytWd/ewjyxNDfOmswCm9GWMJT/ue/dU4aZNbwZeYAetq42VyLmsmSjvoX7z74X6ZaYCtzAr0EuGw==} + engines: {node: '>=16.20.0'} + cpu: [s390x] + os: [linux] + + '@typescript/typescript-linux-x64@7.0.2': + resolution: {integrity: sha512-EYdf2cNg7rgCWJnxCdJ+F3V39O8ihb37eHAu1LK8oAFizgTQbPOK7zHHXbPt8rX24COqODXeI3sIf0fCXG7H/A==} + engines: {node: '>=16.20.0'} + cpu: [x64] + os: [linux] + + '@typescript/typescript-netbsd-arm64@7.0.2': + resolution: {integrity: sha512-+polYF4MF04aPpO5FTkHran9yUQDSXqy5GiSDKpsll5jy3l3+g9QLhpf39T+ePtefhXLOGrLl0QIjkQP6VnelA==} + engines: {node: '>=16.20.0'} + cpu: [arm64] + os: [netbsd] + + '@typescript/typescript-netbsd-x64@7.0.2': + resolution: {integrity: sha512-8YIT0EHM/3dq10ZOVF/A7pc/YSMtbcecct4rWtexrnSCHOPcpC2KTLXfTCR6vDpnSiY12heNb1GiN/wu+T/FyA==} + engines: {node: '>=16.20.0'} + cpu: [x64] + os: [netbsd] + + '@typescript/typescript-openbsd-arm64@7.0.2': + resolution: {integrity: sha512-APT8+ClYnuYm1u9+kgGXoMj2VzWzcymwh2gNSQVySHfkRDGOTVkoWLjCmOQSaO+PoqQ57B0flRp9SA+7GnnkzQ==} + engines: {node: '>=16.20.0'} + cpu: [arm64] + os: [openbsd] + + '@typescript/typescript-openbsd-x64@7.0.2': + resolution: {integrity: sha512-yX7s+Q0Dln0Dt9tEzZsAjXXR/+ytBM7AlglaqyeMPxQszJ1JhlJdZ6jLA+IzldHtflX81em7lDao1xXu+aRRkg==} + engines: {node: '>=16.20.0'} + cpu: [x64] + os: [openbsd] + + '@typescript/typescript-sunos-x64@7.0.2': + resolution: {integrity: sha512-dLJDGaLZ1D4HPQn62u1n8mBDkJREwMsAkCdkwd4Ieqw+x3TUyTsqY0YiBCtE6H6OzzgGk3iuZ3vFWRS+E8/d1g==} + engines: {node: '>=16.20.0'} + cpu: [x64] + os: [sunos] + + '@typescript/typescript-win32-arm64@7.0.2': + resolution: {integrity: sha512-Gyl1Vy6OsWesLzmq+EP0Fb7b4Nid5232AvcA2SFcdYreldpNtYFFofPjnt62y9hQy7VTaZp65ICJjuAQRaVcIQ==} + engines: {node: '>=16.20.0'} + cpu: [arm64] + os: [win32] + + '@typescript/typescript-win32-x64@7.0.2': + resolution: {integrity: sha512-0BQ3HkAHHlKLSp1qRvf3SUhGpGsDuhB/jgFw75guyqbxJqEaS0Cw/VFO8i2nHglJUzQCRtMMR/IBAKE3ETMC4g==} + engines: {node: '>=16.20.0'} + cpu: [x64] + os: [win32] + + '@vitejs/plugin-react@6.1.2': + resolution: {integrity: sha512-fhJNGUdscQa4HkI0xFxwonWyhnVReCPDbXI7FH7jmzpnVCrFQI7PRrhWecO263610vOrs9tr2Y4xcf8uAdFxbw==} + engines: {node: ^20.19.0 || >=22.12.0} + peerDependencies: + '@rolldown/plugin-babel': ^0.1.7 || ^0.2.0 + babel-plugin-react-compiler: ^1.0.0 + oxc-transform-react: ^0.152.0 + vite: ^8.0.0 + peerDependenciesMeta: + '@rolldown/plugin-babel': + optional: true + babel-plugin-react-compiler: + optional: true + oxc-transform-react: + optional: true + + '@vitest/mocker@5.0.5': + resolution: {integrity: sha512-xLL3lkDegJZw+MGoGaCCsFayDZthGgpAtr3Vziyfc4p7xH89K7KRPcRBBh/kEYm0Aqkt5DtTmkYpBtRV/FrHZg==} + peerDependencies: + msw: ^2.4.9 || ^3.0.0 + vite: ^6.0.0 || ^7.0.0 || ^8.0.0 + peerDependenciesMeta: + msw: + optional: true + vite: + optional: true + + '@vitest/spy@5.0.5': + resolution: {integrity: sha512-lwJRExuH417257Q5wv9QYugN9IMJkoxcrKrYxGPQkBzl7wlNpTUxD/5yNX4ESKVUIShKPgkGchYPFMWOOk0wzw==} + + ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + + ansi-styles@5.2.0: + resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} + engines: {node: '>=10'} + + ansis@4.4.0: + resolution: {integrity: sha512-9k3v7xcHwgdO/DruxGIg4HtjvlAZlcnsX/mzqUb1t3NkYnl9kK2UJ+Gq0io+vQf7iT//BD/HB/NBkUR1LWxoeA==} + engines: {node: '>=14'} + + argparse@2.0.1: + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + + argparse@3.0.3: + resolution: {integrity: sha512-Sn98ftV3KfsO8xfLPHG6oT8y+b0yvbrLgZjgPDXsharNY15tTAjqIsIju4S32nl6/iEUNNE4v+yL2Zhm8ooP3w==} + + aria-hidden@1.2.6: + resolution: {integrity: sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA==} + engines: {node: '>=10'} + + aria-query@5.3.0: + resolution: {integrity: sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==} + + assertion-error@2.0.1: + resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} + engines: {node: '>=12'} + + babel-dead-code-elimination@1.0.12: + resolution: {integrity: sha512-GERT7L2TiYcYDtYk1IpD+ASAYXjKbLTDPhBtYj7X1NuRMDTMtAx9kyBenub1Ev41lo91OHCKdmP+egTDmfQ7Ig==} + + baseline-browser-mapping@2.11.29: + resolution: {integrity: sha512-YeesxhUmR4h5y5V8KF8iBCqJb8YFrBJ++XBTeGcWIaQOYXGN19JM0FoiOjAhwuDoln8owMgXcWBmgHtYSkky2w==} + engines: {node: '>=6.0.0'} + hasBin: true + + bidi-js@1.1.0: + resolution: {integrity: sha512-fX1Onk0tdVPC7obPWB5EbJ1z7NVhLq4m2xZLq2YXBkxzMXIGRpNMU88n0EPgWseKl12J7zXs7qrDxPK4sRs2fg==} + + browserslist@4.29.3: + resolution: {integrity: sha512-1R4kiYKXGViqEN0CnoDrXc1StD9niAwu+j2dukWzrD4bJgsD4lDmEp0CRbc6E/vYJIfTHwPmwyaKtVSudICdPA==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + hasBin: true + + bson@7.3.3: + resolution: {integrity: sha512-oz3LwE3qGEhTCSyhzQRLY3Bj1NLOsjFMf6tcmY5J8M+3R7EVcmoBfSHWvjUK3yXCLDUsGpIuB3aQL4nDZ1EV/g==} + engines: {node: '>=20.19.0'} + + caniuse-lite@1.0.30001816: + resolution: {integrity: sha512-+8Yx7BXCoqk6IF8yTicjfUR6D/ldJzdlsodlEOiOSPmhK844WIgk67/zIQaGAOxNkZyyvBlrRFnLvqKIoqbAFw==} + + chai@6.3.0: + resolution: {integrity: sha512-XWAtwJ6OHO+tj0EKCs0Y2UamnyOxseZWltU4x2U2wh8g4AigdjwvtUjvLP2tqkA/avxHEtzxNaqGq/YGNwckKg==} + engines: {node: '>=18'} + + chardet@2.2.0: + resolution: {integrity: sha512-rddelWYNPRrXq6PtNEN2S3f6t9ILzvqaN5pVgi4kqt9jHQaXIial9PznB5iSPVlQSLNaaH22ItWz3EJtQ10+OA==} + + chokidar@5.0.0: + resolution: {integrity: sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==} + engines: {node: '>= 20.19.0'} + + class-variance-authority@0.7.1: + resolution: {integrity: sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg==} + + cli-width@4.1.0: + resolution: {integrity: sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==} + engines: {node: '>= 12'} + + clsx@2.1.1: + resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==} + engines: {node: '>=6'} + + cn@0.5.0: + resolution: {integrity: sha512-JGEixZEpfFXm1P5uXwvEobOFLlHwIWi5v4tjd1ZwfiYmcEilkuD2l+054rvJcYCR1B+uVThHeUbgmNz1FwuxuA==} + engines: {node: '>=22'} + hasBin: true + + consola@3.4.2: + resolution: {integrity: sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==} + engines: {node: ^14.18.0 || >=16.10.0} + + convert-source-map@2.0.0: + resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} + + cookie-es@3.1.1: + resolution: {integrity: sha512-UaXxwISYJPTr9hwQxMFYZ7kNhSXboMXP+Z3TRX6f1/NyaGPfuNUZOWP1pUEb75B2HjfklIYLVRfWiFZJyC6Npg==} + + crossws@0.4.15: + resolution: {integrity: sha512-NsUOpDZosz7nyI+qEIl05yaiXOWaXH2oTeM+XBWtiSWZtb5rzcIsl1AST/HzM2jzUn76eFuyrkn83E6iSBRUvw==} + peerDependencies: + srvx: '>=0.11.5' + peerDependenciesMeta: + srvx: + optional: true + + css-tree@3.2.1: + resolution: {integrity: sha512-X7sjQzceUhu1u7Y/ylrRZFU2FS6LRiFVp6rKLPg23y3x3c3DOKAwuXGDp+PAGjh6CSnCjYeAul8pcT8bAl+lSA==} + engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0} + + csstype@3.2.3: + resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==} + + data-urls@8.0.0: + resolution: {integrity: sha512-JQUCCK+/CAGbGGx618PlFZMXH81Jtj7t73CHv9dd/zVWvxgGT2zLFRjnKb+Ng46GIwcy+f7f88qd4duqllK+WQ==} + engines: {node: ^22.14.0 || >=24.0.0} + + db0@0.4.1: + resolution: {integrity: sha512-6RBY/bSn42UrqATwsiULj2uYFyEykB3XeA/NLIVQeHNXlYV6D4Idxx3/aa6k5Y45Dwzx7sygeLotnqHWSeURYA==} + + debug@4.4.3: + resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + decimal.js@10.6.0: + resolution: {integrity: sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==} + + dequal@2.0.3: + resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} + engines: {node: '>=6'} + + detect-libc@2.1.2: + resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==} + engines: {node: '>=8'} + + detect-node-es@1.1.0: + resolution: {integrity: sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==} + + diff@9.0.0: + resolution: {integrity: sha512-svtcdpS8CgJyqAjEQIXdb3OjhFVVYjzGAPO8WGCmRbrml64SPw/jJD4GoE98aR7r25A0XcgrK3F02yw9R/vhQw==} + engines: {node: '>=0.3.1'} + + dom-accessibility-api@0.5.16: + resolution: {integrity: sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==} + + electron-to-chromium@1.5.459: + resolution: {integrity: sha512-4SC9HHSFjO/liAhifpdOL5hG9b4BP7/5G3y3UPZVO8trlAXr1CaUEEJL0gWK3kOcYcZrOA5rkwG45Gra/lTIgg==} + + enhanced-resolve@5.26.0: + resolution: {integrity: sha512-9vhedylFonb2YGogzUKX6+Ja72gOJbN1QHAqdrvqLwhdl/QWbKopzoUC9EbQNVsAns/bx/4uyqalrQAoy1IByw==} + engines: {node: '>=10.13.0'} + + entities@8.1.0: + resolution: {integrity: sha512-kxL7msIffSuh9aaFAMD7rxAIuTRMAHMeBtgHW2yUdWw732ZNh4MehkF2gdjvtdmikkaIP9bFDDJOPlsvm7avrA==} + engines: {node: '>=20.19.0'} + + env-runner@0.2.3: + resolution: {integrity: sha512-S8EFBKyznRwPVwayK187cYjvnpgC92xy+q0BIF++V965pfjMVVRbQ/HoTYGA/1EHmZ7E68k6Heq+4WnvVhOL5w==} + hasBin: true + + es-module-lexer@2.3.2: + resolution: {integrity: sha512-poHGpORABojJJucnV9KbOavETW8lBVnphkW77ER5/BQ5Fz7oXSoCNek7IH3vR5nRjdsEz926ibFYX8KtLQmdyw==} + + esbuild@0.28.2: + resolution: {integrity: sha512-HKVLS8dvII+xoKW9kmqxbRKrnWEXfJJr/FZhhJmiqIB0e053QNYFqOBouTMO/k5sID4MvCiUCvv8b9M4h32wIA==} + engines: {node: '>=18'} + hasBin: true + + escalade@3.2.0: + resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} + engines: {node: '>=6'} + + estree-walker@3.0.3: + resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} + + expect-type@1.4.0: + resolution: {integrity: sha512-KfYbmpRm0VbLjEvVa9yGwCi9GI34xvi7A/HXYWQO65CSD2u3MczUJSuwXKFIxlGsgBQizV9q5J9NHj4VG0n+pA==} + engines: {node: '>=12.0.0'} + + exsolve@1.1.3: + resolution: {integrity: sha512-kuzL9zherLQoqDeQaS55AiiIg1kb4KYXaSusTtgZTPlvKP2gGCI82LNmBNh5RjDVUXIcmgx+/Mx7vPwRzBbhJA==} + + fast-string-truncated-width@3.0.3: + resolution: {integrity: sha512-0jjjIEL6+0jag3l2XWWizO64/aZVtpiGE3t0Zgqxv0DPuxiMjvB3M24fCyhZUO4KomJQPj3LTSUnDP3GpdwC0g==} + + fast-string-width@3.0.2: + resolution: {integrity: sha512-gX8LrtNEI5hq8DVUfRQMbr5lpaS4nMIWV+7XEbXk2b8kiQIizgnlr12B4dA3ZEx3308ze0O4Q1R+cHts8kyUJg==} + + fast-wrap-ansi@0.2.2: + resolution: {integrity: sha512-7F2Fl+TjRSenLqlU3UjSH0iyqopqoZIu7eZVpEirP2g1GtWa2G/ecEmBdgz31+Mxr+ELclgg6sokpSFIQiZ02Q==} + + fdir@6.5.0: + resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==} + engines: {node: '>=12.0.0'} + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true + + fetchdts@0.2.0: + resolution: {integrity: sha512-PJb4ZTGT2/wK78RmVrxZITStWabhZlKBsL52VOgq+c7clEkdHdEB+0rtzrXCbZJqeYJj+IwNWYqB5/G6vouA6A==} + + fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + + gensync@1.0.0-beta.2: + resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} + engines: {node: '>=6.9.0'} + + get-nonce@1.0.1: + resolution: {integrity: sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==} + engines: {node: '>=6'} + + graceful-fs@4.2.11: + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + + h3@2.0.3: + resolution: {integrity: sha512-4vCJUR90OSGLITLit4WWpB4cj0rzd5eM8w3CHmi4ulh3LdaUICYy3FIaGpBibgtt+AB3cDiyql3ApgcLRGrClA==} + engines: {node: '>=20.19.0'} + hasBin: true + peerDependencies: + crossws: ^0.4.12 + ocache: '>=0.3.0' + peerDependenciesMeta: + crossws: + optional: true + ocache: + optional: true + + hookable@6.1.2: + resolution: {integrity: sha512-+abwxtiEA52GCVIsQqut3S/uKTbUwYIp4Pe/vv+6py5XiXBCqMZHg6pA6Y5qhgLSEys0/cYuPbO0z1QFj5ZCmg==} + + html-encoding-sniffer@7.0.0: + resolution: {integrity: sha512-UikN5yr7xsCDAq87Or5or0PAlD3HJJOKVzM05az588WnpDJ4Ux7a2A53Qi6gofGg2/EtvF/H4hCi/TXfCW4Y6w==} + engines: {node: ^22.13.0 || >=24.0.0} + + httpxy@0.5.5: + resolution: {integrity: sha512-uDjmnPyp1q4Sgzf3w+J/Fc6UqcCEj0x4Wjp7OqK5dGhNeDgpyrAmnS6ey8QWrX3SWDon2DMKf9sBa5X9+CVyMA==} + + iconv-lite@0.7.3: + resolution: {integrity: sha512-IKXpvIzjnC9XTAUbVBcMfGS0EPaIXtW6v+zr+RRp+hqULEpo0owZax6wyRwPOJbWbzjYspQwusTsfVr0ifh4uQ==} + engines: {node: '>=0.10.0'} + + is-potential-custom-element-name@1.0.1: + resolution: {integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==} + + isbot@5.2.2: + resolution: {integrity: sha512-iQcBXcd+Rv/pkubRyGh2utW2j1oPG5hZY6TUhVPpqK4G+o3IbxpJNx04hgksjc/N7GK5pEorUxDeg31cFgEk/w==} + engines: {node: '>=18'} + + jiti@2.7.0: + resolution: {integrity: sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==} + hasBin: true + + js-tokens@4.0.0: + resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + + js-yaml@4.3.2: + resolution: {integrity: sha512-SFNOvSJ+Dgf/9An904Yx+CgSlIPCkIpao4qo51lpee25TIRejdH3rhR4EZMGoNx3/TP3O+wzWuiTFl4sqbltzA==} + hasBin: true + + jsdom@30.1.3: + resolution: {integrity: sha512-hQMUPvRgN7KxsfIytDQji7bimuJeRQa6Qo5+iuiZQk5CafeRxLIA10/cG5YCBFNpD9RO3oqIiN4CO1Y44kxqXg==} + engines: {node: ^22.22.2 || ^24.15.0 || >=26.0.0} + peerDependencies: + canvas: ^3.2.3 + peerDependenciesMeta: + canvas: + optional: true + + jsesc@3.1.0: + resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==} + engines: {node: '>=6'} + hasBin: true + + json5@2.2.3: + resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} + engines: {node: '>=6'} + hasBin: true + + lightningcss-android-arm64@1.32.0: + resolution: {integrity: sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [android] + + lightningcss-android-arm64@1.33.0: + resolution: {integrity: sha512-gEpRTalKdosp4Bb8qWtc2iOgE5SeIHlpS1up9bFq2wAyYhl1UdTObYiHe98zEM9SQvSoqQZ1IQD0JNpg3Ml5pg==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [android] + + lightningcss-darwin-arm64@1.32.0: + resolution: {integrity: sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [darwin] + + 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.32.0: + resolution: {integrity: sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + 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.32.0: + resolution: {integrity: sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [freebsd] + + 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.32.0: + resolution: {integrity: sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==} + engines: {node: '>= 12.0.0'} + cpu: [arm] + os: [linux] + + 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.32.0: + resolution: {integrity: sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + + lightningcss-linux-arm64-gnu@1.33.0: + resolution: {integrity: sha512-j2v/itmy4HlNxlc6voKXYgBqNi0Ng2LShg4z7GufpEgs05P+2suBVyi9I6YHq5uoVFx9ETin3eCEhLVyXGQnKg==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + + lightningcss-linux-arm64-musl@1.32.0: + resolution: {integrity: sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + + lightningcss-linux-arm64-musl@1.33.0: + resolution: {integrity: sha512-yiO5ROMuYQgXbC60yjZU5CYSFZGKXL0HFATXt9mHJn1+zW55oCtMI9NfcVhYLMFDL7gV7oBPon/EmMMGg2OvtQ==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + + lightningcss-linux-x64-gnu@1.32.0: + resolution: {integrity: sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + + lightningcss-linux-x64-gnu@1.33.0: + resolution: {integrity: sha512-ar+Ju7LmcN0Jo4FpL4hpFybwNG9/3A/Br5KW2n2jyODg3MEZXaDYADdemoNS+BDNfMgKvylJLj4S5tyRActuAg==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + + lightningcss-linux-x64-musl@1.32.0: + resolution: {integrity: sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + + lightningcss-linux-x64-musl@1.33.0: + resolution: {integrity: sha512-RYiYbkokw0trfKqqzfF55lginwEPrD3OJDfTuJzFs1MK6iFnDenaz1fqLLtX4ITG3OktJQXOeTaw1awrBAlZPw==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + + lightningcss-win32-arm64-msvc@1.32.0: + resolution: {integrity: sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [win32] + + 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.32.0: + resolution: {integrity: sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + 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.32.0: + resolution: {integrity: sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==} + engines: {node: '>= 12.0.0'} + + lightningcss@1.33.0: + resolution: {integrity: sha512-WkUDrojuJs0xkgGf2udWxa3yGBRxPtxUkB79i6aCZLRgc7PM8fZe9TosfPDcvEpQZbuFASnHYmRLBLUbmLOIIA==} + engines: {node: '>= 12.0.0'} + + linkify-it@6.1.0: + resolution: {integrity: sha512-wJ/TwpSDTLepCrQoYWYIExIKg5Zchex2Nn5yk2mFnB+6PtdkHtyLx742md9csRjjOnGkKIS/RrbY7l8D6gT9Vw==} + + lru-cache@11.5.3: + resolution: {integrity: sha512-U4N8FgzmWxc8k1VH8Kr6lQg18U7Fjvby6wXHVRX/ZZ7IwWbRMgrRbP0Wrb5q5NVinryp4SQampHKdvtecItxUg==} + engines: {node: 20 || >=22} + + lru-cache@5.1.1: + resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} + + lz-string@1.5.0: + resolution: {integrity: sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==} + hasBin: true + + magic-string@0.30.21: + resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} + + magic-string@1.4.3: + resolution: {integrity: sha512-z12OxmaPGE0F4xlpGdjuAUckipLpQlTAuAmyGhNoD7ODpYUzvDfvtxUbjM/jwznyP178oju/KDdyi220wNJ0RQ==} + + markdown-it@15.0.2: + resolution: {integrity: sha512-q4IGxMv56jCqT4OCRCADBoDP3LO4MhmTXjFbphHPXs4g3j9Xg5RDnxqN8IF/3vIWEU+VCnUq+7JUg/cfy2E6Qw==} + hasBin: true + + mdn-data@2.27.1: + resolution: {integrity: sha512-9Yubnt3e8A0OKwxYSXyhLymGW4sCufcLG6VdiDdUGVkPhpqLxlvP5vl1983gQjJl3tqbrM731mjaZaP68AgosQ==} + + mdurl@2.1.0: + resolution: {integrity: sha512-1+HBaOx0zi/dQWht8rNv9MYf9qqpqL/kxI0hXImU6Y547zM6Sni8BQibt7ifgMcYtQg41ao3Ivd6cnSM86inpg==} + + memory-pager@1.5.0: + resolution: {integrity: sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==} + + mongodb-connection-string-url@7.0.2: + resolution: {integrity: sha512-ZoS07RoFqpKYQwAk59qmrx8+jJHNHU30UjlU96QktiGn1ltvDr+vCznLX5DiUBLEpMAHatHNWV1nM/74ul66kA==} + engines: {node: '>=20.19.0'} + + mongodb@7.7.0: + resolution: {integrity: sha512-XG1xXEqyouAV8GCb3PuRaujofeXKpAJAPvXYWZgHl6Dz4QHSJ1nRLl0+GpqaLTwKvC0RFE9truOur34RNFY1nw==} + engines: {node: '>=20.19.0'} + peerDependencies: + '@aws-sdk/credential-providers': ^3.806.0 + '@mongodb-js/zstd': ^7.0.0 + gcp-metadata: ^7.0.1 + kerberos: ^7.0.0 + mongodb-client-encryption: ^7.2.0 + snappy: ^7.3.2 + socks: ^2.8.6 + peerDependenciesMeta: + '@aws-sdk/credential-providers': + optional: true + '@mongodb-js/zstd': + optional: true + gcp-metadata: + optional: true + kerberos: + optional: true + mongodb-client-encryption: + optional: true + snappy: + optional: true + socks: + optional: true + + ms@2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + + mute-stream@3.0.0: + resolution: {integrity: sha512-dkEJPVvun4FryqBmZ5KhDo0K9iDXAwn08tMLDinNdRBNPcYEDiWYysLcc6k3mjTMlbP9KyylvRpd4wFtwrT9rw==} + engines: {node: ^20.17.0 || >=22.9.0} + + nanoid@3.3.20: + resolution: {integrity: sha512-uKdg2G3GNCKQn9byYOpxbGqrT2fGO5KRt5J/8b3pok8rT6qxGWF6hxMyJiEYtAf+FVyYuD9hRaDqX5uPFYJ4ZQ==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + + nf3@0.3.24: + resolution: {integrity: sha512-HxLK4bo+5jNsEETZp4w3tJblHOA9MCBY14IN9nZJJV8JDxt9yNIYxuBuLMjTAR5GFa3HL61+8VQDUrXv3/C8fw==} + + nitro@3.0.260903-beta: + resolution: {integrity: sha512-54gANPi62O8rfMvepiJUVuIzEIinYfpeHbebywlLxvVTgIYXDwSvpaU9Id+0sJOBjBx0wC1/CVYXJkH7SY+l0g==} + engines: {node: ^20.19.0 || >=22.12.0} + hasBin: true + + node-releases@2.0.59: + resolution: {integrity: sha512-5qr2okC4ItAI0hG5SaV0HoYMpnM/Y6+Oqr7AmPYy/2uEoGvS+GbSKLeRxSS1uAdu59yz0ouzcuXievSgg///WA==} + engines: {node: '>=18'} + + obug@3.0.0: + resolution: {integrity: sha512-5vvB5+W7ePv+p3uqxi+RcW1XAzLW0/hxt3/4X4Lc4qHudzOhmBiBwOY6DRob4WnanAEGvNcLjF+KNOufrUoEQw==} + engines: {node: '>=12.20.0'} + + ocache@0.3.0: + resolution: {integrity: sha512-RS/9P0zeBb0gDJmadGERLH8lZNXK7xbufTDhclkXGvFGTsj0G4M5/cLk+mizcERH29mLXNnocfB5wjcK70wGJg==} + + parse5@8.0.1: + resolution: {integrity: sha512-z1e/HMG90obSGeidlli3hj7cbocou0/wa5HacvI3ASx34PecNjNQeaHNo5WIZpWofN9kgkqV1q5YvXe3F0FoPw==} + + pathe@2.0.3: + resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} + + picocolors@1.1.1: + resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} + + picomatch@4.0.7: + resolution: {integrity: sha512-qcJu88Q2IWqJsDD529JKMdwGm/dvInW4HvQnRwiH9JtihJvzGOscDtHE3x1pBKeUOTysQ8kVmLnJ2kJu7yhcGA==} + engines: {node: '>=12'} + + postcss@8.5.30: + resolution: {integrity: sha512-zkd+e9S1AQHhmaBKye9zlFHWjOwVgqXl1q3ECYy8561K7qxR2cREf/STLskulBFd78k6AOFeA+ff1TtEzk9bAA==} + engines: {node: ^10 || ^12 || >=14} + + prettier@3.9.10: + resolution: {integrity: sha512-skGHTH1Yb9QvaTC4hWnRTzEYtCpApF0UMBPz+t/0ZPzP8ihefo/btKd+QA7pUE0fEwA1SbS/NmhyEcstdXOIdA==} + engines: {node: '>=14'} + hasBin: true + + pretty-format@27.5.1: + resolution: {integrity: sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + + punycode.js@2.3.1: + resolution: {integrity: sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==} + engines: {node: '>=6'} + + punycode@2.3.1: + resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} + engines: {node: '>=6'} + + radix-ui@1.8.1: + resolution: {integrity: sha512-HPfpVGizO9xANlsFSauruLhRe/3+iOt3vPX0MXYle/UQi3gorQrSYtBcdiv0BZYewcl2rvL59qrIuLFMGAmUrw==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + react-dom@19.3.1: + resolution: {integrity: sha512-Y0bARz53lhEC1NMCASs0/j+faB/zqt3R8hpvg1e8+61ZVJ4UL0UdC4cBbXfZMcIuhrfgeILTLe+ZeBCavQPtKQ==} + peerDependencies: + react: ^19.3.1 + + react-is@17.0.2: + resolution: {integrity: sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==} + + react-remove-scroll-bar@2.3.8: + resolution: {integrity: sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q==} + engines: {node: '>=10'} + peerDependencies: + '@types/react': '*' + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + peerDependenciesMeta: + '@types/react': + optional: true + + react-remove-scroll@2.7.2: + resolution: {integrity: sha512-Iqb9NjCCTt6Hf+vOdNIZGdTiH1QSqr27H/Ek9sv/a97gfueI/5h1s3yRi1nngzMUaOOToin5dI1dXKdXiF+u0Q==} + engines: {node: '>=10'} + peerDependencies: + '@types/react': '*' + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + react-style-singleton@2.2.3: + resolution: {integrity: sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ==} + engines: {node: '>=10'} + peerDependencies: + '@types/react': '*' + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + react@19.3.1: + resolution: {integrity: sha512-QNhWdt7nrgVWWQG58QuGsAR3jv3Hbe4mb4vz7w2csnHavciZJgda1CPNaldF6eVxv90ud3jUXpKlHL69gO38yw==} + engines: {node: '>=0.10.0'} + + readdirp@5.1.1: + resolution: {integrity: sha512-Kko+Y5XQ6fM+Ce3dq3m9YGxnacYZYl9cA1wZjaF3Vbry2L3i1qVg8+CAgNPsXRArPMUMCaOR7oa9Nqntc43JKA==} + engines: {node: '>= 20.19.0'} + + require-from-string@2.0.2: + resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} + engines: {node: '>=0.10.0'} + + rolldown@1.2.14: + resolution: {integrity: sha512-eTBTTqMR6uHKLgcUqpJP8ntzDI6V4LYA8negAMBEI7gkgVvOdrx6VsvS2Ym+83KhOPdLCHWJu0w7UQFJZhHKNw==} + engines: {node: ^20.19.0 || >=22.12.0} + hasBin: true + + rou3@0.9.2: + resolution: {integrity: sha512-3SOzvaAg8rkHrXtRjpCvCvbyO5to9oOO27Z/XqHEYXfMRVSw/qMIVdmaOk9W2lcRLtR6dlqTjo9hDeJk70QBYQ==} + + rou3@1.0.0: + resolution: {integrity: sha512-ySeaQkSrua+ut9g+65I7FHqOFBaY8tV0FmccXItoq0q21se32Q3u4YiW7/RqXSosWgYJaaKwRHXy3BST9PeCNQ==} + engines: {node: '>=20.19.0'} + + safer-buffer@2.1.2: + resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + + saxes@6.0.0: + resolution: {integrity: sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==} + engines: {node: '>=v12.22.7'} + + scheduler@0.28.0: + resolution: {integrity: sha512-juorfCmIkIw8tT+p5BXSm6PJjQF/ycEYmKyzURCIt/RaZIhL+PulbQ9Yu2z1HdOJDdqDTlxA1+xKBmHXJsczAw==} + + semver@6.3.1: + resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} + hasBin: true + + seroval-plugins@1.6.9: + resolution: {integrity: sha512-kiDK/Tb8IWZ61WEU8pA2PDmAuw37gKph9Y77OZlD56mg0Y2g0Bg7gZ1HeHhs5d40w+nRoUq/wj08V26ilbez9g==} + engines: {node: '>=10'} + peerDependencies: + seroval: ^1.0 + + seroval@1.6.9: + resolution: {integrity: sha512-UeEzHwAK+yl0YLbsvROV1t5yMYEwZZ0CfKYxDvUgS2fO9Vxdf8djqVIB+OuVpuawRNPqw68LE1Du/GMsW2ZPqA==} + engines: {node: '>=10'} + + signal-exit@4.1.0: + resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} + engines: {node: '>=14'} + + source-map-js@1.2.2: + resolution: {integrity: sha512-KGj/8Y43x35aZVDtt+J4mK1hoLGHULMYfSkODJNQjNDC3oW1PqPoxMwo0pLUsWM/UEGzON/NxeHywEfNXNP3Vw==} + engines: {node: '>=0.10.0'} + + source-map@0.7.6: + resolution: {integrity: sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==} + engines: {node: '>= 12'} + + sparse-bitfield@3.0.3: + resolution: {integrity: sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==} + + srvx@1.0.6: + resolution: {integrity: sha512-QeTKgAhk8OSsfeq60bl3wuVs9PmBftzmk7owBInA/F1YQne+TRw0UcPymNpURldAmx8hfmM2PNNGH/zgo3GpLA==} + engines: {node: '>=20.16.0'} + hasBin: true + + std-env@4.3.0: + resolution: {integrity: sha512-OtU/EgQ1kIm5KwqQpBC6ZEMXrZRui11w8zgfTWp8cdO9B8OaPsbA8bTHO2P+HNo1VlUTGMVBwPhydu6poeXiag==} + + tailwindcss@4.3.3: + resolution: {integrity: sha512-gOhV3P7ufE62QDGg1zVaTgCR+EtPv92k2nIhVcVKcLmxT1sUBsQGhnZj175j+MqRt4zLF7ic+sCYjfhxMxj7YQ==} + + tapable@2.3.3: + resolution: {integrity: sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==} + engines: {node: '>=6'} + + tinybench@6.2.2: + resolution: {integrity: sha512-nIZ2N2dFpjBsg2hgitKu7mA+FvsIJuGJOwysRngmVRRmWgR/UyPjwJj8c/fT/dhm8EkHnF5EOogRf+0Z2qrimA==} + engines: {node: '>=20.0.0'} + + tinyexec@1.3.1: + resolution: {integrity: sha512-GCvB3aoys96IuDFBMcTB46JOR6mdMtAToqwiW8JlWhsoh1mhHi/xn9ss/Dg7N555GiJyEt2qzoG/NHCwM6h1EA==} + engines: {node: '>=18'} + + tinyglobby@0.2.17: + resolution: {integrity: sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==} + engines: {node: '>=12.0.0'} + + tldts-core@7.4.18: + resolution: {integrity: sha512-KI2PKvCmvQI/xD6ypPqkU0i7oxNXR/O58RLRaHR4svsgVUQ2JE/XC8BtMbG6PSehD27I8sZJRcC1ASnCy6lp3g==} + + tldts@7.4.18: + resolution: {integrity: sha512-somxA8xKAUzlAxl0TX/jMSYIbRNFIVGnI96pVGJPeMc5BsHmfVXn6mOJT6U++ELnl04eGfzpfcEuZe8WiASkXg==} + hasBin: true + + tough-cookie@6.0.2: + resolution: {integrity: sha512-exgYmnmL/sJpR3upZfXG5PoatXQii55xAiXGXzY+sROLZ/Y+SLcp9PgJNI9Vz37HpQ74WvDcLT8eqm+kV3FzrA==} + engines: {node: '>=16'} + + tr46@5.1.1: + resolution: {integrity: sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw==} + engines: {node: '>=18'} + + tr46@7.0.0: + resolution: {integrity: sha512-BcDSDW+SIGWVOns1Zm6Yg91q9AEj7eaID0QDY9oIqJD1A8dscNwMcl9Sms2DeuWCNov1X0/oXanHGYQBSLwZsg==} + engines: {node: ^22.14.0 || >=24.0.0} + + tslib@2.8.1: + resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} + + tsx@4.23.15: + resolution: {integrity: sha512-Yiex1Ovn8z2xPpOWckIiysV1SSyRMY9BkLF++q0yKiDxCqRhosKfMg3janKkiLBwZ5c/YryloKwGZcrEmtwxKw==} + engines: {node: '>=18.0.0'} + hasBin: true + + turbo@2.11.9: + resolution: {integrity: sha512-k2ev5dv9OgP2pJwaPuydkZdid+haX2U5TDGcPtpAz0gb0nbRR3eXY/cpfrlvHih52YRTxWIcRVKc0ri3C2Scrg==} + hasBin: true + + typescript@7.0.2: + resolution: {integrity: sha512-8FYau96o3NKOhbjKi/qNvG/W5jhzxkbdm5sj9AbZ/5T5sWqn3hJgLfGx27sRKZWTvyzCP8dLRBTf5tBTSRVUNA==} + engines: {node: '>=16.20.0'} + hasBin: true + + uc.micro@3.0.0: + resolution: {integrity: sha512-U3PppEkleoTnIfi8BozMx3yju3qc/L6SwqWo2Sw+54PX+PX0q9I+r1Um5HCmqD7n9VDX5/v3vQH/AjA6deDdtw==} + + ufo@1.6.4: + resolution: {integrity: sha512-JFNbkD1Svwe0KvGi8GOeLcP4kAWQ609twvCdcHxq1oSL8svv39ZuSvajcD8B+5D0eL4+s1Is2D/O6KN3qcTeRA==} + + undici-types@7.24.6: + resolution: {integrity: sha512-WRNW+sJgj5OBN4/0JpHFqtqzhpbnV0GuB+OozA9gCL7a993SmU+1JBZCzLNxYsbMfIeDL+lTsphD5jN5N+n0zg==} + + undici@8.12.2: + resolution: {integrity: sha512-XtuDWVdqTLr3NAxm2ly9/hU6kUsJOgGh1RASzMBbsw6aWCOaQzHdW+QQDfdERjfJ2V5vL5pRPa4RetO9UfivDg==} + engines: {node: '>=22.19.0'} + + unenv@2.0.0-rc.24: + resolution: {integrity: sha512-i7qRCmY42zmCwnYlh9H2SvLEypEFGye5iRmEMKjcGi7zk9UquigRjFtTLz0TYqr0ZGLZhaMHl/foy1bZR+Cwlw==} + + unplugin@3.4.0: + resolution: {integrity: sha512-9skdIFlCsPdFV7wUfZxNsFInlW+7nJmGu2gkTu0OUhF56aXGsHab9x52/QhdJ4lC7ZDPWTxbiC4ANqVlsuaW3w==} + engines: {node: ^20.19.0 || >=22.12.0} + peerDependencies: + '@farmfe/core': '*' + '@rsbuild/core': '*' + '@rspack/core': '*' + bun-types-no-globals: '*' + esbuild: '*' + rolldown: '*' + rollup: '*' + unloader: '*' + vite: '*' + webpack: '*' + peerDependenciesMeta: + '@farmfe/core': + optional: true + '@rsbuild/core': + optional: true + '@rspack/core': + optional: true + bun-types-no-globals: + optional: true + esbuild: + optional: true + rolldown: + optional: true + rollup: + optional: true + unloader: + optional: true + vite: + optional: true + webpack: + optional: true + + unstorage@2.0.0-alpha.11: + resolution: {integrity: sha512-4rDO/NjgnkbVvWAPpxugX7YI/xVpC74NLrmAbH6I0D4hcSVq/1m5q2pSfQjP/ABs+7EsRtP/ZjyYMD9bEBgeTw==} + + update-browserslist-db@1.3.4: + resolution: {integrity: sha512-t8wonIOdQyOjtPd2VktlBu6QjTVTks6v8bSi7kd0r2Vll8TK1JYDZtRRdbmCHOAMphkZgrzK+L+vXK4pyZ8t4A==} + hasBin: true + peerDependencies: + browserslist: '>= 4.21.0' + + use-callback-ref@1.3.3: + resolution: {integrity: sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg==} + engines: {node: '>=10'} + peerDependencies: + '@types/react': '*' + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + use-sidecar@1.1.3: + resolution: {integrity: sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ==} + engines: {node: '>=10'} + peerDependencies: + '@types/react': '*' + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + use-sync-external-store@1.7.0: + resolution: {integrity: sha512-6L+EeigHMQhdaIPNIFUKwfWJSwWFQ8gJbJ2DLOs5sDIegTwR9fRxvnM3uciHKjIZhFz+KAv2emhWMRvDmMcY8A==} + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + + vite@8.3.4: + resolution: {integrity: sha512-IftLE8phJhdNRIGNEV4JCCvfNScoZQVfcXaN8TQropWGJtOHcu+iAB9pHcuGvmEb/kddw0LBe/jS8ztdC6xdiQ==} + engines: {node: ^20.19.0 || >=22.12.0} + hasBin: true + peerDependencies: + '@types/node': ^20.19.0 || >=22.12.0 + '@vitejs/devtools': ^0.7.1 + esbuild: ^0.27.0 || ^0.28.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 + 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 + sass: + optional: true + sass-embedded: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + tsx: + optional: true + yaml: + optional: true + + vitefu@1.1.3: + resolution: {integrity: sha512-ub4okH7Z5KLjb6hDyjqrGXqWtWvoYdU3IGm/NorpgHncKoLTCfRIbvlhBm7r0YstIaQRYlp4yEbFqDcKSzXSSg==} + peerDependencies: + vite: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 + peerDependenciesMeta: + vite: + optional: true + + vitest@5.0.5: + resolution: {integrity: sha512-cPODOMF8YnkiiYtDdHo6n4wWmBrOBBbOIYH2d33M4l3CdNn72h+qMmO6uXffUN6A5AZFXNND/d+krS9mgkXRfg==} + engines: {node: ^22.12.0 || ^24.0.0 || >=26.0.0} + hasBin: true + peerDependencies: + '@edge-runtime/vm': '*' + '@opentelemetry/api': ^1.9.0 + '@types/node': ^22.0.0 || >=24.0.0 + '@vitest/browser-playwright': 5.0.5 + '@vitest/browser-preview': 5.0.5 + '@vitest/browser-webdriverio': ^5.0.0-beta.5 || >=5.0.0 + '@vitest/coverage-istanbul': 5.0.5 + '@vitest/coverage-v8': 5.0.5 + '@vitest/ui': 5.0.5 + happy-dom: '*' + jsdom: '*' + vite: ^6.4.0 || ^7.0.0 || ^8.0.0 + peerDependenciesMeta: + '@edge-runtime/vm': + optional: true + '@opentelemetry/api': + optional: true + '@types/node': + optional: true + '@vitest/browser-playwright': + optional: true + '@vitest/browser-preview': + optional: true + '@vitest/browser-webdriverio': + optional: true + '@vitest/coverage-istanbul': + optional: true + '@vitest/coverage-v8': + optional: true + '@vitest/ui': + optional: true + happy-dom: + optional: true + jsdom: + optional: true + + w3c-xmlserializer@6.0.0: + resolution: {integrity: sha512-4Nsy8K5Tr6SPDH9jhKJOHf7ChDrc1zufZTVSF7x72hwuEXBqxqk9G6cK+K2NRUtB3iELRJqjXb4JPDMBjMTl2Q==} + engines: {node: ^22.22.2 || ^24.15.0 || >=26.0.0} + + webidl-conversions@7.0.0: + resolution: {integrity: sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==} + engines: {node: '>=12'} + + webidl-conversions@8.0.1: + resolution: {integrity: sha512-BMhLD/Sw+GbJC21C/UgyaZX41nPt8bUTg+jWyDeg7e7YN4xOM05YPSIXceACnXVtqyEw/LMClUQMtMZ+PGGpqQ==} + engines: {node: '>=20'} + + webpack-virtual-modules@0.6.2: + resolution: {integrity: sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==} + + whatwg-mimetype@5.0.0: + resolution: {integrity: sha512-sXcNcHOC51uPGF0P/D4NVtrkjSU2fNsm9iog4ZvZJsL3rjoDAzXZhkm2MWt1y+PUdggKAYVoMAIYcs78wJ51Cw==} + engines: {node: '>=20'} + + whatwg-url@14.2.0: + resolution: {integrity: sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw==} + engines: {node: '>=18'} + + whatwg-url@17.3.0: + resolution: {integrity: sha512-KwOAJrpf+GTgBvcBQJcP38sMF0DsQKdwtG+TxM2pW44P6E5k0hDbWrDmyuJDIF0Uef0aQq0ZoJs+5oI+k8ddhg==} + engines: {node: ^22.14.0 || >=24.0.0} + + why-is-node-running@3.2.1: + resolution: {integrity: sha512-Tb2FUhB4vUsGQlfSquQLYkApkuPAFQXGFzxWKHHumVz2dK+X1RUm/HnID4+TfIGYJ1kTcwOaCk/buYCEJr6YjQ==} + engines: {node: '>=20.11'} + hasBin: true + + xml-name-validator@5.0.0: + resolution: {integrity: sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==} + engines: {node: '>=18'} + + xmlbuilder2@4.0.3: + resolution: {integrity: sha512-bx8Q1STctnNaaDymWnkfQLKofs0mGNN7rLLapJlGuV3VlvegD7Ls4ggMjE3aUSWItCCzU0PEv45lI87iSigiCA==} + engines: {node: '>=20.0'} + + xmlchars@2.2.0: + resolution: {integrity: sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==} + + yallist@3.1.1: + resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} + + yaml@2.9.1: + resolution: {integrity: sha512-3NxN8+78OdzbT7C/WjGsyfPAtJaN3FNDsWxv7Y7mcDsT/oOmgW8BpyQQFFBnvZE3j9Y2Sdz1ULFLezL7Eb2yFw==} + engines: {node: '>= 14.6'} + hasBin: true + + zod@4.6.5: + resolution: {integrity: sha512-v5l/aFXZQeai4awLbOpSoHecE9UiMrnfx75tEXLjNonXVARxQ5mOeipTjROUchszUNCqnE+hqAMujRsRHsut2Q==} + +snapshots: + + '@asamuzakjp/css-color@7.1.7': + dependencies: + '@csstools/css-calc': 3.4.3(@csstools/css-parser-algorithms@4.0.2(@csstools/css-tokenizer@4.0.2))(@csstools/css-tokenizer@4.0.2) + '@csstools/css-color-parser': 4.2.6(@csstools/css-parser-algorithms@4.0.2(@csstools/css-tokenizer@4.0.2))(@csstools/css-tokenizer@4.0.2) + '@csstools/css-parser-algorithms': 4.0.2(@csstools/css-tokenizer@4.0.2) + '@csstools/css-tokenizer': 4.0.2 + lru-cache: 11.5.3 + + '@asamuzakjp/dom-selector@10.0.4': + dependencies: + bidi-js: 1.1.0 + css-tree: 3.2.1 + is-potential-custom-element-name: 1.0.1 + lru-cache: 11.5.3 + + '@babel/code-frame@7.29.7': + dependencies: + '@babel/helper-validator-identifier': 7.29.7 + js-tokens: 4.0.0 + picocolors: 1.1.1 + + '@babel/compat-data@7.29.7': {} + + '@babel/core@7.29.7': + dependencies: + '@babel/code-frame': 7.29.7 + '@babel/generator': 7.29.8 + '@babel/helper-compilation-targets': 7.29.7 + '@babel/helper-module-transforms': 7.29.7(@babel/core@7.29.7) + '@babel/helpers': 7.29.10 + '@babel/parser': 7.29.9 + '@babel/template': 7.29.7 + '@babel/traverse': 7.29.10 + '@babel/types': 7.29.8 + '@jridgewell/remapping': 2.3.5 + convert-source-map: 2.0.0 + debug: 4.4.3 + gensync: 1.0.0-beta.2 + json5: 2.2.3 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + '@babel/generator@7.29.8': + dependencies: + '@babel/parser': 7.29.9 + '@babel/types': 7.29.8 + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.31 + jsesc: 3.1.0 + + '@babel/helper-compilation-targets@7.29.7': + dependencies: + '@babel/compat-data': 7.29.7 + '@babel/helper-validator-option': 7.29.7 + browserslist: 4.29.3 + lru-cache: 5.1.1 + semver: 6.3.1 + + '@babel/helper-globals@7.29.7': {} + + '@babel/helper-module-imports@7.29.7': + dependencies: + '@babel/traverse': 7.29.10 + '@babel/types': 7.29.8 + transitivePeerDependencies: + - supports-color + + '@babel/helper-module-transforms@7.29.7(@babel/core@7.29.7)': + dependencies: + '@babel/core': 7.29.7 + '@babel/helper-module-imports': 7.29.7 + '@babel/helper-validator-identifier': 7.29.7 + '@babel/traverse': 7.29.10 + transitivePeerDependencies: + - supports-color + + '@babel/helper-string-parser@7.29.7': {} + + '@babel/helper-validator-identifier@7.29.7': {} + + '@babel/helper-validator-option@7.29.7': {} + + '@babel/helpers@7.29.10': + dependencies: + '@babel/template': 7.29.7 + '@babel/types': 7.29.8 + + '@babel/parser@7.29.9': + dependencies: + '@babel/types': 7.29.8 + + '@babel/runtime@7.29.10': {} + + '@babel/template@7.29.7': + dependencies: + '@babel/code-frame': 7.29.7 + '@babel/parser': 7.29.9 + '@babel/types': 7.29.8 + + '@babel/traverse@7.29.10': + dependencies: + '@babel/code-frame': 7.29.7 + '@babel/generator': 7.29.8 + '@babel/helper-globals': 7.29.7 + '@babel/parser': 7.29.9 + '@babel/template': 7.29.7 + '@babel/types': 7.29.8 + debug: 4.4.3 + transitivePeerDependencies: + - supports-color + + '@babel/types@7.29.8': + dependencies: + '@babel/helper-string-parser': 7.29.7 + '@babel/helper-validator-identifier': 7.29.7 + + '@bramus/specificity@2.4.3': + dependencies: + css-tree: 3.2.1 + + '@csstools/color-helpers@6.1.2': {} + + '@csstools/css-calc@3.4.3(@csstools/css-parser-algorithms@4.0.2(@csstools/css-tokenizer@4.0.2))(@csstools/css-tokenizer@4.0.2)': + dependencies: + '@csstools/css-parser-algorithms': 4.0.2(@csstools/css-tokenizer@4.0.2) + '@csstools/css-tokenizer': 4.0.2 + + '@csstools/css-color-parser@4.2.6(@csstools/css-parser-algorithms@4.0.2(@csstools/css-tokenizer@4.0.2))(@csstools/css-tokenizer@4.0.2)': + dependencies: + '@csstools/color-helpers': 6.1.2 + '@csstools/css-calc': 3.4.3(@csstools/css-parser-algorithms@4.0.2(@csstools/css-tokenizer@4.0.2))(@csstools/css-tokenizer@4.0.2) + '@csstools/css-parser-algorithms': 4.0.2(@csstools/css-tokenizer@4.0.2) + '@csstools/css-tokenizer': 4.0.2 + + '@csstools/css-parser-algorithms@4.0.2(@csstools/css-tokenizer@4.0.2)': + dependencies: + '@csstools/css-tokenizer': 4.0.2 + + '@csstools/css-syntax-patches-for-csstree@1.1.15(css-tree@3.2.1)': + optionalDependencies: + css-tree: 3.2.1 + + '@csstools/css-tokenizer@4.0.2': {} + + '@esbuild/aix-ppc64@0.28.2': + optional: true + + '@esbuild/android-arm64@0.28.2': + optional: true + + '@esbuild/android-arm@0.28.2': + optional: true + + '@esbuild/android-x64@0.28.2': + optional: true + + '@esbuild/darwin-arm64@0.28.2': + optional: true + + '@esbuild/darwin-x64@0.28.2': + optional: true + + '@esbuild/freebsd-arm64@0.28.2': + optional: true + + '@esbuild/freebsd-x64@0.28.2': + optional: true + + '@esbuild/linux-arm64@0.28.2': + optional: true + + '@esbuild/linux-arm@0.28.2': + optional: true + + '@esbuild/linux-ia32@0.28.2': + optional: true + + '@esbuild/linux-loong64@0.28.2': + optional: true + + '@esbuild/linux-mips64el@0.28.2': + optional: true + + '@esbuild/linux-ppc64@0.28.2': + optional: true + + '@esbuild/linux-riscv64@0.28.2': + optional: true + + '@esbuild/linux-s390x@0.28.2': + optional: true + + '@esbuild/linux-x64@0.28.2': + optional: true + + '@esbuild/netbsd-arm64@0.28.2': + optional: true + + '@esbuild/netbsd-x64@0.28.2': + optional: true + + '@esbuild/openbsd-arm64@0.28.2': + optional: true + + '@esbuild/openbsd-x64@0.28.2': + optional: true + + '@esbuild/openharmony-arm64@0.28.2': + optional: true + + '@esbuild/sunos-x64@0.28.2': + optional: true + + '@esbuild/win32-arm64@0.28.2': + optional: true + + '@esbuild/win32-ia32@0.28.2': + optional: true + + '@esbuild/win32-x64@0.28.2': + optional: true + + '@exodus/bytes@1.16.0': {} + + '@floating-ui/core@1.8.0': + dependencies: + '@floating-ui/utils': 0.2.12 + + '@floating-ui/dom@1.8.0': + dependencies: + '@floating-ui/core': 1.8.0 + '@floating-ui/utils': 0.2.12 + + '@floating-ui/react-dom@2.1.9(react-dom@19.3.1(react@19.3.1))(react@19.3.1)': + dependencies: + '@floating-ui/dom': 1.8.0 + react: 19.3.1 + react-dom: 19.3.1(react@19.3.1) + + '@floating-ui/utils@0.2.12': {} + + '@inquirer/ansi@2.0.9': {} + + '@inquirer/checkbox@5.2.6(@types/node@24.19.2)': + dependencies: + '@inquirer/ansi': 2.0.9 + '@inquirer/core': 12.0.4(@types/node@24.19.2) + '@inquirer/figures': 2.0.9 + '@inquirer/type': 4.2.0(@types/node@24.19.2) + optionalDependencies: + '@types/node': 24.19.2 + + '@inquirer/confirm@6.3.3(@types/node@24.19.2)': + dependencies: + '@inquirer/core': 12.0.4(@types/node@24.19.2) + '@inquirer/type': 4.2.0(@types/node@24.19.2) + optionalDependencies: + '@types/node': 24.19.2 + + '@inquirer/core@12.0.4(@types/node@24.19.2)': + dependencies: + '@inquirer/ansi': 2.0.9 + '@inquirer/figures': 2.0.9 + '@inquirer/type': 4.2.0(@types/node@24.19.2) + cli-width: 4.1.0 + fast-wrap-ansi: 0.2.2 + mute-stream: 3.0.0 + signal-exit: 4.1.0 + optionalDependencies: + '@types/node': 24.19.2 + + '@inquirer/editor@5.3.4(@types/node@24.19.2)': + dependencies: + '@inquirer/core': 12.0.4(@types/node@24.19.2) + '@inquirer/external-editor': 3.0.6(@types/node@24.19.2) + '@inquirer/type': 4.2.0(@types/node@24.19.2) + optionalDependencies: + '@types/node': 24.19.2 + + '@inquirer/expand@5.1.6(@types/node@24.19.2)': + dependencies: + '@inquirer/core': 12.0.4(@types/node@24.19.2) + '@inquirer/type': 4.2.0(@types/node@24.19.2) + optionalDependencies: + '@types/node': 24.19.2 + + '@inquirer/external-editor@3.0.6(@types/node@24.19.2)': + dependencies: + chardet: 2.2.0 + iconv-lite: 0.7.3 + optionalDependencies: + '@types/node': 24.19.2 + + '@inquirer/figures@2.0.9': {} + + '@inquirer/input@5.1.7(@types/node@24.19.2)': + dependencies: + '@inquirer/core': 12.0.4(@types/node@24.19.2) + '@inquirer/type': 4.2.0(@types/node@24.19.2) + optionalDependencies: + '@types/node': 24.19.2 + + '@inquirer/number@4.2.4(@types/node@24.19.2)': + dependencies: + '@inquirer/core': 12.0.4(@types/node@24.19.2) + '@inquirer/type': 4.2.0(@types/node@24.19.2) + optionalDependencies: + '@types/node': 24.19.2 + + '@inquirer/password@5.2.3(@types/node@24.19.2)': + dependencies: + '@inquirer/ansi': 2.0.9 + '@inquirer/core': 12.0.4(@types/node@24.19.2) + '@inquirer/type': 4.2.0(@types/node@24.19.2) + optionalDependencies: + '@types/node': 24.19.2 + + '@inquirer/prompts@8.7.3(@types/node@24.19.2)': + dependencies: + '@inquirer/checkbox': 5.2.6(@types/node@24.19.2) + '@inquirer/confirm': 6.3.3(@types/node@24.19.2) + '@inquirer/editor': 5.3.4(@types/node@24.19.2) + '@inquirer/expand': 5.1.6(@types/node@24.19.2) + '@inquirer/input': 5.1.7(@types/node@24.19.2) + '@inquirer/number': 4.2.4(@types/node@24.19.2) + '@inquirer/password': 5.2.3(@types/node@24.19.2) + '@inquirer/rawlist': 5.3.6(@types/node@24.19.2) + '@inquirer/search': 4.3.4(@types/node@24.19.2) + '@inquirer/select': 5.2.6(@types/node@24.19.2) + optionalDependencies: + '@types/node': 24.19.2 + + '@inquirer/rawlist@5.3.6(@types/node@24.19.2)': + dependencies: + '@inquirer/core': 12.0.4(@types/node@24.19.2) + '@inquirer/type': 4.2.0(@types/node@24.19.2) + optionalDependencies: + '@types/node': 24.19.2 + + '@inquirer/search@4.3.4(@types/node@24.19.2)': + dependencies: + '@inquirer/core': 12.0.4(@types/node@24.19.2) + '@inquirer/figures': 2.0.9 + '@inquirer/type': 4.2.0(@types/node@24.19.2) + optionalDependencies: + '@types/node': 24.19.2 + + '@inquirer/select@5.2.6(@types/node@24.19.2)': + dependencies: + '@inquirer/ansi': 2.0.9 + '@inquirer/core': 12.0.4(@types/node@24.19.2) + '@inquirer/figures': 2.0.9 + '@inquirer/type': 4.2.0(@types/node@24.19.2) + optionalDependencies: + '@types/node': 24.19.2 + + '@inquirer/type@4.2.0(@types/node@24.19.2)': + optionalDependencies: + '@types/node': 24.19.2 + + '@jridgewell/gen-mapping@0.3.13': + dependencies: + '@jridgewell/sourcemap-codec': 1.6.0 + '@jridgewell/trace-mapping': 0.3.31 + + '@jridgewell/remapping@2.3.5': + dependencies: + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.31 + + '@jridgewell/resolve-uri@3.1.2': {} + + '@jridgewell/sourcemap-codec@1.6.0': {} + + '@jridgewell/trace-mapping@0.3.31': + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.6.0 + + '@lemoncode/lemony@0.10.0': + dependencies: + markdown-it: 15.0.2 + yaml: 2.9.1 + zod: 4.6.5 + + '@mongodb-js/saslprep@1.6.1': + dependencies: + sparse-bitfield: 3.0.3 + + '@oozcitak/dom@2.0.2': + dependencies: + '@oozcitak/infra': 2.0.2 + '@oozcitak/url': 3.0.0 + '@oozcitak/util': 10.0.0 + + '@oozcitak/infra@2.0.2': + dependencies: + '@oozcitak/util': 10.0.0 + + '@oozcitak/url@3.0.0': + dependencies: + '@oozcitak/infra': 2.0.2 + '@oozcitak/util': 10.0.0 + + '@oozcitak/util@10.0.0': {} + + '@oxc-project/types@0.154.0': {} + + '@radix-ui/number@1.1.3': {} + + '@radix-ui/primitive@1.2.0': {} + + '@radix-ui/react-accessible-icon@1.2.0(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)': + dependencies: + '@radix-ui/react-visually-hidden': 1.2.13(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + react: 19.3.1 + react-dom: 19.3.1(react@19.3.1) + optionalDependencies: + '@types/react': 19.3.0 + '@types/react-dom': 19.3.0(@types/react@19.3.0) + + '@radix-ui/react-accordion@1.3.1(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)': + dependencies: + '@radix-ui/primitive': 1.2.0 + '@radix-ui/react-collapsible': 1.2.1(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-collection': 1.2.0(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-context': 1.3.0(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-direction': 1.2.0(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-id': 1.1.4(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-primitive': 2.2.0(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-use-controllable-state': 1.3.0(@types/react@19.3.0)(react@19.3.1) + react: 19.3.1 + react-dom: 19.3.1(react@19.3.1) + optionalDependencies: + '@types/react': 19.3.0 + '@types/react-dom': 19.3.0(@types/react@19.3.0) + + '@radix-ui/react-alert-dialog@1.2.1(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)': + dependencies: + '@radix-ui/primitive': 1.2.0 + '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-context': 1.3.0(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-dialog': 1.3.1(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-primitive': 2.2.0(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + react: 19.3.1 + react-dom: 19.3.1(react@19.3.1) + optionalDependencies: + '@types/react': 19.3.0 + '@types/react-dom': 19.3.0(@types/react@19.3.0) + + '@radix-ui/react-arrow@1.1.17(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)': + dependencies: + '@radix-ui/react-primitive': 2.2.0(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + react: 19.3.1 + react-dom: 19.3.1(react@19.3.1) + optionalDependencies: + '@types/react': 19.3.0 + '@types/react-dom': 19.3.0(@types/react@19.3.0) + + '@radix-ui/react-aspect-ratio@1.2.0(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)': + dependencies: + '@radix-ui/react-primitive': 2.2.0(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + react: 19.3.1 + react-dom: 19.3.1(react@19.3.1) + optionalDependencies: + '@types/react': 19.3.0 + '@types/react-dom': 19.3.0(@types/react@19.3.0) + + '@radix-ui/react-avatar@1.3.1(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)': + dependencies: + '@radix-ui/primitive': 1.2.0 + '@radix-ui/react-context': 1.3.0(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-primitive': 2.2.0(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-use-callback-ref': 1.1.5(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-use-is-hydrated': 0.1.3(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.3.0)(react@19.3.1) + react: 19.3.1 + react-dom: 19.3.1(react@19.3.1) + optionalDependencies: + '@types/react': 19.3.0 + '@types/react-dom': 19.3.0(@types/react@19.3.0) + + '@radix-ui/react-checkbox@1.4.1(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)': + dependencies: + '@radix-ui/primitive': 1.2.0 + '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-context': 1.3.0(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-presence': 1.1.11(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-primitive': 2.2.0(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-use-controllable-state': 1.3.0(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-use-size': 1.1.5(@types/react@19.3.0)(react@19.3.1) + react: 19.3.1 + react-dom: 19.3.1(react@19.3.1) + optionalDependencies: + '@types/react': 19.3.0 + '@types/react-dom': 19.3.0(@types/react@19.3.0) + + '@radix-ui/react-collapsible@1.2.1(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)': + dependencies: + '@radix-ui/primitive': 1.2.0 + '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-context': 1.3.0(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-id': 1.1.4(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-presence': 1.1.11(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-primitive': 2.2.0(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-use-controllable-state': 1.3.0(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.3.0)(react@19.3.1) + react: 19.3.1 + react-dom: 19.3.1(react@19.3.1) + optionalDependencies: + '@types/react': 19.3.0 + '@types/react-dom': 19.3.0(@types/react@19.3.0) + + '@radix-ui/react-collection@1.2.0(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)': + dependencies: + '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-context': 1.3.0(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-primitive': 2.2.0(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-slot': 1.5.0(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.3.0)(react@19.3.1) + react: 19.3.1 + react-dom: 19.3.1(react@19.3.1) + optionalDependencies: + '@types/react': 19.3.0 + '@types/react-dom': 19.3.0(@types/react@19.3.0) + + '@radix-ui/react-compose-refs@1.1.5(@types/react@19.3.0)(react@19.3.1)': + dependencies: + react: 19.3.1 + optionalDependencies: + '@types/react': 19.3.0 + + '@radix-ui/react-context-menu@2.4.1(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)': + dependencies: + '@radix-ui/primitive': 1.2.0 + '@radix-ui/react-context': 1.3.0(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-menu': 2.2.1(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-primitive': 2.2.0(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-use-controllable-state': 1.3.0(@types/react@19.3.0)(react@19.3.1) + react: 19.3.1 + react-dom: 19.3.1(react@19.3.1) + optionalDependencies: + '@types/react': 19.3.0 + '@types/react-dom': 19.3.0(@types/react@19.3.0) + + '@radix-ui/react-context@1.3.0(@types/react@19.3.0)(react@19.3.1)': + dependencies: + react: 19.3.1 + optionalDependencies: + '@types/react': 19.3.0 + + '@radix-ui/react-dialog@1.3.1(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)': + dependencies: + '@radix-ui/primitive': 1.2.0 + '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-context': 1.3.0(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-dismissable-layer': 1.2.1(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-focus-guards': 1.2.0(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-focus-scope': 1.3.1(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-id': 1.1.4(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-portal': 1.2.0(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-presence': 1.1.11(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-primitive': 2.2.0(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-slot': 1.5.0(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-use-controllable-state': 1.3.0(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.3.0)(react@19.3.1) + aria-hidden: 1.2.6 + react: 19.3.1 + react-dom: 19.3.1(react@19.3.1) + react-remove-scroll: 2.7.2(@types/react@19.3.0)(react@19.3.1) + optionalDependencies: + '@types/react': 19.3.0 + '@types/react-dom': 19.3.0(@types/react@19.3.0) + + '@radix-ui/react-direction@1.2.0(@types/react@19.3.0)(react@19.3.1)': + dependencies: + react: 19.3.1 + optionalDependencies: + '@types/react': 19.3.0 + + '@radix-ui/react-dismissable-layer@1.2.1(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)': + dependencies: + '@radix-ui/primitive': 1.2.0 + '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-primitive': 2.2.0(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-use-callback-ref': 1.1.5(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-use-effect-event': 0.0.5(@types/react@19.3.0)(react@19.3.1) + react: 19.3.1 + react-dom: 19.3.1(react@19.3.1) + optionalDependencies: + '@types/react': 19.3.0 + '@types/react-dom': 19.3.0(@types/react@19.3.0) + + '@radix-ui/react-dropdown-menu@2.2.1(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)': + dependencies: + '@radix-ui/primitive': 1.2.0 + '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-context': 1.3.0(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-id': 1.1.4(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-menu': 2.2.1(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-primitive': 2.2.0(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-use-controllable-state': 1.3.0(@types/react@19.3.0)(react@19.3.1) + react: 19.3.1 + react-dom: 19.3.1(react@19.3.1) + optionalDependencies: + '@types/react': 19.3.0 + '@types/react-dom': 19.3.0(@types/react@19.3.0) + + '@radix-ui/react-focus-guards@1.2.0(@types/react@19.3.0)(react@19.3.1)': + dependencies: + react: 19.3.1 + optionalDependencies: + '@types/react': 19.3.0 + + '@radix-ui/react-focus-scope@1.3.1(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)': + dependencies: + '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-primitive': 2.2.0(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-use-callback-ref': 1.1.5(@types/react@19.3.0)(react@19.3.1) + react: 19.3.1 + react-dom: 19.3.1(react@19.3.1) + optionalDependencies: + '@types/react': 19.3.0 + '@types/react-dom': 19.3.0(@types/react@19.3.0) + + '@radix-ui/react-form@0.3.0(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)': + dependencies: + '@radix-ui/primitive': 1.2.0 + '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-context': 1.3.0(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-id': 1.1.4(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-label': 2.1.17(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-primitive': 2.2.0(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + react: 19.3.1 + react-dom: 19.3.1(react@19.3.1) + optionalDependencies: + '@types/react': 19.3.0 + '@types/react-dom': 19.3.0(@types/react@19.3.0) + + '@radix-ui/react-hover-card@1.2.1(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)': + dependencies: + '@radix-ui/primitive': 1.2.0 + '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-context': 1.3.0(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-dismissable-layer': 1.2.1(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-focus-scope': 1.3.1(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-popper': 1.4.0(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-portal': 1.2.0(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-presence': 1.1.11(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-primitive': 2.2.0(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-use-controllable-state': 1.3.0(@types/react@19.3.0)(react@19.3.1) + react: 19.3.1 + react-dom: 19.3.1(react@19.3.1) + optionalDependencies: + '@types/react': 19.3.0 + '@types/react-dom': 19.3.0(@types/react@19.3.0) + + '@radix-ui/react-id@1.1.4(@types/react@19.3.0)(react@19.3.1)': + dependencies: + '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.3.0)(react@19.3.1) + react: 19.3.1 + optionalDependencies: + '@types/react': 19.3.0 + + '@radix-ui/react-label@2.1.17(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)': + dependencies: + '@radix-ui/react-primitive': 2.2.0(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + react: 19.3.1 + react-dom: 19.3.1(react@19.3.1) + optionalDependencies: + '@types/react': 19.3.0 + '@types/react-dom': 19.3.0(@types/react@19.3.0) + + '@radix-ui/react-menu@2.2.1(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)': + dependencies: + '@radix-ui/primitive': 1.2.0 + '@radix-ui/react-collection': 1.2.0(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-context': 1.3.0(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-direction': 1.2.0(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-dismissable-layer': 1.2.1(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-focus-guards': 1.2.0(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-focus-scope': 1.3.1(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-id': 1.1.4(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-popper': 1.4.0(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-portal': 1.2.0(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-presence': 1.1.11(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-primitive': 2.2.0(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-roving-focus': 1.2.1(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-slot': 1.5.0(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-use-callback-ref': 1.1.5(@types/react@19.3.0)(react@19.3.1) + aria-hidden: 1.2.6 + react: 19.3.1 + react-dom: 19.3.1(react@19.3.1) + react-remove-scroll: 2.7.2(@types/react@19.3.0)(react@19.3.1) + optionalDependencies: + '@types/react': 19.3.0 + '@types/react-dom': 19.3.0(@types/react@19.3.0) + + '@radix-ui/react-menubar@1.2.1(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)': + dependencies: + '@radix-ui/primitive': 1.2.0 + '@radix-ui/react-collection': 1.2.0(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-context': 1.3.0(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-direction': 1.2.0(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-id': 1.1.4(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-menu': 2.2.1(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-primitive': 2.2.0(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-roving-focus': 1.2.1(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-use-controllable-state': 1.3.0(@types/react@19.3.0)(react@19.3.1) + react: 19.3.1 + react-dom: 19.3.1(react@19.3.1) + optionalDependencies: + '@types/react': 19.3.0 + '@types/react-dom': 19.3.0(@types/react@19.3.0) + + '@radix-ui/react-navigation-menu@1.4.1(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)': + dependencies: + '@radix-ui/primitive': 1.2.0 + '@radix-ui/react-collection': 1.2.0(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-context': 1.3.0(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-direction': 1.2.0(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-dismissable-layer': 1.2.1(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-id': 1.1.4(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-presence': 1.1.11(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-primitive': 2.2.0(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-slot': 1.5.0(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-use-callback-ref': 1.1.5(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-use-controllable-state': 1.3.0(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-use-previous': 1.1.4(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-visually-hidden': 1.2.13(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + react: 19.3.1 + react-dom: 19.3.1(react@19.3.1) + optionalDependencies: + '@types/react': 19.3.0 + '@types/react-dom': 19.3.0(@types/react@19.3.0) + + '@radix-ui/react-one-time-password-field@0.2.1(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)': + dependencies: + '@radix-ui/number': 1.1.3 + '@radix-ui/primitive': 1.2.0 + '@radix-ui/react-collection': 1.2.0(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-context': 1.3.0(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-direction': 1.2.0(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-primitive': 2.2.0(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-roving-focus': 1.2.1(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-use-controllable-state': 1.3.0(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-use-effect-event': 0.0.5(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-use-is-hydrated': 0.1.3(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.3.0)(react@19.3.1) + react: 19.3.1 + react-dom: 19.3.1(react@19.3.1) + optionalDependencies: + '@types/react': 19.3.0 + '@types/react-dom': 19.3.0(@types/react@19.3.0) + + '@radix-ui/react-password-toggle-field@0.2.1(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)': + dependencies: + '@radix-ui/primitive': 1.2.0 + '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-context': 1.3.0(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-id': 1.1.4(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-primitive': 2.2.0(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-use-controllable-state': 1.3.0(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-use-effect-event': 0.0.5(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-use-is-hydrated': 0.1.3(@types/react@19.3.0)(react@19.3.1) + react: 19.3.1 + react-dom: 19.3.1(react@19.3.1) + optionalDependencies: + '@types/react': 19.3.0 + '@types/react-dom': 19.3.0(@types/react@19.3.0) + + '@radix-ui/react-popover@1.3.1(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)': + dependencies: + '@radix-ui/primitive': 1.2.0 + '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-context': 1.3.0(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-dismissable-layer': 1.2.1(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-focus-guards': 1.2.0(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-focus-scope': 1.3.1(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-id': 1.1.4(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-popper': 1.4.0(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-portal': 1.2.0(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-presence': 1.1.11(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-primitive': 2.2.0(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-slot': 1.5.0(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-use-controllable-state': 1.3.0(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.3.0)(react@19.3.1) + aria-hidden: 1.2.6 + react: 19.3.1 + react-dom: 19.3.1(react@19.3.1) + react-remove-scroll: 2.7.2(@types/react@19.3.0)(react@19.3.1) + optionalDependencies: + '@types/react': 19.3.0 + '@types/react-dom': 19.3.0(@types/react@19.3.0) + + '@radix-ui/react-popper@1.4.0(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)': + dependencies: + '@floating-ui/react-dom': 2.1.9(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-arrow': 1.1.17(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-context': 1.3.0(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-primitive': 2.2.0(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-use-callback-ref': 1.1.5(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-use-rect': 1.1.4(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-use-size': 1.1.5(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/rect': 1.1.3 + react: 19.3.1 + react-dom: 19.3.1(react@19.3.1) + optionalDependencies: + '@types/react': 19.3.0 + '@types/react-dom': 19.3.0(@types/react@19.3.0) + + '@radix-ui/react-portal@1.2.0(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)': + dependencies: + '@radix-ui/react-primitive': 2.2.0(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.3.0)(react@19.3.1) + react: 19.3.1 + react-dom: 19.3.1(react@19.3.1) + optionalDependencies: + '@types/react': 19.3.0 + '@types/react-dom': 19.3.0(@types/react@19.3.0) + + '@radix-ui/react-presence@1.1.11(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)': + dependencies: + '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.3.0)(react@19.3.1) + react: 19.3.1 + react-dom: 19.3.1(react@19.3.1) + optionalDependencies: + '@types/react': 19.3.0 + '@types/react-dom': 19.3.0(@types/react@19.3.0) + + '@radix-ui/react-primitive@2.2.0(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)': + dependencies: + '@radix-ui/react-slot': 1.5.0(@types/react@19.3.0)(react@19.3.1) + react: 19.3.1 + react-dom: 19.3.1(react@19.3.1) + optionalDependencies: + '@types/react': 19.3.0 + '@types/react-dom': 19.3.0(@types/react@19.3.0) + + '@radix-ui/react-progress@1.2.1(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)': + dependencies: + '@radix-ui/react-context': 1.3.0(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-primitive': 2.2.0(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + react: 19.3.1 + react-dom: 19.3.1(react@19.3.1) + optionalDependencies: + '@types/react': 19.3.0 + '@types/react-dom': 19.3.0(@types/react@19.3.0) + + '@radix-ui/react-radio-group@1.5.1(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)': + dependencies: + '@radix-ui/primitive': 1.2.0 + '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-context': 1.3.0(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-direction': 1.2.0(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-presence': 1.1.11(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-primitive': 2.2.0(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-roving-focus': 1.2.1(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-use-controllable-state': 1.3.0(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-use-size': 1.1.5(@types/react@19.3.0)(react@19.3.1) + react: 19.3.1 + react-dom: 19.3.1(react@19.3.1) + optionalDependencies: + '@types/react': 19.3.0 + '@types/react-dom': 19.3.0(@types/react@19.3.0) + + '@radix-ui/react-roving-focus@1.2.1(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)': + dependencies: + '@radix-ui/primitive': 1.2.0 + '@radix-ui/react-collection': 1.2.0(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-context': 1.3.0(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-direction': 1.2.0(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-id': 1.1.4(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-primitive': 2.2.0(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-use-callback-ref': 1.1.5(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-use-controllable-state': 1.3.0(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-use-is-hydrated': 0.1.3(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.3.0)(react@19.3.1) + react: 19.3.1 + react-dom: 19.3.1(react@19.3.1) + optionalDependencies: + '@types/react': 19.3.0 + '@types/react-dom': 19.3.0(@types/react@19.3.0) + + '@radix-ui/react-scroll-area@1.4.0(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)': + dependencies: + '@radix-ui/number': 1.1.3 + '@radix-ui/primitive': 1.2.0 + '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-context': 1.3.0(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-direction': 1.2.0(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-presence': 1.1.11(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-primitive': 2.2.0(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-slot': 1.5.0(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-use-callback-ref': 1.1.5(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.3.0)(react@19.3.1) + react: 19.3.1 + react-dom: 19.3.1(react@19.3.1) + optionalDependencies: + '@types/react': 19.3.0 + '@types/react-dom': 19.3.0(@types/react@19.3.0) + + '@radix-ui/react-select@2.4.1(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)': + dependencies: + '@radix-ui/number': 1.1.3 + '@radix-ui/primitive': 1.2.0 + '@radix-ui/react-collection': 1.2.0(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-context': 1.3.0(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-direction': 1.2.0(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-dismissable-layer': 1.2.1(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-focus-guards': 1.2.0(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-focus-scope': 1.3.1(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-id': 1.1.4(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-popper': 1.4.0(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-portal': 1.2.0(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-presence': 1.1.11(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-primitive': 2.2.0(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-slot': 1.5.0(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-use-callback-ref': 1.1.5(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-use-controllable-state': 1.3.0(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-visually-hidden': 1.2.13(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + aria-hidden: 1.2.6 + react: 19.3.1 + react-dom: 19.3.1(react@19.3.1) + react-remove-scroll: 2.7.2(@types/react@19.3.0)(react@19.3.1) + optionalDependencies: + '@types/react': 19.3.0 + '@types/react-dom': 19.3.0(@types/react@19.3.0) + + '@radix-ui/react-separator@1.2.0(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)': + dependencies: + '@radix-ui/react-primitive': 2.2.0(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + react: 19.3.1 + react-dom: 19.3.1(react@19.3.1) + optionalDependencies: + '@types/react': 19.3.0 + '@types/react-dom': 19.3.0(@types/react@19.3.0) + + '@radix-ui/react-slider@1.6.1(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)': + dependencies: + '@radix-ui/number': 1.1.3 + '@radix-ui/primitive': 1.2.0 + '@radix-ui/react-collection': 1.2.0(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-context': 1.3.0(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-direction': 1.2.0(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-primitive': 2.2.0(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-use-controllable-state': 1.3.0(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-use-size': 1.1.5(@types/react@19.3.0)(react@19.3.1) + react: 19.3.1 + react-dom: 19.3.1(react@19.3.1) + optionalDependencies: + '@types/react': 19.3.0 + '@types/react-dom': 19.3.0(@types/react@19.3.0) + + '@radix-ui/react-slot@1.5.0(@types/react@19.3.0)(react@19.3.1)': + dependencies: + '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.3.0)(react@19.3.1) + react: 19.3.1 + optionalDependencies: + '@types/react': 19.3.0 + + '@radix-ui/react-switch@1.4.1(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)': + dependencies: + '@radix-ui/primitive': 1.2.0 + '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-context': 1.3.0(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-primitive': 2.2.0(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-use-controllable-state': 1.3.0(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-use-size': 1.1.5(@types/react@19.3.0)(react@19.3.1) + react: 19.3.1 + react-dom: 19.3.1(react@19.3.1) + optionalDependencies: + '@types/react': 19.3.0 + '@types/react-dom': 19.3.0(@types/react@19.3.0) + + '@radix-ui/react-tabs@1.2.1(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)': + dependencies: + '@radix-ui/primitive': 1.2.0 + '@radix-ui/react-context': 1.3.0(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-direction': 1.2.0(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-id': 1.1.4(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-presence': 1.1.11(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-primitive': 2.2.0(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-roving-focus': 1.2.1(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-use-controllable-state': 1.3.0(@types/react@19.3.0)(react@19.3.1) + react: 19.3.1 + react-dom: 19.3.1(react@19.3.1) + optionalDependencies: + '@types/react': 19.3.0 + '@types/react-dom': 19.3.0(@types/react@19.3.0) + + '@radix-ui/react-toast@1.3.1(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)': + dependencies: + '@radix-ui/primitive': 1.2.0 + '@radix-ui/react-collection': 1.2.0(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-context': 1.3.0(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-dismissable-layer': 1.2.1(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-portal': 1.2.0(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-presence': 1.1.11(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-primitive': 2.2.0(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-use-callback-ref': 1.1.5(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-use-controllable-state': 1.3.0(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-visually-hidden': 1.2.13(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + react: 19.3.1 + react-dom: 19.3.1(react@19.3.1) + optionalDependencies: + '@types/react': 19.3.0 + '@types/react-dom': 19.3.0(@types/react@19.3.0) + + '@radix-ui/react-toggle-group@1.2.1(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)': + dependencies: + '@radix-ui/primitive': 1.2.0 + '@radix-ui/react-context': 1.3.0(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-direction': 1.2.0(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-primitive': 2.2.0(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-roving-focus': 1.2.1(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-toggle': 1.2.1(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-use-controllable-state': 1.3.0(@types/react@19.3.0)(react@19.3.1) + react: 19.3.1 + react-dom: 19.3.1(react@19.3.1) + optionalDependencies: + '@types/react': 19.3.0 + '@types/react-dom': 19.3.0(@types/react@19.3.0) + + '@radix-ui/react-toggle@1.2.1(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)': + dependencies: + '@radix-ui/primitive': 1.2.0 + '@radix-ui/react-primitive': 2.2.0(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-use-controllable-state': 1.3.0(@types/react@19.3.0)(react@19.3.1) + react: 19.3.1 + react-dom: 19.3.1(react@19.3.1) + optionalDependencies: + '@types/react': 19.3.0 + '@types/react-dom': 19.3.0(@types/react@19.3.0) + + '@radix-ui/react-toolbar@1.2.1(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)': + dependencies: + '@radix-ui/primitive': 1.2.0 + '@radix-ui/react-context': 1.3.0(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-direction': 1.2.0(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-primitive': 2.2.0(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-roving-focus': 1.2.1(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-separator': 1.2.0(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-toggle-group': 1.2.1(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + react: 19.3.1 + react-dom: 19.3.1(react@19.3.1) + optionalDependencies: + '@types/react': 19.3.0 + '@types/react-dom': 19.3.0(@types/react@19.3.0) + + '@radix-ui/react-tooltip@1.4.1(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)': + dependencies: + '@radix-ui/primitive': 1.2.0 + '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-context': 1.3.0(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-dismissable-layer': 1.2.1(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-focus-scope': 1.3.1(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-id': 1.1.4(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-popper': 1.4.0(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-portal': 1.2.0(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-presence': 1.1.11(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-primitive': 2.2.0(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-slot': 1.5.0(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-use-controllable-state': 1.3.0(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-visually-hidden': 1.2.13(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + react: 19.3.1 + react-dom: 19.3.1(react@19.3.1) + optionalDependencies: + '@types/react': 19.3.0 + '@types/react-dom': 19.3.0(@types/react@19.3.0) + + '@radix-ui/react-use-callback-ref@1.1.5(@types/react@19.3.0)(react@19.3.1)': + dependencies: + '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.3.0)(react@19.3.1) + react: 19.3.1 + optionalDependencies: + '@types/react': 19.3.0 + + '@radix-ui/react-use-controllable-state@1.3.0(@types/react@19.3.0)(react@19.3.1)': + dependencies: + '@radix-ui/primitive': 1.2.0 + '@radix-ui/react-use-effect-event': 0.0.5(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.3.0)(react@19.3.1) + react: 19.3.1 + optionalDependencies: + '@types/react': 19.3.0 + + '@radix-ui/react-use-effect-event@0.0.5(@types/react@19.3.0)(react@19.3.1)': + dependencies: + '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.3.0)(react@19.3.1) + react: 19.3.1 + optionalDependencies: + '@types/react': 19.3.0 + + '@radix-ui/react-use-escape-keydown@1.1.6(@types/react@19.3.0)(react@19.3.1)': + dependencies: + '@radix-ui/react-use-callback-ref': 1.1.5(@types/react@19.3.0)(react@19.3.1) + react: 19.3.1 + optionalDependencies: + '@types/react': 19.3.0 + + '@radix-ui/react-use-is-hydrated@0.1.3(@types/react@19.3.0)(react@19.3.1)': + dependencies: + react: 19.3.1 + optionalDependencies: + '@types/react': 19.3.0 + + '@radix-ui/react-use-layout-effect@1.1.4(@types/react@19.3.0)(react@19.3.1)': + dependencies: + react: 19.3.1 + optionalDependencies: + '@types/react': 19.3.0 + + '@radix-ui/react-use-previous@1.1.4(@types/react@19.3.0)(react@19.3.1)': + dependencies: + react: 19.3.1 + optionalDependencies: + '@types/react': 19.3.0 + + '@radix-ui/react-use-rect@1.1.4(@types/react@19.3.0)(react@19.3.1)': + dependencies: + '@radix-ui/rect': 1.1.3 + react: 19.3.1 + optionalDependencies: + '@types/react': 19.3.0 + + '@radix-ui/react-use-size@1.1.5(@types/react@19.3.0)(react@19.3.1)': + dependencies: + '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.3.0)(react@19.3.1) + react: 19.3.1 + optionalDependencies: + '@types/react': 19.3.0 + + '@radix-ui/react-visually-hidden@1.2.13(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)': + dependencies: + '@radix-ui/react-primitive': 2.2.0(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + react: 19.3.1 + react-dom: 19.3.1(react@19.3.1) + optionalDependencies: + '@types/react': 19.3.0 + '@types/react-dom': 19.3.0(@types/react@19.3.0) + + '@radix-ui/rect@1.1.3': {} + + '@rolldown/binding-android-arm-eabi@1.2.14': + optional: true + + '@rolldown/binding-android-arm64@1.2.14': + optional: true + + '@rolldown/binding-darwin-arm64@1.2.14': + optional: true + + '@rolldown/binding-darwin-x64@1.2.14': + optional: true + + '@rolldown/binding-freebsd-x64@1.2.14': + optional: true + + '@rolldown/binding-linux-arm-gnueabihf@1.2.14': + optional: true + + '@rolldown/binding-linux-arm64-gnu@1.2.14': + optional: true + + '@rolldown/binding-linux-arm64-musl@1.2.14': + optional: true + + '@rolldown/binding-linux-ppc64-gnu@1.2.14': + optional: true + + '@rolldown/binding-linux-s390x-gnu@1.2.14': + optional: true + + '@rolldown/binding-linux-x64-gnu@1.2.14': + optional: true + + '@rolldown/binding-linux-x64-musl@1.2.14': + optional: true + + '@rolldown/binding-openharmony-arm64@1.2.14': + optional: true + + '@rolldown/binding-win32-arm64-msvc@1.2.14': + optional: true + + '@rolldown/binding-win32-x64-msvc@1.2.14': + optional: true + + '@rolldown/pluginutils@1.0.1': {} + + '@tailwindcss/node@4.3.3': + dependencies: + '@jridgewell/remapping': 2.3.5 + enhanced-resolve: 5.26.0 + jiti: 2.7.0 + lightningcss: 1.32.0 + magic-string: 0.30.21 + source-map-js: 1.2.2 + tailwindcss: 4.3.3 + + '@tailwindcss/oxide-android-arm64@4.3.3': + optional: true + + '@tailwindcss/oxide-darwin-arm64@4.3.3': + optional: true + + '@tailwindcss/oxide-darwin-x64@4.3.3': + optional: true + + '@tailwindcss/oxide-freebsd-x64@4.3.3': + optional: true + + '@tailwindcss/oxide-linux-arm-gnueabihf@4.3.3': + optional: true + + '@tailwindcss/oxide-linux-arm64-gnu@4.3.3': + optional: true + + '@tailwindcss/oxide-linux-arm64-musl@4.3.3': + optional: true + + '@tailwindcss/oxide-linux-x64-gnu@4.3.3': + optional: true + + '@tailwindcss/oxide-linux-x64-musl@4.3.3': + optional: true + + '@tailwindcss/oxide-wasm32-wasi@4.3.3': + optional: true + + '@tailwindcss/oxide-win32-arm64-msvc@4.3.3': + optional: true + + '@tailwindcss/oxide-win32-x64-msvc@4.3.3': + optional: true + + '@tailwindcss/oxide@4.3.3': + optionalDependencies: + '@tailwindcss/oxide-android-arm64': 4.3.3 + '@tailwindcss/oxide-darwin-arm64': 4.3.3 + '@tailwindcss/oxide-darwin-x64': 4.3.3 + '@tailwindcss/oxide-freebsd-x64': 4.3.3 + '@tailwindcss/oxide-linux-arm-gnueabihf': 4.3.3 + '@tailwindcss/oxide-linux-arm64-gnu': 4.3.3 + '@tailwindcss/oxide-linux-arm64-musl': 4.3.3 + '@tailwindcss/oxide-linux-x64-gnu': 4.3.3 + '@tailwindcss/oxide-linux-x64-musl': 4.3.3 + '@tailwindcss/oxide-wasm32-wasi': 4.3.3 + '@tailwindcss/oxide-win32-arm64-msvc': 4.3.3 + '@tailwindcss/oxide-win32-x64-msvc': 4.3.3 + + '@tailwindcss/vite@4.3.3(vite@8.3.4(@types/node@24.19.2)(esbuild@0.28.2)(jiti@2.7.0)(tsx@4.23.15)(yaml@2.9.1))': + dependencies: + '@tailwindcss/node': 4.3.3 + '@tailwindcss/oxide': 4.3.3 + tailwindcss: 4.3.3 + vite: 8.3.4(@types/node@24.19.2)(esbuild@0.28.2)(jiti@2.7.0)(tsx@4.23.15)(yaml@2.9.1) + + '@tanstack/history@1.162.5': {} + + '@tanstack/react-router@1.170.45(react-dom@19.3.1(react@19.3.1))(react@19.3.1)': + dependencies: + '@tanstack/history': 1.162.5 + '@tanstack/react-store': 0.11.2(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@tanstack/router-core': 1.171.38 + isbot: 5.2.2 + react: 19.3.1 + react-dom: 19.3.1(react@19.3.1) + + '@tanstack/react-start-client@1.168.43(react-dom@19.3.1(react@19.3.1))(react@19.3.1)': + dependencies: + '@tanstack/react-router': 1.170.45(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@tanstack/router-core': 1.171.38 + '@tanstack/start-client-core': 1.170.38 + react: 19.3.1 + react-dom: 19.3.1(react@19.3.1) + + '@tanstack/react-start-rsc@0.1.64(esbuild@0.28.2)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(rolldown@1.2.14)(vite@8.3.4(@types/node@24.19.2)(esbuild@0.28.2)(jiti@2.7.0)(tsx@4.23.15)(yaml@2.9.1))': + dependencies: + '@tanstack/react-router': 1.170.45(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@tanstack/router-core': 1.171.38 + '@tanstack/router-utils': 1.162.4 + '@tanstack/start-client-core': 1.170.38 + '@tanstack/start-fn-stubs': 1.162.0 + '@tanstack/start-plugin-core': 1.171.54(@tanstack/react-router@1.170.45(react-dom@19.3.1(react@19.3.1))(react@19.3.1))(esbuild@0.28.2)(rolldown@1.2.14)(vite@8.3.4(@types/node@24.19.2)(esbuild@0.28.2)(jiti@2.7.0)(tsx@4.23.15)(yaml@2.9.1)) + '@tanstack/start-storage-context': 1.167.40 + pathe: 2.0.3 + react: 19.3.1 + react-dom: 19.3.1(react@19.3.1) + transitivePeerDependencies: + - '@farmfe/core' + - '@rsbuild/core' + - bun-types-no-globals + - esbuild + - rolldown + - rollup + - supports-color + - unloader + - vite + - vite-plugin-solid + - webpack + + '@tanstack/react-start-server@1.167.51(react-dom@19.3.1(react@19.3.1))(react@19.3.1)': + dependencies: + '@tanstack/react-router': 1.170.45(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@tanstack/router-core': 1.171.38 + '@tanstack/start-server-core': 1.169.44 + react: 19.3.1 + react-dom: 19.3.1(react@19.3.1) + + '@tanstack/react-start@1.169.3(esbuild@0.28.2)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(rolldown@1.2.14)(vite@8.3.4(@types/node@24.19.2)(esbuild@0.28.2)(jiti@2.7.0)(tsx@4.23.15)(yaml@2.9.1))': + dependencies: + '@tanstack/react-router': 1.170.45(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@tanstack/react-start-client': 1.168.43(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@tanstack/react-start-rsc': 0.1.64(esbuild@0.28.2)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(rolldown@1.2.14)(vite@8.3.4(@types/node@24.19.2)(esbuild@0.28.2)(jiti@2.7.0)(tsx@4.23.15)(yaml@2.9.1)) + '@tanstack/react-start-server': 1.167.51(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@tanstack/router-utils': 1.162.4 + '@tanstack/start-client-core': 1.170.38 + '@tanstack/start-plugin-core': 1.171.54(@tanstack/react-router@1.170.45(react-dom@19.3.1(react@19.3.1))(react@19.3.1))(esbuild@0.28.2)(rolldown@1.2.14)(vite@8.3.4(@types/node@24.19.2)(esbuild@0.28.2)(jiti@2.7.0)(tsx@4.23.15)(yaml@2.9.1)) + '@tanstack/start-server-core': 1.169.44 + pathe: 2.0.3 + react: 19.3.1 + react-dom: 19.3.1(react@19.3.1) + optionalDependencies: + vite: 8.3.4(@types/node@24.19.2)(esbuild@0.28.2)(jiti@2.7.0)(tsx@4.23.15)(yaml@2.9.1) + transitivePeerDependencies: + - '@farmfe/core' + - '@rspack/core' + - bun-types-no-globals + - esbuild + - react-server-dom-rspack + - rolldown + - rollup + - supports-color + - unloader + - vite-plugin-solid + - webpack + + '@tanstack/react-store@0.11.2(react-dom@19.3.1(react@19.3.1))(react@19.3.1)': + dependencies: + '@tanstack/store': 0.11.2 + react: 19.3.1 + react-dom: 19.3.1(react@19.3.1) + use-sync-external-store: 1.7.0(react@19.3.1) + + '@tanstack/router-core@1.171.38': + dependencies: + '@tanstack/history': 1.162.5 + cookie-es: 3.1.1 + seroval: 1.6.9 + seroval-plugins: 1.6.9(seroval@1.6.9) + + '@tanstack/router-generator@1.167.45': + dependencies: + '@babel/types': 7.29.8 + '@tanstack/router-core': 1.171.38 + '@tanstack/router-utils': 1.162.4 + '@tanstack/virtual-file-routes': 1.162.0 + jiti: 2.7.0 + magic-string: 0.30.21 + prettier: 3.9.10 + zod: 4.6.5 + transitivePeerDependencies: + - supports-color + + '@tanstack/router-plugin@1.168.47(@tanstack/react-router@1.170.45(react-dom@19.3.1(react@19.3.1))(react@19.3.1))(esbuild@0.28.2)(rolldown@1.2.14)(vite@8.3.4(@types/node@24.19.2)(esbuild@0.28.2)(jiti@2.7.0)(tsx@4.23.15)(yaml@2.9.1))': + dependencies: + '@babel/core': 7.29.7 + '@babel/template': 7.29.7 + '@babel/types': 7.29.8 + '@tanstack/router-core': 1.171.38 + '@tanstack/router-generator': 1.167.45 + '@tanstack/router-utils': 1.162.4 + chokidar: 5.0.0 + unplugin: 3.4.0(esbuild@0.28.2)(rolldown@1.2.14)(vite@8.3.4(@types/node@24.19.2)(esbuild@0.28.2)(jiti@2.7.0)(tsx@4.23.15)(yaml@2.9.1)) + zod: 4.6.5 + optionalDependencies: + '@tanstack/react-router': 1.170.45(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + vite: 8.3.4(@types/node@24.19.2)(esbuild@0.28.2)(jiti@2.7.0)(tsx@4.23.15)(yaml@2.9.1) + transitivePeerDependencies: + - '@farmfe/core' + - '@rspack/core' + - bun-types-no-globals + - esbuild + - rolldown + - rollup + - supports-color + - unloader + + '@tanstack/router-utils@1.162.4': + dependencies: + '@babel/generator': 7.29.8 + '@babel/parser': 7.29.9 + '@babel/types': 7.29.8 + ansis: 4.4.0 + babel-dead-code-elimination: 1.0.12 + diff: 9.0.0 + pathe: 2.0.3 + tinyglobby: 0.2.17 + transitivePeerDependencies: + - supports-color + + '@tanstack/start-client-core@1.170.38': + dependencies: + '@tanstack/router-core': 1.171.38 + '@tanstack/start-fn-stubs': 1.162.0 + '@tanstack/start-storage-context': 1.167.40 + seroval: 1.6.9 + + '@tanstack/start-fn-stubs@1.162.0': {} + + '@tanstack/start-plugin-core@1.171.54(@tanstack/react-router@1.170.45(react-dom@19.3.1(react@19.3.1))(react@19.3.1))(esbuild@0.28.2)(rolldown@1.2.14)(vite@8.3.4(@types/node@24.19.2)(esbuild@0.28.2)(jiti@2.7.0)(tsx@4.23.15)(yaml@2.9.1))': + dependencies: + '@babel/code-frame': 7.29.7 + '@babel/core': 7.29.7 + '@babel/types': 7.29.8 + '@jridgewell/remapping': 2.3.5 + '@tanstack/router-core': 1.171.38 + '@tanstack/router-generator': 1.167.45 + '@tanstack/router-plugin': 1.168.47(@tanstack/react-router@1.170.45(react-dom@19.3.1(react@19.3.1))(react@19.3.1))(esbuild@0.28.2)(rolldown@1.2.14)(vite@8.3.4(@types/node@24.19.2)(esbuild@0.28.2)(jiti@2.7.0)(tsx@4.23.15)(yaml@2.9.1)) + '@tanstack/router-utils': 1.162.4 + '@tanstack/start-server-core': 1.169.44 + exsolve: 1.1.3 + lightningcss: 1.33.0 + pathe: 2.0.3 + picomatch: 4.0.7 + seroval: 1.6.9 + source-map: 0.7.6 + srvx: 1.0.6 + tinyglobby: 0.2.17 + ufo: 1.6.4 + vitefu: 1.1.3(vite@8.3.4(@types/node@24.19.2)(esbuild@0.28.2)(jiti@2.7.0)(tsx@4.23.15)(yaml@2.9.1)) + xmlbuilder2: 4.0.3 + zod: 4.6.5 + optionalDependencies: + vite: 8.3.4(@types/node@24.19.2)(esbuild@0.28.2)(jiti@2.7.0)(tsx@4.23.15)(yaml@2.9.1) + transitivePeerDependencies: + - '@farmfe/core' + - '@rspack/core' + - '@tanstack/react-router' + - bun-types-no-globals + - esbuild + - rolldown + - rollup + - supports-color + - unloader + - vite-plugin-solid + - webpack + + '@tanstack/start-server-core@1.169.44': + dependencies: + '@tanstack/history': 1.162.5 + '@tanstack/router-core': 1.171.38 + '@tanstack/start-client-core': 1.170.38 + '@tanstack/start-storage-context': 1.167.40 + cookie-es: 3.1.1 + fetchdts: 0.2.0 + seroval: 1.6.9 + + '@tanstack/start-storage-context@1.167.40': + dependencies: + '@tanstack/router-core': 1.171.38 + + '@tanstack/store@0.11.2': {} + + '@tanstack/virtual-file-routes@1.162.0': {} + + '@testing-library/dom@10.4.2': + dependencies: + '@babel/code-frame': 7.29.7 + '@babel/runtime': 7.29.10 + '@types/aria-query': 5.0.4 + aria-query: 5.3.0 + dom-accessibility-api: 0.5.16 + lz-string: 1.5.0 + picocolors: 1.1.1 + pretty-format: 27.5.1 + + '@testing-library/react@16.3.3(@testing-library/dom@10.4.2)(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)': + dependencies: + '@babel/runtime': 7.29.10 + '@testing-library/dom': 10.4.2 + react: 19.3.1 + react-dom: 19.3.1(react@19.3.1) + optionalDependencies: + '@types/react': 19.3.0 + '@types/react-dom': 19.3.0(@types/react@19.3.0) + + '@turbo/darwin-64@2.11.9': + optional: true + + '@turbo/darwin-arm64@2.11.9': + optional: true + + '@turbo/linux-64@2.11.9': + optional: true + + '@turbo/linux-arm64@2.11.9': + optional: true + + '@turbo/windows-64@2.11.9': + optional: true + + '@turbo/windows-arm64@2.11.9': + optional: true + + '@types/aria-query@5.0.4': {} + + '@types/chai@5.2.3': + dependencies: + '@types/deep-eql': 4.0.2 + assertion-error: 2.0.1 + + '@types/deep-eql@4.0.2': {} + + '@types/estree@1.0.9': {} + + '@types/node@24.19.2': + dependencies: + undici-types: 7.24.6 + + '@types/react-dom@19.3.0(@types/react@19.3.0)': + dependencies: + '@types/react': 19.3.0 + + '@types/react@19.3.0': + dependencies: + csstype: 3.2.3 + + '@types/webidl-conversions@7.0.3': {} + + '@types/whatwg-url@13.0.0': + dependencies: + '@types/webidl-conversions': 7.0.3 + + '@typescript/typescript-aix-ppc64@7.0.2': + optional: true + + '@typescript/typescript-darwin-arm64@7.0.2': + optional: true + + '@typescript/typescript-darwin-x64@7.0.2': + optional: true + + '@typescript/typescript-freebsd-arm64@7.0.2': + optional: true + + '@typescript/typescript-freebsd-x64@7.0.2': + optional: true + + '@typescript/typescript-linux-arm64@7.0.2': + optional: true + + '@typescript/typescript-linux-arm@7.0.2': + optional: true + + '@typescript/typescript-linux-loong64@7.0.2': + optional: true + + '@typescript/typescript-linux-mips64el@7.0.2': + optional: true + + '@typescript/typescript-linux-ppc64@7.0.2': + optional: true + + '@typescript/typescript-linux-riscv64@7.0.2': + optional: true + + '@typescript/typescript-linux-s390x@7.0.2': + optional: true + + '@typescript/typescript-linux-x64@7.0.2': + optional: true + + '@typescript/typescript-netbsd-arm64@7.0.2': + optional: true + + '@typescript/typescript-netbsd-x64@7.0.2': + optional: true + + '@typescript/typescript-openbsd-arm64@7.0.2': + optional: true + + '@typescript/typescript-openbsd-x64@7.0.2': + optional: true + + '@typescript/typescript-sunos-x64@7.0.2': + optional: true + + '@typescript/typescript-win32-arm64@7.0.2': + optional: true + + '@typescript/typescript-win32-x64@7.0.2': + optional: true + + '@vitejs/plugin-react@6.1.2(vite@8.3.4(@types/node@24.19.2)(esbuild@0.28.2)(jiti@2.7.0)(tsx@4.23.15)(yaml@2.9.1))': + dependencies: + '@rolldown/pluginutils': 1.0.1 + vite: 8.3.4(@types/node@24.19.2)(esbuild@0.28.2)(jiti@2.7.0)(tsx@4.23.15)(yaml@2.9.1) + + '@vitest/mocker@5.0.5(vite@8.3.4(@types/node@24.19.2)(esbuild@0.28.2)(jiti@2.7.0)(tsx@4.23.15)(yaml@2.9.1))': + dependencies: + '@jridgewell/trace-mapping': 0.3.31 + '@vitest/spy': 5.0.5 + estree-walker: 3.0.3 + magic-string: 1.4.3 + optionalDependencies: + vite: 8.3.4(@types/node@24.19.2)(esbuild@0.28.2)(jiti@2.7.0)(tsx@4.23.15)(yaml@2.9.1) + + '@vitest/spy@5.0.5': {} + + ansi-regex@5.0.1: {} + + ansi-styles@5.2.0: {} + + ansis@4.4.0: {} + + argparse@2.0.1: {} + + argparse@3.0.3: {} + + aria-hidden@1.2.6: + dependencies: + tslib: 2.8.1 + + aria-query@5.3.0: + dependencies: + dequal: 2.0.3 + + assertion-error@2.0.1: {} + + babel-dead-code-elimination@1.0.12: + dependencies: + '@babel/core': 7.29.7 + '@babel/parser': 7.29.9 + '@babel/traverse': 7.29.10 + '@babel/types': 7.29.8 + transitivePeerDependencies: + - supports-color + + baseline-browser-mapping@2.11.29: {} + + bidi-js@1.1.0: + dependencies: + require-from-string: 2.0.2 + + browserslist@4.29.3: + dependencies: + baseline-browser-mapping: 2.11.29 + caniuse-lite: 1.0.30001816 + electron-to-chromium: 1.5.459 + node-releases: 2.0.59 + update-browserslist-db: 1.3.4(browserslist@4.29.3) + + bson@7.3.3: {} + + caniuse-lite@1.0.30001816: {} + + chai@6.3.0: {} + + chardet@2.2.0: {} + + chokidar@5.0.0: + dependencies: + readdirp: 5.1.1 + + class-variance-authority@0.7.1: + dependencies: + clsx: 2.1.1 + + cli-width@4.1.0: {} + + clsx@2.1.1: {} + + cn@0.5.0: {} + + consola@3.4.2: {} + + convert-source-map@2.0.0: {} + + cookie-es@3.1.1: {} + + crossws@0.4.15(srvx@1.0.6): + optionalDependencies: + srvx: 1.0.6 + + css-tree@3.2.1: + dependencies: + mdn-data: 2.27.1 + source-map-js: 1.2.2 + + csstype@3.2.3: {} + + data-urls@8.0.0: + dependencies: + whatwg-mimetype: 5.0.0 + whatwg-url: 17.3.0 + transitivePeerDependencies: + - '@noble/hashes' + + db0@0.4.1: {} + + debug@4.4.3: + dependencies: + ms: 2.1.3 + + decimal.js@10.6.0: {} + + dequal@2.0.3: {} + + detect-libc@2.1.2: {} + + detect-node-es@1.1.0: {} + + diff@9.0.0: {} + + dom-accessibility-api@0.5.16: {} + + electron-to-chromium@1.5.459: {} + + enhanced-resolve@5.26.0: + dependencies: + graceful-fs: 4.2.11 + tapable: 2.3.3 + + entities@8.1.0: {} + + env-runner@0.2.3: + dependencies: + crossws: 0.4.15(srvx@1.0.6) + exsolve: 1.1.3 + httpxy: 0.5.5 + srvx: 1.0.6 + + es-module-lexer@2.3.2: {} + + esbuild@0.28.2: + optionalDependencies: + '@esbuild/aix-ppc64': 0.28.2 + '@esbuild/android-arm': 0.28.2 + '@esbuild/android-arm64': 0.28.2 + '@esbuild/android-x64': 0.28.2 + '@esbuild/darwin-arm64': 0.28.2 + '@esbuild/darwin-x64': 0.28.2 + '@esbuild/freebsd-arm64': 0.28.2 + '@esbuild/freebsd-x64': 0.28.2 + '@esbuild/linux-arm': 0.28.2 + '@esbuild/linux-arm64': 0.28.2 + '@esbuild/linux-ia32': 0.28.2 + '@esbuild/linux-loong64': 0.28.2 + '@esbuild/linux-mips64el': 0.28.2 + '@esbuild/linux-ppc64': 0.28.2 + '@esbuild/linux-riscv64': 0.28.2 + '@esbuild/linux-s390x': 0.28.2 + '@esbuild/linux-x64': 0.28.2 + '@esbuild/netbsd-arm64': 0.28.2 + '@esbuild/netbsd-x64': 0.28.2 + '@esbuild/openbsd-arm64': 0.28.2 + '@esbuild/openbsd-x64': 0.28.2 + '@esbuild/openharmony-arm64': 0.28.2 + '@esbuild/sunos-x64': 0.28.2 + '@esbuild/win32-arm64': 0.28.2 + '@esbuild/win32-ia32': 0.28.2 + '@esbuild/win32-x64': 0.28.2 + + escalade@3.2.0: {} + + estree-walker@3.0.3: + dependencies: + '@types/estree': 1.0.9 + + expect-type@1.4.0: {} + + exsolve@1.1.3: {} + + fast-string-truncated-width@3.0.3: {} + + fast-string-width@3.0.2: + dependencies: + fast-string-truncated-width: 3.0.3 + + fast-wrap-ansi@0.2.2: + dependencies: + fast-string-width: 3.0.2 + + fdir@6.5.0(picomatch@4.0.7): + optionalDependencies: + picomatch: 4.0.7 + + fetchdts@0.2.0: {} + + fsevents@2.3.3: + optional: true + + gensync@1.0.0-beta.2: {} + + get-nonce@1.0.1: {} + + graceful-fs@4.2.11: {} + + h3@2.0.3(crossws@0.4.15(srvx@1.0.6))(ocache@0.3.0): + dependencies: + rou3: 1.0.0 + srvx: 1.0.6 + optionalDependencies: + crossws: 0.4.15(srvx@1.0.6) + ocache: 0.3.0 + + hookable@6.1.2: {} + + html-encoding-sniffer@7.0.0: + dependencies: + '@exodus/bytes': 1.16.0 + transitivePeerDependencies: + - '@noble/hashes' + + httpxy@0.5.5: {} + + iconv-lite@0.7.3: + dependencies: + safer-buffer: 2.1.2 + + is-potential-custom-element-name@1.0.1: {} + + isbot@5.2.2: {} + + jiti@2.7.0: {} + + js-tokens@4.0.0: {} + + js-yaml@4.3.2: + dependencies: + argparse: 2.0.1 + + jsdom@30.1.3: + dependencies: + '@asamuzakjp/css-color': 7.1.7 + '@asamuzakjp/dom-selector': 10.0.4 + '@bramus/specificity': 2.4.3 + '@csstools/css-syntax-patches-for-csstree': 1.1.15(css-tree@3.2.1) + '@exodus/bytes': 1.16.0 + css-tree: 3.2.1 + data-urls: 8.0.0 + decimal.js: 10.6.0 + html-encoding-sniffer: 7.0.0 + is-potential-custom-element-name: 1.0.1 + lru-cache: 11.5.3 + parse5: 8.0.1 + saxes: 6.0.0 + tough-cookie: 6.0.2 + undici: 8.12.2 + w3c-xmlserializer: 6.0.0 + webidl-conversions: 8.0.1 + whatwg-mimetype: 5.0.0 + whatwg-url: 17.3.0 + xml-name-validator: 5.0.0 + transitivePeerDependencies: + - '@noble/hashes' + + jsesc@3.1.0: {} + + json5@2.2.3: {} + + lightningcss-android-arm64@1.32.0: + optional: true + + lightningcss-android-arm64@1.33.0: + optional: true + + lightningcss-darwin-arm64@1.32.0: + optional: true + + lightningcss-darwin-arm64@1.33.0: + optional: true + + lightningcss-darwin-x64@1.32.0: + optional: true + + lightningcss-darwin-x64@1.33.0: + optional: true + + lightningcss-freebsd-x64@1.32.0: + optional: true + + lightningcss-freebsd-x64@1.33.0: + optional: true + + lightningcss-linux-arm-gnueabihf@1.32.0: + optional: true + + lightningcss-linux-arm-gnueabihf@1.33.0: + optional: true + + lightningcss-linux-arm64-gnu@1.32.0: + optional: true + + lightningcss-linux-arm64-gnu@1.33.0: + optional: true + + lightningcss-linux-arm64-musl@1.32.0: + optional: true + + lightningcss-linux-arm64-musl@1.33.0: + optional: true + + lightningcss-linux-x64-gnu@1.32.0: + optional: true + + lightningcss-linux-x64-gnu@1.33.0: + optional: true + + lightningcss-linux-x64-musl@1.32.0: + optional: true + + lightningcss-linux-x64-musl@1.33.0: + optional: true + + lightningcss-win32-arm64-msvc@1.32.0: + optional: true + + lightningcss-win32-arm64-msvc@1.33.0: + optional: true + + lightningcss-win32-x64-msvc@1.32.0: + optional: true + + lightningcss-win32-x64-msvc@1.33.0: + optional: true + + lightningcss@1.32.0: + dependencies: + detect-libc: 2.1.2 + optionalDependencies: + lightningcss-android-arm64: 1.32.0 + lightningcss-darwin-arm64: 1.32.0 + lightningcss-darwin-x64: 1.32.0 + lightningcss-freebsd-x64: 1.32.0 + lightningcss-linux-arm-gnueabihf: 1.32.0 + lightningcss-linux-arm64-gnu: 1.32.0 + lightningcss-linux-arm64-musl: 1.32.0 + lightningcss-linux-x64-gnu: 1.32.0 + lightningcss-linux-x64-musl: 1.32.0 + lightningcss-win32-arm64-msvc: 1.32.0 + lightningcss-win32-x64-msvc: 1.32.0 + + lightningcss@1.33.0: + 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 + + linkify-it@6.1.0: + dependencies: + uc.micro: 3.0.0 + + lru-cache@11.5.3: {} + + lru-cache@5.1.1: + dependencies: + yallist: 3.1.1 + + lz-string@1.5.0: {} + + magic-string@0.30.21: + dependencies: + '@jridgewell/sourcemap-codec': 1.6.0 + + magic-string@1.4.3: + dependencies: + '@jridgewell/sourcemap-codec': 1.6.0 + + markdown-it@15.0.2: + dependencies: + argparse: 3.0.3 + entities: 8.1.0 + linkify-it: 6.1.0 + mdurl: 2.1.0 + punycode.js: 2.3.1 + uc.micro: 3.0.0 + + mdn-data@2.27.1: {} + + mdurl@2.1.0: {} + + memory-pager@1.5.0: {} + + mongodb-connection-string-url@7.0.2: + dependencies: + '@types/whatwg-url': 13.0.0 + whatwg-url: 14.2.0 + + mongodb@7.7.0: + dependencies: + '@mongodb-js/saslprep': 1.6.1 + bson: 7.3.3 + mongodb-connection-string-url: 7.0.2 + + ms@2.1.3: {} + + mute-stream@3.0.0: {} + + nanoid@3.3.20: {} + + nf3@0.3.24: {} + + nitro@3.0.260903-beta: + dependencies: + consola: 3.4.2 + crossws: 0.4.15(srvx@1.0.6) + db0: 0.4.1 + env-runner: 0.2.3 + h3: 2.0.3(crossws@0.4.15(srvx@1.0.6))(ocache@0.3.0) + hookable: 6.1.2 + nf3: 0.3.24 + ocache: 0.3.0 + rolldown: 1.2.14 + rou3: 0.9.2 + srvx: 1.0.6 + unenv: 2.0.0-rc.24 + unstorage: 2.0.0-alpha.11 + + node-releases@2.0.59: {} + + obug@3.0.0: {} + + ocache@0.3.0: {} + + parse5@8.0.1: + dependencies: + entities: 8.1.0 + + pathe@2.0.3: {} + + picocolors@1.1.1: {} + + picomatch@4.0.7: {} + + postcss@8.5.30: + dependencies: + nanoid: 3.3.20 + picocolors: 1.1.1 + source-map-js: 1.2.2 + + prettier@3.9.10: {} + + pretty-format@27.5.1: + dependencies: + ansi-regex: 5.0.1 + ansi-styles: 5.2.0 + react-is: 17.0.2 + + punycode.js@2.3.1: {} + + punycode@2.3.1: {} + + radix-ui@1.8.1(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1): + dependencies: + '@radix-ui/primitive': 1.2.0 + '@radix-ui/react-accessible-icon': 1.2.0(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-accordion': 1.3.1(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-alert-dialog': 1.2.1(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-arrow': 1.1.17(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-aspect-ratio': 1.2.0(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-avatar': 1.3.1(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-checkbox': 1.4.1(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-collapsible': 1.2.1(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-collection': 1.2.0(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-context': 1.3.0(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-context-menu': 2.4.1(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-dialog': 1.3.1(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-direction': 1.2.0(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-dismissable-layer': 1.2.1(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-dropdown-menu': 2.2.1(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-focus-guards': 1.2.0(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-focus-scope': 1.3.1(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-form': 0.3.0(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-hover-card': 1.2.1(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-label': 2.1.17(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-menu': 2.2.1(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-menubar': 1.2.1(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-navigation-menu': 1.4.1(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-one-time-password-field': 0.2.1(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-password-toggle-field': 0.2.1(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-popover': 1.3.1(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-popper': 1.4.0(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-portal': 1.2.0(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-presence': 1.1.11(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-primitive': 2.2.0(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-progress': 1.2.1(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-radio-group': 1.5.1(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-roving-focus': 1.2.1(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-scroll-area': 1.4.0(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-select': 2.4.1(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-separator': 1.2.0(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-slider': 1.6.1(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-slot': 1.5.0(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-switch': 1.4.1(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-tabs': 1.2.1(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-toast': 1.3.1(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-toggle': 1.2.1(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-toggle-group': 1.2.1(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-toolbar': 1.2.1(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-tooltip': 1.4.1(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@radix-ui/react-use-callback-ref': 1.1.5(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-use-controllable-state': 1.3.0(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-use-effect-event': 0.0.5(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-use-escape-keydown': 1.1.6(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-use-is-hydrated': 0.1.3(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-use-size': 1.1.5(@types/react@19.3.0)(react@19.3.1) + '@radix-ui/react-visually-hidden': 1.2.13(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + react: 19.3.1 + react-dom: 19.3.1(react@19.3.1) + optionalDependencies: + '@types/react': 19.3.0 + '@types/react-dom': 19.3.0(@types/react@19.3.0) + + react-dom@19.3.1(react@19.3.1): + dependencies: + react: 19.3.1 + scheduler: 0.28.0 + + react-is@17.0.2: {} + + react-remove-scroll-bar@2.3.8(@types/react@19.3.0)(react@19.3.1): + dependencies: + react: 19.3.1 + react-style-singleton: 2.2.3(@types/react@19.3.0)(react@19.3.1) + tslib: 2.8.1 + optionalDependencies: + '@types/react': 19.3.0 + + react-remove-scroll@2.7.2(@types/react@19.3.0)(react@19.3.1): + dependencies: + react: 19.3.1 + react-remove-scroll-bar: 2.3.8(@types/react@19.3.0)(react@19.3.1) + react-style-singleton: 2.2.3(@types/react@19.3.0)(react@19.3.1) + tslib: 2.8.1 + use-callback-ref: 1.3.3(@types/react@19.3.0)(react@19.3.1) + use-sidecar: 1.1.3(@types/react@19.3.0)(react@19.3.1) + optionalDependencies: + '@types/react': 19.3.0 + + react-style-singleton@2.2.3(@types/react@19.3.0)(react@19.3.1): + dependencies: + get-nonce: 1.0.1 + react: 19.3.1 + tslib: 2.8.1 + optionalDependencies: + '@types/react': 19.3.0 + + react@19.3.1: {} + + readdirp@5.1.1: {} + + require-from-string@2.0.2: {} + + rolldown@1.2.14: + dependencies: + '@oxc-project/types': 0.154.0 + '@rolldown/pluginutils': 1.0.1 + optionalDependencies: + '@rolldown/binding-android-arm-eabi': 1.2.14 + '@rolldown/binding-android-arm64': 1.2.14 + '@rolldown/binding-darwin-arm64': 1.2.14 + '@rolldown/binding-darwin-x64': 1.2.14 + '@rolldown/binding-freebsd-x64': 1.2.14 + '@rolldown/binding-linux-arm-gnueabihf': 1.2.14 + '@rolldown/binding-linux-arm64-gnu': 1.2.14 + '@rolldown/binding-linux-arm64-musl': 1.2.14 + '@rolldown/binding-linux-ppc64-gnu': 1.2.14 + '@rolldown/binding-linux-s390x-gnu': 1.2.14 + '@rolldown/binding-linux-x64-gnu': 1.2.14 + '@rolldown/binding-linux-x64-musl': 1.2.14 + '@rolldown/binding-openharmony-arm64': 1.2.14 + '@rolldown/binding-win32-arm64-msvc': 1.2.14 + '@rolldown/binding-win32-x64-msvc': 1.2.14 + + rou3@0.9.2: {} + + rou3@1.0.0: {} + + safer-buffer@2.1.2: {} + + saxes@6.0.0: + dependencies: + xmlchars: 2.2.0 + + scheduler@0.28.0: {} + + semver@6.3.1: {} + + seroval-plugins@1.6.9(seroval@1.6.9): + dependencies: + seroval: 1.6.9 + + seroval@1.6.9: {} + + signal-exit@4.1.0: {} + + source-map-js@1.2.2: {} + + source-map@0.7.6: {} + + sparse-bitfield@3.0.3: + dependencies: + memory-pager: 1.5.0 + + srvx@1.0.6: {} + + std-env@4.3.0: {} + + tailwindcss@4.3.3: {} + + tapable@2.3.3: {} + + tinybench@6.2.2: {} + + tinyexec@1.3.1: {} + + tinyglobby@0.2.17: + dependencies: + fdir: 6.5.0(picomatch@4.0.7) + picomatch: 4.0.7 + + tldts-core@7.4.18: {} + + tldts@7.4.18: + dependencies: + tldts-core: 7.4.18 + + tough-cookie@6.0.2: + dependencies: + tldts: 7.4.18 + + tr46@5.1.1: + dependencies: + punycode: 2.3.1 + + tr46@7.0.0: + dependencies: + punycode: 2.3.1 + + tslib@2.8.1: {} + + tsx@4.23.15: + dependencies: + esbuild: 0.28.2 + optionalDependencies: + fsevents: 2.3.3 + + turbo@2.11.9: + optionalDependencies: + '@turbo/darwin-64': 2.11.9 + '@turbo/darwin-arm64': 2.11.9 + '@turbo/linux-64': 2.11.9 + '@turbo/linux-arm64': 2.11.9 + '@turbo/windows-64': 2.11.9 + '@turbo/windows-arm64': 2.11.9 + + typescript@7.0.2: + optionalDependencies: + '@typescript/typescript-aix-ppc64': 7.0.2 + '@typescript/typescript-darwin-arm64': 7.0.2 + '@typescript/typescript-darwin-x64': 7.0.2 + '@typescript/typescript-freebsd-arm64': 7.0.2 + '@typescript/typescript-freebsd-x64': 7.0.2 + '@typescript/typescript-linux-arm': 7.0.2 + '@typescript/typescript-linux-arm64': 7.0.2 + '@typescript/typescript-linux-loong64': 7.0.2 + '@typescript/typescript-linux-mips64el': 7.0.2 + '@typescript/typescript-linux-ppc64': 7.0.2 + '@typescript/typescript-linux-riscv64': 7.0.2 + '@typescript/typescript-linux-s390x': 7.0.2 + '@typescript/typescript-linux-x64': 7.0.2 + '@typescript/typescript-netbsd-arm64': 7.0.2 + '@typescript/typescript-netbsd-x64': 7.0.2 + '@typescript/typescript-openbsd-arm64': 7.0.2 + '@typescript/typescript-openbsd-x64': 7.0.2 + '@typescript/typescript-sunos-x64': 7.0.2 + '@typescript/typescript-win32-arm64': 7.0.2 + '@typescript/typescript-win32-x64': 7.0.2 + + uc.micro@3.0.0: {} + + ufo@1.6.4: {} + + undici-types@7.24.6: {} + + undici@8.12.2: {} + + unenv@2.0.0-rc.24: + dependencies: + pathe: 2.0.3 + + unplugin@3.4.0(esbuild@0.28.2)(rolldown@1.2.14)(vite@8.3.4(@types/node@24.19.2)(esbuild@0.28.2)(jiti@2.7.0)(tsx@4.23.15)(yaml@2.9.1)): + dependencies: + '@jridgewell/remapping': 2.3.5 + picomatch: 4.0.7 + webpack-virtual-modules: 0.6.2 + optionalDependencies: + esbuild: 0.28.2 + rolldown: 1.2.14 + vite: 8.3.4(@types/node@24.19.2)(esbuild@0.28.2)(jiti@2.7.0)(tsx@4.23.15)(yaml@2.9.1) + + unstorage@2.0.0-alpha.11: {} + + update-browserslist-db@1.3.4(browserslist@4.29.3): + dependencies: + browserslist: 4.29.3 + escalade: 3.2.0 + picocolors: 1.1.1 + + use-callback-ref@1.3.3(@types/react@19.3.0)(react@19.3.1): + dependencies: + react: 19.3.1 + tslib: 2.8.1 + optionalDependencies: + '@types/react': 19.3.0 + + use-sidecar@1.1.3(@types/react@19.3.0)(react@19.3.1): + dependencies: + detect-node-es: 1.1.0 + react: 19.3.1 + tslib: 2.8.1 + optionalDependencies: + '@types/react': 19.3.0 + + use-sync-external-store@1.7.0(react@19.3.1): + dependencies: + react: 19.3.1 + + vite@8.3.4(@types/node@24.19.2)(esbuild@0.28.2)(jiti@2.7.0)(tsx@4.23.15)(yaml@2.9.1): + dependencies: + lightningcss: 1.33.0 + picomatch: 4.0.7 + postcss: 8.5.30 + rolldown: 1.2.14 + tinyglobby: 0.2.17 + optionalDependencies: + '@types/node': 24.19.2 + esbuild: 0.28.2 + fsevents: 2.3.3 + jiti: 2.7.0 + tsx: 4.23.15 + yaml: 2.9.1 + + vitefu@1.1.3(vite@8.3.4(@types/node@24.19.2)(esbuild@0.28.2)(jiti@2.7.0)(tsx@4.23.15)(yaml@2.9.1)): + optionalDependencies: + vite: 8.3.4(@types/node@24.19.2)(esbuild@0.28.2)(jiti@2.7.0)(tsx@4.23.15)(yaml@2.9.1) + + vitest@5.0.5(@types/node@24.19.2)(jsdom@30.1.3)(vite@8.3.4(@types/node@24.19.2)(esbuild@0.28.2)(jiti@2.7.0)(tsx@4.23.15)(yaml@2.9.1)): + dependencies: + '@types/chai': 5.2.3 + '@vitest/mocker': 5.0.5(vite@8.3.4(@types/node@24.19.2)(esbuild@0.28.2)(jiti@2.7.0)(tsx@4.23.15)(yaml@2.9.1)) + chai: 6.3.0 + es-module-lexer: 2.3.2 + expect-type: 1.4.0 + magic-string: 1.4.3 + obug: 3.0.0 + picomatch: 4.0.7 + std-env: 4.3.0 + tinybench: 6.2.2 + tinyexec: 1.3.1 + tinyglobby: 0.2.17 + vite: 8.3.4(@types/node@24.19.2)(esbuild@0.28.2)(jiti@2.7.0)(tsx@4.23.15)(yaml@2.9.1) + why-is-node-running: 3.2.1 + optionalDependencies: + '@types/node': 24.19.2 + jsdom: 30.1.3 + transitivePeerDependencies: + - msw + + w3c-xmlserializer@6.0.0: + dependencies: + xml-name-validator: 5.0.0 + + webidl-conversions@7.0.0: {} + + webidl-conversions@8.0.1: {} + + webpack-virtual-modules@0.6.2: {} + + whatwg-mimetype@5.0.0: {} + + whatwg-url@14.2.0: + dependencies: + tr46: 5.1.1 + webidl-conversions: 7.0.0 + + whatwg-url@17.3.0: + dependencies: + '@exodus/bytes': 1.16.0 + tr46: 7.0.0 + webidl-conversions: 8.0.1 + transitivePeerDependencies: + - '@noble/hashes' + + why-is-node-running@3.2.1: {} + + xml-name-validator@5.0.0: {} + + xmlbuilder2@4.0.3: + dependencies: + '@oozcitak/dom': 2.0.2 + '@oozcitak/infra': 2.0.2 + '@oozcitak/util': 10.0.0 + js-yaml: 4.3.2 + + xmlchars@2.2.0: {} + + yallist@3.1.1: {} + + yaml@2.9.1: {} + + zod@4.6.5: {} diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml new file mode 100644 index 0000000..855781d --- /dev/null +++ b/pnpm-workspace.yaml @@ -0,0 +1,10 @@ +packages: + - 'apps/*' + - 'packages/*' + - 'console-runner' + +# pnpm 10 blocks dependency build scripts by default; these two need theirs to +# fetch/compile their native binaries (Vite's bundler and Tailwind's CSS engine). +onlyBuiltDependencies: + - esbuild + - lightningcss diff --git a/tsconfig.base.json b/tsconfig.base.json new file mode 100644 index 0000000..ca3e922 --- /dev/null +++ b/tsconfig.base.json @@ -0,0 +1,22 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig", + "compilerOptions": { + "target": "ES2023", + "lib": ["ES2023"], + "module": "preserve", + "moduleResolution": "bundler", + "moduleDetection": "force", + "resolveJsonModule": true, + "verbatimModuleSyntax": true, + "isolatedModules": true, + "esModuleInterop": true, + "skipLibCheck": true, + "noEmit": true, + + "strict": true, + "noUncheckedIndexedAccess": true, + "noImplicitOverride": true, + "noFallthroughCasesInSwitch": true, + "forceConsistentCasingInFileNames": true + } +} diff --git a/turbo.json b/turbo.json new file mode 100644 index 0000000..bd62b6f --- /dev/null +++ b/turbo.json @@ -0,0 +1,19 @@ +{ + "$schema": "https://turborepo.dev/schema.json", + "tasks": { + "dev": { + "cache": false, + "persistent": true + }, + "build": { + "dependsOn": ["^build"], + "outputs": [".output/**", "dist/**", ".tanstack/**"] + }, + "test": { + "outputs": [] + }, + "typecheck": { + "outputs": [] + } + } +} From dcce210f3dffa80d6ec6034ed1f429106121128e Mon Sep 17 00:00:00 2001 From: Braulio Date: Sun, 18 Oct 2026 00:05:35 +0200 Subject: [PATCH 3/4] task(1): implementation checkpoint OK Lemony-Checkpoint: .claude/hooks/lib/lemony.sh checkpoint ok --task-id=1 --auto-commit=off --- .claude/state/tasks/1/progress.md | 419 ++++++++++++++++++ .../tasks/1/review-ledger/full-pass.json | 202 +++++++++ .claude/state/tasks/1/spec/tasks.md | 50 +-- 3 files changed, 646 insertions(+), 25 deletions(-) create mode 100644 .claude/state/tasks/1/progress.md create mode 100644 .claude/state/tasks/1/review-ledger/full-pass.json diff --git a/.claude/state/tasks/1/progress.md b/.claude/state/tasks/1/progress.md new file mode 100644 index 0000000..2ee378b --- /dev/null +++ b/.claude/state/tasks/1/progress.md @@ -0,0 +1,419 @@ +# Progress — Task #1 · Infraestructura base del monorepo + +Issue: https://github.com/Lemoncode/demo-memora/issues/1 +Branch: `harness/1-infra-monorepo` +Spec: `.claude/state/tasks/1/spec/` +PRD: `docs/prds/infra-monorepo-2026-10-17.md` + +Mode: all-at-once +Auto-commit: off +Implementation anchor (single group = whole tasks.md): `11be63560fbbb9c132e2ae635923b080b244a95a` + +Spec approved at the gate on 2026-10-17 (first-pass approval, no revision cycles). +Declared gates confirmed by the human at the gate: `typecheck`, `format:check`, +`test`, `build` — written to `harness.config.yml` by T23. + +## Status + +**Implementation complete — all 25 tasks green across all 7 groups.** + +**Checkpoint OK (human, 2026-10-18)** — all-at-once gate, auto-commit off. The human +answered `ok` as it stands, with no human delta in the worktree. The four gates were +re-validated fresh over the final worktree before the OK resolved (`TURBO_FORCE=true`: +typecheck 3/3, format:check clean, test 3/3 task-green — 20 tests, build 1/1). The +visual check of `http://localhost:3000/` was offered to the human with the dev server +running; the server was shut down afterwards. The deferral ends here: the branch gets +its first implementation commits through the `checkpoint ok` call. + +The five Reviewer findings were accepted as **not blocking** and routed to follow-up +capture rather than fixed in this delivery (destructive-confirm `default: false` +regression test, the `0.0.0.0` port publish, the stale `components.json` aliases, the +inaccurate "pinned exactly" claim below, and the unspecified Ctrl+D/EOF exit). + +## Active subtask + +None — ready for the review gate. + +## Pinned stack versions (R21) + +The PRD names the TanStack Start → Tailwind → shadcn chain as the most fragile part +of the delivery, so the whole `apps/web` toolchain is pinned **exactly** (no carets): + +| Package | Pinned | +| -------------------------- | ---------- | +| `@tanstack/react-start` | 1.169.3 | +| `@tanstack/react-router` | 1.170.45 | +| `nitro` | 3.0.260903-beta | +| `react` / `react-dom` | 19.3.1 | +| `tailwindcss` | 4.3.3 | +| `@tailwindcss/vite` | 4.3.3 | +| `vite` | 8.3.4 | +| `vitest` | 5.0.5 | +| `typescript` | 7.0.2 | +| `turbo` | 2.11.9 | +| `prettier` | 3.9.10 | +| `tsx` | 4.23.15 | +| shadcn CLI used | 4.22.0 | + +**No shadcn/Tailwind incompatibility was hit** — the R21 unwanted-behaviour path did +not fire. shadcn 4.22.0 and Tailwind 4.3.3 integrate cleanly; the combination above is +the one proven green by all four gates. + +Toolchain measured on this machine: Node v24.16.0, pnpm 10.19.0 — matching D7 exactly +(`.nvmrc` 24.16.0, `engines.node >=24.16.0 <25`, `packageManager pnpm@10.19.0`). + +## Decision log + +- **T1 — the pnpm migration was low-risk, not high-risk.** The Orchestrator flagged + that reinstalling `@lemoncode/lemony` under pnpm could break the hooks this session + depends on. Checked first: the package resolves from the **public npm registry** + (`registry.npmjs.org`), not GitHub Packages as `lemony.sh`'s comment suggests, so no + auth was involved. After `pnpm install`, `node_modules/.bin/lemony` exists and + `.claude/hooks/lib/lemony.sh --version` prints `0.10.0` (R5 proven). No discovery + needed. +- **T4 — `.prettierignore` also excludes two harness files that live outside + `.claude/`.** R11 enumerates `node_modules`, `.claude/`, `pnpm-lock.yaml`, build + outputs and caches, but the installer also drops `harness.config.schema.json` (repo + root) and `docs/playbooks/README.md`, and Prettier wanted to reformat both. Both are + regenerated by `lemony repair`/`update`, which is exactly the failure R11 exists to + prevent ("a harness vendor update can never fail the format gate"). Added them to the + ignore list — faithful to R11's rationale, a small extension of its literal list. + **Flagged for the reviewer.** +- **T3 — dropped `exactOptionalPropertyTypes` from `tsconfig.base.json`.** R8 requires + `strict: true`; I had also added this option, which is high-friction against React and + third-party prop types for little value here. The base keeps `strict` plus + `noUncheckedIndexedAccess`, `noImplicitOverride`, `noFallthroughCasesInSwitch`, + `verbatimModuleSyntax` and `isolatedModules`. +- **T5 — `apps/web` was authored by hand, not left as CLI output.** The official + scaffolder (`create-start-app` 0.59.45, run in a scratchpad probe only) was used to + learn the current API shape, then discarded. Its output could not be used as-is: its + `styles.css` ships a complete custom visual direction (bespoke palette, a remote + Google Fonts `@import`, gradients, `.island-shell`/`.feature-card` classes) and + `components.json` defaults to base colour **`zinc`**. R13 requires `neutral` and R16 + plus the human's gate instruction require default tokens only with no visual-direction + decisions. Authoring the app directly satisfies R18 by construction rather than by + pruning, and keeps the remote font request (a hermeticity hazard) out of the repo. +- **T5 — the test config is a separate `vitest.config.ts`.** A `test` block inside + `vite.config.ts` is no longer valid against Vite 8's `UserConfig` type (the typecheck + gate caught it: `'test' does not exist in type 'UserConfigExport'`). design.md allows + either shape. The split also keeps the Nitro/Start SSR plugins out of the smoke test, + which is what makes it hermetic (R56). +- **T6 — the shadcn `neutral` token block was taken verbatim from the shadcn + registry.** `shadcn add button card` installed the components but wrote **no** CSS + variables, so `bg-card` / `bg-primary` would not have existed and the styling chain + would have been silently broken. Fetched the canonical values from + `https://ui.shadcn.com/r/colors/neutral.json` (`cssVarsV4`) and wrote them with the + Tailwind v4 `@theme inline` wiring. **No invented values.** The full default set is + kept, including the `.dark` block — those are shadcn's defaults and nothing in the app + toggles them, so R16 (no switcher, no toggle, no custom palette) holds. +- **T6 — `shadcn add` left a missing dependency.** `button.tsx` imports `cva` from + `class-variance-authority`, which the CLI did not add to `package.json`; the typecheck + gate caught it and it was added explicitly. The CLI did add `cn@0.5.0` and + `radix-ui@1.8.1` — `cn` is published from `github.com/shadcn-ui/cn` (the official + shadcn org), checked because a short package name is a typosquat shape. +- **T7 — RTL cleanup is wired in `vitest.setup.ts`.** The first green attempt failed + with "Found multiple elements with the role button": Testing Library's automatic + cleanup only self-registers when Vitest runs with globals enabled, and this suite uses + explicit imports instead. An `afterEach(cleanup)` setup file fixes it for every future + spec rather than per file. +- **T7 — the page component lives in `src/components/home-page.tsx`.** The spec file + cannot sit in `src/routes/` (the TanStack route generator scans that directory), and + the route module's component was not exported. Extracting the component gives the + spec a real public interface to render and keeps `src/routes/index.tsx` as pure + wiring. +- **T8 — `@types/node` was pruned from `apps/web` after an empirical check.** It was + only reachable through my own `types: ["vite/client", "node"]`; with `"node"` removed, + `tsc --noEmit` still passes, so per R18 the dependency is genuinely unused and is + gone. `react-dom`, `typescript` and the `@types/react*` packages have no direct import + but are required by the runtime and the gates, so they stay. +- **`routeTree.gen.ts` is committed, not gitignored.** CI runs `typecheck` before + `build`, and the typecheck needs the generated route tree to resolve + `./routeTree.gen`. It is Prettier-ignored (the file's own header says to exclude it + from formatters) and the generator rewrites it deterministically, so `git status` + stays clean after a build (R12). + +## Verification so far + +- `pnpm typecheck` / `pnpm test` / `pnpm build` / `pnpm format:check` — all green. +- The typecheck gate was **proven to actually fail** on a real type error twice during + the run (the Vite 8 `test` key, the missing `cva` dependency), which is the + load-bearing evidence for R9 given there is no linter. +- `pnpm dev` → `http://localhost:3000/` returns **200** with «Hola Mundo» rendered, + `data-slot="card"` and `data-slot="button"` in the markup. +- The compiled stylesheet served at `/src/styles.css` contains the resolved utilities + `.bg-card`, `.text-card-foreground`, `.bg-primary`, `.text-primary-foreground`, + `.rounded-xl`, `.min-h-screen` and the neutral token values (`--card: oklch(1 0 0)`, + `--primary: oklch(0.205 0 0)`) — the styling chain is proven applied end to end, not + merely present in the markup (R15). +- `git status` is clean of build output after `build` + `test` + a `dev` session; + `.turbo/`, `.output/` and `.nitro/` are ignored (R12). + +## T25 — manual real-run verification (R58, R59) + +Run on 2026-10-17 in the prescribed order. A green suite is **not** evidence the +infrastructure runs; this is. + +| # | Step | Result | +| - | -------------------------------- | ---------------------------------------------------------------------------------------------------------- | +| 1 | `pnpm db:up` | ✅ exit 0 in ~6 s; `docker compose ps` → `Up 5 seconds (healthy)`. Returns only once healthy. | +| 2 | `pnpm runner` | ✅ four-entry menu, arrow-key navigation (`↑↓ navigate • ⏎ select`). | +| 3 | «Comprobar conexión» | ✅ `✔ Conexión correcta con localhost:27017, base de datos «memora».` | +| 4 | `pnpm dev` | ✅ Vite 8.3.4 ready in 674 ms on `http://localhost:3000/`. | +| 5 | «Hola Mundo» page loads | ✅ HTTP 200; greeting, `Empezar`, `data-slot="card"` and `data-slot="button"` in the SSR HTML; every referenced asset resolves 200 (client entry module + both stylesheets); compiled CSS carries `.bg-card`/`.bg-primary` and the neutral tokens. Opened in the default browser with `open http://localhost:3000/`. **See the caveat below.** | +| 6 | `pnpm db:down` | ✅ exit 0; container stopped and removed; named volume `demo-memora_memora-mongo-data` preserved. | + +**Caveat on step 5, stated plainly:** Claude in Chrome was **not available** in this +session (no `mcp__claude-in-chrome__*` tools), so the page was verified over HTTP — +status, server-rendered markup, and a fetch of every script/stylesheet the page +references, which is what would break hydration if it 404'd — and then opened in the +real browser. **Nobody has visually confirmed the rendered pixels.** The human should +glance at `http://localhost:3000/` once: expect the greeting in a bordered white card, +centred, with a dark «Empezar» button. + +Observed during step 5 and chased down: the dev server logs one +`notFoundError on route "__root__"` warning. It comes from the browser's automatic +`GET /favicon.ico`, which correctly 404s — the repo has no favicon and the spec never +asks for one. Requesting `/` produces no warning. Benign, and out of this spec's scope. + +### Beyond the six steps — other real-run evidence + +- **R25 (data survives `db:down`)**: inserted a document, ran `db:down`, container + removed and volume kept, `db:up`, the document read back (`count=1`). +- **R26 (`db:reset` empties)**: with a document present, `pnpm db:reset` removed the + volume, brought up a fresh healthy container, `countDocuments()` → `0`, + `getCollectionNames()` → `[]`. +- **R27 (Docker down)**: with the daemon stopped, `pnpm db:up` printed Docker's own + message unchanged (`Cannot connect to the Docker daemon at + unix:///…/docker.sock. Is the docker daemon running?`) and exited 1. No masking. +- **R47/R48/R50 (destructive guard)**: the prompt reads + `Vas a BORRAR todos los datos de la base «memora». ¿Seguro? (y/N)` — note `(y/N)`, + default **no**. Enter → `Operación cancelada: no se ha borrado nada.` and the seeded + document was **still there** (`count=1`). +- **R49 (accepted ⇒ really drops)**: answering `y` → `✔ Base de datos «memora» + borrada.` and the real database was empty afterwards (`count=0`, no collections). +- **R41 (Mongo down)**: with the container down, «Comprobar conexión» printed the + driver's own `connect ECONNREFUSED ::1:27017, connect ECONNREFUSED 127.0.0.1:27017` + plus `¿Está Mongo levantado? Prueba con \`pnpm db:up\`.`, returned to the menu, and + «Salir» still exited 0. No stack trace. +- **R42/R43**: with `.env` removed and `MONGODB_URI` unset, «Cargar datos de prueba» + printed its `TODO` (no DB access) and «Comprobar conexión» printed + `✖ MONGODB_URI no está definida. Copia .env.example a .env …` **without attempting a + connection**, menu still usable. +- **R35**: `tsx` does forward Node's `--env-file-if-exists`, so D11's preferred path + stands and no `dotenv` fallback was needed. With `.env` absent the runner starts fine + (exit 0); a shell-exported `MONGODB_URI` is picked up. Node prints its own + `.env not found. Continuing without it.` notice (three times, once per tsx child + process) — cosmetic only. +- **R39/R44**: «Salir» exits 0 closing the client; Ctrl+C at a prompt exits quietly + with no stack trace and no `ELIFECYCLE` noise. +- **R5**: `lemony doctor` independently reports + `✓ cli-resolution: Telemetry CLI resolves from node_modules/.bin/lemony`. + +## Final gate run (T23 hermetic check included) + +Run with the Mongo container removed **and Docker Desktop shut down**: + +| Gate | Result | +| ------------------ | ---------------------------------------------------- | +| `pnpm typecheck` | ✅ 3/3 workspaces | +| `pnpm format:check`| ✅ all matched files | +| `pnpm test` | ✅ 20 tests (db 11, console-runner 7, web 2) | +| `pnpm build` | ✅ 1/1 | +| `pnpm audit` | ✅ no known vulnerabilities | + +**The typecheck gate was proven to actually fail** (section G acceptance criterion), +by a hand probe: `resolveMongoUri`'s return type was mutated `string` → `number` +behind a restore trap, `pnpm typecheck` went red with +`src/config.ts(25,3): error TS2322: Type 'string' is not assignable to type 'number'` +and `Failed: @memora/db#typecheck`, and the trap restored the file (tree clean, no +`.bak` left, all four gates green again afterwards). This matters more than usual here: +there is no linter, so `typecheck` is the only mechanical gate catching this class of +error. It had already failed for real twice during the run (the Vite 8 `test` key and +the missing `class-variance-authority` dependency). + +`harness.config.yml` validated by `lemony doctor` → `✓ config: harness.config.yml is +valid.` with `gates: [typecheck, 'format:check', test, build]` and no `merge:` block, +so `merge.allow_no_checks` stays at its default `false`. + +**Hermeticity (R56)**: the suite is green with no Mongo container and the Docker daemon +down. For the "no network" half, no source or spec file references `fetch`, +`XMLHttpRequest`, or the `http`/`https`/`net`/`dns` modules — grepped, zero hits — and +the front smoke test renders the component directly with the Nitro/Start SSR plugins +excluded from `vitest.config.ts`. I did **not** physically sever the network interface, +so that half rests on the code-level evidence rather than an executed experiment. + +**R12**: after a full `build` + `test` + `dev` cycle, `git status --porcelain -uall` +shows no untracked (`??`) and no unstaged-modified entries — only the staged work. + +**R29**: `grep` for the driver outside `packages/db` returns a single hit, +`packages/db/src/client.ts` itself. No other workspace imports `mongodb`, and neither +`apps/web` nor `console-runner` declares it as a dependency. `apps/web` declares no +dependency on `@memora/db` (D1). + +Docker Desktop was started by me for this verification and **shut down again +afterwards**, restoring the machine to the state it was in at the start of the session. + +## Next action + +Hand back to the Orchestrator for the review gate. Everything is staged and +uncommitted; HEAD is still the spec commit. The Orchestrator commits on the human's OK +and opens the PR. + +## Review evidence — full pass (pre-gate, uncommitted) + +Reviewer, fresh context, 2026-10-17. Scope: the staged diff against anchor +`11be63560fbbb9c132e2ae635923b080b244a95a`, 49 files, whole `tasks.md` as the single +group. Ledger: `.claude/state/tasks/1/review-ledger/full-pass.json` — validated green +(criteria 59/59, gates 4/4, passes 5/5, no spec-side problems). + +**Verdict: APPROVE** — with one headline advisory and three hardening notes. No +requirement fails; one (R48) is PARTIAL on test coverage by an approved design decision. + +### Gates, re-run independently + +The first run came back as turbo **cache replays**, which is not fresh execution, so +every gate was re-run with `TURBO_FORCE=true`: + +| Gate | Result (cache bypassed) | +| --- | --- | +| `typecheck` | 3/3 workspaces green | +| `format:check` | all matched files clean | +| `test` | 20/20 green (db 11, console-runner 7, web 2), Docker daemon **down** | +| `build` | 1/1, exit 0, `.output/nitro.json` generated | +| `pnpm audit` | no known vulnerabilities | +| `pnpm install --frozen-lockfile` | green — CI's first step, the likeliest CI break | + +**The `typecheck` gate was independently proven to go red.** Since the project has no +linter by decision, this is the load-bearing gate, so I did not take it on trust: +mutating `resolveMongoUri`'s return type to `number` produced `0 successful, 3 total`, +`Failed: @memora/db#typecheck`, `error TS2322`, plus a cross-workspace `TS2345` in +`console-runner`. Restore trap fired; tree clean. + +### Real run (what a green suite cannot prove) + +- **Front end**: `pnpm dev` ready in 3 s; `GET /` → **200** with «Hola Mundo» in the SSR + HTML, `lang="es"`, `data-slot="card"` + `card-header/title/description/content` and + `data-slot="button"` («Empezar»). `/src/styles.css` → 200, 21 721 bytes, containing the + **resolved** utilities `.bg-card`, `.text-card-foreground`, `.bg-primary`, + `.text-primary-foreground`, `.rounded-xl`, `.min-h-screen`, `.shadow-sm`, `.max-w-md` + and the neutral token values. The styling chain is applied end to end, not merely + imported. Dev log: zero errors or warnings. +- **No remote font survived.** Zero external URLs in the served HTML; the only URL in the + compiled CSS is Tailwind's own licence comment. The scaffolder's Google Fonts `@import` + hermeticity hazard is genuinely absent (R18). +- **shadcn tokens are not invented.** Fetched `https://ui.shadcn.com/r/colors/neutral.json` + and compared `cssVarsV4` against `src/styles.css`: **every light and dark value matches + byte for byte**, including the `.dark` block and the `--sidebar-primary: + oklch(0.488 0.243 264.376)` quirk. The hand-repair is faithful to the registry. +- **Runner**, driven through a real pty: exactly four menu entries, arrow-key navigation, + loop back after each operation, «Salir» → exit 0. With Mongo down, «Comprobar conexión» + printed the driver's own `connect ECONNREFUSED ::1:27017, connect ECONNREFUSED + 127.0.0.1:27017` plus the `pnpm db:up` hint, no stack trace, menu still usable. With + `MONGODB_URI` unset and no `.env` load: the explicit configuration error, **no + connection attempted**, menu usable. «Cargar datos de prueba» printed its `TODO` and + touched nothing. +- **R12**: after a full `build` + `test` + a `dev` session, `git status --porcelain -uall` + showed no untracked and no unstaged-modified entries — only the staged work. +- **R5**: `.claude/hooks/lib/lemony.sh --version` → `0.10.0`. +- **Docker-dependent steps could not be executed.** The daemon is down and the Docker CLI + itself hangs on this machine (a bare `docker info` hangs identically), so R24–R27 rest on + inspection plus the Implementer's recorded runs. The scripts are bare `docker compose` + invocations with no wrapper, retry or `|| true`, so Docker's error and exit code + propagate unchanged by construction (R27). +- **The page was still not visually confirmed.** No browser automation is available to me + either (no Claude-in-Chrome or built-in browser tools; `WebFetch` refuses localhost), so + this was HTTP-level verification only. **A human glance at `http://localhost:3000/` + remains part of the gate** — expect the greeting in a bordered white card, centred, with + a dark «Empezar» button. + +### Mutation probes (hand path — declared risk `data-loss`) + +Six files probed, eight mutants, each behind a restore trap; tree verified clean after +every probe, no `.bak` stranded. + +| Mutant | Outcome | +| --- | --- | +| `clean-database.ts` — confirmation guard removed | **killed** | +| `main.ts:116` — destructive confirm `default: false` → `true` | **SURVIVED** | +| `check-connection.ts` — `pnpm db:up` hint dropped | **killed** | +| `seed-data.ts` — message claims success instead of `TODO` | **killed** | +| `client.ts` — timeout 5 000 → 50 000 ms | **killed** | +| `config.ts` — `?.trim()` dropped | **killed** | +| `config.ts` — return type `string` → `number` (typecheck probe) | **killed** | + +The `R50` guard — the one that makes a declined confirmation touch nothing — is genuinely +protected. The `R48` default is not; see below. + +> Worth knowing at the checkpoint: this project has no `test:mutation` script, so these +> probes were artisanal, one shell round trip each. Declaring a `test:mutation` script in +> the root `package.json` (driving Stryker or any mutation tool) would activate the cheap +> batched path on the next review. + +### Findings + +**1. Advisory, headline — the destructive confirm's safe default has no regression test.** +`console-runner/src/main.ts:116` is `default: false, // Enter cancels (R48).` and that is +correct; the Implementer's real run recorded the `(y/N)` rendering, Enter cancelling, and +the seeded document intact. But flipping it to `default: true` — turning Enter from +*cancel* into *delete the database* — leaves the whole `console-runner` suite green, 7/7. +This is the only destructive operation in the delivery, in a group that declared +`[risk: data-loss]`, and its guard is held up by a one-off manual observation that does not +regress. + +I did **not** reject on it, deliberately: the implementation meets R48, and the gap sits +inside `design.md`'s *human-approved* decision that the prompt layer is not tested +("testing it would mean driving a TTY"). Rejecting would overrule a decision the human +already signed at the spec gate. Cheapest closure if the human wants it closed, no TTY +needed: extract the confirm's options (or a `buildCleanConfirm(database)` factory) and +assert `default === false` and that the message names the database — roughly ten lines. + +**2. Advisory — Ctrl+D at a prompt exits 13 with a Node warning, and it is undocumented.** +Reproduced independently: stdin EOF at the menu leaves +`Warning: Detected unsettled top-level await at console-runner/src/main.ts:146` and +`ELIFECYCLE Command failed with exit code 13`. R44 specifies Ctrl+C, which works +correctly, so this is *unspecified* rather than failing, and it is non-destructive — I +judge it acceptable to ship for a local maintenance tool. But it is **absent from the +record above**, and R58/R59 make `progress.md` the durable real-run evidence; the human +should know before signing. Noted here so it is no longer undocumented. + +**3. Security, medium / hardening — the credential-less Mongo publishes on all interfaces.** +`docker-compose.yml:20` is `- '27017:27017'`, which binds `0.0.0.0`. On any shared or +untrusted network, every host on the LAN gets unauthenticated full read/write on every +database. The header comment warns against copying the file to a reachable environment, +but the default binding already makes the dev machine reachable. `'127.0.0.1:27017:27017'` +closes it and still satisfies R22's port publication and R28's +`mongodb://localhost:27017/memora`. Not a spec violation — R22's letter is met — so it is a +recommendation, not a block. + +**4. Low / informational.** +- The shadcn components take `cn` from a third-party npm package rather than a local + `src/lib/utils.ts`. **Provenance checked and clean**: npm metadata resolves to + `github.com/shadcn-ui/cn` and the lockfile integrity hash matches the registry's exactly. + Worth pinning exactly — it currently carries a caret. +- `progress.md`'s claim that the `apps/web` toolchain is pinned "**exactly** (no carets)" + is inaccurate for two dependencies: `cn: ^0.5.0` and `radix-ui: ^1.8.1`. Everything in + the tabulated list is indeed caret-free. +- Result assertions use `toEqual` rather than `toStrictEqual` in six places + (`clean-database.spec.ts:23/31/44`, `check-connection.spec.ts:17`, + `client.spec.ts:39/51/73`), so an unexpected `undefined`-valued property would pass. +- The menu dispatch (`main.ts:71`) is an `if`-chain with no terminal `else`, so an + unrecognised choice would spin the `for(;;)` loop silently. Unreachable today (closed + typed union) — hardening only. +- `apps/web/components.json` aliases point at `#/lib/utils` and `#/hooks`, neither of which + exists, so the next `shadcn add` will generate an import that does not resolve. +- `.prettierignore`'s two extra entries (`harness.config.schema.json`, + `docs/playbooks/README.md`) were judged **compliant** with R11, not drift: both files + exist, are installer-dropped harness artifacts regenerated by `lemony repair`/`update`, + and so fall inside R11's general clause ("vendor and generated paths") and squarely + inside its stated rationale. + +### Why no issue comment and no stale-approve record + +There is no PR and no commit — the work is entirely staged and `HEAD` is still the anchor. +A stale-approve record computed now would be actively misleading: the merge-base is +`95075e8` and the committed diff `merge-base..HEAD` contains **2 files** (the PRD and the +product brief), **none** of the 49 files reviewed, so `Reviewed-tree` would name a tree +without any of the implementation. Because the merge executor trusts the newest comment +carrying both markers, planting them now could later authorize a merge of content nobody +reviewed. The record belongs on the real full pass, once the Orchestrator has committed on +the human's OK and opened the PR. diff --git a/.claude/state/tasks/1/review-ledger/full-pass.json b/.claude/state/tasks/1/review-ledger/full-pass.json new file mode 100644 index 0000000..a7e5b05 --- /dev/null +++ b/.claude/state/tasks/1/review-ledger/full-pass.json @@ -0,0 +1,202 @@ +{ + "version": 2, + "step": "full-pass", + "criteria": [ + { "id": "R1", "evidence": "pnpm-workspace.yaml declares apps/*, packages/* and console-runner; root package.json is private. `pnpm install --frozen-lockfile` reports \"Scope: all 4 workspace projects\"." }, + { "id": "R2", "evidence": "package.json: packageManager pnpm@10.19.0, engines.node \">=24.16.0 <25\"; .nvmrc holds 24.16.0. Machine runs node v24.16.0 / pnpm 10.19.0 — read back in this review." }, + { "id": "R3", "evidence": "Ran `pnpm install --frozen-lockfile` myself: exit 0, \"Lockfile is up to date\", no interactive prompt (pnpm-workspace.yaml onlyBuiltDependencies pre-approves esbuild/lightningcss native builds)." }, + { "id": "R4", "evidence": "`ls package-lock.json` -> No such file; `git ls-files package-lock.json` empty (deleted from index, diff shows D). pnpm-lock.yaml staged (5235 lines)." }, + { "id": "R5", "evidence": "Ran `.claude/hooks/lib/lemony.sh --version` -> 0.10.0; node_modules/.bin/lemony present (mode 755)." }, + { "id": "R6", "evidence": "Machine-checked the script set against R6's list: exactly 10 keys, exact match true (dev, build, test, typecheck, format, format:check, db:up, db:down, db:reset, runner)." }, + { "id": "R7", "evidence": "All four workspace-spanning scripts are `turbo run `; turbo.json declares dev (cache false, persistent), build, test, typecheck. Turbo output shows \"Packages in scope: @memora/db, @memora/web, console-runner\"." }, + { "id": "R8", "evidence": "tsconfig.base.json sets strict: true (plus noUncheckedIndexedAccess, noImplicitOverride, noFallthroughCasesInSwitch, verbatimModuleSyntax, isolatedModules); all three workspace tsconfigs extend it." }, + { "id": "R9", "evidence": "Ran TURBO_FORCE=true pnpm typecheck: 3/3 green on fresh execution. Then hand-probed the gate: mutated resolveMongoUri's return type string->number behind a restore trap; turbo reported \"0 successful, 3 total\" and \"Failed: @memora/db#typecheck\" with error TS2322 and a cross-workspace TS2345 in console-runner. Tree restored clean." }, + { "id": "R10", "evidence": "Ran `pnpm format:check` (prettier --check .): \"All matched files use Prettier code style!\"." }, + { "id": "R11", "evidence": ".prettierignore excludes node_modules/, .claude/, pnpm-lock.yaml, build outputs (dist/, .output/, .tanstack/, .vite/), caches (.turbo/, coverage/) and generated **/routeTree.gen.ts. It also excludes harness.config.schema.json and docs/playbooks/README.md: I confirmed both files exist, are installer-dropped harness artifacts regenerated by `lemony repair`/`update`, and so fall inside R11's general clause (\"vendor and generated paths\") and squarely inside its stated rationale. Judged compliant, not drift." }, + { "id": "R12", "evidence": "Ran a full build + test + a dev session myself, then `git status --porcelain -uall`: no `??` and no unstaged-modified entries — only the staged work. .gitignore covers .env, dist/, .output/, .tanstack/, .nitro/, .turbo/, .vite/, coverage/, *.tsbuildinfo." }, + { "id": "R13", "evidence": "apps/web is a TanStack Start app (@tanstack/react-start 1.169.3) in strict TS; tailwindcss 4.3.3 wired via @tailwindcss/vite; components.json has style \"new-york\" and baseColor \"neutral\". I fetched https://ui.shadcn.com/r/colors/neutral.json and diffed cssVarsV4 against src/styles.css: every light and dark value matches byte for byte — the tokens are the registry's, not invented." }, + { "id": "R14", "evidence": "Ran `pnpm dev` myself: ready in 3s, GET http://localhost:3000/ -> HTTP 200 with «Hola Mundo» in the server-rendered HTML." }, + { "id": "R15", "evidence": "Served HTML carries data-slot=\"card\", card-header, card-title, card-description, card-content and data-slot=\"button\" with «Empezar». Fetched /src/styles.css (200, 21721 bytes): the compiled sheet contains resolved .bg-card, .text-card-foreground, .bg-primary, .text-primary-foreground, .rounded-xl, .min-h-screen, .shadow-sm, .max-w-md plus the neutral token values — the chain is applied, not merely imported." }, + { "id": "R16", "evidence": "Default tokens only: no theme switcher, no toggle, no custom palette anywhere in the diff. The `.dark` block and `@custom-variant dark` are shadcn's own defaults (verified against the registry) and nothing in the app sets the `dark` class." }, + { "id": "R17", "evidence": "Ran TURBO_FORCE=true pnpm build (cache bypassed): 1/1 successful, exit 0, \"Generated .output/nitro.json\". One benign rolldown notice about a module-level directive; no error." }, + { "id": "R18", "evidence": "No scaffolder residue: zero external URLs in the served HTML and none in the compiled CSS except Tailwind's own license comment (/*! tailwindcss v4.3.3 ... https://tailwindcss.com */) — so no remote Google Fonts @import survived. No demo routes or assets; @types/node pruned from apps/web. Every declared dependency traces to an import, the gates or the runtime." }, + { "id": "R19", "evidence": "apps/web/src/components/home-page.spec.tsx renders HomePage and asserts the «Hola Mundo» heading and a button whose data-slot is \"button\". Ran the suite with the Docker daemon down: 2/2 green. vitest.config.ts loads only the React transform, excluding the Start/Nitro SSR plugins." }, + { "id": "R20", "evidence": "Grepped apps/web/package.json for @memora/db: no match. No front-end file imports it." }, + { "id": "R21", "evidence": "The unwanted path did not fire — no shadcn/Tailwind incompatibility was hit, and all four gates are green on the combination. progress.md tabulates the pinned versions anyway. Noted separately that progress.md's \"no carets\" claim is inaccurate for two apps/web deps (cn ^0.5.0, radix-ui ^1.8.1)." }, + { "id": "R22", "evidence": "docker-compose.yml: single service, image mongo:8, ports '27017:27017', no credentials/env, named volume memora-mongo-data mounted at /data/db, healthcheck `mongosh --quiet --eval db.adminCommand('ping')` with interval/timeout/retries/start_period. Flagged separately that the port publishes on all interfaces rather than loopback." }, + { "id": "R23", "evidence": "The file opens with \"LOCAL DEVELOPMENT ONLY — no credentials.\" and three paragraphs spelling out that anyone reaching the port has full read/write and that it must never be copied to an externally reachable environment." }, + { "id": "R24", "evidence": "db:up is `docker compose up -d --wait` — detached, and --wait blocks until the healthcheck reports healthy. I could not execute it: the Docker daemon is down on this machine and the Docker CLI itself hangs (a bare `docker info` hangs identically), so I verified the script by inspection and rely on the Implementer's recorded run (exit 0 in ~6s, `Up 5 seconds (healthy)`)." }, + { "id": "R25", "evidence": "db:down is `docker compose down` with no -v, so the named volume survives by construction. Implementer's recorded experiment: document inserted, db:down, db:up, read back count=1." }, + { "id": "R26", "evidence": "db:reset is `docker compose down -v && docker compose up -d --wait` — volume removed, then a fresh healthy container. Implementer's recorded experiment: countDocuments() 0 and getCollectionNames() [] afterwards." }, + { "id": "R27", "evidence": "All three db:* scripts are bare `docker compose` invocations — no wrapper, no retry loop, no `|| true`, so Docker's own stderr and exit code propagate unchanged through pnpm. My own attempt hung inside the Docker CLI rather than the script (bare `docker info` hangs the same way with the daemon stopped), which itself shows the script adds no masking; the Implementer recorded the exact unmasked daemon error and exit 1." }, + { "id": "R28", "evidence": "Database name `memora` and URI mongodb://localhost:27017/memora appear in .env.example, the compose header comment, config.ts's error text and README.md. Confirmed at runtime: the client resolves databaseName \"memora\" from the URI." }, + { "id": "R29", "evidence": "Grepped the whole tree: the only `from 'mongodb'` is packages/db/src/client.ts:1, and packages/db/package.json is the only manifest declaring the driver." }, + { "id": "R30", "evidence": "resolveMongoUri(env: EnvRecord) reads only its argument — no process.env access, no file read. config.spec.ts pins this with a test that sets process.env.MONGODB_URI and still expects a throw for an empty record." }, + { "id": "R31", "evidence": "Throws naming both MONGODB_URI and .env.example, with no default fallback; 6 tests cover present / absent / empty / whitespace-only / trimming / no-process.env-fallback. Mutant: dropped the `?.trim()` — 2 tests went red (killed)." }, + { "id": "R32", "evidence": "SERVER_SELECTION_TIMEOUT_MS = 5_000 passed to the MongoClient constructor; client.spec.ts asserts options.serverSelectionTimeoutMS <= 5000. Mutant: widened to 50_000 — \"expected 50000 to be less than or equal to 5000\" (killed)." }, + { "id": "R33", "evidence": "pingDatabase and dropDatabase both call client.db() with no argument, so the database is whatever the URI encodes. Tests cover a second database name (\"otra-base\" on db.internal:27018) to prove nothing is hard-coded." }, + { "id": "R34", "evidence": ".env.example is staged with MONGODB_URI=mongodb://localhost:27017/memora; `git check-ignore -v .env` resolves to .gitignore:17. A real .env exists in the worktree and is not staged." }, + { "id": "R35", "evidence": "The runner script is `tsx --env-file-if-exists=.env console-runner/src/main.ts`, loaded from the repository root. I ran the entry point without the flag (pnpm exec tsx console-runner/src/main.ts) and it started fine with no .env in play, confirming the absent-file path does not fail." }, + { "id": "R36", "evidence": "packages/db/package.json points types and exports at ./src/index.ts, declares no build script and emits no dist/; `tsc --noEmit` passes for @memora/db on its own in the fresh typecheck run." }, + { "id": "R37", "evidence": "Dependency is the official mongodb 7.7.0 (lockfile entry confirmed); no Mongoose, Prisma or any other ODM anywhere in the manifests." }, + { "id": "R38", "evidence": "Drove the real menu through a pty: exactly four entries — Comprobar conexión con Mongo / Limpiar base de datos / Cargar datos de prueba / Salir — with \"↑↓ navigate • ⏎ select\" and arrow-key movement working. No flags required." }, + { "id": "R39", "evidence": "Drove it myself: after a failed connection check the loop returned to the menu and stayed usable; selecting «Salir» exited 0. closeClient() is awaited on every exit path." }, + { "id": "R40", "evidence": "checkConnection pings and returns { ok: true, host, database }; main.ts prints «Conexión correcta con , base de datos «»». Covered by check-connection.spec.ts and by client.spec.ts's ping tests." }, + { "id": "R41", "evidence": "Reproduced with Mongo down: the runner printed the driver's own message verbatim (\"connect ECONNREFUSED ::1:27017, connect ECONNREFUSED 127.0.0.1:27017\") plus \"¿Está Mongo levantado? Prueba con `pnpm db:up`.\", returned to the menu, and no stack trace appeared. Mutant: dropped the hint — the spec went red (killed)." }, + { "id": "R42", "evidence": "Reproduced with MONGODB_URI unset and no .env load: the runner printed \"✖ MONGODB_URI no está definida. Copia .env.example a .env …\" and no ECONNREFUSED followed, so no connection was attempted; the menu stayed usable. Structurally guaranteed — resolveMongoUri throws before createMongoClient is reached." }, + { "id": "R43", "evidence": "Reproduced: «Cargar datos de prueba» printed \"TODO: los datos de prueba llegarán con el modelo de dominio. No se ha escrito nada en la base de datos.\" and touched nothing. loadSeedData takes no client at all; seed-data.spec.ts pins both the TODO text and the zero arity. Mutant: rewrote the message to claim success — killed." }, + { "id": "R44", "evidence": "Ctrl+C is handled: ExitPromptError is matched by name, the client is closed and the process leaves quietly with no stack trace (Implementer's recorded run; the code path is explicit at main.ts:138-143). ADVISORY, outside R44's letter: I reproduced stdin EOF (Ctrl+D) at the menu and it leaves \"Warning: Detected unsettled top-level await at console-runner/src/main.ts:146\" and ELIFECYCLE exit 13. R44 specifies Ctrl+C only, so this is unspecified rather than failing; it is undocumented in progress.md and named in my verdict." }, + { "id": "R45", "evidence": "Grepped @inquirer/prompts: imported only in console-runner/src/main.ts. All three operations are plain functions receiving the client as a parameter, and all three are tested against hand-written doubles." }, + { "id": "R46", "evidence": "The runner is executed by tsx straight over TypeScript; console-runner/package.json declares no build script." }, + { "id": "R47", "evidence": "main.ts:112-117 reads target.db().databaseName locally (no server call) and the confirm message names it: \"Vas a BORRAR todos los datos de la base «memora». ¿Seguro?\". The prompt is issued before cleanDatabase is called." }, + { "id": "R48", "evidence": "PARTIAL. The implementation is correct — main.ts:116 is `default: false, // Enter cancels (R48).` — and the Implementer's real run recorded the \"(y/N)\" rendering with Enter cancelling and the seeded document intact. But no automated test asserts it: I mutated main.ts:116 to `default: true` (Enter would delete the database) and the entire console-runner suite stayed green, 7/7. The gap is inside design.md's human-approved \"prompt layer not tested, by decision\", so it is a specified gap rather than an implementer omission; raised as the headline advisory in my verdict with a cheap fix." }, + { "id": "R49", "evidence": "cleanDatabase calls dropDatabase(client) on the URI-encoded database and returns { status: 'dropped', database }; clean-database.spec.ts asserts dropDatabase was called exactly once. Implementer's real run confirmed the database was actually empty afterwards." }, + { "id": "R50", "evidence": "The guard `if (!confirmed) return { status: 'cancelled' };` sits before anything touches the client, and the spec asserts not even db() was called. Mutant: removed the guard — the declined test went red (killed). This is the data-loss guard and it is genuinely protected." }, + { "id": "R51", "evidence": "The drop is wrapped in try/catch returning { status: 'failed', error }; the spec drives a rejecting double and asserts the reported error, and main.ts prints it and loops back to the menu rather than throwing." }, + { "id": "R52", "evidence": ".github/workflows/ci.yml triggers on pull_request to main, installs with `pnpm install --frozen-lockfile` and caches the pnpm store via setup-node's cache: pnpm, then runs typecheck, format:check, test and build. The workflow has never executed (no PR yet), so I verified what I could: all three action major tags resolve (actions/checkout@v7, actions/setup-node@v7, pnpm/action-setup@v6 — HTTP 200 each) and `pnpm install --frozen-lockfile` succeeds locally, which is the step most likely to break CI." }, + { "id": "R53", "evidence": "Read the workflow line by line: no continue-on-error, no `||`, no `set +e`, no composite step that could swallow an exit code. Each gate is its own step, so any non-zero exit fails the job." }, + { "id": "R54", "evidence": "setup-node uses node-version-file: .nvmrc, and pnpm/action-setup is deliberately given no `version:` input so it reads the root packageManager field. Both are commented in the workflow with the reason." }, + { "id": "R55", "evidence": "harness.config.yml declares gates as exactly [typecheck, 'format:check', test, build] and carries no `merge:` block, so merge.allow_no_checks stays at its default false. Read the committed file directly." }, + { "id": "R56", "evidence": "Ran the whole suite (20 tests: db 11, console-runner 7, web 2) with the Docker daemon down — green, cache bypassed. For the network half: grepped the sources for fetch/XMLHttpRequest and the http/https/net/dns/tls modules, zero hits; the front spec excludes the SSR plugins; and client.spec.ts's real MongoClient construction uses a non-SRV mongodb:// URI, which resolves no DNS until connect. The network interface was not physically severed, so that half rests on code-level evidence — the same honest caveat progress.md states." }, + { "id": "R57", "evidence": "README.md documents the quickstart (pnpm install, cp .env.example .env, db:up, dev), a db:* table, the runner and its two behaviours, and the four gate commands with the no-linter rationale." }, + { "id": "R58", "evidence": "progress.md carries the six-step table in the prescribed order (db:up -> runner -> check connection -> dev -> page loads -> db:down), each with its result, plus a further section of real-run evidence for R25, R26, R27, R41, R42, R43, R47-R50 and R35." }, + { "id": "R59", "evidence": "progress.md states explicitly that a green suite is not evidence the infrastructure runs, and states plainly that nobody has visually confirmed the rendered pixels. I could not close that gap either — no browser automation is available to me (no claude-in-chrome or built-in browser tools; WebFetch refuses localhost), so I verified over HTTP only and the visual check remains the human's at the gate." } + ], + "gates": [ + { "kind": "script", "script": "typecheck", "evidence": "TURBO_FORCE=true pnpm typecheck — 3/3 workspaces green on fresh execution (the first run was a turbo cache replay, so I re-ran it cache-bypassed). Also hand-probed red: a mutated return type produced \"0 successful, 3 total\" / \"Failed: @memora/db#typecheck\"." }, + { "kind": "script", "script": "format:check", "evidence": "pnpm format:check (prettier --check .) — \"All matched files use Prettier code style!\"." }, + { "kind": "script", "script": "test", "evidence": "TURBO_FORCE=true pnpm test — 20/20 green, cache bypassed (@memora/db 11, console-runner 7, @memora/web 2), with the Docker daemon down." }, + { "kind": "script", "script": "build", "evidence": "TURBO_FORCE=true pnpm build — 1/1 successful, exit 0, .output/nitro.json generated. One benign rolldown module-level-directive notice." }, + { "kind": "real-run", "evidence": "Beyond the scripts: ran `pnpm install --frozen-lockfile` (CI's first step, green); started pnpm dev and fetched / (200) plus /src/styles.css (200) and the TanStack stylesheet (200), checking the SSR markup and the resolved utilities; drove the real @inquirer menu through a pty for the four entries, arrow-key navigation, the Mongo-down failure path, the unresolved-MONGODB_URI path, the seed TODO and «Salir» (exit 0); reproduced the Ctrl+D exit-13 limitation; ran `.claude/hooks/lib/lemony.sh --version` (0.10.0); and re-checked `git status` clean after build + test + dev. Docker-dependent steps (db:up/down/reset) could not run — the daemon is down and the Docker CLI hangs on this machine — so those rest on inspection plus the Implementer's recorded runs." } + ], + "mutants": { + "basis": "declared-risk", + "files": [ + { + "file": "console-runner/src/actions/clean-database.ts", + "status": "probed", + "probes": [ + { "mutation": "removed the `if (!confirmed) return { status: 'cancelled' };` guard so a declined confirmation falls through to the drop", "outcome": "killed", "killedBy": "console-runner/src/actions/clean-database.spec.ts" } + ] + }, + { + "file": "console-runner/src/main.ts", + "status": "probed", + "probes": [ + { "mutation": "flipped the destructive confirm at main.ts:116 from `default: false` to `default: true`, turning Enter from cancel into delete-the-database", "outcome": "survived" } + ] + }, + { + "file": "console-runner/src/actions/check-connection.ts", + "status": "probed", + "probes": [ + { "mutation": "dropped the `pnpm db:up` hint from the failure message, returning the bare driver message", "outcome": "killed", "killedBy": "console-runner/src/actions/check-connection.spec.ts" } + ] + }, + { + "file": "console-runner/src/actions/seed-data.ts", + "status": "probed", + "probes": [ + { "mutation": "rewrote the pending message to claim \"Datos de prueba cargados correctamente\" instead of TODO", "outcome": "killed", "killedBy": "console-runner/src/actions/seed-data.spec.ts" } + ] + }, + { + "file": "packages/db/src/client.ts", + "status": "probed", + "probes": [ + { "mutation": "widened SERVER_SELECTION_TIMEOUT_MS from 5_000 to 50_000, past R32's cap", "outcome": "killed", "killedBy": "packages/db/src/client.spec.ts" } + ] + }, + { + "file": "packages/db/src/config.ts", + "status": "probed", + "probes": [ + { "mutation": "dropped the `?.trim()` so a whitespace-only MONGODB_URI is accepted as present", "outcome": "killed", "killedBy": "packages/db/src/config.spec.ts" }, + { "mutation": "changed resolveMongoUri's return type from string to number (a typecheck-gate probe rather than a suite probe)", "outcome": "killed", "killedBy": "pnpm typecheck (tsc --noEmit, @memora/db + console-runner)" } + ] + }, + { "file": "docker-compose.yml", "status": "not-applicable", "reason": "no-mutable-logic", "note": "Declarative compose manifest (Group 3, risk: data-loss). Its data-loss surface is the named volume and the published port; no automated test exists that any mutation could make red — it is covered by the real run only (db:down preserves the volume, db:reset removes it), which is why I pressed on it by inspection instead." }, + { "file": "package.json", "status": "not-applicable", "reason": "no-mutable-logic", "note": "Root manifest (Group 1 + Group 3, risk: data-loss). The destructive behaviour lives in a shell string — db:reset's `docker compose down -v` — with no automated coverage by design; verified by reading it and by the Implementer's recorded db:reset experiment. I did machine-check the script set against R6." }, + { "file": ".env.example", "status": "not-applicable", "reason": "no-mutable-logic", "note": "Group 4 (no declared risk): a two-value example file, nothing to flip." }, + { "file": ".github/workflows/ci.yml", "status": "not-applicable", "reason": "no-mutable-logic", "note": "Group 7 (no declared risk): workflow YAML that has never executed, so no suite could kill a mutant. Reviewed by reading, plus live checks that its three action major tags resolve." }, + { "file": ".gitignore", "status": "not-applicable", "reason": "no-mutable-logic", "note": "Group 1 (no declared risk): ignore patterns. Verified behaviourally instead — git status stayed clean after build + test + dev." }, + { "file": ".nvmrc", "status": "not-applicable", "reason": "no-mutable-logic", "note": "Group 1 (no declared risk): a single version string." }, + { "file": ".prettierignore", "status": "not-applicable", "reason": "no-mutable-logic", "note": "Group 1 (no declared risk): ignore patterns; judged against R11's letter and rationale by reading." }, + { "file": ".prettierrc", "status": "not-applicable", "reason": "no-mutable-logic", "note": "Group 1 (no declared risk): formatter options." }, + { "file": "README.md", "status": "not-applicable", "reason": "no-mutable-logic", "note": "Group 7 (no declared risk): documentation." }, + { "file": "apps/web/components.json", "status": "not-applicable", "reason": "no-mutable-logic", "note": "Group 2 (no declared risk): shadcn CLI config consumed only at generation time." }, + { "file": "apps/web/package.json", "status": "not-applicable", "reason": "no-mutable-logic", "note": "Group 2 (no declared risk): manifest. Checked every dependency against an actual import or gate need." }, + { "file": "apps/web/src/components/home-page.tsx", "status": "not-applicable", "reason": "outside-declared-risk", "note": "Changed by Group 2 (front-end «Hola Mundo»), which declares no risk. Covered by home-page.spec.tsx and by the live SSR fetch." }, + { "file": "apps/web/src/components/ui/button.tsx", "status": "not-applicable", "reason": "outside-declared-risk", "note": "Changed by Group 2, which declares no risk. Vendored shadcn registry output (repaired only by adding the class-variance-authority dependency the CLI omitted)." }, + { "file": "apps/web/src/components/ui/card.tsx", "status": "not-applicable", "reason": "outside-declared-risk", "note": "Changed by Group 2, which declares no risk. Vendored shadcn registry output." }, + { "file": "apps/web/src/routeTree.gen.ts", "status": "not-applicable", "reason": "generated", "note": "Emitted deterministically by the TanStack route generator; committed on purpose so CI's typecheck can resolve ./routeTree.gen before build, and Prettier-ignored." }, + { "file": "apps/web/src/router.tsx", "status": "not-applicable", "reason": "outside-declared-risk", "note": "Changed by Group 2, which declares no risk. Router wiring, exercised by the live dev-server fetch." }, + { "file": "apps/web/src/routes/__root.tsx", "status": "not-applicable", "reason": "outside-declared-risk", "note": "Changed by Group 2, which declares no risk. Shell document, exercised by the live SSR fetch (lang=\"es\", head links, stylesheet 200)." }, + { "file": "apps/web/src/routes/index.tsx", "status": "not-applicable", "reason": "no-mutable-logic", "note": "Group 2 (no declared risk): a one-line createFileRoute binding with no branch to flip." }, + { "file": "apps/web/src/styles.css", "status": "not-applicable", "reason": "no-mutable-logic", "note": "Group 2 (no declared risk): CSS token declarations. Verified a stronger way — diffed byte for byte against the shadcn registry's neutral cssVarsV4, and confirmed the utilities resolve in the compiled sheet." }, + { "file": "apps/web/tsconfig.json", "status": "not-applicable", "reason": "no-mutable-logic", "note": "Group 2 (no declared risk): compiler options." }, + { "file": "apps/web/tsr.config.json", "status": "not-applicable", "reason": "no-mutable-logic", "note": "Group 2 (no declared risk): a single generator target key." }, + { "file": "apps/web/vite.config.ts", "status": "not-applicable", "reason": "no-mutable-logic", "note": "Group 2 (no declared risk): a plugin list; exercised for real by dev and build." }, + { "file": "apps/web/vitest.config.ts", "status": "not-applicable", "reason": "no-mutable-logic", "note": "Group 2 (no declared risk): test-runner config — the harness that would kill a mutant, not a target of one." }, + { "file": "apps/web/vitest.setup.ts", "status": "not-applicable", "reason": "no-mutable-logic", "note": "Group 2 (no declared risk): an afterEach(cleanup) registration in the test harness itself." }, + { "file": "console-runner/package.json", "status": "not-applicable", "reason": "no-mutable-logic", "note": "Group 5 (no declared risk): manifest." }, + { "file": "console-runner/tsconfig.json", "status": "not-applicable", "reason": "no-mutable-logic", "note": "Group 5 (no declared risk): compiler options." }, + { "file": "harness.config.yml", "status": "not-applicable", "reason": "no-mutable-logic", "note": "Group 7 (no declared risk): harness configuration; the gates list was read directly and matches R55 exactly." }, + { "file": "packages/db/package.json", "status": "not-applicable", "reason": "no-mutable-logic", "note": "Group 4 (no declared risk): manifest; exports/types verified by consumers resolving @memora/db from source." }, + { "file": "packages/db/src/index.ts", "status": "not-applicable", "reason": "no-mutable-logic", "note": "Group 4 (no declared risk): re-export barrel with no logic; a mutation would be a compile error, not a behaviour change." }, + { "file": "packages/db/tsconfig.json", "status": "not-applicable", "reason": "no-mutable-logic", "note": "Group 4 (no declared risk): compiler options." }, + { "file": "pnpm-lock.yaml", "status": "not-applicable", "reason": "generated", "note": "Generated by pnpm; verified instead with `pnpm install --frozen-lockfile` (green) and by checking the cn/radix-ui/class-variance-authority/mongodb entries against the npm registry." }, + { "file": "pnpm-workspace.yaml", "status": "not-applicable", "reason": "no-mutable-logic", "note": "Group 1 (no declared risk): workspace globs plus onlyBuiltDependencies; verified behaviourally by the install scoping all 4 projects." }, + { "file": "tsconfig.base.json", "status": "not-applicable", "reason": "no-mutable-logic", "note": "Group 1 (no declared risk): shared compiler options. Its load-bearing effect (strict typecheck going red) was probed through packages/db/src/config.ts instead." }, + { "file": "turbo.json", "status": "not-applicable", "reason": "no-mutable-logic", "note": "Group 1 (no declared risk): task graph declaration; exercised for real by all four gate runs." } + ] + }, + "passes": [ + { + "name": "senior-review", + "outcome": "findings", + "examined": [".env.example", ".github/workflows/ci.yml", ".gitignore", ".nvmrc", ".prettierignore", ".prettierrc", "README.md", "apps/web/components.json", "apps/web/package.json", "apps/web/src/components/home-page.tsx", "apps/web/src/components/ui/button.tsx", "apps/web/src/components/ui/card.tsx", "apps/web/src/routeTree.gen.ts", "apps/web/src/router.tsx", "apps/web/src/routes/__root.tsx", "apps/web/src/routes/index.tsx", "apps/web/src/styles.css", "apps/web/tsconfig.json", "apps/web/tsr.config.json", "apps/web/vite.config.ts", "apps/web/vitest.config.ts", "apps/web/vitest.setup.ts", "console-runner/package.json", "console-runner/src/actions/check-connection.ts", "console-runner/src/actions/clean-database.ts", "console-runner/src/actions/seed-data.ts", "console-runner/src/main.ts", "console-runner/tsconfig.json", "docker-compose.yml", "harness.config.yml", "package.json", "packages/db/package.json", "packages/db/src/client.ts", "packages/db/src/config.ts", "packages/db/src/index.ts", "packages/db/tsconfig.json", "pnpm-lock.yaml", "pnpm-workspace.yaml", "tsconfig.base.json", "turbo.json"], + "findings": [ + { "file": "console-runner/src/main.ts", "line": 116, "summary": "The destructive confirm's `default: false` — the keystroke that separates cancel from delete — has no automated assertion; flipping it to true leaves the suite 7/7 green." }, + { "file": "console-runner/src/actions/clean-database.spec.ts", "line": 23, "summary": "Result assertions use toEqual rather than toStrictEqual, so an unexpected undefined-valued property would pass; same pattern at clean-database.spec.ts:31/44, check-connection.spec.ts:17, client.spec.ts:39/51/73." }, + { "file": "console-runner/src/main.ts", "line": 71, "summary": "The menu dispatch is an if-chain with no terminal else, so an unrecognised choice would spin the for(;;) loop silently instead of failing loudly. Unreachable today (the value set is a closed typed union), so hardening rather than a bug." } + ] + }, + { + "name": "spec-compliance-check", + "outcome": "findings", + "examined": [".env.example", ".github/workflows/ci.yml", ".gitignore", ".nvmrc", ".prettierignore", ".prettierrc", "README.md", "apps/web/components.json", "apps/web/package.json", "apps/web/src/components/home-page.tsx", "apps/web/src/components/ui/button.tsx", "apps/web/src/components/ui/card.tsx", "apps/web/src/routeTree.gen.ts", "apps/web/src/router.tsx", "apps/web/src/routes/__root.tsx", "apps/web/src/routes/index.tsx", "apps/web/src/styles.css", "apps/web/tsconfig.json", "apps/web/tsr.config.json", "apps/web/vite.config.ts", "apps/web/vitest.config.ts", "apps/web/vitest.setup.ts", "console-runner/package.json", "console-runner/src/actions/check-connection.ts", "console-runner/src/actions/clean-database.ts", "console-runner/src/actions/seed-data.ts", "console-runner/src/main.ts", "console-runner/tsconfig.json", "docker-compose.yml", "harness.config.yml", "package.json", "packages/db/package.json", "packages/db/src/client.ts", "packages/db/src/config.ts", "packages/db/src/index.ts", "packages/db/tsconfig.json", "pnpm-lock.yaml", "pnpm-workspace.yaml", "tsconfig.base.json", "turbo.json"], + "findings": [ + { "file": "console-runner/src/main.ts", "line": 116, "summary": "R48 PARTIAL: implemented correctly and demonstrated in the real run, but untested — the mutation to `default: true` survived. The gap sits inside design.md's human-approved \"prompt layer not tested, by decision\", so it is a specified gap, not an implementer omission." }, + { "file": "console-runner/src/main.ts", "line": 146, "summary": "R44 covers Ctrl+C only and is satisfied; stdin EOF (Ctrl+D) is unspecified and exits 13 with an \"unsettled top-level await\" warning. Not a compliance failure, but it is absent from progress.md, which R58/R59 make the durable real-run record." } + ] + }, + { + "name": "security-review", + "outcome": "findings", + "examined": [".env.example", ".github/workflows/ci.yml", ".gitignore", ".nvmrc", ".prettierignore", ".prettierrc", "README.md", "apps/web/components.json", "apps/web/package.json", "apps/web/src/components/home-page.tsx", "apps/web/src/components/ui/button.tsx", "apps/web/src/components/ui/card.tsx", "apps/web/src/routeTree.gen.ts", "apps/web/src/router.tsx", "apps/web/src/routes/__root.tsx", "apps/web/src/routes/index.tsx", "apps/web/src/styles.css", "apps/web/tsconfig.json", "apps/web/tsr.config.json", "apps/web/vite.config.ts", "apps/web/vitest.config.ts", "apps/web/vitest.setup.ts", "console-runner/package.json", "console-runner/src/actions/check-connection.ts", "console-runner/src/actions/clean-database.ts", "console-runner/src/actions/seed-data.ts", "console-runner/src/main.ts", "console-runner/tsconfig.json", "docker-compose.yml", "harness.config.yml", "package.json", "packages/db/package.json", "packages/db/src/client.ts", "packages/db/src/config.ts", "packages/db/src/index.ts", "packages/db/tsconfig.json", "pnpm-lock.yaml", "pnpm-workspace.yaml", "tsconfig.base.json", "turbo.json"], + "findings": [ + { "file": "docker-compose.yml", "line": 20, "summary": "Medium / hardening: `- '27017:27017'` publishes the credential-less MongoDB on all interfaces (0.0.0.0), so on any shared or untrusted network every host on the LAN gets unauthenticated full read/write on every database. The header comment warns against copying the file to a reachable environment, but the default binding already makes the dev machine reachable. `'127.0.0.1:27017:27017'` closes it while still satisfying R22's port publication and R28's mongodb://localhost:27017/memora." }, + { "file": "apps/web/package.json", "line": 18, "summary": "Low / informational: the shadcn components take `cn` from a third-party npm package rather than a local src/lib/utils.ts. Provenance checked and clean — npm metadata resolves to github.com/shadcn-ui/cn and the lockfile integrity hash matches the registry's exactly — but it is a new supply-chain edge on a very short package name, worth pinning exactly (it currently carries a caret)." }, + { "file": "pnpm-workspace.yaml", "line": 9, "summary": "Low / informational, named per §11: `onlyBuiltDependencies: [esbuild, lightningcss]` re-enables dependency install scripts for those two packages, which is executable code running at install time. Narrow, deliberate and documented in the file; no other package regains that privilege." } + ] + }, + { + "name": "silent-failure-hunter", + "outcome": "findings", + "examined": [".env.example", ".github/workflows/ci.yml", ".gitignore", ".nvmrc", ".prettierignore", ".prettierrc", "README.md", "apps/web/components.json", "apps/web/package.json", "apps/web/src/components/home-page.tsx", "apps/web/src/components/ui/button.tsx", "apps/web/src/components/ui/card.tsx", "apps/web/src/routeTree.gen.ts", "apps/web/src/router.tsx", "apps/web/src/routes/__root.tsx", "apps/web/src/routes/index.tsx", "apps/web/src/styles.css", "apps/web/tsconfig.json", "apps/web/tsr.config.json", "apps/web/vite.config.ts", "apps/web/vitest.config.ts", "apps/web/vitest.setup.ts", "console-runner/package.json", "console-runner/src/actions/check-connection.ts", "console-runner/src/actions/clean-database.ts", "console-runner/src/actions/seed-data.ts", "console-runner/src/main.ts", "console-runner/tsconfig.json", "docker-compose.yml", "harness.config.yml", "package.json", "packages/db/package.json", "packages/db/src/client.ts", "packages/db/src/config.ts", "packages/db/src/index.ts", "packages/db/tsconfig.json", "pnpm-lock.yaml", "pnpm-workspace.yaml", "tsconfig.base.json", "turbo.json"], + "findings": [ + { "file": "console-runner/src/main.ts", "line": 71, "summary": "Pass 5: the menu dispatch has no terminal else, so an unrecognised choice would loop silently rather than fail loudly. Unreachable with today's closed typed union — hardening, not a live bug." } + ] + }, + { + "name": "test-gap-report", + "outcome": "findings", + "examined": [".env.example", ".github/workflows/ci.yml", ".gitignore", ".nvmrc", ".prettierignore", ".prettierrc", "README.md", "apps/web/components.json", "apps/web/package.json", "apps/web/src/components/home-page.tsx", "apps/web/src/components/ui/button.tsx", "apps/web/src/components/ui/card.tsx", "apps/web/src/routeTree.gen.ts", "apps/web/src/router.tsx", "apps/web/src/routes/__root.tsx", "apps/web/src/routes/index.tsx", "apps/web/src/styles.css", "apps/web/tsconfig.json", "apps/web/tsr.config.json", "apps/web/vite.config.ts", "apps/web/vitest.config.ts", "apps/web/vitest.setup.ts", "console-runner/package.json", "console-runner/src/actions/check-connection.ts", "console-runner/src/actions/clean-database.ts", "console-runner/src/actions/seed-data.ts", "console-runner/src/main.ts", "console-runner/tsconfig.json", "docker-compose.yml", "harness.config.yml", "package.json", "packages/db/package.json", "packages/db/src/client.ts", "packages/db/src/config.ts", "packages/db/src/index.ts", "packages/db/tsconfig.json", "pnpm-lock.yaml", "pnpm-workspace.yaml", "tsconfig.base.json", "turbo.json"], + "findings": [ + { "file": "console-runner/src/main.ts", "line": 1, "summary": "The only logic-bearing file in the change with no dedicated spec — and seven requirements ride on it (R38, R39, R41 wiring, R42 wiring, R44, R47, R48). design.md excludes it by decision, so the gap is specified; its whole protection is the one-off manual run recorded in progress.md, which does not regress. Cheapest closure without a TTY: extract the confirm's options (or a buildCleanConfirm(database) factory) and assert default === false and that the message names the database." }, + { "file": "docker-compose.yml", "line": 1, "summary": "The db:* scripts and the compose manifest have no automated coverage at all (hermeticity forbids it, R56), so R24-R27 rest entirely on the recorded real run. Accepted as a deliberate consequence of the hermetic-suite requirement, noted so it is visible rather than implicit." } + ] + } + ] +} diff --git a/.claude/state/tasks/1/spec/tasks.md b/.claude/state/tasks/1/spec/tasks.md index ea9a867..f2d7e7b 100644 --- a/.claude/state/tasks/1/spec/tasks.md +++ b/.claude/state/tasks/1/spec/tasks.md @@ -10,108 +10,108 @@ checkpoint. ## Group 1 — Workspace root _(isolates the package-manager migration: it replaces the live npm install the harness depends on and is the hardest step to reverse)_ -- [ ] T1 — Turn the root into a private pnpm workspace: `pnpm-workspace.yaml` +- [x] T1 — Turn the root into a private pnpm workspace: `pnpm-workspace.yaml` (`apps/*`, `packages/*`, `console-runner`), root `package.json` with `packageManager: pnpm@10.19.0` and `engines.node >=24.16.0 <25`, `.nvmrc` with `24.16.0`, `@lemoncode/lemony` kept as a root devDependency; delete `package-lock.json`, run `pnpm install`, commit `pnpm-lock.yaml`, and prove the harness launcher still resolves (`.claude/hooks/lib/lemony.sh --version` or an `emit`, which needs `node_modules/.bin/lemony`) (R1, R2, R3, R4, R5) -- [ ] T2 — Add `turbo.json` (tasks `dev` persistent + uncached, `build`, `test`, +- [x] T2 — Add `turbo.json` (tasks `dev` persistent + uncached, `build`, `test`, `typecheck`) and the ten root scripts of the single entry point, with the workspace-spanning four delegating to Turborepo (R6, R7) -- [ ] T3 — Add `tsconfig.base.json` with strict mode and wire `pnpm typecheck` so it +- [x] T3 — Add `tsconfig.base.json` with strict mode and wire `pnpm typecheck` so it runs `tsc --noEmit` per workspace and fails on any type error (R8, R9) -- [ ] T4 — Add Prettier (`.prettierrc`), `.prettierignore` excluding `node_modules`, +- [x] T4 — Add Prettier (`.prettierrc`), `.prettierignore` excluding `node_modules`, `.claude/`, `pnpm-lock.yaml` and build outputs, the `format` / `format:check` scripts, and extend `.gitignore` with `.env`, `.turbo/` and the build outputs so a build/test/dev cycle leaves `git status` clean (R10, R11, R12) ## Group 2 — Front end «Hola Mundo» _(isolates the stack integration the PRD calls the most fragile part of this delivery: TanStack Start + Tailwind + shadcn)_ -- [ ] T5 — Scaffold `apps/web` as a TanStack Start app in strict TypeScript, reachable +- [x] T5 — Scaffold `apps/web` as a TanStack Start app in strict TypeScript, reachable through the root `dev`, `build` and `typecheck` scripts, declaring no dependency on `@memora/db` and touching no database (R14, R17, R20) -- [ ] T6 — Configure Tailwind and initialise shadcn (`new-york`, `neutral`), install +- [x] T6 — Configure Tailwind and initialise shadcn (`new-york`, `neutral`), install `Button` and `Card`, and render the «Hola Mundo» page inside a `Card` with a `Button`, using default tokens only — no theme switcher; if shadcn and the installed Tailwind disagree, pin the working combination and record the versions in `progress.md` (R13, R15, R16, R21) -- [ ] T7 — Add the single front smoke test (Vitest + jsdom + Testing Library) that +- [x] T7 — Add the single front smoke test (Vitest + jsdom + Testing Library) that renders the page and asserts the greeting text and the `Button`, green with Docker stopped and no network (R19) -- [ ] T8 — Prune the scaffolding noise: remove every demo route, asset, script and +- [x] T8 — Prune the scaffolding noise: remove every demo route, asset, script and dependency the CLI left that the page, the tests, the gates or the build do not use (R18) ## Group 3 — Local MongoDB in Docker _(isolates the data surface: `db:reset` deletes the named volume, so the mistake here destroys local data)_ [risk: data-loss] -- [ ] T9 — Add the root `docker-compose.yml`: single `mongo:8` service, `27017:27017`, +- [x] T9 — Add the root `docker-compose.yml`: single `mongo:8` service, `27017:27017`, no credentials, named volume at `/data/db`, a `ping` healthcheck, and the header comment marking it local-development-only; database `memora` at `mongodb://localhost:27017/memora` (R22, R23, R28) -- [ ] T10 — Add `db:up` (detached, waiting for healthy) and `db:down` (container +- [x] T10 — Add `db:up` (detached, waiting for healthy) and `db:down` (container removed, volume preserved), each surfacing Docker's own error and exiting non-zero when the daemon is down or the port is bound (R24, R25, R27) -- [ ] T11 — Add `db:reset`: remove the container **and** its volume, then bring up a +- [x] T11 — Add `db:reset`: remove the container **and** its volume, then bring up a fresh healthy container so the database comes back empty (R26) ## Group 4 — `packages/db`, the only door to Mongo _(isolates a new seam every future consumer will depend on: configuration resolution and the client factory)_ -- [ ] T12 — Create `packages/db` as `@memora/db`: `exports`/`types` pointing at +- [x] T12 — Create `packages/db` as `@memora/db`: `exports`/`types` pointing at `src/index.ts` (no build step, no `dist/`), the official `mongodb` driver and no ODM, typechecking on its own, and the only place in the repository that imports the driver (R29, R36, R37) -- [ ] T13 — TDD `resolveMongoUri(env)`: returns the configured URI; throws an explicit +- [x] T13 — TDD `resolveMongoUri(env)`: returns the configured URI; throws an explicit error naming `MONGODB_URI` and `.env.example` when absent, empty or whitespace-only, with no default fallback (R30, R31) -- [ ] T14 — TDD the client primitives against a double: `createMongoClient` with +- [x] T14 — TDD the client primitives against a double: `createMongoClient` with `serverSelectionTimeoutMS` ≤ 5000, `pingDatabase` returning the host and database reached, and `dropDatabase` operating on the URI-encoded database with no hard-coded name (R32, R33) -- [ ] T15 — Add the versioned `.env.example` with +- [x] T15 — Add the versioned `.env.example` with `MONGODB_URI=mongodb://localhost:27017/memora` and confirm `.env` is ignored by git (R34) ## Group 5 — Console runner menu _(isolates the interactive entry point and its non-destructive operations; the destructive one is deliberately left to the next group)_ -- [ ] T16 — Create the `console-runner` workspace at the repository root and the root +- [x] T16 — Create the `console-runner` workspace at the repository root and the root `runner` script running `tsx console-runner/src/main.ts` from the root, loading the root `.env` when it exists and not failing when it does not (R35, R46) -- [ ] T17 — Build the `@inquirer/prompts` `select` menu with its four entries and the +- [x] T17 — Build the `@inquirer/prompts` `select` menu with its four entries and the loop that returns to it after each operation; «Salir» closes the client and exits 0, and a Ctrl+C (`ExitPromptError`) exits quietly with no stack trace (R38, R39, R44) -- [ ] T18 — TDD the prompt-free `checkConnection` operation against a Mongo double — +- [x] T18 — TDD the prompt-free `checkConnection` operation against a Mongo double — success reports host and database, failure reports the driver message plus the `pnpm db:up` hint and returns to the menu without crashing — and wire it to the menu (R40, R41, R45) -- [ ] T19 — TDD `loadSeedData` returning the pending marker and printing a `TODO` with +- [x] T19 — TDD `loadSeedData` returning the pending marker and printing a `TODO` with no database access at all, and the unresolved-`MONGODB_URI` path printing the configuration error and returning to the menu without connecting (R42, R43) ## Group 6 — Clean database _(isolates the only operation in the delivery that destroys data, one keystroke away from the connection check)_ [risk: data-loss] -- [ ] T20 — TDD the prompt-free `cleanDatabase(deps, confirmed)` operation: confirmed ⇒ +- [x] T20 — TDD the prompt-free `cleanDatabase(deps, confirmed)` operation: confirmed ⇒ `dropDatabase` called exactly once and the outcome reported; declined ⇒ no method called on the client double and a cancelled marker returned; a driver failure ⇒ reported, runner still usable (R47, R49, R50, R51) -- [ ] T21 — Wire the operation to the menu behind an `@inquirer/prompts` `confirm` that +- [x] T21 — Wire the operation to the menu behind an `@inquirer/prompts` `confirm` that names the target database and defaults to no, so Enter cancels (R48) ## Group 7 — CI, declared gates and the real-run verification _(closes the delivery: the gates the harness reads, the documentation a fresh clone needs, and the only proof the infrastructure actually runs)_ -- [ ] T22 — Add `.github/workflows/ci.yml` running on pull requests to `main`: pnpm +- [x] T22 — Add `.github/workflows/ci.yml` running on pull requests to `main`: pnpm install `--frozen-lockfile` with the store cached, Node from `.nvmrc` and pnpm from `packageManager`, then `typecheck`, `format:check`, `test` and `build`, with no step allowed to swallow a red gate (R52, R53, R54) -- [ ] T23 — Declare `gates:` in `harness.config.yml` as exactly `typecheck`, +- [x] T23 — Declare `gates:` in `harness.config.yml` as exactly `typecheck`, `format:check`, `test`, `build`, leaving `merge.allow_no_checks` at its default `false`, and confirm the whole suite is hermetic (green with Docker stopped and no network) (R55, R56) -- [ ] T24 — Write the `README.md` quickstart: `pnpm install`, `db:up` / `db:down` / +- [x] T24 — Write the `README.md` quickstart: `pnpm install`, `db:up` / `db:down` / `db:reset`, `dev`, `runner` and the four gate commands (R57) -- [ ] T25 — Run the manual real-run verification and record its outcome in +- [x] T25 — Run the manual real-run verification and record its outcome in `progress.md`: `pnpm db:up` → `pnpm runner` → «check connection» green → `pnpm dev` → the «Hola Mundo» page loads in a browser → `pnpm db:down`; a green suite alone is not evidence the infrastructure runs (R58, R59) From e417e2079ea2a563f12969662de9069a3659ff9e Mon Sep 17 00:00:00 2001 From: Braulio Date: Sun, 18 Oct 2026 00:35:35 +0200 Subject: [PATCH 4/4] update full pass --- .../tasks/1/review-ledger/full-pass.json | 256 ++++++++++-------- 1 file changed, 139 insertions(+), 117 deletions(-) diff --git a/.claude/state/tasks/1/review-ledger/full-pass.json b/.claude/state/tasks/1/review-ledger/full-pass.json index a7e5b05..c5e0857 100644 --- a/.claude/state/tasks/1/review-ledger/full-pass.json +++ b/.claude/state/tasks/1/review-ledger/full-pass.json @@ -2,72 +2,72 @@ "version": 2, "step": "full-pass", "criteria": [ - { "id": "R1", "evidence": "pnpm-workspace.yaml declares apps/*, packages/* and console-runner; root package.json is private. `pnpm install --frozen-lockfile` reports \"Scope: all 4 workspace projects\"." }, - { "id": "R2", "evidence": "package.json: packageManager pnpm@10.19.0, engines.node \">=24.16.0 <25\"; .nvmrc holds 24.16.0. Machine runs node v24.16.0 / pnpm 10.19.0 — read back in this review." }, - { "id": "R3", "evidence": "Ran `pnpm install --frozen-lockfile` myself: exit 0, \"Lockfile is up to date\", no interactive prompt (pnpm-workspace.yaml onlyBuiltDependencies pre-approves esbuild/lightningcss native builds)." }, - { "id": "R4", "evidence": "`ls package-lock.json` -> No such file; `git ls-files package-lock.json` empty (deleted from index, diff shows D). pnpm-lock.yaml staged (5235 lines)." }, - { "id": "R5", "evidence": "Ran `.claude/hooks/lib/lemony.sh --version` -> 0.10.0; node_modules/.bin/lemony present (mode 755)." }, - { "id": "R6", "evidence": "Machine-checked the script set against R6's list: exactly 10 keys, exact match true (dev, build, test, typecheck, format, format:check, db:up, db:down, db:reset, runner)." }, - { "id": "R7", "evidence": "All four workspace-spanning scripts are `turbo run `; turbo.json declares dev (cache false, persistent), build, test, typecheck. Turbo output shows \"Packages in scope: @memora/db, @memora/web, console-runner\"." }, - { "id": "R8", "evidence": "tsconfig.base.json sets strict: true (plus noUncheckedIndexedAccess, noImplicitOverride, noFallthroughCasesInSwitch, verbatimModuleSyntax, isolatedModules); all three workspace tsconfigs extend it." }, - { "id": "R9", "evidence": "Ran TURBO_FORCE=true pnpm typecheck: 3/3 green on fresh execution. Then hand-probed the gate: mutated resolveMongoUri's return type string->number behind a restore trap; turbo reported \"0 successful, 3 total\" and \"Failed: @memora/db#typecheck\" with error TS2322 and a cross-workspace TS2345 in console-runner. Tree restored clean." }, - { "id": "R10", "evidence": "Ran `pnpm format:check` (prettier --check .): \"All matched files use Prettier code style!\"." }, - { "id": "R11", "evidence": ".prettierignore excludes node_modules/, .claude/, pnpm-lock.yaml, build outputs (dist/, .output/, .tanstack/, .vite/), caches (.turbo/, coverage/) and generated **/routeTree.gen.ts. It also excludes harness.config.schema.json and docs/playbooks/README.md: I confirmed both files exist, are installer-dropped harness artifacts regenerated by `lemony repair`/`update`, and so fall inside R11's general clause (\"vendor and generated paths\") and squarely inside its stated rationale. Judged compliant, not drift." }, - { "id": "R12", "evidence": "Ran a full build + test + a dev session myself, then `git status --porcelain -uall`: no `??` and no unstaged-modified entries — only the staged work. .gitignore covers .env, dist/, .output/, .tanstack/, .nitro/, .turbo/, .vite/, coverage/, *.tsbuildinfo." }, - { "id": "R13", "evidence": "apps/web is a TanStack Start app (@tanstack/react-start 1.169.3) in strict TS; tailwindcss 4.3.3 wired via @tailwindcss/vite; components.json has style \"new-york\" and baseColor \"neutral\". I fetched https://ui.shadcn.com/r/colors/neutral.json and diffed cssVarsV4 against src/styles.css: every light and dark value matches byte for byte — the tokens are the registry's, not invented." }, - { "id": "R14", "evidence": "Ran `pnpm dev` myself: ready in 3s, GET http://localhost:3000/ -> HTTP 200 with «Hola Mundo» in the server-rendered HTML." }, - { "id": "R15", "evidence": "Served HTML carries data-slot=\"card\", card-header, card-title, card-description, card-content and data-slot=\"button\" with «Empezar». Fetched /src/styles.css (200, 21721 bytes): the compiled sheet contains resolved .bg-card, .text-card-foreground, .bg-primary, .text-primary-foreground, .rounded-xl, .min-h-screen, .shadow-sm, .max-w-md plus the neutral token values — the chain is applied, not merely imported." }, - { "id": "R16", "evidence": "Default tokens only: no theme switcher, no toggle, no custom palette anywhere in the diff. The `.dark` block and `@custom-variant dark` are shadcn's own defaults (verified against the registry) and nothing in the app sets the `dark` class." }, - { "id": "R17", "evidence": "Ran TURBO_FORCE=true pnpm build (cache bypassed): 1/1 successful, exit 0, \"Generated .output/nitro.json\". One benign rolldown notice about a module-level directive; no error." }, - { "id": "R18", "evidence": "No scaffolder residue: zero external URLs in the served HTML and none in the compiled CSS except Tailwind's own license comment (/*! tailwindcss v4.3.3 ... https://tailwindcss.com */) — so no remote Google Fonts @import survived. No demo routes or assets; @types/node pruned from apps/web. Every declared dependency traces to an import, the gates or the runtime." }, - { "id": "R19", "evidence": "apps/web/src/components/home-page.spec.tsx renders HomePage and asserts the «Hola Mundo» heading and a button whose data-slot is \"button\". Ran the suite with the Docker daemon down: 2/2 green. vitest.config.ts loads only the React transform, excluding the Start/Nitro SSR plugins." }, - { "id": "R20", "evidence": "Grepped apps/web/package.json for @memora/db: no match. No front-end file imports it." }, - { "id": "R21", "evidence": "The unwanted path did not fire — no shadcn/Tailwind incompatibility was hit, and all four gates are green on the combination. progress.md tabulates the pinned versions anyway. Noted separately that progress.md's \"no carets\" claim is inaccurate for two apps/web deps (cn ^0.5.0, radix-ui ^1.8.1)." }, - { "id": "R22", "evidence": "docker-compose.yml: single service, image mongo:8, ports '27017:27017', no credentials/env, named volume memora-mongo-data mounted at /data/db, healthcheck `mongosh --quiet --eval db.adminCommand('ping')` with interval/timeout/retries/start_period. Flagged separately that the port publishes on all interfaces rather than loopback." }, - { "id": "R23", "evidence": "The file opens with \"LOCAL DEVELOPMENT ONLY — no credentials.\" and three paragraphs spelling out that anyone reaching the port has full read/write and that it must never be copied to an externally reachable environment." }, - { "id": "R24", "evidence": "db:up is `docker compose up -d --wait` — detached, and --wait blocks until the healthcheck reports healthy. I could not execute it: the Docker daemon is down on this machine and the Docker CLI itself hangs (a bare `docker info` hangs identically), so I verified the script by inspection and rely on the Implementer's recorded run (exit 0 in ~6s, `Up 5 seconds (healthy)`)." }, - { "id": "R25", "evidence": "db:down is `docker compose down` with no -v, so the named volume survives by construction. Implementer's recorded experiment: document inserted, db:down, db:up, read back count=1." }, - { "id": "R26", "evidence": "db:reset is `docker compose down -v && docker compose up -d --wait` — volume removed, then a fresh healthy container. Implementer's recorded experiment: countDocuments() 0 and getCollectionNames() [] afterwards." }, - { "id": "R27", "evidence": "All three db:* scripts are bare `docker compose` invocations — no wrapper, no retry loop, no `|| true`, so Docker's own stderr and exit code propagate unchanged through pnpm. My own attempt hung inside the Docker CLI rather than the script (bare `docker info` hangs the same way with the daemon stopped), which itself shows the script adds no masking; the Implementer recorded the exact unmasked daemon error and exit 1." }, - { "id": "R28", "evidence": "Database name `memora` and URI mongodb://localhost:27017/memora appear in .env.example, the compose header comment, config.ts's error text and README.md. Confirmed at runtime: the client resolves databaseName \"memora\" from the URI." }, - { "id": "R29", "evidence": "Grepped the whole tree: the only `from 'mongodb'` is packages/db/src/client.ts:1, and packages/db/package.json is the only manifest declaring the driver." }, - { "id": "R30", "evidence": "resolveMongoUri(env: EnvRecord) reads only its argument — no process.env access, no file read. config.spec.ts pins this with a test that sets process.env.MONGODB_URI and still expects a throw for an empty record." }, - { "id": "R31", "evidence": "Throws naming both MONGODB_URI and .env.example, with no default fallback; 6 tests cover present / absent / empty / whitespace-only / trimming / no-process.env-fallback. Mutant: dropped the `?.trim()` — 2 tests went red (killed)." }, - { "id": "R32", "evidence": "SERVER_SELECTION_TIMEOUT_MS = 5_000 passed to the MongoClient constructor; client.spec.ts asserts options.serverSelectionTimeoutMS <= 5000. Mutant: widened to 50_000 — \"expected 50000 to be less than or equal to 5000\" (killed)." }, - { "id": "R33", "evidence": "pingDatabase and dropDatabase both call client.db() with no argument, so the database is whatever the URI encodes. Tests cover a second database name (\"otra-base\" on db.internal:27018) to prove nothing is hard-coded." }, - { "id": "R34", "evidence": ".env.example is staged with MONGODB_URI=mongodb://localhost:27017/memora; `git check-ignore -v .env` resolves to .gitignore:17. A real .env exists in the worktree and is not staged." }, - { "id": "R35", "evidence": "The runner script is `tsx --env-file-if-exists=.env console-runner/src/main.ts`, loaded from the repository root. I ran the entry point without the flag (pnpm exec tsx console-runner/src/main.ts) and it started fine with no .env in play, confirming the absent-file path does not fail." }, - { "id": "R36", "evidence": "packages/db/package.json points types and exports at ./src/index.ts, declares no build script and emits no dist/; `tsc --noEmit` passes for @memora/db on its own in the fresh typecheck run." }, - { "id": "R37", "evidence": "Dependency is the official mongodb 7.7.0 (lockfile entry confirmed); no Mongoose, Prisma or any other ODM anywhere in the manifests." }, - { "id": "R38", "evidence": "Drove the real menu through a pty: exactly four entries — Comprobar conexión con Mongo / Limpiar base de datos / Cargar datos de prueba / Salir — with \"↑↓ navigate • ⏎ select\" and arrow-key movement working. No flags required." }, - { "id": "R39", "evidence": "Drove it myself: after a failed connection check the loop returned to the menu and stayed usable; selecting «Salir» exited 0. closeClient() is awaited on every exit path." }, - { "id": "R40", "evidence": "checkConnection pings and returns { ok: true, host, database }; main.ts prints «Conexión correcta con , base de datos «»». Covered by check-connection.spec.ts and by client.spec.ts's ping tests." }, - { "id": "R41", "evidence": "Reproduced with Mongo down: the runner printed the driver's own message verbatim (\"connect ECONNREFUSED ::1:27017, connect ECONNREFUSED 127.0.0.1:27017\") plus \"¿Está Mongo levantado? Prueba con `pnpm db:up`.\", returned to the menu, and no stack trace appeared. Mutant: dropped the hint — the spec went red (killed)." }, - { "id": "R42", "evidence": "Reproduced with MONGODB_URI unset and no .env load: the runner printed \"✖ MONGODB_URI no está definida. Copia .env.example a .env …\" and no ECONNREFUSED followed, so no connection was attempted; the menu stayed usable. Structurally guaranteed — resolveMongoUri throws before createMongoClient is reached." }, - { "id": "R43", "evidence": "Reproduced: «Cargar datos de prueba» printed \"TODO: los datos de prueba llegarán con el modelo de dominio. No se ha escrito nada en la base de datos.\" and touched nothing. loadSeedData takes no client at all; seed-data.spec.ts pins both the TODO text and the zero arity. Mutant: rewrote the message to claim success — killed." }, - { "id": "R44", "evidence": "Ctrl+C is handled: ExitPromptError is matched by name, the client is closed and the process leaves quietly with no stack trace (Implementer's recorded run; the code path is explicit at main.ts:138-143). ADVISORY, outside R44's letter: I reproduced stdin EOF (Ctrl+D) at the menu and it leaves \"Warning: Detected unsettled top-level await at console-runner/src/main.ts:146\" and ELIFECYCLE exit 13. R44 specifies Ctrl+C only, so this is unspecified rather than failing; it is undocumented in progress.md and named in my verdict." }, - { "id": "R45", "evidence": "Grepped @inquirer/prompts: imported only in console-runner/src/main.ts. All three operations are plain functions receiving the client as a parameter, and all three are tested against hand-written doubles." }, - { "id": "R46", "evidence": "The runner is executed by tsx straight over TypeScript; console-runner/package.json declares no build script." }, - { "id": "R47", "evidence": "main.ts:112-117 reads target.db().databaseName locally (no server call) and the confirm message names it: \"Vas a BORRAR todos los datos de la base «memora». ¿Seguro?\". The prompt is issued before cleanDatabase is called." }, - { "id": "R48", "evidence": "PARTIAL. The implementation is correct — main.ts:116 is `default: false, // Enter cancels (R48).` — and the Implementer's real run recorded the \"(y/N)\" rendering with Enter cancelling and the seeded document intact. But no automated test asserts it: I mutated main.ts:116 to `default: true` (Enter would delete the database) and the entire console-runner suite stayed green, 7/7. The gap is inside design.md's human-approved \"prompt layer not tested, by decision\", so it is a specified gap rather than an implementer omission; raised as the headline advisory in my verdict with a cheap fix." }, - { "id": "R49", "evidence": "cleanDatabase calls dropDatabase(client) on the URI-encoded database and returns { status: 'dropped', database }; clean-database.spec.ts asserts dropDatabase was called exactly once. Implementer's real run confirmed the database was actually empty afterwards." }, - { "id": "R50", "evidence": "The guard `if (!confirmed) return { status: 'cancelled' };` sits before anything touches the client, and the spec asserts not even db() was called. Mutant: removed the guard — the declined test went red (killed). This is the data-loss guard and it is genuinely protected." }, - { "id": "R51", "evidence": "The drop is wrapped in try/catch returning { status: 'failed', error }; the spec drives a rejecting double and asserts the reported error, and main.ts prints it and loops back to the menu rather than throwing." }, - { "id": "R52", "evidence": ".github/workflows/ci.yml triggers on pull_request to main, installs with `pnpm install --frozen-lockfile` and caches the pnpm store via setup-node's cache: pnpm, then runs typecheck, format:check, test and build. The workflow has never executed (no PR yet), so I verified what I could: all three action major tags resolve (actions/checkout@v7, actions/setup-node@v7, pnpm/action-setup@v6 — HTTP 200 each) and `pnpm install --frozen-lockfile` succeeds locally, which is the step most likely to break CI." }, - { "id": "R53", "evidence": "Read the workflow line by line: no continue-on-error, no `||`, no `set +e`, no composite step that could swallow an exit code. Each gate is its own step, so any non-zero exit fails the job." }, - { "id": "R54", "evidence": "setup-node uses node-version-file: .nvmrc, and pnpm/action-setup is deliberately given no `version:` input so it reads the root packageManager field. Both are commented in the workflow with the reason." }, - { "id": "R55", "evidence": "harness.config.yml declares gates as exactly [typecheck, 'format:check', test, build] and carries no `merge:` block, so merge.allow_no_checks stays at its default false. Read the committed file directly." }, - { "id": "R56", "evidence": "Ran the whole suite (20 tests: db 11, console-runner 7, web 2) with the Docker daemon down — green, cache bypassed. For the network half: grepped the sources for fetch/XMLHttpRequest and the http/https/net/dns/tls modules, zero hits; the front spec excludes the SSR plugins; and client.spec.ts's real MongoClient construction uses a non-SRV mongodb:// URI, which resolves no DNS until connect. The network interface was not physically severed, so that half rests on code-level evidence — the same honest caveat progress.md states." }, - { "id": "R57", "evidence": "README.md documents the quickstart (pnpm install, cp .env.example .env, db:up, dev), a db:* table, the runner and its two behaviours, and the four gate commands with the no-linter rationale." }, - { "id": "R58", "evidence": "progress.md carries the six-step table in the prescribed order (db:up -> runner -> check connection -> dev -> page loads -> db:down), each with its result, plus a further section of real-run evidence for R25, R26, R27, R41, R42, R43, R47-R50 and R35." }, - { "id": "R59", "evidence": "progress.md states explicitly that a green suite is not evidence the infrastructure runs, and states plainly that nobody has visually confirmed the rendered pixels. I could not close that gap either — no browser automation is available to me (no claude-in-chrome or built-in browser tools; WebFetch refuses localhost), so I verified over HTTP only and the visual check remains the human's at the gate." } + { "id": "R1", "evidence": "pnpm-workspace.yaml declares 'apps/*', 'packages/*' and 'console-runner'; root package.json is private: true. Ran `pnpm install --frozen-lockfile` myself: \"Scope: all 4 workspace projects\"." }, + { "id": "R2", "evidence": "package.json: packageManager \"pnpm@10.19.0\", engines.node \">=24.16.0 <25\"; .nvmrc holds 24.16.0. Read back the live toolchain in this review: node v24.16.0, pnpm 10.19.0 — both inside the declared range." }, + { "id": "R3", "evidence": "Ran `pnpm install --frozen-lockfile` at the root: exit 0, \"Lockfile is up to date, resolution step is skipped\", \"Already up to date\", done in 368ms. No manual step, no interactive approval prompt (pnpm-workspace.yaml's onlyBuiltDependencies pre-approves the two native builds)." }, + { "id": "R4", "evidence": "`git ls-files | grep -i lock` returns exactly one path: pnpm-lock.yaml. package-lock.json shows as D in the anchored diff and is absent from the worktree and the index." }, + { "id": "R5", "evidence": "Ran `.claude/hooks/lib/lemony.sh --version` -> 0.10.0 after my own install; `ls -l node_modules/.bin/lemony` -> -rwxr-xr-x, 1698 bytes. The launcher's hard-coded path resolves." }, + { "id": "R6", "evidence": "Read the script block: exactly the ten names R6 lists — dev, build, test, typecheck, format, format:check, db:up, db:down, db:reset, runner — and nothing else." }, + { "id": "R7", "evidence": "dev/build/test/typecheck are each `turbo run `; turbo.json declares all four, with dev cache:false + persistent:true. My own gate runs printed per-package task lines for @memora/db, @memora/web and console-runner, so the fan-out is Turborepo's, not a shell loop." }, + { "id": "R8", "evidence": "tsconfig.base.json sets strict: true, plus noUncheckedIndexedAccess, noImplicitOverride, noFallthroughCasesInSwitch, verbatimModuleSyntax, isolatedModules and forceConsistentCasingInFileNames. All three workspace tsconfigs extend it (read each one)." }, + { "id": "R9", "evidence": "Ran `TURBO_FORCE=true pnpm typecheck`: the log shows \"cache bypass, force executing\" for all three packages, `tsc --noEmit` per workspace, 3 successful / 3 total. Then I proved the gate goes RED myself: mutated resolveMongoUri's return type string -> number behind a restore trap; rc=1, \"0 successful, 3 total\", \"Failed: console-runner#typecheck\", error TS2322 in @memora/db plus a cross-workspace TS2345 at console-runner/src/main.ts(51,34). Tree restored clean." }, + { "id": "R10", "evidence": "Ran `pnpm format:check` (prettier --check .): \"All matched files use Prettier code style!\", exit 0." }, + { "id": "R11", "evidence": ".prettierignore excludes node_modules/, .claude/, pnpm-lock.yaml, the build outputs (dist/, .output/, .tanstack/, .vite/), the caches (.turbo/, coverage/) and the generated **/routeTree.gen.ts. It also excludes harness.config.schema.json and docs/playbooks/README.md: I confirmed both files exist on disk and are installer-dropped harness artifacts regenerated by `lemony repair`/`update`. I judge that compliant — it falls inside R11's general clause (\"vendor and generated paths\") and squarely inside its stated rationale (\"a harness vendor update can never fail the format gate\") — not drift." }, + { "id": "R12", "evidence": "Ran a full build + test + a real dev session myself, then `git status --porcelain -uall`: empty. No untracked, no modified tracked files. .gitignore covers .env, dist/, .output/, .tanstack/, .nitro/, .turbo/, .vite/, coverage/ and *.tsbuildinfo." }, + { "id": "R13", "evidence": "apps/web depends on @tanstack/react-start 1.169.3 and @tanstack/react-router 1.170.45, extends the strict base tsconfig, wires Tailwind 4.3.3 through @tailwindcss/vite, and components.json declares style \"new-york\" with baseColor \"neutral\". The served stylesheet carries the neutral token values (--card: oklch(1 0 0), --primary: oklch(0.205 0 0)) — read out of the live HTTP response, not just the source." }, + { "id": "R14", "evidence": "Ran `pnpm dev` myself and fetched http://localhost:3000/: HTTP 200 with «Hola Mundo» in the server-rendered HTML, lang=\"es\". The dev log carried zero errors and zero warnings." }, + { "id": "R15", "evidence": "The served HTML carries data-slot=\"card\", data-slot=\"card-header\", data-slot=\"card-title\" and data-slot=\"button\" with «Empezar». Fetched the referenced /src/styles.css: HTTP 200, 21721 bytes, containing the RESOLVED utilities .bg-card, .text-card-foreground, .bg-primary, .text-primary-foreground, .rounded-xl, .min-h-screen, .shadow-sm and .max-w-md. The chain is applied end to end, not merely imported. home-page.tsx renders the Button inside CardContent inside Card." }, + { "id": "R16", "evidence": "Default tokens only. src/styles.css is a single @import 'tailwindcss' plus the shadcn neutral token block; no custom palette, no theme switcher and no toggle anywhere in the diff. The .dark block and @custom-variant dark are shadcn's own defaults and nothing in the app ever sets the dark class (grepped)." }, + { "id": "R17", "evidence": "Ran `TURBO_FORCE=true pnpm build` cache-bypassed: 1 successful / 1 total, exit 0, \"✓ built in 202ms\", \"Generated .output/nitro.json\". One benign rolldown MODULE_LEVEL_DIRECTIVE notice about a \"use client\" directive inside a @radix-ui dependency — a notice, not an error." }, + { "id": "R18", "evidence": "No scaffolder residue. Zero external URLs in the served HTML; the only URL in the 21721-byte compiled CSS is Tailwind's own licence comment (https://tailwindcss.com) — so the scaffolder's remote Google Fonts @import is genuinely absent. No demo routes or assets. I traced every apps/web dependency to a real consumer: cn and radix-ui (Slot) are imported by button.tsx/card.tsx, class-variance-authority by button.tsx, nitro by vite.config.ts, the rest by the runtime or the gates. I also probed the one plausible leftover: dropping types:[\"node\"] from packages/db/tsconfig.json makes tsc fail (TS2591 on process.env in config.spec.ts, TS2740 on MongoClientOptions), so @types/node there is genuinely needed, not noise." }, + { "id": "R19", "evidence": "apps/web/src/components/home-page.spec.tsx renders HomePage and asserts the «Hola Mundo» heading by role plus a button whose data-slot is \"button\". Ran it with no Docker daemon reachable: 2/2 green. vitest.config.ts loads only the React transform (no Start/Nitro SSR plugins), which is what keeps it hermetic. I measured the test's strength rather than assuming it: changing the greeting to \"Hello World\" turns it red, and swapping the shadcn