diff --git a/.gitignore b/.gitignore index b6326bb..7d8d6c4 100644 --- a/.gitignore +++ b/.gitignore @@ -3,9 +3,6 @@ node_modules/ build/ dist/ .vite/ -.turbo/ -apps/*/.turbo/ -packages/*/.turbo/ .env .env.* @@ -13,8 +10,6 @@ packages/*/.turbo/ data/*.sqlite data/*.sqlite-* -apps/*/data/*.sqlite -apps/*/data/*.sqlite-* coverage/ playwright-report/ test-results/ diff --git a/packages/ui/.storybook/main.ts b/.storybook/main.ts similarity index 83% rename from packages/ui/.storybook/main.ts rename to .storybook/main.ts index 34237be..cfd3a61 100644 --- a/packages/ui/.storybook/main.ts +++ b/.storybook/main.ts @@ -2,6 +2,7 @@ import type { StorybookConfig } from "@storybook/react-vite"; const config: StorybookConfig = { stories: ["../src/**/*.stories.@(js|ts|tsx)"], + staticDirs: ["../static"], addons: [ "@storybook/addon-a11y", "@storybook/addon-vitest", @@ -10,6 +11,9 @@ const config: StorybookConfig = { name: "@storybook/react-vite", options: {}, }, + docs: { + autodocs: "tag", + }, }; export default config; diff --git a/packages/ui/.storybook/preview.ts b/.storybook/preview.ts similarity index 63% rename from packages/ui/.storybook/preview.ts rename to .storybook/preview.ts index 87df132..964f47b 100644 --- a/packages/ui/.storybook/preview.ts +++ b/.storybook/preview.ts @@ -1,5 +1,17 @@ -import "../src/styles.css"; +import "../src/app.css"; import type { Preview } from "@storybook/react-vite"; +import { setupWorker } from "msw/browser"; +import { externalApiHandlers } from "../src/lib/testing/external-api-mocks"; + +if (typeof window !== "undefined") { + const worker = setupWorker(...externalApiHandlers); + void worker.start({ + onUnhandledRequest: "bypass", + serviceWorker: { + url: "/mockServiceWorker.js", + }, + }); +} const preview: Preview = { decorators: [ @@ -32,10 +44,10 @@ const preview: Preview = { backgrounds: { default: "canvas", values: [ - { name: "canvas", value: "#0b0f0d" }, - { name: "raised", value: "#151d18" }, - { name: "light canvas", value: "#eef2e7" }, - { name: "light raised", value: "#f1f5ea" }, + { name: "canvas", value: "#020302" }, + { name: "raised", value: "#0b0d0c" }, + { name: "light canvas", value: "#f3f5ed" }, + { name: "light raised", value: "#eef1e7" }, ], }, controls: { diff --git a/Containerfile b/Containerfile new file mode 100644 index 0000000..d19c2d0 --- /dev/null +++ b/Containerfile @@ -0,0 +1,31 @@ +FROM docker.io/oven/bun:1.3.14 AS deps + +WORKDIR /app +COPY package.json bun.lock ./ +RUN bun install --frozen-lockfile + +FROM deps AS build + +COPY . . +RUN bun run build + +FROM docker.io/oven/bun:1.3.14 AS runtime + +WORKDIR /app +ENV NODE_ENV=production +ENV HOST=0.0.0.0 +ENV PORT=3000 +ENV DATABASE_URL=file:/data/dimensionlab.sqlite +ENV DASHBOARD_MIGRATIONS_DIR=/app/drizzle + +COPY package.json bun.lock ./ +RUN bun install --frozen-lockfile --production +COPY --from=build /app/build ./build +COPY --from=build /app/dist ./dist +COPY --from=build /app/drizzle ./drizzle + +RUN mkdir -p /data +VOLUME ["/data"] +EXPOSE 3000 + +CMD ["bun", "build/index.js"] diff --git a/README.md b/README.md index 59dedf6..f39dcb5 100644 --- a/README.md +++ b/README.md @@ -1,20 +1,11 @@ # Dimension Lab Website -Turbo/Bun workspace for the Dimension Lab system overview dashboard and its -reusable React component library. +Standalone React runtime for the Dimension Lab system overview dashboard. This project is not a Homepage customization and does not depend on Homepage runtime, frontend code, or configuration. The dashboard will be model-driven: -the reusable UI package stays content-free, while environment-specific data -lives in validated dashboard model state inside the web app. - -## Workspace Layout - -- `apps/web`: Vite React website, Bun API server, model fixtures, Drizzle - persistence, Playwright e2e checks, and container build. -- `packages/ui`: reusable dashboard React components, design tokens, - shadcn/radix primitives, generic fixtures, and Storybook. -- `docs/superpowers`: migration specs and execution plans used for this repo. +the reusable renderer stays content-free, while environment-specific data lives +in validated dashboard model state. ## Development @@ -27,18 +18,18 @@ This MVP uses Drizzle with Bun SQLite for local file-backed persistence. ## Scripts -- `bun run dev`: start the web app dev runtime through Turbo. -- `bun run check`: run TypeScript checks in all workspaces. -- `bun run test`: run the unit test stage in all workspaces. +- `bun run dev`: start the local Vite development server with a Bun API proxy. +- `bun run check`: run TypeScript checks. +- `bun run test`: run Vitest. - `bun run test:unit`: run Vitest explicitly as the unit test stage. - `bun run test:e2e`: build and run Playwright browser smoke and QA checks. -- `bun run test:qa`: run the release gate through Turbo. -- `bun run build`: build the UI package, production website, and Bun server. -- `bun run preview`: preview the production web build. -- `bun run storybook`: start the UI package component explorer on port 6006. -- `bun run build-storybook`: build the UI package static Storybook artifact. -- `bun run db:generate`: generate web app Drizzle migrations. -- `bun run db:check`: validate web app migration consistency. +- `bun run test:qa`: run the MVP release gate. +- `bun run build`: build the production app. +- `bun run preview`: preview the production build. +- `bun run storybook`: start the component explorer on port 6006. +- `bun run build-storybook`: build the static Storybook review artifact. +- `bun run db:generate`: generate Drizzle migrations from the server schema. +- `bun run db:check`: validate migration consistency. ## Persistence @@ -49,14 +40,14 @@ URL is: DATABASE_URL=file:./data/dimensionlab.sqlite ``` -SQLite files under `data/` and `apps/*/data/` are ignored. Drizzle schema lives -in `apps/web/src/lib/server/db/schema.ts`; tracked migrations live in -`apps/web/drizzle/`. Runtime startup applies the checked-in dashboard migrations -before reads or writes. If the app is launched from outside the web app tree, -set `DASHBOARD_MIGRATIONS_DIR` to the tracked migrations directory. The current -driver is `bun:sqlite`, which keeps this repo installable in the Bun workflow. -The store boundary is isolated so a later Postgres driver can replace the -SQLite connection without changing the dashboard model or renderer. +SQLite files under `data/` are ignored. Drizzle schema lives in +`src/lib/server/db/schema.ts`; tracked migrations live in `drizzle/`. Runtime +startup applies the checked-in dashboard migrations before reads or writes. If +the app is launched from outside the repo tree, set `DASHBOARD_MIGRATIONS_DIR` +to the tracked migrations directory. The current driver is `bun:sqlite`, which +keeps this repo installable in the Bun workflow. The store boundary is isolated +so a later Postgres driver can replace the SQLite connection without changing +the dashboard model or renderer. Stored dashboard documents pass through a version migration boundary before reads or writes; the MVP supports `dashboard.v1` and fails unsupported versions with an explicit migration error. @@ -64,26 +55,25 @@ with an explicit migration error. ## Seed Data The initial Dimension Lab dashboard lives in -`apps/web/src/lib/model/fixtures/dimensionlab.ts` as validated model data. It -includes the first-screen telemetry, service groups, status strip, weather -module, Iconify icon identifiers, links, and datasource references. Values that -are not live yet are labeled as fallback values in the data so later datasource -adapters can replace them without changing presentation components. +`src/lib/model/fixtures/dimensionlab.ts` as validated model data. It includes +the first-screen telemetry, service groups, status strip, weather module, +Iconify icon identifiers, links, and datasource references. Values that are not +live yet are labeled as fallback values in the data so later datasource adapters +can replace them without changing presentation components. ## Runtime Shape -The browser app in `apps/web` is built with Vite and React. Local development -starts Vite for HMR and a loopback Bun API server for `/api/*` routes. -Production uses a small Bun HTTP server at `apps/web/build/index.js` to serve -the Vite `apps/web/dist/` assets and JSON API routes. The current persistence -runtime is Bun because the MVP SQLite driver is `bun:sqlite`. +The browser app is built with Vite and React. Local development starts Vite for +HMR and a loopback Bun API server for `/api/*` routes. Production uses a small +Bun HTTP server at `build/index.js` to serve the Vite `dist/` assets and JSON +API routes. The current persistence runtime is Bun because the MVP SQLite +driver is `bun:sqlite`. ## Storybook -Storybook lives with `packages/ui` and covers the reusable UI components with -generic fixtures only. Stories must not import environment-specific dashboard -content; the presentation layer accepts labels, values, icons, status, and links -through typed props. +Storybook covers the reusable UI components with generic fixtures only. Stories +must not import environment-specific dashboard content; the presentation layer +accepts labels, values, icons, status, and links through typed props. ## MVP QA Gate @@ -116,29 +106,27 @@ belong in validated model data, not reusable components. ## Deployment Notes -The production build emits Vite client assets under `apps/web/dist/` and a Bun -server entry at `apps/web/build/index.js`. A minimal deployment flow is: +The production build emits Vite client assets under `dist/` and a Bun server +entry at `build/index.js`. A minimal deployment flow is: ```sh bun install --frozen-lockfile bun run build -cd apps/web DATABASE_URL=file:/data/dimensionlab.sqlite HOST=0.0.0.0 PORT=3000 bun build/index.js ``` Mount `/data` or set `DATABASE_URL` to another persistent SQLite path. If the process starts outside the repository root, set `DASHBOARD_MIGRATIONS_DIR` to -the checked-in `apps/web/drizzle/` directory so startup migrations can run. +the checked-in `drizzle/` directory so startup migrations can run. ### Internal Container -The checked-in `apps/web/Containerfile` builds the React client and Bun server -from the workspace root into a runtime image. For the Dimension Lab internal -host, run it behind Caddy on a loopback port and mount persistent state at -`/data`: +The checked-in `Containerfile` builds the React client and Bun server into a +runtime image. For the Dimension Lab internal host, run it behind Caddy on a +loopback port and mount persistent state at `/data`: ```sh -podman build -f apps/web/Containerfile -t localhost/dimensionlab-website:latest . +podman build -t localhost/dimensionlab-website:latest . podman run --rm \ --publish 127.0.0.1:25341:3000 \ --volume "$HOME/containers/dimensionlab-website/data:/data:Z" \ @@ -149,4 +137,4 @@ podman run --rm \ The env file must provide `AGENT_CONFIG_TOKEN`. Runtime defaults inside the image set `HOST=0.0.0.0`, `PORT=3000`, `DATABASE_URL=file:/data/dimensionlab.sqlite`, and -`DASHBOARD_MIGRATIONS_DIR=/repo/apps/web/drizzle`. +`DASHBOARD_MIGRATIONS_DIR=/app/drizzle`. diff --git a/apps/web/Containerfile b/apps/web/Containerfile deleted file mode 100644 index 912f780..0000000 --- a/apps/web/Containerfile +++ /dev/null @@ -1,32 +0,0 @@ -FROM docker.io/oven/bun:1.3.14 AS deps - -WORKDIR /repo -ENV PATH=/repo/apps/web/node_modules/.bin:/repo/packages/ui/node_modules/.bin:/repo/node_modules/.bin:$PATH -COPY package.json bun.lock turbo.json tsconfig.base.json ./ -COPY apps/web/package.json apps/web/package.json -COPY packages/ui/package.json packages/ui/package.json -RUN bun install --frozen-lockfile - -FROM deps AS build - -COPY . . -RUN bun install --frozen-lockfile && bun run build - -FROM deps AS runtime - -WORKDIR /repo/apps/web -ENV NODE_ENV=production -ENV HOST=0.0.0.0 -ENV PORT=3000 -ENV DATABASE_URL=file:/data/dimensionlab.sqlite -ENV DASHBOARD_MIGRATIONS_DIR=/repo/apps/web/drizzle - -COPY --from=build /repo/apps/web/build ./build -COPY --from=build /repo/apps/web/dist ./dist -COPY --from=build /repo/apps/web/drizzle ./drizzle - -RUN mkdir -p /data -VOLUME ["/data"] -EXPOSE 3000 - -CMD ["bun", "build/index.js"] diff --git a/apps/web/package.json b/apps/web/package.json deleted file mode 100644 index 7875aa8..0000000 --- a/apps/web/package.json +++ /dev/null @@ -1,51 +0,0 @@ -{ - "name": "@dimensionlab/web", - "version": "0.0.1", - "private": true, - "type": "module", - "scripts": { - "dev": "bun src/server/dev.ts", - "build": "vite build && bun build src/server/index.ts --target bun --outdir build", - "preview": "HOST=0.0.0.0 PORT=4173 bun build/index.js", - "check": "tsc --noEmit", - "test": "vitest run", - "test:unit": "vitest run", - "test:e2e": "env -u NO_COLOR playwright test", - "test:qa": "bun run check && bun run test:unit && bun run build && bun run test:e2e", - "db:generate": "drizzle-kit generate", - "db:check": "drizzle-kit check" - }, - "dependencies": { - "@dimensionlab/ui": "workspace:*", - "@sinclair/typebox": "^0.34.49", - "ajv": "^8.20.0", - "ajv-formats": "^3.0.1", - "drizzle-orm": "^0.45.2", - "react": "^19.2.7", - "react-dom": "^19.2.7", - "tw-animate-css": "^1.4.0" - }, - "devDependencies": { - "@axe-core/playwright": "^4.11.3", - "@playwright/test": "^1.61.0", - "@tailwindcss/vite": "^4.3.1", - "@types/bun": "^1.3.14", - "@types/node": "^25.9.3", - "@types/react": "^19.2.17", - "@types/react-dom": "^19.2.3", - "@vitejs/plugin-react": "^6.0.2", - "bun-types": "^1.3.14", - "drizzle-kit": "^0.31.10", - "msw": "^2.14.6", - "shadcn": "^4.11.0", - "tailwindcss": "^4.3.1", - "typescript": "^6.0.3", - "vite": "^8.0.16", - "vitest": "^4.1.9" - }, - "msw": { - "workerDirectory": [ - "static" - ] - } -} diff --git a/apps/web/src/lib/workspace-boundary.test.ts b/apps/web/src/lib/workspace-boundary.test.ts deleted file mode 100644 index 66a11c5..0000000 --- a/apps/web/src/lib/workspace-boundary.test.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { existsSync, readFileSync } from "node:fs"; -import { join } from "node:path"; -import { describe, expect, test } from "vitest"; - -const root = existsSync(join(process.cwd(), "turbo.json")) - ? process.cwd() - : join(process.cwd(), "..", ".."); - -describe("workspace boundaries", () => { - test("declares the root as a turbo-managed bun workspace", () => { - const packageJson = JSON.parse( - readFileSync(join(root, "package.json"), "utf8"), - ) as { - private?: boolean; - scripts?: Record; - workspaces?: string[]; - }; - - expect(packageJson.private).toBe(true); - expect(packageJson.workspaces).toEqual(["apps/*", "packages/*"]); - expect(packageJson.scripts?.build).toBe("turbo build"); - expect(existsSync(join(root, "turbo.json"))).toBe(true); - }); - - test("keeps the website app and reusable UI library as separate packages", () => { - const webPackage = JSON.parse( - readFileSync(join(root, "apps/web/package.json"), "utf8"), - ) as { dependencies?: Record; name?: string }; - const uiPackage = JSON.parse( - readFileSync(join(root, "packages/ui/package.json"), "utf8"), - ) as { exports?: Record; name?: string }; - - expect(webPackage.name).toBe("@dimensionlab/web"); - expect(webPackage.dependencies?.["@dimensionlab/ui"]).toBe("workspace:*"); - expect(uiPackage.name).toBe("@dimensionlab/ui"); - expect(uiPackage.exports).toHaveProperty("."); - expect(uiPackage.exports).toHaveProperty("./styles.css"); - }); -}); diff --git a/apps/web/tsconfig.json b/apps/web/tsconfig.json deleted file mode 100644 index edfa07d..0000000 --- a/apps/web/tsconfig.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "extends": "../../tsconfig.base.json", - "compilerOptions": { - "baseUrl": ".", - "paths": { - "@dimensionlab/ui": ["../../packages/ui/src/index.ts"], - "@dimensionlab/ui/styles.css": ["../../packages/ui/src/styles.css"], - "$lib/*": ["src/lib/*"] - }, - "types": ["node", "bun-types", "react", "react-dom", "vite/client"] - }, - "include": [ - "src/**/*.ts", - "src/**/*.tsx", - "tests/**/*.ts", - "vite.config.ts", - "playwright.config.ts", - "drizzle.config.ts" - ], - "exclude": ["build", "dist", "node_modules"] -} diff --git a/bun.lock b/bun.lock index 543520d..36ab7d6 100644 --- a/bun.lock +++ b/bun.lock @@ -4,75 +4,45 @@ "workspaces": { "": { "name": "dimensionlab-website", - "devDependencies": { - "turbo": "^2.5.0", - }, - }, - "apps/web": { - "name": "@dimensionlab/web", - "version": "0.0.1", "dependencies": { - "@dimensionlab/ui": "workspace:*", + "@fontsource-variable/geist": "^5.2.9", + "@iconify/react": "^6.0.2", "@sinclair/typebox": "^0.34.49", "ajv": "^8.20.0", "ajv-formats": "^3.0.1", + "class-variance-authority": "^0.7.1", + "clsx": "^2.1.1", "drizzle-orm": "^0.45.2", + "lucide-react": "^1.21.0", + "radix-ui": "^1.6.0", "react": "^19.2.7", "react-dom": "^19.2.7", + "tailwind-merge": "^3.6.0", "tw-animate-css": "^1.4.0", + "uplot": "^1.6.32", }, "devDependencies": { "@axe-core/playwright": "^4.11.3", "@playwright/test": "^1.61.0", + "@storybook/addon-a11y": "^10.4.6", + "@storybook/addon-vitest": "^10.4.6", + "@storybook/react-vite": "^10.4.6", "@tailwindcss/vite": "^4.3.1", "@types/bun": "^1.3.14", "@types/node": "^25.9.3", "@types/react": "^19.2.17", "@types/react-dom": "^19.2.3", "@vitejs/plugin-react": "^6.0.2", - "bun-types": "^1.3.14", "drizzle-kit": "^0.31.10", "msw": "^2.14.6", "shadcn": "^4.11.0", + "storybook": "^10.4.6", "tailwindcss": "^4.3.1", "typescript": "^6.0.3", "vite": "^8.0.16", "vitest": "^4.1.9", }, }, - "packages/ui": { - "name": "@dimensionlab/ui", - "version": "0.0.1", - "dependencies": { - "@fontsource-variable/geist": "^5.2.9", - "@iconify/react": "^6.0.2", - "class-variance-authority": "^0.7.1", - "clsx": "^2.1.1", - "lucide-react": "^1.21.0", - "radix-ui": "^1.6.0", - "tailwind-merge": "^3.6.0", - "tw-animate-css": "^1.4.0", - "uplot": "^1.6.32", - }, - "devDependencies": { - "@storybook/addon-a11y": "^10.4.6", - "@storybook/addon-vitest": "^10.4.6", - "@storybook/react-vite": "^10.4.6", - "@types/bun": "^1.3.14", - "@types/node": "^25.9.3", - "@types/react": "^19.2.17", - "@types/react-dom": "^19.2.3", - "bun-types": "^1.3.14", - "storybook": "^10.4.6", - "typescript": "^6.0.3", - "vite": "^8.0.16", - "vitest": "^4.1.9", - }, - "peerDependencies": { - "react": "^19.0.0", - "react-dom": "^19.0.0", - }, - }, }, "packages": { "@adobe/css-tools": ["@adobe/css-tools@4.5.0", "", {}, "sha512-6OzddxPio9UiWTCemp4N8cYLV2ZN1ncRnV1cVGtve7dhPOtRkleRyx32GQCYSwDYgaHU3USMm84tNsvKzRCa1Q=="], @@ -137,10 +107,6 @@ "@babel/types": ["@babel/types@7.29.7", "", { "dependencies": { "@babel/helper-string-parser": "^7.29.7", "@babel/helper-validator-identifier": "^7.29.7" } }, "sha512-4zBIxpPzowiZpusoFkyGVwakdRJUyuH5PxQ/PrqghfdFWWasvnCdPfQXHrenDai+gyLARulZjZowCOj6fjT4pA=="], - "@dimensionlab/ui": ["@dimensionlab/ui@workspace:packages/ui"], - - "@dimensionlab/web": ["@dimensionlab/web@workspace:apps/web"], - "@dotenvx/dotenvx": ["@dotenvx/dotenvx@1.74.3", "", { "dependencies": { "commander": "^11.1.0", "conf": "^10.2.0", "dotenv": "^17.2.1", "eciesjs": "^0.4.10", "enquirer": "^2.4.1", "env-paths": "^2.2.1", "execa": "^5.1.1", "fdir": "^6.2.0", "ignore": "^5.3.0", "object-treeify": "1.1.33", "open": "^8.4.2", "picomatch": "^4.0.4", "systeminformation": "^5.22.11", "undici": "^7.11.0", "which": "^4.0.0", "yocto-spinner": "^1.1.0" }, "bin": { "dotenvx": "src/cli/dotenvx.js" } }, "sha512-+VjTIiOCApjB0K4a41+SkN18gTetmhU9UN2JD8LHeNUqo/38FmtgvdtWsW/WWN1dyYRGS7XKeAAb/ruy7x1tRw=="], "@drizzle-team/brocli": ["@drizzle-team/brocli@0.10.2", "", {}, "sha512-z33Il7l5dKjUgGULTqBsQBQwckHh5AbIuxhdsIxDDiZAzBOrZO6q9ogcWC65kU382AfynTfgNumVcNIjuIua6w=="], @@ -157,57 +123,57 @@ "@esbuild-kit/esm-loader": ["@esbuild-kit/esm-loader@2.6.5", "", { "dependencies": { "@esbuild-kit/core-utils": "^3.3.2", "get-tsconfig": "^4.7.0" } }, "sha512-FxEMIkJKnodyA1OaCUoEvbYRkoZlLZ4d/eXFu9Fh8CbBBgP5EmZxrfTRyN0qpXZ4vOvqnE5YdRdcrmUUXuU+dA=="], - "@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.28.1", "", { "os": "aix", "cpu": "ppc64" }, "sha512-Svl7tq8k/08+p6CXPpRjQ1fKX+1odH/BQbb48fV6fj3CWHhsoIOoY87w1oHXm0qEpkIK3ZfVgp0hed3XBXzXMQ=="], + "@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.25.12", "", { "os": "aix", "cpu": "ppc64" }, "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA=="], - "@esbuild/android-arm": ["@esbuild/android-arm@0.28.1", "", { "os": "android", "cpu": "arm" }, "sha512-0k2F129Xdio1TdJfzJ8sy1Q47vUD2NnwdhiAf7drUN1EBTfPf4hsFCtmMgu/6m8JSzsBrlmVjudMBQqOfG8usQ=="], + "@esbuild/android-arm": ["@esbuild/android-arm@0.25.12", "", { "os": "android", "cpu": "arm" }, "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg=="], - "@esbuild/android-arm64": ["@esbuild/android-arm64@0.28.1", "", { "os": "android", "cpu": "arm64" }, "sha512-34EGEbCIAgosYz6goLcopX6Mo7NyGv9tfwEM2/7Ce2VcVRk568iSvniGWcUXIy7wEDR1wzolcxcriFVrWYcwBg=="], + "@esbuild/android-arm64": ["@esbuild/android-arm64@0.25.12", "", { "os": "android", "cpu": "arm64" }, "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg=="], - "@esbuild/android-x64": ["@esbuild/android-x64@0.28.1", "", { "os": "android", "cpu": "x64" }, "sha512-dbwY7ltSMDWsRatcRpCnES4F+im88OCUgGZjy52shC7GqHRE/cYlxNbB4Z4UpJswpcc4Qxd2oE/ufM0p61IKng=="], + "@esbuild/android-x64": ["@esbuild/android-x64@0.25.12", "", { "os": "android", "cpu": "x64" }, "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg=="], - "@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.28.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-TZbWkQY7kvTAXbXUT7uVACR5cMHsDiSz9z7ZKAX/RTq/WJEk3QyRr0wZpNhBDX+/0CtdqUIJlOiodQcta6tY3Q=="], + "@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.25.12", "", { "os": "darwin", "cpu": "arm64" }, "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg=="], - "@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.28.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-zfdzgK9ACBNZLI/CyHTOx81SyNbM6YXn7rxSgX97VjyiPl9W1i4Ka4fgKECEoFCKGpvBj5qArWIGgQjOwkgskQ=="], + "@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.25.12", "", { "os": "darwin", "cpu": "x64" }, "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA=="], - "@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.28.1", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-wG2EA8ENdEI0qhkSZMjfqrdY+ziCYCPMmtZjjIwOmXFjmyzEHn+UUxk5of+SYsjtfs3VpnlC7QLzSI5hY/rOAw=="], + "@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.25.12", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg=="], - "@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.28.1", "", { "os": "freebsd", "cpu": "x64" }, "sha512-i7dZ9vQgnvSCzi/rYCXNgtF/U+eKZNJBzu3eTQbRgHnM7tNSizLOkRFAl3qzVc/Op/u5YkHHa4pf/3DOYHthLQ=="], + "@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.25.12", "", { "os": "freebsd", "cpu": "x64" }, "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ=="], - "@esbuild/linux-arm": ["@esbuild/linux-arm@0.28.1", "", { "os": "linux", "cpu": "arm" }, "sha512-qVXBOHQS+d5Y722GwJzJUtOLlX7km3CraOaGormF1pDtPd2C/l1SHRPgjLunLGe51Sh5YYWKMFDyV4SxgMQYTQ=="], + "@esbuild/linux-arm": ["@esbuild/linux-arm@0.25.12", "", { "os": "linux", "cpu": "arm" }, "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw=="], - "@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.28.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-yHs+0uc8+nvEAfAfxrWQKK5peSNzBc4PegcMO0EJ2hT71uA7vB8Ihg2e77R2P7SG5uYjPbHlLLmve4LLLRCf0g=="], + "@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.25.12", "", { "os": "linux", "cpu": "arm64" }, "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ=="], - "@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.28.1", "", { "os": "linux", "cpu": "ia32" }, "sha512-d1z4ZuP0ajrfz/FhGT4vv278rX8KnPPJx8i5+AtK7TYbx9Le9F1hyzurZpkEyjkGa9dUGhQow4C1NmeGvqxN2w=="], + "@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.25.12", "", { "os": "linux", "cpu": "ia32" }, "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA=="], - "@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.28.1", "", { "os": "linux", "cpu": "none" }, "sha512-M5sRjUVZrkm1OAPR3dlOYzNmN+loZKGVi1VUQGrwuqLcbR6qeAz+famMhjASeH3YVKvZz+zT1jlh/keC3Rj/lg=="], + "@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.25.12", "", { "os": "linux", "cpu": "none" }, "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng=="], - "@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.28.1", "", { "os": "linux", "cpu": "none" }, "sha512-mRObBZeHh2OxcBFPWE/FjylkRgZdYuiTR3vaTozquCGOH14iP9oN4x4Ge81CoIDYQrXmIxpFumJBu5MtZpnQJQ=="], + "@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.25.12", "", { "os": "linux", "cpu": "none" }, "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw=="], - "@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.28.1", "", { "os": "linux", "cpu": "ppc64" }, "sha512-slScBsMAb3GFDcdrCgLwZtPYRoH2H/youv10QiZyRjmsP48fznoveWytSgCI/R0ZcUgpc0ZhIUEx6LHts8yrfQ=="], + "@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.25.12", "", { "os": "linux", "cpu": "ppc64" }, "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA=="], - "@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.28.1", "", { "os": "linux", "cpu": "none" }, "sha512-kw0owk1o0GFETUJyW0jc0G4Yzs0BHZn0JDZ8JRT088vjJYX777BAs1fDGxAC+q831qOs2DTC96mNsG2opdfyyQ=="], + "@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.25.12", "", { "os": "linux", "cpu": "none" }, "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w=="], - "@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.28.1", "", { "os": "linux", "cpu": "s390x" }, "sha512-/lAIjX8aYFRByhh6L5rYtPEDRqa9de/4V/juOXcta5frjvzXO4/sqEtyytse0g3zZFuWu5cDN0MkLz2qRDD2Ag=="], + "@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.25.12", "", { "os": "linux", "cpu": "s390x" }, "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg=="], - "@esbuild/linux-x64": ["@esbuild/linux-x64@0.28.1", "", { "os": "linux", "cpu": "x64" }, "sha512-u/anNYF2mmVOEDwLtnQ1wOr3EZ9sTNGLWrsYGYwHWzGA3Si84IOkHXlbWTD1NB+9/1lcnweYKO54uhxZydNzfA=="], + "@esbuild/linux-x64": ["@esbuild/linux-x64@0.25.12", "", { "os": "linux", "cpu": "x64" }, "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw=="], - "@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.28.1", "", { "os": "none", "cpu": "arm64" }, "sha512-oks0DYbLwWMmaakTsCb+zL4E+aHRVLom9IJZOAthMQEPiQmydXHkziYEsGYRx0uNV/IjEKGAV941JzH02pflqw=="], + "@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.25.12", "", { "os": "none", "cpu": "arm64" }, "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg=="], - "@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.28.1", "", { "os": "none", "cpu": "x64" }, "sha512-aeL6lAnN89Hz43Mlh1G8ARasbuoYvSITDEx0tHh5b7jJnHcssqgjy9Yx430GDpmCa6OyrKoS0aNRjKundRizGg=="], + "@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.25.12", "", { "os": "none", "cpu": "x64" }, "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ=="], - "@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.28.1", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-MEFJe5C3R8pwXdZ5Y21oo6m7ePiS0d9pWucn99O/wvyJZChoIQKrQDxKrGeW8F5+T0okTHesAmDeiHDTIq0V/Q=="], + "@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.25.12", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A=="], - "@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.28.1", "", { "os": "openbsd", "cpu": "x64" }, "sha512-i/ZLIOafE0Z8cI/XANJAixoJL/uRAoS2xOA3rb0xN+KK0K177cMAsQYkzHtBrtMXAKuAc7HGgcWiZ/sRC1Nxgw=="], + "@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.25.12", "", { "os": "openbsd", "cpu": "x64" }, "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw=="], - "@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.28.1", "", { "os": "none", "cpu": "arm64" }, "sha512-ge+Z7EXFNt2BO1oAMsVpiQ8EwndV9i1xXerAeTIK7AtPs3bKFXQM7nlRxDSIUIMeueR1CNXxqztLzdNeReKBJg=="], + "@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.25.12", "", { "os": "none", "cpu": "arm64" }, "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg=="], - "@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.28.1", "", { "os": "sunos", "cpu": "x64" }, "sha512-BEjgtECkL3vY+SaSQ6nzVfiALUeFxpawyp8Jmf5PtYhf1Ug40N1h/hxlhts+f1FvSvarEigdxS3BlSMI2PJLcQ=="], + "@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.25.12", "", { "os": "sunos", "cpu": "x64" }, "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w=="], - "@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.28.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-lCv9eK/H6ZJWbE7bh2nw54CZ9M2nupBxJcTsdk/QQnWkdSjKGuxmmH8/GWrlT1eMmZfn4dGcCjRte397WqfQXA=="], + "@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.25.12", "", { "os": "win32", "cpu": "arm64" }, "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg=="], - "@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.28.1", "", { "os": "win32", "cpu": "ia32" }, "sha512-zvb/mB2bSCoJOpoCBgYKKpX6YM6mJBlBUVUtVj41DlZJVEB6/0CKlRYxP5wWl1C1ILiCoAU5wZZ4q1P3qeS6Eg=="], + "@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.25.12", "", { "os": "win32", "cpu": "ia32" }, "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ=="], - "@esbuild/win32-x64": ["@esbuild/win32-x64@0.28.1", "", { "os": "win32", "cpu": "x64" }, "sha512-bm4Mowrv+GXMlpWX++EcXw/iLyd1o3+bJkC2DkWXYVvgZCqD/bSj9ctZeAMC3cIxgjRVR2Dufaiu4YPxr5gW1A=="], + "@esbuild/win32-x64": ["@esbuild/win32-x64@0.25.12", "", { "os": "win32", "cpu": "x64" }, "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA=="], "@floating-ui/core": ["@floating-ui/core@1.7.5", "", { "dependencies": { "@floating-ui/utils": "^0.2.11" } }, "sha512-1Ih4WTWyw0+lKyFMcBHGbb5U5FtuHJuujoyyr5zTaWS5EYMeT6Jb2AuDeftsCsEuchO+mM2ij5+q9crhydzLhQ=="], @@ -621,18 +587,6 @@ "@ts-morph/common": ["@ts-morph/common@0.27.0", "", { "dependencies": { "fast-glob": "^3.3.3", "minimatch": "^10.0.1", "path-browserify": "^1.0.1" } }, "sha512-Wf29UqxWDpc+i61k3oIOzcUfQt79PIT9y/MWfAGlrkjg6lBC1hwDECLXPVJAhWjiGbfBCxZd65F/LIZF3+jeJQ=="], - "@turbo/darwin-64": ["@turbo/darwin-64@2.9.18", "", { "os": "darwin", "cpu": "x64" }, "sha512-9f27peFu16ur8c0v9nUFUEyBnbKuuFsUTjHFWfmwGfzySBXbHwzU44QhZon6Mznz0cHsIr3984NQj/bVrnGSRw=="], - - "@turbo/darwin-arm64": ["@turbo/darwin-arm64@2.9.18", "", { "os": "darwin", "cpu": "arm64" }, "sha512-9A6TMRq/Ib+QnbhLlgkhOm+624wO4pzSQ/yQviQfWHOlFvaYxdnIAYmu2H6TS6y7kSVL0DvzNe04NbESTOzFVQ=="], - - "@turbo/linux-64": ["@turbo/linux-64@2.9.18", "", { "os": "linux", "cpu": "x64" }, "sha512-zCdIDtz69AnbYh913elJRRoF3QY5aa2HNnf+4rAkc7bQ+tWujiDkCNV7stazOUPggaDvhKIf2Z87qHftTeXSkw=="], - - "@turbo/linux-arm64": ["@turbo/linux-arm64@2.9.18", "", { "os": "linux", "cpu": "arm64" }, "sha512-Va1kXI04naMgYwqv/5Dfa36dTDx8015U7oaQAjrXa45ua9OoFjSV4OmvkML4EmXvUclQHCiBRbY8bvd0jV7eAg=="], - - "@turbo/windows-64": ["@turbo/windows-64@2.9.18", "", { "os": "win32", "cpu": "x64" }, "sha512-m0kDhZANxSNz9ck1ybogFscHabriAsp4eDFNrN/1H5WrgTF7b3VlcPZnhuO3v2+E2KnCbeAc+UUT10BZZHdDKw=="], - - "@turbo/windows-arm64": ["@turbo/windows-arm64@2.9.18", "", { "os": "win32", "cpu": "arm64" }, "sha512-nUdR8WqoomUys9iIQmG45TMiizJ+5BV8egSeLLZba/AWblyp3fVBcIH1kSE58OtK4g2YzbMJEth6Ttv9w5rqMA=="], - "@tybys/wasm-util": ["@tybys/wasm-util@0.10.2", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-RoBvJ2X0wuKlWFIjrwffGw1IqZHKQqzIchKaadZZfnNpsAYp2mM0h36JtPCjNDAHGgYez/15uMBpfGwchhiMgg=="], "@types/aria-query": ["@types/aria-query@5.0.4", "", {}, "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw=="], @@ -701,7 +655,7 @@ "ansi-regex": ["ansi-regex@6.2.2", "", {}, "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg=="], - "ansi-styles": ["ansi-styles@5.2.0", "", {}, "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA=="], + "ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], "argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="], @@ -715,7 +669,7 @@ "atomically": ["atomically@1.7.0", "", {}, "sha512-Xcz9l0z7y9yQ9rdDaxlmaI4uJHf/T8g9hOEzJcsEqX2SjCj4J20uK7+ldkDHMbpJDK76wF7xEIgxc/vSlsfw5w=="], - "axe-core": ["axe-core@4.12.1", "", {}, "sha512-s7iGf5GaVMxEG0ENN9x+xTr7GFZCb1ZP/1uATUpCEK2X78nDB3RwbtFCo9pGAf9ru+VwoQ464DkaLEeRM08wJA=="], + "axe-core": ["axe-core@4.11.4", "", {}, "sha512-KunSNx+TVpkAw/6ULfhnx+HWRecjqZGTOyquAoWHYLRSdK1tB5Ihce1ZW+UY3fj33bYAFWPu7W/GRSmmrCGuxA=="], "balanced-match": ["balanced-match@4.0.4", "", {}, "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA=="], @@ -865,7 +819,7 @@ "es-object-atoms": ["es-object-atoms@1.1.2", "", { "dependencies": { "es-errors": "^1.3.0" } }, "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw=="], - "esbuild": ["esbuild@0.28.1", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.28.1", "@esbuild/android-arm": "0.28.1", "@esbuild/android-arm64": "0.28.1", "@esbuild/android-x64": "0.28.1", "@esbuild/darwin-arm64": "0.28.1", "@esbuild/darwin-x64": "0.28.1", "@esbuild/freebsd-arm64": "0.28.1", "@esbuild/freebsd-x64": "0.28.1", "@esbuild/linux-arm": "0.28.1", "@esbuild/linux-arm64": "0.28.1", "@esbuild/linux-ia32": "0.28.1", "@esbuild/linux-loong64": "0.28.1", "@esbuild/linux-mips64el": "0.28.1", "@esbuild/linux-ppc64": "0.28.1", "@esbuild/linux-riscv64": "0.28.1", "@esbuild/linux-s390x": "0.28.1", "@esbuild/linux-x64": "0.28.1", "@esbuild/netbsd-arm64": "0.28.1", "@esbuild/netbsd-x64": "0.28.1", "@esbuild/openbsd-arm64": "0.28.1", "@esbuild/openbsd-x64": "0.28.1", "@esbuild/openharmony-arm64": "0.28.1", "@esbuild/sunos-x64": "0.28.1", "@esbuild/win32-arm64": "0.28.1", "@esbuild/win32-ia32": "0.28.1", "@esbuild/win32-x64": "0.28.1" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-HrJrvZv5ayxBzPfwphOoNzkzOIIlifzk0KJrGK2c8R4+LKpMtpYLQeUdjnwjWv/LZlkH2laZk+4w78pi99D4Vw=="], + "esbuild": ["esbuild@0.25.12", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.12", "@esbuild/android-arm": "0.25.12", "@esbuild/android-arm64": "0.25.12", "@esbuild/android-x64": "0.25.12", "@esbuild/darwin-arm64": "0.25.12", "@esbuild/darwin-x64": "0.25.12", "@esbuild/freebsd-arm64": "0.25.12", "@esbuild/freebsd-x64": "0.25.12", "@esbuild/linux-arm": "0.25.12", "@esbuild/linux-arm64": "0.25.12", "@esbuild/linux-ia32": "0.25.12", "@esbuild/linux-loong64": "0.25.12", "@esbuild/linux-mips64el": "0.25.12", "@esbuild/linux-ppc64": "0.25.12", "@esbuild/linux-riscv64": "0.25.12", "@esbuild/linux-s390x": "0.25.12", "@esbuild/linux-x64": "0.25.12", "@esbuild/netbsd-arm64": "0.25.12", "@esbuild/netbsd-x64": "0.25.12", "@esbuild/openbsd-arm64": "0.25.12", "@esbuild/openbsd-x64": "0.25.12", "@esbuild/openharmony-arm64": "0.25.12", "@esbuild/sunos-x64": "0.25.12", "@esbuild/win32-arm64": "0.25.12", "@esbuild/win32-ia32": "0.25.12", "@esbuild/win32-x64": "0.25.12" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg=="], "escalade": ["escalade@3.2.0", "", {}, "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA=="], @@ -991,7 +945,7 @@ "is-core-module": ["is-core-module@2.16.2", "", { "dependencies": { "hasown": "^2.0.3" } }, "sha512-evOr8xfXKxE6qSR0hSXL2r3sd7ALj8+7jQEUvPYcm5sgZFdJ+AYzT6yNmJenvIYQBgIGwfwz08sL8zoL7yq2BA=="], - "is-docker": ["is-docker@3.0.0", "", { "bin": { "is-docker": "cli.js" } }, "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ=="], + "is-docker": ["is-docker@2.2.1", "", { "bin": { "is-docker": "cli.js" } }, "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ=="], "is-extglob": ["is-extglob@2.1.1", "", {}, "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ=="], @@ -1021,7 +975,7 @@ "is-unicode-supported": ["is-unicode-supported@2.1.0", "", {}, "sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ=="], - "is-wsl": ["is-wsl@3.1.1", "", { "dependencies": { "is-inside-container": "^1.0.0" } }, "sha512-e6rvdUCiQCAuumZslxRJWR/Doq4VpPR82kqclvcS0efgt430SlGIk05vdCN58+VrzgtIcfNODjozVielycD4Sw=="], + "is-wsl": ["is-wsl@2.2.0", "", { "dependencies": { "is-docker": "^2.0.0" } }, "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww=="], "isexe": ["isexe@3.1.5", "", {}, "sha512-6B3tLtFqtQS4ekarvLVMZ+X+VlvQekbe4taUkf/rhVO3d/h0M2rfARm/pXLcPEsjjMsFgrFgSrhQIxcSVrBz8w=="], @@ -1147,7 +1101,7 @@ "onetime": ["onetime@5.1.2", "", { "dependencies": { "mimic-fn": "^2.1.0" } }, "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg=="], - "open": ["open@10.2.0", "", { "dependencies": { "default-browser": "^5.2.1", "define-lazy-prop": "^3.0.0", "is-inside-container": "^1.0.0", "wsl-utils": "^0.1.0" } }, "sha512-YgBpdJHPyQ2UE5x+hlSXcnejzAvD0b22U2OuAP+8OnlJT+PjWPxtgmGqKKc+RgTM63U9gN0YzrYc71R2WT/hTA=="], + "open": ["open@11.0.0", "", { "dependencies": { "default-browser": "^5.4.0", "define-lazy-prop": "^3.0.0", "is-in-ssh": "^1.0.0", "is-inside-container": "^1.0.0", "powershell-utils": "^0.1.0", "wsl-utils": "^0.3.0" } }, "sha512-smsWv2LzFjP03xmvFoJ331ss6h+jixfA4UUV/Bsiyuu4YJPfN+FIQGOIiv4w9/+MoHkfkJ22UIaQWRVFRfH6Vw=="], "ora": ["ora@8.2.0", "", { "dependencies": { "chalk": "^5.3.0", "cli-cursor": "^5.0.0", "cli-spinners": "^2.9.2", "is-interactive": "^2.0.0", "is-unicode-supported": "^2.0.0", "log-symbols": "^6.0.0", "stdin-discarder": "^0.2.2", "string-width": "^7.2.0", "strip-ansi": "^7.1.0" } }, "sha512-weP+BZ8MVNnlCm8c0Qdc1WSWq4Qn7I+9CJGm7Qali6g44e/PUzbjNqJX5NJ9ljlNMosfJvg1fKEGILklK9cwnw=="], @@ -1377,8 +1331,6 @@ "tsx": ["tsx@4.22.4", "", { "dependencies": { "esbuild": "~0.28.0" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "bin": { "tsx": "dist/cli.mjs" } }, "sha512-X8EX+XV4QR5xCsrgxaED954zTDfY8KqlDtskKEL0cHhyS/P8b4IFOvGDQpsC9Q1XnLq915wEfwwY/zzskCtmhg=="], - "turbo": ["turbo@2.9.18", "", { "optionalDependencies": { "@turbo/darwin-64": "2.9.18", "@turbo/darwin-arm64": "2.9.18", "@turbo/linux-64": "2.9.18", "@turbo/linux-arm64": "2.9.18", "@turbo/windows-64": "2.9.18", "@turbo/windows-arm64": "2.9.18" }, "bin": { "turbo": "bin/turbo" } }, "sha512-bwabv6PupzeavybzEoArBAkwq5fnzwf8OFnRtpHwnviFWuwJPFxtyH+aVp36TmIqK3aYYgtTJ3J0m2ysxxSzQg=="], - "tw-animate-css": ["tw-animate-css@1.4.0", "", {}, "sha512-7bziOlRqH0hJx80h/3mbicLW7o8qLsH5+RaLR2t+OHM3D0JlWGODQKQ4cxbK7WlvmUxpcj6Kgu6EKqjrGFe3QQ=="], "type-fest": ["type-fest@5.7.0", "", { "dependencies": { "tagged-tag": "^1.0.0" } }, "sha512-1URUxUqfHFM1c+zfSPsa3gnkO7Aq21qyH75SIduNYz4SzY964rn1X2vCMQaHSHhktiw+0kPa2iyb6PUpXqB6Vg=="], @@ -1435,7 +1387,7 @@ "ws": ["ws@8.21.0", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-Vsp28b7DRcimFQvrqu2Wek3z1iYxDCWqHYB8Qsnk/S4RfaCQzPGPyBNuVjJV3cd6UiKtUtp6sNM77gWvzcCH+g=="], - "wsl-utils": ["wsl-utils@0.1.0", "", { "dependencies": { "is-wsl": "^3.1.0" } }, "sha512-h3Fbisa2nKGPxCpm89Hk33lBLsnaGBvctQopaBSOW/uIs6FTe1ATyAnKFJrzVs9vpGdsTe73WF3V4lIsk4Gacw=="], + "wsl-utils": ["wsl-utils@0.3.1", "", { "dependencies": { "is-wsl": "^3.1.0", "powershell-utils": "^0.1.0" } }, "sha512-g/eziiSUNBSsdDJtCLB8bdYEUMj4jR7AGeUo96p/3dTafgjHhpF4RiCFPiRILwjQoDXx5MqkBr4fwWtR3Ky4Wg=="], "y18n": ["y18n@5.0.8", "", {}, "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA=="], @@ -1453,8 +1405,6 @@ "zod-to-json-schema": ["zod-to-json-schema@3.25.2", "", { "peerDependencies": { "zod": "^3.25.28 || ^4" } }, "sha512-O/PgfnpT1xKSDeQYSCfRI5Gy3hPf91mKVDuYLUHZJMiDFptvP41MSnWofm8dnCm0256ZNfZIM7DSzuSMAFnjHA=="], - "@axe-core/playwright/axe-core": ["axe-core@4.11.4", "", {}, "sha512-KunSNx+TVpkAw/6ULfhnx+HWRecjqZGTOyquAoWHYLRSdK1tB5Ihce1ZW+UY3fj33bYAFWPu7W/GRSmmrCGuxA=="], - "@babel/core/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], "@babel/helper-compilation-targets/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], @@ -1479,6 +1429,8 @@ "@rolldown/binding-wasm32-wasi/@emnapi/runtime": ["@emnapi/runtime@1.10.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA=="], + "@storybook/addon-a11y/axe-core": ["axe-core@4.12.1", "", {}, "sha512-s7iGf5GaVMxEG0ENN9x+xTr7GFZCb1ZP/1uATUpCEK2X78nDB3RwbtFCo9pGAf9ru+VwoQ464DkaLEeRM08wJA=="], + "@tailwindcss/oxide-wasm32-wasi/@emnapi/core": ["@emnapi/core@1.11.0", "", { "dependencies": { "@emnapi/wasi-threads": "1.2.2", "tslib": "^2.4.0" }, "bundled": true }, "sha512-l9Oo58x0HOP5znGzVhYW9U3e5wVuA4LAZU2AGezTmkhO1CgQRFDhDg4nneHsu/t3WniXg9QrG2nIXL/ZS8ln8Q=="], "@tailwindcss/oxide-wasm32-wasi/@emnapi/runtime": ["@emnapi/runtime@1.11.0", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-55coeOFKHv1ywEcUXJtWU5f+Jr/W5tZDvZig8DLKSwUN1JpROQ4rk/SNOQiFWmaR/VKF4zuFyW1B8JduOSv6Pg=="], @@ -1515,12 +1467,12 @@ "dot-prop/is-obj": ["is-obj@2.0.0", "", {}, "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w=="], - "drizzle-kit/esbuild": ["esbuild@0.25.12", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.12", "@esbuild/android-arm": "0.25.12", "@esbuild/android-arm64": "0.25.12", "@esbuild/android-x64": "0.25.12", "@esbuild/darwin-arm64": "0.25.12", "@esbuild/darwin-x64": "0.25.12", "@esbuild/freebsd-arm64": "0.25.12", "@esbuild/freebsd-x64": "0.25.12", "@esbuild/linux-arm": "0.25.12", "@esbuild/linux-arm64": "0.25.12", "@esbuild/linux-ia32": "0.25.12", "@esbuild/linux-loong64": "0.25.12", "@esbuild/linux-mips64el": "0.25.12", "@esbuild/linux-ppc64": "0.25.12", "@esbuild/linux-riscv64": "0.25.12", "@esbuild/linux-s390x": "0.25.12", "@esbuild/linux-x64": "0.25.12", "@esbuild/netbsd-arm64": "0.25.12", "@esbuild/netbsd-x64": "0.25.12", "@esbuild/openbsd-arm64": "0.25.12", "@esbuild/openbsd-x64": "0.25.12", "@esbuild/openharmony-arm64": "0.25.12", "@esbuild/sunos-x64": "0.25.12", "@esbuild/win32-arm64": "0.25.12", "@esbuild/win32-ia32": "0.25.12", "@esbuild/win32-x64": "0.25.12" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg=="], - "enquirer/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], "express/cookie": ["cookie@0.7.2", "", {}, "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w=="], + "is-inside-container/is-docker": ["is-docker@3.0.0", "", { "bin": { "is-docker": "cli.js" } }, "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ=="], + "log-symbols/is-unicode-supported": ["is-unicode-supported@1.3.0", "", {}, "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ=="], "micromatch/picomatch": ["picomatch@2.3.2", "", {}, "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA=="], @@ -1537,6 +1489,8 @@ "pretty-format/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], + "pretty-format/ansi-styles": ["ansi-styles@5.2.0", "", {}, "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA=="], + "prompts/kleur": ["kleur@3.0.3", "", {}, "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w=="], "redent/strip-indent": ["strip-indent@3.0.0", "", { "dependencies": { "min-indent": "^1.0.0" } }, "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ=="], @@ -1547,20 +1501,24 @@ "router/path-to-regexp": ["path-to-regexp@8.4.2", "", {}, "sha512-qRcuIdP69NPm4qbACK+aDogI5CBDMi1jKe0ry5rSQJz8JVLsC7jV8XpiJjGRLLol3N+R5ihGYcrPLTno6pAdBA=="], - "shadcn/open": ["open@11.0.0", "", { "dependencies": { "default-browser": "^5.4.0", "define-lazy-prop": "^3.0.0", "is-in-ssh": "^1.0.0", "is-inside-container": "^1.0.0", "powershell-utils": "^0.1.0", "wsl-utils": "^0.3.0" } }, "sha512-smsWv2LzFjP03xmvFoJ331ss6h+jixfA4UUV/Bsiyuu4YJPfN+FIQGOIiv4w9/+MoHkfkJ22UIaQWRVFRfH6Vw=="], + "storybook/esbuild": ["esbuild@0.28.1", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.28.1", "@esbuild/android-arm": "0.28.1", "@esbuild/android-arm64": "0.28.1", "@esbuild/android-x64": "0.28.1", "@esbuild/darwin-arm64": "0.28.1", "@esbuild/darwin-x64": "0.28.1", "@esbuild/freebsd-arm64": "0.28.1", "@esbuild/freebsd-x64": "0.28.1", "@esbuild/linux-arm": "0.28.1", "@esbuild/linux-arm64": "0.28.1", "@esbuild/linux-ia32": "0.28.1", "@esbuild/linux-loong64": "0.28.1", "@esbuild/linux-mips64el": "0.28.1", "@esbuild/linux-ppc64": "0.28.1", "@esbuild/linux-riscv64": "0.28.1", "@esbuild/linux-s390x": "0.28.1", "@esbuild/linux-x64": "0.28.1", "@esbuild/netbsd-arm64": "0.28.1", "@esbuild/netbsd-x64": "0.28.1", "@esbuild/openbsd-arm64": "0.28.1", "@esbuild/openbsd-x64": "0.28.1", "@esbuild/openharmony-arm64": "0.28.1", "@esbuild/sunos-x64": "0.28.1", "@esbuild/win32-arm64": "0.28.1", "@esbuild/win32-ia32": "0.28.1", "@esbuild/win32-x64": "0.28.1" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-HrJrvZv5ayxBzPfwphOoNzkzOIIlifzk0KJrGK2c8R4+LKpMtpYLQeUdjnwjWv/LZlkH2laZk+4w78pi99D4Vw=="], + + "storybook/open": ["open@10.2.0", "", { "dependencies": { "default-browser": "^5.2.1", "define-lazy-prop": "^3.0.0", "is-inside-container": "^1.0.0", "wsl-utils": "^0.1.0" } }, "sha512-YgBpdJHPyQ2UE5x+hlSXcnejzAvD0b22U2OuAP+8OnlJT+PjWPxtgmGqKKc+RgTM63U9gN0YzrYc71R2WT/hTA=="], "string-width/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], + "tsx/esbuild": ["esbuild@0.28.1", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.28.1", "@esbuild/android-arm": "0.28.1", "@esbuild/android-arm64": "0.28.1", "@esbuild/android-x64": "0.28.1", "@esbuild/darwin-arm64": "0.28.1", "@esbuild/darwin-x64": "0.28.1", "@esbuild/freebsd-arm64": "0.28.1", "@esbuild/freebsd-x64": "0.28.1", "@esbuild/linux-arm": "0.28.1", "@esbuild/linux-arm64": "0.28.1", "@esbuild/linux-ia32": "0.28.1", "@esbuild/linux-loong64": "0.28.1", "@esbuild/linux-mips64el": "0.28.1", "@esbuild/linux-ppc64": "0.28.1", "@esbuild/linux-riscv64": "0.28.1", "@esbuild/linux-s390x": "0.28.1", "@esbuild/linux-x64": "0.28.1", "@esbuild/netbsd-arm64": "0.28.1", "@esbuild/netbsd-x64": "0.28.1", "@esbuild/openbsd-arm64": "0.28.1", "@esbuild/openbsd-x64": "0.28.1", "@esbuild/openharmony-arm64": "0.28.1", "@esbuild/sunos-x64": "0.28.1", "@esbuild/win32-arm64": "0.28.1", "@esbuild/win32-ia32": "0.28.1", "@esbuild/win32-x64": "0.28.1" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-HrJrvZv5ayxBzPfwphOoNzkzOIIlifzk0KJrGK2c8R4+LKpMtpYLQeUdjnwjWv/LZlkH2laZk+4w78pi99D4Vw=="], + "type-is/content-type": ["content-type@2.0.0", "", {}, "sha512-j/O/d7GcZCyNl7/hwZAb606rzqkyvaDctLmckbxLzHvFBzTJHuGEdodATcP3yIRoDrLHkIATJuvzbFlp/ki2cQ=="], "vitest/@vitest/expect": ["@vitest/expect@4.1.9", "", { "dependencies": { "@standard-schema/spec": "^1.1.0", "@types/chai": "^5.2.2", "@vitest/spy": "4.1.9", "@vitest/utils": "4.1.9", "chai": "^6.2.2", "tinyrainbow": "^3.1.0" } }, "sha512-vl/rYsUKcBr3SnQn166+XR5ZQcgMx3DQhFWdfli/cWpLnLUmbxZvyrJZotLFUryib+LtArYMSTJ5RbQ57ZqrlA=="], "vitest/@vitest/spy": ["@vitest/spy@4.1.9", "", {}, "sha512-fHpsS6mIi+PiEW+vcRVOMkX1oSaPKne3VOclSFICPcGOmfKgXPU5iAah+wcNcj2xPrCCmfq99IDGf+EojhhvhA=="], - "wrap-ansi/ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], - "wrap-ansi/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], + "wsl-utils/is-wsl": ["is-wsl@3.1.1", "", { "dependencies": { "is-inside-container": "^1.0.0" } }, "sha512-e6rvdUCiQCAuumZslxRJWR/Doq4VpPR82kqclvcS0efgt430SlGIk05vdCN58+VrzgtIcfNODjozVielycD4Sw=="], + "@dotenvx/dotenvx/execa/get-stream": ["get-stream@6.0.1", "", {}, "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg=="], "@dotenvx/dotenvx/execa/human-signals": ["human-signals@2.1.0", "", {}, "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw=="], @@ -1575,10 +1533,6 @@ "@dotenvx/dotenvx/open/define-lazy-prop": ["define-lazy-prop@2.0.0", "", {}, "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og=="], - "@dotenvx/dotenvx/open/is-docker": ["is-docker@2.2.1", "", { "bin": { "is-docker": "cli.js" } }, "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ=="], - - "@dotenvx/dotenvx/open/is-wsl": ["is-wsl@2.2.0", "", { "dependencies": { "is-docker": "^2.0.0" } }, "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww=="], - "@esbuild-kit/core-utils/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.18.20", "", { "os": "android", "cpu": "arm" }, "sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw=="], "@esbuild-kit/core-utils/esbuild/@esbuild/android-arm64": ["@esbuild/android-arm64@0.18.20", "", { "os": "android", "cpu": "arm64" }, "sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ=="], @@ -1631,68 +1585,122 @@ "cross-spawn/which/isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="], - "drizzle-kit/esbuild/@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.25.12", "", { "os": "aix", "cpu": "ppc64" }, "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA=="], - - "drizzle-kit/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.25.12", "", { "os": "android", "cpu": "arm" }, "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg=="], - - "drizzle-kit/esbuild/@esbuild/android-arm64": ["@esbuild/android-arm64@0.25.12", "", { "os": "android", "cpu": "arm64" }, "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg=="], - - "drizzle-kit/esbuild/@esbuild/android-x64": ["@esbuild/android-x64@0.25.12", "", { "os": "android", "cpu": "x64" }, "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg=="], - - "drizzle-kit/esbuild/@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.25.12", "", { "os": "darwin", "cpu": "arm64" }, "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg=="], - - "drizzle-kit/esbuild/@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.25.12", "", { "os": "darwin", "cpu": "x64" }, "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA=="], - - "drizzle-kit/esbuild/@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.25.12", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg=="], - - "drizzle-kit/esbuild/@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.25.12", "", { "os": "freebsd", "cpu": "x64" }, "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ=="], - - "drizzle-kit/esbuild/@esbuild/linux-arm": ["@esbuild/linux-arm@0.25.12", "", { "os": "linux", "cpu": "arm" }, "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw=="], - - "drizzle-kit/esbuild/@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.25.12", "", { "os": "linux", "cpu": "arm64" }, "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ=="], - - "drizzle-kit/esbuild/@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.25.12", "", { "os": "linux", "cpu": "ia32" }, "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA=="], - - "drizzle-kit/esbuild/@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.25.12", "", { "os": "linux", "cpu": "none" }, "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng=="], - - "drizzle-kit/esbuild/@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.25.12", "", { "os": "linux", "cpu": "none" }, "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw=="], - - "drizzle-kit/esbuild/@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.25.12", "", { "os": "linux", "cpu": "ppc64" }, "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA=="], - - "drizzle-kit/esbuild/@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.25.12", "", { "os": "linux", "cpu": "none" }, "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w=="], - - "drizzle-kit/esbuild/@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.25.12", "", { "os": "linux", "cpu": "s390x" }, "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg=="], - - "drizzle-kit/esbuild/@esbuild/linux-x64": ["@esbuild/linux-x64@0.25.12", "", { "os": "linux", "cpu": "x64" }, "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw=="], - - "drizzle-kit/esbuild/@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.25.12", "", { "os": "none", "cpu": "arm64" }, "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg=="], - - "drizzle-kit/esbuild/@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.25.12", "", { "os": "none", "cpu": "x64" }, "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ=="], - - "drizzle-kit/esbuild/@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.25.12", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A=="], - - "drizzle-kit/esbuild/@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.25.12", "", { "os": "openbsd", "cpu": "x64" }, "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw=="], - - "drizzle-kit/esbuild/@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.25.12", "", { "os": "none", "cpu": "arm64" }, "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg=="], - - "drizzle-kit/esbuild/@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.25.12", "", { "os": "sunos", "cpu": "x64" }, "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w=="], - - "drizzle-kit/esbuild/@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.25.12", "", { "os": "win32", "cpu": "arm64" }, "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg=="], - - "drizzle-kit/esbuild/@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.25.12", "", { "os": "win32", "cpu": "ia32" }, "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ=="], - - "drizzle-kit/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.25.12", "", { "os": "win32", "cpu": "x64" }, "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA=="], - "enquirer/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], "ora/string-width/emoji-regex": ["emoji-regex@10.6.0", "", {}, "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A=="], - "shadcn/open/wsl-utils": ["wsl-utils@0.3.1", "", { "dependencies": { "is-wsl": "^3.1.0", "powershell-utils": "^0.1.0" } }, "sha512-g/eziiSUNBSsdDJtCLB8bdYEUMj4jR7AGeUo96p/3dTafgjHhpF4RiCFPiRILwjQoDXx5MqkBr4fwWtR3Ky4Wg=="], + "storybook/esbuild/@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.28.1", "", { "os": "aix", "cpu": "ppc64" }, "sha512-Svl7tq8k/08+p6CXPpRjQ1fKX+1odH/BQbb48fV6fj3CWHhsoIOoY87w1oHXm0qEpkIK3ZfVgp0hed3XBXzXMQ=="], + + "storybook/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.28.1", "", { "os": "android", "cpu": "arm" }, "sha512-0k2F129Xdio1TdJfzJ8sy1Q47vUD2NnwdhiAf7drUN1EBTfPf4hsFCtmMgu/6m8JSzsBrlmVjudMBQqOfG8usQ=="], + + "storybook/esbuild/@esbuild/android-arm64": ["@esbuild/android-arm64@0.28.1", "", { "os": "android", "cpu": "arm64" }, "sha512-34EGEbCIAgosYz6goLcopX6Mo7NyGv9tfwEM2/7Ce2VcVRk568iSvniGWcUXIy7wEDR1wzolcxcriFVrWYcwBg=="], + + "storybook/esbuild/@esbuild/android-x64": ["@esbuild/android-x64@0.28.1", "", { "os": "android", "cpu": "x64" }, "sha512-dbwY7ltSMDWsRatcRpCnES4F+im88OCUgGZjy52shC7GqHRE/cYlxNbB4Z4UpJswpcc4Qxd2oE/ufM0p61IKng=="], + + "storybook/esbuild/@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.28.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-TZbWkQY7kvTAXbXUT7uVACR5cMHsDiSz9z7ZKAX/RTq/WJEk3QyRr0wZpNhBDX+/0CtdqUIJlOiodQcta6tY3Q=="], + + "storybook/esbuild/@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.28.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-zfdzgK9ACBNZLI/CyHTOx81SyNbM6YXn7rxSgX97VjyiPl9W1i4Ka4fgKECEoFCKGpvBj5qArWIGgQjOwkgskQ=="], + + "storybook/esbuild/@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.28.1", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-wG2EA8ENdEI0qhkSZMjfqrdY+ziCYCPMmtZjjIwOmXFjmyzEHn+UUxk5of+SYsjtfs3VpnlC7QLzSI5hY/rOAw=="], + + "storybook/esbuild/@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.28.1", "", { "os": "freebsd", "cpu": "x64" }, "sha512-i7dZ9vQgnvSCzi/rYCXNgtF/U+eKZNJBzu3eTQbRgHnM7tNSizLOkRFAl3qzVc/Op/u5YkHHa4pf/3DOYHthLQ=="], + + "storybook/esbuild/@esbuild/linux-arm": ["@esbuild/linux-arm@0.28.1", "", { "os": "linux", "cpu": "arm" }, "sha512-qVXBOHQS+d5Y722GwJzJUtOLlX7km3CraOaGormF1pDtPd2C/l1SHRPgjLunLGe51Sh5YYWKMFDyV4SxgMQYTQ=="], + + "storybook/esbuild/@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.28.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-yHs+0uc8+nvEAfAfxrWQKK5peSNzBc4PegcMO0EJ2hT71uA7vB8Ihg2e77R2P7SG5uYjPbHlLLmve4LLLRCf0g=="], + + "storybook/esbuild/@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.28.1", "", { "os": "linux", "cpu": "ia32" }, "sha512-d1z4ZuP0ajrfz/FhGT4vv278rX8KnPPJx8i5+AtK7TYbx9Le9F1hyzurZpkEyjkGa9dUGhQow4C1NmeGvqxN2w=="], + + "storybook/esbuild/@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.28.1", "", { "os": "linux", "cpu": "none" }, "sha512-M5sRjUVZrkm1OAPR3dlOYzNmN+loZKGVi1VUQGrwuqLcbR6qeAz+famMhjASeH3YVKvZz+zT1jlh/keC3Rj/lg=="], + + "storybook/esbuild/@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.28.1", "", { "os": "linux", "cpu": "none" }, "sha512-mRObBZeHh2OxcBFPWE/FjylkRgZdYuiTR3vaTozquCGOH14iP9oN4x4Ge81CoIDYQrXmIxpFumJBu5MtZpnQJQ=="], + + "storybook/esbuild/@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.28.1", "", { "os": "linux", "cpu": "ppc64" }, "sha512-slScBsMAb3GFDcdrCgLwZtPYRoH2H/youv10QiZyRjmsP48fznoveWytSgCI/R0ZcUgpc0ZhIUEx6LHts8yrfQ=="], + + "storybook/esbuild/@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.28.1", "", { "os": "linux", "cpu": "none" }, "sha512-kw0owk1o0GFETUJyW0jc0G4Yzs0BHZn0JDZ8JRT088vjJYX777BAs1fDGxAC+q831qOs2DTC96mNsG2opdfyyQ=="], + + "storybook/esbuild/@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.28.1", "", { "os": "linux", "cpu": "s390x" }, "sha512-/lAIjX8aYFRByhh6L5rYtPEDRqa9de/4V/juOXcta5frjvzXO4/sqEtyytse0g3zZFuWu5cDN0MkLz2qRDD2Ag=="], + + "storybook/esbuild/@esbuild/linux-x64": ["@esbuild/linux-x64@0.28.1", "", { "os": "linux", "cpu": "x64" }, "sha512-u/anNYF2mmVOEDwLtnQ1wOr3EZ9sTNGLWrsYGYwHWzGA3Si84IOkHXlbWTD1NB+9/1lcnweYKO54uhxZydNzfA=="], + + "storybook/esbuild/@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.28.1", "", { "os": "none", "cpu": "arm64" }, "sha512-oks0DYbLwWMmaakTsCb+zL4E+aHRVLom9IJZOAthMQEPiQmydXHkziYEsGYRx0uNV/IjEKGAV941JzH02pflqw=="], + + "storybook/esbuild/@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.28.1", "", { "os": "none", "cpu": "x64" }, "sha512-aeL6lAnN89Hz43Mlh1G8ARasbuoYvSITDEx0tHh5b7jJnHcssqgjy9Yx430GDpmCa6OyrKoS0aNRjKundRizGg=="], + + "storybook/esbuild/@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.28.1", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-MEFJe5C3R8pwXdZ5Y21oo6m7ePiS0d9pWucn99O/wvyJZChoIQKrQDxKrGeW8F5+T0okTHesAmDeiHDTIq0V/Q=="], + + "storybook/esbuild/@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.28.1", "", { "os": "openbsd", "cpu": "x64" }, "sha512-i/ZLIOafE0Z8cI/XANJAixoJL/uRAoS2xOA3rb0xN+KK0K177cMAsQYkzHtBrtMXAKuAc7HGgcWiZ/sRC1Nxgw=="], + + "storybook/esbuild/@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.28.1", "", { "os": "none", "cpu": "arm64" }, "sha512-ge+Z7EXFNt2BO1oAMsVpiQ8EwndV9i1xXerAeTIK7AtPs3bKFXQM7nlRxDSIUIMeueR1CNXxqztLzdNeReKBJg=="], + + "storybook/esbuild/@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.28.1", "", { "os": "sunos", "cpu": "x64" }, "sha512-BEjgtECkL3vY+SaSQ6nzVfiALUeFxpawyp8Jmf5PtYhf1Ug40N1h/hxlhts+f1FvSvarEigdxS3BlSMI2PJLcQ=="], + + "storybook/esbuild/@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.28.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-lCv9eK/H6ZJWbE7bh2nw54CZ9M2nupBxJcTsdk/QQnWkdSjKGuxmmH8/GWrlT1eMmZfn4dGcCjRte397WqfQXA=="], + + "storybook/esbuild/@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.28.1", "", { "os": "win32", "cpu": "ia32" }, "sha512-zvb/mB2bSCoJOpoCBgYKKpX6YM6mJBlBUVUtVj41DlZJVEB6/0CKlRYxP5wWl1C1ILiCoAU5wZZ4q1P3qeS6Eg=="], + + "storybook/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.28.1", "", { "os": "win32", "cpu": "x64" }, "sha512-bm4Mowrv+GXMlpWX++EcXw/iLyd1o3+bJkC2DkWXYVvgZCqD/bSj9ctZeAMC3cIxgjRVR2Dufaiu4YPxr5gW1A=="], + + "storybook/open/wsl-utils": ["wsl-utils@0.1.0", "", { "dependencies": { "is-wsl": "^3.1.0" } }, "sha512-h3Fbisa2nKGPxCpm89Hk33lBLsnaGBvctQopaBSOW/uIs6FTe1ATyAnKFJrzVs9vpGdsTe73WF3V4lIsk4Gacw=="], "string-width/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], + "tsx/esbuild/@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.28.1", "", { "os": "aix", "cpu": "ppc64" }, "sha512-Svl7tq8k/08+p6CXPpRjQ1fKX+1odH/BQbb48fV6fj3CWHhsoIOoY87w1oHXm0qEpkIK3ZfVgp0hed3XBXzXMQ=="], + + "tsx/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.28.1", "", { "os": "android", "cpu": "arm" }, "sha512-0k2F129Xdio1TdJfzJ8sy1Q47vUD2NnwdhiAf7drUN1EBTfPf4hsFCtmMgu/6m8JSzsBrlmVjudMBQqOfG8usQ=="], + + "tsx/esbuild/@esbuild/android-arm64": ["@esbuild/android-arm64@0.28.1", "", { "os": "android", "cpu": "arm64" }, "sha512-34EGEbCIAgosYz6goLcopX6Mo7NyGv9tfwEM2/7Ce2VcVRk568iSvniGWcUXIy7wEDR1wzolcxcriFVrWYcwBg=="], + + "tsx/esbuild/@esbuild/android-x64": ["@esbuild/android-x64@0.28.1", "", { "os": "android", "cpu": "x64" }, "sha512-dbwY7ltSMDWsRatcRpCnES4F+im88OCUgGZjy52shC7GqHRE/cYlxNbB4Z4UpJswpcc4Qxd2oE/ufM0p61IKng=="], + + "tsx/esbuild/@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.28.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-TZbWkQY7kvTAXbXUT7uVACR5cMHsDiSz9z7ZKAX/RTq/WJEk3QyRr0wZpNhBDX+/0CtdqUIJlOiodQcta6tY3Q=="], + + "tsx/esbuild/@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.28.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-zfdzgK9ACBNZLI/CyHTOx81SyNbM6YXn7rxSgX97VjyiPl9W1i4Ka4fgKECEoFCKGpvBj5qArWIGgQjOwkgskQ=="], + + "tsx/esbuild/@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.28.1", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-wG2EA8ENdEI0qhkSZMjfqrdY+ziCYCPMmtZjjIwOmXFjmyzEHn+UUxk5of+SYsjtfs3VpnlC7QLzSI5hY/rOAw=="], + + "tsx/esbuild/@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.28.1", "", { "os": "freebsd", "cpu": "x64" }, "sha512-i7dZ9vQgnvSCzi/rYCXNgtF/U+eKZNJBzu3eTQbRgHnM7tNSizLOkRFAl3qzVc/Op/u5YkHHa4pf/3DOYHthLQ=="], + + "tsx/esbuild/@esbuild/linux-arm": ["@esbuild/linux-arm@0.28.1", "", { "os": "linux", "cpu": "arm" }, "sha512-qVXBOHQS+d5Y722GwJzJUtOLlX7km3CraOaGormF1pDtPd2C/l1SHRPgjLunLGe51Sh5YYWKMFDyV4SxgMQYTQ=="], + + "tsx/esbuild/@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.28.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-yHs+0uc8+nvEAfAfxrWQKK5peSNzBc4PegcMO0EJ2hT71uA7vB8Ihg2e77R2P7SG5uYjPbHlLLmve4LLLRCf0g=="], + + "tsx/esbuild/@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.28.1", "", { "os": "linux", "cpu": "ia32" }, "sha512-d1z4ZuP0ajrfz/FhGT4vv278rX8KnPPJx8i5+AtK7TYbx9Le9F1hyzurZpkEyjkGa9dUGhQow4C1NmeGvqxN2w=="], + + "tsx/esbuild/@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.28.1", "", { "os": "linux", "cpu": "none" }, "sha512-M5sRjUVZrkm1OAPR3dlOYzNmN+loZKGVi1VUQGrwuqLcbR6qeAz+famMhjASeH3YVKvZz+zT1jlh/keC3Rj/lg=="], + + "tsx/esbuild/@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.28.1", "", { "os": "linux", "cpu": "none" }, "sha512-mRObBZeHh2OxcBFPWE/FjylkRgZdYuiTR3vaTozquCGOH14iP9oN4x4Ge81CoIDYQrXmIxpFumJBu5MtZpnQJQ=="], + + "tsx/esbuild/@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.28.1", "", { "os": "linux", "cpu": "ppc64" }, "sha512-slScBsMAb3GFDcdrCgLwZtPYRoH2H/youv10QiZyRjmsP48fznoveWytSgCI/R0ZcUgpc0ZhIUEx6LHts8yrfQ=="], + + "tsx/esbuild/@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.28.1", "", { "os": "linux", "cpu": "none" }, "sha512-kw0owk1o0GFETUJyW0jc0G4Yzs0BHZn0JDZ8JRT088vjJYX777BAs1fDGxAC+q831qOs2DTC96mNsG2opdfyyQ=="], + + "tsx/esbuild/@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.28.1", "", { "os": "linux", "cpu": "s390x" }, "sha512-/lAIjX8aYFRByhh6L5rYtPEDRqa9de/4V/juOXcta5frjvzXO4/sqEtyytse0g3zZFuWu5cDN0MkLz2qRDD2Ag=="], + + "tsx/esbuild/@esbuild/linux-x64": ["@esbuild/linux-x64@0.28.1", "", { "os": "linux", "cpu": "x64" }, "sha512-u/anNYF2mmVOEDwLtnQ1wOr3EZ9sTNGLWrsYGYwHWzGA3Si84IOkHXlbWTD1NB+9/1lcnweYKO54uhxZydNzfA=="], + + "tsx/esbuild/@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.28.1", "", { "os": "none", "cpu": "arm64" }, "sha512-oks0DYbLwWMmaakTsCb+zL4E+aHRVLom9IJZOAthMQEPiQmydXHkziYEsGYRx0uNV/IjEKGAV941JzH02pflqw=="], + + "tsx/esbuild/@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.28.1", "", { "os": "none", "cpu": "x64" }, "sha512-aeL6lAnN89Hz43Mlh1G8ARasbuoYvSITDEx0tHh5b7jJnHcssqgjy9Yx430GDpmCa6OyrKoS0aNRjKundRizGg=="], + + "tsx/esbuild/@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.28.1", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-MEFJe5C3R8pwXdZ5Y21oo6m7ePiS0d9pWucn99O/wvyJZChoIQKrQDxKrGeW8F5+T0okTHesAmDeiHDTIq0V/Q=="], + + "tsx/esbuild/@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.28.1", "", { "os": "openbsd", "cpu": "x64" }, "sha512-i/ZLIOafE0Z8cI/XANJAixoJL/uRAoS2xOA3rb0xN+KK0K177cMAsQYkzHtBrtMXAKuAc7HGgcWiZ/sRC1Nxgw=="], + + "tsx/esbuild/@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.28.1", "", { "os": "none", "cpu": "arm64" }, "sha512-ge+Z7EXFNt2BO1oAMsVpiQ8EwndV9i1xXerAeTIK7AtPs3bKFXQM7nlRxDSIUIMeueR1CNXxqztLzdNeReKBJg=="], + + "tsx/esbuild/@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.28.1", "", { "os": "sunos", "cpu": "x64" }, "sha512-BEjgtECkL3vY+SaSQ6nzVfiALUeFxpawyp8Jmf5PtYhf1Ug40N1h/hxlhts+f1FvSvarEigdxS3BlSMI2PJLcQ=="], + + "tsx/esbuild/@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.28.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-lCv9eK/H6ZJWbE7bh2nw54CZ9M2nupBxJcTsdk/QQnWkdSjKGuxmmH8/GWrlT1eMmZfn4dGcCjRte397WqfQXA=="], + + "tsx/esbuild/@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.28.1", "", { "os": "win32", "cpu": "ia32" }, "sha512-zvb/mB2bSCoJOpoCBgYKKpX6YM6mJBlBUVUtVj41DlZJVEB6/0CKlRYxP5wWl1C1ILiCoAU5wZZ4q1P3qeS6Eg=="], + + "tsx/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.28.1", "", { "os": "win32", "cpu": "x64" }, "sha512-bm4Mowrv+GXMlpWX++EcXw/iLyd1o3+bJkC2DkWXYVvgZCqD/bSj9ctZeAMC3cIxgjRVR2Dufaiu4YPxr5gW1A=="], + "vitest/@vitest/expect/chai": ["chai@6.2.2", "", {}, "sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg=="], "wrap-ansi/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], + + "storybook/open/wsl-utils/is-wsl": ["is-wsl@3.1.1", "", { "dependencies": { "is-inside-container": "^1.0.0" } }, "sha512-e6rvdUCiQCAuumZslxRJWR/Doq4VpPR82kqclvcS0efgt430SlGIk05vdCN58+VrzgtIcfNODjozVielycD4Sw=="], } } diff --git a/packages/ui/components.json b/components.json similarity index 67% rename from packages/ui/components.json rename to components.json index d951369..f8d8d59 100644 --- a/packages/ui/components.json +++ b/components.json @@ -5,7 +5,7 @@ "tsx": true, "tailwind": { "config": "", - "css": "src/styles.css", + "css": "src/app.css", "baseColor": "neutral", "cssVariables": true, "prefix": "" @@ -13,11 +13,11 @@ "iconLibrary": "lucide", "rtl": false, "aliases": { - "components": "src/components", - "utils": "src/utils", - "ui": "src/primitives", - "lib": "src", - "hooks": "src/hooks" + "components": "$lib/components", + "utils": "$lib/utils", + "ui": "$lib/components/ui", + "lib": "$lib/.", + "hooks": "$lib/hooks" }, "menuColor": "default", "menuAccent": "subtle", diff --git a/docs/superpowers/plans/2026-06-20-turbo-component-library.md b/docs/superpowers/plans/2026-06-20-turbo-component-library.md deleted file mode 100644 index e53586c..0000000 --- a/docs/superpowers/plans/2026-06-20-turbo-component-library.md +++ /dev/null @@ -1,436 +0,0 @@ -# Turbo Component Library Implementation Plan - -> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. - -**Goal:** Convert the single-package Dimension Lab website into a Turborepo workspace where `apps/web` consumes a compiled reusable React component library from `packages/ui`. - -**Architecture:** The root becomes a private Bun workspace with Turbo orchestration. `packages/ui` owns generic reusable UI components, CSS, theme helpers, Storybook, and package-level tests. `apps/web` owns the website runtime, model/server/database logic, the model-to-UI adapter, e2e tests, and deployment container. - -**Tech Stack:** Bun workspaces, Turborepo, Vite, React 19, TypeScript, Storybook React Vite, Tailwind CSS v4, shadcn CSS, Vitest, Playwright, Drizzle ORM, Bun SQLite. - ---- - -## File Structure - -- Create root `turbo.json`: cacheable task graph for `build`, `check`, `test:unit`, `build-storybook`, `test:e2e`, and `test:qa`. -- Create root `tsconfig.base.json`: shared strict TypeScript defaults. -- Modify root `package.json`: private workspace root with `apps/*` and `packages/*`, Turbo scripts, and `turbo` dev dependency only. -- Create `packages/ui/package.json`: compiled `@dimensionlab/ui` package with code and CSS exports. -- Create `packages/ui/tsconfig.json` and `packages/ui/tsconfig.build.json`: package typecheck and declaration/JS build config. -- Create `packages/ui/src/styles.css`: library style entry importing font, uPlot CSS, tokens, and component CSS. -- Move `src/lib/ui/components/**` to `packages/ui/src/components/**`. -- Move `src/lib/ui/stories/**` to `packages/ui/src/stories/**`. -- Move `src/lib/ui/tokens.css` to `packages/ui/src/tokens.css`. -- Move `src/lib/ui/theme.ts`, `types.ts`, `format.ts`, `fixtures.ts`, and `index.ts` to `packages/ui/src/**`. -- Move `src/lib/ui/components/styles.css` to `packages/ui/src/components/styles.css`. -- Move `.storybook/**` to `packages/ui/.storybook/**`. -- Move unused shadcn primitives from `src/lib/components/ui/**` to `packages/ui/src/primitives/**` and update their `cn` import to package-local `src/utils.ts`. -- Move `src/lib/utils.ts` to `packages/ui/src/utils.ts`. -- Move app runtime files into `apps/web`: `src/App.tsx`, `src/main.tsx`, `src/app.css`, `src/server/**`, `src/lib/model/**`, `src/lib/server/**`, `src/lib/testing/**`, `src/vite-env.d.ts`, `src/page.test.tsx`, `src/server/dev.ts`, `tests/**`, `drizzle/**`, `Containerfile`, `index.html`, `playwright.config.ts`, `vite.config.ts`, `drizzle.config.ts`, and app-specific README/deployment files. -- Move `src/lib/ui/model-renderer.ts` and `model-renderer.test.ts` into `apps/web/src/lib/ui-adapter/**`. -- Create `apps/web/package.json`, `apps/web/tsconfig.json`, `apps/web/vite.config.ts`, and `apps/web/playwright.config.ts`. -- Update `apps/web/src/App.tsx` to import components/types from `@dimensionlab/ui` and import the adapter from `$lib/ui-adapter/model-renderer`. -- Update `apps/web/src/app.css` to import `@dimensionlab/ui/styles.css` instead of local UI CSS files. -- Update tests that read paths so package boundary tests inspect `packages/ui` and app tests inspect `apps/web`. -- Update `README.md` to describe the workspace commands, package boundaries, Storybook location, and deployment path. - -## Task 1: Workspace And Boundary Tests - -**Files:** -- Modify: `package.json` -- Create: `turbo.json` -- Create: `tsconfig.base.json` -- Create: `packages/ui/package.json` -- Create: `packages/ui/tsconfig.json` -- Create: `packages/ui/tsconfig.build.json` -- Create: `apps/web/package.json` -- Create: `apps/web/tsconfig.json` -- Create: `apps/web/src/lib/workspace-boundary.test.ts` - -- [ ] **Step 1: Write the failing workspace boundary test** - -Create `apps/web/src/lib/workspace-boundary.test.ts`: - -```ts -import { existsSync, readFileSync } from "node:fs"; -import { join } from "node:path"; -import { describe, expect, test } from "vitest"; - -const root = join(import.meta.dir, "../../../.."); - -describe("workspace boundaries", () => { - test("declares the root as a turbo-managed bun workspace", () => { - const packageJson = JSON.parse(readFileSync(join(root, "package.json"), "utf8")) as { - private?: boolean; - scripts?: Record; - workspaces?: string[]; - }; - - expect(packageJson.private).toBe(true); - expect(packageJson.workspaces).toEqual(["apps/*", "packages/*"]); - expect(packageJson.scripts?.build).toBe("turbo build"); - expect(existsSync(join(root, "turbo.json"))).toBe(true); - }); - - test("keeps the website app and reusable UI library as separate packages", () => { - const webPackage = JSON.parse( - readFileSync(join(root, "apps/web/package.json"), "utf8"), - ) as { dependencies?: Record; name?: string }; - const uiPackage = JSON.parse( - readFileSync(join(root, "packages/ui/package.json"), "utf8"), - ) as { exports?: Record; name?: string }; - - expect(webPackage.name).toBe("@dimensionlab/web"); - expect(webPackage.dependencies?.["@dimensionlab/ui"]).toBe("workspace:*"); - expect(uiPackage.name).toBe("@dimensionlab/ui"); - expect(uiPackage.exports).toHaveProperty("."); - expect(uiPackage.exports).toHaveProperty("./styles.css"); - }); -}); -``` - -- [ ] **Step 2: Run the test to verify it fails** - -Run: - -```sh -bunx vitest run apps/web/src/lib/workspace-boundary.test.ts -``` - -Expected: FAIL because `apps/web`, `packages/ui`, and `turbo.json` do not exist. - -- [ ] **Step 3: Add minimal workspace manifests** - -Create root `package.json` as the workspace orchestrator: - -```json -{ - "name": "dimensionlab", - "version": "0.0.1", - "private": true, - "type": "module", - "packageManager": "bun@1.3.14", - "workspaces": ["apps/*", "packages/*"], - "scripts": { - "dev": "turbo dev --filter=@dimensionlab/web", - "build": "turbo build", - "preview": "bun --cwd apps/web run preview", - "storybook": "turbo storybook --filter=@dimensionlab/ui", - "build-storybook": "turbo build-storybook --filter=@dimensionlab/ui", - "check": "turbo check", - "test": "turbo test:unit", - "test:unit": "turbo test:unit", - "test:e2e": "turbo test:e2e --filter=@dimensionlab/web", - "test:qa": "turbo test:qa", - "db:generate": "bun --cwd apps/web run db:generate", - "db:check": "bun --cwd apps/web run db:check" - }, - "devDependencies": { - "turbo": "^2.5.0" - } -} -``` - -Create `turbo.json`: - -```json -{ - "$schema": "https://turbo.build/schema.json", - "tasks": { - "build": { - "dependsOn": ["^build"], - "outputs": ["dist/**", "build/**"] - }, - "check": { - "dependsOn": ["^build"], - "outputs": [] - }, - "test:unit": { - "dependsOn": ["^build"], - "outputs": [] - }, - "build-storybook": { - "dependsOn": ["^build"], - "outputs": ["storybook-static/**"] - }, - "test:e2e": { - "dependsOn": ["build", "^build"], - "outputs": ["test-results/**", "playwright-report/**"] - }, - "test:qa": { - "dependsOn": ["check", "test:unit", "build", "build-storybook", "test:e2e"], - "outputs": [] - }, - "dev": { - "cache": false, - "persistent": true - }, - "storybook": { - "cache": false, - "persistent": true - } - } -} -``` - -Create minimal `packages/ui/package.json` with `@dimensionlab/ui` exports and -minimal `apps/web/package.json` with `@dimensionlab/ui` as a workspace -dependency. Move the full dependency lists in Task 2 and Task 3. - -- [ ] **Step 4: Run the boundary test** - -Run: - -```sh -bunx vitest run apps/web/src/lib/workspace-boundary.test.ts -``` - -Expected: PASS. - -- [ ] **Step 5: Commit** - -```sh -git add package.json turbo.json tsconfig.base.json apps/web/package.json apps/web/tsconfig.json apps/web/src/lib/workspace-boundary.test.ts packages/ui/package.json packages/ui/tsconfig.json packages/ui/tsconfig.build.json -git commit -m "build: add turbo workspace manifests" -``` - -## Task 2: Extract The UI Package - -**Files:** -- Move: `src/lib/ui/components/**` to `packages/ui/src/components/**` -- Move: `src/lib/ui/stories/**` to `packages/ui/src/stories/**` -- Move: `src/lib/ui/{index.ts,types.ts,theme.ts,format.ts,fixtures.ts,tokens.css}` to `packages/ui/src/**` -- Move: `.storybook/**` to `packages/ui/.storybook/**` -- Move: `src/lib/components/ui/**` to `packages/ui/src/primitives/**` -- Move: `src/lib/utils.ts` to `packages/ui/src/utils.ts` -- Create: `packages/ui/src/styles.css` -- Modify: `packages/ui/src/index.ts` -- Modify: `packages/ui/src/storybook.test.ts` -- Modify: `packages/ui/src/content-boundary.test.ts` - -- [ ] **Step 1: Write the failing UI isolation assertion** - -Update the package boundary tests to read from `packages/ui/src` and assert no -imports from `apps/web`, `$lib/server`, or `$lib/model` exist: - -```ts -expect(source).not.toMatch(/from ["'](?:apps\/web|\$lib\/server|\$lib\/model)/); -``` - -Run: - -```sh -bunx vitest run packages/ui/src/content-boundary.test.ts -``` - -Expected: FAIL until the files move and the app-specific adapter is removed. - -- [ ] **Step 2: Move generic UI files** - -Run mechanical moves with `git mv`. Move `model-renderer.ts` out of the UI -package in Task 3 rather than into `packages/ui`. - -- [ ] **Step 3: Add the UI style entry** - -Create `packages/ui/src/styles.css`: - -```css -@import "@fontsource-variable/geist"; -@import "uplot/dist/uPlot.min.css"; -@import "./tokens.css"; -@import "./components/styles.css"; -``` - -- [ ] **Step 4: Make package imports relative or package-local** - -Update moved primitive files to import `cn` from `../utils`. -Remove `dashboardDocumentToUiDashboard` from `packages/ui/src/index.ts`. - -- [ ] **Step 5: Build the package** - -Run: - -```sh -bun --cwd packages/ui run build -bun --cwd packages/ui run check -bun --cwd packages/ui run test:unit -``` - -Expected: PASS and `packages/ui/dist` contains `index.js`, `index.d.ts`, and -CSS files. - -- [ ] **Step 6: Commit** - -```sh -git add packages/ui src/lib/ui src/lib/components src/lib/utils.ts -git commit -m "refactor(ui): extract reusable component package" -``` - -## Task 3: Move The Web App Workspace - -**Files:** -- Move: `src/**` app files that are not reusable UI to `apps/web/src/**` -- Move: `tests/**` to `apps/web/tests/**` -- Move: `drizzle/**` to `apps/web/drizzle/**` -- Move: `Containerfile` to `apps/web/Containerfile` -- Move: `index.html`, `vite.config.ts`, `playwright.config.ts`, `drizzle.config.ts` to `apps/web/**` -- Create: `apps/web/src/lib/ui-adapter/model-renderer.ts` -- Modify: `apps/web/src/App.tsx` -- Modify: `apps/web/src/app.css` - -- [ ] **Step 1: Move the model adapter out of UI** - -Move `src/lib/ui/model-renderer.ts` to -`apps/web/src/lib/ui-adapter/model-renderer.ts` and update imports from -`$lib/model` plus UI types from `@dimensionlab/ui`. - -- [ ] **Step 2: Move app runtime and tests** - -Use `git mv` for app/server/model/test/deployment files into `apps/web`. - -- [ ] **Step 3: Update app imports** - -In `apps/web/src/App.tsx`, import UI components and types from -`@dimensionlab/ui`, and import `dashboardDocumentToUiDashboard` from -`$lib/ui-adapter/model-renderer`. - -In `apps/web/src/app.css`, replace local UI imports with: - -```css -@import "tailwindcss"; -@import "tw-animate-css"; -@import "shadcn/tailwind.css"; -@import "@dimensionlab/ui/styles.css"; -``` - -- [ ] **Step 4: Run app typecheck and unit tests** - -Run: - -```sh -bun --cwd apps/web run check -bun --cwd apps/web run test:unit -``` - -Expected: PASS. - -- [ ] **Step 5: Commit** - -```sh -git add apps/web src tests drizzle Containerfile index.html vite.config.ts playwright.config.ts drizzle.config.ts -git commit -m "refactor(web): move website into app workspace" -``` - -## Task 4: Wire Turbo, Storybook, Playwright, And Container - -**Files:** -- Modify: `apps/web/playwright.config.ts` -- Modify: `apps/web/Containerfile` -- Modify: `apps/web/vite.config.ts` -- Modify: `packages/ui/.storybook/main.ts` -- Modify: `packages/ui/.storybook/preview.ts` -- Modify: `tests/e2e/storybook-server.ts` after move to `apps/web/tests/e2e/storybook-server.ts` -- Modify: `README.md` - -- [ ] **Step 1: Update Playwright commands for workspaces** - -In `apps/web/playwright.config.ts`, make the web server command build from the -workspace root or app directory consistently: - -```ts -command: `DISABLE_LIVE_DATASOURCES=1 bun run build && DISABLE_LIVE_DATASOURCES=1 DATABASE_URL=${databaseUrl} HOST=127.0.0.1 PORT=${port} bun build/index.js` -``` - -This command runs inside `apps/web` when invoked through the app package script. - -- [ ] **Step 2: Update Storybook package paths** - -`packages/ui/.storybook/main.ts` should use `../src/**/*.stories.@(js|ts|tsx)`. -`packages/ui/.storybook/preview.ts` should import `../src/styles.css` and use -generic MSW handlers only if they are moved into the UI package. - -- [ ] **Step 3: Update the container build** - -`apps/web/Containerfile` should build from the repository root context or copy -only the workspace files it needs. Preserve the runtime command: - -```dockerfile -CMD ["bun", "build/index.js"] -``` - -- [ ] **Step 4: Run full root checks** - -Run: - -```sh -bun install -bun run check -bun run test:unit -bun run build -bun run build-storybook -bun run test:e2e -``` - -Expected: PASS. - -- [ ] **Step 5: Commit** - -```sh -git add README.md apps/web packages/ui package.json turbo.json bun.lock -git commit -m "build: wire turbo workspace qa" -``` - -## Task 5: Final QA, PR, Review, Merge, Deploy - -**Files:** -- No planned source edits unless verification finds blockers. - -- [ ] **Step 1: Run release gate** - -Run: - -```sh -bun run test:qa -``` - -Expected: PASS. - -- [ ] **Step 2: Push and open PR** - -Run: - -```sh -git push -u origin codex/turbo-component-library -``` - -Open a ready PR against `main` titled: - -```text -refactor: migrate dashboard to turbo component library -``` - -- [ ] **Step 3: Independent review** - -Send an independent reviewer to inspect the PR diff against the objective: -Turbo repo, `apps/web`, compiled `packages/ui`, reusable components removed -from app, Storybook with UI package, root QA passing, no server behavior change. - -- [ ] **Step 4: Resolve blockers** - -For each blocking review finding, write or update a failing test first, verify -the failure, implement the fix, run targeted checks, commit, push, and re-review. - -- [ ] **Step 5: Merge and deploy** - -When review and checks are clean, merge the PR into `main`, sync the production -checkout, rebuild the Podman image, restart `dimensionlab-website.service`, and -verify `https://dimensionlab.net/` with a browser smoke check. - -## Self-Review - -- Spec coverage: every completion criterion in the design maps to Task 1 through - Task 5. -- Placeholder scan: no task says TBD, TODO, or "add tests" without commands. -- Type consistency: package names are consistently `@dimensionlab/ui` and - `@dimensionlab/web`; the app adapter path is consistently - `$lib/ui-adapter/model-renderer`. diff --git a/docs/superpowers/specs/2026-06-20-turbo-component-library-design.md b/docs/superpowers/specs/2026-06-20-turbo-component-library-design.md deleted file mode 100644 index ba0fefc..0000000 --- a/docs/superpowers/specs/2026-06-20-turbo-component-library-design.md +++ /dev/null @@ -1,186 +0,0 @@ -# Turbo Component Library Migration Design - -## Context - -The current Dimension Lab website is a single Bun/Vite React package. It owns -the browser app, Bun production server, dashboard model, persistence, datasource -adapters, reusable UI components, Storybook, Playwright checks, and container -deployment from one `package.json`. - -The UI components are already mostly generic and content-free under -`src/lib/ui`, but they are not reusable by another project because they live -inside the app package, depend on app path aliases, and share the app build, -test, and Storybook configuration. One file in that area, -`src/lib/ui/model-renderer.ts`, imports the Dimension Lab dashboard model and -therefore is an app adapter, not reusable component-library code. - -The migration goal is to turn the repository into a Turborepo workspace where -the Dimension Lab website consumes a separate reusable React component package. - -## Target Repository Shape - -Use one application workspace and one component-library workspace: - -```text -. -├── apps/ -│ └── web/ -│ ├── src/ -│ ├── tests/ -│ ├── drizzle/ -│ ├── Containerfile -│ └── package.json -├── packages/ -│ └── ui/ -│ ├── src/ -│ ├── .storybook/ -│ ├── package.json -│ └── tsconfig.json -├── package.json -├── turbo.json -├── tsconfig.base.json -└── bun.lock -``` - -The root package is private and contains only workspace orchestration: -workspaces, Turbo scripts, shared dev dependencies where useful, and the lock -file. Runtime dependencies belong to the workspace that imports them. - -## Package Ownership - -`packages/ui` is a compiled React library named `@dimensionlab/ui`. - -It owns: - -- Reusable React components currently under `src/lib/ui/components`. -- UI CSS tokens and component styles. -- Theme helpers currently under `src/lib/ui/theme.ts`. -- Generic UI prop/data types currently under `src/lib/ui/types.ts`. -- Generic formatting helpers currently under `src/lib/ui/format.ts`. -- Generic Storybook stories and story fixtures. -- UI render tests, boundary tests, and Storybook inventory tests. - -It must not import from the website app, the dashboard model, server modules, -database modules, datasource modules, or deployment files. - -The library publishes explicit package exports: - -- `@dimensionlab/ui` for component and type exports. -- `@dimensionlab/ui/styles.css` for the combined token/component CSS entry. -- Optional explicit subpath exports for future direct imports where useful. - -The compiled output goes to `packages/ui/dist` and includes JavaScript, -declaration files, and copied CSS. The package stays private for now but is -structured so it can later be published or moved into another Dimension Lab repo -without taking the website runtime with it. - -`apps/web` owns: - -- The Vite React browser app. -- The Bun production server and API routes. -- Dashboard model, fixtures, schema, validation, and model migrations. -- Drizzle/SQLite persistence and checked-in SQL migrations. -- Datasource adapters and runtime dashboard loading. -- Agent dashboard configuration endpoint. -- The `dashboardDocumentToUiDashboard` adapter that maps the app model to UI - package props. -- Playwright e2e tests and deployment container. - -## Why A Compiled Package - -The component package should be compiled rather than a just-in-time source -package. This is slightly more setup, but it better fits reuse outside the -current app because consumers can import stable JavaScript and declarations -instead of relying on their bundler to transpile this repo's TypeScript source. -It also gives Turbo a cacheable `@dimensionlab/ui#build` task. - -## Build And Task Graph - -Root scripts delegate through Turbo: - -- `bun run dev` runs the web dev server and any required dependency tasks. -- `bun run build` runs package builds in dependency order. -- `bun run check` runs TypeScript checks for all workspaces. -- `bun run test:unit` runs Vitest unit tests for all workspaces. -- `bun run build-storybook` builds Storybook from `packages/ui`. -- `bun run test:e2e` runs the web app Playwright suite. -- `bun run test:qa` is the full release gate. - -`turbo.json` defines `build`, `check`, `test:unit`, `build-storybook`, -`test:e2e`, and `test:qa` tasks. Build outputs include `dist/**`, -`storybook-static/**`, and `build/**` as appropriate. - -The web app depends on `@dimensionlab/ui` using Bun workspace syntax. The web -Vite config aliases `$lib` to `apps/web/src/lib`; the UI package should not use -that app alias. - -## Storybook - -Storybook moves with the component package. It should load -`@dimensionlab/ui/styles.css`, use React Vite Storybook, and keep the existing -generic story inventory. Environment-specific Dimension Lab labels, hostnames, -links, fallback values, and datasource names remain forbidden in package UI -source and stories. - -The repository should no longer have a root Storybook tied to the web app. - -## Deployment - -The deployed website remains the same service from the outside: - -- Production command remains `bun build/index.js` inside the runtime image. -- The container still exposes port `3000` and mounts `/data`. -- Runtime environment variables and database behavior remain unchanged. - -The `Containerfile` moves to `apps/web/Containerfile` or remains root with -updated workspace-aware copy/build steps. The chosen layout must preserve the -existing Podman service contract used by `dimensionlab-website.service`. - -## Testing Strategy - -The migration must add or update tests that prove the new boundaries: - -- The root package is a Bun workspace with `apps/*` and `packages/*`. -- The web app imports UI from `@dimensionlab/ui`, not from local copied - component files. -- `packages/ui` does not import from `apps/web`, `$lib/server`, `$lib/model`, - or any website runtime module. -- `dashboardDocumentToUiDashboard` lives in `apps/web` and is tested there. -- Storybook inventory is evaluated against `packages/ui`. -- The full QA gate still covers typecheck, unit tests, app build, Storybook - build, and Playwright desktop/mobile checks. - -## Completion Criteria - -The migration is complete only when current evidence proves all of these: - -- Root `package.json` is a private workspace root with Turbo scripts. -- `turbo.json` exists and models the workspace task graph. -- The web application lives under `apps/web`. -- The reusable React component library lives under `packages/ui`. -- `packages/ui/package.json` is named `@dimensionlab/ui` and has compiled - exports for code, types, and CSS. -- The web app depends on `@dimensionlab/ui` through the workspace. -- Reusable components and Storybook have been removed from the web app package. -- App-specific model/server/database/datasource code has not moved into - `packages/ui`. -- `dashboardDocumentToUiDashboard` is outside the UI package. -- `bun run check` passes from the root. -- `bun run test:unit` passes from the root. -- `bun run build` passes from the root. -- `bun run build-storybook` passes from the root. -- `bun run test:e2e` passes from the root. -- The production container can still be built and run with the same service - contract. - -## Migration Approach - -Implement this on branch `codex/turbo-component-library` in focused commits: - -1. Add the workspace/Turbo scaffolding and boundary tests. -2. Move UI code and Storybook to `packages/ui`. -3. Move the app runtime into `apps/web` and wire it to `@dimensionlab/ui`. -4. Move the model-to-UI adapter into the web app. -5. Update build, test, Playwright, Storybook, README, and container paths. -6. Run the full QA gate, push a ready PR, perform independent review, resolve - blockers, merge to `main`, and deploy only when checks and review are clean. diff --git a/apps/web/drizzle.config.ts b/drizzle.config.ts similarity index 100% rename from apps/web/drizzle.config.ts rename to drizzle.config.ts diff --git a/apps/web/drizzle/0000_dashboard_persistence.sql b/drizzle/0000_dashboard_persistence.sql similarity index 100% rename from apps/web/drizzle/0000_dashboard_persistence.sql rename to drizzle/0000_dashboard_persistence.sql diff --git a/apps/web/drizzle/meta/0000_snapshot.json b/drizzle/meta/0000_snapshot.json similarity index 100% rename from apps/web/drizzle/meta/0000_snapshot.json rename to drizzle/meta/0000_snapshot.json diff --git a/apps/web/drizzle/meta/_journal.json b/drizzle/meta/_journal.json similarity index 100% rename from apps/web/drizzle/meta/_journal.json rename to drizzle/meta/_journal.json diff --git a/apps/web/index.html b/index.html similarity index 100% rename from apps/web/index.html rename to index.html diff --git a/package.json b/package.json index ba20908..f1cf4ab 100644 --- a/package.json +++ b/package.json @@ -1,28 +1,63 @@ { - "name": "dimensionlab", + "name": "dimensionlab-website", "version": "0.0.1", "private": true, "type": "module", - "packageManager": "bun@1.3.14", - "workspaces": [ - "apps/*", - "packages/*" - ], "scripts": { - "dev": "turbo dev --filter=@dimensionlab/web", - "build": "turbo build", - "preview": "bun --cwd apps/web run preview", - "storybook": "turbo storybook --filter=@dimensionlab/ui", - "build-storybook": "turbo build-storybook --filter=@dimensionlab/ui", - "check": "turbo check", - "test": "turbo test:unit", - "test:unit": "turbo test:unit", - "test:e2e": "turbo test:e2e --filter=@dimensionlab/web", - "test:qa": "turbo test:qa", - "db:generate": "bun --cwd apps/web run db:generate", - "db:check": "bun --cwd apps/web run db:check" + "dev": "bun src/server/dev.ts", + "build": "vite build && bun build src/server/index.ts --target bun --outdir build", + "preview": "HOST=0.0.0.0 PORT=4173 bun build/index.js", + "storybook": "storybook dev -p 6006 --host 0.0.0.0", + "build-storybook": "storybook build", + "check": "tsc --noEmit", + "test": "vitest run", + "test:unit": "vitest run", + "test:e2e": "env -u NO_COLOR playwright test", + "test:qa": "bun run check && bun run test:unit && bun run build && bun run build-storybook && bun run test:e2e", + "db:generate": "drizzle-kit generate", + "db:check": "drizzle-kit check" + }, + "dependencies": { + "@fontsource-variable/geist": "^5.2.9", + "@iconify/react": "^6.0.2", + "@sinclair/typebox": "^0.34.49", + "ajv": "^8.20.0", + "ajv-formats": "^3.0.1", + "class-variance-authority": "^0.7.1", + "clsx": "^2.1.1", + "drizzle-orm": "^0.45.2", + "lucide-react": "^1.21.0", + "radix-ui": "^1.6.0", + "react": "^19.2.7", + "react-dom": "^19.2.7", + "tailwind-merge": "^3.6.0", + "tw-animate-css": "^1.4.0", + "uplot": "^1.6.32" }, "devDependencies": { - "turbo": "^2.5.0" + "@axe-core/playwright": "^4.11.3", + "@playwright/test": "^1.61.0", + "@storybook/addon-a11y": "^10.4.6", + "@storybook/addon-vitest": "^10.4.6", + "@storybook/react-vite": "^10.4.6", + "@tailwindcss/vite": "^4.3.1", + "@types/bun": "^1.3.14", + "@types/node": "^25.9.3", + "@types/react": "^19.2.17", + "@types/react-dom": "^19.2.3", + "@vitejs/plugin-react": "^6.0.2", + "drizzle-kit": "^0.31.10", + "msw": "^2.14.6", + "shadcn": "^4.11.0", + "storybook": "^10.4.6", + "tailwindcss": "^4.3.1", + "typescript": "^6.0.3", + "vite": "^8.0.16", + "vitest": "^4.1.9" + }, + "msw": { + "workerDirectory": [ + "static" + ] } } diff --git a/packages/ui/package.json b/packages/ui/package.json deleted file mode 100644 index cb7febf..0000000 --- a/packages/ui/package.json +++ /dev/null @@ -1,52 +0,0 @@ -{ - "name": "@dimensionlab/ui", - "version": "0.0.1", - "private": true, - "type": "module", - "sideEffects": ["*.css", "**/*.css"], - "exports": { - ".": { - "types": "./dist/index.d.ts", - "default": "./dist/index.js" - }, - "./styles.css": "./dist/styles.css", - "./tokens.css": "./dist/tokens.css" - }, - "scripts": { - "build": "rm -rf dist && tsc -p tsconfig.build.json && mkdir -p dist/components && cp src/styles.css dist/styles.css && cp src/tokens.css dist/tokens.css && cp src/components/styles.css dist/components/styles.css", - "check": "tsc --noEmit", - "test": "vitest run", - "test:unit": "vitest run", - "storybook": "storybook dev -p 6006 --host 0.0.0.0", - "build-storybook": "storybook build" - }, - "dependencies": { - "@fontsource-variable/geist": "^5.2.9", - "@iconify/react": "^6.0.2", - "class-variance-authority": "^0.7.1", - "clsx": "^2.1.1", - "lucide-react": "^1.21.0", - "radix-ui": "^1.6.0", - "tailwind-merge": "^3.6.0", - "tw-animate-css": "^1.4.0", - "uplot": "^1.6.32" - }, - "peerDependencies": { - "react": "^19.0.0", - "react-dom": "^19.0.0" - }, - "devDependencies": { - "@storybook/addon-a11y": "^10.4.6", - "@storybook/addon-vitest": "^10.4.6", - "@storybook/react-vite": "^10.4.6", - "@types/bun": "^1.3.14", - "@types/node": "^25.9.3", - "@types/react": "^19.2.17", - "@types/react-dom": "^19.2.3", - "bun-types": "^1.3.14", - "storybook": "^10.4.6", - "typescript": "^6.0.3", - "vite": "^8.0.16", - "vitest": "^4.1.9" - } -} diff --git a/packages/ui/src/content-boundary.test.ts b/packages/ui/src/content-boundary.test.ts deleted file mode 100644 index 80b85ce..0000000 --- a/packages/ui/src/content-boundary.test.ts +++ /dev/null @@ -1,74 +0,0 @@ -import { existsSync, readdirSync, readFileSync, statSync } from "node:fs"; -import { join } from "node:path"; -import { describe, expect, test } from "vitest"; - -const root = process.cwd(); -const uiSourceRoot = existsSync(join(root, "packages/ui/src")) - ? join(root, "packages/ui/src") - : join(root, "src"); - -const forbiddenTerms = [ - "dimensionlab", - "dimension lab", - "vaultwarden", - "forgejo", - "grafana", - "uptime kuma", - "prometheus", - "backrest", - "open webui", - "comfyui", - "adminer", - "cockpit", - "ollama", -]; - -describe("UI package content boundary", () => { - test("contains the reusable dashboard component inventory", () => { - expect(existsSync(join(uiSourceRoot, "index.ts"))).toBe(true); - expect(existsSync(join(uiSourceRoot, "components/DashboardFrame.tsx"))).toBe( - true, - ); - expect(existsSync(join(uiSourceRoot, "components/ThemeToggle.tsx"))).toBe( - true, - ); - expect(existsSync(join(uiSourceRoot, "styles.css"))).toBe(true); - }); - - test("keeps environment-specific content out of reusable UI source", () => { - const source = readUiSource(uiSourceRoot).toLowerCase(); - - expect(forbiddenTerms.filter((term) => source.includes(term))).toEqual([]); - }); - - test("does not import website runtime modules", () => { - const source = readUiSource(uiSourceRoot); - - expect(source).not.toMatch( - /from ["'](?:apps\/web|\$lib\/server|\$lib\/model)/, - ); - expect(source).not.toContain("../web/"); - }); - - test("keeps icon rendering driven by icon identifiers", () => { - const source = readUiSource(uiSourceRoot); - - expect(source).not.toContain("@iconify-json/"); - expect(source).not.toContain("/icons/"); - }); -}); - -function readUiSource(path: string): string { - if (!existsSync(path)) return ""; - - const stats = statSync(path); - if (stats.isFile()) { - if (path.endsWith(".test.ts") || path.endsWith(".test.tsx")) return ""; - if (!/\.(tsx|ts|css)$/.test(path)) return ""; - return readFileSync(path, "utf8"); - } - - return readdirSync(path) - .map((entry) => readUiSource(join(path, entry))) - .join("\n"); -} diff --git a/packages/ui/src/css.d.ts b/packages/ui/src/css.d.ts deleted file mode 100644 index cbe652d..0000000 --- a/packages/ui/src/css.d.ts +++ /dev/null @@ -1 +0,0 @@ -declare module "*.css"; diff --git a/packages/ui/src/styles.css b/packages/ui/src/styles.css deleted file mode 100644 index fd6f4a2..0000000 --- a/packages/ui/src/styles.css +++ /dev/null @@ -1,4 +0,0 @@ -@import "@fontsource-variable/geist"; -@import "uplot/dist/uPlot.min.css"; -@import "./tokens.css"; -@import "./components/styles.css"; diff --git a/packages/ui/tsconfig.build.json b/packages/ui/tsconfig.build.json deleted file mode 100644 index bd56366..0000000 --- a/packages/ui/tsconfig.build.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "extends": "./tsconfig.json", - "compilerOptions": { - "declaration": true, - "emitDeclarationOnly": false, - "noEmit": false, - "outDir": "dist", - "rootDir": "src" - }, - "include": ["src/**/*.ts", "src/**/*.tsx"], - "exclude": [ - "dist", - "node_modules", - "storybook-static", - "src/**/*.test.ts", - "src/**/*.test.tsx", - "src/stories/**" - ] -} diff --git a/packages/ui/tsconfig.json b/packages/ui/tsconfig.json deleted file mode 100644 index 2ad97bc..0000000 --- a/packages/ui/tsconfig.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "extends": "../../tsconfig.base.json", - "compilerOptions": { - "baseUrl": "." - }, - "include": ["src/**/*.ts", "src/**/*.tsx", ".storybook/**/*.ts"], - "exclude": ["dist", "node_modules", "storybook-static"] -} diff --git a/apps/web/playwright.config.ts b/playwright.config.ts similarity index 90% rename from apps/web/playwright.config.ts rename to playwright.config.ts index afba557..3593452 100644 --- a/apps/web/playwright.config.ts +++ b/playwright.config.ts @@ -27,7 +27,7 @@ export default defineConfig({ timeout: 120_000, }, { - command: `cd ../.. && bun run build-storybook && STORYBOOK_STATIC_PORT=${storybookPort} bun apps/web/tests/e2e/storybook-server.ts`, + command: `bun run build-storybook && STORYBOOK_STATIC_PORT=${storybookPort} bun tests/e2e/storybook-server.ts`, url: storybookURL, reuseExistingServer: false, timeout: 120_000, diff --git a/apps/web/src/App.test.tsx b/src/App.test.tsx similarity index 100% rename from apps/web/src/App.test.tsx rename to src/App.test.tsx diff --git a/apps/web/src/App.tsx b/src/App.tsx similarity index 97% rename from apps/web/src/App.tsx rename to src/App.tsx index 0099173..99cdc5e 100644 --- a/apps/web/src/App.tsx +++ b/src/App.tsx @@ -1,15 +1,15 @@ import { useEffect, useState } from "react"; import type { DashboardRuntimeState } from "$lib/server/dashboard"; -import { dashboardDocumentToUiDashboard } from "$lib/ui-adapter/model-renderer"; import { DashboardFrame, SystemState, ThemeToggle, + dashboardDocumentToUiDashboard, persistUiTheme, resolveInitialUiTheme, type UiTheme, type UiSeverity, -} from "@dimensionlab/ui"; +} from "$lib/ui"; const loadingDashboardState: DashboardRuntimeState = { state: "loading", diff --git a/apps/web/src/app.css b/src/app.css similarity index 97% rename from apps/web/src/app.css rename to src/app.css index eeaabcb..0345394 100644 --- a/apps/web/src/app.css +++ b/src/app.css @@ -1,7 +1,9 @@ @import "tailwindcss"; -@import "@dimensionlab/ui/styles.css"; +@import "./lib/ui/tokens.css"; +@import "./lib/ui/components/styles.css"; @import "tw-animate-css"; @import "shadcn/tailwind.css"; +@import "@fontsource-variable/geist"; @custom-variant dark (&:is(.dark *)); diff --git a/packages/ui/src/primitives/alert.tsx b/src/lib/components/ui/alert.tsx similarity index 98% rename from packages/ui/src/primitives/alert.tsx rename to src/lib/components/ui/alert.tsx index d5d1609..fc34841 100644 --- a/packages/ui/src/primitives/alert.tsx +++ b/src/lib/components/ui/alert.tsx @@ -1,7 +1,7 @@ import * as React from "react" import { cva, type VariantProps } from "class-variance-authority" -import { cn } from "../utils" +import { cn } from "$lib/utils" const alertVariants = cva( "group/alert relative grid w-full gap-0.5 rounded-lg border px-2.5 py-2 text-left text-sm has-data-[slot=alert-action]:relative has-data-[slot=alert-action]:pr-18 has-[>svg]:grid-cols-[auto_1fr] has-[>svg]:gap-x-2 *:[svg]:row-span-2 *:[svg]:translate-y-0.5 *:[svg]:text-current *:[svg:not([class*='size-'])]:size-4", diff --git a/packages/ui/src/primitives/badge.tsx b/src/lib/components/ui/badge.tsx similarity index 98% rename from packages/ui/src/primitives/badge.tsx rename to src/lib/components/ui/badge.tsx index baa1535..a3d91d7 100644 --- a/packages/ui/src/primitives/badge.tsx +++ b/src/lib/components/ui/badge.tsx @@ -2,7 +2,7 @@ import * as React from "react" import { cva, type VariantProps } from "class-variance-authority" import { Slot } from "radix-ui" -import { cn } from "../utils" +import { cn } from "$lib/utils" const badgeVariants = cva( "group/badge inline-flex h-5 w-fit shrink-0 items-center justify-center gap-1 overflow-hidden rounded-4xl border border-transparent px-2 py-0.5 text-xs font-medium whitespace-nowrap transition-all focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&>svg]:pointer-events-none [&>svg]:size-3!", diff --git a/packages/ui/src/primitives/button.tsx b/src/lib/components/ui/button.tsx similarity index 99% rename from packages/ui/src/primitives/button.tsx rename to src/lib/components/ui/button.tsx index e37f9b0..8dda5f2 100644 --- a/packages/ui/src/primitives/button.tsx +++ b/src/lib/components/ui/button.tsx @@ -2,7 +2,7 @@ import * as React from "react" import { cva, type VariantProps } from "class-variance-authority" import { Slot } from "radix-ui" -import { cn } from "../utils" +import { cn } from "$lib/utils" const buttonVariants = cva( "group/button inline-flex shrink-0 items-center justify-center rounded-lg border border-transparent bg-clip-padding text-sm font-medium whitespace-nowrap transition-all outline-none select-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 active:not-aria-[haspopup]:translate-y-px disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", diff --git a/packages/ui/src/primitives/card.tsx b/src/lib/components/ui/card.tsx similarity index 98% rename from packages/ui/src/primitives/card.tsx rename to src/lib/components/ui/card.tsx index e5e5996..bcb9e07 100644 --- a/packages/ui/src/primitives/card.tsx +++ b/src/lib/components/ui/card.tsx @@ -1,6 +1,6 @@ import * as React from "react" -import { cn } from "../utils" +import { cn } from "$lib/utils" function Card({ className, diff --git a/packages/ui/src/primitives/progress.tsx b/src/lib/components/ui/progress.tsx similarity index 95% rename from packages/ui/src/primitives/progress.tsx rename to src/lib/components/ui/progress.tsx index 59fac6c..65d0a6b 100644 --- a/packages/ui/src/primitives/progress.tsx +++ b/src/lib/components/ui/progress.tsx @@ -1,7 +1,7 @@ import * as React from "react" import { Progress as ProgressPrimitive } from "radix-ui" -import { cn } from "../utils" +import { cn } from "$lib/utils" function Progress({ className, diff --git a/packages/ui/src/primitives/separator.tsx b/src/lib/components/ui/separator.tsx similarity index 95% rename from packages/ui/src/primitives/separator.tsx rename to src/lib/components/ui/separator.tsx index ee9f6cb..84e3c64 100644 --- a/packages/ui/src/primitives/separator.tsx +++ b/src/lib/components/ui/separator.tsx @@ -3,7 +3,7 @@ import * as React from "react" import { Separator as SeparatorPrimitive } from "radix-ui" -import { cn } from "../utils" +import { cn } from "$lib/utils" function Separator({ className, diff --git a/packages/ui/src/primitives/skeleton.tsx b/src/lib/components/ui/skeleton.tsx similarity index 88% rename from packages/ui/src/primitives/skeleton.tsx rename to src/lib/components/ui/skeleton.tsx index a1df193..61466a8 100644 --- a/packages/ui/src/primitives/skeleton.tsx +++ b/src/lib/components/ui/skeleton.tsx @@ -1,4 +1,4 @@ -import { cn } from "../utils" +import { cn } from "$lib/utils" function Skeleton({ className, ...props }: React.ComponentProps<"div">) { return ( diff --git a/apps/web/src/lib/model/fixtures/dimensionlab.test.ts b/src/lib/model/fixtures/dimensionlab.test.ts similarity index 100% rename from apps/web/src/lib/model/fixtures/dimensionlab.test.ts rename to src/lib/model/fixtures/dimensionlab.test.ts diff --git a/apps/web/src/lib/model/fixtures/dimensionlab.ts b/src/lib/model/fixtures/dimensionlab.ts similarity index 100% rename from apps/web/src/lib/model/fixtures/dimensionlab.ts rename to src/lib/model/fixtures/dimensionlab.ts diff --git a/apps/web/src/lib/model/fixtures/generic.ts b/src/lib/model/fixtures/generic.ts similarity index 100% rename from apps/web/src/lib/model/fixtures/generic.ts rename to src/lib/model/fixtures/generic.ts diff --git a/apps/web/src/lib/model/fixtures/index.ts b/src/lib/model/fixtures/index.ts similarity index 100% rename from apps/web/src/lib/model/fixtures/index.ts rename to src/lib/model/fixtures/index.ts diff --git a/apps/web/src/lib/model/index.ts b/src/lib/model/index.ts similarity index 100% rename from apps/web/src/lib/model/index.ts rename to src/lib/model/index.ts diff --git a/apps/web/src/lib/model/schema.test.ts b/src/lib/model/schema.test.ts similarity index 100% rename from apps/web/src/lib/model/schema.test.ts rename to src/lib/model/schema.test.ts diff --git a/apps/web/src/lib/model/schema.ts b/src/lib/model/schema.ts similarity index 100% rename from apps/web/src/lib/model/schema.ts rename to src/lib/model/schema.ts diff --git a/apps/web/src/lib/model/validation.ts b/src/lib/model/validation.ts similarity index 100% rename from apps/web/src/lib/model/validation.ts rename to src/lib/model/validation.ts diff --git a/apps/web/src/lib/presentation-boundary.test.ts b/src/lib/presentation-boundary.test.ts similarity index 64% rename from apps/web/src/lib/presentation-boundary.test.ts rename to src/lib/presentation-boundary.test.ts index 7daf204..8e29ece 100644 --- a/apps/web/src/lib/presentation-boundary.test.ts +++ b/src/lib/presentation-boundary.test.ts @@ -2,17 +2,9 @@ import { existsSync, readdirSync, readFileSync, statSync } from "node:fs"; import { join } from "node:path"; import { describe, expect, test } from "vitest"; -const appRoot = process.cwd().endsWith(`${join("apps", "web")}`) - ? process.cwd() - : join(process.cwd(), "apps", "web"); -const repoRoot = existsSync(join(process.cwd(), "turbo.json")) - ? process.cwd() - : join(appRoot, "..", ".."); const presentationRoots = [ - join(repoRoot, "packages", "ui", "src"), - join(appRoot, "src", "App.tsx"), - join(appRoot, "src", "app.css"), - join(appRoot, "src", "lib", "ui-adapter"), + join(process.cwd(), "src", "lib", "ui"), + join(process.cwd(), "src", "routes"), ]; const forbiddenTerms = [ @@ -34,9 +26,7 @@ const forbiddenTerms = [ describe("presentation content boundary", () => { test("keeps environment-specific content out of route and UI implementation", () => { - const source = withoutInternalPackageScope( - presentationRoots.map(readPresentationSource).join("\n").toLowerCase(), - ); + const source = presentationRoots.map(readPresentationSource).join("\n").toLowerCase(); expect(forbiddenTerms.filter((term) => source.includes(term))).toEqual([]); }); @@ -44,7 +34,7 @@ describe("presentation content boundary", () => { test("does not keep legacy presentation component files in the React runtime", () => { const legacyExtension = [".sve", "lte"].join(""); - expect(findFiles(join(appRoot, "src"), legacyExtension)).toEqual([]); + expect(findFiles(join(process.cwd(), "src"), legacyExtension)).toEqual([]); }); }); @@ -54,9 +44,7 @@ function readPresentationSource(path: string): string { const stats = statSync(path); if (stats.isFile()) { if (path.endsWith(".test.ts")) return ""; - if (path.includes(`${join("packages", "ui", "src", "stories")}${"/"}`)) { - return ""; - } + if (path.includes(`${join("src", "lib", "ui", "stories")}${"/"}`)) return ""; if (!/\.(tsx|ts|js|mjs|css|json)$/.test(path)) return ""; return readFileSync(path, "utf8"); } @@ -72,7 +60,3 @@ function findFiles(path: string, extension: string): string[] { return readdirSync(path).flatMap((entry) => findFiles(join(path, entry), extension)); } - -function withoutInternalPackageScope(source: string): string { - return source.replaceAll("@dimensionlab/ui", "@internal/ui"); -} diff --git a/apps/web/src/lib/server/agent-config/agent-config.test.ts b/src/lib/server/agent-config/agent-config.test.ts similarity index 100% rename from apps/web/src/lib/server/agent-config/agent-config.test.ts rename to src/lib/server/agent-config/agent-config.test.ts diff --git a/apps/web/src/lib/server/agent-config/index.ts b/src/lib/server/agent-config/index.ts similarity index 100% rename from apps/web/src/lib/server/agent-config/index.ts rename to src/lib/server/agent-config/index.ts diff --git a/apps/web/src/lib/server/dashboard.test.ts b/src/lib/server/dashboard.test.ts similarity index 100% rename from apps/web/src/lib/server/dashboard.test.ts rename to src/lib/server/dashboard.test.ts diff --git a/apps/web/src/lib/server/dashboard.ts b/src/lib/server/dashboard.ts similarity index 100% rename from apps/web/src/lib/server/dashboard.ts rename to src/lib/server/dashboard.ts diff --git a/apps/web/src/lib/server/datasources/dashboard-datasources.test.ts b/src/lib/server/datasources/dashboard-datasources.test.ts similarity index 100% rename from apps/web/src/lib/server/datasources/dashboard-datasources.test.ts rename to src/lib/server/datasources/dashboard-datasources.test.ts diff --git a/apps/web/src/lib/server/datasources/index.ts b/src/lib/server/datasources/index.ts similarity index 100% rename from apps/web/src/lib/server/datasources/index.ts rename to src/lib/server/datasources/index.ts diff --git a/apps/web/src/lib/server/db/connection.ts b/src/lib/server/db/connection.ts similarity index 100% rename from apps/web/src/lib/server/db/connection.ts rename to src/lib/server/db/connection.ts diff --git a/apps/web/src/lib/server/db/dashboard-store.test.ts b/src/lib/server/db/dashboard-store.test.ts similarity index 100% rename from apps/web/src/lib/server/db/dashboard-store.test.ts rename to src/lib/server/db/dashboard-store.test.ts diff --git a/apps/web/src/lib/server/db/dashboard-store.ts b/src/lib/server/db/dashboard-store.ts similarity index 100% rename from apps/web/src/lib/server/db/dashboard-store.ts rename to src/lib/server/db/dashboard-store.ts diff --git a/apps/web/src/lib/server/db/migrations.ts b/src/lib/server/db/migrations.ts similarity index 100% rename from apps/web/src/lib/server/db/migrations.ts rename to src/lib/server/db/migrations.ts diff --git a/apps/web/src/lib/server/db/model-migrations.test.ts b/src/lib/server/db/model-migrations.test.ts similarity index 100% rename from apps/web/src/lib/server/db/model-migrations.test.ts rename to src/lib/server/db/model-migrations.test.ts diff --git a/apps/web/src/lib/server/db/model-migrations.ts b/src/lib/server/db/model-migrations.ts similarity index 100% rename from apps/web/src/lib/server/db/model-migrations.ts rename to src/lib/server/db/model-migrations.ts diff --git a/apps/web/src/lib/server/db/schema.ts b/src/lib/server/db/schema.ts similarity index 100% rename from apps/web/src/lib/server/db/schema.ts rename to src/lib/server/db/schema.ts diff --git a/apps/web/src/lib/testing/external-api-mocks.test.ts b/src/lib/testing/external-api-mocks.test.ts similarity index 100% rename from apps/web/src/lib/testing/external-api-mocks.test.ts rename to src/lib/testing/external-api-mocks.test.ts diff --git a/apps/web/src/lib/testing/external-api-mocks.ts b/src/lib/testing/external-api-mocks.ts similarity index 100% rename from apps/web/src/lib/testing/external-api-mocks.ts rename to src/lib/testing/external-api-mocks.ts diff --git a/packages/ui/src/components/Badge.tsx b/src/lib/ui/components/Badge.tsx similarity index 100% rename from packages/ui/src/components/Badge.tsx rename to src/lib/ui/components/Badge.tsx diff --git a/packages/ui/src/components/Button.tsx b/src/lib/ui/components/Button.tsx similarity index 100% rename from packages/ui/src/components/Button.tsx rename to src/lib/ui/components/Button.tsx diff --git a/packages/ui/src/components/CornerBracketFrame.tsx b/src/lib/ui/components/CornerBracketFrame.tsx similarity index 100% rename from packages/ui/src/components/CornerBracketFrame.tsx rename to src/lib/ui/components/CornerBracketFrame.tsx diff --git a/packages/ui/src/components/DashboardFrame.tsx b/src/lib/ui/components/DashboardFrame.tsx similarity index 100% rename from packages/ui/src/components/DashboardFrame.tsx rename to src/lib/ui/components/DashboardFrame.tsx diff --git a/packages/ui/src/components/DashboardHeader.tsx b/src/lib/ui/components/DashboardHeader.tsx similarity index 100% rename from packages/ui/src/components/DashboardHeader.tsx rename to src/lib/ui/components/DashboardHeader.tsx diff --git a/packages/ui/src/components/DiagonalStripeField.tsx b/src/lib/ui/components/DiagonalStripeField.tsx similarity index 100% rename from packages/ui/src/components/DiagonalStripeField.tsx rename to src/lib/ui/components/DiagonalStripeField.tsx diff --git a/packages/ui/src/components/FooterCell.tsx b/src/lib/ui/components/FooterCell.tsx similarity index 100% rename from packages/ui/src/components/FooterCell.tsx rename to src/lib/ui/components/FooterCell.tsx diff --git a/packages/ui/src/components/FooterStatusCell.tsx b/src/lib/ui/components/FooterStatusCell.tsx similarity index 100% rename from packages/ui/src/components/FooterStatusCell.tsx rename to src/lib/ui/components/FooterStatusCell.tsx diff --git a/packages/ui/src/components/GridFrame.tsx b/src/lib/ui/components/GridFrame.tsx similarity index 100% rename from packages/ui/src/components/GridFrame.tsx rename to src/lib/ui/components/GridFrame.tsx diff --git a/packages/ui/src/components/IconButton.tsx b/src/lib/ui/components/IconButton.tsx similarity index 100% rename from packages/ui/src/components/IconButton.tsx rename to src/lib/ui/components/IconButton.tsx diff --git a/packages/ui/src/components/IconGlyph.tsx b/src/lib/ui/components/IconGlyph.tsx similarity index 100% rename from packages/ui/src/components/IconGlyph.tsx rename to src/lib/ui/components/IconGlyph.tsx diff --git a/packages/ui/src/components/LineChart.tsx b/src/lib/ui/components/LineChart.tsx similarity index 100% rename from packages/ui/src/components/LineChart.tsx rename to src/lib/ui/components/LineChart.tsx diff --git a/packages/ui/src/components/ModuleCard.tsx b/src/lib/ui/components/ModuleCard.tsx similarity index 100% rename from packages/ui/src/components/ModuleCard.tsx rename to src/lib/ui/components/ModuleCard.tsx diff --git a/packages/ui/src/components/Panel.tsx b/src/lib/ui/components/Panel.tsx similarity index 100% rename from packages/ui/src/components/Panel.tsx rename to src/lib/ui/components/Panel.tsx diff --git a/packages/ui/src/components/ProgressMeter.tsx b/src/lib/ui/components/ProgressMeter.tsx similarity index 100% rename from packages/ui/src/components/ProgressMeter.tsx rename to src/lib/ui/components/ProgressMeter.tsx diff --git a/packages/ui/src/components/ScanlineField.tsx b/src/lib/ui/components/ScanlineField.tsx similarity index 100% rename from packages/ui/src/components/ScanlineField.tsx rename to src/lib/ui/components/ScanlineField.tsx diff --git a/packages/ui/src/components/Separator.tsx b/src/lib/ui/components/Separator.tsx similarity index 100% rename from packages/ui/src/components/Separator.tsx rename to src/lib/ui/components/Separator.tsx diff --git a/packages/ui/src/components/ServiceGroupPanel.tsx b/src/lib/ui/components/ServiceGroupPanel.tsx similarity index 100% rename from packages/ui/src/components/ServiceGroupPanel.tsx rename to src/lib/ui/components/ServiceGroupPanel.tsx diff --git a/packages/ui/src/components/ServicePanel.tsx b/src/lib/ui/components/ServicePanel.tsx similarity index 100% rename from packages/ui/src/components/ServicePanel.tsx rename to src/lib/ui/components/ServicePanel.tsx diff --git a/packages/ui/src/components/ServiceRow.tsx b/src/lib/ui/components/ServiceRow.tsx similarity index 100% rename from packages/ui/src/components/ServiceRow.tsx rename to src/lib/ui/components/ServiceRow.tsx diff --git a/packages/ui/src/components/SignalTrace.tsx b/src/lib/ui/components/SignalTrace.tsx similarity index 100% rename from packages/ui/src/components/SignalTrace.tsx rename to src/lib/ui/components/SignalTrace.tsx diff --git a/packages/ui/src/components/Sparkline.tsx b/src/lib/ui/components/Sparkline.tsx similarity index 100% rename from packages/ui/src/components/Sparkline.tsx rename to src/lib/ui/components/Sparkline.tsx diff --git a/packages/ui/src/components/StatusBadge.tsx b/src/lib/ui/components/StatusBadge.tsx similarity index 100% rename from packages/ui/src/components/StatusBadge.tsx rename to src/lib/ui/components/StatusBadge.tsx diff --git a/packages/ui/src/components/StatusStrip.tsx b/src/lib/ui/components/StatusStrip.tsx similarity index 100% rename from packages/ui/src/components/StatusStrip.tsx rename to src/lib/ui/components/StatusStrip.tsx diff --git a/packages/ui/src/components/SystemState.tsx b/src/lib/ui/components/SystemState.tsx similarity index 100% rename from packages/ui/src/components/SystemState.tsx rename to src/lib/ui/components/SystemState.tsx diff --git a/packages/ui/src/components/TelemetryCard.tsx b/src/lib/ui/components/TelemetryCard.tsx similarity index 100% rename from packages/ui/src/components/TelemetryCard.tsx rename to src/lib/ui/components/TelemetryCard.tsx diff --git a/packages/ui/src/components/TelemetryGrid.tsx b/src/lib/ui/components/TelemetryGrid.tsx similarity index 100% rename from packages/ui/src/components/TelemetryGrid.tsx rename to src/lib/ui/components/TelemetryGrid.tsx diff --git a/packages/ui/src/components/TelemetryStrip.tsx b/src/lib/ui/components/TelemetryStrip.tsx similarity index 100% rename from packages/ui/src/components/TelemetryStrip.tsx rename to src/lib/ui/components/TelemetryStrip.tsx diff --git a/packages/ui/src/components/ThemeToggle.tsx b/src/lib/ui/components/ThemeToggle.tsx similarity index 100% rename from packages/ui/src/components/ThemeToggle.tsx rename to src/lib/ui/components/ThemeToggle.tsx diff --git a/packages/ui/src/components/WeatherModule.tsx b/src/lib/ui/components/WeatherModule.tsx similarity index 100% rename from packages/ui/src/components/WeatherModule.tsx rename to src/lib/ui/components/WeatherModule.tsx diff --git a/packages/ui/src/components/render.test.tsx b/src/lib/ui/components/render.test.tsx similarity index 100% rename from packages/ui/src/components/render.test.tsx rename to src/lib/ui/components/render.test.tsx diff --git a/packages/ui/src/components/styles.css b/src/lib/ui/components/styles.css similarity index 100% rename from packages/ui/src/components/styles.css rename to src/lib/ui/components/styles.css diff --git a/src/lib/ui/content-boundary.test.ts b/src/lib/ui/content-boundary.test.ts new file mode 100644 index 0000000..6613644 --- /dev/null +++ b/src/lib/ui/content-boundary.test.ts @@ -0,0 +1,49 @@ +import { readdirSync, readFileSync, statSync } from "node:fs"; +import { join } from "node:path"; +import { describe, expect, test } from "vitest"; + +const forbiddenTerms = [ + "dimensionlab", + "dimension lab", + "vaultwarden", + "forgejo", + "grafana", + "uptime kuma", + "prometheus", + "backrest", + "open webui", + "comfyui", + "adminer", + "cockpit", + "ollama", +]; + +describe("UI content boundary", () => { + test("keeps environment-specific content out of reusable UI source", () => { + const source = readUiSource(join(process.cwd(), "src", "lib", "ui")); + const normalized = source.toLowerCase(); + + expect( + forbiddenTerms.filter((term) => normalized.includes(term)), + ).toEqual([]); + }); + + test("keeps icon rendering driven by icon identifiers", () => { + const source = readUiSource(join(process.cwd(), "src", "lib", "ui")); + + expect(source).not.toContain("@iconify-json/"); + expect(source).not.toContain("/icons/"); + }); +}); + +function readUiSource(path: string): string { + const stats = statSync(path); + if (stats.isFile()) { + if (path.endsWith(".test.ts")) return ""; + return readFileSync(path, "utf8"); + } + + return readdirSync(path) + .map((entry) => readUiSource(join(path, entry))) + .join("\n"); +} diff --git a/packages/ui/src/fixtures.ts b/src/lib/ui/fixtures.ts similarity index 100% rename from packages/ui/src/fixtures.ts rename to src/lib/ui/fixtures.ts diff --git a/packages/ui/src/format.ts b/src/lib/ui/format.ts similarity index 100% rename from packages/ui/src/format.ts rename to src/lib/ui/format.ts diff --git a/packages/ui/src/index.ts b/src/lib/ui/index.ts similarity index 96% rename from packages/ui/src/index.ts rename to src/lib/ui/index.ts index a9a83df..9eb5448 100644 --- a/packages/ui/src/index.ts +++ b/src/lib/ui/index.ts @@ -29,6 +29,7 @@ export { TelemetryStrip } from "./components/TelemetryStrip"; export { ThemeToggle } from "./components/ThemeToggle"; export { WeatherModule } from "./components/WeatherModule"; export { dashboardPreviewFixtures } from "./fixtures"; +export { dashboardDocumentToUiDashboard } from "./model-renderer"; export { getNextUiTheme, isUiTheme, diff --git a/apps/web/src/lib/ui-adapter/model-renderer.test.ts b/src/lib/ui/model-renderer.test.ts similarity index 89% rename from apps/web/src/lib/ui-adapter/model-renderer.test.ts rename to src/lib/ui/model-renderer.test.ts index fb04ec4..62942ee 100644 --- a/apps/web/src/lib/ui-adapter/model-renderer.test.ts +++ b/src/lib/ui/model-renderer.test.ts @@ -1,15 +1,13 @@ import { readFileSync } from "node:fs"; import { join } from "node:path"; import { describe, expect, test } from "vitest"; -import { type DashboardDocument } from "$lib/model"; +import { + type DashboardDocument, +} from "$lib/model"; import { dimensionLabDashboardFixture } from "$lib/model/fixtures/dimensionlab"; import { genericDashboardFixture } from "$lib/model/fixtures/generic"; import { dashboardDocumentToUiDashboard } from "./model-renderer"; -const appRoot = process.cwd().endsWith(`${join("apps", "web")}`) - ? process.cwd() - : join(process.cwd(), "apps", "web"); - describe("dashboard model renderer", () => { test("projects the Dimension Lab model into UI component props", () => { const dashboard = dashboardDocumentToUiDashboard(dimensionLabDashboardFixture); @@ -88,12 +86,7 @@ describe("dashboard model renderer", () => { }); test("does not hardcode environment-specific content in mapper source", () => { - const source = readFileSync( - join(appRoot, "src/lib/ui-adapter/model-renderer.ts"), - "utf8", - ) - .toLowerCase() - .replaceAll("@dimensionlab/ui", "@internal/ui"); + const source = readFileSync(join(process.cwd(), "src/lib/ui/model-renderer.ts"), "utf8").toLowerCase(); expect(source).not.toContain("dimension"); expect(source).not.toContain("vaultwarden"); diff --git a/apps/web/src/lib/ui-adapter/model-renderer.ts b/src/lib/ui/model-renderer.ts similarity index 98% rename from apps/web/src/lib/ui-adapter/model-renderer.ts rename to src/lib/ui/model-renderer.ts index 1db2173..d5f3647 100644 --- a/apps/web/src/lib/ui-adapter/model-renderer.ts +++ b/src/lib/ui/model-renderer.ts @@ -14,7 +14,7 @@ import type { UiServiceRow, UiStatusItem, UiTelemetryCard, -} from "@dimensionlab/ui"; +} from "./types"; export function dashboardDocumentToUiDashboard( document: DashboardDocument, diff --git a/packages/ui/src/stories/Badge.stories.tsx b/src/lib/ui/stories/Badge.stories.tsx similarity index 100% rename from packages/ui/src/stories/Badge.stories.tsx rename to src/lib/ui/stories/Badge.stories.tsx diff --git a/packages/ui/src/stories/Button.stories.tsx b/src/lib/ui/stories/Button.stories.tsx similarity index 100% rename from packages/ui/src/stories/Button.stories.tsx rename to src/lib/ui/stories/Button.stories.tsx diff --git a/packages/ui/src/stories/CornerBracketFrame.stories.tsx b/src/lib/ui/stories/CornerBracketFrame.stories.tsx similarity index 100% rename from packages/ui/src/stories/CornerBracketFrame.stories.tsx rename to src/lib/ui/stories/CornerBracketFrame.stories.tsx diff --git a/packages/ui/src/stories/DashboardFrame.stories.tsx b/src/lib/ui/stories/DashboardFrame.stories.tsx similarity index 100% rename from packages/ui/src/stories/DashboardFrame.stories.tsx rename to src/lib/ui/stories/DashboardFrame.stories.tsx diff --git a/packages/ui/src/stories/DashboardHeader.stories.tsx b/src/lib/ui/stories/DashboardHeader.stories.tsx similarity index 100% rename from packages/ui/src/stories/DashboardHeader.stories.tsx rename to src/lib/ui/stories/DashboardHeader.stories.tsx diff --git a/packages/ui/src/stories/DashboardOnePager.stories.tsx b/src/lib/ui/stories/DashboardOnePager.stories.tsx similarity index 100% rename from packages/ui/src/stories/DashboardOnePager.stories.tsx rename to src/lib/ui/stories/DashboardOnePager.stories.tsx diff --git a/packages/ui/src/stories/DiagonalStripeField.stories.tsx b/src/lib/ui/stories/DiagonalStripeField.stories.tsx similarity index 100% rename from packages/ui/src/stories/DiagonalStripeField.stories.tsx rename to src/lib/ui/stories/DiagonalStripeField.stories.tsx diff --git a/packages/ui/src/stories/FooterCell.stories.tsx b/src/lib/ui/stories/FooterCell.stories.tsx similarity index 100% rename from packages/ui/src/stories/FooterCell.stories.tsx rename to src/lib/ui/stories/FooterCell.stories.tsx diff --git a/packages/ui/src/stories/FooterStatusCell.stories.tsx b/src/lib/ui/stories/FooterStatusCell.stories.tsx similarity index 100% rename from packages/ui/src/stories/FooterStatusCell.stories.tsx rename to src/lib/ui/stories/FooterStatusCell.stories.tsx diff --git a/packages/ui/src/stories/GridFrame.stories.tsx b/src/lib/ui/stories/GridFrame.stories.tsx similarity index 100% rename from packages/ui/src/stories/GridFrame.stories.tsx rename to src/lib/ui/stories/GridFrame.stories.tsx diff --git a/packages/ui/src/stories/IconButton.stories.tsx b/src/lib/ui/stories/IconButton.stories.tsx similarity index 100% rename from packages/ui/src/stories/IconButton.stories.tsx rename to src/lib/ui/stories/IconButton.stories.tsx diff --git a/packages/ui/src/stories/IconGlyph.stories.tsx b/src/lib/ui/stories/IconGlyph.stories.tsx similarity index 100% rename from packages/ui/src/stories/IconGlyph.stories.tsx rename to src/lib/ui/stories/IconGlyph.stories.tsx diff --git a/packages/ui/src/stories/LineChart.stories.tsx b/src/lib/ui/stories/LineChart.stories.tsx similarity index 100% rename from packages/ui/src/stories/LineChart.stories.tsx rename to src/lib/ui/stories/LineChart.stories.tsx diff --git a/packages/ui/src/stories/ModuleCard.stories.tsx b/src/lib/ui/stories/ModuleCard.stories.tsx similarity index 100% rename from packages/ui/src/stories/ModuleCard.stories.tsx rename to src/lib/ui/stories/ModuleCard.stories.tsx diff --git a/packages/ui/src/stories/Panel.stories.tsx b/src/lib/ui/stories/Panel.stories.tsx similarity index 100% rename from packages/ui/src/stories/Panel.stories.tsx rename to src/lib/ui/stories/Panel.stories.tsx diff --git a/packages/ui/src/stories/ProgressMeter.stories.tsx b/src/lib/ui/stories/ProgressMeter.stories.tsx similarity index 100% rename from packages/ui/src/stories/ProgressMeter.stories.tsx rename to src/lib/ui/stories/ProgressMeter.stories.tsx diff --git a/packages/ui/src/stories/ScanlineField.stories.tsx b/src/lib/ui/stories/ScanlineField.stories.tsx similarity index 100% rename from packages/ui/src/stories/ScanlineField.stories.tsx rename to src/lib/ui/stories/ScanlineField.stories.tsx diff --git a/packages/ui/src/stories/Separator.stories.tsx b/src/lib/ui/stories/Separator.stories.tsx similarity index 100% rename from packages/ui/src/stories/Separator.stories.tsx rename to src/lib/ui/stories/Separator.stories.tsx diff --git a/packages/ui/src/stories/ServiceGroupPanel.stories.tsx b/src/lib/ui/stories/ServiceGroupPanel.stories.tsx similarity index 100% rename from packages/ui/src/stories/ServiceGroupPanel.stories.tsx rename to src/lib/ui/stories/ServiceGroupPanel.stories.tsx diff --git a/packages/ui/src/stories/ServicePanel.stories.tsx b/src/lib/ui/stories/ServicePanel.stories.tsx similarity index 100% rename from packages/ui/src/stories/ServicePanel.stories.tsx rename to src/lib/ui/stories/ServicePanel.stories.tsx diff --git a/packages/ui/src/stories/ServiceRow.stories.tsx b/src/lib/ui/stories/ServiceRow.stories.tsx similarity index 100% rename from packages/ui/src/stories/ServiceRow.stories.tsx rename to src/lib/ui/stories/ServiceRow.stories.tsx diff --git a/packages/ui/src/stories/SignalTrace.stories.tsx b/src/lib/ui/stories/SignalTrace.stories.tsx similarity index 100% rename from packages/ui/src/stories/SignalTrace.stories.tsx rename to src/lib/ui/stories/SignalTrace.stories.tsx diff --git a/packages/ui/src/stories/Sparkline.stories.tsx b/src/lib/ui/stories/Sparkline.stories.tsx similarity index 100% rename from packages/ui/src/stories/Sparkline.stories.tsx rename to src/lib/ui/stories/Sparkline.stories.tsx diff --git a/packages/ui/src/stories/StatusBadge.stories.tsx b/src/lib/ui/stories/StatusBadge.stories.tsx similarity index 100% rename from packages/ui/src/stories/StatusBadge.stories.tsx rename to src/lib/ui/stories/StatusBadge.stories.tsx diff --git a/packages/ui/src/stories/StatusStrip.stories.tsx b/src/lib/ui/stories/StatusStrip.stories.tsx similarity index 100% rename from packages/ui/src/stories/StatusStrip.stories.tsx rename to src/lib/ui/stories/StatusStrip.stories.tsx diff --git a/packages/ui/src/stories/SystemState.stories.tsx b/src/lib/ui/stories/SystemState.stories.tsx similarity index 100% rename from packages/ui/src/stories/SystemState.stories.tsx rename to src/lib/ui/stories/SystemState.stories.tsx diff --git a/packages/ui/src/stories/TelemetryCard.stories.tsx b/src/lib/ui/stories/TelemetryCard.stories.tsx similarity index 100% rename from packages/ui/src/stories/TelemetryCard.stories.tsx rename to src/lib/ui/stories/TelemetryCard.stories.tsx diff --git a/packages/ui/src/stories/TelemetryGrid.stories.tsx b/src/lib/ui/stories/TelemetryGrid.stories.tsx similarity index 100% rename from packages/ui/src/stories/TelemetryGrid.stories.tsx rename to src/lib/ui/stories/TelemetryGrid.stories.tsx diff --git a/packages/ui/src/stories/TelemetryStrip.stories.tsx b/src/lib/ui/stories/TelemetryStrip.stories.tsx similarity index 100% rename from packages/ui/src/stories/TelemetryStrip.stories.tsx rename to src/lib/ui/stories/TelemetryStrip.stories.tsx diff --git a/packages/ui/src/stories/ThemeToggle.stories.tsx b/src/lib/ui/stories/ThemeToggle.stories.tsx similarity index 100% rename from packages/ui/src/stories/ThemeToggle.stories.tsx rename to src/lib/ui/stories/ThemeToggle.stories.tsx diff --git a/packages/ui/src/stories/WeatherModule.stories.tsx b/src/lib/ui/stories/WeatherModule.stories.tsx similarity index 100% rename from packages/ui/src/stories/WeatherModule.stories.tsx rename to src/lib/ui/stories/WeatherModule.stories.tsx diff --git a/packages/ui/src/stories/story-data.ts b/src/lib/ui/stories/story-data.ts similarity index 100% rename from packages/ui/src/stories/story-data.ts rename to src/lib/ui/stories/story-data.ts diff --git a/packages/ui/src/storybook.test.ts b/src/lib/ui/storybook.test.ts similarity index 86% rename from packages/ui/src/storybook.test.ts rename to src/lib/ui/storybook.test.ts index 4ef14ba..aa76cad 100644 --- a/packages/ui/src/storybook.test.ts +++ b/src/lib/ui/storybook.test.ts @@ -3,11 +3,8 @@ import { join } from "node:path"; import { describe, expect, test } from "vitest"; const root = process.cwd(); -const packageRoot = existsSync(join(root, "packages/ui/package.json")) - ? join(root, "packages/ui") - : root; -const componentsDir = join(packageRoot, "src/components"); -const storiesDir = join(packageRoot, "src/stories"); +const componentsDir = join(root, "src/lib/ui/components"); +const storiesDir = join(root, "src/lib/ui/stories"); const requiredStoryFiles = [ "Badge.stories.tsx", @@ -52,7 +49,7 @@ const forbiddenStoryContent = [ describe("Storybook inventory", () => { test("exposes scripts for local and static Storybook review", () => { - const packageJson = JSON.parse(readFileSync(join(packageRoot, "package.json"), "utf8")) as { + const packageJson = JSON.parse(readFileSync(join(root, "package.json"), "utf8")) as { scripts?: Record; }; @@ -68,22 +65,21 @@ describe("Storybook inventory", () => { }); test("loads dashboard component styles through the global app stylesheet", () => { - const packageStyles = readFileSync(join(packageRoot, "src/styles.css"), "utf8"); + const appStyles = readFileSync(join(root, "src/app.css"), "utf8"); const dashboardFrame = readFileSync( join(componentsDir, "DashboardFrame.tsx"), "utf8", ); - expect(packageStyles).toContain('./components/styles.css'); + expect(appStyles).toContain('./lib/ui/components/styles.css'); expect(dashboardFrame).not.toContain('./styles.css'); }); test("configures Storybook theme switching for reusable components", () => { - const previewSource = readFileSync(join(packageRoot, ".storybook/preview.ts"), "utf8"); + const previewSource = readFileSync(join(root, ".storybook/preview.ts"), "utf8"); expect(previewSource).toContain("globalTypes"); expect(previewSource).toContain("data-ui-theme"); - expect(previewSource).toContain("../src/styles.css"); }); test("keeps component and story files paired as the UI inventory changes", () => { @@ -139,7 +135,7 @@ describe("Storybook inventory", () => { test("does not add deferred form/navigation primitives", () => { for (const component of ["Input", "ToggleGroup", "ScrollArea"]) { - expect(existsSync(join(componentsDir, `${component}.tsx`))).toBe(false); + expect(existsSync(join(root, `src/lib/ui/components/${component}.tsx`))).toBe(false); expect(existsSync(join(storiesDir, `${component}.stories.tsx`))).toBe(false); } }); diff --git a/packages/ui/src/theme.test.ts b/src/lib/ui/theme.test.ts similarity index 100% rename from packages/ui/src/theme.test.ts rename to src/lib/ui/theme.test.ts diff --git a/packages/ui/src/theme.ts b/src/lib/ui/theme.ts similarity index 100% rename from packages/ui/src/theme.ts rename to src/lib/ui/theme.ts diff --git a/packages/ui/src/tokens.css b/src/lib/ui/tokens.css similarity index 100% rename from packages/ui/src/tokens.css rename to src/lib/ui/tokens.css diff --git a/packages/ui/src/types.ts b/src/lib/ui/types.ts similarity index 100% rename from packages/ui/src/types.ts rename to src/lib/ui/types.ts diff --git a/packages/ui/src/utils.ts b/src/lib/utils.ts similarity index 100% rename from packages/ui/src/utils.ts rename to src/lib/utils.ts diff --git a/apps/web/src/main.tsx b/src/main.tsx similarity index 100% rename from apps/web/src/main.tsx rename to src/main.tsx diff --git a/apps/web/src/page.test.tsx b/src/page.test.tsx similarity index 100% rename from apps/web/src/page.test.tsx rename to src/page.test.tsx diff --git a/apps/web/src/server/dev.test.ts b/src/server/dev.test.ts similarity index 100% rename from apps/web/src/server/dev.test.ts rename to src/server/dev.test.ts diff --git a/apps/web/src/server/dev.ts b/src/server/dev.ts similarity index 100% rename from apps/web/src/server/dev.ts rename to src/server/dev.ts diff --git a/apps/web/src/server/index.ts b/src/server/index.ts similarity index 100% rename from apps/web/src/server/index.ts rename to src/server/index.ts diff --git a/apps/web/src/server/routes/agent-dashboard.test.ts b/src/server/routes/agent-dashboard.test.ts similarity index 100% rename from apps/web/src/server/routes/agent-dashboard.test.ts rename to src/server/routes/agent-dashboard.test.ts diff --git a/apps/web/src/server/routes/agent-dashboard.ts b/src/server/routes/agent-dashboard.ts similarity index 100% rename from apps/web/src/server/routes/agent-dashboard.ts rename to src/server/routes/agent-dashboard.ts diff --git a/apps/web/src/server/routes/dashboard.test.ts b/src/server/routes/dashboard.test.ts similarity index 100% rename from apps/web/src/server/routes/dashboard.test.ts rename to src/server/routes/dashboard.test.ts diff --git a/apps/web/src/server/routes/dashboard.ts b/src/server/routes/dashboard.ts similarity index 100% rename from apps/web/src/server/routes/dashboard.ts rename to src/server/routes/dashboard.ts diff --git a/apps/web/src/vite-env.d.ts b/src/vite-env.d.ts similarity index 100% rename from apps/web/src/vite-env.d.ts rename to src/vite-env.d.ts diff --git a/apps/web/static/mockServiceWorker.js b/static/mockServiceWorker.js similarity index 100% rename from apps/web/static/mockServiceWorker.js rename to static/mockServiceWorker.js diff --git a/apps/web/tests/e2e/dashboard.spec.ts b/tests/e2e/dashboard.spec.ts similarity index 100% rename from apps/web/tests/e2e/dashboard.spec.ts rename to tests/e2e/dashboard.spec.ts diff --git a/apps/web/tests/e2e/dashboard.spec.ts-snapshots/dashboard-desktop-chromium-desktop-linux.png b/tests/e2e/dashboard.spec.ts-snapshots/dashboard-desktop-chromium-desktop-linux.png similarity index 100% rename from apps/web/tests/e2e/dashboard.spec.ts-snapshots/dashboard-desktop-chromium-desktop-linux.png rename to tests/e2e/dashboard.spec.ts-snapshots/dashboard-desktop-chromium-desktop-linux.png diff --git a/apps/web/tests/e2e/dashboard.spec.ts-snapshots/dashboard-light-desktop-chromium-desktop-linux.png b/tests/e2e/dashboard.spec.ts-snapshots/dashboard-light-desktop-chromium-desktop-linux.png similarity index 100% rename from apps/web/tests/e2e/dashboard.spec.ts-snapshots/dashboard-light-desktop-chromium-desktop-linux.png rename to tests/e2e/dashboard.spec.ts-snapshots/dashboard-light-desktop-chromium-desktop-linux.png diff --git a/apps/web/tests/e2e/dashboard.spec.ts-snapshots/dashboard-mobile-chromium-mobile-linux.png b/tests/e2e/dashboard.spec.ts-snapshots/dashboard-mobile-chromium-mobile-linux.png similarity index 100% rename from apps/web/tests/e2e/dashboard.spec.ts-snapshots/dashboard-mobile-chromium-mobile-linux.png rename to tests/e2e/dashboard.spec.ts-snapshots/dashboard-mobile-chromium-mobile-linux.png diff --git a/apps/web/tests/e2e/storybook-server.ts b/tests/e2e/storybook-server.ts similarity index 82% rename from apps/web/tests/e2e/storybook-server.ts rename to tests/e2e/storybook-server.ts index 7544654..e6e3f63 100644 --- a/apps/web/tests/e2e/storybook-server.ts +++ b/tests/e2e/storybook-server.ts @@ -1,13 +1,11 @@ import { existsSync } from "node:fs"; import { resolve, sep } from "node:path"; -const root = resolve(process.cwd(), "packages/ui/storybook-static"); +const root = resolve(process.cwd(), "storybook-static"); const port = Number(process.env.STORYBOOK_STATIC_PORT || 6007); if (!existsSync(resolve(root, "iframe.html"))) { - throw new Error( - "packages/ui/storybook-static is missing. Run bun run build-storybook first.", - ); + throw new Error("storybook-static is missing. Run bun run build-storybook first."); } Bun.serve({ diff --git a/apps/web/tests/e2e/storybook.spec.ts b/tests/e2e/storybook.spec.ts similarity index 100% rename from apps/web/tests/e2e/storybook.spec.ts rename to tests/e2e/storybook.spec.ts diff --git a/tsconfig.base.json b/tsconfig.base.json deleted file mode 100644 index dcde3db..0000000 --- a/tsconfig.base.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "compilerOptions": { - "allowJs": true, - "checkJs": true, - "esModuleInterop": true, - "forceConsistentCasingInFileNames": true, - "ignoreDeprecations": "6.0", - "jsx": "react-jsx", - "module": "ESNext", - "moduleResolution": "bundler", - "resolveJsonModule": true, - "skipLibCheck": true, - "sourceMap": true, - "strict": true, - "target": "ES2022", - "types": ["node", "bun-types", "react", "react-dom"] - } -} diff --git a/tsconfig.json b/tsconfig.json index 57ef1e6..ab92320 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,7 +1,35 @@ { - "files": [], - "references": [ - { "path": "./apps/web" }, - { "path": "./packages/ui" } + "compilerOptions": { + "allowJs": true, + "baseUrl": ".", + "checkJs": true, + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "ignoreDeprecations": "6.0", + "jsx": "react-jsx", + "module": "ESNext", + "moduleResolution": "bundler", + "paths": { + "$lib/*": ["src/lib/*"] + }, + "resolveJsonModule": true, + "skipLibCheck": true, + "sourceMap": true, + "strict": true, + "target": "ES2022", + "types": ["node", "bun-types", "react", "react-dom"] + }, + "include": [ + "src/**/*.ts", + "src/**/*.tsx", + "tests/**/*.ts", + "vite.config.ts", + "playwright.config.ts", + "drizzle.config.ts" + ], + "exclude": [ + "build", + "node_modules", + ".storybook" ] } diff --git a/turbo.json b/turbo.json deleted file mode 100644 index ee027a8..0000000 --- a/turbo.json +++ /dev/null @@ -1,43 +0,0 @@ -{ - "$schema": "https://turbo.build/schema.json", - "tasks": { - "build": { - "dependsOn": ["^build"], - "outputs": ["dist/**", "build/**"] - }, - "check": { - "dependsOn": ["^build"], - "outputs": [] - }, - "test:unit": { - "dependsOn": ["^build"], - "outputs": [] - }, - "build-storybook": { - "dependsOn": ["^build"], - "outputs": ["storybook-static/**"] - }, - "test:e2e": { - "dependsOn": ["build", "^build"], - "outputs": ["test-results/**", "playwright-report/**"] - }, - "test:qa": { - "dependsOn": [ - "check", - "test:unit", - "build", - "build-storybook", - "test:e2e" - ], - "outputs": [] - }, - "dev": { - "cache": false, - "persistent": true - }, - "storybook": { - "cache": false, - "persistent": true - } - } -} diff --git a/apps/web/vite.config.ts b/vite.config.ts similarity index 76% rename from apps/web/vite.config.ts rename to vite.config.ts index d88ee57..ceff746 100644 --- a/apps/web/vite.config.ts +++ b/vite.config.ts @@ -24,12 +24,6 @@ export default defineConfig({ plugins: [react(), tailwindcss()], resolve: { alias: { - "@dimensionlab/ui/styles.css": fileURLToPath( - new URL("../../packages/ui/src/styles.css", import.meta.url), - ), - "@dimensionlab/ui": fileURLToPath( - new URL("../../packages/ui/src/index.ts", import.meta.url), - ), $lib: fileURLToPath(new URL("./src/lib", import.meta.url)), }, },