Compare commits
No commits in common. "de9b8c51bdc6b7440a6625ccf57ad35c5c34ac60" and "4c6335d31600fa661d0af5c3a396165011e5af34" have entirely different histories.
de9b8c51bd
...
4c6335d316
15 changed files with 389 additions and 711 deletions
55
README.md
55
README.md
|
|
@ -43,12 +43,14 @@ cd bms
|
||||||
|
|
||||||
### 2. Create the environment files
|
### 2. Create the environment files
|
||||||
|
|
||||||
|
Copy the example files and fill in your values:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cp backend/.env.example backend/.env
|
cp backend/.env.example backend/.env
|
||||||
cp frontend/.env.local.example frontend/.env.local
|
cp frontend/.env.local.example frontend/.env.local
|
||||||
```
|
```
|
||||||
|
|
||||||
The defaults work as-is — they already match the service names in `docker-compose.yml`. **The app runs in demo mode with authentication disabled**, so there are no keys to obtain before the first run. See [Environment Variables](#environment-variables) below.
|
Open each file and follow the inline comments. At minimum you need to set the Clerk keys (see [Environment Variables](#environment-variables) below).
|
||||||
|
|
||||||
### 3. Start all services
|
### 3. Start all services
|
||||||
|
|
||||||
|
|
@ -70,14 +72,6 @@ Open your browser at **http://your-server:5646**
|
||||||
|
|
||||||
## Environment Variables
|
## Environment Variables
|
||||||
|
|
||||||
> **Authentication is disabled.** The app runs in demo mode: `frontend/proxy.ts` passes every
|
|
||||||
> request through and there is no auth provider in `app/layout.tsx`. Deploy it on a trusted
|
|
||||||
> network (LAN, VPN, or behind an authenticating reverse proxy) — every route is open.
|
|
||||||
>
|
|
||||||
> To turn auth back on: reinstall `@clerk/nextjs`, wrap the tree in `<ClerkProvider>` in
|
|
||||||
> `app/layout.tsx`, restore `<UserButton />` in `components/layout/topbar.tsx`, re-add the
|
|
||||||
> `sign-in` / `sign-up` route groups, and swap `proxy.ts` for `clerkMiddleware`.
|
|
||||||
|
|
||||||
### `backend/.env`
|
### `backend/.env`
|
||||||
|
|
||||||
```env
|
```env
|
||||||
|
|
@ -88,6 +82,11 @@ DATABASE_URL=postgresql+asyncpg://dcim:dcim_pass@db:5432/dcim
|
||||||
MQTT_HOST=mqtt
|
MQTT_HOST=mqtt
|
||||||
MQTT_PORT=1883
|
MQTT_PORT=1883
|
||||||
|
|
||||||
|
# Clerk authentication
|
||||||
|
# Get these from https://dashboard.clerk.com → Your App → API Keys
|
||||||
|
CLERK_SECRET_KEY=sk_test_REPLACE_ME
|
||||||
|
CLERK_JWKS_URL=https://YOUR_APP.clerk.accounts.dev/.well-known/jwks.json
|
||||||
|
|
||||||
# CORS — add your frontend origin if you expose the backend directly
|
# CORS — add your frontend origin if you expose the backend directly
|
||||||
# Leave empty when using the built-in Next.js proxy (recommended)
|
# Leave empty when using the built-in Next.js proxy (recommended)
|
||||||
CORS_ORIGINS=[]
|
CORS_ORIGINS=[]
|
||||||
|
|
@ -98,14 +97,24 @@ DEBUG=true
|
||||||
### `frontend/.env.local`
|
### `frontend/.env.local`
|
||||||
|
|
||||||
```env
|
```env
|
||||||
|
# Clerk authentication (same app as above)
|
||||||
|
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_test_REPLACE_ME
|
||||||
|
CLERK_SECRET_KEY=sk_test_REPLACE_ME
|
||||||
|
|
||||||
|
# Clerk redirect paths — no need to change these
|
||||||
|
NEXT_PUBLIC_CLERK_SIGN_IN_URL=/sign-in
|
||||||
|
NEXT_PUBLIC_CLERK_SIGN_UP_URL=/sign-up
|
||||||
|
NEXT_PUBLIC_CLERK_AFTER_SIGN_IN_URL=/dashboard
|
||||||
|
NEXT_PUBLIC_CLERK_AFTER_SIGN_UP_URL=/dashboard
|
||||||
|
|
||||||
# API path — leave as-is, Next.js proxies /api/backend/* to the backend internally
|
# API path — leave as-is, Next.js proxies /api/backend/* to the backend internally
|
||||||
NEXT_PUBLIC_API_URL=/api/backend
|
NEXT_PUBLIC_API_URL=/api/backend
|
||||||
|
|
||||||
# Backend internal URL (used by the Next.js server-side proxy, not sent to the browser)
|
|
||||||
# In Docker: http://backend:8000 In local dev: http://localhost:8000
|
|
||||||
BACKEND_INTERNAL_URL=http://backend:8000
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
> **Where do I get Clerk keys?**
|
||||||
|
> Sign up free at https://clerk.com → create an application → go to **API Keys**.
|
||||||
|
> Copy the **Publishable key** and **Secret key** into both files above.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Verify Everything Is Running
|
## Verify Everything Is Running
|
||||||
|
|
@ -172,26 +181,6 @@ Browser → Reverse Proxy → :5646 (Next.js)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Deploying to the Unraid Server
|
|
||||||
|
|
||||||
The live instance runs on the Unraid Docker host at `192.168.1.249` as the Portainer stack
|
|
||||||
**`bms`** — reachable at **http://192.168.1.249:5646/dashboard**.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
python3 ops/deploy.py # build all four images + deploy/update the stack
|
|
||||||
python3 ops/deploy.py --no-build # redeploy the stack using the existing images
|
|
||||||
```
|
|
||||||
|
|
||||||
There is no `docker` CLI in WSL and no SSH to the Unraid box, so `ops/deploy.py` ships each
|
|
||||||
service's build context to the remote daemon's `/build` endpoint over the Portainer API
|
|
||||||
(token at `~/.portainer-token`), then pushes `docker-compose.prod.yml` as a Portainer stack.
|
|
||||||
The script is idempotent — rerun it after any code change.
|
|
||||||
|
|
||||||
`docker-compose.prod.yml` differs from the dev `docker-compose.yml`: images instead of build
|
|
||||||
contexts, no source bind mounts, no `--reload`, and only the frontend publishes a host port.
|
|
||||||
Postgres data is bind-mounted to `/mnt/user/appdata/bms/db` so it lands on the Unraid array
|
|
||||||
instead of growing inside `docker.img`, and it survives redeploys.
|
|
||||||
|
|
||||||
## Local Development (without Docker)
|
## Local Development (without Docker)
|
||||||
|
|
||||||
Useful if you want hot-reload on the frontend or backend without rebuilding containers.
|
Useful if you want hot-reload on the frontend or backend without rebuilding containers.
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,11 @@ DATABASE_URL=postgresql+asyncpg://dcim:dcim_pass@db:5432/dcim
|
||||||
MQTT_HOST=mqtt
|
MQTT_HOST=mqtt
|
||||||
MQTT_PORT=1883
|
MQTT_PORT=1883
|
||||||
|
|
||||||
|
# Clerk authentication
|
||||||
|
# Get these from https://dashboard.clerk.com → Your App → API Keys
|
||||||
|
CLERK_SECRET_KEY=sk_test_REPLACE_ME
|
||||||
|
CLERK_JWKS_URL=https://YOUR_APP.clerk.accounts.dev/.well-known/jwks.json
|
||||||
|
|
||||||
# CORS origins — only needed if the backend is accessed directly from a browser
|
# CORS origins — only needed if the backend is accessed directly from a browser
|
||||||
# Example: CORS_ORIGINS=["https://yourdomain.com"]
|
# Example: CORS_ORIGINS=["https://yourdomain.com"]
|
||||||
# Leave empty when using the built-in Next.js proxy (recommended)
|
# Leave empty when using the built-in Next.js proxy (recommended)
|
||||||
|
|
|
||||||
|
|
@ -1,116 +0,0 @@
|
||||||
# Production stack — deployed to the Unraid Docker host as a Portainer stack.
|
|
||||||
#
|
|
||||||
# Differences from docker-compose.yml (the local dev file):
|
|
||||||
# * No build: sections. ops/deploy.py builds the four images on the Unraid daemon
|
|
||||||
# first; this file only references them by tag.
|
|
||||||
# * No source bind mounts and no uvicorn --reload. Code lives in the image.
|
|
||||||
# * No env_file. Everything is set inline — there are no .env files on the host.
|
|
||||||
# * Only the frontend publishes a host port. Postgres and MQTT stay on the
|
|
||||||
# internal bms_net network, as the README's reverse-proxy note recommends.
|
|
||||||
# * Postgres data is bind-mounted to /mnt/user/appdata/bms/db so it lands on the
|
|
||||||
# Unraid array rather than growing inside docker.img.
|
|
||||||
#
|
|
||||||
# Deploy / redeploy with: python3 ops/deploy.py
|
|
||||||
|
|
||||||
services:
|
|
||||||
|
|
||||||
# ── MQTT Broker ──────────────────────────────────────────────────
|
|
||||||
mqtt:
|
|
||||||
image: bms-mqtt:latest
|
|
||||||
container_name: bms_mqtt
|
|
||||||
restart: unless-stopped
|
|
||||||
networks: [bms_net]
|
|
||||||
healthcheck:
|
|
||||||
test: ["CMD-SHELL", "mosquitto_sub -t '$$SYS/#' -C 1 -i healthcheck -W 3"]
|
|
||||||
interval: 10s
|
|
||||||
timeout: 5s
|
|
||||||
retries: 5
|
|
||||||
|
|
||||||
# ── PostgreSQL + TimescaleDB ─────────────────────────────────────
|
|
||||||
db:
|
|
||||||
image: timescale/timescaledb:latest-pg16
|
|
||||||
container_name: bms_db
|
|
||||||
restart: unless-stopped
|
|
||||||
networks: [bms_net]
|
|
||||||
environment:
|
|
||||||
POSTGRES_USER: dcim
|
|
||||||
POSTGRES_PASSWORD: dcim_pass
|
|
||||||
POSTGRES_DB: dcim
|
|
||||||
volumes:
|
|
||||||
- /mnt/user/appdata/bms/db:/var/lib/postgresql/data
|
|
||||||
healthcheck:
|
|
||||||
test: ["CMD-SHELL", "pg_isready -U dcim -d dcim"]
|
|
||||||
interval: 10s
|
|
||||||
timeout: 5s
|
|
||||||
retries: 5
|
|
||||||
|
|
||||||
# ── FastAPI backend ──────────────────────────────────────────────
|
|
||||||
backend:
|
|
||||||
image: bms-backend:latest
|
|
||||||
container_name: bms_backend
|
|
||||||
restart: unless-stopped
|
|
||||||
networks: [bms_net]
|
|
||||||
environment:
|
|
||||||
DATABASE_URL: postgresql+asyncpg://dcim:dcim_pass@db:5432/dcim
|
|
||||||
MQTT_HOST: mqtt
|
|
||||||
MQTT_PORT: "1883"
|
|
||||||
CORS_ORIGINS: "[]"
|
|
||||||
DEBUG: "false"
|
|
||||||
depends_on:
|
|
||||||
db:
|
|
||||||
condition: service_healthy
|
|
||||||
mqtt:
|
|
||||||
condition: service_healthy
|
|
||||||
healthcheck:
|
|
||||||
test: ["CMD-SHELL", "curl -sf http://localhost:8000/api/health || exit 1"]
|
|
||||||
interval: 10s
|
|
||||||
timeout: 5s
|
|
||||||
retries: 10
|
|
||||||
start_period: 20s
|
|
||||||
|
|
||||||
# ── Simulator bots (seed first, then run bots) ───────────────────
|
|
||||||
simulators:
|
|
||||||
image: bms-simulators:latest
|
|
||||||
container_name: bms_simulators
|
|
||||||
restart: unless-stopped
|
|
||||||
networks: [bms_net]
|
|
||||||
environment:
|
|
||||||
MQTT_HOST: mqtt
|
|
||||||
MQTT_PORT: "1883"
|
|
||||||
DATABASE_URL: postgresql://dcim:dcim_pass@db:5432/dcim
|
|
||||||
SEED_MINUTES: "30"
|
|
||||||
depends_on:
|
|
||||||
db:
|
|
||||||
condition: service_healthy
|
|
||||||
mqtt:
|
|
||||||
condition: service_healthy
|
|
||||||
backend:
|
|
||||||
condition: service_healthy
|
|
||||||
|
|
||||||
# ── Next.js frontend (the only publicly reachable service) ───────
|
|
||||||
frontend:
|
|
||||||
image: bms-frontend:latest
|
|
||||||
container_name: bms_frontend
|
|
||||||
restart: unless-stopped
|
|
||||||
networks: [bms_net]
|
|
||||||
ports:
|
|
||||||
- "5646:5646"
|
|
||||||
environment:
|
|
||||||
PORT: "5646"
|
|
||||||
HOSTNAME: "0.0.0.0"
|
|
||||||
NODE_ENV: production
|
|
||||||
BACKEND_INTERNAL_URL: http://backend:8000
|
|
||||||
depends_on:
|
|
||||||
- backend
|
|
||||||
|
|
||||||
networks:
|
|
||||||
# The Unraid daemon's default address pools are fully subnetted — 24 existing
|
|
||||||
# stacks have claimed every 172.17-172.31/16 and 192.168.x/20 slot, so letting
|
|
||||||
# Docker auto-allocate fails with "all predefined address pools have been fully
|
|
||||||
# subnetted". An explicit subnet bypasses the allocator entirely.
|
|
||||||
# 172.31.42.0/24 is free: the only other 172.31 tenant is wg0 on 172.31.200.0/24.
|
|
||||||
bms_net:
|
|
||||||
driver: bridge
|
|
||||||
ipam:
|
|
||||||
config:
|
|
||||||
- subnet: 172.31.42.0/24
|
|
||||||
|
|
@ -1,11 +1,19 @@
|
||||||
# ─────────────────────────────────────────────────────────────────
|
# ─────────────────────────────────────────────────────────────────
|
||||||
# BMS Frontend — Environment Variables
|
# BMS Frontend — Environment Variables
|
||||||
# Copy this file to .env.local. The defaults below work as-is.
|
# Copy this file to .env.local and fill in your values.
|
||||||
# Never commit .env.local to git.
|
# Never commit .env.local to git.
|
||||||
# ─────────────────────────────────────────────────────────────────
|
# ─────────────────────────────────────────────────────────────────
|
||||||
#
|
|
||||||
# Authentication is disabled (demo mode) — see proxy.ts and the README.
|
# Clerk authentication
|
||||||
# There are no auth keys to set.
|
# Get these from https://dashboard.clerk.com → Your App → API Keys
|
||||||
|
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_test_REPLACE_ME
|
||||||
|
CLERK_SECRET_KEY=sk_test_REPLACE_ME
|
||||||
|
|
||||||
|
# Clerk redirect paths — no change needed
|
||||||
|
NEXT_PUBLIC_CLERK_SIGN_IN_URL=/sign-in
|
||||||
|
NEXT_PUBLIC_CLERK_SIGN_UP_URL=/sign-up
|
||||||
|
NEXT_PUBLIC_CLERK_AFTER_SIGN_IN_URL=/dashboard
|
||||||
|
NEXT_PUBLIC_CLERK_AFTER_SIGN_UP_URL=/dashboard
|
||||||
|
|
||||||
# API path — leave as-is
|
# API path — leave as-is
|
||||||
# All /api/backend/* requests are proxied server-side to the FastAPI backend
|
# All /api/backend/* requests are proxied server-side to the FastAPI backend
|
||||||
|
|
|
||||||
|
|
@ -4,9 +4,7 @@ FROM node:22-alpine AS base
|
||||||
FROM base AS deps
|
FROM base AS deps
|
||||||
RUN apk add --no-cache libc6-compat
|
RUN apk add --no-cache libc6-compat
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
# pnpm-workspace.yaml carries ignoredBuiltDependencies — without it pnpm 10+
|
COPY package.json pnpm-lock.yaml* ./
|
||||||
# aborts the install with ERR_PNPM_IGNORED_BUILDS.
|
|
||||||
COPY package.json pnpm-lock.yaml* pnpm-workspace.yaml* ./
|
|
||||||
RUN corepack enable pnpm && pnpm install --frozen-lockfile
|
RUN corepack enable pnpm && pnpm install --frozen-lockfile
|
||||||
|
|
||||||
# Build the app
|
# Build the app
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import type { Metadata } from "next";
|
import type { Metadata } from "next";
|
||||||
import { Geist, Geist_Mono } from "next/font/google";
|
import { Geist, Geist_Mono } from "next/font/google";
|
||||||
|
import { ClerkProvider } from "@clerk/nextjs";
|
||||||
import { ThemeProvider } from "@/components/theme-provider";
|
import { ThemeProvider } from "@/components/theme-provider";
|
||||||
import { TooltipProvider } from "@/components/ui/tooltip";
|
import { TooltipProvider } from "@/components/ui/tooltip";
|
||||||
import "./globals.css";
|
import "./globals.css";
|
||||||
|
|
@ -24,9 +25,8 @@ export default function RootLayout({
|
||||||
}: Readonly<{
|
}: Readonly<{
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
}>) {
|
}>) {
|
||||||
// Demo mode: no auth provider — see proxy.ts. Re-add <ClerkProvider> here
|
|
||||||
// (and the keys in .env.local) if authentication is ever turned back on.
|
|
||||||
return (
|
return (
|
||||||
|
<ClerkProvider>
|
||||||
<html lang="en" suppressHydrationWarning>
|
<html lang="en" suppressHydrationWarning>
|
||||||
<body className={`${geistSans.variable} ${geistMono.variable} antialiased`}>
|
<body className={`${geistSans.variable} ${geistMono.variable} antialiased`}>
|
||||||
<ThemeProvider
|
<ThemeProvider
|
||||||
|
|
@ -41,5 +41,6 @@ export default function RootLayout({
|
||||||
</ThemeProvider>
|
</ThemeProvider>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
</ClerkProvider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
21
frontend/app/sign-in/[[...sign-in]]/page.tsx
Normal file
21
frontend/app/sign-in/[[...sign-in]]/page.tsx
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
import { SignIn } from "@clerk/nextjs";
|
||||||
|
import { Database } from "lucide-react";
|
||||||
|
|
||||||
|
export default function SignInPage() {
|
||||||
|
return (
|
||||||
|
<div className="flex min-h-screen items-center justify-center bg-background">
|
||||||
|
<div className="flex flex-col items-center gap-8">
|
||||||
|
<div className="flex items-center gap-3">
|
||||||
|
<div className="flex items-center justify-center w-10 h-10 rounded-xl bg-primary">
|
||||||
|
<Database className="w-5 h-5 text-primary-foreground" />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<p className="text-lg font-bold tracking-tight">DemoBMS</p>
|
||||||
|
<p className="text-xs text-muted-foreground">Infrastructure Management</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<SignIn />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
21
frontend/app/sign-up/[[...sign-up]]/page.tsx
Normal file
21
frontend/app/sign-up/[[...sign-up]]/page.tsx
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
import { SignUp } from "@clerk/nextjs";
|
||||||
|
import { Database } from "lucide-react";
|
||||||
|
|
||||||
|
export default function SignUpPage() {
|
||||||
|
return (
|
||||||
|
<div className="flex min-h-screen items-center justify-center bg-background">
|
||||||
|
<div className="flex flex-col items-center gap-8">
|
||||||
|
<div className="flex items-center gap-3">
|
||||||
|
<div className="flex items-center justify-center w-10 h-10 rounded-xl bg-primary">
|
||||||
|
<Database className="w-5 h-5 text-primary-foreground" />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<p className="text-lg font-bold tracking-tight">DemoBMS</p>
|
||||||
|
<p className="text-xs text-muted-foreground">Infrastructure Management</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<SignUp />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -4,6 +4,7 @@ import { Bell, Menu, Moon, Sun } from "lucide-react";
|
||||||
import { SimulatorPanel } from "@/components/simulator/SimulatorPanel";
|
import { SimulatorPanel } from "@/components/simulator/SimulatorPanel";
|
||||||
import { usePathname } from "next/navigation";
|
import { usePathname } from "next/navigation";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
|
import { UserButton } from "@clerk/nextjs";
|
||||||
import { useTheme } from "next-themes";
|
import { useTheme } from "next-themes";
|
||||||
import { Badge } from "@/components/ui/badge";
|
import { Badge } from "@/components/ui/badge";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
|
|
@ -84,6 +85,15 @@ export function Topbar() {
|
||||||
>
|
>
|
||||||
{theme === "dark" ? <Sun className="w-4 h-4" /> : <Moon className="w-4 h-4" />}
|
{theme === "dark" ? <Sun className="w-4 h-4" /> : <Moon className="w-4 h-4" />}
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
|
{/* Clerk user button */}
|
||||||
|
<UserButton
|
||||||
|
appearance={{
|
||||||
|
elements: {
|
||||||
|
avatarBox: "w-7 h-7",
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,6 @@
|
||||||
"name": "frontend",
|
"name": "frontend",
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"packageManager": "pnpm@11.20.0",
|
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "next dev",
|
"dev": "next dev",
|
||||||
"build": "next build",
|
"build": "next build",
|
||||||
|
|
@ -10,6 +9,7 @@
|
||||||
"lint": "eslint"
|
"lint": "eslint"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@clerk/nextjs": "^7.0.1",
|
||||||
"class-variance-authority": "^0.7.1",
|
"class-variance-authority": "^0.7.1",
|
||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
"lucide-react": "^0.577.0",
|
"lucide-react": "^0.577.0",
|
||||||
|
|
|
||||||
440
frontend/pnpm-lock.yaml
generated
440
frontend/pnpm-lock.yaml
generated
|
|
@ -8,6 +8,9 @@ importers:
|
||||||
|
|
||||||
.:
|
.:
|
||||||
dependencies:
|
dependencies:
|
||||||
|
'@clerk/nextjs':
|
||||||
|
specifier: ^7.0.1
|
||||||
|
version: 7.0.1(next@16.1.6(@babel/core@7.29.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
|
||||||
class-variance-authority:
|
class-variance-authority:
|
||||||
specifier: ^0.7.1
|
specifier: ^0.7.1
|
||||||
version: 0.7.1
|
version: 0.7.1
|
||||||
|
|
@ -19,7 +22,7 @@ importers:
|
||||||
version: 0.577.0(react@19.2.3)
|
version: 0.577.0(react@19.2.3)
|
||||||
next:
|
next:
|
||||||
specifier: 16.1.6
|
specifier: 16.1.6
|
||||||
version: 16.1.6(@babel/core@7.29.0(supports-color@7.2.0))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
|
version: 16.1.6(@babel/core@7.29.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
|
||||||
next-themes:
|
next-themes:
|
||||||
specifier: ^0.4.6
|
specifier: ^0.4.6
|
||||||
version: 0.4.6(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
|
version: 0.4.6(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
|
||||||
|
|
@ -59,13 +62,13 @@ importers:
|
||||||
version: 19.2.3(@types/react@19.2.14)
|
version: 19.2.3(@types/react@19.2.14)
|
||||||
eslint:
|
eslint:
|
||||||
specifier: ^9
|
specifier: ^9
|
||||||
version: 9.39.3(jiti@2.6.1)(supports-color@7.2.0)
|
version: 9.39.3(jiti@2.6.1)
|
||||||
eslint-config-next:
|
eslint-config-next:
|
||||||
specifier: 16.1.6
|
specifier: 16.1.6
|
||||||
version: 16.1.6(@typescript-eslint/parser@8.56.1(eslint@9.39.3(jiti@2.6.1)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3))(eslint@9.39.3(jiti@2.6.1)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3)
|
version: 16.1.6(@typescript-eslint/parser@8.56.1(eslint@9.39.3(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.3(jiti@2.6.1))(typescript@5.9.3)
|
||||||
shadcn:
|
shadcn:
|
||||||
specifier: ^3.8.5
|
specifier: ^3.8.5
|
||||||
version: 3.8.5(@types/node@20.19.35)(supports-color@7.2.0)(typescript@5.9.3)
|
version: 3.8.5(@types/node@20.19.35)(typescript@5.9.3)
|
||||||
tailwindcss:
|
tailwindcss:
|
||||||
specifier: ^4
|
specifier: ^4
|
||||||
version: 4.2.1
|
version: 4.2.1
|
||||||
|
|
@ -215,6 +218,37 @@ packages:
|
||||||
resolution: {integrity: sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==}
|
resolution: {integrity: sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==}
|
||||||
engines: {node: '>=6.9.0'}
|
engines: {node: '>=6.9.0'}
|
||||||
|
|
||||||
|
'@clerk/backend@3.0.1':
|
||||||
|
resolution: {integrity: sha512-U5E+KpNlFlaJRdpOoOltIV8o1YjTWw5affsugEb/kIvGceSP6SzvNEBr/TnCY+2yu87Vq22ShEycpQBlse2Bkw==}
|
||||||
|
engines: {node: '>=20.9.0'}
|
||||||
|
|
||||||
|
'@clerk/nextjs@7.0.1':
|
||||||
|
resolution: {integrity: sha512-sm5vpQkVUpTWFGe6k4wELL4zTve4JK5IWd8epBj6x4fBAWJMqtC3QeWrvaI7Sl8Ef/0STOM41FcwsVtVMk4v9Q==}
|
||||||
|
engines: {node: '>=20.9.0'}
|
||||||
|
peerDependencies:
|
||||||
|
next: ^15.2.8 || ^15.3.8 || ^15.4.10 || ^15.5.9 || ^15.6.0-0 || ^16.0.10 || ^16.1.0-0
|
||||||
|
react: ^18.0.0 || ~19.0.3 || ~19.1.4 || ~19.2.3 || ~19.3.0-0
|
||||||
|
react-dom: ^18.0.0 || ~19.0.3 || ~19.1.4 || ~19.2.3 || ~19.3.0-0
|
||||||
|
|
||||||
|
'@clerk/react@6.0.1':
|
||||||
|
resolution: {integrity: sha512-zq6vfH7Yiul4PPxUmyl/iW6CZbIzxfHvhXLxZK9zbqHQEy9xDlIQirhWIiHucBqMWTJruudY5KCV5WBe2xmfww==}
|
||||||
|
engines: {node: '>=20.9.0'}
|
||||||
|
peerDependencies:
|
||||||
|
react: ^18.0.0 || ~19.0.3 || ~19.1.4 || ~19.2.3 || ~19.3.0-0
|
||||||
|
react-dom: ^18.0.0 || ~19.0.3 || ~19.1.4 || ~19.2.3 || ~19.3.0-0
|
||||||
|
|
||||||
|
'@clerk/shared@4.0.0':
|
||||||
|
resolution: {integrity: sha512-Z3QhVud7FM9SBgSGxyUdC+nDg6vro+5zJ5gDO1To3FDzRLWKW4xIGd5y8UBqWZMMMHWaSDiZvYlUynb+gs8PnQ==}
|
||||||
|
engines: {node: '>=20.9.0'}
|
||||||
|
peerDependencies:
|
||||||
|
react: ^18.0.0 || ~19.0.3 || ~19.1.4 || ~19.2.3 || ~19.3.0-0
|
||||||
|
react-dom: ^18.0.0 || ~19.0.3 || ~19.1.4 || ~19.2.3 || ~19.3.0-0
|
||||||
|
peerDependenciesMeta:
|
||||||
|
react:
|
||||||
|
optional: true
|
||||||
|
react-dom:
|
||||||
|
optional: true
|
||||||
|
|
||||||
'@dotenvx/dotenvx@1.52.0':
|
'@dotenvx/dotenvx@1.52.0':
|
||||||
resolution: {integrity: sha512-CaQcc8JvtzQhUSm9877b6V4Tb7HCotkcyud9X2YwdqtQKwgljkMRwU96fVYKnzN3V0Hj74oP7Es+vZ0mS+Aa1w==}
|
resolution: {integrity: sha512-CaQcc8JvtzQhUSm9877b6V4Tb7HCotkcyud9X2YwdqtQKwgljkMRwU96fVYKnzN3V0Hj74oP7Es+vZ0mS+Aa1w==}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
@ -1336,6 +1370,9 @@ packages:
|
||||||
resolution: {integrity: sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ==}
|
resolution: {integrity: sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ==}
|
||||||
engines: {node: '>=18'}
|
engines: {node: '>=18'}
|
||||||
|
|
||||||
|
'@stablelib/base64@1.0.1':
|
||||||
|
resolution: {integrity: sha512-1bnPQqSxSuc3Ii6MhBysoWCg58j97aUjuCSZrGSmDxNqtytIi0k8utUenAwTZN4V5mXXYGsVUI9zeBqy+jBOSQ==}
|
||||||
|
|
||||||
'@standard-schema/spec@1.1.0':
|
'@standard-schema/spec@1.1.0':
|
||||||
resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==}
|
resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==}
|
||||||
|
|
||||||
|
|
@ -1437,6 +1474,9 @@ packages:
|
||||||
'@tailwindcss/postcss@4.2.1':
|
'@tailwindcss/postcss@4.2.1':
|
||||||
resolution: {integrity: sha512-OEwGIBnXnj7zJeonOh6ZG9woofIjGrd2BORfvE5p9USYKDCZoQmfqLcfNiRWoJlRWLdNPn2IgVZuWAOM4iTYMw==}
|
resolution: {integrity: sha512-OEwGIBnXnj7zJeonOh6ZG9woofIjGrd2BORfvE5p9USYKDCZoQmfqLcfNiRWoJlRWLdNPn2IgVZuWAOM4iTYMw==}
|
||||||
|
|
||||||
|
'@tanstack/query-core@5.90.16':
|
||||||
|
resolution: {integrity: sha512-MvtWckSVufs/ja463/K4PyJeqT+HMlJWtw6PrCpywznd2NSgO3m4KwO9RqbFqGg6iDE8vVMFWMeQI4Io3eEYww==}
|
||||||
|
|
||||||
'@ts-morph/common@0.27.0':
|
'@ts-morph/common@0.27.0':
|
||||||
resolution: {integrity: sha512-Wf29UqxWDpc+i61k3oIOzcUfQt79PIT9y/MWfAGlrkjg6lBC1hwDECLXPVJAhWjiGbfBCxZd65F/LIZF3+jeJQ==}
|
resolution: {integrity: sha512-Wf29UqxWDpc+i61k3oIOzcUfQt79PIT9y/MWfAGlrkjg6lBC1hwDECLXPVJAhWjiGbfBCxZd65F/LIZF3+jeJQ==}
|
||||||
|
|
||||||
|
|
@ -2059,6 +2099,10 @@ packages:
|
||||||
resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==}
|
resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==}
|
||||||
engines: {node: '>= 0.8'}
|
engines: {node: '>= 0.8'}
|
||||||
|
|
||||||
|
dequal@2.0.3:
|
||||||
|
resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==}
|
||||||
|
engines: {node: '>=6'}
|
||||||
|
|
||||||
detect-libc@2.1.2:
|
detect-libc@2.1.2:
|
||||||
resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==}
|
resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
|
|
@ -2337,6 +2381,9 @@ packages:
|
||||||
fast-levenshtein@2.0.6:
|
fast-levenshtein@2.0.6:
|
||||||
resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==}
|
resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==}
|
||||||
|
|
||||||
|
fast-sha256@1.3.0:
|
||||||
|
resolution: {integrity: sha512-n11RGP/lrWEFI/bWdygLxhI+pVeo1ZYIVwvvPkW7azl/rOy+F3HYRZ2K5zeE9mmkhQppyv9sQFx0JM9UabnpPQ==}
|
||||||
|
|
||||||
fast-uri@3.1.0:
|
fast-uri@3.1.0:
|
||||||
resolution: {integrity: sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==}
|
resolution: {integrity: sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==}
|
||||||
|
|
||||||
|
|
@ -2474,6 +2521,9 @@ packages:
|
||||||
resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==}
|
resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==}
|
||||||
engines: {node: '>=10.13.0'}
|
engines: {node: '>=10.13.0'}
|
||||||
|
|
||||||
|
glob-to-regexp@0.4.1:
|
||||||
|
resolution: {integrity: sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==}
|
||||||
|
|
||||||
globals@14.0.0:
|
globals@14.0.0:
|
||||||
resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==}
|
resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==}
|
||||||
engines: {node: '>=18'}
|
engines: {node: '>=18'}
|
||||||
|
|
@ -2785,6 +2835,10 @@ packages:
|
||||||
jose@6.2.0:
|
jose@6.2.0:
|
||||||
resolution: {integrity: sha512-xsfE1TcSCbUdo6U07tR0mvhg0flGxU8tPLbF03mirl2ukGQENhUg4ubGYQnhVH0b5stLlPM+WOqDkEl1R1y5sQ==}
|
resolution: {integrity: sha512-xsfE1TcSCbUdo6U07tR0mvhg0flGxU8tPLbF03mirl2ukGQENhUg4ubGYQnhVH0b5stLlPM+WOqDkEl1R1y5sQ==}
|
||||||
|
|
||||||
|
js-cookie@3.0.5:
|
||||||
|
resolution: {integrity: sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw==}
|
||||||
|
engines: {node: '>=14'}
|
||||||
|
|
||||||
js-tokens@4.0.0:
|
js-tokens@4.0.0:
|
||||||
resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
|
resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
|
||||||
|
|
||||||
|
|
@ -3471,6 +3525,9 @@ packages:
|
||||||
resolution: {integrity: sha512-xRXBn0pPqQTVQiC8wyQrKs2MOlX24zQ0POGaj0kultvoOCstBQM5yvOhAVSUwOMjQtTvsPWoNCHfPGwaaQJhTw==}
|
resolution: {integrity: sha512-xRXBn0pPqQTVQiC8wyQrKs2MOlX24zQ0POGaj0kultvoOCstBQM5yvOhAVSUwOMjQtTvsPWoNCHfPGwaaQJhTw==}
|
||||||
engines: {node: '>= 18'}
|
engines: {node: '>= 18'}
|
||||||
|
|
||||||
|
server-only@0.0.1:
|
||||||
|
resolution: {integrity: sha512-qepMx2JxAa5jjfzxG79yPPq+8BuFToHd1hm7kI+Z4zAq1ftQiP7HcxMhDDItrbtwVeLg/cY2JnKnrcFkmiswNA==}
|
||||||
|
|
||||||
set-function-length@1.2.2:
|
set-function-length@1.2.2:
|
||||||
resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==}
|
resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==}
|
||||||
engines: {node: '>= 0.4'}
|
engines: {node: '>= 0.4'}
|
||||||
|
|
@ -3545,10 +3602,16 @@ packages:
|
||||||
stable-hash@0.0.5:
|
stable-hash@0.0.5:
|
||||||
resolution: {integrity: sha512-+L3ccpzibovGXFK+Ap/f8LOS0ahMrHTf3xu7mMLSpEGU0EO9ucaysSylKo9eRDFNhWve/y275iPmIZ4z39a9iA==}
|
resolution: {integrity: sha512-+L3ccpzibovGXFK+Ap/f8LOS0ahMrHTf3xu7mMLSpEGU0EO9ucaysSylKo9eRDFNhWve/y275iPmIZ4z39a9iA==}
|
||||||
|
|
||||||
|
standardwebhooks@1.0.0:
|
||||||
|
resolution: {integrity: sha512-BbHGOQK9olHPMvQNHWul6MYlrRTAOKn03rOe4A8O3CLWhNf4YHBqq2HJKKC+sfqpxiBY52pNeesD6jIiLDz8jg==}
|
||||||
|
|
||||||
statuses@2.0.2:
|
statuses@2.0.2:
|
||||||
resolution: {integrity: sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==}
|
resolution: {integrity: sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==}
|
||||||
engines: {node: '>= 0.8'}
|
engines: {node: '>= 0.8'}
|
||||||
|
|
||||||
|
std-env@3.10.0:
|
||||||
|
resolution: {integrity: sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==}
|
||||||
|
|
||||||
stdin-discarder@0.2.2:
|
stdin-discarder@0.2.2:
|
||||||
resolution: {integrity: sha512-UhDfHmA92YAlNnCfhmq0VeNL5bDbiZGg7sZ2IvPsXubGkiNa9EC+tUTsjBRsYUAz87btI6/1wf4XoVvQ3uRnmQ==}
|
resolution: {integrity: sha512-UhDfHmA92YAlNnCfhmq0VeNL5bDbiZGg7sZ2IvPsXubGkiNa9EC+tUTsjBRsYUAz87btI6/1wf4XoVvQ3uRnmQ==}
|
||||||
engines: {node: '>=18'}
|
engines: {node: '>=18'}
|
||||||
|
|
@ -3931,20 +3994,20 @@ snapshots:
|
||||||
|
|
||||||
'@babel/compat-data@7.29.0': {}
|
'@babel/compat-data@7.29.0': {}
|
||||||
|
|
||||||
'@babel/core@7.29.0(supports-color@7.2.0)':
|
'@babel/core@7.29.0':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/code-frame': 7.29.0
|
'@babel/code-frame': 7.29.0
|
||||||
'@babel/generator': 7.29.1
|
'@babel/generator': 7.29.1
|
||||||
'@babel/helper-compilation-targets': 7.28.6
|
'@babel/helper-compilation-targets': 7.28.6
|
||||||
'@babel/helper-module-transforms': 7.28.6(@babel/core@7.29.0(supports-color@7.2.0))(supports-color@7.2.0)
|
'@babel/helper-module-transforms': 7.28.6(@babel/core@7.29.0)
|
||||||
'@babel/helpers': 7.28.6
|
'@babel/helpers': 7.28.6
|
||||||
'@babel/parser': 7.29.0
|
'@babel/parser': 7.29.0
|
||||||
'@babel/template': 7.28.6
|
'@babel/template': 7.28.6
|
||||||
'@babel/traverse': 7.29.0(supports-color@7.2.0)
|
'@babel/traverse': 7.29.0
|
||||||
'@babel/types': 7.29.0
|
'@babel/types': 7.29.0
|
||||||
'@jridgewell/remapping': 2.3.5
|
'@jridgewell/remapping': 2.3.5
|
||||||
convert-source-map: 2.0.0
|
convert-source-map: 2.0.0
|
||||||
debug: 4.4.3(supports-color@7.2.0)
|
debug: 4.4.3
|
||||||
gensync: 1.0.0-beta.2
|
gensync: 1.0.0-beta.2
|
||||||
json5: 2.2.3
|
json5: 2.2.3
|
||||||
semver: 6.3.1
|
semver: 6.3.1
|
||||||
|
|
@ -3971,41 +4034,41 @@ snapshots:
|
||||||
lru-cache: 5.1.1
|
lru-cache: 5.1.1
|
||||||
semver: 6.3.1
|
semver: 6.3.1
|
||||||
|
|
||||||
'@babel/helper-create-class-features-plugin@7.28.6(@babel/core@7.29.0(supports-color@7.2.0))(supports-color@7.2.0)':
|
'@babel/helper-create-class-features-plugin@7.28.6(@babel/core@7.29.0)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/core': 7.29.0(supports-color@7.2.0)
|
'@babel/core': 7.29.0
|
||||||
'@babel/helper-annotate-as-pure': 7.27.3
|
'@babel/helper-annotate-as-pure': 7.27.3
|
||||||
'@babel/helper-member-expression-to-functions': 7.28.5(supports-color@7.2.0)
|
'@babel/helper-member-expression-to-functions': 7.28.5
|
||||||
'@babel/helper-optimise-call-expression': 7.27.1
|
'@babel/helper-optimise-call-expression': 7.27.1
|
||||||
'@babel/helper-replace-supers': 7.28.6(@babel/core@7.29.0(supports-color@7.2.0))(supports-color@7.2.0)
|
'@babel/helper-replace-supers': 7.28.6(@babel/core@7.29.0)
|
||||||
'@babel/helper-skip-transparent-expression-wrappers': 7.27.1(supports-color@7.2.0)
|
'@babel/helper-skip-transparent-expression-wrappers': 7.27.1
|
||||||
'@babel/traverse': 7.29.0(supports-color@7.2.0)
|
'@babel/traverse': 7.29.0
|
||||||
semver: 6.3.1
|
semver: 6.3.1
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
'@babel/helper-globals@7.28.0': {}
|
'@babel/helper-globals@7.28.0': {}
|
||||||
|
|
||||||
'@babel/helper-member-expression-to-functions@7.28.5(supports-color@7.2.0)':
|
'@babel/helper-member-expression-to-functions@7.28.5':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/traverse': 7.29.0(supports-color@7.2.0)
|
'@babel/traverse': 7.29.0
|
||||||
'@babel/types': 7.29.0
|
'@babel/types': 7.29.0
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
'@babel/helper-module-imports@7.28.6(supports-color@7.2.0)':
|
'@babel/helper-module-imports@7.28.6':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/traverse': 7.29.0(supports-color@7.2.0)
|
'@babel/traverse': 7.29.0
|
||||||
'@babel/types': 7.29.0
|
'@babel/types': 7.29.0
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
'@babel/helper-module-transforms@7.28.6(@babel/core@7.29.0(supports-color@7.2.0))(supports-color@7.2.0)':
|
'@babel/helper-module-transforms@7.28.6(@babel/core@7.29.0)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/core': 7.29.0(supports-color@7.2.0)
|
'@babel/core': 7.29.0
|
||||||
'@babel/helper-module-imports': 7.28.6(supports-color@7.2.0)
|
'@babel/helper-module-imports': 7.28.6
|
||||||
'@babel/helper-validator-identifier': 7.28.5
|
'@babel/helper-validator-identifier': 7.28.5
|
||||||
'@babel/traverse': 7.29.0(supports-color@7.2.0)
|
'@babel/traverse': 7.29.0
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
|
|
@ -4015,18 +4078,18 @@ snapshots:
|
||||||
|
|
||||||
'@babel/helper-plugin-utils@7.28.6': {}
|
'@babel/helper-plugin-utils@7.28.6': {}
|
||||||
|
|
||||||
'@babel/helper-replace-supers@7.28.6(@babel/core@7.29.0(supports-color@7.2.0))(supports-color@7.2.0)':
|
'@babel/helper-replace-supers@7.28.6(@babel/core@7.29.0)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/core': 7.29.0(supports-color@7.2.0)
|
'@babel/core': 7.29.0
|
||||||
'@babel/helper-member-expression-to-functions': 7.28.5(supports-color@7.2.0)
|
'@babel/helper-member-expression-to-functions': 7.28.5
|
||||||
'@babel/helper-optimise-call-expression': 7.27.1
|
'@babel/helper-optimise-call-expression': 7.27.1
|
||||||
'@babel/traverse': 7.29.0(supports-color@7.2.0)
|
'@babel/traverse': 7.29.0
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
'@babel/helper-skip-transparent-expression-wrappers@7.27.1(supports-color@7.2.0)':
|
'@babel/helper-skip-transparent-expression-wrappers@7.27.1':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/traverse': 7.29.0(supports-color@7.2.0)
|
'@babel/traverse': 7.29.0
|
||||||
'@babel/types': 7.29.0
|
'@babel/types': 7.29.0
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
@ -4046,43 +4109,43 @@ snapshots:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/types': 7.29.0
|
'@babel/types': 7.29.0
|
||||||
|
|
||||||
'@babel/plugin-syntax-jsx@7.28.6(@babel/core@7.29.0(supports-color@7.2.0))':
|
'@babel/plugin-syntax-jsx@7.28.6(@babel/core@7.29.0)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/core': 7.29.0(supports-color@7.2.0)
|
'@babel/core': 7.29.0
|
||||||
'@babel/helper-plugin-utils': 7.28.6
|
'@babel/helper-plugin-utils': 7.28.6
|
||||||
|
|
||||||
'@babel/plugin-syntax-typescript@7.28.6(@babel/core@7.29.0(supports-color@7.2.0))':
|
'@babel/plugin-syntax-typescript@7.28.6(@babel/core@7.29.0)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/core': 7.29.0(supports-color@7.2.0)
|
'@babel/core': 7.29.0
|
||||||
'@babel/helper-plugin-utils': 7.28.6
|
'@babel/helper-plugin-utils': 7.28.6
|
||||||
|
|
||||||
'@babel/plugin-transform-modules-commonjs@7.28.6(@babel/core@7.29.0(supports-color@7.2.0))(supports-color@7.2.0)':
|
'@babel/plugin-transform-modules-commonjs@7.28.6(@babel/core@7.29.0)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/core': 7.29.0(supports-color@7.2.0)
|
'@babel/core': 7.29.0
|
||||||
'@babel/helper-module-transforms': 7.28.6(@babel/core@7.29.0(supports-color@7.2.0))(supports-color@7.2.0)
|
'@babel/helper-module-transforms': 7.28.6(@babel/core@7.29.0)
|
||||||
'@babel/helper-plugin-utils': 7.28.6
|
'@babel/helper-plugin-utils': 7.28.6
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
'@babel/plugin-transform-typescript@7.28.6(@babel/core@7.29.0(supports-color@7.2.0))(supports-color@7.2.0)':
|
'@babel/plugin-transform-typescript@7.28.6(@babel/core@7.29.0)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/core': 7.29.0(supports-color@7.2.0)
|
'@babel/core': 7.29.0
|
||||||
'@babel/helper-annotate-as-pure': 7.27.3
|
'@babel/helper-annotate-as-pure': 7.27.3
|
||||||
'@babel/helper-create-class-features-plugin': 7.28.6(@babel/core@7.29.0(supports-color@7.2.0))(supports-color@7.2.0)
|
'@babel/helper-create-class-features-plugin': 7.28.6(@babel/core@7.29.0)
|
||||||
'@babel/helper-plugin-utils': 7.28.6
|
'@babel/helper-plugin-utils': 7.28.6
|
||||||
'@babel/helper-skip-transparent-expression-wrappers': 7.27.1(supports-color@7.2.0)
|
'@babel/helper-skip-transparent-expression-wrappers': 7.27.1
|
||||||
'@babel/plugin-syntax-typescript': 7.28.6(@babel/core@7.29.0(supports-color@7.2.0))
|
'@babel/plugin-syntax-typescript': 7.28.6(@babel/core@7.29.0)
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
'@babel/preset-typescript@7.28.5(@babel/core@7.29.0(supports-color@7.2.0))(supports-color@7.2.0)':
|
'@babel/preset-typescript@7.28.5(@babel/core@7.29.0)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/core': 7.29.0(supports-color@7.2.0)
|
'@babel/core': 7.29.0
|
||||||
'@babel/helper-plugin-utils': 7.28.6
|
'@babel/helper-plugin-utils': 7.28.6
|
||||||
'@babel/helper-validator-option': 7.27.1
|
'@babel/helper-validator-option': 7.27.1
|
||||||
'@babel/plugin-syntax-jsx': 7.28.6(@babel/core@7.29.0(supports-color@7.2.0))
|
'@babel/plugin-syntax-jsx': 7.28.6(@babel/core@7.29.0)
|
||||||
'@babel/plugin-transform-modules-commonjs': 7.28.6(@babel/core@7.29.0(supports-color@7.2.0))(supports-color@7.2.0)
|
'@babel/plugin-transform-modules-commonjs': 7.28.6(@babel/core@7.29.0)
|
||||||
'@babel/plugin-transform-typescript': 7.28.6(@babel/core@7.29.0(supports-color@7.2.0))(supports-color@7.2.0)
|
'@babel/plugin-transform-typescript': 7.28.6(@babel/core@7.29.0)
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
|
|
@ -4092,7 +4155,7 @@ snapshots:
|
||||||
'@babel/parser': 7.29.0
|
'@babel/parser': 7.29.0
|
||||||
'@babel/types': 7.29.0
|
'@babel/types': 7.29.0
|
||||||
|
|
||||||
'@babel/traverse@7.29.0(supports-color@7.2.0)':
|
'@babel/traverse@7.29.0':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/code-frame': 7.29.0
|
'@babel/code-frame': 7.29.0
|
||||||
'@babel/generator': 7.29.1
|
'@babel/generator': 7.29.1
|
||||||
|
|
@ -4100,7 +4163,7 @@ snapshots:
|
||||||
'@babel/parser': 7.29.0
|
'@babel/parser': 7.29.0
|
||||||
'@babel/template': 7.28.6
|
'@babel/template': 7.28.6
|
||||||
'@babel/types': 7.29.0
|
'@babel/types': 7.29.0
|
||||||
debug: 4.4.3(supports-color@7.2.0)
|
debug: 4.4.3
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
|
|
@ -4109,6 +4172,44 @@ snapshots:
|
||||||
'@babel/helper-string-parser': 7.27.1
|
'@babel/helper-string-parser': 7.27.1
|
||||||
'@babel/helper-validator-identifier': 7.28.5
|
'@babel/helper-validator-identifier': 7.28.5
|
||||||
|
|
||||||
|
'@clerk/backend@3.0.1(react-dom@19.2.3(react@19.2.3))(react@19.2.3)':
|
||||||
|
dependencies:
|
||||||
|
'@clerk/shared': 4.0.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
|
||||||
|
standardwebhooks: 1.0.0
|
||||||
|
tslib: 2.8.1
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- react
|
||||||
|
- react-dom
|
||||||
|
|
||||||
|
'@clerk/nextjs@7.0.1(next@16.1.6(@babel/core@7.29.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)':
|
||||||
|
dependencies:
|
||||||
|
'@clerk/backend': 3.0.1(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
|
||||||
|
'@clerk/react': 6.0.1(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
|
||||||
|
'@clerk/shared': 4.0.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
|
||||||
|
next: 16.1.6(@babel/core@7.29.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
|
||||||
|
react: 19.2.3
|
||||||
|
react-dom: 19.2.3(react@19.2.3)
|
||||||
|
server-only: 0.0.1
|
||||||
|
tslib: 2.8.1
|
||||||
|
|
||||||
|
'@clerk/react@6.0.1(react-dom@19.2.3(react@19.2.3))(react@19.2.3)':
|
||||||
|
dependencies:
|
||||||
|
'@clerk/shared': 4.0.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
|
||||||
|
react: 19.2.3
|
||||||
|
react-dom: 19.2.3(react@19.2.3)
|
||||||
|
tslib: 2.8.1
|
||||||
|
|
||||||
|
'@clerk/shared@4.0.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3)':
|
||||||
|
dependencies:
|
||||||
|
'@tanstack/query-core': 5.90.16
|
||||||
|
dequal: 2.0.3
|
||||||
|
glob-to-regexp: 0.4.1
|
||||||
|
js-cookie: 3.0.5
|
||||||
|
std-env: 3.10.0
|
||||||
|
optionalDependencies:
|
||||||
|
react: 19.2.3
|
||||||
|
react-dom: 19.2.3(react@19.2.3)
|
||||||
|
|
||||||
'@dotenvx/dotenvx@1.52.0':
|
'@dotenvx/dotenvx@1.52.0':
|
||||||
dependencies:
|
dependencies:
|
||||||
commander: 11.1.0
|
commander: 11.1.0
|
||||||
|
|
@ -4141,17 +4242,17 @@ snapshots:
|
||||||
tslib: 2.8.1
|
tslib: 2.8.1
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@eslint-community/eslint-utils@4.9.1(eslint@9.39.3(jiti@2.6.1)(supports-color@7.2.0))':
|
'@eslint-community/eslint-utils@4.9.1(eslint@9.39.3(jiti@2.6.1))':
|
||||||
dependencies:
|
dependencies:
|
||||||
eslint: 9.39.3(jiti@2.6.1)(supports-color@7.2.0)
|
eslint: 9.39.3(jiti@2.6.1)
|
||||||
eslint-visitor-keys: 3.4.3
|
eslint-visitor-keys: 3.4.3
|
||||||
|
|
||||||
'@eslint-community/regexpp@4.12.2': {}
|
'@eslint-community/regexpp@4.12.2': {}
|
||||||
|
|
||||||
'@eslint/config-array@0.21.1(supports-color@7.2.0)':
|
'@eslint/config-array@0.21.1':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@eslint/object-schema': 2.1.7
|
'@eslint/object-schema': 2.1.7
|
||||||
debug: 4.4.3(supports-color@7.2.0)
|
debug: 4.4.3
|
||||||
minimatch: 3.1.5
|
minimatch: 3.1.5
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
@ -4164,10 +4265,10 @@ snapshots:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/json-schema': 7.0.15
|
'@types/json-schema': 7.0.15
|
||||||
|
|
||||||
'@eslint/eslintrc@3.3.4(supports-color@7.2.0)':
|
'@eslint/eslintrc@3.3.4':
|
||||||
dependencies:
|
dependencies:
|
||||||
ajv: 6.14.0
|
ajv: 6.14.0
|
||||||
debug: 4.4.3(supports-color@7.2.0)
|
debug: 4.4.3
|
||||||
espree: 10.4.0
|
espree: 10.4.0
|
||||||
globals: 14.0.0
|
globals: 14.0.0
|
||||||
ignore: 5.3.2
|
ignore: 5.3.2
|
||||||
|
|
@ -4363,7 +4464,7 @@ snapshots:
|
||||||
'@jridgewell/resolve-uri': 3.1.2
|
'@jridgewell/resolve-uri': 3.1.2
|
||||||
'@jridgewell/sourcemap-codec': 1.5.5
|
'@jridgewell/sourcemap-codec': 1.5.5
|
||||||
|
|
||||||
'@modelcontextprotocol/sdk@1.27.1(supports-color@7.2.0)(zod@3.25.76)':
|
'@modelcontextprotocol/sdk@1.27.1(zod@3.25.76)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@hono/node-server': 1.19.11(hono@4.12.5)
|
'@hono/node-server': 1.19.11(hono@4.12.5)
|
||||||
ajv: 8.18.0
|
ajv: 8.18.0
|
||||||
|
|
@ -4373,8 +4474,8 @@ snapshots:
|
||||||
cross-spawn: 7.0.6
|
cross-spawn: 7.0.6
|
||||||
eventsource: 3.0.7
|
eventsource: 3.0.7
|
||||||
eventsource-parser: 3.0.6
|
eventsource-parser: 3.0.6
|
||||||
express: 5.2.1(supports-color@7.2.0)
|
express: 5.2.1
|
||||||
express-rate-limit: 8.2.1(express@5.2.1(supports-color@7.2.0))
|
express-rate-limit: 8.2.1(express@5.2.1)
|
||||||
hono: 4.12.5
|
hono: 4.12.5
|
||||||
jose: 6.2.0
|
jose: 6.2.0
|
||||||
json-schema-typed: 8.0.2
|
json-schema-typed: 8.0.2
|
||||||
|
|
@ -5227,6 +5328,8 @@ snapshots:
|
||||||
|
|
||||||
'@sindresorhus/merge-streams@4.0.0': {}
|
'@sindresorhus/merge-streams@4.0.0': {}
|
||||||
|
|
||||||
|
'@stablelib/base64@1.0.1': {}
|
||||||
|
|
||||||
'@standard-schema/spec@1.1.0': {}
|
'@standard-schema/spec@1.1.0': {}
|
||||||
|
|
||||||
'@standard-schema/utils@0.3.0': {}
|
'@standard-schema/utils@0.3.0': {}
|
||||||
|
|
@ -5304,6 +5407,8 @@ snapshots:
|
||||||
postcss: 8.5.8
|
postcss: 8.5.8
|
||||||
tailwindcss: 4.2.1
|
tailwindcss: 4.2.1
|
||||||
|
|
||||||
|
'@tanstack/query-core@5.90.16': {}
|
||||||
|
|
||||||
'@ts-morph/common@0.27.0':
|
'@ts-morph/common@0.27.0':
|
||||||
dependencies:
|
dependencies:
|
||||||
fast-glob: 3.3.3
|
fast-glob: 3.3.3
|
||||||
|
|
@ -5363,15 +5468,15 @@ snapshots:
|
||||||
|
|
||||||
'@types/validate-npm-package-name@4.0.2': {}
|
'@types/validate-npm-package-name@4.0.2': {}
|
||||||
|
|
||||||
'@typescript-eslint/eslint-plugin@8.56.1(@typescript-eslint/parser@8.56.1(eslint@9.39.3(jiti@2.6.1)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3))(eslint@9.39.3(jiti@2.6.1)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3)':
|
'@typescript-eslint/eslint-plugin@8.56.1(@typescript-eslint/parser@8.56.1(eslint@9.39.3(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.3(jiti@2.6.1))(typescript@5.9.3)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@eslint-community/regexpp': 4.12.2
|
'@eslint-community/regexpp': 4.12.2
|
||||||
'@typescript-eslint/parser': 8.56.1(eslint@9.39.3(jiti@2.6.1)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3)
|
'@typescript-eslint/parser': 8.56.1(eslint@9.39.3(jiti@2.6.1))(typescript@5.9.3)
|
||||||
'@typescript-eslint/scope-manager': 8.56.1
|
'@typescript-eslint/scope-manager': 8.56.1
|
||||||
'@typescript-eslint/type-utils': 8.56.1(eslint@9.39.3(jiti@2.6.1)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3)
|
'@typescript-eslint/type-utils': 8.56.1(eslint@9.39.3(jiti@2.6.1))(typescript@5.9.3)
|
||||||
'@typescript-eslint/utils': 8.56.1(eslint@9.39.3(jiti@2.6.1)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3)
|
'@typescript-eslint/utils': 8.56.1(eslint@9.39.3(jiti@2.6.1))(typescript@5.9.3)
|
||||||
'@typescript-eslint/visitor-keys': 8.56.1
|
'@typescript-eslint/visitor-keys': 8.56.1
|
||||||
eslint: 9.39.3(jiti@2.6.1)(supports-color@7.2.0)
|
eslint: 9.39.3(jiti@2.6.1)
|
||||||
ignore: 7.0.5
|
ignore: 7.0.5
|
||||||
natural-compare: 1.4.0
|
natural-compare: 1.4.0
|
||||||
ts-api-utils: 2.4.0(typescript@5.9.3)
|
ts-api-utils: 2.4.0(typescript@5.9.3)
|
||||||
|
|
@ -5379,23 +5484,23 @@ snapshots:
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
'@typescript-eslint/parser@8.56.1(eslint@9.39.3(jiti@2.6.1)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3)':
|
'@typescript-eslint/parser@8.56.1(eslint@9.39.3(jiti@2.6.1))(typescript@5.9.3)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@typescript-eslint/scope-manager': 8.56.1
|
'@typescript-eslint/scope-manager': 8.56.1
|
||||||
'@typescript-eslint/types': 8.56.1
|
'@typescript-eslint/types': 8.56.1
|
||||||
'@typescript-eslint/typescript-estree': 8.56.1(supports-color@7.2.0)(typescript@5.9.3)
|
'@typescript-eslint/typescript-estree': 8.56.1(typescript@5.9.3)
|
||||||
'@typescript-eslint/visitor-keys': 8.56.1
|
'@typescript-eslint/visitor-keys': 8.56.1
|
||||||
debug: 4.4.3(supports-color@7.2.0)
|
debug: 4.4.3
|
||||||
eslint: 9.39.3(jiti@2.6.1)(supports-color@7.2.0)
|
eslint: 9.39.3(jiti@2.6.1)
|
||||||
typescript: 5.9.3
|
typescript: 5.9.3
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
'@typescript-eslint/project-service@8.56.1(supports-color@7.2.0)(typescript@5.9.3)':
|
'@typescript-eslint/project-service@8.56.1(typescript@5.9.3)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@typescript-eslint/tsconfig-utils': 8.56.1(typescript@5.9.3)
|
'@typescript-eslint/tsconfig-utils': 8.56.1(typescript@5.9.3)
|
||||||
'@typescript-eslint/types': 8.56.1
|
'@typescript-eslint/types': 8.56.1
|
||||||
debug: 4.4.3(supports-color@7.2.0)
|
debug: 4.4.3
|
||||||
typescript: 5.9.3
|
typescript: 5.9.3
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
@ -5409,13 +5514,13 @@ snapshots:
|
||||||
dependencies:
|
dependencies:
|
||||||
typescript: 5.9.3
|
typescript: 5.9.3
|
||||||
|
|
||||||
'@typescript-eslint/type-utils@8.56.1(eslint@9.39.3(jiti@2.6.1)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3)':
|
'@typescript-eslint/type-utils@8.56.1(eslint@9.39.3(jiti@2.6.1))(typescript@5.9.3)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@typescript-eslint/types': 8.56.1
|
'@typescript-eslint/types': 8.56.1
|
||||||
'@typescript-eslint/typescript-estree': 8.56.1(supports-color@7.2.0)(typescript@5.9.3)
|
'@typescript-eslint/typescript-estree': 8.56.1(typescript@5.9.3)
|
||||||
'@typescript-eslint/utils': 8.56.1(eslint@9.39.3(jiti@2.6.1)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3)
|
'@typescript-eslint/utils': 8.56.1(eslint@9.39.3(jiti@2.6.1))(typescript@5.9.3)
|
||||||
debug: 4.4.3(supports-color@7.2.0)
|
debug: 4.4.3
|
||||||
eslint: 9.39.3(jiti@2.6.1)(supports-color@7.2.0)
|
eslint: 9.39.3(jiti@2.6.1)
|
||||||
ts-api-utils: 2.4.0(typescript@5.9.3)
|
ts-api-utils: 2.4.0(typescript@5.9.3)
|
||||||
typescript: 5.9.3
|
typescript: 5.9.3
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
|
|
@ -5423,13 +5528,13 @@ snapshots:
|
||||||
|
|
||||||
'@typescript-eslint/types@8.56.1': {}
|
'@typescript-eslint/types@8.56.1': {}
|
||||||
|
|
||||||
'@typescript-eslint/typescript-estree@8.56.1(supports-color@7.2.0)(typescript@5.9.3)':
|
'@typescript-eslint/typescript-estree@8.56.1(typescript@5.9.3)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@typescript-eslint/project-service': 8.56.1(supports-color@7.2.0)(typescript@5.9.3)
|
'@typescript-eslint/project-service': 8.56.1(typescript@5.9.3)
|
||||||
'@typescript-eslint/tsconfig-utils': 8.56.1(typescript@5.9.3)
|
'@typescript-eslint/tsconfig-utils': 8.56.1(typescript@5.9.3)
|
||||||
'@typescript-eslint/types': 8.56.1
|
'@typescript-eslint/types': 8.56.1
|
||||||
'@typescript-eslint/visitor-keys': 8.56.1
|
'@typescript-eslint/visitor-keys': 8.56.1
|
||||||
debug: 4.4.3(supports-color@7.2.0)
|
debug: 4.4.3
|
||||||
minimatch: 10.2.4
|
minimatch: 10.2.4
|
||||||
semver: 7.7.4
|
semver: 7.7.4
|
||||||
tinyglobby: 0.2.15
|
tinyglobby: 0.2.15
|
||||||
|
|
@ -5438,13 +5543,13 @@ snapshots:
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
'@typescript-eslint/utils@8.56.1(eslint@9.39.3(jiti@2.6.1)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3)':
|
'@typescript-eslint/utils@8.56.1(eslint@9.39.3(jiti@2.6.1))(typescript@5.9.3)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@eslint-community/eslint-utils': 4.9.1(eslint@9.39.3(jiti@2.6.1)(supports-color@7.2.0))
|
'@eslint-community/eslint-utils': 4.9.1(eslint@9.39.3(jiti@2.6.1))
|
||||||
'@typescript-eslint/scope-manager': 8.56.1
|
'@typescript-eslint/scope-manager': 8.56.1
|
||||||
'@typescript-eslint/types': 8.56.1
|
'@typescript-eslint/types': 8.56.1
|
||||||
'@typescript-eslint/typescript-estree': 8.56.1(supports-color@7.2.0)(typescript@5.9.3)
|
'@typescript-eslint/typescript-estree': 8.56.1(typescript@5.9.3)
|
||||||
eslint: 9.39.3(jiti@2.6.1)(supports-color@7.2.0)
|
eslint: 9.39.3(jiti@2.6.1)
|
||||||
typescript: 5.9.3
|
typescript: 5.9.3
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
@ -5651,11 +5756,11 @@ snapshots:
|
||||||
|
|
||||||
baseline-browser-mapping@2.10.0: {}
|
baseline-browser-mapping@2.10.0: {}
|
||||||
|
|
||||||
body-parser@2.2.2(supports-color@7.2.0):
|
body-parser@2.2.2:
|
||||||
dependencies:
|
dependencies:
|
||||||
bytes: 3.1.2
|
bytes: 3.1.2
|
||||||
content-type: 1.0.5
|
content-type: 1.0.5
|
||||||
debug: 4.4.3(supports-color@7.2.0)
|
debug: 4.4.3
|
||||||
http-errors: 2.0.1
|
http-errors: 2.0.1
|
||||||
iconv-lite: 0.7.2
|
iconv-lite: 0.7.2
|
||||||
on-finished: 2.4.1
|
on-finished: 2.4.1
|
||||||
|
|
@ -5852,17 +5957,13 @@ snapshots:
|
||||||
es-errors: 1.3.0
|
es-errors: 1.3.0
|
||||||
is-data-view: 1.0.2
|
is-data-view: 1.0.2
|
||||||
|
|
||||||
debug@3.2.7(supports-color@7.2.0):
|
debug@3.2.7:
|
||||||
dependencies:
|
dependencies:
|
||||||
ms: 2.1.3
|
ms: 2.1.3
|
||||||
optionalDependencies:
|
|
||||||
supports-color: 7.2.0
|
|
||||||
|
|
||||||
debug@4.4.3(supports-color@7.2.0):
|
debug@4.4.3:
|
||||||
dependencies:
|
dependencies:
|
||||||
ms: 2.1.3
|
ms: 2.1.3
|
||||||
optionalDependencies:
|
|
||||||
supports-color: 7.2.0
|
|
||||||
|
|
||||||
decimal.js-light@2.5.1: {}
|
decimal.js-light@2.5.1: {}
|
||||||
|
|
||||||
|
|
@ -5895,6 +5996,8 @@ snapshots:
|
||||||
|
|
||||||
depd@2.0.0: {}
|
depd@2.0.0: {}
|
||||||
|
|
||||||
|
dequal@2.0.3: {}
|
||||||
|
|
||||||
detect-libc@2.1.2: {}
|
detect-libc@2.1.2: {}
|
||||||
|
|
||||||
detect-node-es@1.1.0: {}
|
detect-node-es@1.1.0: {}
|
||||||
|
|
@ -6052,18 +6155,18 @@ snapshots:
|
||||||
|
|
||||||
escape-string-regexp@4.0.0: {}
|
escape-string-regexp@4.0.0: {}
|
||||||
|
|
||||||
eslint-config-next@16.1.6(@typescript-eslint/parser@8.56.1(eslint@9.39.3(jiti@2.6.1)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3))(eslint@9.39.3(jiti@2.6.1)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3):
|
eslint-config-next@16.1.6(@typescript-eslint/parser@8.56.1(eslint@9.39.3(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.3(jiti@2.6.1))(typescript@5.9.3):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@next/eslint-plugin-next': 16.1.6
|
'@next/eslint-plugin-next': 16.1.6
|
||||||
eslint: 9.39.3(jiti@2.6.1)(supports-color@7.2.0)
|
eslint: 9.39.3(jiti@2.6.1)
|
||||||
eslint-import-resolver-node: 0.3.9(supports-color@7.2.0)
|
eslint-import-resolver-node: 0.3.9
|
||||||
eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.39.3(jiti@2.6.1)(supports-color@7.2.0))(supports-color@7.2.0)
|
eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.39.3(jiti@2.6.1))
|
||||||
eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.56.1(eslint@9.39.3(jiti@2.6.1)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.3(jiti@2.6.1)(supports-color@7.2.0))(supports-color@7.2.0)
|
eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.56.1(eslint@9.39.3(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.3(jiti@2.6.1))
|
||||||
eslint-plugin-jsx-a11y: 6.10.2(eslint@9.39.3(jiti@2.6.1)(supports-color@7.2.0))
|
eslint-plugin-jsx-a11y: 6.10.2(eslint@9.39.3(jiti@2.6.1))
|
||||||
eslint-plugin-react: 7.37.5(eslint@9.39.3(jiti@2.6.1)(supports-color@7.2.0))
|
eslint-plugin-react: 7.37.5(eslint@9.39.3(jiti@2.6.1))
|
||||||
eslint-plugin-react-hooks: 7.0.1(eslint@9.39.3(jiti@2.6.1)(supports-color@7.2.0))(supports-color@7.2.0)
|
eslint-plugin-react-hooks: 7.0.1(eslint@9.39.3(jiti@2.6.1))
|
||||||
globals: 16.4.0
|
globals: 16.4.0
|
||||||
typescript-eslint: 8.56.1(eslint@9.39.3(jiti@2.6.1)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3)
|
typescript-eslint: 8.56.1(eslint@9.39.3(jiti@2.6.1))(typescript@5.9.3)
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
typescript: 5.9.3
|
typescript: 5.9.3
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
|
|
@ -6072,52 +6175,52 @@ snapshots:
|
||||||
- eslint-plugin-import-x
|
- eslint-plugin-import-x
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
eslint-import-resolver-node@0.3.9(supports-color@7.2.0):
|
eslint-import-resolver-node@0.3.9:
|
||||||
dependencies:
|
dependencies:
|
||||||
debug: 3.2.7(supports-color@7.2.0)
|
debug: 3.2.7
|
||||||
is-core-module: 2.16.1
|
is-core-module: 2.16.1
|
||||||
resolve: 1.22.11
|
resolve: 1.22.11
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0)(eslint@9.39.3(jiti@2.6.1)(supports-color@7.2.0))(supports-color@7.2.0):
|
eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0)(eslint@9.39.3(jiti@2.6.1)):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@nolyfill/is-core-module': 1.0.39
|
'@nolyfill/is-core-module': 1.0.39
|
||||||
debug: 4.4.3(supports-color@7.2.0)
|
debug: 4.4.3
|
||||||
eslint: 9.39.3(jiti@2.6.1)(supports-color@7.2.0)
|
eslint: 9.39.3(jiti@2.6.1)
|
||||||
get-tsconfig: 4.13.6
|
get-tsconfig: 4.13.6
|
||||||
is-bun-module: 2.0.0
|
is-bun-module: 2.0.0
|
||||||
stable-hash: 0.0.5
|
stable-hash: 0.0.5
|
||||||
tinyglobby: 0.2.15
|
tinyglobby: 0.2.15
|
||||||
unrs-resolver: 1.11.1
|
unrs-resolver: 1.11.1
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.56.1(eslint@9.39.3(jiti@2.6.1)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.3(jiti@2.6.1)(supports-color@7.2.0))(supports-color@7.2.0)
|
eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.56.1(eslint@9.39.3(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.3(jiti@2.6.1))
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
eslint-module-utils@2.12.1(@typescript-eslint/parser@8.56.1(eslint@9.39.3(jiti@2.6.1)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3))(eslint-import-resolver-node@0.3.9(supports-color@7.2.0))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.3(jiti@2.6.1)(supports-color@7.2.0))(supports-color@7.2.0):
|
eslint-module-utils@2.12.1(@typescript-eslint/parser@8.56.1(eslint@9.39.3(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.3(jiti@2.6.1)):
|
||||||
dependencies:
|
dependencies:
|
||||||
debug: 3.2.7(supports-color@7.2.0)
|
debug: 3.2.7
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
'@typescript-eslint/parser': 8.56.1(eslint@9.39.3(jiti@2.6.1)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3)
|
'@typescript-eslint/parser': 8.56.1(eslint@9.39.3(jiti@2.6.1))(typescript@5.9.3)
|
||||||
eslint: 9.39.3(jiti@2.6.1)(supports-color@7.2.0)
|
eslint: 9.39.3(jiti@2.6.1)
|
||||||
eslint-import-resolver-node: 0.3.9(supports-color@7.2.0)
|
eslint-import-resolver-node: 0.3.9
|
||||||
eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.39.3(jiti@2.6.1)(supports-color@7.2.0))(supports-color@7.2.0)
|
eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.39.3(jiti@2.6.1))
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.56.1(eslint@9.39.3(jiti@2.6.1)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.3(jiti@2.6.1)(supports-color@7.2.0))(supports-color@7.2.0):
|
eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.56.1(eslint@9.39.3(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.3(jiti@2.6.1)):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@rtsao/scc': 1.1.0
|
'@rtsao/scc': 1.1.0
|
||||||
array-includes: 3.1.9
|
array-includes: 3.1.9
|
||||||
array.prototype.findlastindex: 1.2.6
|
array.prototype.findlastindex: 1.2.6
|
||||||
array.prototype.flat: 1.3.3
|
array.prototype.flat: 1.3.3
|
||||||
array.prototype.flatmap: 1.3.3
|
array.prototype.flatmap: 1.3.3
|
||||||
debug: 3.2.7(supports-color@7.2.0)
|
debug: 3.2.7
|
||||||
doctrine: 2.1.0
|
doctrine: 2.1.0
|
||||||
eslint: 9.39.3(jiti@2.6.1)(supports-color@7.2.0)
|
eslint: 9.39.3(jiti@2.6.1)
|
||||||
eslint-import-resolver-node: 0.3.9(supports-color@7.2.0)
|
eslint-import-resolver-node: 0.3.9
|
||||||
eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.56.1(eslint@9.39.3(jiti@2.6.1)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3))(eslint-import-resolver-node@0.3.9(supports-color@7.2.0))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.3(jiti@2.6.1)(supports-color@7.2.0))(supports-color@7.2.0)
|
eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.56.1(eslint@9.39.3(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.3(jiti@2.6.1))
|
||||||
hasown: 2.0.2
|
hasown: 2.0.2
|
||||||
is-core-module: 2.16.1
|
is-core-module: 2.16.1
|
||||||
is-glob: 4.0.3
|
is-glob: 4.0.3
|
||||||
|
|
@ -6129,13 +6232,13 @@ snapshots:
|
||||||
string.prototype.trimend: 1.0.9
|
string.prototype.trimend: 1.0.9
|
||||||
tsconfig-paths: 3.15.0
|
tsconfig-paths: 3.15.0
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
'@typescript-eslint/parser': 8.56.1(eslint@9.39.3(jiti@2.6.1)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3)
|
'@typescript-eslint/parser': 8.56.1(eslint@9.39.3(jiti@2.6.1))(typescript@5.9.3)
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- eslint-import-resolver-typescript
|
- eslint-import-resolver-typescript
|
||||||
- eslint-import-resolver-webpack
|
- eslint-import-resolver-webpack
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
eslint-plugin-jsx-a11y@6.10.2(eslint@9.39.3(jiti@2.6.1)(supports-color@7.2.0)):
|
eslint-plugin-jsx-a11y@6.10.2(eslint@9.39.3(jiti@2.6.1)):
|
||||||
dependencies:
|
dependencies:
|
||||||
aria-query: 5.3.2
|
aria-query: 5.3.2
|
||||||
array-includes: 3.1.9
|
array-includes: 3.1.9
|
||||||
|
|
@ -6145,7 +6248,7 @@ snapshots:
|
||||||
axobject-query: 4.1.0
|
axobject-query: 4.1.0
|
||||||
damerau-levenshtein: 1.0.8
|
damerau-levenshtein: 1.0.8
|
||||||
emoji-regex: 9.2.2
|
emoji-regex: 9.2.2
|
||||||
eslint: 9.39.3(jiti@2.6.1)(supports-color@7.2.0)
|
eslint: 9.39.3(jiti@2.6.1)
|
||||||
hasown: 2.0.2
|
hasown: 2.0.2
|
||||||
jsx-ast-utils: 3.3.5
|
jsx-ast-utils: 3.3.5
|
||||||
language-tags: 1.0.9
|
language-tags: 1.0.9
|
||||||
|
|
@ -6154,18 +6257,18 @@ snapshots:
|
||||||
safe-regex-test: 1.1.0
|
safe-regex-test: 1.1.0
|
||||||
string.prototype.includes: 2.0.1
|
string.prototype.includes: 2.0.1
|
||||||
|
|
||||||
eslint-plugin-react-hooks@7.0.1(eslint@9.39.3(jiti@2.6.1)(supports-color@7.2.0))(supports-color@7.2.0):
|
eslint-plugin-react-hooks@7.0.1(eslint@9.39.3(jiti@2.6.1)):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/core': 7.29.0(supports-color@7.2.0)
|
'@babel/core': 7.29.0
|
||||||
'@babel/parser': 7.29.0
|
'@babel/parser': 7.29.0
|
||||||
eslint: 9.39.3(jiti@2.6.1)(supports-color@7.2.0)
|
eslint: 9.39.3(jiti@2.6.1)
|
||||||
hermes-parser: 0.25.1
|
hermes-parser: 0.25.1
|
||||||
zod: 4.3.6
|
zod: 4.3.6
|
||||||
zod-validation-error: 4.0.2(zod@4.3.6)
|
zod-validation-error: 4.0.2(zod@4.3.6)
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
eslint-plugin-react@7.37.5(eslint@9.39.3(jiti@2.6.1)(supports-color@7.2.0)):
|
eslint-plugin-react@7.37.5(eslint@9.39.3(jiti@2.6.1)):
|
||||||
dependencies:
|
dependencies:
|
||||||
array-includes: 3.1.9
|
array-includes: 3.1.9
|
||||||
array.prototype.findlast: 1.2.5
|
array.prototype.findlast: 1.2.5
|
||||||
|
|
@ -6173,7 +6276,7 @@ snapshots:
|
||||||
array.prototype.tosorted: 1.1.4
|
array.prototype.tosorted: 1.1.4
|
||||||
doctrine: 2.1.0
|
doctrine: 2.1.0
|
||||||
es-iterator-helpers: 1.2.2
|
es-iterator-helpers: 1.2.2
|
||||||
eslint: 9.39.3(jiti@2.6.1)(supports-color@7.2.0)
|
eslint: 9.39.3(jiti@2.6.1)
|
||||||
estraverse: 5.3.0
|
estraverse: 5.3.0
|
||||||
hasown: 2.0.2
|
hasown: 2.0.2
|
||||||
jsx-ast-utils: 3.3.5
|
jsx-ast-utils: 3.3.5
|
||||||
|
|
@ -6198,14 +6301,14 @@ snapshots:
|
||||||
|
|
||||||
eslint-visitor-keys@5.0.1: {}
|
eslint-visitor-keys@5.0.1: {}
|
||||||
|
|
||||||
eslint@9.39.3(jiti@2.6.1)(supports-color@7.2.0):
|
eslint@9.39.3(jiti@2.6.1):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@eslint-community/eslint-utils': 4.9.1(eslint@9.39.3(jiti@2.6.1)(supports-color@7.2.0))
|
'@eslint-community/eslint-utils': 4.9.1(eslint@9.39.3(jiti@2.6.1))
|
||||||
'@eslint-community/regexpp': 4.12.2
|
'@eslint-community/regexpp': 4.12.2
|
||||||
'@eslint/config-array': 0.21.1(supports-color@7.2.0)
|
'@eslint/config-array': 0.21.1
|
||||||
'@eslint/config-helpers': 0.4.2
|
'@eslint/config-helpers': 0.4.2
|
||||||
'@eslint/core': 0.17.0
|
'@eslint/core': 0.17.0
|
||||||
'@eslint/eslintrc': 3.3.4(supports-color@7.2.0)
|
'@eslint/eslintrc': 3.3.4
|
||||||
'@eslint/js': 9.39.3
|
'@eslint/js': 9.39.3
|
||||||
'@eslint/plugin-kit': 0.4.1
|
'@eslint/plugin-kit': 0.4.1
|
||||||
'@humanfs/node': 0.16.7
|
'@humanfs/node': 0.16.7
|
||||||
|
|
@ -6215,7 +6318,7 @@ snapshots:
|
||||||
ajv: 6.14.0
|
ajv: 6.14.0
|
||||||
chalk: 4.1.2
|
chalk: 4.1.2
|
||||||
cross-spawn: 7.0.6
|
cross-spawn: 7.0.6
|
||||||
debug: 4.4.3(supports-color@7.2.0)
|
debug: 4.4.3
|
||||||
escape-string-regexp: 4.0.0
|
escape-string-regexp: 4.0.0
|
||||||
eslint-scope: 8.4.0
|
eslint-scope: 8.4.0
|
||||||
eslint-visitor-keys: 4.2.1
|
eslint-visitor-keys: 4.2.1
|
||||||
|
|
@ -6296,25 +6399,25 @@ snapshots:
|
||||||
strip-final-newline: 4.0.0
|
strip-final-newline: 4.0.0
|
||||||
yoctocolors: 2.1.2
|
yoctocolors: 2.1.2
|
||||||
|
|
||||||
express-rate-limit@8.2.1(express@5.2.1(supports-color@7.2.0)):
|
express-rate-limit@8.2.1(express@5.2.1):
|
||||||
dependencies:
|
dependencies:
|
||||||
express: 5.2.1(supports-color@7.2.0)
|
express: 5.2.1
|
||||||
ip-address: 10.0.1
|
ip-address: 10.0.1
|
||||||
|
|
||||||
express@5.2.1(supports-color@7.2.0):
|
express@5.2.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
accepts: 2.0.0
|
accepts: 2.0.0
|
||||||
body-parser: 2.2.2(supports-color@7.2.0)
|
body-parser: 2.2.2
|
||||||
content-disposition: 1.0.1
|
content-disposition: 1.0.1
|
||||||
content-type: 1.0.5
|
content-type: 1.0.5
|
||||||
cookie: 0.7.2
|
cookie: 0.7.2
|
||||||
cookie-signature: 1.2.2
|
cookie-signature: 1.2.2
|
||||||
debug: 4.4.3(supports-color@7.2.0)
|
debug: 4.4.3
|
||||||
depd: 2.0.0
|
depd: 2.0.0
|
||||||
encodeurl: 2.0.0
|
encodeurl: 2.0.0
|
||||||
escape-html: 1.0.3
|
escape-html: 1.0.3
|
||||||
etag: 1.8.1
|
etag: 1.8.1
|
||||||
finalhandler: 2.1.1(supports-color@7.2.0)
|
finalhandler: 2.1.1
|
||||||
fresh: 2.0.0
|
fresh: 2.0.0
|
||||||
http-errors: 2.0.1
|
http-errors: 2.0.1
|
||||||
merge-descriptors: 2.0.0
|
merge-descriptors: 2.0.0
|
||||||
|
|
@ -6325,9 +6428,9 @@ snapshots:
|
||||||
proxy-addr: 2.0.7
|
proxy-addr: 2.0.7
|
||||||
qs: 6.15.0
|
qs: 6.15.0
|
||||||
range-parser: 1.2.1
|
range-parser: 1.2.1
|
||||||
router: 2.2.0(supports-color@7.2.0)
|
router: 2.2.0
|
||||||
send: 1.2.1(supports-color@7.2.0)
|
send: 1.2.1
|
||||||
serve-static: 2.2.1(supports-color@7.2.0)
|
serve-static: 2.2.1
|
||||||
statuses: 2.0.2
|
statuses: 2.0.2
|
||||||
type-is: 2.0.1
|
type-is: 2.0.1
|
||||||
vary: 1.1.2
|
vary: 1.1.2
|
||||||
|
|
@ -6356,6 +6459,8 @@ snapshots:
|
||||||
|
|
||||||
fast-levenshtein@2.0.6: {}
|
fast-levenshtein@2.0.6: {}
|
||||||
|
|
||||||
|
fast-sha256@1.3.0: {}
|
||||||
|
|
||||||
fast-uri@3.1.0: {}
|
fast-uri@3.1.0: {}
|
||||||
|
|
||||||
fastq@1.20.1:
|
fastq@1.20.1:
|
||||||
|
|
@ -6383,9 +6488,9 @@ snapshots:
|
||||||
dependencies:
|
dependencies:
|
||||||
to-regex-range: 5.0.1
|
to-regex-range: 5.0.1
|
||||||
|
|
||||||
finalhandler@2.1.1(supports-color@7.2.0):
|
finalhandler@2.1.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
debug: 4.4.3(supports-color@7.2.0)
|
debug: 4.4.3
|
||||||
encodeurl: 2.0.0
|
encodeurl: 2.0.0
|
||||||
escape-html: 1.0.3
|
escape-html: 1.0.3
|
||||||
on-finished: 2.4.1
|
on-finished: 2.4.1
|
||||||
|
|
@ -6496,6 +6601,8 @@ snapshots:
|
||||||
dependencies:
|
dependencies:
|
||||||
is-glob: 4.0.3
|
is-glob: 4.0.3
|
||||||
|
|
||||||
|
glob-to-regexp@0.4.1: {}
|
||||||
|
|
||||||
globals@14.0.0: {}
|
globals@14.0.0: {}
|
||||||
|
|
||||||
globals@16.4.0: {}
|
globals@16.4.0: {}
|
||||||
|
|
@ -6551,10 +6658,10 @@ snapshots:
|
||||||
statuses: 2.0.2
|
statuses: 2.0.2
|
||||||
toidentifier: 1.0.1
|
toidentifier: 1.0.1
|
||||||
|
|
||||||
https-proxy-agent@7.0.6(supports-color@7.2.0):
|
https-proxy-agent@7.0.6:
|
||||||
dependencies:
|
dependencies:
|
||||||
agent-base: 7.1.4
|
agent-base: 7.1.4
|
||||||
debug: 4.4.3(supports-color@7.2.0)
|
debug: 4.4.3
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
|
|
@ -6762,6 +6869,8 @@ snapshots:
|
||||||
|
|
||||||
jose@6.2.0: {}
|
jose@6.2.0: {}
|
||||||
|
|
||||||
|
js-cookie@3.0.5: {}
|
||||||
|
|
||||||
js-tokens@4.0.0: {}
|
js-tokens@4.0.0: {}
|
||||||
|
|
||||||
js-yaml@4.1.1:
|
js-yaml@4.1.1:
|
||||||
|
|
@ -6975,7 +7084,7 @@ snapshots:
|
||||||
react: 19.2.3
|
react: 19.2.3
|
||||||
react-dom: 19.2.3(react@19.2.3)
|
react-dom: 19.2.3(react@19.2.3)
|
||||||
|
|
||||||
next@16.1.6(@babel/core@7.29.0(supports-color@7.2.0))(react-dom@19.2.3(react@19.2.3))(react@19.2.3):
|
next@16.1.6(@babel/core@7.29.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@next/env': 16.1.6
|
'@next/env': 16.1.6
|
||||||
'@swc/helpers': 0.5.15
|
'@swc/helpers': 0.5.15
|
||||||
|
|
@ -6984,7 +7093,7 @@ snapshots:
|
||||||
postcss: 8.4.31
|
postcss: 8.4.31
|
||||||
react: 19.2.3
|
react: 19.2.3
|
||||||
react-dom: 19.2.3(react@19.2.3)
|
react-dom: 19.2.3(react@19.2.3)
|
||||||
styled-jsx: 5.1.6(@babel/core@7.29.0(supports-color@7.2.0))(react@19.2.3)
|
styled-jsx: 5.1.6(@babel/core@7.29.0)(react@19.2.3)
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
'@next/swc-darwin-arm64': 16.1.6
|
'@next/swc-darwin-arm64': 16.1.6
|
||||||
'@next/swc-darwin-x64': 16.1.6
|
'@next/swc-darwin-x64': 16.1.6
|
||||||
|
|
@ -7431,9 +7540,9 @@ snapshots:
|
||||||
|
|
||||||
reusify@1.1.0: {}
|
reusify@1.1.0: {}
|
||||||
|
|
||||||
router@2.2.0(supports-color@7.2.0):
|
router@2.2.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
debug: 4.4.3(supports-color@7.2.0)
|
debug: 4.4.3
|
||||||
depd: 2.0.0
|
depd: 2.0.0
|
||||||
is-promise: 4.0.0
|
is-promise: 4.0.0
|
||||||
parseurl: 1.3.3
|
parseurl: 1.3.3
|
||||||
|
|
@ -7474,9 +7583,9 @@ snapshots:
|
||||||
|
|
||||||
semver@7.7.4: {}
|
semver@7.7.4: {}
|
||||||
|
|
||||||
send@1.2.1(supports-color@7.2.0):
|
send@1.2.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
debug: 4.4.3(supports-color@7.2.0)
|
debug: 4.4.3
|
||||||
encodeurl: 2.0.0
|
encodeurl: 2.0.0
|
||||||
escape-html: 1.0.3
|
escape-html: 1.0.3
|
||||||
etag: 1.8.1
|
etag: 1.8.1
|
||||||
|
|
@ -7490,15 +7599,17 @@ snapshots:
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
serve-static@2.2.1(supports-color@7.2.0):
|
serve-static@2.2.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
encodeurl: 2.0.0
|
encodeurl: 2.0.0
|
||||||
escape-html: 1.0.3
|
escape-html: 1.0.3
|
||||||
parseurl: 1.3.3
|
parseurl: 1.3.3
|
||||||
send: 1.2.1(supports-color@7.2.0)
|
send: 1.2.1
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
|
server-only@0.0.1: {}
|
||||||
|
|
||||||
set-function-length@1.2.2:
|
set-function-length@1.2.2:
|
||||||
dependencies:
|
dependencies:
|
||||||
define-data-property: 1.1.4
|
define-data-property: 1.1.4
|
||||||
|
|
@ -7523,15 +7634,15 @@ snapshots:
|
||||||
|
|
||||||
setprototypeof@1.2.0: {}
|
setprototypeof@1.2.0: {}
|
||||||
|
|
||||||
shadcn@3.8.5(@types/node@20.19.35)(supports-color@7.2.0)(typescript@5.9.3):
|
shadcn@3.8.5(@types/node@20.19.35)(typescript@5.9.3):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@antfu/ni': 25.0.0
|
'@antfu/ni': 25.0.0
|
||||||
'@babel/core': 7.29.0(supports-color@7.2.0)
|
'@babel/core': 7.29.0
|
||||||
'@babel/parser': 7.29.0
|
'@babel/parser': 7.29.0
|
||||||
'@babel/plugin-transform-typescript': 7.28.6(@babel/core@7.29.0(supports-color@7.2.0))(supports-color@7.2.0)
|
'@babel/plugin-transform-typescript': 7.28.6(@babel/core@7.29.0)
|
||||||
'@babel/preset-typescript': 7.28.5(@babel/core@7.29.0(supports-color@7.2.0))(supports-color@7.2.0)
|
'@babel/preset-typescript': 7.28.5(@babel/core@7.29.0)
|
||||||
'@dotenvx/dotenvx': 1.52.0
|
'@dotenvx/dotenvx': 1.52.0
|
||||||
'@modelcontextprotocol/sdk': 1.27.1(supports-color@7.2.0)(zod@3.25.76)
|
'@modelcontextprotocol/sdk': 1.27.1(zod@3.25.76)
|
||||||
'@types/validate-npm-package-name': 4.0.2
|
'@types/validate-npm-package-name': 4.0.2
|
||||||
browserslist: 4.28.1
|
browserslist: 4.28.1
|
||||||
commander: 14.0.3
|
commander: 14.0.3
|
||||||
|
|
@ -7543,7 +7654,7 @@ snapshots:
|
||||||
fast-glob: 3.3.3
|
fast-glob: 3.3.3
|
||||||
fs-extra: 11.3.4
|
fs-extra: 11.3.4
|
||||||
fuzzysort: 3.1.0
|
fuzzysort: 3.1.0
|
||||||
https-proxy-agent: 7.0.6(supports-color@7.2.0)
|
https-proxy-agent: 7.0.6
|
||||||
kleur: 4.1.5
|
kleur: 4.1.5
|
||||||
msw: 2.12.10(@types/node@20.19.35)(typescript@5.9.3)
|
msw: 2.12.10(@types/node@20.19.35)(typescript@5.9.3)
|
||||||
node-fetch: 3.3.2
|
node-fetch: 3.3.2
|
||||||
|
|
@ -7650,8 +7761,15 @@ snapshots:
|
||||||
|
|
||||||
stable-hash@0.0.5: {}
|
stable-hash@0.0.5: {}
|
||||||
|
|
||||||
|
standardwebhooks@1.0.0:
|
||||||
|
dependencies:
|
||||||
|
'@stablelib/base64': 1.0.1
|
||||||
|
fast-sha256: 1.3.0
|
||||||
|
|
||||||
statuses@2.0.2: {}
|
statuses@2.0.2: {}
|
||||||
|
|
||||||
|
std-env@3.10.0: {}
|
||||||
|
|
||||||
stdin-discarder@0.2.2: {}
|
stdin-discarder@0.2.2: {}
|
||||||
|
|
||||||
stop-iteration-iterator@1.1.0:
|
stop-iteration-iterator@1.1.0:
|
||||||
|
|
@ -7745,12 +7863,12 @@ snapshots:
|
||||||
|
|
||||||
strip-json-comments@3.1.1: {}
|
strip-json-comments@3.1.1: {}
|
||||||
|
|
||||||
styled-jsx@5.1.6(@babel/core@7.29.0(supports-color@7.2.0))(react@19.2.3):
|
styled-jsx@5.1.6(@babel/core@7.29.0)(react@19.2.3):
|
||||||
dependencies:
|
dependencies:
|
||||||
client-only: 0.0.1
|
client-only: 0.0.1
|
||||||
react: 19.2.3
|
react: 19.2.3
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
'@babel/core': 7.29.0(supports-color@7.2.0)
|
'@babel/core': 7.29.0
|
||||||
|
|
||||||
supports-color@7.2.0:
|
supports-color@7.2.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
|
|
@ -7864,13 +7982,13 @@ snapshots:
|
||||||
possible-typed-array-names: 1.1.0
|
possible-typed-array-names: 1.1.0
|
||||||
reflect.getprototypeof: 1.0.10
|
reflect.getprototypeof: 1.0.10
|
||||||
|
|
||||||
typescript-eslint@8.56.1(eslint@9.39.3(jiti@2.6.1)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3):
|
typescript-eslint@8.56.1(eslint@9.39.3(jiti@2.6.1))(typescript@5.9.3):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@typescript-eslint/eslint-plugin': 8.56.1(@typescript-eslint/parser@8.56.1(eslint@9.39.3(jiti@2.6.1)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3))(eslint@9.39.3(jiti@2.6.1)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3)
|
'@typescript-eslint/eslint-plugin': 8.56.1(@typescript-eslint/parser@8.56.1(eslint@9.39.3(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.3(jiti@2.6.1))(typescript@5.9.3)
|
||||||
'@typescript-eslint/parser': 8.56.1(eslint@9.39.3(jiti@2.6.1)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3)
|
'@typescript-eslint/parser': 8.56.1(eslint@9.39.3(jiti@2.6.1))(typescript@5.9.3)
|
||||||
'@typescript-eslint/typescript-estree': 8.56.1(supports-color@7.2.0)(typescript@5.9.3)
|
'@typescript-eslint/typescript-estree': 8.56.1(typescript@5.9.3)
|
||||||
'@typescript-eslint/utils': 8.56.1(eslint@9.39.3(jiti@2.6.1)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3)
|
'@typescript-eslint/utils': 8.56.1(eslint@9.39.3(jiti@2.6.1))(typescript@5.9.3)
|
||||||
eslint: 9.39.3(jiti@2.6.1)(supports-color@7.2.0)
|
eslint: 9.39.3(jiti@2.6.1)
|
||||||
typescript: 5.9.3
|
typescript: 5.9.3
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,3 @@
|
||||||
# pnpm refuses to install (ERR_PNPM_IGNORED_BUILDS) if a dependency has a
|
|
||||||
# postinstall script that is neither approved nor explicitly declined.
|
|
||||||
#
|
|
||||||
# `allowBuilds` is the pnpm 11 spelling; `ignoredBuiltDependencies` is kept for
|
|
||||||
# pnpm 10, which does not understand `allowBuilds`. Both must list the same
|
|
||||||
# packages. None of these are needed to run `next build`:
|
|
||||||
# sharp — image-optimisation binary; unused, the app has no next/image
|
|
||||||
# unrs-resolver — native resolver for eslint-config-next (lint only)
|
|
||||||
# msw — pulled in by the `shadcn` CLI; its postinstall only writes a
|
|
||||||
# browser service worker
|
|
||||||
allowBuilds:
|
|
||||||
msw: false
|
|
||||||
sharp: false
|
|
||||||
unrs-resolver: false
|
|
||||||
|
|
||||||
ignoredBuiltDependencies:
|
ignoredBuiltDependencies:
|
||||||
- sharp
|
- sharp
|
||||||
- unrs-resolver
|
- unrs-resolver
|
||||||
- msw
|
|
||||||
|
|
|
||||||
|
|
@ -1,11 +0,0 @@
|
||||||
# Mosquitto with the broker config baked in.
|
|
||||||
#
|
|
||||||
# The compose file bind-mounts ./infra/mosquitto/mosquitto.conf, which only works
|
|
||||||
# when the repo is checked out on the Docker host. The Unraid deploy builds images
|
|
||||||
# remotely via the Portainer Docker API and has no repo on the host, so the config
|
|
||||||
# travels inside the image instead.
|
|
||||||
FROM eclipse-mosquitto:2
|
|
||||||
|
|
||||||
COPY mosquitto.conf /mosquitto/config/mosquitto.conf
|
|
||||||
|
|
||||||
EXPOSE 1883
|
|
||||||
85
memory.md
85
memory.md
|
|
@ -1,85 +0,0 @@
|
||||||
# BMS — memory
|
|
||||||
|
|
||||||
DCIM demo platform: Next.js 16 frontend, FastAPI backend, TimescaleDB, Mosquitto MQTT,
|
|
||||||
and Python simulator bots that publish fake data-centre telemetry.
|
|
||||||
|
|
||||||
Live at **http://192.168.1.249:5646/dashboard** (Portainer stack `bms` on Unraid).
|
|
||||||
|
|
||||||
## Decisions & rationale
|
|
||||||
|
|
||||||
- **Auth is disabled (demo mode).** The repo shipped half-converted: `proxy.ts` already said
|
|
||||||
"auth is disabled for demo mode", but `app/layout.tsx` still wrapped the tree in
|
|
||||||
`<ClerkProvider>` and `topbar.tsx` used `<UserButton>`. `@clerk/nextjs` v7 fails `next build`
|
|
||||||
without a real publishable key, so the frontend image could not build at all. Finished the
|
|
||||||
conversion instead of buying Clerk keys: removed `ClerkProvider`/`UserButton`, deleted the
|
|
||||||
`sign-in`/`sign-up` route groups, and dropped `@clerk/nextjs` from `package.json`. The service
|
|
||||||
is LAN-only and reachable remotely over Tailscale, so the tailnet is the auth boundary.
|
|
||||||
- **Deploy via the Portainer API, not compose-on-host.** No `docker` CLI in WSL and Unraid's
|
|
||||||
SSH (port 22) is closed, so `ops/deploy.py` tars each service's build context, POSTs it to the
|
|
||||||
remote daemon's `/build` endpoint, then pushes `docker-compose.prod.yml` as a Portainer stack.
|
|
||||||
Same pattern as `toknmtr/ops/deploy.py`.
|
|
||||||
- **Separate `docker-compose.prod.yml`.** The dev compose file bind-mounts source into the
|
|
||||||
containers and runs `uvicorn --reload` — wrong for a long-running deploy, and impossible
|
|
||||||
anyway since the repo is not checked out on the Unraid host. The prod file references
|
|
||||||
prebuilt image tags, sets env inline (no `.env` files on the host), and publishes only the
|
|
||||||
frontend's port.
|
|
||||||
- **Mosquitto config is baked into an image** (`infra/mosquitto/Dockerfile`) rather than
|
|
||||||
bind-mounted, for the same reason: no repo on the host.
|
|
||||||
- **`bms_net` pins subnet 172.31.42.0/24.** Docker's default address pools on that host are
|
|
||||||
fully subnetted — 24 existing stacks have claimed every `172.17-172.31/16` and
|
|
||||||
`192.168.x/20` slot, so auto-allocation fails with "all predefined address pools have been
|
|
||||||
fully subnetted". An explicit subnet bypasses the allocator without disturbing other stacks.
|
|
||||||
Only other 172.31 tenant is `wg0` on 172.31.200.0/24.
|
|
||||||
- **Postgres data bind-mounts to `/mnt/user/appdata/bms/db`**, not a named volume, so a
|
|
||||||
growing timeseries DB lands on the array instead of filling Unraid's fixed-size `docker.img`.
|
|
||||||
- **`pnpm-workspace.yaml` must be copied in the frontend Dockerfile's deps stage.** It carries
|
|
||||||
the build-script allowlist; without it pnpm aborts with `ERR_PNPM_IGNORED_BUILDS`. The file
|
|
||||||
now declares both `allowBuilds` (pnpm 11 spelling) and `ignoredBuiltDependencies` (pnpm 10).
|
|
||||||
`sharp`, `unrs-resolver` and `msw` are all declined — the app has no `next/image`, so sharp
|
|
||||||
is dead weight. `packageManager: pnpm@11.20.0` is pinned so a future pnpm release cannot
|
|
||||||
silently change this again.
|
|
||||||
|
|
||||||
## Open questions / TODOs
|
|
||||||
|
|
||||||
- [ ] Postgres uses the repo's default credentials (`dcim`/`dcim_pass`). Fine while the DB has
|
|
||||||
no published host port and the box is LAN-only, but change both the compose env and
|
|
||||||
`DATABASE_URL` together if the port is ever exposed.
|
|
||||||
- [ ] The simulator floods logs with `mqtt WARNING There are N pending publish calls.` — it
|
|
||||||
publishes faster than aiomqtt drains. Cosmetic, but it makes `docker logs` near-useless
|
|
||||||
and grows the log file. Worth batching or throttling the bots.
|
|
||||||
- [ ] `backend/api/routes/ws.py` exists but nothing in the frontend opens a WebSocket (the UI
|
|
||||||
polls every 15 s). Either wire it up or drop it. Note: Next.js rewrites do not proxy WS
|
|
||||||
upgrades, so a WS client would need to reach the backend directly.
|
|
||||||
- [ ] No host port is published for Postgres or MQTT. Add a `ports:` entry to
|
|
||||||
`docker-compose.prod.yml` if direct DB access or external MQTT publishing is ever needed.
|
|
||||||
- [ ] No reverse-proxy entry yet. Add an Nginx Proxy Manager host pointing at `:5646` if this
|
|
||||||
should be reachable by name rather than IP:port.
|
|
||||||
|
|
||||||
## Session log
|
|
||||||
|
|
||||||
### 2026-08-04
|
|
||||||
|
|
||||||
- Cloned the Forgejo repo into `~/claude/projects/BMS` and deployed it to the Unraid host.
|
|
||||||
- Finished the demo-mode auth conversion (see Decisions) so the frontend image could build;
|
|
||||||
regenerated `pnpm-lock.yaml` without `@clerk/nextjs`. Verified `next build` locally — all
|
|
||||||
18 routes prerender.
|
|
||||||
- Hit and fixed three deploy blockers in order: (1) the frontend Dockerfile never copied
|
|
||||||
`pnpm-workspace.yaml`, so pnpm's ignored-builds allowlist was invisible inside the build;
|
|
||||||
(2) pnpm 11 renamed that setting to `allowBuilds` and ignores `ignoredBuiltDependencies`;
|
|
||||||
(3) the Unraid daemon's Docker address pools were exhausted, so the stack network could not
|
|
||||||
be created.
|
|
||||||
- Backend's host port 8000 deliberately not published — Portainer's Edge tunnel already owns
|
|
||||||
8000 on that host. Ports 1883/5433/5646 were free; only 5646 is published.
|
|
||||||
- Added `ops/deploy.py`, `docker-compose.prod.yml`, `infra/mosquitto/Dockerfile`; updated the
|
|
||||||
README (demo-mode note, Unraid deploy section) and both `.env` examples.
|
|
||||||
- Verified live: all 5 containers healthy, 30 min of seeded history present, telemetry
|
|
||||||
flowing, alarm engine firing (55 active), dashboard screenshotted and rendering correctly.
|
|
||||||
|
|
||||||
## External references
|
|
||||||
|
|
||||||
- Repo: https://git.rdx4.com/megaproxy/BMS
|
|
||||||
- Live dashboard: http://192.168.1.249:5646/dashboard
|
|
||||||
- API docs (Swagger): http://192.168.1.249:5646/api/backend/docs
|
|
||||||
- Portainer (stack `bms`, endpoint id 3): http://192.168.1.249:9000 — token at `~/.portainer-token`
|
|
||||||
- Postgres data on the host: `/mnt/user/appdata/bms/db`
|
|
||||||
- Deploy pattern copied from: `~/claude/projects/toknmtr/ops/deploy.py`
|
|
||||||
265
ops/deploy.py
265
ops/deploy.py
|
|
@ -1,265 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
"""Deploy the BMS stack to the Unraid Docker host via the Portainer API.
|
|
||||||
|
|
||||||
Why this shape: there is no usable `docker` CLI in WSL, no SSH to the Unraid box
|
|
||||||
(port 22 is closed) and no shared registry the Unraid daemon can pull from. So each
|
|
||||||
service's build *context* is packed into a tar and POSTed to the remote daemon's
|
|
||||||
`/build` endpoint — Unraid runs the Dockerfiles itself. Once the four images exist
|
|
||||||
locally on that daemon, docker-compose.prod.yml is pushed as a Portainer stack,
|
|
||||||
which references the images by tag and never needs the repo on the host.
|
|
||||||
|
|
||||||
Mirrors the pattern in ~/claude/projects/toknmtr/ops/deploy.py.
|
|
||||||
Idempotent: re-running rebuilds every image and updates the existing stack in place.
|
|
||||||
The Postgres bind mount at /mnt/user/appdata/bms/db survives redeploys.
|
|
||||||
|
|
||||||
Usage:
|
|
||||||
python3 ops/deploy.py # build everything + deploy the stack
|
|
||||||
python3 ops/deploy.py --no-build # redeploy the stack using existing images
|
|
||||||
"""
|
|
||||||
import io
|
|
||||||
import json
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
import tarfile
|
|
||||||
import time
|
|
||||||
import urllib.error
|
|
||||||
import urllib.request
|
|
||||||
|
|
||||||
PORTAINER = "http://192.168.1.249:9000"
|
|
||||||
EP = 3 # 'local' docker endpoint (unix:///var/run/docker.sock)
|
|
||||||
DOCKER = f"{PORTAINER}/api/endpoints/{EP}/docker"
|
|
||||||
|
|
||||||
HOST = "192.168.1.249"
|
|
||||||
FRONTEND_PORT = "5646"
|
|
||||||
STACK_NAME = "bms"
|
|
||||||
APPDATA = "/mnt/user/appdata/bms"
|
|
||||||
|
|
||||||
PROJECT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
|
||||||
COMPOSE_FILE = os.path.join(PROJECT_DIR, "docker-compose.prod.yml")
|
|
||||||
|
|
||||||
# (image tag, context subdirectory) — built in this order.
|
|
||||||
# mqtt/backend first so the slow frontend build is last and failures surface early.
|
|
||||||
IMAGES = [
|
|
||||||
("bms-mqtt:latest", "infra/mosquitto"),
|
|
||||||
("bms-backend:latest", "backend"),
|
|
||||||
("bms-simulators:latest", "simulators"),
|
|
||||||
("bms-frontend:latest", "frontend"),
|
|
||||||
]
|
|
||||||
|
|
||||||
# Never shipped in a build context.
|
|
||||||
EXCLUDE_DIRS = {".git", "node_modules", ".next", "__pycache__", ".venv", "venv",
|
|
||||||
".vscode", ".idea", ".claude"}
|
|
||||||
EXCLUDE_SUFFIXES = (".pyc", ".pyo", ".log", ".tsbuildinfo")
|
|
||||||
EXCLUDE_FILES = {".env", ".env.local", ".DS_Store", "Thumbs.db"}
|
|
||||||
|
|
||||||
TOKEN = open(os.path.expanduser("~/.portainer-token")).read().strip()
|
|
||||||
HDR = {"X-API-Key": TOKEN}
|
|
||||||
|
|
||||||
|
|
||||||
def req(url, method, data=None, headers=None, raw=False, timeout=900):
|
|
||||||
h = dict(HDR)
|
|
||||||
if headers:
|
|
||||||
h.update(headers)
|
|
||||||
body = data
|
|
||||||
if data is not None and not raw:
|
|
||||||
body = json.dumps(data).encode()
|
|
||||||
h["Content-Type"] = "application/json"
|
|
||||||
r = urllib.request.Request(url, data=body, headers=h, method=method)
|
|
||||||
try:
|
|
||||||
with urllib.request.urlopen(r, timeout=timeout) as resp:
|
|
||||||
return resp.status, resp.read()
|
|
||||||
except urllib.error.HTTPError as e:
|
|
||||||
return e.code, e.read()
|
|
||||||
|
|
||||||
|
|
||||||
def docker(method, path, **kw):
|
|
||||||
return req(DOCKER + path, method, **kw)
|
|
||||||
|
|
||||||
|
|
||||||
def api(method, path, **kw):
|
|
||||||
return req(PORTAINER + "/api" + path, method, **kw)
|
|
||||||
|
|
||||||
|
|
||||||
# ── image builds ─────────────────────────────────────────────────────
|
|
||||||
|
|
||||||
def context_tar(subdir):
|
|
||||||
"""Pack one service directory (minus excludes) for the Docker /build API."""
|
|
||||||
root_dir = os.path.join(PROJECT_DIR, subdir)
|
|
||||||
if not os.path.isdir(root_dir):
|
|
||||||
sys.exit(f"ERROR: build context {subdir} does not exist.")
|
|
||||||
if not os.path.exists(os.path.join(root_dir, "Dockerfile")):
|
|
||||||
sys.exit(f"ERROR: no Dockerfile in {subdir}.")
|
|
||||||
buf = io.BytesIO()
|
|
||||||
with tarfile.open(fileobj=buf, mode="w") as tar:
|
|
||||||
for root, dirs, files in os.walk(root_dir):
|
|
||||||
dirs[:] = [d for d in dirs if d not in EXCLUDE_DIRS]
|
|
||||||
for fn in files:
|
|
||||||
if fn in EXCLUDE_FILES or fn.endswith(EXCLUDE_SUFFIXES):
|
|
||||||
continue
|
|
||||||
full = os.path.join(root, fn)
|
|
||||||
tar.add(full, arcname=os.path.relpath(full, root_dir))
|
|
||||||
return buf.getvalue()
|
|
||||||
|
|
||||||
|
|
||||||
def build_image(tag, subdir):
|
|
||||||
ctx = context_tar(subdir)
|
|
||||||
print(f"\n── building {tag} from {subdir}/ ({len(ctx)/1024:.0f} KiB context)")
|
|
||||||
status, out = docker(
|
|
||||||
"POST",
|
|
||||||
f"/build?t={tag}&dockerfile=Dockerfile&forcerm=true",
|
|
||||||
data=ctx,
|
|
||||||
headers={"Content-Type": "application/x-tar"},
|
|
||||||
raw=True,
|
|
||||||
timeout=1800, # the Next.js build is the slow one
|
|
||||||
)
|
|
||||||
text = out.decode(errors="replace")
|
|
||||||
errored = None
|
|
||||||
last = ""
|
|
||||||
for line in text.splitlines():
|
|
||||||
try:
|
|
||||||
msg = json.loads(line)
|
|
||||||
except ValueError:
|
|
||||||
continue
|
|
||||||
if "stream" in msg:
|
|
||||||
s = msg["stream"].rstrip()
|
|
||||||
if s:
|
|
||||||
last = s
|
|
||||||
if s.startswith("Step ") or "Successfully" in s:
|
|
||||||
print(" " + s)
|
|
||||||
if "error" in msg:
|
|
||||||
errored = msg["error"]
|
|
||||||
if status != 200 or errored:
|
|
||||||
print(f"BUILD FAILED ({tag}) — status {status}")
|
|
||||||
print(text[-3000:])
|
|
||||||
sys.exit(f"ERROR: build of {tag} failed.")
|
|
||||||
print(f" OK: {last[:120]}")
|
|
||||||
|
|
||||||
|
|
||||||
# ── host prep ────────────────────────────────────────────────────────
|
|
||||||
|
|
||||||
def ensure_appdata():
|
|
||||||
"""Create /mnt/user/appdata/bms/db before Postgres bind-mounts it.
|
|
||||||
|
|
||||||
dockerd would auto-create the path, but doing it explicitly turns a silent
|
|
||||||
permission problem into a visible one.
|
|
||||||
"""
|
|
||||||
print(f"\n── ensuring {APPDATA}/db exists on the host")
|
|
||||||
docker("POST", "/images/create?fromImage=busybox&tag=latest", data=b"", raw=True,
|
|
||||||
headers={"Content-Type": "application/json"}, timeout=300)
|
|
||||||
body = {
|
|
||||||
"Image": "busybox:latest",
|
|
||||||
"Cmd": ["mkdir", "-p", "/hostdata/bms/db"],
|
|
||||||
"HostConfig": {"Binds": ["/mnt/user/appdata:/hostdata"], "AutoRemove": True},
|
|
||||||
}
|
|
||||||
status, out = docker("POST", "/containers/create?name=bms_mkdir_oneshot", data=body)
|
|
||||||
if status not in (200, 201):
|
|
||||||
print(" warn: could not create helper container:",
|
|
||||||
out.decode(errors="replace")[:200])
|
|
||||||
print(" continuing — dockerd will create the bind path itself")
|
|
||||||
return
|
|
||||||
cid = json.loads(out)["Id"]
|
|
||||||
docker("POST", f"/containers/{cid}/start")
|
|
||||||
docker("POST", f"/containers/{cid}/wait", data={}, timeout=120)
|
|
||||||
print(" OK")
|
|
||||||
|
|
||||||
|
|
||||||
# ── stack deploy ─────────────────────────────────────────────────────
|
|
||||||
|
|
||||||
def find_stack():
|
|
||||||
status, out = api("GET", "/stacks")
|
|
||||||
if status != 200:
|
|
||||||
sys.exit(f"ERROR: could not list stacks ({status}): "
|
|
||||||
f"{out.decode(errors='replace')[:300]}")
|
|
||||||
for s in json.loads(out):
|
|
||||||
if s.get("Name") == STACK_NAME:
|
|
||||||
return s
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
def deploy_stack():
|
|
||||||
compose = open(COMPOSE_FILE).read()
|
|
||||||
existing = find_stack()
|
|
||||||
|
|
||||||
if existing:
|
|
||||||
sid = existing["Id"]
|
|
||||||
print(f"\n── updating existing stack '{STACK_NAME}' (id {sid})")
|
|
||||||
status, out = api(
|
|
||||||
"PUT", f"/stacks/{sid}?endpointId={EP}",
|
|
||||||
data={"stackFileContent": compose, "env": existing.get("Env", []),
|
|
||||||
"prune": True, "pullImage": False},
|
|
||||||
timeout=900,
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
print(f"\n── creating stack '{STACK_NAME}'")
|
|
||||||
status, out = api(
|
|
||||||
"POST", f"/stacks/create/standalone/string?endpointId={EP}",
|
|
||||||
data={"name": STACK_NAME, "stackFileContent": compose, "env": []},
|
|
||||||
timeout=900,
|
|
||||||
)
|
|
||||||
if status == 404:
|
|
||||||
# Portainer < 2.19 route
|
|
||||||
status, out = api(
|
|
||||||
"POST", f"/stacks?type=2&method=string&endpointId={EP}",
|
|
||||||
data={"Name": STACK_NAME, "StackFileContent": compose, "Env": []},
|
|
||||||
timeout=900,
|
|
||||||
)
|
|
||||||
|
|
||||||
if status not in (200, 201):
|
|
||||||
print("STACK DEPLOY FAILED — status", status)
|
|
||||||
print(out.decode(errors="replace")[:3000])
|
|
||||||
sys.exit("ERROR: stack deploy failed.")
|
|
||||||
print(" stack deployed")
|
|
||||||
|
|
||||||
|
|
||||||
# ── verify ───────────────────────────────────────────────────────────
|
|
||||||
|
|
||||||
def container_states():
|
|
||||||
status, out = docker("GET", "/containers/json?all=1")
|
|
||||||
if status != 200:
|
|
||||||
return {}
|
|
||||||
return {n.lstrip("/"): (c.get("State"), c.get("Status"))
|
|
||||||
for c in json.loads(out) for n in c.get("Names", [])
|
|
||||||
if n.lstrip("/").startswith("bms_")}
|
|
||||||
|
|
||||||
|
|
||||||
def verify():
|
|
||||||
print("\n── verifying")
|
|
||||||
home = f"http://{HOST}:{FRONTEND_PORT}/dashboard"
|
|
||||||
health = f"http://{HOST}:{FRONTEND_PORT}/api/backend/api/health"
|
|
||||||
ok = False
|
|
||||||
for i in range(40):
|
|
||||||
time.sleep(5)
|
|
||||||
try:
|
|
||||||
with urllib.request.urlopen(health, timeout=10) as r:
|
|
||||||
j = json.load(r)
|
|
||||||
with urllib.request.urlopen(home, timeout=15) as r2:
|
|
||||||
code = r2.status
|
|
||||||
print(f" OK after {5*(i+1)}s — backend health={j}, /dashboard HTTP {code}")
|
|
||||||
ok = True
|
|
||||||
break
|
|
||||||
except Exception as e:
|
|
||||||
print(f" ...not ready ({type(e).__name__}: {str(e)[:70]})")
|
|
||||||
|
|
||||||
print("\n container states:")
|
|
||||||
for name, (state, st) in sorted(container_states().items()):
|
|
||||||
print(f" {name:20s} {state:10s} {st}")
|
|
||||||
|
|
||||||
if not ok:
|
|
||||||
sys.exit("ERROR: stack did not come up healthy in time.")
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
if "--no-build" not in sys.argv:
|
|
||||||
for tag, subdir in IMAGES:
|
|
||||||
build_image(tag, subdir)
|
|
||||||
else:
|
|
||||||
print("Skipping image builds (--no-build).")
|
|
||||||
ensure_appdata()
|
|
||||||
deploy_stack()
|
|
||||||
verify()
|
|
||||||
print(f"\nDeployed. Dashboard: http://{HOST}:{FRONTEND_PORT}/dashboard")
|
|
||||||
print(f"API docs: http://{HOST}:{FRONTEND_PORT}/api/backend/docs")
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
main()
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue